diff options
Diffstat (limited to 'lib')
840 files changed, 15769 insertions, 11395 deletions
diff --git a/lib/autoloader.php b/lib/autoloader.php deleted file mode 100644 index 41b272a457c..00000000000 --- a/lib/autoloader.php +++ /dev/null @@ -1,169 +0,0 @@ -<?php - -declare(strict_types=1); -/** - * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2013-2016 ownCloud, Inc. - * SPDX-License-Identifier: AGPL-3.0-only - */ -namespace OC; - -use OCP\App\AppPathNotFoundException; -use OCP\App\IAppManager; -use OCP\AutoloadNotAllowedException; -use OCP\ICache; -use Psr\Log\LoggerInterface; - -class Autoloader { - /** @var bool */ - private $useGlobalClassPath = true; - /** @var array */ - private $validRoots = []; - - /** - * Optional low-latency memory cache for class to path mapping. - * - * @var \OC\Memcache\Cache - */ - protected $memoryCache; - - /** - * Autoloader constructor. - * - * @param string[] $validRoots - */ - public function __construct(array $validRoots) { - foreach ($validRoots as $root) { - $this->validRoots[$root] = true; - } - } - - /** - * Add a path to the list of valid php roots for auto loading - * - * @param string $root - */ - public function addValidRoot(string $root): void { - $root = stream_resolve_include_path($root); - $this->validRoots[$root] = true; - } - - /** - * disable the usage of the global classpath \OC::$CLASSPATH - */ - public function disableGlobalClassPath(): void { - $this->useGlobalClassPath = false; - } - - /** - * enable the usage of the global classpath \OC::$CLASSPATH - */ - public function enableGlobalClassPath(): void { - $this->useGlobalClassPath = true; - } - - /** - * get the possible paths for a class - * - * @param string $class - * @return array an array of possible paths - */ - public function findClass(string $class): array { - $class = trim($class, '\\'); - - $paths = []; - if ($this->useGlobalClassPath && array_key_exists($class, \OC::$CLASSPATH)) { - $paths[] = \OC::$CLASSPATH[$class]; - /** - * @TODO: Remove this when necessary - * Remove "apps/" from inclusion path for smooth migration to multi app dir - */ - if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) { - \OCP\Server::get(LoggerInterface::class)->debug('include path for class "' . $class . '" starts with "apps/"', ['app' => 'core']); - $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]); - } - } elseif (strpos($class, 'OC_') === 0) { - $paths[] = \OC::$SERVERROOT . '/lib/private/legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); - } elseif (strpos($class, 'OCA\\') === 0) { - [, $app, $rest] = explode('\\', $class, 3); - $app = strtolower($app); - try { - $appPath = \OCP\Server::get(IAppManager::class)->getAppPath($app); - if (stream_resolve_include_path($appPath)) { - $paths[] = $appPath . '/' . strtolower(str_replace('\\', '/', $rest) . '.php'); - // If not found in the root of the app directory, insert '/lib' after app id and try again. - $paths[] = $appPath . '/lib/' . strtolower(str_replace('\\', '/', $rest) . '.php'); - } - } catch (AppPathNotFoundException) { - // App not found, ignore - } - } elseif ($class === 'Test\\TestCase') { - // This File is considered public API, so we make sure that the class - // can still be loaded, although the PSR-4 paths have not been loaded. - $paths[] = \OC::$SERVERROOT . '/tests/lib/TestCase.php'; - } - return $paths; - } - - /** - * @param string $fullPath - * @return bool - * @throws AutoloadNotAllowedException - */ - protected function isValidPath(string $fullPath): bool { - foreach ($this->validRoots as $root => $true) { - if (substr($fullPath, 0, strlen($root) + 1) === $root . '/') { - return true; - } - } - throw new AutoloadNotAllowedException($fullPath); - } - - /** - * Load the specified class - * - * @param string $class - * @return bool - * @throws AutoloadNotAllowedException - */ - public function load(string $class): bool { - $pathsToRequire = null; - if ($this->memoryCache) { - $pathsToRequire = $this->memoryCache->get($class); - } - - if (class_exists($class, false)) { - return false; - } - - if (!is_array($pathsToRequire)) { - // No cache or cache miss - $pathsToRequire = []; - foreach ($this->findClass($class) as $path) { - $fullPath = stream_resolve_include_path($path); - if ($fullPath && $this->isValidPath($fullPath)) { - $pathsToRequire[] = $fullPath; - } - } - - if ($this->memoryCache) { - $this->memoryCache->set($class, $pathsToRequire, 60); // cache 60 sec - } - } - - foreach ($pathsToRequire as $fullPath) { - require_once $fullPath; - } - - return false; - } - - /** - * Sets the optional low-latency cache for class to path mapping. - * - * @param ICache $memoryCache Instance of memory cache. - */ - public function setMemoryCache(?ICache $memoryCache = null): void { - $this->memoryCache = $memoryCache; - } -} diff --git a/lib/base.php b/lib/base.php index b0334ecd729..7bfef10fec2 100644 --- a/lib/base.php +++ b/lib/base.php @@ -6,18 +6,27 @@ declare(strict_types=1); * SPDX-FileCopyrightText: 2013-2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ -use OC\Encryption\HookManager; + +use OC\Profiler\BuiltInProfiler; +use OC\Share20\GroupDeletedListener; use OC\Share20\Hooks; +use OC\Share20\UserDeletedListener; +use OC\Share20\UserRemovedListener; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Events\BeforeFileSystemSetupEvent; +use OCP\Group\Events\GroupDeletedEvent; use OCP\Group\Events\UserRemovedEvent; +use OCP\IConfig; use OCP\ILogger; use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUserSession; use OCP\Security\Bruteforce\IThrottler; use OCP\Server; -use OCP\Share; +use OCP\Template\ITemplateManager; use OCP\User\Events\UserChangedEvent; +use OCP\User\Events\UserDeletedEvent; +use OCP\Util; use Psr\Log\LoggerInterface; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use function OCP\Log\logger; @@ -31,10 +40,6 @@ require_once 'public/Constants.php'; */ class OC { /** - * Associative array for autoloading. classname => filename - */ - public static array $CLASSPATH = []; - /** * The installation path for Nextcloud on the server (e.g. /srv/http/nextcloud) */ public static string $SERVERROOT = ''; @@ -64,8 +69,6 @@ class OC { */ public static bool $CLI = false; - public static \OC\Autoloader $loader; - public static \Composer\Autoload\ClassLoader $composerAutoloader; public static \OC\Server $server; @@ -119,7 +122,6 @@ class OC { } } - if (OC::$CLI) { OC::$WEBROOT = self::$config->getValue('overwritewebroot', ''); } else { @@ -139,8 +141,8 @@ class OC { // Resolve /nextcloud to /nextcloud/ to ensure to always have a trailing // slash which is required by URL generation. - if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === \OC::$WEBROOT && - substr($_SERVER['REQUEST_URI'], -1) !== '/') { + if (isset($_SERVER['REQUEST_URI']) && $_SERVER['REQUEST_URI'] === \OC::$WEBROOT + && substr($_SERVER['REQUEST_URI'], -1) !== '/') { header('Location: ' . \OC::$WEBROOT . '/'); exit(); } @@ -180,8 +182,6 @@ class OC { } public static function checkConfig(): void { - $l = Server::get(\OCP\L10N\IFactory::class)->get('lib'); - // Create config if it does not already exist $configFilePath = self::$configDir . '/config.php'; if (!file_exists($configFilePath)) { @@ -190,9 +190,11 @@ class OC { // Check if config is writable $configFileWritable = is_writable($configFilePath); - if (!$configFileWritable && !OC_Helper::isReadOnlyConfigEnabled() + $configReadOnly = Server::get(IConfig::class)->getSystemValueBool('config_is_read_only'); + if (!$configFileWritable && !$configReadOnly || !$configFileWritable && \OCP\Util::needUpgrade()) { $urlGenerator = Server::get(IURLGenerator::class); + $l = Server::get(\OCP\L10N\IFactory::class)->get('lib'); if (self::$CLI) { echo $l->t('Cannot write into "config" directory!') . "\n"; @@ -202,7 +204,7 @@ class OC { echo $l->t('See %s', [ $urlGenerator->linkToDocs('admin-config') ]) . "\n"; exit; } else { - OC_Template::printErrorPage( + Server::get(ITemplateManager::class)->printErrorPage( $l->t('Cannot write into "config" directory!'), $l->t('This can usually be fixed by giving the web server write access to the config directory.') . ' ' . $l->t('But, if you prefer to keep config.php file read only, set the option "config_is_read_only" to true in it.') . ' ' @@ -238,7 +240,7 @@ class OC { header('Retry-After: 120'); // render error page - $template = new OC_Template('', 'update.user', 'guest'); + $template = Server::get(ITemplateManager::class)->getTemplate('', 'update.user', 'guest'); \OCP\Util::addScript('core', 'maintenance'); \OCP\Util::addStyle('core', 'guest'); $template->printPage(); @@ -255,7 +257,7 @@ class OC { $tooBig = false; if (!$disableWebUpdater) { $apps = Server::get(\OCP\App\IAppManager::class); - if ($apps->isInstalled('user_ldap')) { + if ($apps->isEnabledForAnyone('user_ldap')) { $qb = Server::get(\OCP\IDBConnection::class)->getQueryBuilder(); $result = $qb->select($qb->func()->count('*', 'user_count')) @@ -266,7 +268,7 @@ class OC { $tooBig = ($row['user_count'] > 50); } - if (!$tooBig && $apps->isInstalled('user_saml')) { + if (!$tooBig && $apps->isEnabledForAnyone('user_saml')) { $qb = Server::get(\OCP\IDBConnection::class)->getQueryBuilder(); $result = $qb->select($qb->func()->count('*', 'user_count')) @@ -279,13 +281,12 @@ class OC { } if (!$tooBig) { // count users - $stats = Server::get(\OCP\IUserManager::class)->countUsers(); - $totalUsers = array_sum($stats); + $totalUsers = Server::get(\OCP\IUserManager::class)->countUsersTotal(51); $tooBig = ($totalUsers > 50); } } - $ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) && - $_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis'; + $ignoreTooBigWarning = isset($_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup']) + && $_GET['IKnowThatThisIsABigInstanceAndTheUpdateRequestCouldRunIntoATimeoutAndHowToRestoreABackup'] === 'IAmSuperSureToDoThis'; if ($disableWebUpdater || ($tooBig && !$ignoreTooBigWarning)) { // send http status 503 @@ -295,7 +296,7 @@ class OC { $serverVersion = \OCP\Server::get(\OCP\ServerVersion::class); // render error page - $template = new OC_Template('', 'update.use-cli', 'guest'); + $template = Server::get(ITemplateManager::class)->getTemplate('', 'update.use-cli', 'guest'); $template->assign('productName', 'nextcloud'); // for now $template->assign('version', $serverVersion->getVersionString()); $template->assign('tooBig', $tooBig); @@ -322,7 +323,7 @@ class OC { /** @var \OC\App\AppManager $appManager */ $appManager = Server::get(\OCP\App\IAppManager::class); - $tmpl = new OC_Template('', 'update.admin', 'guest'); + $tmpl = Server::get(ITemplateManager::class)->getTemplate('', 'update.admin', 'guest'); $tmpl->assign('version', \OCP\Server::get(\OCP\ServerVersion::class)->getVersionString()); $tmpl->assign('isAppsOnlyUpgrade', $isAppsOnlyUpgrade); @@ -363,13 +364,6 @@ class OC { public static function initSession(): void { $request = Server::get(IRequest::class); - // Do not initialize sessions for 'status.php' requests - // Monitoring endpoints can quickly flood session handlers - // and 'status.php' doesn't require sessions anyway - if (str_ends_with($request->getScriptName(), '/status.php')) { - return; - } - // TODO: Temporary disabled again to solve issues with CalDAV/CardDAV clients like DAVx5 that use cookies // TODO: See https://github.com/nextcloud/server/issues/37277#issuecomment-1476366147 and the other comments // TODO: for further information. @@ -388,10 +382,23 @@ class OC { // prevents javascript from accessing php session cookies ini_set('session.cookie_httponly', 'true'); + // Do not initialize sessions for 'status.php' requests + // Monitoring endpoints can quickly flood session handlers + // and 'status.php' doesn't require sessions anyway + if (str_ends_with($request->getScriptName(), '/status.php')) { + return; + } + // set the cookie path to the Nextcloud directory $cookie_path = OC::$WEBROOT ? : '/'; ini_set('session.cookie_path', $cookie_path); + // set the cookie domain to the Nextcloud domain + $cookie_domain = self::$config->getValue('cookie_domain', ''); + if ($cookie_domain) { + ini_set('session.cookie_domain', $cookie_domain); + } + // Let the session name be changed in the initSession Hook $sessionName = OC_Util::getInstanceId(); @@ -415,7 +422,7 @@ class OC { } catch (Exception $e) { Server::get(LoggerInterface::class)->error($e->getMessage(), ['app' => 'base','exception' => $e]); //show the user a detailed error page - OC_Template::printExceptionErrorPage($e, 500); + Server::get(ITemplateManager::class)->printExceptionErrorPage($e, 500); die(); } @@ -451,6 +458,27 @@ class OC { * Try to set some values to the required Nextcloud default */ public static function setRequiredIniValues(): void { + // Don't display errors and log them + @ini_set('display_errors', '0'); + @ini_set('log_errors', '1'); + + // Try to configure php to enable big file uploads. + // This doesn't work always depending on the webserver and php configuration. + // Let's try to overwrite some defaults if they are smaller than 1 hour + + if (intval(@ini_get('max_execution_time') ?: 0) < 3600) { + @ini_set('max_execution_time', strval(3600)); + } + + if (intval(@ini_get('max_input_time') ?: 0) < 3600) { + @ini_set('max_input_time', strval(3600)); + } + + // Try to set the maximum execution time to the largest time limit we have + if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { + @set_time_limit(max(intval(@ini_get('max_execution_time')), intval(@ini_get('max_input_time')))); + } + @ini_set('default_charset', 'UTF-8'); @ini_set('gd.jpeg_ignore_warning', '1'); } @@ -495,7 +523,7 @@ class OC { * We use an additional cookie since we want to protect logout CSRF and * also we can't directly interfere with PHP's session mechanism. */ - private static function performSameSiteCookieProtection(\OCP\IConfig $config): void { + private static function performSameSiteCookieProtection(IConfig $config): void { $request = Server::get(IRequest::class); // Some user agents are notorious and don't really properly follow HTTP @@ -523,10 +551,10 @@ class OC { $processingScript = explode('/', $requestUri); $processingScript = $processingScript[count($processingScript) - 1]; - // index.php routes are handled in the middleware - // and cron.php does not need any authentication at all - if ($processingScript === 'index.php' - || $processingScript === 'cron.php') { + if ($processingScript === 'index.php' // index.php routes are handled in the middleware + || $processingScript === 'cron.php' // and cron.php does not need any authentication at all + || $processingScript === 'public.php' // For public.php, auth for password protected shares is done in the PublicAuth plugin + ) { return; } @@ -549,25 +577,26 @@ class OC { } public static function init(): void { + // First handle PHP configuration and copy auth headers to the expected + // $_SERVER variable before doing anything Server object related + self::setRequiredIniValues(); + self::handleAuthHeaders(); + // prevent any XML processing from loading external entities libxml_set_external_entity_loader(static function () { return null; }); + // Set default timezone before the Server object is booted + if (!date_default_timezone_set('UTC')) { + throw new \RuntimeException('Could not set timezone to UTC'); + } + // calculate the root directories OC::$SERVERROOT = str_replace('\\', '/', substr(__DIR__, 0, -4)); // register autoloader $loaderStart = microtime(true); - require_once __DIR__ . '/autoloader.php'; - self::$loader = new \OC\Autoloader([ - OC::$SERVERROOT . '/lib/private/legacy', - ]); - if (defined('PHPUNIT_RUN')) { - self::$loader->addValidRoot(OC::$SERVERROOT . '/tests'); - } - spl_autoload_register([self::$loader, 'load']); - $loaderEnd = microtime(true); self::$CLI = (php_sapi_name() == 'cli'); @@ -593,11 +622,25 @@ class OC { print($e->getMessage()); exit(); } + $loaderEnd = microtime(true); + + // Enable lazy loading if activated + \OC\AppFramework\Utility\SimpleContainer::$useLazyObjects = (bool)self::$config->getValue('enable_lazy_objects', true); // setup the basic server self::$server = new \OC\Server(\OC::$WEBROOT, self::$config); self::$server->boot(); + try { + $profiler = new BuiltInProfiler( + Server::get(IConfig::class), + Server::get(IRequest::class), + ); + $profiler->start(); + } catch (\Throwable $e) { + logger('core')->error('Failed to start profiler: ' . $e->getMessage(), ['app' => 'base']); + } + if (self::$CLI && in_array('--' . \OCP\Console\ReservedOptions::DEBUG_LOG, $_SERVER['argv'])) { \OC\Core\Listener\BeforeMessageLoggedEventListener::setup(); } @@ -611,41 +654,10 @@ class OC { error_reporting(E_ALL); } - // Don't display errors and log them - @ini_set('display_errors', '0'); - @ini_set('log_errors', '1'); - - if (!date_default_timezone_set('UTC')) { - throw new \RuntimeException('Could not set timezone to UTC'); - } - - - //try to configure php to enable big file uploads. - //this doesn´t work always depending on the webserver and php configuration. - //Let´s try to overwrite some defaults if they are smaller than 1 hour - - if (intval(@ini_get('max_execution_time') ?: 0) < 3600) { - @ini_set('max_execution_time', strval(3600)); - } - - if (intval(@ini_get('max_input_time') ?: 0) < 3600) { - @ini_set('max_input_time', strval(3600)); - } - - //try to set the maximum execution time to the largest time limit we have - if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { - @set_time_limit(max(intval(@ini_get('max_execution_time')), intval(@ini_get('max_input_time')))); - } - - self::setRequiredIniValues(); - self::handleAuthHeaders(); - $systemConfig = Server::get(\OC\SystemConfig::class); - self::registerAutoloaderCache($systemConfig); - // initialize intl fallback if necessary OC_Util::isSetLocaleWorking(); - $config = Server::get(\OCP\IConfig::class); + $config = Server::get(IConfig::class); if (!defined('PHPUNIT_RUN')) { $errorHandler = new OC\Log\ErrorHandler( \OCP\Server::get(\Psr\Log\LoggerInterface::class), @@ -654,7 +666,7 @@ class OC { if ($config->getSystemValueBool('debug', false)) { set_error_handler([$errorHandler, 'onAll'], E_ALL); if (\OC::$CLI) { - $exceptionHandler = ['OC_Template', 'printExceptionErrorPage']; + $exceptionHandler = [Server::get(ITemplateManager::class), 'printExceptionErrorPage']; } } else { set_error_handler([$errorHandler, 'onError']); @@ -675,7 +687,11 @@ class OC { throw new \OCP\HintException('The PHP SimpleXML/PHP-XML extension is not installed.', 'Install the extension or make sure it is enabled.'); } - OC_App::loadApps(['session']); + $systemConfig = Server::get(\OC\SystemConfig::class); + $appManager = Server::get(\OCP\App\IAppManager::class); + if ($systemConfig->getValue('installed', false)) { + $appManager->loadApps(['session']); + } if (!self::$CLI) { self::initSession(); } @@ -688,13 +704,14 @@ class OC { self::performSameSiteCookieProtection($config); if (!defined('OC_CONSOLE')) { + $eventLogger->start('check_server', 'Run a few configuration checks'); $errors = OC_Util::checkServer($systemConfig); if (count($errors) > 0) { if (!self::$CLI) { http_response_code(503); - OC_Util::addStyle('guest'); + Util::addStyle('guest'); try { - OC_Template::printGuestPage('', 'error', ['errors' => $errors]); + Server::get(ITemplateManager::class)->printGuestPage('', 'error', ['errors' => $errors]); exit; } catch (\Exception $e) { // In case any error happens when showing the error page, we simply fall back to posting the text. @@ -722,6 +739,7 @@ class OC { } elseif (self::$CLI && $config->getSystemValueBool('installed', false)) { $config->deleteAppValue('core', 'cronErrors'); } + $eventLogger->end('check_server'); } // User and Groups @@ -729,7 +747,8 @@ class OC { self::$server->getSession()->set('user_id', ''); } - OC_User::useBackend(new \OC\User\Database()); + $eventLogger->start('setup_backends', 'Setup group and user backends'); + Server::get(\OCP\IUserManager::class)->registerBackend(new \OC\User\Database()); Server::get(\OCP\IGroupManager::class)->addBackend(new \OC\Group\Database()); // Subscribe to the hook @@ -747,6 +766,7 @@ class OC { // Run upgrades in incognito mode OC_User::setIncognitoMode(true); } + $eventLogger->end('setup_backends'); self::registerCleanupHooks($systemConfig); self::registerShareHooks($systemConfig); @@ -759,9 +779,9 @@ class OC { // Make sure that the application class is not loaded before the database is setup if ($systemConfig->getValue('installed', false)) { - OC_App::loadApp('settings'); - /* Build core application to make sure that listeners are registered */ - Server::get(\OC\Core\Application::class); + $appManager->loadApp('settings'); + /* Run core application registration */ + $bootstrapCoordinator->runLazyRegistration('core'); } //make sure temporary files are cleaned up @@ -773,7 +793,7 @@ class OC { // Check whether the sample configuration has been copied if ($systemConfig->getValue('copied_sample_config', false)) { $l = Server::get(\OCP\L10N\IFactory::class)->get('lib'); - OC_Template::printErrorPage( + Server::get(ITemplateManager::class)->printErrorPage( $l->t('Sample configuration detected'), $l->t('It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php'), 503 @@ -815,7 +835,7 @@ class OC { ] ); - $tmpl = new OCP\Template('core', 'untrustedDomain', 'guest'); + $tmpl = Server::get(ITemplateManager::class)->getTemplate('core', 'untrustedDomain', 'guest'); $tmpl->assign('docUrl', Server::get(IURLGenerator::class)->linkToDocs('admin-trusted-domains')); $tmpl->printPage(); @@ -829,6 +849,21 @@ class OC { register_shutdown_function(function () use ($eventLogger) { $eventLogger->end('request'); }); + + register_shutdown_function(function () { + $memoryPeak = memory_get_peak_usage(); + $logLevel = match (true) { + $memoryPeak > 500_000_000 => ILogger::FATAL, + $memoryPeak > 400_000_000 => ILogger::ERROR, + $memoryPeak > 300_000_000 => ILogger::WARN, + default => null, + }; + if ($logLevel !== null) { + $message = 'Request used more than 300 MB of RAM: ' . Util::humanFileSize($memoryPeak); + $logger = Server::get(LoggerInterface::class); + $logger->log($logLevel, $message, ['app' => 'core']); + } + }); } /** @@ -869,15 +904,16 @@ class OC { } private static function registerEncryptionWrapperAndHooks(): void { + /** @var \OC\Encryption\Manager */ $manager = Server::get(\OCP\Encryption\IManager::class); - \OCP\Util::connectHook('OC_Filesystem', 'preSetup', $manager, 'setupStorage'); + Server::get(IEventDispatcher::class)->addListener( + BeforeFileSystemSetupEvent::class, + $manager->setupStorage(...), + ); $enabled = $manager->isEnabled(); if ($enabled) { - \OCP\Util::connectHook(Share::class, 'post_shared', HookManager::class, 'postShared'); - \OCP\Util::connectHook(Share::class, 'post_unshare', HookManager::class, 'postUnshared'); - \OCP\Util::connectHook('OC_Filesystem', 'post_rename', HookManager::class, 'postRename'); - \OCP\Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', HookManager::class, 'postRestore'); + \OC\Encryption\EncryptionEventListener::register(Server::get(IEventDispatcher::class)); } } @@ -927,29 +963,11 @@ class OC { */ public static function registerShareHooks(\OC\SystemConfig $systemConfig): void { if ($systemConfig->getValue('installed')) { - OC_Hook::connect('OC_User', 'post_deleteUser', Hooks::class, 'post_deleteUser'); - OC_Hook::connect('OC_User', 'post_deleteGroup', Hooks::class, 'post_deleteGroup'); - /** @var IEventDispatcher $dispatcher */ $dispatcher = Server::get(IEventDispatcher::class); - $dispatcher->addServiceListener(UserRemovedEvent::class, \OC\Share20\UserRemovedListener::class); - } - } - - protected static function registerAutoloaderCache(\OC\SystemConfig $systemConfig): void { - // The class loader takes an optional low-latency cache, which MUST be - // namespaced. The instanceid is used for namespacing, but might be - // unavailable at this point. Furthermore, it might not be possible to - // generate an instanceid via \OC_Util::getInstanceId() because the - // config file may not be writable. As such, we only register a class - // loader cache if instanceid is available without trying to create one. - $instanceId = $systemConfig->getValue('instanceid', null); - if ($instanceId) { - try { - $memcacheFactory = Server::get(\OCP\ICacheFactory::class); - self::$loader->setMemoryCache($memcacheFactory->createLocal('Autoloader')); - } catch (\Exception $ex) { - } + $dispatcher->addServiceListener(UserRemovedEvent::class, UserRemovedListener::class); + $dispatcher->addServiceListener(GroupDeletedEvent::class, GroupDeletedListener::class); + $dispatcher->addServiceListener(UserDeletedEvent::class, UserDeletedListener::class); } } @@ -969,6 +987,7 @@ class OC { } $request = Server::get(IRequest::class); + $request->throwDecodingExceptionIfAny(); $requestPath = $request->getRawPathInfo(); if ($requestPath === '/heartbeat') { return; @@ -987,19 +1006,21 @@ class OC { } } + $appManager = Server::get(\OCP\App\IAppManager::class); + // Always load authentication apps - OC_App::loadApps(['authentication']); - OC_App::loadApps(['extended_authentication']); + $appManager->loadApps(['authentication']); + $appManager->loadApps(['extended_authentication']); // Load minimum set of apps if (!\OCP\Util::needUpgrade() && !((bool)$systemConfig->getValue('maintenance', false))) { // For logged-in users: Load everything if (Server::get(IUserSession::class)->isLoggedIn()) { - OC_App::loadApps(); + $appManager->loadApps(); } else { // For guests: Load only filesystem and logging - OC_App::loadApps(['filesystem', 'logging']); + $appManager->loadApps(['filesystem', 'logging']); // Don't try to login when a client is trying to get a OAuth token. // OAuth needs to support basic auth too, so the login is not valid @@ -1012,9 +1033,9 @@ class OC { if (!self::$CLI) { try { - if (!((bool)$systemConfig->getValue('maintenance', false)) && !\OCP\Util::needUpgrade()) { - OC_App::loadApps(['filesystem', 'logging']); - OC_App::loadApps(); + if (!\OCP\Util::needUpgrade()) { + $appManager->loadApps(['filesystem', 'logging']); + $appManager->loadApps(); } Server::get(\OC\Route\Router::class)->match($request->getRawPathInfo()); return; @@ -1070,7 +1091,7 @@ class OC { logger('core')->emergency($e->getMessage(), ['exception' => $e]); } $l = Server::get(\OCP\L10N\IFactory::class)->get('lib'); - OC_Template::printErrorPage( + Server::get(ITemplateManager::class)->printErrorPage( '404', $l->t('The page could not be found on the server.'), 404 @@ -1131,11 +1152,11 @@ class OC { } protected static function tryAppAPILogin(OCP\IRequest $request): bool { - $appManager = Server::get(OCP\App\IAppManager::class); if (!$request->getHeader('AUTHORIZATION-APP-API')) { return false; } - if (!$appManager->isInstalled('app_api')) { + $appManager = Server::get(OCP\App\IAppManager::class); + if (!$appManager->isEnabledForAnyone('app_api')) { return false; } try { diff --git a/lib/composer/autoload.php b/lib/composer/autoload.php index b3b39129e7a..7b1481e876c 100644 --- a/lib/composer/autoload.php +++ b/lib/composer/autoload.php @@ -14,10 +14,7 @@ if (PHP_VERSION_ID < 50600) { echo $err; } } - trigger_error( - $err, - E_USER_ERROR - ); + throw new RuntimeException($err); } require_once __DIR__ . '/composer/autoload_real.php'; diff --git a/lib/composer/composer/InstalledVersions.php b/lib/composer/composer/InstalledVersions.php index 51e734a774b..6d29bff66aa 100644 --- a/lib/composer/composer/InstalledVersions.php +++ b/lib/composer/composer/InstalledVersions.php @@ -33,6 +33,11 @@ class InstalledVersions private static $installed; /** + * @var bool + */ + private static $installedIsLocalDir; + + /** * @var bool|null */ private static $canGetVendors; @@ -309,6 +314,12 @@ class InstalledVersions { self::$installed = $data; self::$installedByVendor = array(); + + // when using reload, we disable the duplicate protection to ensure that self::$installed data is + // always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not, + // so we have to assume it does not, and that may result in duplicate data being returned when listing + // all installed packages for example + self::$installedIsLocalDir = false; } /** @@ -322,19 +333,27 @@ class InstalledVersions } $installed = array(); + $copiedLocalDir = false; if (self::$canGetVendors) { + $selfDir = strtr(__DIR__, '\\', '/'); foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + $vendorDir = strtr($vendorDir, '\\', '/'); if (isset(self::$installedByVendor[$vendorDir])) { $installed[] = self::$installedByVendor[$vendorDir]; } elseif (is_file($vendorDir.'/composer/installed.php')) { /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */ $required = require $vendorDir.'/composer/installed.php'; - $installed[] = self::$installedByVendor[$vendorDir] = $required; - if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { - self::$installed = $installed[count($installed) - 1]; + self::$installedByVendor[$vendorDir] = $required; + $installed[] = $required; + if (self::$installed === null && $vendorDir.'/composer' === $selfDir) { + self::$installed = $required; + self::$installedIsLocalDir = true; } } + if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) { + $copiedLocalDir = true; + } } } @@ -350,7 +369,7 @@ class InstalledVersions } } - if (self::$installed !== array()) { + if (self::$installed !== array() && !$copiedLocalDir) { $installed[] = self::$installed; } diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 528bf3bb2da..5300af5242c 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -11,6 +11,9 @@ return array( 'NCU\\Config\\Exceptions\\TypeConflictException' => $baseDir . '/lib/unstable/Config/Exceptions/TypeConflictException.php', 'NCU\\Config\\Exceptions\\UnknownKeyException' => $baseDir . '/lib/unstable/Config/Exceptions/UnknownKeyException.php', 'NCU\\Config\\IUserConfig' => $baseDir . '/lib/unstable/Config/IUserConfig.php', + 'NCU\\Config\\Lexicon\\ConfigLexiconEntry' => $baseDir . '/lib/unstable/Config/Lexicon/ConfigLexiconEntry.php', + 'NCU\\Config\\Lexicon\\ConfigLexiconStrictness' => $baseDir . '/lib/unstable/Config/Lexicon/ConfigLexiconStrictness.php', + 'NCU\\Config\\Lexicon\\IConfigLexicon' => $baseDir . '/lib/unstable/Config/Lexicon/IConfigLexicon.php', 'NCU\\Config\\ValueType' => $baseDir . '/lib/unstable/Config/ValueType.php', 'NCU\\Federation\\ISignedCloudFederationProvider' => $baseDir . '/lib/unstable/Federation/ISignedCloudFederationProvider.php', 'NCU\\Security\\Signature\\Enum\\DigestAlgorithm' => $baseDir . '/lib/unstable/Security/Signature/Enum/DigestAlgorithm.php', @@ -82,6 +85,7 @@ return array( 'OCP\\AppFramework\\Http\\Attribute\\OpenAPI' => $baseDir . '/lib/public/AppFramework/Http/Attribute/OpenAPI.php', 'OCP\\AppFramework\\Http\\Attribute\\PasswordConfirmationRequired' => $baseDir . '/lib/public/AppFramework/Http/Attribute/PasswordConfirmationRequired.php', 'OCP\\AppFramework\\Http\\Attribute\\PublicPage' => $baseDir . '/lib/public/AppFramework/Http/Attribute/PublicPage.php', + 'OCP\\AppFramework\\Http\\Attribute\\RequestHeader' => $baseDir . '/lib/public/AppFramework/Http/Attribute/RequestHeader.php', 'OCP\\AppFramework\\Http\\Attribute\\Route' => $baseDir . '/lib/public/AppFramework/Http/Attribute/Route.php', 'OCP\\AppFramework\\Http\\Attribute\\StrictCookiesRequired' => $baseDir . '/lib/public/AppFramework/Http/Attribute/StrictCookiesRequired.php', 'OCP\\AppFramework\\Http\\Attribute\\SubAdminRequired' => $baseDir . '/lib/public/AppFramework/Http/Attribute/SubAdminRequired.php', @@ -187,8 +191,21 @@ return array( 'OCP\\Broadcast\\Events\\IBroadcastEvent' => $baseDir . '/lib/public/Broadcast/Events/IBroadcastEvent.php', 'OCP\\Cache\\CappedMemoryCache' => $baseDir . '/lib/public/Cache/CappedMemoryCache.php', 'OCP\\Calendar\\BackendTemporarilyUnavailableException' => $baseDir . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php', + 'OCP\\Calendar\\CalendarEventStatus' => $baseDir . '/lib/public/Calendar/CalendarEventStatus.php', + 'OCP\\Calendar\\CalendarExportOptions' => $baseDir . '/lib/public/Calendar/CalendarExportOptions.php', + 'OCP\\Calendar\\Events\\AbstractCalendarObjectEvent' => $baseDir . '/lib/public/Calendar/Events/AbstractCalendarObjectEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectCreatedEvent' => $baseDir . '/lib/public/Calendar/Events/CalendarObjectCreatedEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectDeletedEvent' => $baseDir . '/lib/public/Calendar/Events/CalendarObjectDeletedEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectMovedEvent' => $baseDir . '/lib/public/Calendar/Events/CalendarObjectMovedEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectMovedToTrashEvent' => $baseDir . '/lib/public/Calendar/Events/CalendarObjectMovedToTrashEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectRestoredEvent' => $baseDir . '/lib/public/Calendar/Events/CalendarObjectRestoredEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectUpdatedEvent' => $baseDir . '/lib/public/Calendar/Events/CalendarObjectUpdatedEvent.php', 'OCP\\Calendar\\Exceptions\\CalendarException' => $baseDir . '/lib/public/Calendar/Exceptions/CalendarException.php', + 'OCP\\Calendar\\IAvailabilityResult' => $baseDir . '/lib/public/Calendar/IAvailabilityResult.php', 'OCP\\Calendar\\ICalendar' => $baseDir . '/lib/public/Calendar/ICalendar.php', + 'OCP\\Calendar\\ICalendarEventBuilder' => $baseDir . '/lib/public/Calendar/ICalendarEventBuilder.php', + 'OCP\\Calendar\\ICalendarExport' => $baseDir . '/lib/public/Calendar/ICalendarExport.php', + 'OCP\\Calendar\\ICalendarIsEnabled' => $baseDir . '/lib/public/Calendar/ICalendarIsEnabled.php', 'OCP\\Calendar\\ICalendarIsShared' => $baseDir . '/lib/public/Calendar/ICalendarIsShared.php', 'OCP\\Calendar\\ICalendarIsWritable' => $baseDir . '/lib/public/Calendar/ICalendarIsWritable.php', 'OCP\\Calendar\\ICalendarProvider' => $baseDir . '/lib/public/Calendar/ICalendarProvider.php', @@ -305,6 +322,7 @@ return array( 'OCP\\DirectEditing\\IToken' => $baseDir . '/lib/public/DirectEditing/IToken.php', 'OCP\\DirectEditing\\RegisterDirectEditorEvent' => $baseDir . '/lib/public/DirectEditing/RegisterDirectEditorEvent.php', 'OCP\\Encryption\\Exceptions\\GenericEncryptionException' => $baseDir . '/lib/public/Encryption/Exceptions/GenericEncryptionException.php', + 'OCP\\Encryption\\Exceptions\\InvalidHeaderException' => $baseDir . '/lib/public/Encryption/Exceptions/InvalidHeaderException.php', 'OCP\\Encryption\\IEncryptionModule' => $baseDir . '/lib/public/Encryption/IEncryptionModule.php', 'OCP\\Encryption\\IFile' => $baseDir . '/lib/public/Encryption/IFile.php', 'OCP\\Encryption\\IManager' => $baseDir . '/lib/public/Encryption/IManager.php', @@ -364,6 +382,9 @@ return array( 'OCP\\Files\\Cache\\IScanner' => $baseDir . '/lib/public/Files/Cache/IScanner.php', 'OCP\\Files\\Cache\\IUpdater' => $baseDir . '/lib/public/Files/Cache/IUpdater.php', 'OCP\\Files\\Cache\\IWatcher' => $baseDir . '/lib/public/Files/Cache/IWatcher.php', + 'OCP\\Files\\Config\\Event\\UserMountAddedEvent' => $baseDir . '/lib/public/Files/Config/Event/UserMountAddedEvent.php', + 'OCP\\Files\\Config\\Event\\UserMountRemovedEvent' => $baseDir . '/lib/public/Files/Config/Event/UserMountRemovedEvent.php', + 'OCP\\Files\\Config\\Event\\UserMountUpdatedEvent' => $baseDir . '/lib/public/Files/Config/Event/UserMountUpdatedEvent.php', 'OCP\\Files\\Config\\ICachedMountFileInfo' => $baseDir . '/lib/public/Files/Config/ICachedMountFileInfo.php', 'OCP\\Files\\Config\\ICachedMountInfo' => $baseDir . '/lib/public/Files/Config/ICachedMountInfo.php', 'OCP\\Files\\Config\\IHomeMountProvider' => $baseDir . '/lib/public/Files/Config/IHomeMountProvider.php', @@ -372,6 +393,9 @@ return array( 'OCP\\Files\\Config\\IRootMountProvider' => $baseDir . '/lib/public/Files/Config/IRootMountProvider.php', 'OCP\\Files\\Config\\IUserMountCache' => $baseDir . '/lib/public/Files/Config/IUserMountCache.php', 'OCP\\Files\\ConnectionLostException' => $baseDir . '/lib/public/Files/ConnectionLostException.php', + 'OCP\\Files\\Conversion\\ConversionMimeProvider' => $baseDir . '/lib/public/Files/Conversion/ConversionMimeProvider.php', + 'OCP\\Files\\Conversion\\IConversionManager' => $baseDir . '/lib/public/Files/Conversion/IConversionManager.php', + 'OCP\\Files\\Conversion\\IConversionProvider' => $baseDir . '/lib/public/Files/Conversion/IConversionProvider.php', 'OCP\\Files\\DavUtil' => $baseDir . '/lib/public/Files/DavUtil.php', 'OCP\\Files\\EmptyFileNameException' => $baseDir . '/lib/public/Files/EmptyFileNameException.php', 'OCP\\Files\\EntityTooLargeException' => $baseDir . '/lib/public/Files/EntityTooLargeException.php', @@ -440,6 +464,7 @@ return array( 'OCP\\Files\\Notify\\INotifyHandler' => $baseDir . '/lib/public/Files/Notify/INotifyHandler.php', 'OCP\\Files\\Notify\\IRenameChange' => $baseDir . '/lib/public/Files/Notify/IRenameChange.php', 'OCP\\Files\\ObjectStore\\IObjectStore' => $baseDir . '/lib/public/Files/ObjectStore/IObjectStore.php', + 'OCP\\Files\\ObjectStore\\IObjectStoreMetaData' => $baseDir . '/lib/public/Files/ObjectStore/IObjectStoreMetaData.php', 'OCP\\Files\\ObjectStore\\IObjectStoreMultiPartUpload' => $baseDir . '/lib/public/Files/ObjectStore/IObjectStoreMultiPartUpload.php', 'OCP\\Files\\ReservedWordException' => $baseDir . '/lib/public/Files/ReservedWordException.php', 'OCP\\Files\\Search\\ISearchBinaryOperator' => $baseDir . '/lib/public/Files/Search/ISearchBinaryOperator.php', @@ -543,6 +568,7 @@ return array( 'OCP\\Http\\WellKnown\\IResponse' => $baseDir . '/lib/public/Http/WellKnown/IResponse.php', 'OCP\\Http\\WellKnown\\JrdResponse' => $baseDir . '/lib/public/Http/WellKnown/JrdResponse.php', 'OCP\\IAddressBook' => $baseDir . '/lib/public/IAddressBook.php', + 'OCP\\IAddressBookEnabled' => $baseDir . '/lib/public/IAddressBookEnabled.php', 'OCP\\IAppConfig' => $baseDir . '/lib/public/IAppConfig.php', 'OCP\\IAvatar' => $baseDir . '/lib/public/IAvatar.php', 'OCP\\IAvatarManager' => $baseDir . '/lib/public/IAvatarManager.php', @@ -637,6 +663,7 @@ return array( 'OCP\\Migration\\IOutput' => $baseDir . '/lib/public/Migration/IOutput.php', 'OCP\\Migration\\IRepairStep' => $baseDir . '/lib/public/Migration/IRepairStep.php', 'OCP\\Migration\\SimpleMigrationStep' => $baseDir . '/lib/public/Migration/SimpleMigrationStep.php', + 'OCP\\Navigation\\Events\\LoadAdditionalEntriesEvent' => $baseDir . '/lib/public/Navigation/Events/LoadAdditionalEntriesEvent.php', 'OCP\\Notification\\AlreadyProcessedException' => $baseDir . '/lib/public/Notification/AlreadyProcessedException.php', 'OCP\\Notification\\IAction' => $baseDir . '/lib/public/Notification/IAction.php', 'OCP\\Notification\\IApp' => $baseDir . '/lib/public/Notification/IApp.php', @@ -652,6 +679,7 @@ return array( 'OCP\\OCM\\Events\\ResourceTypeRegisterEvent' => $baseDir . '/lib/public/OCM/Events/ResourceTypeRegisterEvent.php', 'OCP\\OCM\\Exceptions\\OCMArgumentException' => $baseDir . '/lib/public/OCM/Exceptions/OCMArgumentException.php', 'OCP\\OCM\\Exceptions\\OCMProviderException' => $baseDir . '/lib/public/OCM/Exceptions/OCMProviderException.php', + 'OCP\\OCM\\ICapabilityAwareOCMProvider' => $baseDir . '/lib/public/OCM/ICapabilityAwareOCMProvider.php', 'OCP\\OCM\\IOCMDiscoveryService' => $baseDir . '/lib/public/OCM/IOCMDiscoveryService.php', 'OCP\\OCM\\IOCMProvider' => $baseDir . '/lib/public/OCM/IOCMProvider.php', 'OCP\\OCM\\IOCMResource' => $baseDir . '/lib/public/OCM/IOCMResource.php', @@ -749,6 +777,7 @@ return array( 'OCP\\Share\\Exceptions\\GenericShareException' => $baseDir . '/lib/public/Share/Exceptions/GenericShareException.php', 'OCP\\Share\\Exceptions\\IllegalIDChangeException' => $baseDir . '/lib/public/Share/Exceptions/IllegalIDChangeException.php', 'OCP\\Share\\Exceptions\\ShareNotFound' => $baseDir . '/lib/public/Share/Exceptions/ShareNotFound.php', + 'OCP\\Share\\Exceptions\\ShareTokenException' => $baseDir . '/lib/public/Share/Exceptions/ShareTokenException.php', 'OCP\\Share\\IAttributes' => $baseDir . '/lib/public/Share/IAttributes.php', 'OCP\\Share\\IManager' => $baseDir . '/lib/public/Share/IManager.php', 'OCP\\Share\\IProviderFactory' => $baseDir . '/lib/public/Share/IProviderFactory.php', @@ -758,6 +787,7 @@ return array( 'OCP\\Share\\IShareHelper' => $baseDir . '/lib/public/Share/IShareHelper.php', 'OCP\\Share\\IShareProvider' => $baseDir . '/lib/public/Share/IShareProvider.php', 'OCP\\Share\\IShareProviderSupportsAccept' => $baseDir . '/lib/public/Share/IShareProviderSupportsAccept.php', + 'OCP\\Share\\IShareProviderSupportsAllSharesInFolder' => $baseDir . '/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php', 'OCP\\Share\\IShareProviderWithNotification' => $baseDir . '/lib/public/Share/IShareProviderWithNotification.php', 'OCP\\Share_Backend' => $baseDir . '/lib/public/Share_Backend.php', 'OCP\\Share_Backend_Collection' => $baseDir . '/lib/public/Share_Backend_Collection.php', @@ -786,7 +816,9 @@ return array( 'OCP\\SystemTag\\MapperEvent' => $baseDir . '/lib/public/SystemTag/MapperEvent.php', 'OCP\\SystemTag\\SystemTagsEntityEvent' => $baseDir . '/lib/public/SystemTag/SystemTagsEntityEvent.php', 'OCP\\SystemTag\\TagAlreadyExistsException' => $baseDir . '/lib/public/SystemTag/TagAlreadyExistsException.php', + 'OCP\\SystemTag\\TagCreationForbiddenException' => $baseDir . '/lib/public/SystemTag/TagCreationForbiddenException.php', 'OCP\\SystemTag\\TagNotFoundException' => $baseDir . '/lib/public/SystemTag/TagNotFoundException.php', + 'OCP\\SystemTag\\TagUpdateForbiddenException' => $baseDir . '/lib/public/SystemTag/TagUpdateForbiddenException.php', 'OCP\\Talk\\Exceptions\\NoBackendException' => $baseDir . '/lib/public/Talk/Exceptions/NoBackendException.php', 'OCP\\Talk\\IBroker' => $baseDir . '/lib/public/Talk/IBroker.php', 'OCP\\Talk\\IConversation' => $baseDir . '/lib/public/Talk/IConversation.php', @@ -794,6 +826,7 @@ return array( 'OCP\\Talk\\ITalkBackend' => $baseDir . '/lib/public/Talk/ITalkBackend.php', 'OCP\\TaskProcessing\\EShapeType' => $baseDir . '/lib/public/TaskProcessing/EShapeType.php', 'OCP\\TaskProcessing\\Events\\AbstractTaskProcessingEvent' => $baseDir . '/lib/public/TaskProcessing/Events/AbstractTaskProcessingEvent.php', + 'OCP\\TaskProcessing\\Events\\GetTaskProcessingProvidersEvent' => $baseDir . '/lib/public/TaskProcessing/Events/GetTaskProcessingProvidersEvent.php', 'OCP\\TaskProcessing\\Events\\TaskFailedEvent' => $baseDir . '/lib/public/TaskProcessing/Events/TaskFailedEvent.php', 'OCP\\TaskProcessing\\Events\\TaskSuccessfulEvent' => $baseDir . '/lib/public/TaskProcessing/Events/TaskSuccessfulEvent.php', 'OCP\\TaskProcessing\\Exception\\Exception' => $baseDir . '/lib/public/TaskProcessing/Exception/Exception.php', @@ -814,12 +847,14 @@ return array( 'OCP\\TaskProcessing\\TaskTypes\\ContextWrite' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/ContextWrite.php', 'OCP\\TaskProcessing\\TaskTypes\\GenerateEmoji' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/GenerateEmoji.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToImage' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToImage.php', + 'OCP\\TaskProcessing\\TaskTypes\\TextToSpeech' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToSpeech.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToText' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToText.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextChangeTone' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextChangeTone.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextChat' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextChat.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextChatWithTools' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextChatWithTools.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextFormalization' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextFormalization.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextHeadline' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php', + 'OCP\\TaskProcessing\\TaskTypes\\TextToTextProofread' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextProofread.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextReformulation' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextReformulation.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextSimplification' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextSimplification.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextSummary' => $baseDir . '/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php', @@ -830,6 +865,9 @@ return array( 'OCP\\Teams\\Team' => $baseDir . '/lib/public/Teams/Team.php', 'OCP\\Teams\\TeamResource' => $baseDir . '/lib/public/Teams/TeamResource.php', 'OCP\\Template' => $baseDir . '/lib/public/Template.php', + 'OCP\\Template\\ITemplate' => $baseDir . '/lib/public/Template/ITemplate.php', + 'OCP\\Template\\ITemplateManager' => $baseDir . '/lib/public/Template/ITemplateManager.php', + 'OCP\\Template\\TemplateNotFoundException' => $baseDir . '/lib/public/Template/TemplateNotFoundException.php', 'OCP\\TextProcessing\\Events\\AbstractTextProcessingEvent' => $baseDir . '/lib/public/TextProcessing/Events/AbstractTextProcessingEvent.php', 'OCP\\TextProcessing\\Events\\TaskFailedEvent' => $baseDir . '/lib/public/TextProcessing/Events/TaskFailedEvent.php', 'OCP\\TextProcessing\\Events\\TaskSuccessfulEvent' => $baseDir . '/lib/public/TextProcessing/Events/TaskSuccessfulEvent.php', @@ -881,6 +919,7 @@ return array( 'OCP\\User\\Backend\\IGetDisplayNameBackend' => $baseDir . '/lib/public/User/Backend/IGetDisplayNameBackend.php', 'OCP\\User\\Backend\\IGetHomeBackend' => $baseDir . '/lib/public/User/Backend/IGetHomeBackend.php', 'OCP\\User\\Backend\\IGetRealUIDBackend' => $baseDir . '/lib/public/User/Backend/IGetRealUIDBackend.php', + 'OCP\\User\\Backend\\ILimitAwareCountUsersBackend' => $baseDir . '/lib/public/User/Backend/ILimitAwareCountUsersBackend.php', 'OCP\\User\\Backend\\IPasswordConfirmationBackend' => $baseDir . '/lib/public/User/Backend/IPasswordConfirmationBackend.php', 'OCP\\User\\Backend\\IPasswordHashBackend' => $baseDir . '/lib/public/User/Backend/IPasswordHashBackend.php', 'OCP\\User\\Backend\\IProvideAvatarBackend' => $baseDir . '/lib/public/User/Backend/IProvideAvatarBackend.php', @@ -969,6 +1008,7 @@ return array( 'OC\\AppFramework\\Http\\RequestId' => $baseDir . '/lib/private/AppFramework/Http/RequestId.php', 'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php', 'OC\\AppFramework\\Middleware\\CompressionMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php', + 'OC\\AppFramework\\Middleware\\FlowV2EphemeralSessionsMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php', 'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => $baseDir . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php', 'OC\\AppFramework\\Middleware\\NotModifiedMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php', 'OC\\AppFramework\\Middleware\\OCSMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/OCSMiddleware.php', @@ -999,7 +1039,6 @@ return array( 'OC\\AppFramework\\OCS\\V1Response' => $baseDir . '/lib/private/AppFramework/OCS/V1Response.php', 'OC\\AppFramework\\OCS\\V2Response' => $baseDir . '/lib/private/AppFramework/OCS/V2Response.php', 'OC\\AppFramework\\Routing\\RouteActionHandler' => $baseDir . '/lib/private/AppFramework/Routing/RouteActionHandler.php', - 'OC\\AppFramework\\Routing\\RouteConfig' => $baseDir . '/lib/private/AppFramework/Routing/RouteConfig.php', 'OC\\AppFramework\\Routing\\RouteParser' => $baseDir . '/lib/private/AppFramework/Routing/RouteParser.php', 'OC\\AppFramework\\ScopedPsrLogger' => $baseDir . '/lib/private/AppFramework/ScopedPsrLogger.php', 'OC\\AppFramework\\Services\\AppConfig' => $baseDir . '/lib/private/AppFramework/Services/AppConfig.php', @@ -1011,6 +1050,7 @@ return array( 'OC\\AppScriptDependency' => $baseDir . '/lib/private/AppScriptDependency.php', 'OC\\AppScriptSort' => $baseDir . '/lib/private/AppScriptSort.php', 'OC\\App\\AppManager' => $baseDir . '/lib/private/App/AppManager.php', + 'OC\\App\\AppStore\\AppNotFoundException' => $baseDir . '/lib/private/App/AppStore/AppNotFoundException.php', 'OC\\App\\AppStore\\Bundles\\Bundle' => $baseDir . '/lib/private/App/AppStore/Bundles/Bundle.php', 'OC\\App\\AppStore\\Bundles\\BundleFetcher' => $baseDir . '/lib/private/App/AppStore/Bundles/BundleFetcher.php', 'OC\\App\\AppStore\\Bundles\\EducationBundle' => $baseDir . '/lib/private/App/AppStore/Bundles/EducationBundle.php', @@ -1064,8 +1104,8 @@ return array( 'OC\\Authentication\\Login\\ClearLostPasswordTokensCommand' => $baseDir . '/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php', 'OC\\Authentication\\Login\\CompleteLoginCommand' => $baseDir . '/lib/private/Authentication/Login/CompleteLoginCommand.php', 'OC\\Authentication\\Login\\CreateSessionTokenCommand' => $baseDir . '/lib/private/Authentication/Login/CreateSessionTokenCommand.php', - 'OC\\Authentication\\Login\\EmailLoginCommand' => $baseDir . '/lib/private/Authentication/Login/EmailLoginCommand.php', 'OC\\Authentication\\Login\\FinishRememberedLoginCommand' => $baseDir . '/lib/private/Authentication/Login/FinishRememberedLoginCommand.php', + 'OC\\Authentication\\Login\\FlowV2EphemeralSessionsCommand' => $baseDir . '/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php', 'OC\\Authentication\\Login\\LoggedInCheckCommand' => $baseDir . '/lib/private/Authentication/Login/LoggedInCheckCommand.php', 'OC\\Authentication\\Login\\LoginData' => $baseDir . '/lib/private/Authentication/Login/LoginData.php', 'OC\\Authentication\\Login\\LoginResult' => $baseDir . '/lib/private/Authentication/Login/LoginResult.php', @@ -1111,6 +1151,8 @@ return array( 'OC\\Broadcast\\Events\\BroadcastEvent' => $baseDir . '/lib/private/Broadcast/Events/BroadcastEvent.php', 'OC\\Cache\\CappedMemoryCache' => $baseDir . '/lib/private/Cache/CappedMemoryCache.php', 'OC\\Cache\\File' => $baseDir . '/lib/private/Cache/File.php', + 'OC\\Calendar\\AvailabilityResult' => $baseDir . '/lib/private/Calendar/AvailabilityResult.php', + 'OC\\Calendar\\CalendarEventBuilder' => $baseDir . '/lib/private/Calendar/CalendarEventBuilder.php', 'OC\\Calendar\\CalendarQuery' => $baseDir . '/lib/private/Calendar/CalendarQuery.php', 'OC\\Calendar\\Manager' => $baseDir . '/lib/private/Calendar/Manager.php', 'OC\\Calendar\\Resource\\Manager' => $baseDir . '/lib/private/Calendar/Resource/Manager.php', @@ -1148,6 +1190,8 @@ return array( 'OC\\Comments\\Manager' => $baseDir . '/lib/private/Comments/Manager.php', 'OC\\Comments\\ManagerFactory' => $baseDir . '/lib/private/Comments/ManagerFactory.php', 'OC\\Config' => $baseDir . '/lib/private/Config.php', + 'OC\\Config\\ConfigManager' => $baseDir . '/lib/private/Config/ConfigManager.php', + 'OC\\Config\\Lexicon\\CoreConfigLexicon' => $baseDir . '/lib/private/Config/Lexicon/CoreConfigLexicon.php', 'OC\\Config\\UserConfig' => $baseDir . '/lib/private/Config/UserConfig.php', 'OC\\Console\\Application' => $baseDir . '/lib/private/Console/Application.php', 'OC\\Console\\TimestampFormatter' => $baseDir . '/lib/private/Console/TimestampFormatter.php', @@ -1161,7 +1205,7 @@ return array( 'OC\\Contacts\\ContactsMenu\\Providers\\EMailProvider' => $baseDir . '/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php', 'OC\\Contacts\\ContactsMenu\\Providers\\LocalTimeProvider' => $baseDir . '/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php', 'OC\\Contacts\\ContactsMenu\\Providers\\ProfileProvider' => $baseDir . '/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php', - 'OC\\Core\\Application' => $baseDir . '/core/Application.php', + 'OC\\Core\\AppInfo\\Application' => $baseDir . '/core/AppInfo/Application.php', 'OC\\Core\\BackgroundJobs\\BackgroundCleanupUpdaterBackupsJob' => $baseDir . '/core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php', 'OC\\Core\\BackgroundJobs\\CheckForUserCertificates' => $baseDir . '/core/BackgroundJobs/CheckForUserCertificates.php', 'OC\\Core\\BackgroundJobs\\CleanupLoginFlowV2' => $baseDir . '/core/BackgroundJobs/CleanupLoginFlowV2.php', @@ -1190,6 +1234,7 @@ return array( 'OC\\Core\\Command\\Config\\Import' => $baseDir . '/core/Command/Config/Import.php', 'OC\\Core\\Command\\Config\\ListConfigs' => $baseDir . '/core/Command/Config/ListConfigs.php', 'OC\\Core\\Command\\Config\\System\\Base' => $baseDir . '/core/Command/Config/System/Base.php', + 'OC\\Core\\Command\\Config\\System\\CastHelper' => $baseDir . '/core/Command/Config/System/CastHelper.php', 'OC\\Core\\Command\\Config\\System\\DeleteConfig' => $baseDir . '/core/Command/Config/System/DeleteConfig.php', 'OC\\Core\\Command\\Config\\System\\GetConfig' => $baseDir . '/core/Command/Config/System/GetConfig.php', 'OC\\Core\\Command\\Config\\System\\SetConfig' => $baseDir . '/core/Command/Config/System/SetConfig.php', @@ -1228,6 +1273,8 @@ return array( 'OC\\Core\\Command\\Info\\File' => $baseDir . '/core/Command/Info/File.php', 'OC\\Core\\Command\\Info\\FileUtils' => $baseDir . '/core/Command/Info/FileUtils.php', 'OC\\Core\\Command\\Info\\Space' => $baseDir . '/core/Command/Info/Space.php', + 'OC\\Core\\Command\\Info\\Storage' => $baseDir . '/core/Command/Info/Storage.php', + 'OC\\Core\\Command\\Info\\Storages' => $baseDir . '/core/Command/Info/Storages.php', 'OC\\Core\\Command\\Integrity\\CheckApp' => $baseDir . '/core/Command/Integrity/CheckApp.php', 'OC\\Core\\Command\\Integrity\\CheckCore' => $baseDir . '/core/Command/Integrity/CheckCore.php', 'OC\\Core\\Command\\Integrity\\SignApp' => $baseDir . '/core/Command/Integrity/SignApp.php', @@ -1246,11 +1293,17 @@ return array( 'OC\\Core\\Command\\Maintenance\\RepairShareOwnership' => $baseDir . '/core/Command/Maintenance/RepairShareOwnership.php', 'OC\\Core\\Command\\Maintenance\\UpdateHtaccess' => $baseDir . '/core/Command/Maintenance/UpdateHtaccess.php', 'OC\\Core\\Command\\Maintenance\\UpdateTheme' => $baseDir . '/core/Command/Maintenance/UpdateTheme.php', + 'OC\\Core\\Command\\Memcache\\DistributedClear' => $baseDir . '/core/Command/Memcache/DistributedClear.php', + 'OC\\Core\\Command\\Memcache\\DistributedDelete' => $baseDir . '/core/Command/Memcache/DistributedDelete.php', + 'OC\\Core\\Command\\Memcache\\DistributedGet' => $baseDir . '/core/Command/Memcache/DistributedGet.php', + 'OC\\Core\\Command\\Memcache\\DistributedSet' => $baseDir . '/core/Command/Memcache/DistributedSet.php', 'OC\\Core\\Command\\Memcache\\RedisCommand' => $baseDir . '/core/Command/Memcache/RedisCommand.php', 'OC\\Core\\Command\\Preview\\Cleanup' => $baseDir . '/core/Command/Preview/Cleanup.php', 'OC\\Core\\Command\\Preview\\Generate' => $baseDir . '/core/Command/Preview/Generate.php', 'OC\\Core\\Command\\Preview\\Repair' => $baseDir . '/core/Command/Preview/Repair.php', 'OC\\Core\\Command\\Preview\\ResetRenderedTexts' => $baseDir . '/core/Command/Preview/ResetRenderedTexts.php', + 'OC\\Core\\Command\\Router\\ListRoutes' => $baseDir . '/core/Command/Router/ListRoutes.php', + 'OC\\Core\\Command\\Router\\MatchRoute' => $baseDir . '/core/Command/Router/MatchRoute.php', 'OC\\Core\\Command\\Security\\BruteforceAttempts' => $baseDir . '/core/Command/Security/BruteforceAttempts.php', 'OC\\Core\\Command\\Security\\BruteforceResetAttempts' => $baseDir . '/core/Command/Security/BruteforceResetAttempts.php', 'OC\\Core\\Command\\Security\\ExportCertificates' => $baseDir . '/core/Command/Security/ExportCertificates.php', @@ -1263,6 +1316,7 @@ return array( 'OC\\Core\\Command\\SystemTag\\Delete' => $baseDir . '/core/Command/SystemTag/Delete.php', 'OC\\Core\\Command\\SystemTag\\Edit' => $baseDir . '/core/Command/SystemTag/Edit.php', 'OC\\Core\\Command\\SystemTag\\ListCommand' => $baseDir . '/core/Command/SystemTag/ListCommand.php', + 'OC\\Core\\Command\\TaskProcessing\\EnabledCommand' => $baseDir . '/core/Command/TaskProcessing/EnabledCommand.php', 'OC\\Core\\Command\\TaskProcessing\\GetCommand' => $baseDir . '/core/Command/TaskProcessing/GetCommand.php', 'OC\\Core\\Command\\TaskProcessing\\ListCommand' => $baseDir . '/core/Command/TaskProcessing/ListCommand.php', 'OC\\Core\\Command\\TaskProcessing\\Statistics' => $baseDir . '/core/Command/TaskProcessing/Statistics.php', @@ -1285,6 +1339,7 @@ return array( 'OC\\Core\\Command\\User\\Keys\\Verify' => $baseDir . '/core/Command/User/Keys/Verify.php', 'OC\\Core\\Command\\User\\LastSeen' => $baseDir . '/core/Command/User/LastSeen.php', 'OC\\Core\\Command\\User\\ListCommand' => $baseDir . '/core/Command/User/ListCommand.php', + 'OC\\Core\\Command\\User\\Profile' => $baseDir . '/core/Command/User/Profile.php', 'OC\\Core\\Command\\User\\Report' => $baseDir . '/core/Command/User/Report.php', 'OC\\Core\\Command\\User\\ResetPassword' => $baseDir . '/core/Command/User/ResetPassword.php', 'OC\\Core\\Command\\User\\Setting' => $baseDir . '/core/Command/User/Setting.php', @@ -1320,6 +1375,7 @@ return array( 'OC\\Core\\Controller\\TextProcessingApiController' => $baseDir . '/core/Controller/TextProcessingApiController.php', 'OC\\Core\\Controller\\TextToImageApiController' => $baseDir . '/core/Controller/TextToImageApiController.php', 'OC\\Core\\Controller\\TranslationApiController' => $baseDir . '/core/Controller/TranslationApiController.php', + 'OC\\Core\\Controller\\TwoFactorApiController' => $baseDir . '/core/Controller/TwoFactorApiController.php', 'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php', 'OC\\Core\\Controller\\UnifiedSearchController' => $baseDir . '/core/Controller/UnifiedSearchController.php', 'OC\\Core\\Controller\\UnsupportedBrowserController' => $baseDir . '/core/Controller/UnsupportedBrowserController.php', @@ -1337,10 +1393,14 @@ return array( 'OC\\Core\\Db\\ProfileConfigMapper' => $baseDir . '/core/Db/ProfileConfigMapper.php', 'OC\\Core\\Events\\BeforePasswordResetEvent' => $baseDir . '/core/Events/BeforePasswordResetEvent.php', 'OC\\Core\\Events\\PasswordResetEvent' => $baseDir . '/core/Events/PasswordResetEvent.php', + 'OC\\Core\\Exception\\LoginFlowV2ClientForbiddenException' => $baseDir . '/core/Exception/LoginFlowV2ClientForbiddenException.php', 'OC\\Core\\Exception\\LoginFlowV2NotFoundException' => $baseDir . '/core/Exception/LoginFlowV2NotFoundException.php', 'OC\\Core\\Exception\\ResetPasswordException' => $baseDir . '/core/Exception/ResetPasswordException.php', + 'OC\\Core\\Listener\\AddMissingIndicesListener' => $baseDir . '/core/Listener/AddMissingIndicesListener.php', + 'OC\\Core\\Listener\\AddMissingPrimaryKeyListener' => $baseDir . '/core/Listener/AddMissingPrimaryKeyListener.php', 'OC\\Core\\Listener\\BeforeMessageLoggedEventListener' => $baseDir . '/core/Listener/BeforeMessageLoggedEventListener.php', 'OC\\Core\\Listener\\BeforeTemplateRenderedListener' => $baseDir . '/core/Listener/BeforeTemplateRenderedListener.php', + 'OC\\Core\\Listener\\FeedBackHandler' => $baseDir . '/core/Listener/FeedBackHandler.php', 'OC\\Core\\Middleware\\TwoFactorMiddleware' => $baseDir . '/core/Middleware/TwoFactorMiddleware.php', 'OC\\Core\\Migrations\\Version13000Date20170705121758' => $baseDir . '/core/Migrations/Version13000Date20170705121758.php', 'OC\\Core\\Migrations\\Version13000Date20170718121200' => $baseDir . '/core/Migrations/Version13000Date20170718121200.php', @@ -1419,6 +1479,8 @@ return array( 'OC\\Core\\Migrations\\Version30000Date20240906095113' => $baseDir . '/core/Migrations/Version30000Date20240906095113.php', 'OC\\Core\\Migrations\\Version31000Date20240101084401' => $baseDir . '/core/Migrations/Version31000Date20240101084401.php', 'OC\\Core\\Migrations\\Version31000Date20240814184402' => $baseDir . '/core/Migrations/Version31000Date20240814184402.php', + 'OC\\Core\\Migrations\\Version31000Date20250213102442' => $baseDir . '/core/Migrations/Version31000Date20250213102442.php', + 'OC\\Core\\Migrations\\Version32000Date20250620081925' => $baseDir . '/core/Migrations/Version32000Date20250620081925.php', 'OC\\Core\\Notification\\CoreNotifier' => $baseDir . '/core/Notification/CoreNotifier.php', 'OC\\Core\\ResponseDefinitions' => $baseDir . '/core/ResponseDefinitions.php', 'OC\\Core\\Service\\LoginFlowV2Service' => $baseDir . '/core/Service/LoginFlowV2Service.php', @@ -1497,6 +1559,7 @@ return array( 'OC\\DirectEditing\\Token' => $baseDir . '/lib/private/DirectEditing/Token.php', 'OC\\EmojiHelper' => $baseDir . '/lib/private/EmojiHelper.php', 'OC\\Encryption\\DecryptAll' => $baseDir . '/lib/private/Encryption/DecryptAll.php', + 'OC\\Encryption\\EncryptionEventListener' => $baseDir . '/lib/private/Encryption/EncryptionEventListener.php', 'OC\\Encryption\\EncryptionWrapper' => $baseDir . '/lib/private/Encryption/EncryptionWrapper.php', 'OC\\Encryption\\Exceptions\\DecryptionFailedException' => $baseDir . '/lib/private/Encryption/Exceptions/DecryptionFailedException.php', 'OC\\Encryption\\Exceptions\\EmptyEncryptionDataException' => $baseDir . '/lib/private/Encryption/Exceptions/EmptyEncryptionDataException.php', @@ -1507,7 +1570,6 @@ return array( 'OC\\Encryption\\Exceptions\\ModuleDoesNotExistsException' => $baseDir . '/lib/private/Encryption/Exceptions/ModuleDoesNotExistsException.php', 'OC\\Encryption\\Exceptions\\UnknownCipherException' => $baseDir . '/lib/private/Encryption/Exceptions/UnknownCipherException.php', 'OC\\Encryption\\File' => $baseDir . '/lib/private/Encryption/File.php', - 'OC\\Encryption\\HookManager' => $baseDir . '/lib/private/Encryption/HookManager.php', 'OC\\Encryption\\Keys\\Storage' => $baseDir . '/lib/private/Encryption/Keys/Storage.php', 'OC\\Encryption\\Manager' => $baseDir . '/lib/private/Encryption/Manager.php', 'OC\\Encryption\\Update' => $baseDir . '/lib/private/Encryption/Update.php', @@ -1564,6 +1626,7 @@ return array( 'OC\\Files\\Config\\MountProviderCollection' => $baseDir . '/lib/private/Files/Config/MountProviderCollection.php', 'OC\\Files\\Config\\UserMountCache' => $baseDir . '/lib/private/Files/Config/UserMountCache.php', 'OC\\Files\\Config\\UserMountCacheListener' => $baseDir . '/lib/private/Files/Config/UserMountCacheListener.php', + 'OC\\Files\\Conversion\\ConversionManager' => $baseDir . '/lib/private/Files/Conversion/ConversionManager.php', 'OC\\Files\\FileInfo' => $baseDir . '/lib/private/Files/FileInfo.php', 'OC\\Files\\FilenameValidator' => $baseDir . '/lib/private/Files/FilenameValidator.php', 'OC\\Files\\Filesystem' => $baseDir . '/lib/private/Files/Filesystem.php', @@ -1595,6 +1658,7 @@ return array( 'OC\\Files\\ObjectStore\\Mapper' => $baseDir . '/lib/private/Files/ObjectStore/Mapper.php', 'OC\\Files\\ObjectStore\\ObjectStoreScanner' => $baseDir . '/lib/private/Files/ObjectStore/ObjectStoreScanner.php', 'OC\\Files\\ObjectStore\\ObjectStoreStorage' => $baseDir . '/lib/private/Files/ObjectStore/ObjectStoreStorage.php', + 'OC\\Files\\ObjectStore\\PrimaryObjectStoreConfig' => $baseDir . '/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php', 'OC\\Files\\ObjectStore\\S3' => $baseDir . '/lib/private/Files/ObjectStore/S3.php', 'OC\\Files\\ObjectStore\\S3ConfigTrait' => $baseDir . '/lib/private/Files/ObjectStore/S3ConfigTrait.php', 'OC\\Files\\ObjectStore\\S3ConnectionTrait' => $baseDir . '/lib/private/Files/ObjectStore/S3ConnectionTrait.php', @@ -1816,6 +1880,7 @@ return array( 'OC\\Profile\\Actions\\WebsiteAction' => $baseDir . '/lib/private/Profile/Actions/WebsiteAction.php', 'OC\\Profile\\ProfileManager' => $baseDir . '/lib/private/Profile/ProfileManager.php', 'OC\\Profile\\TProfileHelper' => $baseDir . '/lib/private/Profile/TProfileHelper.php', + 'OC\\Profiler\\BuiltInProfiler' => $baseDir . '/lib/private/Profiler/BuiltInProfiler.php', 'OC\\Profiler\\FileProfilerStorage' => $baseDir . '/lib/private/Profiler/FileProfilerStorage.php', 'OC\\Profiler\\Profile' => $baseDir . '/lib/private/Profiler/Profile.php', 'OC\\Profiler\\Profiler' => $baseDir . '/lib/private/Profiler/Profiler.php', @@ -1844,6 +1909,7 @@ return array( 'OC\\Repair\\ClearGeneratedAvatarCache' => $baseDir . '/lib/private/Repair/ClearGeneratedAvatarCache.php', 'OC\\Repair\\ClearGeneratedAvatarCacheJob' => $baseDir . '/lib/private/Repair/ClearGeneratedAvatarCacheJob.php', 'OC\\Repair\\Collation' => $baseDir . '/lib/private/Repair/Collation.php', + 'OC\\Repair\\ConfigKeyMigration' => $baseDir . '/lib/private/Repair/ConfigKeyMigration.php', 'OC\\Repair\\Events\\RepairAdvanceEvent' => $baseDir . '/lib/private/Repair/Events/RepairAdvanceEvent.php', 'OC\\Repair\\Events\\RepairErrorEvent' => $baseDir . '/lib/private/Repair/Events/RepairErrorEvent.php', 'OC\\Repair\\Events\\RepairFinishEvent' => $baseDir . '/lib/private/Repair/Events/RepairFinishEvent.php', @@ -1862,10 +1928,11 @@ return array( 'OC\\Repair\\NC20\\EncryptionMigration' => $baseDir . '/lib/private/Repair/NC20/EncryptionMigration.php', 'OC\\Repair\\NC20\\ShippedDashboardEnable' => $baseDir . '/lib/private/Repair/NC20/ShippedDashboardEnable.php', 'OC\\Repair\\NC21\\AddCheckForUserCertificatesJob' => $baseDir . '/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php', - 'OC\\Repair\\NC21\\ValidatePhoneNumber' => $baseDir . '/lib/private/Repair/NC21/ValidatePhoneNumber.php', 'OC\\Repair\\NC22\\LookupServerSendCheck' => $baseDir . '/lib/private/Repair/NC22/LookupServerSendCheck.php', 'OC\\Repair\\NC24\\AddTokenCleanupJob' => $baseDir . '/lib/private/Repair/NC24/AddTokenCleanupJob.php', 'OC\\Repair\\NC25\\AddMissingSecretJob' => $baseDir . '/lib/private/Repair/NC25/AddMissingSecretJob.php', + 'OC\\Repair\\NC29\\SanitizeAccountProperties' => $baseDir . '/lib/private/Repair/NC29/SanitizeAccountProperties.php', + 'OC\\Repair\\NC29\\SanitizeAccountPropertiesJob' => $baseDir . '/lib/private/Repair/NC29/SanitizeAccountPropertiesJob.php', 'OC\\Repair\\NC30\\RemoveLegacyDatadirFile' => $baseDir . '/lib/private/Repair/NC30/RemoveLegacyDatadirFile.php', 'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\Owncloud\\CleanPreviews' => $baseDir . '/lib/private/Repair/Owncloud/CleanPreviews.php', @@ -1924,6 +1991,7 @@ return array( 'OC\\Security\\IdentityProof\\Manager' => $baseDir . '/lib/private/Security/IdentityProof/Manager.php', 'OC\\Security\\IdentityProof\\Signer' => $baseDir . '/lib/private/Security/IdentityProof/Signer.php', 'OC\\Security\\Ip\\Address' => $baseDir . '/lib/private/Security/Ip/Address.php', + 'OC\\Security\\Ip\\BruteforceAllowList' => $baseDir . '/lib/private/Security/Ip/BruteforceAllowList.php', 'OC\\Security\\Ip\\Factory' => $baseDir . '/lib/private/Security/Ip/Factory.php', 'OC\\Security\\Ip\\Range' => $baseDir . '/lib/private/Security/Ip/Range.php', 'OC\\Security\\Ip\\RemoteAddress' => $baseDir . '/lib/private/Security/Ip/RemoteAddress.php', @@ -1968,7 +2036,7 @@ return array( 'OC\\Share20\\Exception\\BackendError' => $baseDir . '/lib/private/Share20/Exception/BackendError.php', 'OC\\Share20\\Exception\\InvalidShare' => $baseDir . '/lib/private/Share20/Exception/InvalidShare.php', 'OC\\Share20\\Exception\\ProviderException' => $baseDir . '/lib/private/Share20/Exception/ProviderException.php', - 'OC\\Share20\\Hooks' => $baseDir . '/lib/private/Share20/Hooks.php', + 'OC\\Share20\\GroupDeletedListener' => $baseDir . '/lib/private/Share20/GroupDeletedListener.php', 'OC\\Share20\\LegacyHooks' => $baseDir . '/lib/private/Share20/LegacyHooks.php', 'OC\\Share20\\Manager' => $baseDir . '/lib/private/Share20/Manager.php', 'OC\\Share20\\ProviderFactory' => $baseDir . '/lib/private/Share20/ProviderFactory.php', @@ -1977,6 +2045,7 @@ return array( 'OC\\Share20\\ShareAttributes' => $baseDir . '/lib/private/Share20/ShareAttributes.php', 'OC\\Share20\\ShareDisableChecker' => $baseDir . '/lib/private/Share20/ShareDisableChecker.php', 'OC\\Share20\\ShareHelper' => $baseDir . '/lib/private/Share20/ShareHelper.php', + 'OC\\Share20\\UserDeletedListener' => $baseDir . '/lib/private/Share20/UserDeletedListener.php', 'OC\\Share20\\UserRemovedListener' => $baseDir . '/lib/private/Share20/UserRemovedListener.php', 'OC\\Share\\Constants' => $baseDir . '/lib/private/Share/Constants.php', 'OC\\Share\\Helper' => $baseDir . '/lib/private/Share/Helper.php', @@ -2016,7 +2085,9 @@ return array( 'OC\\Template\\JSResourceLocator' => $baseDir . '/lib/private/Template/JSResourceLocator.php', 'OC\\Template\\ResourceLocator' => $baseDir . '/lib/private/Template/ResourceLocator.php', 'OC\\Template\\ResourceNotFoundException' => $baseDir . '/lib/private/Template/ResourceNotFoundException.php', + 'OC\\Template\\Template' => $baseDir . '/lib/private/Template/Template.php', 'OC\\Template\\TemplateFileLocator' => $baseDir . '/lib/private/Template/TemplateFileLocator.php', + 'OC\\Template\\TemplateManager' => $baseDir . '/lib/private/Template/TemplateManager.php', 'OC\\TextProcessing\\Db\\Task' => $baseDir . '/lib/private/TextProcessing/Db/Task.php', 'OC\\TextProcessing\\Db\\TaskMapper' => $baseDir . '/lib/private/TextProcessing/Db/TaskMapper.php', 'OC\\TextProcessing\\Manager' => $baseDir . '/lib/private/TextProcessing/Manager.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 43b5042c8b4..69231e62689 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -52,6 +52,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'NCU\\Config\\Exceptions\\TypeConflictException' => __DIR__ . '/../../..' . '/lib/unstable/Config/Exceptions/TypeConflictException.php', 'NCU\\Config\\Exceptions\\UnknownKeyException' => __DIR__ . '/../../..' . '/lib/unstable/Config/Exceptions/UnknownKeyException.php', 'NCU\\Config\\IUserConfig' => __DIR__ . '/../../..' . '/lib/unstable/Config/IUserConfig.php', + 'NCU\\Config\\Lexicon\\ConfigLexiconEntry' => __DIR__ . '/../../..' . '/lib/unstable/Config/Lexicon/ConfigLexiconEntry.php', + 'NCU\\Config\\Lexicon\\ConfigLexiconStrictness' => __DIR__ . '/../../..' . '/lib/unstable/Config/Lexicon/ConfigLexiconStrictness.php', + 'NCU\\Config\\Lexicon\\IConfigLexicon' => __DIR__ . '/../../..' . '/lib/unstable/Config/Lexicon/IConfigLexicon.php', 'NCU\\Config\\ValueType' => __DIR__ . '/../../..' . '/lib/unstable/Config/ValueType.php', 'NCU\\Federation\\ISignedCloudFederationProvider' => __DIR__ . '/../../..' . '/lib/unstable/Federation/ISignedCloudFederationProvider.php', 'NCU\\Security\\Signature\\Enum\\DigestAlgorithm' => __DIR__ . '/../../..' . '/lib/unstable/Security/Signature/Enum/DigestAlgorithm.php', @@ -123,6 +126,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\AppFramework\\Http\\Attribute\\OpenAPI' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/OpenAPI.php', 'OCP\\AppFramework\\Http\\Attribute\\PasswordConfirmationRequired' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/PasswordConfirmationRequired.php', 'OCP\\AppFramework\\Http\\Attribute\\PublicPage' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/PublicPage.php', + 'OCP\\AppFramework\\Http\\Attribute\\RequestHeader' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/RequestHeader.php', 'OCP\\AppFramework\\Http\\Attribute\\Route' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/Route.php', 'OCP\\AppFramework\\Http\\Attribute\\StrictCookiesRequired' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/StrictCookiesRequired.php', 'OCP\\AppFramework\\Http\\Attribute\\SubAdminRequired' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/Attribute/SubAdminRequired.php', @@ -228,8 +232,21 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Broadcast\\Events\\IBroadcastEvent' => __DIR__ . '/../../..' . '/lib/public/Broadcast/Events/IBroadcastEvent.php', 'OCP\\Cache\\CappedMemoryCache' => __DIR__ . '/../../..' . '/lib/public/Cache/CappedMemoryCache.php', 'OCP\\Calendar\\BackendTemporarilyUnavailableException' => __DIR__ . '/../../..' . '/lib/public/Calendar/BackendTemporarilyUnavailableException.php', + 'OCP\\Calendar\\CalendarEventStatus' => __DIR__ . '/../../..' . '/lib/public/Calendar/CalendarEventStatus.php', + 'OCP\\Calendar\\CalendarExportOptions' => __DIR__ . '/../../..' . '/lib/public/Calendar/CalendarExportOptions.php', + 'OCP\\Calendar\\Events\\AbstractCalendarObjectEvent' => __DIR__ . '/../../..' . '/lib/public/Calendar/Events/AbstractCalendarObjectEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Calendar/Events/CalendarObjectCreatedEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Calendar/Events/CalendarObjectDeletedEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectMovedEvent' => __DIR__ . '/../../..' . '/lib/public/Calendar/Events/CalendarObjectMovedEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectMovedToTrashEvent' => __DIR__ . '/../../..' . '/lib/public/Calendar/Events/CalendarObjectMovedToTrashEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectRestoredEvent' => __DIR__ . '/../../..' . '/lib/public/Calendar/Events/CalendarObjectRestoredEvent.php', + 'OCP\\Calendar\\Events\\CalendarObjectUpdatedEvent' => __DIR__ . '/../../..' . '/lib/public/Calendar/Events/CalendarObjectUpdatedEvent.php', 'OCP\\Calendar\\Exceptions\\CalendarException' => __DIR__ . '/../../..' . '/lib/public/Calendar/Exceptions/CalendarException.php', + 'OCP\\Calendar\\IAvailabilityResult' => __DIR__ . '/../../..' . '/lib/public/Calendar/IAvailabilityResult.php', 'OCP\\Calendar\\ICalendar' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendar.php', + 'OCP\\Calendar\\ICalendarEventBuilder' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarEventBuilder.php', + 'OCP\\Calendar\\ICalendarExport' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarExport.php', + 'OCP\\Calendar\\ICalendarIsEnabled' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarIsEnabled.php', 'OCP\\Calendar\\ICalendarIsShared' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarIsShared.php', 'OCP\\Calendar\\ICalendarIsWritable' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarIsWritable.php', 'OCP\\Calendar\\ICalendarProvider' => __DIR__ . '/../../..' . '/lib/public/Calendar/ICalendarProvider.php', @@ -346,6 +363,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\DirectEditing\\IToken' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/IToken.php', 'OCP\\DirectEditing\\RegisterDirectEditorEvent' => __DIR__ . '/../../..' . '/lib/public/DirectEditing/RegisterDirectEditorEvent.php', 'OCP\\Encryption\\Exceptions\\GenericEncryptionException' => __DIR__ . '/../../..' . '/lib/public/Encryption/Exceptions/GenericEncryptionException.php', + 'OCP\\Encryption\\Exceptions\\InvalidHeaderException' => __DIR__ . '/../../..' . '/lib/public/Encryption/Exceptions/InvalidHeaderException.php', 'OCP\\Encryption\\IEncryptionModule' => __DIR__ . '/../../..' . '/lib/public/Encryption/IEncryptionModule.php', 'OCP\\Encryption\\IFile' => __DIR__ . '/../../..' . '/lib/public/Encryption/IFile.php', 'OCP\\Encryption\\IManager' => __DIR__ . '/../../..' . '/lib/public/Encryption/IManager.php', @@ -405,6 +423,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Files\\Cache\\IScanner' => __DIR__ . '/../../..' . '/lib/public/Files/Cache/IScanner.php', 'OCP\\Files\\Cache\\IUpdater' => __DIR__ . '/../../..' . '/lib/public/Files/Cache/IUpdater.php', 'OCP\\Files\\Cache\\IWatcher' => __DIR__ . '/../../..' . '/lib/public/Files/Cache/IWatcher.php', + 'OCP\\Files\\Config\\Event\\UserMountAddedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Config/Event/UserMountAddedEvent.php', + 'OCP\\Files\\Config\\Event\\UserMountRemovedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Config/Event/UserMountRemovedEvent.php', + 'OCP\\Files\\Config\\Event\\UserMountUpdatedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Config/Event/UserMountUpdatedEvent.php', 'OCP\\Files\\Config\\ICachedMountFileInfo' => __DIR__ . '/../../..' . '/lib/public/Files/Config/ICachedMountFileInfo.php', 'OCP\\Files\\Config\\ICachedMountInfo' => __DIR__ . '/../../..' . '/lib/public/Files/Config/ICachedMountInfo.php', 'OCP\\Files\\Config\\IHomeMountProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IHomeMountProvider.php', @@ -413,6 +434,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Files\\Config\\IRootMountProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IRootMountProvider.php', 'OCP\\Files\\Config\\IUserMountCache' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IUserMountCache.php', 'OCP\\Files\\ConnectionLostException' => __DIR__ . '/../../..' . '/lib/public/Files/ConnectionLostException.php', + 'OCP\\Files\\Conversion\\ConversionMimeProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Conversion/ConversionMimeProvider.php', + 'OCP\\Files\\Conversion\\IConversionManager' => __DIR__ . '/../../..' . '/lib/public/Files/Conversion/IConversionManager.php', + 'OCP\\Files\\Conversion\\IConversionProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Conversion/IConversionProvider.php', 'OCP\\Files\\DavUtil' => __DIR__ . '/../../..' . '/lib/public/Files/DavUtil.php', 'OCP\\Files\\EmptyFileNameException' => __DIR__ . '/../../..' . '/lib/public/Files/EmptyFileNameException.php', 'OCP\\Files\\EntityTooLargeException' => __DIR__ . '/../../..' . '/lib/public/Files/EntityTooLargeException.php', @@ -481,6 +505,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Files\\Notify\\INotifyHandler' => __DIR__ . '/../../..' . '/lib/public/Files/Notify/INotifyHandler.php', 'OCP\\Files\\Notify\\IRenameChange' => __DIR__ . '/../../..' . '/lib/public/Files/Notify/IRenameChange.php', 'OCP\\Files\\ObjectStore\\IObjectStore' => __DIR__ . '/../../..' . '/lib/public/Files/ObjectStore/IObjectStore.php', + 'OCP\\Files\\ObjectStore\\IObjectStoreMetaData' => __DIR__ . '/../../..' . '/lib/public/Files/ObjectStore/IObjectStoreMetaData.php', 'OCP\\Files\\ObjectStore\\IObjectStoreMultiPartUpload' => __DIR__ . '/../../..' . '/lib/public/Files/ObjectStore/IObjectStoreMultiPartUpload.php', 'OCP\\Files\\ReservedWordException' => __DIR__ . '/../../..' . '/lib/public/Files/ReservedWordException.php', 'OCP\\Files\\Search\\ISearchBinaryOperator' => __DIR__ . '/../../..' . '/lib/public/Files/Search/ISearchBinaryOperator.php', @@ -584,6 +609,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Http\\WellKnown\\IResponse' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/IResponse.php', 'OCP\\Http\\WellKnown\\JrdResponse' => __DIR__ . '/../../..' . '/lib/public/Http/WellKnown/JrdResponse.php', 'OCP\\IAddressBook' => __DIR__ . '/../../..' . '/lib/public/IAddressBook.php', + 'OCP\\IAddressBookEnabled' => __DIR__ . '/../../..' . '/lib/public/IAddressBookEnabled.php', 'OCP\\IAppConfig' => __DIR__ . '/../../..' . '/lib/public/IAppConfig.php', 'OCP\\IAvatar' => __DIR__ . '/../../..' . '/lib/public/IAvatar.php', 'OCP\\IAvatarManager' => __DIR__ . '/../../..' . '/lib/public/IAvatarManager.php', @@ -678,6 +704,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Migration\\IOutput' => __DIR__ . '/../../..' . '/lib/public/Migration/IOutput.php', 'OCP\\Migration\\IRepairStep' => __DIR__ . '/../../..' . '/lib/public/Migration/IRepairStep.php', 'OCP\\Migration\\SimpleMigrationStep' => __DIR__ . '/../../..' . '/lib/public/Migration/SimpleMigrationStep.php', + 'OCP\\Navigation\\Events\\LoadAdditionalEntriesEvent' => __DIR__ . '/../../..' . '/lib/public/Navigation/Events/LoadAdditionalEntriesEvent.php', 'OCP\\Notification\\AlreadyProcessedException' => __DIR__ . '/../../..' . '/lib/public/Notification/AlreadyProcessedException.php', 'OCP\\Notification\\IAction' => __DIR__ . '/../../..' . '/lib/public/Notification/IAction.php', 'OCP\\Notification\\IApp' => __DIR__ . '/../../..' . '/lib/public/Notification/IApp.php', @@ -693,6 +720,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\OCM\\Events\\ResourceTypeRegisterEvent' => __DIR__ . '/../../..' . '/lib/public/OCM/Events/ResourceTypeRegisterEvent.php', 'OCP\\OCM\\Exceptions\\OCMArgumentException' => __DIR__ . '/../../..' . '/lib/public/OCM/Exceptions/OCMArgumentException.php', 'OCP\\OCM\\Exceptions\\OCMProviderException' => __DIR__ . '/../../..' . '/lib/public/OCM/Exceptions/OCMProviderException.php', + 'OCP\\OCM\\ICapabilityAwareOCMProvider' => __DIR__ . '/../../..' . '/lib/public/OCM/ICapabilityAwareOCMProvider.php', 'OCP\\OCM\\IOCMDiscoveryService' => __DIR__ . '/../../..' . '/lib/public/OCM/IOCMDiscoveryService.php', 'OCP\\OCM\\IOCMProvider' => __DIR__ . '/../../..' . '/lib/public/OCM/IOCMProvider.php', 'OCP\\OCM\\IOCMResource' => __DIR__ . '/../../..' . '/lib/public/OCM/IOCMResource.php', @@ -790,6 +818,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Share\\Exceptions\\GenericShareException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/GenericShareException.php', 'OCP\\Share\\Exceptions\\IllegalIDChangeException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/IllegalIDChangeException.php', 'OCP\\Share\\Exceptions\\ShareNotFound' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/ShareNotFound.php', + 'OCP\\Share\\Exceptions\\ShareTokenException' => __DIR__ . '/../../..' . '/lib/public/Share/Exceptions/ShareTokenException.php', 'OCP\\Share\\IAttributes' => __DIR__ . '/../../..' . '/lib/public/Share/IAttributes.php', 'OCP\\Share\\IManager' => __DIR__ . '/../../..' . '/lib/public/Share/IManager.php', 'OCP\\Share\\IProviderFactory' => __DIR__ . '/../../..' . '/lib/public/Share/IProviderFactory.php', @@ -799,6 +828,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Share\\IShareHelper' => __DIR__ . '/../../..' . '/lib/public/Share/IShareHelper.php', 'OCP\\Share\\IShareProvider' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProvider.php', 'OCP\\Share\\IShareProviderSupportsAccept' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProviderSupportsAccept.php', + 'OCP\\Share\\IShareProviderSupportsAllSharesInFolder' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php', 'OCP\\Share\\IShareProviderWithNotification' => __DIR__ . '/../../..' . '/lib/public/Share/IShareProviderWithNotification.php', 'OCP\\Share_Backend' => __DIR__ . '/../../..' . '/lib/public/Share_Backend.php', 'OCP\\Share_Backend_Collection' => __DIR__ . '/../../..' . '/lib/public/Share_Backend_Collection.php', @@ -827,7 +857,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\SystemTag\\MapperEvent' => __DIR__ . '/../../..' . '/lib/public/SystemTag/MapperEvent.php', 'OCP\\SystemTag\\SystemTagsEntityEvent' => __DIR__ . '/../../..' . '/lib/public/SystemTag/SystemTagsEntityEvent.php', 'OCP\\SystemTag\\TagAlreadyExistsException' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagAlreadyExistsException.php', + 'OCP\\SystemTag\\TagCreationForbiddenException' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagCreationForbiddenException.php', 'OCP\\SystemTag\\TagNotFoundException' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagNotFoundException.php', + 'OCP\\SystemTag\\TagUpdateForbiddenException' => __DIR__ . '/../../..' . '/lib/public/SystemTag/TagUpdateForbiddenException.php', 'OCP\\Talk\\Exceptions\\NoBackendException' => __DIR__ . '/../../..' . '/lib/public/Talk/Exceptions/NoBackendException.php', 'OCP\\Talk\\IBroker' => __DIR__ . '/../../..' . '/lib/public/Talk/IBroker.php', 'OCP\\Talk\\IConversation' => __DIR__ . '/../../..' . '/lib/public/Talk/IConversation.php', @@ -835,6 +867,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Talk\\ITalkBackend' => __DIR__ . '/../../..' . '/lib/public/Talk/ITalkBackend.php', 'OCP\\TaskProcessing\\EShapeType' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/EShapeType.php', 'OCP\\TaskProcessing\\Events\\AbstractTaskProcessingEvent' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/Events/AbstractTaskProcessingEvent.php', + 'OCP\\TaskProcessing\\Events\\GetTaskProcessingProvidersEvent' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/Events/GetTaskProcessingProvidersEvent.php', 'OCP\\TaskProcessing\\Events\\TaskFailedEvent' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/Events/TaskFailedEvent.php', 'OCP\\TaskProcessing\\Events\\TaskSuccessfulEvent' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/Events/TaskSuccessfulEvent.php', 'OCP\\TaskProcessing\\Exception\\Exception' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/Exception/Exception.php', @@ -855,12 +888,14 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\TaskProcessing\\TaskTypes\\ContextWrite' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/ContextWrite.php', 'OCP\\TaskProcessing\\TaskTypes\\GenerateEmoji' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/GenerateEmoji.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToImage' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToImage.php', + 'OCP\\TaskProcessing\\TaskTypes\\TextToSpeech' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToSpeech.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToText' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToText.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextChangeTone' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextChangeTone.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextChat' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextChat.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextChatWithTools' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextChatWithTools.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextFormalization' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextFormalization.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextHeadline' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php', + 'OCP\\TaskProcessing\\TaskTypes\\TextToTextProofread' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextProofread.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextReformulation' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextReformulation.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextSimplification' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextSimplification.php', 'OCP\\TaskProcessing\\TaskTypes\\TextToTextSummary' => __DIR__ . '/../../..' . '/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php', @@ -871,6 +906,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Teams\\Team' => __DIR__ . '/../../..' . '/lib/public/Teams/Team.php', 'OCP\\Teams\\TeamResource' => __DIR__ . '/../../..' . '/lib/public/Teams/TeamResource.php', 'OCP\\Template' => __DIR__ . '/../../..' . '/lib/public/Template.php', + 'OCP\\Template\\ITemplate' => __DIR__ . '/../../..' . '/lib/public/Template/ITemplate.php', + 'OCP\\Template\\ITemplateManager' => __DIR__ . '/../../..' . '/lib/public/Template/ITemplateManager.php', + 'OCP\\Template\\TemplateNotFoundException' => __DIR__ . '/../../..' . '/lib/public/Template/TemplateNotFoundException.php', 'OCP\\TextProcessing\\Events\\AbstractTextProcessingEvent' => __DIR__ . '/../../..' . '/lib/public/TextProcessing/Events/AbstractTextProcessingEvent.php', 'OCP\\TextProcessing\\Events\\TaskFailedEvent' => __DIR__ . '/../../..' . '/lib/public/TextProcessing/Events/TaskFailedEvent.php', 'OCP\\TextProcessing\\Events\\TaskSuccessfulEvent' => __DIR__ . '/../../..' . '/lib/public/TextProcessing/Events/TaskSuccessfulEvent.php', @@ -922,6 +960,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\User\\Backend\\IGetDisplayNameBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetDisplayNameBackend.php', 'OCP\\User\\Backend\\IGetHomeBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetHomeBackend.php', 'OCP\\User\\Backend\\IGetRealUIDBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IGetRealUIDBackend.php', + 'OCP\\User\\Backend\\ILimitAwareCountUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ILimitAwareCountUsersBackend.php', 'OCP\\User\\Backend\\IPasswordConfirmationBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordConfirmationBackend.php', 'OCP\\User\\Backend\\IPasswordHashBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordHashBackend.php', 'OCP\\User\\Backend\\IProvideAvatarBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideAvatarBackend.php', @@ -1010,6 +1049,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\AppFramework\\Http\\RequestId' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/RequestId.php', 'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php', 'OC\\AppFramework\\Middleware\\CompressionMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php', + 'OC\\AppFramework\\Middleware\\FlowV2EphemeralSessionsMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php', 'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php', 'OC\\AppFramework\\Middleware\\NotModifiedMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php', 'OC\\AppFramework\\Middleware\\OCSMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/OCSMiddleware.php', @@ -1040,7 +1080,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\AppFramework\\OCS\\V1Response' => __DIR__ . '/../../..' . '/lib/private/AppFramework/OCS/V1Response.php', 'OC\\AppFramework\\OCS\\V2Response' => __DIR__ . '/../../..' . '/lib/private/AppFramework/OCS/V2Response.php', 'OC\\AppFramework\\Routing\\RouteActionHandler' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Routing/RouteActionHandler.php', - 'OC\\AppFramework\\Routing\\RouteConfig' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Routing/RouteConfig.php', 'OC\\AppFramework\\Routing\\RouteParser' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Routing/RouteParser.php', 'OC\\AppFramework\\ScopedPsrLogger' => __DIR__ . '/../../..' . '/lib/private/AppFramework/ScopedPsrLogger.php', 'OC\\AppFramework\\Services\\AppConfig' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Services/AppConfig.php', @@ -1052,6 +1091,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\AppScriptDependency' => __DIR__ . '/../../..' . '/lib/private/AppScriptDependency.php', 'OC\\AppScriptSort' => __DIR__ . '/../../..' . '/lib/private/AppScriptSort.php', 'OC\\App\\AppManager' => __DIR__ . '/../../..' . '/lib/private/App/AppManager.php', + 'OC\\App\\AppStore\\AppNotFoundException' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/AppNotFoundException.php', 'OC\\App\\AppStore\\Bundles\\Bundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/Bundle.php', 'OC\\App\\AppStore\\Bundles\\BundleFetcher' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/BundleFetcher.php', 'OC\\App\\AppStore\\Bundles\\EducationBundle' => __DIR__ . '/../../..' . '/lib/private/App/AppStore/Bundles/EducationBundle.php', @@ -1105,8 +1145,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Authentication\\Login\\ClearLostPasswordTokensCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/ClearLostPasswordTokensCommand.php', 'OC\\Authentication\\Login\\CompleteLoginCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/CompleteLoginCommand.php', 'OC\\Authentication\\Login\\CreateSessionTokenCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/CreateSessionTokenCommand.php', - 'OC\\Authentication\\Login\\EmailLoginCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/EmailLoginCommand.php', 'OC\\Authentication\\Login\\FinishRememberedLoginCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/FinishRememberedLoginCommand.php', + 'OC\\Authentication\\Login\\FlowV2EphemeralSessionsCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php', 'OC\\Authentication\\Login\\LoggedInCheckCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/LoggedInCheckCommand.php', 'OC\\Authentication\\Login\\LoginData' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/LoginData.php', 'OC\\Authentication\\Login\\LoginResult' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/LoginResult.php', @@ -1152,6 +1192,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Broadcast\\Events\\BroadcastEvent' => __DIR__ . '/../../..' . '/lib/private/Broadcast/Events/BroadcastEvent.php', 'OC\\Cache\\CappedMemoryCache' => __DIR__ . '/../../..' . '/lib/private/Cache/CappedMemoryCache.php', 'OC\\Cache\\File' => __DIR__ . '/../../..' . '/lib/private/Cache/File.php', + 'OC\\Calendar\\AvailabilityResult' => __DIR__ . '/../../..' . '/lib/private/Calendar/AvailabilityResult.php', + 'OC\\Calendar\\CalendarEventBuilder' => __DIR__ . '/../../..' . '/lib/private/Calendar/CalendarEventBuilder.php', 'OC\\Calendar\\CalendarQuery' => __DIR__ . '/../../..' . '/lib/private/Calendar/CalendarQuery.php', 'OC\\Calendar\\Manager' => __DIR__ . '/../../..' . '/lib/private/Calendar/Manager.php', 'OC\\Calendar\\Resource\\Manager' => __DIR__ . '/../../..' . '/lib/private/Calendar/Resource/Manager.php', @@ -1189,6 +1231,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Comments\\Manager' => __DIR__ . '/../../..' . '/lib/private/Comments/Manager.php', 'OC\\Comments\\ManagerFactory' => __DIR__ . '/../../..' . '/lib/private/Comments/ManagerFactory.php', 'OC\\Config' => __DIR__ . '/../../..' . '/lib/private/Config.php', + 'OC\\Config\\ConfigManager' => __DIR__ . '/../../..' . '/lib/private/Config/ConfigManager.php', + 'OC\\Config\\Lexicon\\CoreConfigLexicon' => __DIR__ . '/../../..' . '/lib/private/Config/Lexicon/CoreConfigLexicon.php', 'OC\\Config\\UserConfig' => __DIR__ . '/../../..' . '/lib/private/Config/UserConfig.php', 'OC\\Console\\Application' => __DIR__ . '/../../..' . '/lib/private/Console/Application.php', 'OC\\Console\\TimestampFormatter' => __DIR__ . '/../../..' . '/lib/private/Console/TimestampFormatter.php', @@ -1202,7 +1246,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Contacts\\ContactsMenu\\Providers\\EMailProvider' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php', 'OC\\Contacts\\ContactsMenu\\Providers\\LocalTimeProvider' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php', 'OC\\Contacts\\ContactsMenu\\Providers\\ProfileProvider' => __DIR__ . '/../../..' . '/lib/private/Contacts/ContactsMenu/Providers/ProfileProvider.php', - 'OC\\Core\\Application' => __DIR__ . '/../../..' . '/core/Application.php', + 'OC\\Core\\AppInfo\\Application' => __DIR__ . '/../../..' . '/core/AppInfo/Application.php', 'OC\\Core\\BackgroundJobs\\BackgroundCleanupUpdaterBackupsJob' => __DIR__ . '/../../..' . '/core/BackgroundJobs/BackgroundCleanupUpdaterBackupsJob.php', 'OC\\Core\\BackgroundJobs\\CheckForUserCertificates' => __DIR__ . '/../../..' . '/core/BackgroundJobs/CheckForUserCertificates.php', 'OC\\Core\\BackgroundJobs\\CleanupLoginFlowV2' => __DIR__ . '/../../..' . '/core/BackgroundJobs/CleanupLoginFlowV2.php', @@ -1231,6 +1275,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\Config\\Import' => __DIR__ . '/../../..' . '/core/Command/Config/Import.php', 'OC\\Core\\Command\\Config\\ListConfigs' => __DIR__ . '/../../..' . '/core/Command/Config/ListConfigs.php', 'OC\\Core\\Command\\Config\\System\\Base' => __DIR__ . '/../../..' . '/core/Command/Config/System/Base.php', + 'OC\\Core\\Command\\Config\\System\\CastHelper' => __DIR__ . '/../../..' . '/core/Command/Config/System/CastHelper.php', 'OC\\Core\\Command\\Config\\System\\DeleteConfig' => __DIR__ . '/../../..' . '/core/Command/Config/System/DeleteConfig.php', 'OC\\Core\\Command\\Config\\System\\GetConfig' => __DIR__ . '/../../..' . '/core/Command/Config/System/GetConfig.php', 'OC\\Core\\Command\\Config\\System\\SetConfig' => __DIR__ . '/../../..' . '/core/Command/Config/System/SetConfig.php', @@ -1269,6 +1314,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\Info\\File' => __DIR__ . '/../../..' . '/core/Command/Info/File.php', 'OC\\Core\\Command\\Info\\FileUtils' => __DIR__ . '/../../..' . '/core/Command/Info/FileUtils.php', 'OC\\Core\\Command\\Info\\Space' => __DIR__ . '/../../..' . '/core/Command/Info/Space.php', + 'OC\\Core\\Command\\Info\\Storage' => __DIR__ . '/../../..' . '/core/Command/Info/Storage.php', + 'OC\\Core\\Command\\Info\\Storages' => __DIR__ . '/../../..' . '/core/Command/Info/Storages.php', 'OC\\Core\\Command\\Integrity\\CheckApp' => __DIR__ . '/../../..' . '/core/Command/Integrity/CheckApp.php', 'OC\\Core\\Command\\Integrity\\CheckCore' => __DIR__ . '/../../..' . '/core/Command/Integrity/CheckCore.php', 'OC\\Core\\Command\\Integrity\\SignApp' => __DIR__ . '/../../..' . '/core/Command/Integrity/SignApp.php', @@ -1287,11 +1334,17 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\Maintenance\\RepairShareOwnership' => __DIR__ . '/../../..' . '/core/Command/Maintenance/RepairShareOwnership.php', 'OC\\Core\\Command\\Maintenance\\UpdateHtaccess' => __DIR__ . '/../../..' . '/core/Command/Maintenance/UpdateHtaccess.php', 'OC\\Core\\Command\\Maintenance\\UpdateTheme' => __DIR__ . '/../../..' . '/core/Command/Maintenance/UpdateTheme.php', + 'OC\\Core\\Command\\Memcache\\DistributedClear' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedClear.php', + 'OC\\Core\\Command\\Memcache\\DistributedDelete' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedDelete.php', + 'OC\\Core\\Command\\Memcache\\DistributedGet' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedGet.php', + 'OC\\Core\\Command\\Memcache\\DistributedSet' => __DIR__ . '/../../..' . '/core/Command/Memcache/DistributedSet.php', 'OC\\Core\\Command\\Memcache\\RedisCommand' => __DIR__ . '/../../..' . '/core/Command/Memcache/RedisCommand.php', 'OC\\Core\\Command\\Preview\\Cleanup' => __DIR__ . '/../../..' . '/core/Command/Preview/Cleanup.php', 'OC\\Core\\Command\\Preview\\Generate' => __DIR__ . '/../../..' . '/core/Command/Preview/Generate.php', 'OC\\Core\\Command\\Preview\\Repair' => __DIR__ . '/../../..' . '/core/Command/Preview/Repair.php', 'OC\\Core\\Command\\Preview\\ResetRenderedTexts' => __DIR__ . '/../../..' . '/core/Command/Preview/ResetRenderedTexts.php', + 'OC\\Core\\Command\\Router\\ListRoutes' => __DIR__ . '/../../..' . '/core/Command/Router/ListRoutes.php', + 'OC\\Core\\Command\\Router\\MatchRoute' => __DIR__ . '/../../..' . '/core/Command/Router/MatchRoute.php', 'OC\\Core\\Command\\Security\\BruteforceAttempts' => __DIR__ . '/../../..' . '/core/Command/Security/BruteforceAttempts.php', 'OC\\Core\\Command\\Security\\BruteforceResetAttempts' => __DIR__ . '/../../..' . '/core/Command/Security/BruteforceResetAttempts.php', 'OC\\Core\\Command\\Security\\ExportCertificates' => __DIR__ . '/../../..' . '/core/Command/Security/ExportCertificates.php', @@ -1304,6 +1357,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\SystemTag\\Delete' => __DIR__ . '/../../..' . '/core/Command/SystemTag/Delete.php', 'OC\\Core\\Command\\SystemTag\\Edit' => __DIR__ . '/../../..' . '/core/Command/SystemTag/Edit.php', 'OC\\Core\\Command\\SystemTag\\ListCommand' => __DIR__ . '/../../..' . '/core/Command/SystemTag/ListCommand.php', + 'OC\\Core\\Command\\TaskProcessing\\EnabledCommand' => __DIR__ . '/../../..' . '/core/Command/TaskProcessing/EnabledCommand.php', 'OC\\Core\\Command\\TaskProcessing\\GetCommand' => __DIR__ . '/../../..' . '/core/Command/TaskProcessing/GetCommand.php', 'OC\\Core\\Command\\TaskProcessing\\ListCommand' => __DIR__ . '/../../..' . '/core/Command/TaskProcessing/ListCommand.php', 'OC\\Core\\Command\\TaskProcessing\\Statistics' => __DIR__ . '/../../..' . '/core/Command/TaskProcessing/Statistics.php', @@ -1326,6 +1380,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Command\\User\\Keys\\Verify' => __DIR__ . '/../../..' . '/core/Command/User/Keys/Verify.php', 'OC\\Core\\Command\\User\\LastSeen' => __DIR__ . '/../../..' . '/core/Command/User/LastSeen.php', 'OC\\Core\\Command\\User\\ListCommand' => __DIR__ . '/../../..' . '/core/Command/User/ListCommand.php', + 'OC\\Core\\Command\\User\\Profile' => __DIR__ . '/../../..' . '/core/Command/User/Profile.php', 'OC\\Core\\Command\\User\\Report' => __DIR__ . '/../../..' . '/core/Command/User/Report.php', 'OC\\Core\\Command\\User\\ResetPassword' => __DIR__ . '/../../..' . '/core/Command/User/ResetPassword.php', 'OC\\Core\\Command\\User\\Setting' => __DIR__ . '/../../..' . '/core/Command/User/Setting.php', @@ -1361,6 +1416,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Controller\\TextProcessingApiController' => __DIR__ . '/../../..' . '/core/Controller/TextProcessingApiController.php', 'OC\\Core\\Controller\\TextToImageApiController' => __DIR__ . '/../../..' . '/core/Controller/TextToImageApiController.php', 'OC\\Core\\Controller\\TranslationApiController' => __DIR__ . '/../../..' . '/core/Controller/TranslationApiController.php', + 'OC\\Core\\Controller\\TwoFactorApiController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorApiController.php', 'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php', 'OC\\Core\\Controller\\UnifiedSearchController' => __DIR__ . '/../../..' . '/core/Controller/UnifiedSearchController.php', 'OC\\Core\\Controller\\UnsupportedBrowserController' => __DIR__ . '/../../..' . '/core/Controller/UnsupportedBrowserController.php', @@ -1378,10 +1434,14 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Db\\ProfileConfigMapper' => __DIR__ . '/../../..' . '/core/Db/ProfileConfigMapper.php', 'OC\\Core\\Events\\BeforePasswordResetEvent' => __DIR__ . '/../../..' . '/core/Events/BeforePasswordResetEvent.php', 'OC\\Core\\Events\\PasswordResetEvent' => __DIR__ . '/../../..' . '/core/Events/PasswordResetEvent.php', + 'OC\\Core\\Exception\\LoginFlowV2ClientForbiddenException' => __DIR__ . '/../../..' . '/core/Exception/LoginFlowV2ClientForbiddenException.php', 'OC\\Core\\Exception\\LoginFlowV2NotFoundException' => __DIR__ . '/../../..' . '/core/Exception/LoginFlowV2NotFoundException.php', 'OC\\Core\\Exception\\ResetPasswordException' => __DIR__ . '/../../..' . '/core/Exception/ResetPasswordException.php', + 'OC\\Core\\Listener\\AddMissingIndicesListener' => __DIR__ . '/../../..' . '/core/Listener/AddMissingIndicesListener.php', + 'OC\\Core\\Listener\\AddMissingPrimaryKeyListener' => __DIR__ . '/../../..' . '/core/Listener/AddMissingPrimaryKeyListener.php', 'OC\\Core\\Listener\\BeforeMessageLoggedEventListener' => __DIR__ . '/../../..' . '/core/Listener/BeforeMessageLoggedEventListener.php', 'OC\\Core\\Listener\\BeforeTemplateRenderedListener' => __DIR__ . '/../../..' . '/core/Listener/BeforeTemplateRenderedListener.php', + 'OC\\Core\\Listener\\FeedBackHandler' => __DIR__ . '/../../..' . '/core/Listener/FeedBackHandler.php', 'OC\\Core\\Middleware\\TwoFactorMiddleware' => __DIR__ . '/../../..' . '/core/Middleware/TwoFactorMiddleware.php', 'OC\\Core\\Migrations\\Version13000Date20170705121758' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170705121758.php', 'OC\\Core\\Migrations\\Version13000Date20170718121200' => __DIR__ . '/../../..' . '/core/Migrations/Version13000Date20170718121200.php', @@ -1460,6 +1520,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Core\\Migrations\\Version30000Date20240906095113' => __DIR__ . '/../../..' . '/core/Migrations/Version30000Date20240906095113.php', 'OC\\Core\\Migrations\\Version31000Date20240101084401' => __DIR__ . '/../../..' . '/core/Migrations/Version31000Date20240101084401.php', 'OC\\Core\\Migrations\\Version31000Date20240814184402' => __DIR__ . '/../../..' . '/core/Migrations/Version31000Date20240814184402.php', + 'OC\\Core\\Migrations\\Version31000Date20250213102442' => __DIR__ . '/../../..' . '/core/Migrations/Version31000Date20250213102442.php', + 'OC\\Core\\Migrations\\Version32000Date20250620081925' => __DIR__ . '/../../..' . '/core/Migrations/Version32000Date20250620081925.php', 'OC\\Core\\Notification\\CoreNotifier' => __DIR__ . '/../../..' . '/core/Notification/CoreNotifier.php', 'OC\\Core\\ResponseDefinitions' => __DIR__ . '/../../..' . '/core/ResponseDefinitions.php', 'OC\\Core\\Service\\LoginFlowV2Service' => __DIR__ . '/../../..' . '/core/Service/LoginFlowV2Service.php', @@ -1538,6 +1600,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\DirectEditing\\Token' => __DIR__ . '/../../..' . '/lib/private/DirectEditing/Token.php', 'OC\\EmojiHelper' => __DIR__ . '/../../..' . '/lib/private/EmojiHelper.php', 'OC\\Encryption\\DecryptAll' => __DIR__ . '/../../..' . '/lib/private/Encryption/DecryptAll.php', + 'OC\\Encryption\\EncryptionEventListener' => __DIR__ . '/../../..' . '/lib/private/Encryption/EncryptionEventListener.php', 'OC\\Encryption\\EncryptionWrapper' => __DIR__ . '/../../..' . '/lib/private/Encryption/EncryptionWrapper.php', 'OC\\Encryption\\Exceptions\\DecryptionFailedException' => __DIR__ . '/../../..' . '/lib/private/Encryption/Exceptions/DecryptionFailedException.php', 'OC\\Encryption\\Exceptions\\EmptyEncryptionDataException' => __DIR__ . '/../../..' . '/lib/private/Encryption/Exceptions/EmptyEncryptionDataException.php', @@ -1548,7 +1611,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Encryption\\Exceptions\\ModuleDoesNotExistsException' => __DIR__ . '/../../..' . '/lib/private/Encryption/Exceptions/ModuleDoesNotExistsException.php', 'OC\\Encryption\\Exceptions\\UnknownCipherException' => __DIR__ . '/../../..' . '/lib/private/Encryption/Exceptions/UnknownCipherException.php', 'OC\\Encryption\\File' => __DIR__ . '/../../..' . '/lib/private/Encryption/File.php', - 'OC\\Encryption\\HookManager' => __DIR__ . '/../../..' . '/lib/private/Encryption/HookManager.php', 'OC\\Encryption\\Keys\\Storage' => __DIR__ . '/../../..' . '/lib/private/Encryption/Keys/Storage.php', 'OC\\Encryption\\Manager' => __DIR__ . '/../../..' . '/lib/private/Encryption/Manager.php', 'OC\\Encryption\\Update' => __DIR__ . '/../../..' . '/lib/private/Encryption/Update.php', @@ -1605,6 +1667,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Files\\Config\\MountProviderCollection' => __DIR__ . '/../../..' . '/lib/private/Files/Config/MountProviderCollection.php', 'OC\\Files\\Config\\UserMountCache' => __DIR__ . '/../../..' . '/lib/private/Files/Config/UserMountCache.php', 'OC\\Files\\Config\\UserMountCacheListener' => __DIR__ . '/../../..' . '/lib/private/Files/Config/UserMountCacheListener.php', + 'OC\\Files\\Conversion\\ConversionManager' => __DIR__ . '/../../..' . '/lib/private/Files/Conversion/ConversionManager.php', 'OC\\Files\\FileInfo' => __DIR__ . '/../../..' . '/lib/private/Files/FileInfo.php', 'OC\\Files\\FilenameValidator' => __DIR__ . '/../../..' . '/lib/private/Files/FilenameValidator.php', 'OC\\Files\\Filesystem' => __DIR__ . '/../../..' . '/lib/private/Files/Filesystem.php', @@ -1636,6 +1699,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Files\\ObjectStore\\Mapper' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/Mapper.php', 'OC\\Files\\ObjectStore\\ObjectStoreScanner' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/ObjectStoreScanner.php', 'OC\\Files\\ObjectStore\\ObjectStoreStorage' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/ObjectStoreStorage.php', + 'OC\\Files\\ObjectStore\\PrimaryObjectStoreConfig' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php', 'OC\\Files\\ObjectStore\\S3' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3.php', 'OC\\Files\\ObjectStore\\S3ConfigTrait' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3ConfigTrait.php', 'OC\\Files\\ObjectStore\\S3ConnectionTrait' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/S3ConnectionTrait.php', @@ -1857,6 +1921,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Profile\\Actions\\WebsiteAction' => __DIR__ . '/../../..' . '/lib/private/Profile/Actions/WebsiteAction.php', 'OC\\Profile\\ProfileManager' => __DIR__ . '/../../..' . '/lib/private/Profile/ProfileManager.php', 'OC\\Profile\\TProfileHelper' => __DIR__ . '/../../..' . '/lib/private/Profile/TProfileHelper.php', + 'OC\\Profiler\\BuiltInProfiler' => __DIR__ . '/../../..' . '/lib/private/Profiler/BuiltInProfiler.php', 'OC\\Profiler\\FileProfilerStorage' => __DIR__ . '/../../..' . '/lib/private/Profiler/FileProfilerStorage.php', 'OC\\Profiler\\Profile' => __DIR__ . '/../../..' . '/lib/private/Profiler/Profile.php', 'OC\\Profiler\\Profiler' => __DIR__ . '/../../..' . '/lib/private/Profiler/Profiler.php', @@ -1885,6 +1950,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Repair\\ClearGeneratedAvatarCache' => __DIR__ . '/../../..' . '/lib/private/Repair/ClearGeneratedAvatarCache.php', 'OC\\Repair\\ClearGeneratedAvatarCacheJob' => __DIR__ . '/../../..' . '/lib/private/Repair/ClearGeneratedAvatarCacheJob.php', 'OC\\Repair\\Collation' => __DIR__ . '/../../..' . '/lib/private/Repair/Collation.php', + 'OC\\Repair\\ConfigKeyMigration' => __DIR__ . '/../../..' . '/lib/private/Repair/ConfigKeyMigration.php', 'OC\\Repair\\Events\\RepairAdvanceEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairAdvanceEvent.php', 'OC\\Repair\\Events\\RepairErrorEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairErrorEvent.php', 'OC\\Repair\\Events\\RepairFinishEvent' => __DIR__ . '/../../..' . '/lib/private/Repair/Events/RepairFinishEvent.php', @@ -1903,10 +1969,11 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Repair\\NC20\\EncryptionMigration' => __DIR__ . '/../../..' . '/lib/private/Repair/NC20/EncryptionMigration.php', 'OC\\Repair\\NC20\\ShippedDashboardEnable' => __DIR__ . '/../../..' . '/lib/private/Repair/NC20/ShippedDashboardEnable.php', 'OC\\Repair\\NC21\\AddCheckForUserCertificatesJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php', - 'OC\\Repair\\NC21\\ValidatePhoneNumber' => __DIR__ . '/../../..' . '/lib/private/Repair/NC21/ValidatePhoneNumber.php', 'OC\\Repair\\NC22\\LookupServerSendCheck' => __DIR__ . '/../../..' . '/lib/private/Repair/NC22/LookupServerSendCheck.php', 'OC\\Repair\\NC24\\AddTokenCleanupJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC24/AddTokenCleanupJob.php', 'OC\\Repair\\NC25\\AddMissingSecretJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC25/AddMissingSecretJob.php', + 'OC\\Repair\\NC29\\SanitizeAccountProperties' => __DIR__ . '/../../..' . '/lib/private/Repair/NC29/SanitizeAccountProperties.php', + 'OC\\Repair\\NC29\\SanitizeAccountPropertiesJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC29/SanitizeAccountPropertiesJob.php', 'OC\\Repair\\NC30\\RemoveLegacyDatadirFile' => __DIR__ . '/../../..' . '/lib/private/Repair/NC30/RemoveLegacyDatadirFile.php', 'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\Owncloud\\CleanPreviews' => __DIR__ . '/../../..' . '/lib/private/Repair/Owncloud/CleanPreviews.php', @@ -1965,6 +2032,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Security\\IdentityProof\\Manager' => __DIR__ . '/../../..' . '/lib/private/Security/IdentityProof/Manager.php', 'OC\\Security\\IdentityProof\\Signer' => __DIR__ . '/../../..' . '/lib/private/Security/IdentityProof/Signer.php', 'OC\\Security\\Ip\\Address' => __DIR__ . '/../../..' . '/lib/private/Security/Ip/Address.php', + 'OC\\Security\\Ip\\BruteforceAllowList' => __DIR__ . '/../../..' . '/lib/private/Security/Ip/BruteforceAllowList.php', 'OC\\Security\\Ip\\Factory' => __DIR__ . '/../../..' . '/lib/private/Security/Ip/Factory.php', 'OC\\Security\\Ip\\Range' => __DIR__ . '/../../..' . '/lib/private/Security/Ip/Range.php', 'OC\\Security\\Ip\\RemoteAddress' => __DIR__ . '/../../..' . '/lib/private/Security/Ip/RemoteAddress.php', @@ -2009,7 +2077,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Share20\\Exception\\BackendError' => __DIR__ . '/../../..' . '/lib/private/Share20/Exception/BackendError.php', 'OC\\Share20\\Exception\\InvalidShare' => __DIR__ . '/../../..' . '/lib/private/Share20/Exception/InvalidShare.php', 'OC\\Share20\\Exception\\ProviderException' => __DIR__ . '/../../..' . '/lib/private/Share20/Exception/ProviderException.php', - 'OC\\Share20\\Hooks' => __DIR__ . '/../../..' . '/lib/private/Share20/Hooks.php', + 'OC\\Share20\\GroupDeletedListener' => __DIR__ . '/../../..' . '/lib/private/Share20/GroupDeletedListener.php', 'OC\\Share20\\LegacyHooks' => __DIR__ . '/../../..' . '/lib/private/Share20/LegacyHooks.php', 'OC\\Share20\\Manager' => __DIR__ . '/../../..' . '/lib/private/Share20/Manager.php', 'OC\\Share20\\ProviderFactory' => __DIR__ . '/../../..' . '/lib/private/Share20/ProviderFactory.php', @@ -2018,6 +2086,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Share20\\ShareAttributes' => __DIR__ . '/../../..' . '/lib/private/Share20/ShareAttributes.php', 'OC\\Share20\\ShareDisableChecker' => __DIR__ . '/../../..' . '/lib/private/Share20/ShareDisableChecker.php', 'OC\\Share20\\ShareHelper' => __DIR__ . '/../../..' . '/lib/private/Share20/ShareHelper.php', + 'OC\\Share20\\UserDeletedListener' => __DIR__ . '/../../..' . '/lib/private/Share20/UserDeletedListener.php', 'OC\\Share20\\UserRemovedListener' => __DIR__ . '/../../..' . '/lib/private/Share20/UserRemovedListener.php', 'OC\\Share\\Constants' => __DIR__ . '/../../..' . '/lib/private/Share/Constants.php', 'OC\\Share\\Helper' => __DIR__ . '/../../..' . '/lib/private/Share/Helper.php', @@ -2057,7 +2126,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OC\\Template\\JSResourceLocator' => __DIR__ . '/../../..' . '/lib/private/Template/JSResourceLocator.php', 'OC\\Template\\ResourceLocator' => __DIR__ . '/../../..' . '/lib/private/Template/ResourceLocator.php', 'OC\\Template\\ResourceNotFoundException' => __DIR__ . '/../../..' . '/lib/private/Template/ResourceNotFoundException.php', + 'OC\\Template\\Template' => __DIR__ . '/../../..' . '/lib/private/Template/Template.php', 'OC\\Template\\TemplateFileLocator' => __DIR__ . '/../../..' . '/lib/private/Template/TemplateFileLocator.php', + 'OC\\Template\\TemplateManager' => __DIR__ . '/../../..' . '/lib/private/Template/TemplateManager.php', 'OC\\TextProcessing\\Db\\Task' => __DIR__ . '/../../..' . '/lib/private/TextProcessing/Db/Task.php', 'OC\\TextProcessing\\Db\\TaskMapper' => __DIR__ . '/../../..' . '/lib/private/TextProcessing/Db/TaskMapper.php', 'OC\\TextProcessing\\Manager' => __DIR__ . '/../../..' . '/lib/private/TextProcessing/Manager.php', diff --git a/lib/composer/composer/installed.json b/lib/composer/composer/installed.json index 13ea12dca2a..f20a6c47c6d 100644 --- a/lib/composer/composer/installed.json +++ b/lib/composer/composer/installed.json @@ -1,68 +1,5 @@ { - "packages": [ - { - "name": "bamarni/composer-bin-plugin", - "version": "1.8.2", - "version_normalized": "1.8.2.0", - "source": { - "type": "git", - "url": "https://github.com/bamarni/composer-bin-plugin.git", - "reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880", - "reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.0", - "php": "^7.2.5 || ^8.0" - }, - "require-dev": { - "composer/composer": "^2.0", - "ext-json": "*", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.5", - "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0" - }, - "time": "2022-10-31T08:38:03+00:00", - "type": "composer-plugin", - "extra": { - "class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin" - }, - "installation-source": "dist", - "autoload": { - "psr-4": { - "Bamarni\\Composer\\Bin\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "No conflicts for your bin dependencies", - "keywords": [ - "composer", - "conflict", - "dependency", - "executable", - "isolation", - "tool" - ], - "support": { - "issues": "https://github.com/bamarni/composer-bin-plugin/issues", - "source": "https://github.com/bamarni/composer-bin-plugin/tree/1.8.2" - }, - "install-path": "../bamarni/composer-bin-plugin" - } - ], - "dev": true, - "dev-package-names": [ - "bamarni/composer-bin-plugin" - ] + "packages": [], + "dev": false, + "dev-package-names": [] } diff --git a/lib/composer/composer/installed.php b/lib/composer/composer/installed.php index bd6f4140a96..1cfe4bf1d74 100644 --- a/lib/composer/composer/installed.php +++ b/lib/composer/composer/installed.php @@ -3,30 +3,21 @@ 'name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'ee76fe192de8656d216b4079a6c50dda3fc9cdb1', + 'reference' => 'b7422ba97b7b42a9955a52031a32457ca521d740', 'type' => 'library', 'install_path' => __DIR__ . '/../../../', 'aliases' => array(), - 'dev' => true, + 'dev' => false, ), 'versions' => array( '__root__' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'ee76fe192de8656d216b4079a6c50dda3fc9cdb1', + 'reference' => 'b7422ba97b7b42a9955a52031a32457ca521d740', 'type' => 'library', 'install_path' => __DIR__ . '/../../../', 'aliases' => array(), 'dev_requirement' => false, ), - 'bamarni/composer-bin-plugin' => array( - 'pretty_version' => '1.8.2', - 'version' => '1.8.2.0', - 'reference' => '92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880', - 'type' => 'composer-plugin', - 'install_path' => __DIR__ . '/../bamarni/composer-bin-plugin', - 'aliases' => array(), - 'dev_requirement' => true, - ), ), ); diff --git a/lib/l10n/af.js b/lib/l10n/af.js index 4f9af502ede..e5f6ef63633 100644 --- a/lib/l10n/af.js +++ b/lib/l10n/af.js @@ -26,10 +26,7 @@ OC.L10N.register( "Saturday" : "Saterdag", "a safe home for all your data" : "’n veilige tuiste vir al u data", "Storage is temporarily not available" : "Berging is tydelik nie beskikbaar nie", - "Summary" : "Opsomming", - "Help" : "Hulp", - "Users" : "Gebruikers", - "Unknown user" : "Onbekende gebruiker", - "Open »%s«" : "Open »%s«" + "Text" : "Teks", + "Summary" : "Opsomming" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/af.json b/lib/l10n/af.json index b9096c2c245..751b24be3cc 100644 --- a/lib/l10n/af.json +++ b/lib/l10n/af.json @@ -24,10 +24,7 @@ "Saturday" : "Saterdag", "a safe home for all your data" : "’n veilige tuiste vir al u data", "Storage is temporarily not available" : "Berging is tydelik nie beskikbaar nie", - "Summary" : "Opsomming", - "Help" : "Hulp", - "Users" : "Gebruikers", - "Unknown user" : "Onbekende gebruiker", - "Open »%s«" : "Open »%s«" + "Text" : "Teks", + "Summary" : "Opsomming" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/an.js b/lib/l10n/an.js index 0087af4c8a9..a5fb073752e 100644 --- a/lib/l10n/an.js +++ b/lib/l10n/an.js @@ -8,11 +8,9 @@ OC.L10N.register( "today" : "Hue", "yesterday" : "Ayer", "last month" : "Zaguero mes", - "last year" : "Zaguero año", - "Apps" : "Aplicazions", - "Settings" : "Configurazión", - "Email" : "Correu electronico", - "Help" : "Aduya", - "Users" : "Usuarios" + "last year" : "Zaguero anyo", + "Apps" : "Aplicacions", + "Settings" : "Configuración", + "Email" : "Correu electronico" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/an.json b/lib/l10n/an.json index 3a26f9e5613..52f81577846 100644 --- a/lib/l10n/an.json +++ b/lib/l10n/an.json @@ -6,11 +6,9 @@ "today" : "Hue", "yesterday" : "Ayer", "last month" : "Zaguero mes", - "last year" : "Zaguero año", - "Apps" : "Aplicazions", - "Settings" : "Configurazión", - "Email" : "Correu electronico", - "Help" : "Aduya", - "Users" : "Usuarios" + "last year" : "Zaguero anyo", + "Apps" : "Aplicacions", + "Settings" : "Configuración", + "Email" : "Correu electronico" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/ar.js b/lib/l10n/ar.js index 58cd5ef2295..07b5ed9c759 100644 --- a/lib/l10n/ar.js +++ b/lib/l10n/ar.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "مطلوب إصدار الخادم %s أو أعلى.", "Server version %s or lower is required." : "مطلوب إصدار الخادم %s أو أقل.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "الحساب المسجل دخوله يجب أن يكون حساب مدير أو مدير فرعي أو يملك حقاً خاصاً للوصول إلى هذا الإعداد", - "Your current IP address doesn’t allow you to perform admin actions" : "عنوانك الحالي IP يمنعك من أداء مهام المدير", + "Your current IP address doesn't allow you to perform admin actions" : "عنوان IP الحالي لايسمح لك بتنفيذ إجراءات الإدارة", "Logged in account must be an admin or sub admin" : "الحساب المسجل دخوله يجب أن يكون حساب مدير أو مدير فرعي", "Logged in account must be an admin" : "الحساب المسجل دخوله يجب أن يكون حساب مدير", "Wiping of device %s has started" : "بدأ مسح الجهاز %s ", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "الصورة الرمزية ليست على شكل مربّع", "Files" : "الملفات", "View profile" : "عرض الملف الشخصي", + "same time" : "نفس التوقيت", + "_%nh_::_%nh_" : ["%n ساعة","%n ساعة","%n ساعة","%n ساعة","%n ساعة","%n ساعة"], + "_%nm_::_%nm_" : ["%nد","%nد","%nد","%nد","%nد","%nد"], + "%s ahead" : "%s مُتقَدِّم", + "%s behind" : "%s مُتأَخِّر", "Local time: %s" : "الوقت المحلّي: %s", "today" : "اليوم", "tomorrow" : "يوم غد", @@ -81,7 +86,14 @@ OC.L10N.register( "seconds ago" : "منذ ثوانٍ", "Empty file" : "ملفٌ فارغٌ", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "الوحدة module ذات الرقم ID ـ : %s غير موجودة. رجاءً، فعّلها في إعدادات التطبيقات لديك، أو اتصل بمسؤول النظام.", + "No file conversion providers available" : "لا يوجد أي مُزوِّد لتحويل الملفات", + "File is too large to convert" : "الملف كبير جداً فلايمكن تحويله", + "Destination does not match conversion extension" : "المَقصِد لايتطابق مع امتداد التحويل", + "Could not convert file" : "لايمكن تحويل الملف", + "Destination does not exist" : "المَقصِد غير موجود", + "Destination is not creatable" : "المِقصِد لايمكن إنشاؤه", "Dot files are not allowed" : "الملفات النقطية (ملفات ذات أسماء تبدأ بنقطة) غير مسموح بها", + "renamed file" : "ملف معاد تسميته", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" غير مسموح به أن يكون اسم ملف أو مجلد.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" غير مسموح به أن يكون بادئة لاسم ملف أو مجلد.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" غير مسموح به أن يكون داخل اسم ملف أو مجلد.", @@ -92,6 +104,13 @@ OC.L10N.register( "Invalid path" : "مسار غير صالح !", "Failed to create file from template" : "تعذّر إنشاء ملفٍ من قالبٍ", "Templates" : "القوالب", + "Storage %s cannot be moved" : "وحدة التخزين %s لايمكن نقلها", + "Moving a share (%s) into a shared folder is not allowed" : "نقل مشاركة (%s) في مجلد مشترك غير ممكن", + "Moving a storage (%s) into a shared folder is not allowed" : "نقل وحدة تخزين (%s) في مجلد مشترك غير ممكن", + "Moving a share (%s) into another share (%s) is not allowed" : "نقل مشاركة (%s) في مشاركة أخرى (%s) غير ممكن", + "Moving a share (%s) into another storage (%s) is not allowed" : "نقل مشاركة (%s) لوحدة تخزين أخرى (%s) غير ممكن", + "Moving a storage (%s) into a share (%s) is not allowed" : "نقل وحدة تخزين (%s) في مشاركة (%s) غير ممكن", + "Moving a storage (%s) into another storage (%s) is not allowed" : "نقل وحدة تخزين (%s) في وحدة تخزين أخرى (%s) غير ممكن", "Path contains invalid segments" : "يحتوي المسار على أجزاء غير صحيحة", "Filename is a reserved word" : "اسم الملف غير مقبوله لأنه كلمة محجوزة", "Filename contains at least one invalid character" : "اسم الملف به على الأقل حرفٌ غير صالح", @@ -124,7 +143,7 @@ OC.L10N.register( "About" : "عن", "Display name" : "اسم العرض", "Headline" : "عنوان ", - "Organisation" : "مؤسسة", + "Organization" : "المنظمة", "Role" : "الوظيفة", "Pronouns" : "الضمائر", "Unknown account" : "حساب غير معروف", @@ -138,7 +157,7 @@ OC.L10N.register( "Oracle connection could not be established" : "لم تنجح محاولة اتصال Oracle", "Oracle Login and/or password not valid" : "مُعرف تسجيل الدخول او كلمة مرور Oracle غير صحيحة", "PostgreSQL Login and/or password not valid" : "مُعرف تسجيل دخول او كلمة مرور PostgreSQL غير صحيحة", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "نظام ماك العاشر غير مدعوم و %s .لن يعمل بالشكل الصحيح على هذه المنصةاستعمله يكون على مسؤوليتك!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "\"Mac OS X\" غير مدعوم؛ و %s سوف لن يعمل بالشكل الصحيح على هذه المنصة. استعمله على مسؤوليتك!", "For the best results, please consider using a GNU/Linux server instead." : "فضلاً ضع في الاعتبار استخدام نظام GNU/Linux بدل الأنظمة الأخرى للحصول على أفضل النتائج.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "يبدو أن كائن %s يعمل على بيئة PHP 32-Bit وكذلك تم تكوين open_basedir في ملف php.ini. يؤدي ذلك إلى مشاكل مع الملفات التي يزيد حجمها عن 4 غيغابايت ولا يُنصح بذلك بشدة.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "فضلاً إحذف إعداد open_basedir من ملف php.ini لديك أو حوّل إلى PHP إصدار 64 بت.", @@ -149,7 +168,6 @@ OC.L10N.register( "Sharing backend %s not found" : "لم يتم العثور على الواجهة الخلفية (Sharing backend) %s", "Sharing backend for %s not found" : "مشاركة الخلفية لـ %s غير موجود", "%1$s shared %2$s with you" : "قام%1$s بمشاركة %2$s معك", - "Click the button below to open it." : "اضغط على الزر الذي تحته ليتم فتحه.", "Open %s" : "إفتَح %s", "%1$s via %2$s" : "%1$s عبر %2$s", "%1$s shared %2$s with you and wants to add:" : "قام %1$s بمشاركة %2$s معك، وهو يرغب في إضافة:", @@ -169,6 +187,7 @@ OC.L10N.register( "You cannot share your root folder" : "لا يمكنك مشاركة مجلدك الجذر", "You are not allowed to share %s" : "أنت غير مسموح لك أن تشارك %s", "Valid permissions are required for sharing" : "المشاركة تلزمها أذونات صالحة", + "File shares cannot have create or delete permissions" : "لا يمكن لمشاركات الملفات أن يكون لها أذونات الإنشاء أو الحذف", "Cannot increase permissions of %s" : "لا يمكن زيادة أذونات %s", "Shares need at least read permissions" : "المشاركات تتطلب في الحد الأدنى إذناً بالقراءة", "Files cannot be shared with delete permissions" : "لا يمكن مشاركة ملفات بأذونات حذفٍ", @@ -183,7 +202,6 @@ OC.L10N.register( "Path is already shared with this group" : "المسار تمّت مشاركته سلفاً مع هذه المجموعة", "Link sharing is not allowed" : "المشاركة عبر الروابط غير مسموحة", "Public upload is not allowed" : "الرفع من قِبَل العموم غير مسموح به", - "Path contains files shared with you" : "يحتوي المسار على ملفات تمّت مشاركتها معك", "Sharing is disabled" : "المشاركة معطلة", "Sharing is disabled for you" : "المشاركة معطلة بالنسبة لك", "Cannot share with the share owner" : "لا يمكنك المشاركة مع مالك المشاركة", @@ -311,7 +329,6 @@ OC.L10N.register( "The audio to transcribe" : "الكلام المطلوب تحويله إلى نص", "Transcription" : "تحويل الكلام لنص", "The transcribed text" : "النص المُولّد من الكلام", - "ContextAgent" : "وكيل السياق ContextAgent", "Chat with an agent" : "الدردشة مع وكيل", "Chat message" : "رسالة دردشة", "A chat message to send to the agent." : "رسالة دردشة لتُرسل إلى الوكيل.", @@ -384,6 +401,12 @@ OC.L10N.register( "Original text" : "النص الأصلي", "The original text to generate a headline for" : "النص الأصلي المطلوب توليد عنوانٍ له", "The generated headline" : "العنوان الذي تم توليده", + "Proofread" : "مراجعة", + "Proofreads a text and lists corrections" : "يراجع نصاً و يعرض التصحيحات", + "Text" : "نص", + "The text to proofread" : "النص المطلوب مراجعته", + "Corrections" : "التصحيحات", + "The corrections that should be made in your text" : "التصحيحات المطلوبة في نصك", "Reformulate text" : "إعادة صياغة النص", "Takes a text and reformulates it" : "تأخذ النص و تضفي عليه طابعاً رسميّاً", "Write a text that you want the assistant to reformulate" : "أكتُب النص الذي ترغب من المساعد أن يعيد صياغته", @@ -419,41 +442,8 @@ OC.L10N.register( "Generate headline" : "توليد العنوان", "Summarizes text by reducing its length without losing key information." : "يُلَخِّص النص بتقليل طوله دون فقدان المعنى.", "Extracts topics from a text and outputs them separated by commas." : "يستخلص المواضيع من النص و إخراجها مفصولة بفواصل.", - "Education Edition" : "الإصدار التعليمي", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "المستخدم المسجل دخوله يجب أن يكون مدير admin، أو مدير فرعي sub admin، أو يحمل صلاحياتٍ خاصّةٍ للوصول إلى هذه الإعدادات.", - "Logged in user must be an admin or sub admin" : "المستخدم المسجل دخوله يجب أن يكون مدير admin، أو مدير فرعي sub", - "Logged in user must be an admin" : "المستخدم المسجل دخوله يجب أن يكون مدير admin.", - "File name is a reserved word" : "اسم الملف كلمة محجوزة", - "File name contains at least one invalid character" : "اسم الملف به ، على الأقل ، حرف غير صالح", - "File name is too long" : "اسم الملف طويل جداً", - "Help" : "المساعدة", - "Users" : "المستخدمين", - "Unknown user" : "المستخدم مجهول", - "Enter the database username and name for %s" : "أدخل اسم المستخدم و اسم قاعدة البيانات %s", - "Enter the database username for %s" : "أدخل اسم المستخدم لقاعدة البيانات لـ %s", - "MySQL username and/or password not valid" : "اسم المستخدم لقاعدة البيانات MySQL و/أو كلمة المرور غير صحيحة", - "Oracle username and/or password not valid" : "اسم المستخدم و/أو كلمة المرور لنظام Oracle غير صحيح", - "PostgreSQL username and/or password not valid" : "اسم المستخدم / أو كلمة المرور الخاصة بـPostgreSQL غير صحيحة", - "Set an admin username." : "اعداد اسم مستخدم المدير", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s شارك »%2$s« معك و يرغب في إضافة:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s شارك »%2$s« معك و يرغب في إضافة", - "»%s« added a note to a file shared with you" : "»%s« أضاف ملاحظة لملفٍ سلفت مشاركته معك", - "Open »%s«" : "فتح »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "المشاركة %sلم تتم لأن هذا العنصر سبقت مشاركته سلفاً مع المستخدم %s", - "%1$s shared »%2$s« with you" : "%1$s شارك »%2$s« معك", - "%1$s shared »%2$s« with you." : "%1$s شَارَكَ »%2$s« معك.", - "The username is already being used" : "اسم المستخدم قيد الاستخدام بالفعل", - "Could not create user" : "لا يمكن إنشاء المستخدم", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "الحروف التالية فقط مسموحٌ بها في اسم المستخدِم: \"a-z\"و \"A-Z\"و \"0-9\" و الفراغ و \"_.@-'\"", - "A valid username must be provided" : "يجب ادخال اسم مستخدم صحيح", - "Username contains whitespace at the beginning or at the end" : "إنّ اسم المستخدم يحتوي على مسافة بيضاء سواءا في البداية أو النهاية", - "Username must not consist of dots only" : "اسم المستخدم يجب ألاّ يتكون من نقاطٍ dots فقط", - "Username is invalid because files already exist for this user" : "اسم المستخدم غير صحيحٍ لأن هنالك ملفات موجودة سلفاً لهذا المستخدم", - "User disabled" : "تم تعطيل المستخدم", + "Organisation" : "مؤسسة", "File is currently busy, please try again later" : "إنّ الملف مشغول الآمن، يرجى إعادة المحاولة لاحقًا", - "Cannot download file" : "لا يمكن تنزيل الملف", - "Your data directory is readable by other users." : "دليل بياناتك data directory يُمكن قراءته من مستخدمين آخرين.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "الرجاء تغيير الصلاحيات إلى 0770 حتى لا يتمكن المستخدمون الآخرون من عرض محتويات المجلد.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "تأكد من وجود ملفٍ باسم \".ocdata\" في جذر دليل البيانات data directory." + "Cannot download file" : "لا يمكن تنزيل الملف" }, "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"); diff --git a/lib/l10n/ar.json b/lib/l10n/ar.json index 50f91bd2943..6e8159db0e0 100644 --- a/lib/l10n/ar.json +++ b/lib/l10n/ar.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "مطلوب إصدار الخادم %s أو أعلى.", "Server version %s or lower is required." : "مطلوب إصدار الخادم %s أو أقل.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "الحساب المسجل دخوله يجب أن يكون حساب مدير أو مدير فرعي أو يملك حقاً خاصاً للوصول إلى هذا الإعداد", - "Your current IP address doesn’t allow you to perform admin actions" : "عنوانك الحالي IP يمنعك من أداء مهام المدير", + "Your current IP address doesn't allow you to perform admin actions" : "عنوان IP الحالي لايسمح لك بتنفيذ إجراءات الإدارة", "Logged in account must be an admin or sub admin" : "الحساب المسجل دخوله يجب أن يكون حساب مدير أو مدير فرعي", "Logged in account must be an admin" : "الحساب المسجل دخوله يجب أن يكون حساب مدير", "Wiping of device %s has started" : "بدأ مسح الجهاز %s ", @@ -57,6 +57,11 @@ "Avatar image is not square" : "الصورة الرمزية ليست على شكل مربّع", "Files" : "الملفات", "View profile" : "عرض الملف الشخصي", + "same time" : "نفس التوقيت", + "_%nh_::_%nh_" : ["%n ساعة","%n ساعة","%n ساعة","%n ساعة","%n ساعة","%n ساعة"], + "_%nm_::_%nm_" : ["%nد","%nد","%nد","%nد","%nد","%nد"], + "%s ahead" : "%s مُتقَدِّم", + "%s behind" : "%s مُتأَخِّر", "Local time: %s" : "الوقت المحلّي: %s", "today" : "اليوم", "tomorrow" : "يوم غد", @@ -79,7 +84,14 @@ "seconds ago" : "منذ ثوانٍ", "Empty file" : "ملفٌ فارغٌ", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "الوحدة module ذات الرقم ID ـ : %s غير موجودة. رجاءً، فعّلها في إعدادات التطبيقات لديك، أو اتصل بمسؤول النظام.", + "No file conversion providers available" : "لا يوجد أي مُزوِّد لتحويل الملفات", + "File is too large to convert" : "الملف كبير جداً فلايمكن تحويله", + "Destination does not match conversion extension" : "المَقصِد لايتطابق مع امتداد التحويل", + "Could not convert file" : "لايمكن تحويل الملف", + "Destination does not exist" : "المَقصِد غير موجود", + "Destination is not creatable" : "المِقصِد لايمكن إنشاؤه", "Dot files are not allowed" : "الملفات النقطية (ملفات ذات أسماء تبدأ بنقطة) غير مسموح بها", + "renamed file" : "ملف معاد تسميته", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" غير مسموح به أن يكون اسم ملف أو مجلد.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" غير مسموح به أن يكون بادئة لاسم ملف أو مجلد.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" غير مسموح به أن يكون داخل اسم ملف أو مجلد.", @@ -90,6 +102,13 @@ "Invalid path" : "مسار غير صالح !", "Failed to create file from template" : "تعذّر إنشاء ملفٍ من قالبٍ", "Templates" : "القوالب", + "Storage %s cannot be moved" : "وحدة التخزين %s لايمكن نقلها", + "Moving a share (%s) into a shared folder is not allowed" : "نقل مشاركة (%s) في مجلد مشترك غير ممكن", + "Moving a storage (%s) into a shared folder is not allowed" : "نقل وحدة تخزين (%s) في مجلد مشترك غير ممكن", + "Moving a share (%s) into another share (%s) is not allowed" : "نقل مشاركة (%s) في مشاركة أخرى (%s) غير ممكن", + "Moving a share (%s) into another storage (%s) is not allowed" : "نقل مشاركة (%s) لوحدة تخزين أخرى (%s) غير ممكن", + "Moving a storage (%s) into a share (%s) is not allowed" : "نقل وحدة تخزين (%s) في مشاركة (%s) غير ممكن", + "Moving a storage (%s) into another storage (%s) is not allowed" : "نقل وحدة تخزين (%s) في وحدة تخزين أخرى (%s) غير ممكن", "Path contains invalid segments" : "يحتوي المسار على أجزاء غير صحيحة", "Filename is a reserved word" : "اسم الملف غير مقبوله لأنه كلمة محجوزة", "Filename contains at least one invalid character" : "اسم الملف به على الأقل حرفٌ غير صالح", @@ -122,7 +141,7 @@ "About" : "عن", "Display name" : "اسم العرض", "Headline" : "عنوان ", - "Organisation" : "مؤسسة", + "Organization" : "المنظمة", "Role" : "الوظيفة", "Pronouns" : "الضمائر", "Unknown account" : "حساب غير معروف", @@ -136,7 +155,7 @@ "Oracle connection could not be established" : "لم تنجح محاولة اتصال Oracle", "Oracle Login and/or password not valid" : "مُعرف تسجيل الدخول او كلمة مرور Oracle غير صحيحة", "PostgreSQL Login and/or password not valid" : "مُعرف تسجيل دخول او كلمة مرور PostgreSQL غير صحيحة", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "نظام ماك العاشر غير مدعوم و %s .لن يعمل بالشكل الصحيح على هذه المنصةاستعمله يكون على مسؤوليتك!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "\"Mac OS X\" غير مدعوم؛ و %s سوف لن يعمل بالشكل الصحيح على هذه المنصة. استعمله على مسؤوليتك!", "For the best results, please consider using a GNU/Linux server instead." : "فضلاً ضع في الاعتبار استخدام نظام GNU/Linux بدل الأنظمة الأخرى للحصول على أفضل النتائج.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "يبدو أن كائن %s يعمل على بيئة PHP 32-Bit وكذلك تم تكوين open_basedir في ملف php.ini. يؤدي ذلك إلى مشاكل مع الملفات التي يزيد حجمها عن 4 غيغابايت ولا يُنصح بذلك بشدة.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "فضلاً إحذف إعداد open_basedir من ملف php.ini لديك أو حوّل إلى PHP إصدار 64 بت.", @@ -147,7 +166,6 @@ "Sharing backend %s not found" : "لم يتم العثور على الواجهة الخلفية (Sharing backend) %s", "Sharing backend for %s not found" : "مشاركة الخلفية لـ %s غير موجود", "%1$s shared %2$s with you" : "قام%1$s بمشاركة %2$s معك", - "Click the button below to open it." : "اضغط على الزر الذي تحته ليتم فتحه.", "Open %s" : "إفتَح %s", "%1$s via %2$s" : "%1$s عبر %2$s", "%1$s shared %2$s with you and wants to add:" : "قام %1$s بمشاركة %2$s معك، وهو يرغب في إضافة:", @@ -167,6 +185,7 @@ "You cannot share your root folder" : "لا يمكنك مشاركة مجلدك الجذر", "You are not allowed to share %s" : "أنت غير مسموح لك أن تشارك %s", "Valid permissions are required for sharing" : "المشاركة تلزمها أذونات صالحة", + "File shares cannot have create or delete permissions" : "لا يمكن لمشاركات الملفات أن يكون لها أذونات الإنشاء أو الحذف", "Cannot increase permissions of %s" : "لا يمكن زيادة أذونات %s", "Shares need at least read permissions" : "المشاركات تتطلب في الحد الأدنى إذناً بالقراءة", "Files cannot be shared with delete permissions" : "لا يمكن مشاركة ملفات بأذونات حذفٍ", @@ -181,7 +200,6 @@ "Path is already shared with this group" : "المسار تمّت مشاركته سلفاً مع هذه المجموعة", "Link sharing is not allowed" : "المشاركة عبر الروابط غير مسموحة", "Public upload is not allowed" : "الرفع من قِبَل العموم غير مسموح به", - "Path contains files shared with you" : "يحتوي المسار على ملفات تمّت مشاركتها معك", "Sharing is disabled" : "المشاركة معطلة", "Sharing is disabled for you" : "المشاركة معطلة بالنسبة لك", "Cannot share with the share owner" : "لا يمكنك المشاركة مع مالك المشاركة", @@ -309,7 +327,6 @@ "The audio to transcribe" : "الكلام المطلوب تحويله إلى نص", "Transcription" : "تحويل الكلام لنص", "The transcribed text" : "النص المُولّد من الكلام", - "ContextAgent" : "وكيل السياق ContextAgent", "Chat with an agent" : "الدردشة مع وكيل", "Chat message" : "رسالة دردشة", "A chat message to send to the agent." : "رسالة دردشة لتُرسل إلى الوكيل.", @@ -382,6 +399,12 @@ "Original text" : "النص الأصلي", "The original text to generate a headline for" : "النص الأصلي المطلوب توليد عنوانٍ له", "The generated headline" : "العنوان الذي تم توليده", + "Proofread" : "مراجعة", + "Proofreads a text and lists corrections" : "يراجع نصاً و يعرض التصحيحات", + "Text" : "نص", + "The text to proofread" : "النص المطلوب مراجعته", + "Corrections" : "التصحيحات", + "The corrections that should be made in your text" : "التصحيحات المطلوبة في نصك", "Reformulate text" : "إعادة صياغة النص", "Takes a text and reformulates it" : "تأخذ النص و تضفي عليه طابعاً رسميّاً", "Write a text that you want the assistant to reformulate" : "أكتُب النص الذي ترغب من المساعد أن يعيد صياغته", @@ -417,41 +440,8 @@ "Generate headline" : "توليد العنوان", "Summarizes text by reducing its length without losing key information." : "يُلَخِّص النص بتقليل طوله دون فقدان المعنى.", "Extracts topics from a text and outputs them separated by commas." : "يستخلص المواضيع من النص و إخراجها مفصولة بفواصل.", - "Education Edition" : "الإصدار التعليمي", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "المستخدم المسجل دخوله يجب أن يكون مدير admin، أو مدير فرعي sub admin، أو يحمل صلاحياتٍ خاصّةٍ للوصول إلى هذه الإعدادات.", - "Logged in user must be an admin or sub admin" : "المستخدم المسجل دخوله يجب أن يكون مدير admin، أو مدير فرعي sub", - "Logged in user must be an admin" : "المستخدم المسجل دخوله يجب أن يكون مدير admin.", - "File name is a reserved word" : "اسم الملف كلمة محجوزة", - "File name contains at least one invalid character" : "اسم الملف به ، على الأقل ، حرف غير صالح", - "File name is too long" : "اسم الملف طويل جداً", - "Help" : "المساعدة", - "Users" : "المستخدمين", - "Unknown user" : "المستخدم مجهول", - "Enter the database username and name for %s" : "أدخل اسم المستخدم و اسم قاعدة البيانات %s", - "Enter the database username for %s" : "أدخل اسم المستخدم لقاعدة البيانات لـ %s", - "MySQL username and/or password not valid" : "اسم المستخدم لقاعدة البيانات MySQL و/أو كلمة المرور غير صحيحة", - "Oracle username and/or password not valid" : "اسم المستخدم و/أو كلمة المرور لنظام Oracle غير صحيح", - "PostgreSQL username and/or password not valid" : "اسم المستخدم / أو كلمة المرور الخاصة بـPostgreSQL غير صحيحة", - "Set an admin username." : "اعداد اسم مستخدم المدير", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s شارك »%2$s« معك و يرغب في إضافة:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s شارك »%2$s« معك و يرغب في إضافة", - "»%s« added a note to a file shared with you" : "»%s« أضاف ملاحظة لملفٍ سلفت مشاركته معك", - "Open »%s«" : "فتح »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "المشاركة %sلم تتم لأن هذا العنصر سبقت مشاركته سلفاً مع المستخدم %s", - "%1$s shared »%2$s« with you" : "%1$s شارك »%2$s« معك", - "%1$s shared »%2$s« with you." : "%1$s شَارَكَ »%2$s« معك.", - "The username is already being used" : "اسم المستخدم قيد الاستخدام بالفعل", - "Could not create user" : "لا يمكن إنشاء المستخدم", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "الحروف التالية فقط مسموحٌ بها في اسم المستخدِم: \"a-z\"و \"A-Z\"و \"0-9\" و الفراغ و \"_.@-'\"", - "A valid username must be provided" : "يجب ادخال اسم مستخدم صحيح", - "Username contains whitespace at the beginning or at the end" : "إنّ اسم المستخدم يحتوي على مسافة بيضاء سواءا في البداية أو النهاية", - "Username must not consist of dots only" : "اسم المستخدم يجب ألاّ يتكون من نقاطٍ dots فقط", - "Username is invalid because files already exist for this user" : "اسم المستخدم غير صحيحٍ لأن هنالك ملفات موجودة سلفاً لهذا المستخدم", - "User disabled" : "تم تعطيل المستخدم", + "Organisation" : "مؤسسة", "File is currently busy, please try again later" : "إنّ الملف مشغول الآمن، يرجى إعادة المحاولة لاحقًا", - "Cannot download file" : "لا يمكن تنزيل الملف", - "Your data directory is readable by other users." : "دليل بياناتك data directory يُمكن قراءته من مستخدمين آخرين.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "الرجاء تغيير الصلاحيات إلى 0770 حتى لا يتمكن المستخدمون الآخرون من عرض محتويات المجلد.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "تأكد من وجود ملفٍ باسم \".ocdata\" في جذر دليل البيانات data directory." + "Cannot download file" : "لا يمكن تنزيل الملف" },"pluralForm" :"nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;" }
\ No newline at end of file diff --git a/lib/l10n/ast.js b/lib/l10n/ast.js index 284b54dacf6..dd231743133 100644 --- a/lib/l10n/ast.js +++ b/lib/l10n/ast.js @@ -113,7 +113,7 @@ OC.L10N.register( "About" : "Tocante a", "Display name" : "Nome visible", "Headline" : "Titular", - "Organisation" : "Organización", + "Organization" : "Organización", "Role" : "Rol", "Unknown account" : "Cuenta desconocida", "Additional settings" : "Configuración adicional", @@ -126,7 +126,6 @@ OC.L10N.register( "Oracle connection could not be established" : "Nun se pudo configurar la conexón d'Oracle", "Oracle Login and/or password not valid" : "La cuenta y/o contraseña d'Oracle nun ye válida", "PostgreSQL Login and/or password not valid" : "La cuenta y/o contraseña de PostgreSQL nun ye válida", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nun ye compatible y %s nun va funcionar afayadizamente nesta plataforma. ¡Úsalu baxo'l to riegu!", "For the best results, please consider using a GNU/Linux server instead." : "Pa consiguir los meyores resultaos, usa un sirvidor de GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Paez qu'esta instancia de Nextcloud «%s» execútase sobre un entornu PHP de 32 bits y la opción open_basedir ta configurada en php.ini. Esto va orixinar problemes con ficheros superiores a 4GB y ye mui desaconseyable.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Quita la opción «open_basedir» de php.ini o cambia a PHP de 64 bits.", @@ -136,7 +135,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend de compartición «%s» ha implmentar la interfaz OCP\\Share_Backend", "Sharing backend %s not found" : "Nun s'atopó'l backend de compartición «%s»", "Sharing backend for %s not found" : "Nun s'atopó'l backend de compartición pa: %s", - "Click the button below to open it." : "Calca nel botón p'abrilo.", "%1$s via %2$s" : "%1$s per %2$s", "Unknown share type" : "Tipu de compartición desconocida", "You are not allowed to share %s" : "Nun tienes permisu pa compartir «%s»", @@ -205,6 +203,7 @@ OC.L10N.register( "Source material" : "Material d'orixe", "Generate image" : "Xenerar una imaxe", "Chat" : "Charra", + "Text" : "Testu", "Summarize" : "Resume", "Summary" : "Resume", "Extract topics" : "Estrayer temes", @@ -213,37 +212,6 @@ OC.L10N.register( "Result" : "Resultáu", "Summarizes text by reducing its length without losing key information." : "Resume'l testu amenorgando la so llongura ensin perder la información importante.", "Extracts topics from a text and outputs them separated by commas." : "Estrái temes d'un testu y devuélvelos separtaos per comes.", - "Education Edition" : "Edición educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "L'usuariu que tien la sesión aniciada ha ser d'alministración, un sodominiu o tener un permisu especial p'acceder a esta opción", - "Logged in user must be an admin or sub admin" : "L'usuariu que tien la sesión aniciada ha ser d'alministración o un sodominiu", - "Logged in user must be an admin" : "L'usuariu que tien la sesión aniciada ha ser d'alministración", - "File name is a reserved word" : "El nome de ficheru ye una pallabra acutada", - "File name contains at least one invalid character" : "El nome del ficheru contién polo menos un caráuter inváldu", - "File name is too long" : "El nome del ficheru ye mui llongu", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Usuariu desconocíu", - "Enter the database username and name for %s" : "Introduz el nome d'usuariu y el nome de la base de datos pa: %s", - "Enter the database username for %s" : "Introduz el nome d'usuariu de la base de datos pa: %s", - "MySQL username and/or password not valid" : "El nome d'usuariu y/o la contraseña de MySQL son inválidos", - "Oracle username and/or password not valid" : "El nome d'usuariu y/o la contraseña d'Oracle son inválidos", - "PostgreSQL username and/or password not valid" : "El nome d'usuariu y/o la contraseña de PostgreSQL son inválidos", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartío «%2$s» contigo y quier amestar:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartío «%2$s» contigo y quier amestar", - "»%s« added a note to a file shared with you" : "«%s» amestó una nota a un ficheru compartío contigo", - "Open »%s«" : "Abrir «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "La compartición de «%s» falló porque esti elementu yá ta compartíu col usuariu «%s»", - "%1$s shared »%2$s« with you" : "%1$s compartió «%2$s» contigo", - "%1$s shared »%2$s« with you." : "%1$s compartió «%2$s» contigo.", - "The username is already being used" : "El nome d'usuariu yá ta n'usu", - "Could not create user" : "Nun se pudo crear l'usuariu", - "A valid username must be provided" : "Ha fornise un nome d'usuariu válidu", - "Username contains whitespace at the beginning or at the end" : "El nome d'usuariu contién un espaciu nel comienzu o al final", - "Username must not consist of dots only" : "El nome d'usuariu nun ha tar formáu namás por puntos", - "Username is invalid because files already exist for this user" : "El nome d'usuariu ye inválidu porque yá esisten los ficheros pa esti ficheru", - "User disabled" : "L'usuariu ta desactiváu", - "Your data directory is readable by other users." : "Los demás usuarios puen lleer el to direutoriu de datos.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Camuda los permisos a 0770 y, polo tanto, los demás usuarios nun puen llistar el direutoriu.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegúrate de que'l ficheru llamáu «.ocdata» ta nel raigañu del direutoriu de datos." + "Organisation" : "Organización" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/ast.json b/lib/l10n/ast.json index 3fac48c9adc..af17b01f83c 100644 --- a/lib/l10n/ast.json +++ b/lib/l10n/ast.json @@ -111,7 +111,7 @@ "About" : "Tocante a", "Display name" : "Nome visible", "Headline" : "Titular", - "Organisation" : "Organización", + "Organization" : "Organización", "Role" : "Rol", "Unknown account" : "Cuenta desconocida", "Additional settings" : "Configuración adicional", @@ -124,7 +124,6 @@ "Oracle connection could not be established" : "Nun se pudo configurar la conexón d'Oracle", "Oracle Login and/or password not valid" : "La cuenta y/o contraseña d'Oracle nun ye válida", "PostgreSQL Login and/or password not valid" : "La cuenta y/o contraseña de PostgreSQL nun ye válida", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nun ye compatible y %s nun va funcionar afayadizamente nesta plataforma. ¡Úsalu baxo'l to riegu!", "For the best results, please consider using a GNU/Linux server instead." : "Pa consiguir los meyores resultaos, usa un sirvidor de GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Paez qu'esta instancia de Nextcloud «%s» execútase sobre un entornu PHP de 32 bits y la opción open_basedir ta configurada en php.ini. Esto va orixinar problemes con ficheros superiores a 4GB y ye mui desaconseyable.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Quita la opción «open_basedir» de php.ini o cambia a PHP de 64 bits.", @@ -134,7 +133,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend de compartición «%s» ha implmentar la interfaz OCP\\Share_Backend", "Sharing backend %s not found" : "Nun s'atopó'l backend de compartición «%s»", "Sharing backend for %s not found" : "Nun s'atopó'l backend de compartición pa: %s", - "Click the button below to open it." : "Calca nel botón p'abrilo.", "%1$s via %2$s" : "%1$s per %2$s", "Unknown share type" : "Tipu de compartición desconocida", "You are not allowed to share %s" : "Nun tienes permisu pa compartir «%s»", @@ -203,6 +201,7 @@ "Source material" : "Material d'orixe", "Generate image" : "Xenerar una imaxe", "Chat" : "Charra", + "Text" : "Testu", "Summarize" : "Resume", "Summary" : "Resume", "Extract topics" : "Estrayer temes", @@ -211,37 +210,6 @@ "Result" : "Resultáu", "Summarizes text by reducing its length without losing key information." : "Resume'l testu amenorgando la so llongura ensin perder la información importante.", "Extracts topics from a text and outputs them separated by commas." : "Estrái temes d'un testu y devuélvelos separtaos per comes.", - "Education Edition" : "Edición educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "L'usuariu que tien la sesión aniciada ha ser d'alministración, un sodominiu o tener un permisu especial p'acceder a esta opción", - "Logged in user must be an admin or sub admin" : "L'usuariu que tien la sesión aniciada ha ser d'alministración o un sodominiu", - "Logged in user must be an admin" : "L'usuariu que tien la sesión aniciada ha ser d'alministración", - "File name is a reserved word" : "El nome de ficheru ye una pallabra acutada", - "File name contains at least one invalid character" : "El nome del ficheru contién polo menos un caráuter inváldu", - "File name is too long" : "El nome del ficheru ye mui llongu", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Usuariu desconocíu", - "Enter the database username and name for %s" : "Introduz el nome d'usuariu y el nome de la base de datos pa: %s", - "Enter the database username for %s" : "Introduz el nome d'usuariu de la base de datos pa: %s", - "MySQL username and/or password not valid" : "El nome d'usuariu y/o la contraseña de MySQL son inválidos", - "Oracle username and/or password not valid" : "El nome d'usuariu y/o la contraseña d'Oracle son inválidos", - "PostgreSQL username and/or password not valid" : "El nome d'usuariu y/o la contraseña de PostgreSQL son inválidos", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartío «%2$s» contigo y quier amestar:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartío «%2$s» contigo y quier amestar", - "»%s« added a note to a file shared with you" : "«%s» amestó una nota a un ficheru compartío contigo", - "Open »%s«" : "Abrir «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "La compartición de «%s» falló porque esti elementu yá ta compartíu col usuariu «%s»", - "%1$s shared »%2$s« with you" : "%1$s compartió «%2$s» contigo", - "%1$s shared »%2$s« with you." : "%1$s compartió «%2$s» contigo.", - "The username is already being used" : "El nome d'usuariu yá ta n'usu", - "Could not create user" : "Nun se pudo crear l'usuariu", - "A valid username must be provided" : "Ha fornise un nome d'usuariu válidu", - "Username contains whitespace at the beginning or at the end" : "El nome d'usuariu contién un espaciu nel comienzu o al final", - "Username must not consist of dots only" : "El nome d'usuariu nun ha tar formáu namás por puntos", - "Username is invalid because files already exist for this user" : "El nome d'usuariu ye inválidu porque yá esisten los ficheros pa esti ficheru", - "User disabled" : "L'usuariu ta desactiváu", - "Your data directory is readable by other users." : "Los demás usuarios puen lleer el to direutoriu de datos.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Camuda los permisos a 0770 y, polo tanto, los demás usuarios nun puen llistar el direutoriu.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegúrate de que'l ficheru llamáu «.ocdata» ta nel raigañu del direutoriu de datos." + "Organisation" : "Organización" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/az.js b/lib/l10n/az.js index 35dda74c32a..ee9fc7b6387 100644 --- a/lib/l10n/az.js +++ b/lib/l10n/az.js @@ -65,12 +65,6 @@ OC.L10N.register( "Authentication error" : "Təyinat metodikası", "Token expired. Please reload page." : "Token vaxtı bitib. Xahiş olunur səhifəni yenidən yükləyəsiniz.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Bu ola bilər ki, cache/accelerator such tərəfindən cağırılıb hansi ki, Zend OPcache və eAccelerator-da olduğu kimidir.", - "Summary" : "Xülasə", - "Help" : "Kömək", - "Users" : "İstifadəçilər", - "Unknown user" : "Istifadəçi tanınmır ", - "Oracle username and/or password not valid" : "Oracle istifadəçi adı və/ya şifrəsi düzgün deyil", - "Set an admin username." : "İnzibatçı istifadəçi adını təyin et.", - "A valid username must be provided" : "Düzgün istifadəçi adı daxil edilməlidir" + "Summary" : "Xülasə" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/az.json b/lib/l10n/az.json index e01e65b635d..75d1c258247 100644 --- a/lib/l10n/az.json +++ b/lib/l10n/az.json @@ -63,12 +63,6 @@ "Authentication error" : "Təyinat metodikası", "Token expired. Please reload page." : "Token vaxtı bitib. Xahiş olunur səhifəni yenidən yükləyəsiniz.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Bu ola bilər ki, cache/accelerator such tərəfindən cağırılıb hansi ki, Zend OPcache və eAccelerator-da olduğu kimidir.", - "Summary" : "Xülasə", - "Help" : "Kömək", - "Users" : "İstifadəçilər", - "Unknown user" : "Istifadəçi tanınmır ", - "Oracle username and/or password not valid" : "Oracle istifadəçi adı və/ya şifrəsi düzgün deyil", - "Set an admin username." : "İnzibatçı istifadəçi adını təyin et.", - "A valid username must be provided" : "Düzgün istifadəçi adı daxil edilməlidir" + "Summary" : "Xülasə" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/be.js b/lib/l10n/be.js index b2b419bd53e..c09f9f65f7e 100644 --- a/lib/l10n/be.js +++ b/lib/l10n/be.js @@ -30,7 +30,6 @@ OC.L10N.register( "September" : "Верасень", "October" : "Кастрычнік", "November" : "Лістапад", - "December" : "Снежань", - "Help" : "Help" + "December" : "Снежань" }, "nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"); diff --git a/lib/l10n/be.json b/lib/l10n/be.json index 4ef66a740bb..7693febd0b3 100644 --- a/lib/l10n/be.json +++ b/lib/l10n/be.json @@ -28,7 +28,6 @@ "September" : "Верасень", "October" : "Кастрычнік", "November" : "Лістапад", - "December" : "Снежань", - "Help" : "Help" + "December" : "Снежань" },"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);" }
\ No newline at end of file diff --git a/lib/l10n/bg.js b/lib/l10n/bg.js index c32e7cbb023..6c753c9041d 100644 --- a/lib/l10n/bg.js +++ b/lib/l10n/bg.js @@ -52,6 +52,7 @@ OC.L10N.register( "Avatar image is not square" : "Изображението на аватара не е квадратно", "Files" : "Файлове", "View profile" : "Преглед на профил", + "_%nh_::_%nh_" : ["%nч","%nч"], "Local time: %s" : "Местно време: %s", "today" : "днес", "tomorrow" : "утре", @@ -91,6 +92,7 @@ OC.L10N.register( "Administration settings" : "Административни настройки", "Settings" : "Настройки", "Log out" : "Отписване", + "Accounts" : "Профили", "Email" : "Имейл", "Mail %s" : "Поща %s", "Fediverse" : "Fediverse /съвкупност от обединени сървъри/", @@ -102,18 +104,18 @@ OC.L10N.register( "Website" : "Уеб сайт", "Visit %s" : "Посещение %s", "Address" : "Адрес", - "Profile picture" : "Снимка на профила", + "Profile picture" : "Профилна снимка", "About" : "Относно", "Display name" : "Име за визуализация", "Headline" : "Заглавие", - "Organisation" : "Организация", + "Organization" : "Организиране", "Role" : "Роля", + "Pronouns" : "Обръщение", "Additional settings" : "Допълнителни настройки", "Enter the database name for %s" : "Въведете името на базата данни за %s", "You cannot use dots in the database name %s" : "Не можете да използвате точки в името на базата данни %s", "You need to enter details of an existing account." : "Трябва да въведете подробности за съществуващ профил.", "Oracle connection could not be established" : "Не можа да се установи връзка с Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не се подържа и %s няма да работи правилно на тази платформа. Използвайте го на свой собствен риск!", "For the best results, please consider using a GNU/Linux server instead." : "За най-добри резултати, моля, помисли дали не бихте желали да използваште GNU/Linux сървър.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : " Изглежда, че този екземпляр %s работи в 32-битова PHP среда и open_basedir е конфигуриран в php.ini. Това ще доведе до проблеми с файлове над 4 GB и е силно обезкуражено.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Моля, премахтене настройката за open_basedir от вашия php.ini или преминете към 64-битово PHP.", @@ -122,7 +124,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Споделянето на сървърния %s трябва да поддържа OCP\\Share_Backend интерфейс.", "Sharing backend %s not found" : "Споделянето на сървърния %s не е открито.", "Sharing backend for %s not found" : "Споделянето на сървъра за %s не е открито.", - "Click the button below to open it." : "Щракнете върху бутона по-долу, за да го отворите.", "%1$s via %2$s" : "%1$s чрез %2$s", "Unknown share type" : "Неизвестен тип споделяне", "You are not allowed to share %s" : "Не ти е разрешено да споделяш %s.", @@ -197,8 +198,8 @@ OC.L10N.register( "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Това обикновено може да бъде оправено като, се даде достъп на уеб сървъра да записва в основната директория. Погледнете %s", "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Права обикновено могат да бъдат оправени когато се даде достъп на уеб сървъра да пише в основната директория. Погледнете %s.", "Your data directory is not writable." : "Вашата директория с данни не е записваема.", - "Setting locale to %s failed." : "Неуспешно задаване на езикова променлива %s.", - "Please install one of these locales on your system and restart your web server." : "Моля, инсталирайте една от тези езикови променливи на вашата система и си рестартирайте уеб сървъра.", + "Setting locale to %s failed." : "Неуспешно задаване на регион %s. ", + "Please install one of these locales on your system and restart your web server." : "Моля, задайте един от следните региони във Вашата система след което рестартирайте сървъра.", "PHP module %s not installed." : "PHP модулът %s не е инсталиран.", "Please ask your server administrator to install the module." : "Моля, помолете вашия администратор да инсталира модула.", "PHP setting \"%s\" is not set to \"%s\"." : "PHP настройка \"%s\" не е зададена на \"%s\".", @@ -227,45 +228,13 @@ OC.L10N.register( "Storage connection timeout. %s" : "Време за изчакване при свързването с хранилище. %s", "Confirmation" : "Потвърждение", "Prompt" : "Подкана", + "Text" : "Текст", "Summary" : "Резюме", "Translate" : "Превод", "Target language" : "Целеви език", "Result" : "Резултат", - "Education Edition" : "Образователно издание", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Влезлият потребител трябва да е администратор, подадминистратор или да е получил специално право за достъп до тази настройка", - "Logged in user must be an admin or sub admin" : "Влезлият потребител трябва да е администратор или подадминистратор ", - "Logged in user must be an admin" : "Влезлият потребител трябва да е администратор", - "File name is a reserved word" : "Името на файла е запазена дума", - "File name contains at least one invalid character" : "Името на файла съдържа поне един невалиден символ", - "File name is too long" : "Името на файла е твърде дълго", - "Help" : "Помощ", - "Users" : "Потребители", - "Unknown user" : "Непознат потребител", - "Enter the database username and name for %s" : "Въведете името на потребител на базата данни и име за %s", - "Enter the database username for %s" : "Въведете името на потребител на базата данни за %s", - "MySQL username and/or password not valid" : "Име на потребител и/или паролата на MySQL не са валидни", - "Oracle username and/or password not valid" : "Невалидно Oracle потребителско име и/или парола.", - "PostgreSQL username and/or password not valid" : "Невалидно PostgreSQL потребителско име и/или парола.", - "Set an admin username." : "Задайте потребителско име за администратор.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s сподели »%2$s« с вас и иска да добави:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s сподели »%2$s« с вас и иска да добави", - "»%s« added a note to a file shared with you" : "»%s« добави бележка към файл, споделен с вас ", - "Open »%s«" : "Отвори »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Неуспешно споделяне на %s, защото този елемент вече е споделен с потребителя %s", - "%1$s shared »%2$s« with you" : "%1$s сподели »%2$s« с вас", - "%1$s shared »%2$s« with you." : "%1$s сподели »%2$s« с вас.", - "The username is already being used" : "Потребителското име е вече заето.", - "Could not create user" : "Неуспешно създаване на потребител", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Потребителските имена може да съдържат само следните знаци: \"a-z\", \"A-Z\", \"0-9\" и \"_.@-'\"", - "A valid username must be provided" : "Трябва да въведете валидно потребителско.", - "Username contains whitespace at the beginning or at the end" : "Потребителското име започва или завършва с интервал.", - "Username must not consist of dots only" : "Името на потребител не трябва да се състои само от точки", - "Username is invalid because files already exist for this user" : "Името на потребител е невалидно, тъй като файловете вече съществуват за този потребител", - "User disabled" : "Потребителят е деактивиран", + "Organisation" : "Организация", "File is currently busy, please try again later" : "Файлът в момента е зает, моля, опитайте отново по-късно", - "Cannot download file" : "Файлът не можа да бъде изтеглен", - "Your data directory is readable by other users." : "Вашата директория с данни може да се чете от други потребители.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Моля, променете правата за достъп на 0770, за да не може директорията да бъде видяна от други потребители.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Уверете се, че има файл, наречен \".ocdata\" в корена на директорията с данни." + "Cannot download file" : "Файлът не можа да бъде изтеглен" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/bg.json b/lib/l10n/bg.json index a7b5f6c0fe9..b08945b3c91 100644 --- a/lib/l10n/bg.json +++ b/lib/l10n/bg.json @@ -50,6 +50,7 @@ "Avatar image is not square" : "Изображението на аватара не е квадратно", "Files" : "Файлове", "View profile" : "Преглед на профил", + "_%nh_::_%nh_" : ["%nч","%nч"], "Local time: %s" : "Местно време: %s", "today" : "днес", "tomorrow" : "утре", @@ -89,6 +90,7 @@ "Administration settings" : "Административни настройки", "Settings" : "Настройки", "Log out" : "Отписване", + "Accounts" : "Профили", "Email" : "Имейл", "Mail %s" : "Поща %s", "Fediverse" : "Fediverse /съвкупност от обединени сървъри/", @@ -100,18 +102,18 @@ "Website" : "Уеб сайт", "Visit %s" : "Посещение %s", "Address" : "Адрес", - "Profile picture" : "Снимка на профила", + "Profile picture" : "Профилна снимка", "About" : "Относно", "Display name" : "Име за визуализация", "Headline" : "Заглавие", - "Organisation" : "Организация", + "Organization" : "Организиране", "Role" : "Роля", + "Pronouns" : "Обръщение", "Additional settings" : "Допълнителни настройки", "Enter the database name for %s" : "Въведете името на базата данни за %s", "You cannot use dots in the database name %s" : "Не можете да използвате точки в името на базата данни %s", "You need to enter details of an existing account." : "Трябва да въведете подробности за съществуващ профил.", "Oracle connection could not be established" : "Не можа да се установи връзка с Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не се подържа и %s няма да работи правилно на тази платформа. Използвайте го на свой собствен риск!", "For the best results, please consider using a GNU/Linux server instead." : "За най-добри резултати, моля, помисли дали не бихте желали да използваште GNU/Linux сървър.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : " Изглежда, че този екземпляр %s работи в 32-битова PHP среда и open_basedir е конфигуриран в php.ini. Това ще доведе до проблеми с файлове над 4 GB и е силно обезкуражено.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Моля, премахтене настройката за open_basedir от вашия php.ini или преминете към 64-битово PHP.", @@ -120,7 +122,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Споделянето на сървърния %s трябва да поддържа OCP\\Share_Backend интерфейс.", "Sharing backend %s not found" : "Споделянето на сървърния %s не е открито.", "Sharing backend for %s not found" : "Споделянето на сървъра за %s не е открито.", - "Click the button below to open it." : "Щракнете върху бутона по-долу, за да го отворите.", "%1$s via %2$s" : "%1$s чрез %2$s", "Unknown share type" : "Неизвестен тип споделяне", "You are not allowed to share %s" : "Не ти е разрешено да споделяш %s.", @@ -195,8 +196,8 @@ "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Това обикновено може да бъде оправено като, се даде достъп на уеб сървъра да записва в основната директория. Погледнете %s", "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Права обикновено могат да бъдат оправени когато се даде достъп на уеб сървъра да пише в основната директория. Погледнете %s.", "Your data directory is not writable." : "Вашата директория с данни не е записваема.", - "Setting locale to %s failed." : "Неуспешно задаване на езикова променлива %s.", - "Please install one of these locales on your system and restart your web server." : "Моля, инсталирайте една от тези езикови променливи на вашата система и си рестартирайте уеб сървъра.", + "Setting locale to %s failed." : "Неуспешно задаване на регион %s. ", + "Please install one of these locales on your system and restart your web server." : "Моля, задайте един от следните региони във Вашата система след което рестартирайте сървъра.", "PHP module %s not installed." : "PHP модулът %s не е инсталиран.", "Please ask your server administrator to install the module." : "Моля, помолете вашия администратор да инсталира модула.", "PHP setting \"%s\" is not set to \"%s\"." : "PHP настройка \"%s\" не е зададена на \"%s\".", @@ -225,45 +226,13 @@ "Storage connection timeout. %s" : "Време за изчакване при свързването с хранилище. %s", "Confirmation" : "Потвърждение", "Prompt" : "Подкана", + "Text" : "Текст", "Summary" : "Резюме", "Translate" : "Превод", "Target language" : "Целеви език", "Result" : "Резултат", - "Education Edition" : "Образователно издание", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Влезлият потребител трябва да е администратор, подадминистратор или да е получил специално право за достъп до тази настройка", - "Logged in user must be an admin or sub admin" : "Влезлият потребител трябва да е администратор или подадминистратор ", - "Logged in user must be an admin" : "Влезлият потребител трябва да е администратор", - "File name is a reserved word" : "Името на файла е запазена дума", - "File name contains at least one invalid character" : "Името на файла съдържа поне един невалиден символ", - "File name is too long" : "Името на файла е твърде дълго", - "Help" : "Помощ", - "Users" : "Потребители", - "Unknown user" : "Непознат потребител", - "Enter the database username and name for %s" : "Въведете името на потребител на базата данни и име за %s", - "Enter the database username for %s" : "Въведете името на потребител на базата данни за %s", - "MySQL username and/or password not valid" : "Име на потребител и/или паролата на MySQL не са валидни", - "Oracle username and/or password not valid" : "Невалидно Oracle потребителско име и/или парола.", - "PostgreSQL username and/or password not valid" : "Невалидно PostgreSQL потребителско име и/или парола.", - "Set an admin username." : "Задайте потребителско име за администратор.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s сподели »%2$s« с вас и иска да добави:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s сподели »%2$s« с вас и иска да добави", - "»%s« added a note to a file shared with you" : "»%s« добави бележка към файл, споделен с вас ", - "Open »%s«" : "Отвори »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Неуспешно споделяне на %s, защото този елемент вече е споделен с потребителя %s", - "%1$s shared »%2$s« with you" : "%1$s сподели »%2$s« с вас", - "%1$s shared »%2$s« with you." : "%1$s сподели »%2$s« с вас.", - "The username is already being used" : "Потребителското име е вече заето.", - "Could not create user" : "Неуспешно създаване на потребител", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Потребителските имена може да съдържат само следните знаци: \"a-z\", \"A-Z\", \"0-9\" и \"_.@-'\"", - "A valid username must be provided" : "Трябва да въведете валидно потребителско.", - "Username contains whitespace at the beginning or at the end" : "Потребителското име започва или завършва с интервал.", - "Username must not consist of dots only" : "Името на потребител не трябва да се състои само от точки", - "Username is invalid because files already exist for this user" : "Името на потребител е невалидно, тъй като файловете вече съществуват за този потребител", - "User disabled" : "Потребителят е деактивиран", + "Organisation" : "Организация", "File is currently busy, please try again later" : "Файлът в момента е зает, моля, опитайте отново по-късно", - "Cannot download file" : "Файлът не можа да бъде изтеглен", - "Your data directory is readable by other users." : "Вашата директория с данни може да се чете от други потребители.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Моля, променете правата за достъп на 0770, за да не може директорията да бъде видяна от други потребители.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Уверете се, че има файл, наречен \".ocdata\" в корена на директорията с данни." + "Cannot download file" : "Файлът не можа да бъде изтеглен" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/bn_BD.js b/lib/l10n/bn_BD.js index d8e0abc24b8..6f845de9c0d 100644 --- a/lib/l10n/bn_BD.js +++ b/lib/l10n/bn_BD.js @@ -62,9 +62,6 @@ OC.L10N.register( "Dec." : "ডিসে.", "Application is not enabled" : "অ্যাপ্লিকেসনটি সক্রিয় নয়", "Authentication error" : "অনুমোদন ঘটিত সমস্যা", - "Token expired. Please reload page." : "টোকেন মেয়াদোত্তীর্ণ। দয়া করে পৃষ্ঠাটি পূনরায় লোড করুন।", - "Help" : "সহায়িকা", - "Users" : "ব্যবহারকারী", - "Unknown user" : "অপরিচিত ব্যবহারকারী" + "Token expired. Please reload page." : "টোকেন মেয়াদোত্তীর্ণ। দয়া করে পৃষ্ঠাটি পূনরায় লোড করুন।" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/bn_BD.json b/lib/l10n/bn_BD.json index 4ff445c1df1..e94d9262761 100644 --- a/lib/l10n/bn_BD.json +++ b/lib/l10n/bn_BD.json @@ -60,9 +60,6 @@ "Dec." : "ডিসে.", "Application is not enabled" : "অ্যাপ্লিকেসনটি সক্রিয় নয়", "Authentication error" : "অনুমোদন ঘটিত সমস্যা", - "Token expired. Please reload page." : "টোকেন মেয়াদোত্তীর্ণ। দয়া করে পৃষ্ঠাটি পূনরায় লোড করুন।", - "Help" : "সহায়িকা", - "Users" : "ব্যবহারকারী", - "Unknown user" : "অপরিচিত ব্যবহারকারী" + "Token expired. Please reload page." : "টোকেন মেয়াদোত্তীর্ণ। দয়া করে পৃষ্ঠাটি পূনরায় লোড করুন।" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/br.js b/lib/l10n/br.js index 101317604e6..79c6e326bb6 100644 --- a/lib/l10n/br.js +++ b/lib/l10n/br.js @@ -10,7 +10,9 @@ OC.L10N.register( "Unknown filetype" : "N'eo ket anavezet stumm an teuliad", "Invalid image" : "N'eo ket aotreet ar skeudenn", "Files" : "Restroù", + "View profile" : "Gwelet ar profil", "today" : "hiziv", + "tomorrow" : "arc'hoazh", "yesterday" : "dec'h", "_%n day ago_::_%n days ago_" : ["%n deiz zo","%n deiz zo","%n deiz zo","%n deiz zo","%n deiz zo"], "last month" : "ar miz tremenet", @@ -26,20 +28,44 @@ OC.L10N.register( "__language_name__" : "Brezhoneg", "Apps" : "Meziant", "Settings" : "Arventennoù", - "Log out" : "Kuitat", + "Log out" : "Digennaskañ", "Accounts" : "Kontoù", "Email" : "Postel", "Twitter" : "Twitter", - "Website" : "Lec'hien web", + "Website" : "Lec'hienn web", "Address" : "Chom-lec'h", - "Profile picture" : "Skeudenn trolinenn", + "Profile picture" : "Skeudenn brofil", "About" : "Diwar-benn", "Display name" : "Anv ardivink", "Role" : "Roll", "Additional settings" : "Stummoù ouzhpenn", "Set an admin password." : "Lakaat ur ger-tremenn merour.", "Sharing backend for %s not found" : "Rannadenn backend evit %s n'eo ket bet kavet", + "Sunday" : "Sul", "Monday" : "Lun", + "Wednesday" : "Merc'her", + "Friday" : "Gwener", + "Mon." : "Lun", + "Fri." : "Gwe.", + "Sat." : "Sad.", + "January" : "Genver", + "February" : "C'hwevrer", + "March" : "Meurzh", + "April" : "Ebrel", + "May" : "Mae", + "June" : "Even", + "July" : "Gouere", + "August" : "Eost", + "September" : "Gwengolo", + "October" : "Here", + "November" : "Du", + "December" : "Kerdu", + "Feb." : "C'hw.", + "May." : "Mae.", + "Jun." : "Even", + "Aug." : "Eost", + "Nov." : "Du", + "Dec." : "Ker.", "Login canceled by app" : "Mont tre arrestet gant ar meziant", "Application is not enabled" : "N'eo ket aotreet ar meziant", "Authentication error" : "Fazi dilesa", @@ -47,16 +73,9 @@ OC.L10N.register( "PHP module %s not installed." : "Modul %s PHPn n'eo ket staliet.", "Storage connection error. %s" : "Fazi renkañ kenstag. %s", "Storage is temporarily not available" : "N'haller ket tizhout ar skor roadennoù evit ar poent", + "Text" : "Testenn", "Summary" : "Diverrañ", "Translate" : "Treiñ", - "File name contains at least one invalid character" : "Un arouez fall ez eus d'an neubeutañ en anv restr", - "File name is too long" : "Anv ar restr a zo re hir", - "Help" : "Skoazell", - "Users" : "Implijer", - "Unknown user" : "Implijer dianv", - "Set an admin username." : "Lakaat un anv-impljer merour.", - "Open »%s«" : "Digeriñ »%s«", - "The username is already being used" : "An anv-implijet a zo dija implijet", - "User disabled" : "Implijer disaotreet" + "Origin text" : "Testenn orin" }, "nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);"); diff --git a/lib/l10n/br.json b/lib/l10n/br.json index 16f414e164a..c250f436eeb 100644 --- a/lib/l10n/br.json +++ b/lib/l10n/br.json @@ -8,7 +8,9 @@ "Unknown filetype" : "N'eo ket anavezet stumm an teuliad", "Invalid image" : "N'eo ket aotreet ar skeudenn", "Files" : "Restroù", + "View profile" : "Gwelet ar profil", "today" : "hiziv", + "tomorrow" : "arc'hoazh", "yesterday" : "dec'h", "_%n day ago_::_%n days ago_" : ["%n deiz zo","%n deiz zo","%n deiz zo","%n deiz zo","%n deiz zo"], "last month" : "ar miz tremenet", @@ -24,20 +26,44 @@ "__language_name__" : "Brezhoneg", "Apps" : "Meziant", "Settings" : "Arventennoù", - "Log out" : "Kuitat", + "Log out" : "Digennaskañ", "Accounts" : "Kontoù", "Email" : "Postel", "Twitter" : "Twitter", - "Website" : "Lec'hien web", + "Website" : "Lec'hienn web", "Address" : "Chom-lec'h", - "Profile picture" : "Skeudenn trolinenn", + "Profile picture" : "Skeudenn brofil", "About" : "Diwar-benn", "Display name" : "Anv ardivink", "Role" : "Roll", "Additional settings" : "Stummoù ouzhpenn", "Set an admin password." : "Lakaat ur ger-tremenn merour.", "Sharing backend for %s not found" : "Rannadenn backend evit %s n'eo ket bet kavet", + "Sunday" : "Sul", "Monday" : "Lun", + "Wednesday" : "Merc'her", + "Friday" : "Gwener", + "Mon." : "Lun", + "Fri." : "Gwe.", + "Sat." : "Sad.", + "January" : "Genver", + "February" : "C'hwevrer", + "March" : "Meurzh", + "April" : "Ebrel", + "May" : "Mae", + "June" : "Even", + "July" : "Gouere", + "August" : "Eost", + "September" : "Gwengolo", + "October" : "Here", + "November" : "Du", + "December" : "Kerdu", + "Feb." : "C'hw.", + "May." : "Mae.", + "Jun." : "Even", + "Aug." : "Eost", + "Nov." : "Du", + "Dec." : "Ker.", "Login canceled by app" : "Mont tre arrestet gant ar meziant", "Application is not enabled" : "N'eo ket aotreet ar meziant", "Authentication error" : "Fazi dilesa", @@ -45,16 +71,9 @@ "PHP module %s not installed." : "Modul %s PHPn n'eo ket staliet.", "Storage connection error. %s" : "Fazi renkañ kenstag. %s", "Storage is temporarily not available" : "N'haller ket tizhout ar skor roadennoù evit ar poent", + "Text" : "Testenn", "Summary" : "Diverrañ", "Translate" : "Treiñ", - "File name contains at least one invalid character" : "Un arouez fall ez eus d'an neubeutañ en anv restr", - "File name is too long" : "Anv ar restr a zo re hir", - "Help" : "Skoazell", - "Users" : "Implijer", - "Unknown user" : "Implijer dianv", - "Set an admin username." : "Lakaat un anv-impljer merour.", - "Open »%s«" : "Digeriñ »%s«", - "The username is already being used" : "An anv-implijet a zo dija implijet", - "User disabled" : "Implijer disaotreet" + "Origin text" : "Testenn orin" },"pluralForm" :"nplurals=5; plural=((n%10 == 1) && (n%100 != 11) && (n%100 !=71) && (n%100 !=91) ? 0 :(n%10 == 2) && (n%100 != 12) && (n%100 !=72) && (n%100 !=92) ? 1 :(n%10 ==3 || n%10==4 || n%10==9) && (n%100 < 10 || n% 100 > 19) && (n%100 < 70 || n%100 > 79) && (n%100 < 90 || n%100 > 99) ? 2 :(n != 0 && n % 1000000 == 0) ? 3 : 4);" }
\ No newline at end of file diff --git a/lib/l10n/bs.js b/lib/l10n/bs.js index 4aaf400bdd3..e813de70a76 100644 --- a/lib/l10n/bs.js +++ b/lib/l10n/bs.js @@ -13,7 +13,6 @@ OC.L10N.register( "Website" : "Web-prezentacija", "Address" : "Adresa", "Profile picture" : "Slika profila", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nije podržan i %s na ovoj platformi neće raditi kako treba. Korištenje na vlastiti rizik!", "For the best results, please consider using a GNU/Linux server instead." : "Umjesto toga, za najbolje rezultate, molimo razmislite o mogućnosti korištenje GNU/Linux servera.", "Sunday" : "Nedjelja", "Monday" : "Ponedjeljak", @@ -55,9 +54,6 @@ OC.L10N.register( "Dec." : "Dec.", "A valid password must be provided" : "Nužno je navesti valjanu lozinku", "Authentication error" : "Grešna autentifikacije", - "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Uzrok tome je vjerojatno neki ubrzivač predmemorisanja kao što je Zend OPcache ili eAccelerator.", - "Help" : "Pomoć", - "Users" : "Korisnici", - "A valid username must be provided" : "Nužno je navesti valjano korisničko ime" + "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Uzrok tome je vjerojatno neki ubrzivač predmemorisanja kao što je Zend OPcache ili eAccelerator." }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/lib/l10n/bs.json b/lib/l10n/bs.json index 3352a6e0776..d1b0b8f341e 100644 --- a/lib/l10n/bs.json +++ b/lib/l10n/bs.json @@ -11,7 +11,6 @@ "Website" : "Web-prezentacija", "Address" : "Adresa", "Profile picture" : "Slika profila", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nije podržan i %s na ovoj platformi neće raditi kako treba. Korištenje na vlastiti rizik!", "For the best results, please consider using a GNU/Linux server instead." : "Umjesto toga, za najbolje rezultate, molimo razmislite o mogućnosti korištenje GNU/Linux servera.", "Sunday" : "Nedjelja", "Monday" : "Ponedjeljak", @@ -53,9 +52,6 @@ "Dec." : "Dec.", "A valid password must be provided" : "Nužno je navesti valjanu lozinku", "Authentication error" : "Grešna autentifikacije", - "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Uzrok tome je vjerojatno neki ubrzivač predmemorisanja kao što je Zend OPcache ili eAccelerator.", - "Help" : "Pomoć", - "Users" : "Korisnici", - "A valid username must be provided" : "Nužno je navesti valjano korisničko ime" + "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Uzrok tome je vjerojatno neki ubrzivač predmemorisanja kao što je Zend OPcache ili eAccelerator." },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }
\ No newline at end of file diff --git a/lib/l10n/ca.js b/lib/l10n/ca.js index 09b1435925a..cb4e6d1c3ad 100644 --- a/lib/l10n/ca.js +++ b/lib/l10n/ca.js @@ -1,9 +1,9 @@ OC.L10N.register( "lib", { - "Cannot write into \"config\" directory!" : "No es pot escriure en la carpeta «config»!", + "Cannot write into \"config\" directory!" : "No es pot escriure en la carpeta \"config\"!", "This can usually be fixed by giving the web server write access to the config directory." : "Això normalment es pot solucionar donant al servidor web accés d'escriptura a la carpeta de configuració.", - "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "O bé, si preferiu mantenir el fitxer config.php només de lectura, establir l'opció «config_is_read_only» com a «true».", + "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "O bé, si preferiu mantenir el fitxer config.php només de lectura, establir l'opció \"config_is_read_only\" com a cert.", "See %s" : "Consulteu %s", "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Falta l'aplicació %1$s o té una versió no compatible amb aquest servidor. Comproveu la carpeta d'aplicacions.", "Sample configuration detected" : "S'ha detectat una configuració d'exemple", @@ -19,6 +19,7 @@ OC.L10N.register( "%1$s, %2$s and %3$s" : "%1$s, %2$s i %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s i %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s i %5$s", + "Education bundle" : "Paquet d'educació", "Enterprise bundle" : "Paquet empresarial", "Groupware bundle" : "Paquet de treball en grup", "Hub bundle" : "Paquet Hub", @@ -42,7 +43,7 @@ OC.L10N.register( "Wiping of device %s has started" : "S'ha començat a esborrar el dispositiu %s", "Wiping of device »%s« has started" : "S'ha començat a esborrar el dispositiu «%s»", "»%s« started remote wipe" : "«%s» ha començat a esborrar dades en remot", - "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "El dispositiu o aplicació «%s» ha començat a esborrar les dades en remot. Rebreu un altre correu quan s'enllesteixi el procés.", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "El dispositiu o aplicació »%s« ha començat a esborrar les dades en remot. Rebreu un altre correu quan s'enllesteixi el procés", "Wiping of device %s has finished" : "S'ha acabat d'esborrar el dispositiu %s", "Wiping of device »%s« has finished" : "S'ha acabat d'esborrar el dispositiu «%s»", "»%s« finished remote wipe" : "«%s» ha acabat d'esborrar dades en remot", @@ -57,6 +58,11 @@ OC.L10N.register( "Avatar image is not square" : "La imatge de l'avatar no és quadrada", "Files" : "Fitxers", "View profile" : "Visualitza el perfil", + "same time" : "mateix temps", + "_%nh_::_%nh_" : ["%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s endavant", + "%s behind" : "%s darrere", "Local time: %s" : "Hora local: %s", "today" : "avui", "tomorrow" : "demà", @@ -79,12 +85,34 @@ OC.L10N.register( "seconds ago" : "fa uns segons", "Empty file" : "Fitxer buit", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "El mòdul amb l'ID %s no existeix. Habiliteu-lo els paràmetres de les aplicacions o contacteu amb l'administrador.", + "No file conversion providers available" : "No hi ha proveïdors de conversió de fitxers disponibles", + "File is too large to convert" : "El fitxer és massa gran per convertir-lo", + "Destination does not match conversion extension" : "La destinació no coincideix amb l'extensió de conversió", + "Could not convert file" : "No s'ha pogut convertir el fitxer", + "Destination does not exist" : "La destinació no existeix", + "Destination is not creatable" : "La destinació no es pot crear", "Dot files are not allowed" : "No es permeten els fitxers que comencen per un punt", + "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" és un nom de fitxer o carpeta prohibit.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" és un prefix prohibit per als noms de fitxers o carpetes.", + "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" no es permet dins d'un nom de fitxer o carpeta.", + "\"%1$s\" is a forbidden file type." : "\"%1$s\" és un tipus de fitxer prohibit.", + "Filenames must not end with \"%1$s\"." : "Els noms de fitxer no han d'acabar amb \"%1$s\".", + "Invalid parent path" : "El camí principal no és vàlid", "File already exists" : "El fitxer ja existeix", "Invalid path" : "El camí no és vàlid", "Failed to create file from template" : "No s'ha pogut crear el fitxer a partir de la plantilla", "Templates" : "Plantilles", + "Storage %s cannot be moved" : "L'emmagatzematge %s no es pot moure", + "Moving a share (%s) into a shared folder is not allowed" : "No és permès moure una compartició (%s) a una carpeta compartida", + "Moving a storage (%s) into a shared folder is not allowed" : "No és permès moure un emmagatzematge (%s) a una carpeta compartida", + "Moving a share (%s) into another share (%s) is not allowed" : "No és permès moure una compartició (%s) a una altra compartició (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "No és permès moure una compartició (%s) a un altre emmagatzematge (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "No és permès moure un emmagatzematge (%s) a una compartició (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "No és permès moure un emmagatzematge (%s) a un altre emmagatzematge (%s)", + "Path contains invalid segments" : "El camí conté segments no vàlids", + "Filename is a reserved word" : "El nom del fitxer és una paraula reservada", "Filename contains at least one invalid character" : "El nom del fitxer conté com a mínim un caràcter no vàlid", + "Filename is too long" : "El nom del fitxer és massa llarg", "Empty filename is not allowed" : "No es permeten els noms de fitxers buits", "App \"%s\" cannot be installed because appinfo file cannot be read." : "L'aplicació «%s» no es pot instal·lar perquè no es pot llegir el fitxer appinfo.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "L'aplicació «%s» no es pot instal·lar perquè no és compatible amb aquesta versió del servidor.", @@ -113,8 +141,8 @@ OC.L10N.register( "About" : "Quant a", "Display name" : "Nom de visualització", "Headline" : "Capçalera", - "Organisation" : "Organització", "Role" : "Càrrec", + "Pronouns" : "Pronoms", "Unknown account" : "Compte desconegut", "Additional settings" : "Paràmetres addicionals", "Enter the database Login and name for %s" : "Introduïu l'inici de sessió i el nom de la base de dades per a %s", @@ -126,7 +154,6 @@ OC.L10N.register( "Oracle connection could not be established" : "No s'ha pogut establir la connexió amb Oracle", "Oracle Login and/or password not valid" : "L'inici de sessió o la contrasenya d'Oracle no són vàlids", "PostgreSQL Login and/or password not valid" : "L'inici de sessió o la contrasenya del PostgreSQL no són vàlids", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "El Mac OS X no s'admet i el %s no funcionarà correctament en aquesta plataforma. Utilitzeu-lo sota el vostre propi risc! ", "For the best results, please consider using a GNU/Linux server instead." : "Per a obtenir els millors resultats, considereu la possibilitat d'utilitzar un servidor amb GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Sembla que aquesta instància del %s s'està executant en un entorn del PHP de 32 bits i que s'ha configurat open_basedir en el fitxer php.ini. Això comportarà problemes amb els fitxers de més de 4 GB i és molt poc recomanable.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Suprimiu el paràmetre open_basedir del fitxer php.ini o canvieu al PHP de 64 bits.", @@ -136,21 +163,60 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El rerefons d'ús compartit %s ha d'implementar la interfície OCP\\Share_Backend", "Sharing backend %s not found" : "No s'ha trobat el rerefons d'ús compartit %s", "Sharing backend for %s not found" : "No s'ha trobat el rerefons d'ús compartit per a %s", - "Click the button below to open it." : "Feu clic en el botó següent per a obrir-ho.", + "%1$s shared %2$s with you" : "%1$s ha compartit %2$s amb tu", + "Open %s" : "Obre %s", "%1$s via %2$s" : "%1$s mitjançant %2$s", - "Unknown share type" : "Tipus d'element compartit desconegut", + "%1$s shared %2$s with you and wants to add:" : "%1$s ha compartit %2$s amb tu i vol afegir:", + "%1$s shared %2$s with you and wants to add" : "%1$s ha compartit %2$s amb tu i vol afegir", + "%s added a note to a file shared with you" : "%s ha afegit una nota a un fitxer compartit amb tu", + "Passwords are enforced for link and mail shares" : "S'apliquen contrasenyes per compartició d'enllaços i correus", + "Share recipient is not a valid user" : "El destinatari de la compartició no és un usuari vàlid", + "Share recipient is not a valid group" : "El destinatari de la compartició no és un grup vàlid", + "Share recipient should be empty" : "El destinatari de la compartició ha d'estar buit", + "Share recipient should not be empty" : "El destinatari de la compartició no ha d'estar buit", + "Share recipient is not a valid circle" : "El destinatari de la compartició no és un cercle vàlid", + "Unknown share type" : "Tipus de compartició desconegut", + "Share initiator must be set" : "S'ha d'establir l'iniciador de la compartició", + "Cannot share with yourself" : "No es pot compartir amb tu mateix", + "Shared path must be set" : "S'ha d'establir un camí compartit", + "Shared path must be either a file or a folder" : "El camí compartit ha de ser un fitxer o una carpeta", + "You cannot share your root folder" : "No podeu compartir la vostra carpeta arrel", "You are not allowed to share %s" : "No podeu compartir %s", + "Valid permissions are required for sharing" : "Es requereixen permisos vàlids per compartir", + "File shares cannot have create or delete permissions" : "Les comparticions de fitxers no poden tenir permisos de creació o supressió", "Cannot increase permissions of %s" : "No es poden augmentar els permisos de %s", + "Shares need at least read permissions" : "Les comparticions almenys necessiten permisos de lectura", "Files cannot be shared with delete permissions" : "No es poden compartir fitxers amb permisos de supressió", "Files cannot be shared with create permissions" : "No es poden compartir fitxers amb permisos de creació", "Expiration date is in the past" : "La data de caducitat ja ha passat", + "Expiration date is enforced" : "S'aplica la data de caducitat", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["No es pot establir la data de caducitat més d'%n dia en el futur","No es pot establir la data de caducitat més de %n dies en el futur"], "Sharing is only allowed with group members" : "Només es permet l'ús compartit amb membres del grup", "Sharing %s failed, because this item is already shared with the account %s" : "No s'ha pogut compartir %s perquè l'element ja està compartit amb el compte %s", + "Group sharing is now allowed" : "Ara es permet compartir en grup", + "Sharing is only allowed within your own groups" : "La compartició només és permesa dins dels vostres propis grups", + "Path is already shared with this group" : "El camí ja està compartit amb aquest grup", + "Link sharing is not allowed" : "La compartició d'enllaços no és permesa", + "Public upload is not allowed" : "La pujada pública no és permesa", + "Sharing is disabled" : "S’ha desactivat la compartició", + "Sharing is disabled for you" : "La compartició està desactivada per a tu", + "Cannot share with the share owner" : "No es pot compartir amb el propietari de la compartició", + "Share does not have a full ID" : "La compartició no té un ID complet", + "Cannot change share type" : "No es pot canviar el tipus de compartició", + "Can only update recipient on user shares" : "Només es pot actualitzar el destinatari en les comparticions d'usuaris", + "Cannot enable sending the password by Talk with an empty password" : "No es pot habilitar l'enviament de la contrasenya per Converses amb una contrasenya buida", + "Cannot enable sending the password by Talk without setting a new password" : "No es pot activar l'enviament de la contrasenya per Converses sense establir una nova contrasenya", + "Cannot disable sending the password by Talk without setting a new password" : "No es pot desactivar l'enviament de la contrasenya per Converses sense establir una nova contrasenya", + "Share provider does not support accepting" : "El proveïdor de la compartició no admet l'acceptació", + "Cannot change target of link share" : "No es pot canviar el destí de l'enllaç de compartició", + "Invalid share recipient" : "El destinatari de la compartició no és vàlid", + "Group \"%s\" does not exist" : "El grup \"%s\" no existeix", "The requested share does not exist anymore" : "L'element compartit sol·licitat ja no existeix", "The requested share comes from a disabled user" : "L'element compartit sol·licitat prové d'un usuari inhabilitat", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "No s'ha creat l'usuari perquè s'ha assolit el límit d'usuaris. Consulteu les notificacions per a obtenir més informació.", "Could not find category \"%s\"" : "No s'ha trobat la categoria «%s»", + "Input text" : "Text d'entrada", + "The input text" : "El text d'entrada", "Sunday" : "Diumenge", "Monday" : "Dilluns", "Tuesday" : "Dimarts", @@ -207,7 +273,7 @@ OC.L10N.register( "Account disabled" : "El compte està inhabilitat", "Login canceled by app" : "L'aplicació ha cancel·lat l'inici de sessió", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "L'aplicació «%1$s» no es pot instal·lar perquè no es compleixen les dependències següents: %2$s", - "a safe home for all your data" : "Un lloc segur per a totes les vostres dades", + "a safe home for all your data" : "un lloc segur per a totes les vostres dades", "Application is not enabled" : "L'aplicació no està habilitada", "Authentication error" : "Error d'autenticació", "Token expired. Please reload page." : "El testimoni ha caducat. Torneu a carregar la pàgina.", @@ -240,6 +306,7 @@ OC.L10N.register( "Your data directory must be an absolute path." : "La carpeta de dades ha de ser un camí absolut.", "Check the value of \"datadirectory\" in your configuration." : "Comproveu el valor de «datadirectory» en la configuració.", "Your data directory is invalid." : "La carpeta de dades no és vàlida.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Assegureu-vos que hi hagi un fitxer anomenat \"%1$s\" a l'arrel del directori de dades. Hauria de tenir el contingut: \"%2$s\"", "Action \"%s\" not supported or implemented." : "L'acció «%s» no està admesa o implementada.", "Authentication failed, wrong token or provider ID given" : "No s'ha pogut autenticar; s'ha proporcionat un testimoni o un ID de proveïdor incorrecte", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Falten paràmetres per a completar la sol·licitud. Els paràmetres que falten són: «%s»", @@ -251,54 +318,128 @@ OC.L10N.register( "Storage connection error. %s" : "S'ha produït un error de connexió amb l'emmagatzematge. %s", "Storage is temporarily not available" : "L'emmagatzematge no està disponible temporalment", "Storage connection timeout. %s" : "S'ha superat el temps d'espera de la connexió d'emmagatzematge. %s", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Per permetre que aquesta comprovació s'executi, heu d'assegurar-vos que el vostre servidor web es pot connectar a si mateix. Per tant, ha de ser capaç de resoldre i connectar-se a almenys un dels seus `trusted_domains` o `overwrite.cli.url`. Aquest error pot ser el resultat d'una manca de concordança de DNS del servidor o d'una regla de tallafoc de sortida.", + "Transcribe audio" : "Transcripció d'àudio", + "Transcribe the things said in an audio" : "Transcriu les coses dites en un àudio", + "Audio input" : "Entrada d'àudio", + "The audio to transcribe" : "L'àudio a transcriure", + "Transcription" : "Transcripció", + "The transcribed text" : "El text transcrit", + "Chat with an agent" : "Xat amb un agent", + "Chat message" : "Missatge de xat", + "A chat message to send to the agent." : "Un missatge de xat per enviar a l'agent.", "Confirmation" : "Confirmació", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Si confirmar les accions sol·licitades anteriorment: 0 per a la denegació i 1 per a la confirmació.", + "Conversation token" : "Testimoni de conversa", + "A token representing the conversation." : "Un testimoni que representa la conversa.", + "Generated response" : "Resposta generada", + "The response from the chat model." : "La resposta del model de xat.", + "The new conversation token" : "El nou testimoni de conversa", + "Send this along with the next interaction." : "Envieu-ho juntament amb la següent interacció.", + "Requested actions by the agent" : "Accions sol·licitades per l'agent", + "Actions that the agent would like to carry out in JSON format." : "Accions que l'agent vol dur a terme en format JSON.", + "Context write" : "Escriptura de context", + "Writes text in a given style based on the provided source material." : "Escriu text en un estil determinat basant-se en el material font proporcionat.", + "Writing style" : "Estil d'escriptura", + "Demonstrate a writing style that you would like to immitate" : "Demostra un estil d'escriptura que t'agradaria imitar", + "Source material" : "Material d'origen", + "The content that would like to be rewritten in the new writing style" : "El contingut que voldria ser reescrit amb el nou estil d'escriptura", + "Generated text" : "Text generat", + "The generated text with content from the source material in the given style" : "El text generat amb contingut del material d'origen en l'estil donat", + "Emoji generator" : "Generador d'emojis", + "Takes text and generates a representative emoji for it." : "Pren text i genera un emoji representatiu.", + "The text to generate an emoji for" : "El text per a generar un emoji", + "Generated emoji" : "Emoji generat", + "The generated emoji based on the input text" : "L'emoji generat a partir del text d'entrada", + "Generate image" : "Generar imatge", + "Generate an image from a text prompt" : "Genereu una imatge a partir d'una sol·licitud de text", + "Prompt" : "Indicador", + "Describe the image you want to generate" : "Descriu la imatge que vols generar", + "Number of images" : "Nombre d'imatges", + "How many images to generate" : "Quantes imatges generar", + "Output images" : "Imatges de sortida", + "The generated images" : "Les imatges generades", + "Free text to text prompt" : "Text lliure per indicador de text", + "Runs an arbitrary prompt through a language model that returns a reply" : "Executa una indicació arbitraria mitjançant un model de llengua que retorna una resposta", + "Describe a task that you want the assistant to do or ask a question" : "Descriu una tasca que vols que faci l'assistent o fes una pregunta", + "Generated reply" : "Resposta generada", + "The generated text from the assistant" : "El text generat per l'assistent", + "Change Tone" : "Canvia el to", + "Change the tone of a piece of text." : "Canvia el to d'un fragment de text.", + "Write a text that you want the assistant to rewrite in another tone." : "Escriu un text que vols que l'assistent torni a escriure en un altre to.", + "Desired tone" : "To desitjat", + "In which tone should your text be rewritten?" : "En quin to s'ha de reescriure el teu text?", + "The rewritten text in the desired tone, written by the assistant:" : "El text reescrit en el to desitjat, escrit per l'assistent:", + "Chat" : "Xat", + "Chat with the assistant" : "Xat amb l'assistent", + "System prompt" : "Indicador del sistema", + "Define rules and assumptions that the assistant should follow during the conversation." : "Definir regles i supòsits que l'assistent ha de seguir durant la conversa.", + "Chat history" : "Historial de xat", + "The history of chat messages before the current message, starting with a message by the user" : "L'historial dels missatges de xat abans del missatge actual, començant amb un missatge de l'usuari", + "Response message" : "Missatge de resposta", + "The generated response as part of the conversation" : "La resposta generada com a part de la conversa", + "Chat with tools" : "Xat amb eines", + "Chat with the language model with tool calling support." : "Xat amb el model de llengua amb suport de crida d'eines.", + "Tool message" : "Missatge de l'eina", + "The result of tool calls in the last interaction" : "El resultat de les crides d'eines en l'última interacció", + "Available tools" : "Eines disponibles", + "The available tools in JSON format" : "Les eines disponibles en format JSON", + "The response from the chat model" : "La resposta del model de xat", + "Tool calls" : "Crides d'eines", + "Tools call instructions from the model in JSON format" : "Les eines criden instruccions del model en format JSON", + "Formalize text" : "Formalitzar el text", + "Takes a text and makes it sound more formal" : "Pren un text i el fa sonar més formal", + "Write a text that you want the assistant to formalize" : "Escriu un text que vulguis que l'assistent formalitzi", + "Formalized text" : "Text formalitzat", + "The formalized text" : "El text formalitzat", + "Generate a headline" : "Generar un titular", "Generates a possible headline for a text." : "Genera un titular possible per a un text.", + "Original text" : "Text original", + "The original text to generate a headline for" : "El text original per a generar un títol", + "The generated headline" : "El títol generat", + "Proofread" : "Revisat", + "Proofreads a text and lists corrections" : "Corregeix un text i enumera les correccions", + "Text" : "Text", + "The text to proofread" : "El text a corregir", + "Corrections" : "Correccions", + "The corrections that should be made in your text" : "Les correccions que s'han de fer al vostre text", + "Reformulate text" : "Reformular el text", + "Takes a text and reformulates it" : "Agafa un text i el reformula", + "Write a text that you want the assistant to reformulate" : "Escriu un text que vulguis que l'assistent reformuli", + "Reformulated text" : "Text reformulat", + "The reformulated text, written by the assistant" : "El text reformulat, escrit per l'assistent", + "Simplify text" : "Simplifica el text", + "Takes a text and simplifies it" : "Agafa un text i el simplifica", + "Write a text that you want the assistant to simplify" : "Escriu un text que vulguis que l'assistent simplifiqui", + "Simplified text" : "Text simplificat", + "The simplified text" : "El text simplificat", "Summarize" : "Resumeix", + "Summarizes a text" : "Resumeix un text", + "The original text to summarize" : "El text original per resumir", "Summary" : "Resum", + "The generated summary" : "El resum generat", "Extract topics" : "Extreu els temes", + "Extracts topics from a text and outputs them separated by commas" : "Extreu temes d'un text i els envia separats per comes", + "The original text to extract topics from" : "El text original per extreure temes", + "Topics" : "Temes", + "The list of extracted topics" : "La llista de temes extrets", "Translate" : "Tradueix", + "Translate text from one language to another" : "Tradueix text d'una llengua a un altre", + "Origin text" : "Text d'origen", + "The text to translate" : "El text a traduir", + "Origin language" : "Llengua d'origen", + "The language of the origin text" : "La llengua del text d'origen", "Target language" : "Llengua de destinació", + "The desired language to translate the origin text in" : "La llengua desitjada per traduir el text d'origen", "Result" : "Resultat", + "The translated text" : "Copia el text traduït", "Free prompt" : "Sol·licitud lliure", "Runs an arbitrary prompt through the language model." : "Executa una sol·licitud arbitrària mitjançant el model de llengua.", "Generate headline" : "Genera un titular", "Summarizes text by reducing its length without losing key information." : "Resumeix el text reduint-ne la longitud sense perdre la informació clau.", "Extracts topics from a text and outputs them separated by commas." : "Extreu els temes d'un text i els retorna separats per comes.", - "Education Edition" : "Edició educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "L'usuari que ha iniciat la sessió ha de ser administrador, subadministrador o tenir un dret especial per a accedir a aquest paràmetre", - "Logged in user must be an admin or sub admin" : "L'usuari que ha iniciat la sessió ha de ser administrador o subadministrador", - "Logged in user must be an admin" : "L'usuari que ha iniciat la sessió ha de ser administrador", - "File name is a reserved word" : "El nom del fitxer és una paraula reservada", - "File name contains at least one invalid character" : "El nom del fitxer conté almenys un caràcter no vàlid", - "File name is too long" : "El nom del fitxer és massa llarg", - "Help" : "Ajuda", - "Users" : "Usuaris", - "Unknown user" : "Usuari desconegut", - "Enter the database username and name for %s" : "Introduïu el nom d'usuari i el nom de la base de dades per a %s", - "Enter the database username for %s" : "Introduïu el nom d'usuari de la base de dades per a %s", - "MySQL username and/or password not valid" : "El nom d'usuari o la contrasenya del MySQL no són vàlids", - "Oracle username and/or password not valid" : "El nom d'usuari o la contrasenya d'Oracle no són vàlids", - "PostgreSQL username and/or password not valid" : "El nom d'usuari o la contrasenya del PostgreSQL no són vàlids", - "Set an admin username." : "Definiu un nom d'usuari per a l'administrador.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s ha compartit «%2$s» amb vós i vol afegir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s ha compartit «%2$s» amb vós i vol afegir", - "»%s« added a note to a file shared with you" : "%s ha afegit una nota a un fitxer compartit amb vós", - "Open »%s«" : "Obre «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "No s'ha pogut compartir %s perquè l'element ja està compartit amb l'usuari %s", - "%1$s shared »%2$s« with you" : "%1$s ha compartit «%2$s» amb vós", - "%1$s shared »%2$s« with you." : "%1$s ha compartit «%2$s» amb vós.", - "The username is already being used" : "El nom d'usuari ja està en ús", - "Could not create user" : "No s'ha pogut crear l'usuari", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Només es permeten els caràcters següents en un nom d'usuari: «a-z», «A-Z», «0-9», espais i «_.@-'»", - "A valid username must be provided" : "Heu de proporcionar un nom d'usuari vàlid", - "Username contains whitespace at the beginning or at the end" : "El nom d'usuari conté espais en blanc al principi o al final", - "Username must not consist of dots only" : "El nom d'usuari no pot estar format només per punts", - "Username is invalid because files already exist for this user" : "El nom d'usuari no és vàlid perquè ja existeixen fitxers per a aquest usuari", - "User disabled" : "Usuari inhabilitat", + "Organisation" : "Organització", "File is currently busy, please try again later" : "El fitxer està ocupat actualment; torneu-ho a provar més tard", - "Cannot download file" : "No es pot baixar el fitxer", - "Your data directory is readable by other users." : "Els altres usuaris poden llegir la carpeta de dades.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Canvieu els permisos a 0770 perquè els altres usuaris no puguin veure el contingut de la carpeta.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assegureu-vos que hi hagi un fitxer anomenat «.ocdata» en l'arrel de la carpeta de dades." + "Cannot download file" : "No es pot baixar el fitxer" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/ca.json b/lib/l10n/ca.json index c8222c82cd5..2c869e550f4 100644 --- a/lib/l10n/ca.json +++ b/lib/l10n/ca.json @@ -1,7 +1,7 @@ { "translations": { - "Cannot write into \"config\" directory!" : "No es pot escriure en la carpeta «config»!", + "Cannot write into \"config\" directory!" : "No es pot escriure en la carpeta \"config\"!", "This can usually be fixed by giving the web server write access to the config directory." : "Això normalment es pot solucionar donant al servidor web accés d'escriptura a la carpeta de configuració.", - "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "O bé, si preferiu mantenir el fitxer config.php només de lectura, establir l'opció «config_is_read_only» com a «true».", + "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "O bé, si preferiu mantenir el fitxer config.php només de lectura, establir l'opció \"config_is_read_only\" com a cert.", "See %s" : "Consulteu %s", "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Falta l'aplicació %1$s o té una versió no compatible amb aquest servidor. Comproveu la carpeta d'aplicacions.", "Sample configuration detected" : "S'ha detectat una configuració d'exemple", @@ -17,6 +17,7 @@ "%1$s, %2$s and %3$s" : "%1$s, %2$s i %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s i %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s i %5$s", + "Education bundle" : "Paquet d'educació", "Enterprise bundle" : "Paquet empresarial", "Groupware bundle" : "Paquet de treball en grup", "Hub bundle" : "Paquet Hub", @@ -40,7 +41,7 @@ "Wiping of device %s has started" : "S'ha començat a esborrar el dispositiu %s", "Wiping of device »%s« has started" : "S'ha començat a esborrar el dispositiu «%s»", "»%s« started remote wipe" : "«%s» ha començat a esborrar dades en remot", - "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "El dispositiu o aplicació «%s» ha començat a esborrar les dades en remot. Rebreu un altre correu quan s'enllesteixi el procés.", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "El dispositiu o aplicació »%s« ha començat a esborrar les dades en remot. Rebreu un altre correu quan s'enllesteixi el procés", "Wiping of device %s has finished" : "S'ha acabat d'esborrar el dispositiu %s", "Wiping of device »%s« has finished" : "S'ha acabat d'esborrar el dispositiu «%s»", "»%s« finished remote wipe" : "«%s» ha acabat d'esborrar dades en remot", @@ -55,6 +56,11 @@ "Avatar image is not square" : "La imatge de l'avatar no és quadrada", "Files" : "Fitxers", "View profile" : "Visualitza el perfil", + "same time" : "mateix temps", + "_%nh_::_%nh_" : ["%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s endavant", + "%s behind" : "%s darrere", "Local time: %s" : "Hora local: %s", "today" : "avui", "tomorrow" : "demà", @@ -77,12 +83,34 @@ "seconds ago" : "fa uns segons", "Empty file" : "Fitxer buit", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "El mòdul amb l'ID %s no existeix. Habiliteu-lo els paràmetres de les aplicacions o contacteu amb l'administrador.", + "No file conversion providers available" : "No hi ha proveïdors de conversió de fitxers disponibles", + "File is too large to convert" : "El fitxer és massa gran per convertir-lo", + "Destination does not match conversion extension" : "La destinació no coincideix amb l'extensió de conversió", + "Could not convert file" : "No s'ha pogut convertir el fitxer", + "Destination does not exist" : "La destinació no existeix", + "Destination is not creatable" : "La destinació no es pot crear", "Dot files are not allowed" : "No es permeten els fitxers que comencen per un punt", + "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" és un nom de fitxer o carpeta prohibit.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" és un prefix prohibit per als noms de fitxers o carpetes.", + "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" no es permet dins d'un nom de fitxer o carpeta.", + "\"%1$s\" is a forbidden file type." : "\"%1$s\" és un tipus de fitxer prohibit.", + "Filenames must not end with \"%1$s\"." : "Els noms de fitxer no han d'acabar amb \"%1$s\".", + "Invalid parent path" : "El camí principal no és vàlid", "File already exists" : "El fitxer ja existeix", "Invalid path" : "El camí no és vàlid", "Failed to create file from template" : "No s'ha pogut crear el fitxer a partir de la plantilla", "Templates" : "Plantilles", + "Storage %s cannot be moved" : "L'emmagatzematge %s no es pot moure", + "Moving a share (%s) into a shared folder is not allowed" : "No és permès moure una compartició (%s) a una carpeta compartida", + "Moving a storage (%s) into a shared folder is not allowed" : "No és permès moure un emmagatzematge (%s) a una carpeta compartida", + "Moving a share (%s) into another share (%s) is not allowed" : "No és permès moure una compartició (%s) a una altra compartició (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "No és permès moure una compartició (%s) a un altre emmagatzematge (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "No és permès moure un emmagatzematge (%s) a una compartició (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "No és permès moure un emmagatzematge (%s) a un altre emmagatzematge (%s)", + "Path contains invalid segments" : "El camí conté segments no vàlids", + "Filename is a reserved word" : "El nom del fitxer és una paraula reservada", "Filename contains at least one invalid character" : "El nom del fitxer conté com a mínim un caràcter no vàlid", + "Filename is too long" : "El nom del fitxer és massa llarg", "Empty filename is not allowed" : "No es permeten els noms de fitxers buits", "App \"%s\" cannot be installed because appinfo file cannot be read." : "L'aplicació «%s» no es pot instal·lar perquè no es pot llegir el fitxer appinfo.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "L'aplicació «%s» no es pot instal·lar perquè no és compatible amb aquesta versió del servidor.", @@ -111,8 +139,8 @@ "About" : "Quant a", "Display name" : "Nom de visualització", "Headline" : "Capçalera", - "Organisation" : "Organització", "Role" : "Càrrec", + "Pronouns" : "Pronoms", "Unknown account" : "Compte desconegut", "Additional settings" : "Paràmetres addicionals", "Enter the database Login and name for %s" : "Introduïu l'inici de sessió i el nom de la base de dades per a %s", @@ -124,7 +152,6 @@ "Oracle connection could not be established" : "No s'ha pogut establir la connexió amb Oracle", "Oracle Login and/or password not valid" : "L'inici de sessió o la contrasenya d'Oracle no són vàlids", "PostgreSQL Login and/or password not valid" : "L'inici de sessió o la contrasenya del PostgreSQL no són vàlids", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "El Mac OS X no s'admet i el %s no funcionarà correctament en aquesta plataforma. Utilitzeu-lo sota el vostre propi risc! ", "For the best results, please consider using a GNU/Linux server instead." : "Per a obtenir els millors resultats, considereu la possibilitat d'utilitzar un servidor amb GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Sembla que aquesta instància del %s s'està executant en un entorn del PHP de 32 bits i que s'ha configurat open_basedir en el fitxer php.ini. Això comportarà problemes amb els fitxers de més de 4 GB i és molt poc recomanable.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Suprimiu el paràmetre open_basedir del fitxer php.ini o canvieu al PHP de 64 bits.", @@ -134,21 +161,60 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El rerefons d'ús compartit %s ha d'implementar la interfície OCP\\Share_Backend", "Sharing backend %s not found" : "No s'ha trobat el rerefons d'ús compartit %s", "Sharing backend for %s not found" : "No s'ha trobat el rerefons d'ús compartit per a %s", - "Click the button below to open it." : "Feu clic en el botó següent per a obrir-ho.", + "%1$s shared %2$s with you" : "%1$s ha compartit %2$s amb tu", + "Open %s" : "Obre %s", "%1$s via %2$s" : "%1$s mitjançant %2$s", - "Unknown share type" : "Tipus d'element compartit desconegut", + "%1$s shared %2$s with you and wants to add:" : "%1$s ha compartit %2$s amb tu i vol afegir:", + "%1$s shared %2$s with you and wants to add" : "%1$s ha compartit %2$s amb tu i vol afegir", + "%s added a note to a file shared with you" : "%s ha afegit una nota a un fitxer compartit amb tu", + "Passwords are enforced for link and mail shares" : "S'apliquen contrasenyes per compartició d'enllaços i correus", + "Share recipient is not a valid user" : "El destinatari de la compartició no és un usuari vàlid", + "Share recipient is not a valid group" : "El destinatari de la compartició no és un grup vàlid", + "Share recipient should be empty" : "El destinatari de la compartició ha d'estar buit", + "Share recipient should not be empty" : "El destinatari de la compartició no ha d'estar buit", + "Share recipient is not a valid circle" : "El destinatari de la compartició no és un cercle vàlid", + "Unknown share type" : "Tipus de compartició desconegut", + "Share initiator must be set" : "S'ha d'establir l'iniciador de la compartició", + "Cannot share with yourself" : "No es pot compartir amb tu mateix", + "Shared path must be set" : "S'ha d'establir un camí compartit", + "Shared path must be either a file or a folder" : "El camí compartit ha de ser un fitxer o una carpeta", + "You cannot share your root folder" : "No podeu compartir la vostra carpeta arrel", "You are not allowed to share %s" : "No podeu compartir %s", + "Valid permissions are required for sharing" : "Es requereixen permisos vàlids per compartir", + "File shares cannot have create or delete permissions" : "Les comparticions de fitxers no poden tenir permisos de creació o supressió", "Cannot increase permissions of %s" : "No es poden augmentar els permisos de %s", + "Shares need at least read permissions" : "Les comparticions almenys necessiten permisos de lectura", "Files cannot be shared with delete permissions" : "No es poden compartir fitxers amb permisos de supressió", "Files cannot be shared with create permissions" : "No es poden compartir fitxers amb permisos de creació", "Expiration date is in the past" : "La data de caducitat ja ha passat", + "Expiration date is enforced" : "S'aplica la data de caducitat", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["No es pot establir la data de caducitat més d'%n dia en el futur","No es pot establir la data de caducitat més de %n dies en el futur"], "Sharing is only allowed with group members" : "Només es permet l'ús compartit amb membres del grup", "Sharing %s failed, because this item is already shared with the account %s" : "No s'ha pogut compartir %s perquè l'element ja està compartit amb el compte %s", + "Group sharing is now allowed" : "Ara es permet compartir en grup", + "Sharing is only allowed within your own groups" : "La compartició només és permesa dins dels vostres propis grups", + "Path is already shared with this group" : "El camí ja està compartit amb aquest grup", + "Link sharing is not allowed" : "La compartició d'enllaços no és permesa", + "Public upload is not allowed" : "La pujada pública no és permesa", + "Sharing is disabled" : "S’ha desactivat la compartició", + "Sharing is disabled for you" : "La compartició està desactivada per a tu", + "Cannot share with the share owner" : "No es pot compartir amb el propietari de la compartició", + "Share does not have a full ID" : "La compartició no té un ID complet", + "Cannot change share type" : "No es pot canviar el tipus de compartició", + "Can only update recipient on user shares" : "Només es pot actualitzar el destinatari en les comparticions d'usuaris", + "Cannot enable sending the password by Talk with an empty password" : "No es pot habilitar l'enviament de la contrasenya per Converses amb una contrasenya buida", + "Cannot enable sending the password by Talk without setting a new password" : "No es pot activar l'enviament de la contrasenya per Converses sense establir una nova contrasenya", + "Cannot disable sending the password by Talk without setting a new password" : "No es pot desactivar l'enviament de la contrasenya per Converses sense establir una nova contrasenya", + "Share provider does not support accepting" : "El proveïdor de la compartició no admet l'acceptació", + "Cannot change target of link share" : "No es pot canviar el destí de l'enllaç de compartició", + "Invalid share recipient" : "El destinatari de la compartició no és vàlid", + "Group \"%s\" does not exist" : "El grup \"%s\" no existeix", "The requested share does not exist anymore" : "L'element compartit sol·licitat ja no existeix", "The requested share comes from a disabled user" : "L'element compartit sol·licitat prové d'un usuari inhabilitat", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "No s'ha creat l'usuari perquè s'ha assolit el límit d'usuaris. Consulteu les notificacions per a obtenir més informació.", "Could not find category \"%s\"" : "No s'ha trobat la categoria «%s»", + "Input text" : "Text d'entrada", + "The input text" : "El text d'entrada", "Sunday" : "Diumenge", "Monday" : "Dilluns", "Tuesday" : "Dimarts", @@ -205,7 +271,7 @@ "Account disabled" : "El compte està inhabilitat", "Login canceled by app" : "L'aplicació ha cancel·lat l'inici de sessió", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "L'aplicació «%1$s» no es pot instal·lar perquè no es compleixen les dependències següents: %2$s", - "a safe home for all your data" : "Un lloc segur per a totes les vostres dades", + "a safe home for all your data" : "un lloc segur per a totes les vostres dades", "Application is not enabled" : "L'aplicació no està habilitada", "Authentication error" : "Error d'autenticació", "Token expired. Please reload page." : "El testimoni ha caducat. Torneu a carregar la pàgina.", @@ -238,6 +304,7 @@ "Your data directory must be an absolute path." : "La carpeta de dades ha de ser un camí absolut.", "Check the value of \"datadirectory\" in your configuration." : "Comproveu el valor de «datadirectory» en la configuració.", "Your data directory is invalid." : "La carpeta de dades no és vàlida.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Assegureu-vos que hi hagi un fitxer anomenat \"%1$s\" a l'arrel del directori de dades. Hauria de tenir el contingut: \"%2$s\"", "Action \"%s\" not supported or implemented." : "L'acció «%s» no està admesa o implementada.", "Authentication failed, wrong token or provider ID given" : "No s'ha pogut autenticar; s'ha proporcionat un testimoni o un ID de proveïdor incorrecte", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Falten paràmetres per a completar la sol·licitud. Els paràmetres que falten són: «%s»", @@ -249,54 +316,128 @@ "Storage connection error. %s" : "S'ha produït un error de connexió amb l'emmagatzematge. %s", "Storage is temporarily not available" : "L'emmagatzematge no està disponible temporalment", "Storage connection timeout. %s" : "S'ha superat el temps d'espera de la connexió d'emmagatzematge. %s", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Per permetre que aquesta comprovació s'executi, heu d'assegurar-vos que el vostre servidor web es pot connectar a si mateix. Per tant, ha de ser capaç de resoldre i connectar-se a almenys un dels seus `trusted_domains` o `overwrite.cli.url`. Aquest error pot ser el resultat d'una manca de concordança de DNS del servidor o d'una regla de tallafoc de sortida.", + "Transcribe audio" : "Transcripció d'àudio", + "Transcribe the things said in an audio" : "Transcriu les coses dites en un àudio", + "Audio input" : "Entrada d'àudio", + "The audio to transcribe" : "L'àudio a transcriure", + "Transcription" : "Transcripció", + "The transcribed text" : "El text transcrit", + "Chat with an agent" : "Xat amb un agent", + "Chat message" : "Missatge de xat", + "A chat message to send to the agent." : "Un missatge de xat per enviar a l'agent.", "Confirmation" : "Confirmació", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Si confirmar les accions sol·licitades anteriorment: 0 per a la denegació i 1 per a la confirmació.", + "Conversation token" : "Testimoni de conversa", + "A token representing the conversation." : "Un testimoni que representa la conversa.", + "Generated response" : "Resposta generada", + "The response from the chat model." : "La resposta del model de xat.", + "The new conversation token" : "El nou testimoni de conversa", + "Send this along with the next interaction." : "Envieu-ho juntament amb la següent interacció.", + "Requested actions by the agent" : "Accions sol·licitades per l'agent", + "Actions that the agent would like to carry out in JSON format." : "Accions que l'agent vol dur a terme en format JSON.", + "Context write" : "Escriptura de context", + "Writes text in a given style based on the provided source material." : "Escriu text en un estil determinat basant-se en el material font proporcionat.", + "Writing style" : "Estil d'escriptura", + "Demonstrate a writing style that you would like to immitate" : "Demostra un estil d'escriptura que t'agradaria imitar", + "Source material" : "Material d'origen", + "The content that would like to be rewritten in the new writing style" : "El contingut que voldria ser reescrit amb el nou estil d'escriptura", + "Generated text" : "Text generat", + "The generated text with content from the source material in the given style" : "El text generat amb contingut del material d'origen en l'estil donat", + "Emoji generator" : "Generador d'emojis", + "Takes text and generates a representative emoji for it." : "Pren text i genera un emoji representatiu.", + "The text to generate an emoji for" : "El text per a generar un emoji", + "Generated emoji" : "Emoji generat", + "The generated emoji based on the input text" : "L'emoji generat a partir del text d'entrada", + "Generate image" : "Generar imatge", + "Generate an image from a text prompt" : "Genereu una imatge a partir d'una sol·licitud de text", + "Prompt" : "Indicador", + "Describe the image you want to generate" : "Descriu la imatge que vols generar", + "Number of images" : "Nombre d'imatges", + "How many images to generate" : "Quantes imatges generar", + "Output images" : "Imatges de sortida", + "The generated images" : "Les imatges generades", + "Free text to text prompt" : "Text lliure per indicador de text", + "Runs an arbitrary prompt through a language model that returns a reply" : "Executa una indicació arbitraria mitjançant un model de llengua que retorna una resposta", + "Describe a task that you want the assistant to do or ask a question" : "Descriu una tasca que vols que faci l'assistent o fes una pregunta", + "Generated reply" : "Resposta generada", + "The generated text from the assistant" : "El text generat per l'assistent", + "Change Tone" : "Canvia el to", + "Change the tone of a piece of text." : "Canvia el to d'un fragment de text.", + "Write a text that you want the assistant to rewrite in another tone." : "Escriu un text que vols que l'assistent torni a escriure en un altre to.", + "Desired tone" : "To desitjat", + "In which tone should your text be rewritten?" : "En quin to s'ha de reescriure el teu text?", + "The rewritten text in the desired tone, written by the assistant:" : "El text reescrit en el to desitjat, escrit per l'assistent:", + "Chat" : "Xat", + "Chat with the assistant" : "Xat amb l'assistent", + "System prompt" : "Indicador del sistema", + "Define rules and assumptions that the assistant should follow during the conversation." : "Definir regles i supòsits que l'assistent ha de seguir durant la conversa.", + "Chat history" : "Historial de xat", + "The history of chat messages before the current message, starting with a message by the user" : "L'historial dels missatges de xat abans del missatge actual, començant amb un missatge de l'usuari", + "Response message" : "Missatge de resposta", + "The generated response as part of the conversation" : "La resposta generada com a part de la conversa", + "Chat with tools" : "Xat amb eines", + "Chat with the language model with tool calling support." : "Xat amb el model de llengua amb suport de crida d'eines.", + "Tool message" : "Missatge de l'eina", + "The result of tool calls in the last interaction" : "El resultat de les crides d'eines en l'última interacció", + "Available tools" : "Eines disponibles", + "The available tools in JSON format" : "Les eines disponibles en format JSON", + "The response from the chat model" : "La resposta del model de xat", + "Tool calls" : "Crides d'eines", + "Tools call instructions from the model in JSON format" : "Les eines criden instruccions del model en format JSON", + "Formalize text" : "Formalitzar el text", + "Takes a text and makes it sound more formal" : "Pren un text i el fa sonar més formal", + "Write a text that you want the assistant to formalize" : "Escriu un text que vulguis que l'assistent formalitzi", + "Formalized text" : "Text formalitzat", + "The formalized text" : "El text formalitzat", + "Generate a headline" : "Generar un titular", "Generates a possible headline for a text." : "Genera un titular possible per a un text.", + "Original text" : "Text original", + "The original text to generate a headline for" : "El text original per a generar un títol", + "The generated headline" : "El títol generat", + "Proofread" : "Revisat", + "Proofreads a text and lists corrections" : "Corregeix un text i enumera les correccions", + "Text" : "Text", + "The text to proofread" : "El text a corregir", + "Corrections" : "Correccions", + "The corrections that should be made in your text" : "Les correccions que s'han de fer al vostre text", + "Reformulate text" : "Reformular el text", + "Takes a text and reformulates it" : "Agafa un text i el reformula", + "Write a text that you want the assistant to reformulate" : "Escriu un text que vulguis que l'assistent reformuli", + "Reformulated text" : "Text reformulat", + "The reformulated text, written by the assistant" : "El text reformulat, escrit per l'assistent", + "Simplify text" : "Simplifica el text", + "Takes a text and simplifies it" : "Agafa un text i el simplifica", + "Write a text that you want the assistant to simplify" : "Escriu un text que vulguis que l'assistent simplifiqui", + "Simplified text" : "Text simplificat", + "The simplified text" : "El text simplificat", "Summarize" : "Resumeix", + "Summarizes a text" : "Resumeix un text", + "The original text to summarize" : "El text original per resumir", "Summary" : "Resum", + "The generated summary" : "El resum generat", "Extract topics" : "Extreu els temes", + "Extracts topics from a text and outputs them separated by commas" : "Extreu temes d'un text i els envia separats per comes", + "The original text to extract topics from" : "El text original per extreure temes", + "Topics" : "Temes", + "The list of extracted topics" : "La llista de temes extrets", "Translate" : "Tradueix", + "Translate text from one language to another" : "Tradueix text d'una llengua a un altre", + "Origin text" : "Text d'origen", + "The text to translate" : "El text a traduir", + "Origin language" : "Llengua d'origen", + "The language of the origin text" : "La llengua del text d'origen", "Target language" : "Llengua de destinació", + "The desired language to translate the origin text in" : "La llengua desitjada per traduir el text d'origen", "Result" : "Resultat", + "The translated text" : "Copia el text traduït", "Free prompt" : "Sol·licitud lliure", "Runs an arbitrary prompt through the language model." : "Executa una sol·licitud arbitrària mitjançant el model de llengua.", "Generate headline" : "Genera un titular", "Summarizes text by reducing its length without losing key information." : "Resumeix el text reduint-ne la longitud sense perdre la informació clau.", "Extracts topics from a text and outputs them separated by commas." : "Extreu els temes d'un text i els retorna separats per comes.", - "Education Edition" : "Edició educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "L'usuari que ha iniciat la sessió ha de ser administrador, subadministrador o tenir un dret especial per a accedir a aquest paràmetre", - "Logged in user must be an admin or sub admin" : "L'usuari que ha iniciat la sessió ha de ser administrador o subadministrador", - "Logged in user must be an admin" : "L'usuari que ha iniciat la sessió ha de ser administrador", - "File name is a reserved word" : "El nom del fitxer és una paraula reservada", - "File name contains at least one invalid character" : "El nom del fitxer conté almenys un caràcter no vàlid", - "File name is too long" : "El nom del fitxer és massa llarg", - "Help" : "Ajuda", - "Users" : "Usuaris", - "Unknown user" : "Usuari desconegut", - "Enter the database username and name for %s" : "Introduïu el nom d'usuari i el nom de la base de dades per a %s", - "Enter the database username for %s" : "Introduïu el nom d'usuari de la base de dades per a %s", - "MySQL username and/or password not valid" : "El nom d'usuari o la contrasenya del MySQL no són vàlids", - "Oracle username and/or password not valid" : "El nom d'usuari o la contrasenya d'Oracle no són vàlids", - "PostgreSQL username and/or password not valid" : "El nom d'usuari o la contrasenya del PostgreSQL no són vàlids", - "Set an admin username." : "Definiu un nom d'usuari per a l'administrador.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s ha compartit «%2$s» amb vós i vol afegir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s ha compartit «%2$s» amb vós i vol afegir", - "»%s« added a note to a file shared with you" : "%s ha afegit una nota a un fitxer compartit amb vós", - "Open »%s«" : "Obre «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "No s'ha pogut compartir %s perquè l'element ja està compartit amb l'usuari %s", - "%1$s shared »%2$s« with you" : "%1$s ha compartit «%2$s» amb vós", - "%1$s shared »%2$s« with you." : "%1$s ha compartit «%2$s» amb vós.", - "The username is already being used" : "El nom d'usuari ja està en ús", - "Could not create user" : "No s'ha pogut crear l'usuari", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Només es permeten els caràcters següents en un nom d'usuari: «a-z», «A-Z», «0-9», espais i «_.@-'»", - "A valid username must be provided" : "Heu de proporcionar un nom d'usuari vàlid", - "Username contains whitespace at the beginning or at the end" : "El nom d'usuari conté espais en blanc al principi o al final", - "Username must not consist of dots only" : "El nom d'usuari no pot estar format només per punts", - "Username is invalid because files already exist for this user" : "El nom d'usuari no és vàlid perquè ja existeixen fitxers per a aquest usuari", - "User disabled" : "Usuari inhabilitat", + "Organisation" : "Organització", "File is currently busy, please try again later" : "El fitxer està ocupat actualment; torneu-ho a provar més tard", - "Cannot download file" : "No es pot baixar el fitxer", - "Your data directory is readable by other users." : "Els altres usuaris poden llegir la carpeta de dades.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Canvieu els permisos a 0770 perquè els altres usuaris no puguin veure el contingut de la carpeta.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assegureu-vos que hi hagi un fitxer anomenat «.ocdata» en l'arrel de la carpeta de dades." + "Cannot download file" : "No es pot baixar el fitxer" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/cs.js b/lib/l10n/cs.js index 9698cf6b339..a612f043a71 100644 --- a/lib/l10n/cs.js +++ b/lib/l10n/cs.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Je potřeba verze serveru %s nebo novější.", "Server version %s or lower is required." : "Je potřeba verze serveru %s nebo starší.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Aby mohl přistupovat k tomuto nastavení je třeba, aby přihlášený účet byl správce, dílčí správce nebo obdržel speciální oprávnění", - "Your current IP address doesn’t allow you to perform admin actions" : "Pro IP adresu, ze které přistupujete, není umožněno provádět úkony správy", + "Your current IP address doesn't allow you to perform admin actions" : "Pro IP adresu, ze které přistupujete, není umožněno provádět úkony správy", "Logged in account must be an admin or sub admin" : "Je třeba, aby přihlášený účet byl správcem či správcem pro dílčí oblast", "Logged in account must be an admin" : "Je třeba, aby přihlášený účet byl správcem", "Wiping of device %s has started" : "Vymazávání ze zařízení %s zahájeno", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Profilový obrázek není čtvercový", "Files" : "Soubory", "View profile" : "Zobrazit profil ", + "same time" : "stejný čas", + "_%nh_::_%nh_" : ["%nh","%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm","%nm"], + "%s ahead" : "%s před", + "%s behind" : "%s za", "Local time: %s" : "Místní čas: %s", "today" : "dnes", "tomorrow" : "zítra", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "před pár sekundami", "Empty file" : "Prázdný soubor", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s identifikátorem: %s neexistuje. Povolte ho v nastavení aplikací, nebo se obraťte na správce.", + "No file conversion providers available" : "Nejsou k dispozici žádní poskytovatelé převádění souborů", + "File is too large to convert" : "Soubor je příliš velký pro převod", + "Destination does not match conversion extension" : "Cíl neodpovídá příponě převodu", + "Could not convert file" : "Soubor není možné převést", + "Destination does not exist" : "Cíl neexistuje", + "Destination is not creatable" : "Cíl není možné vytvořit", "Dot files are not allowed" : "Názvy souborů, začínající na tečku nejsou dovolené", + "%1$s (renamed)" : "%1$s (přejmenované)", + "renamed file" : "přejmenovaný soubor", "\"%1$s\" is a forbidden file or folder name." : "„%1$s“ je zakázáno v názvu souboru nebo složky.", "\"%1$s\" is a forbidden prefix for file or folder names." : "„%1$s“ je zakázaná předpona pro názvy souborů či složek.", "\"%1$s\" is not allowed inside a file or folder name." : "„%1$s“ není povoleno v rámci názvu souboru či složky.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Neplatný popis umístění", "Failed to create file from template" : "Vytvoření souboru ze šablony se nezdařilo", "Templates" : "Šablony", + "Storage %s cannot be moved" : "Úložiště %s není možné přesunout", + "Moving a share (%s) into a shared folder is not allowed" : "Přesunutí sdílení (%s) do sdílené složky není povoleno", + "Moving a storage (%s) into a shared folder is not allowed" : "Přesunutí úložiště (%s) do sdílené složky není povoleno", + "Moving a share (%s) into another share (%s) is not allowed" : "Přesunutí sdílení (%s) do jiného sdílení (%s) není povoleno", + "Moving a share (%s) into another storage (%s) is not allowed" : "Přesunutí sdílení (%s) do jiného úložiště (%s) není povoleno", + "Moving a storage (%s) into a share (%s) is not allowed" : "Přesunutí úložiště (%s) do sdílení (%s) není povoleno", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Přesunutí úložiště (%s) do jiného úložiště (%s) není povoleno", "Path contains invalid segments" : "Popis umístění obsahuje neplatné úseky", "Filename is a reserved word" : "Název souboru je rezervované slovo", "Filename contains at least one invalid character" : "Název souboru obsahuje přinejmenším jeden neplatný znak", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "O uživateli", "Display name" : "Zobrazované jméno", "Headline" : "Nadpis", - "Organisation" : "Organizace", + "Organization" : "Organizování", "Role" : "Role", "Pronouns" : "Zájmena", "Unknown account" : "Neznámý účet", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Spojení s Oracle nemohlo být navázáno", "Oracle Login and/or password not valid" : "Neplatné přihlašovací jméno a/nebo heslo do Oracle", "PostgreSQL Login and/or password not valid" : "Neplatné přihlašovací jméno a/nebo heslo do PostgreSQL", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "macOS není podporován a %s nebude na této platformě správně fungovat. Používejte pouze na vlastní nebezpečí!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "macOS není podporován a %s nebude na této platformě správně fungovat. Používejte pouze na vlastní nebezpečí!", "For the best results, please consider using a GNU/Linux server instead." : "Místo toho zvažte pro nejlepší funkčnost použití GNU/Linux serveru.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Zdá se, že tato instance %s je provozována v 32-bitovém PHP prostředí a v php.ini je nastavena volba open_basedir. Toto povede k problémům se soubory většími než 4 GB a silně není doporučováno.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Odstraňte z php.ini nastavení volby open_basedir nebo přejděte na 64-bitové PHP.", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Podpůrná vrstva pro sdílení %s nenalezena", "Sharing backend for %s not found" : "Úložiště sdílení pro %s nenalezeno", "%1$s shared %2$s with you" : "%1$s vám nasdílel(a) %2$s", - "Click the button below to open it." : "Pro otevření klikněte na tlačítko níže.", "Open %s" : "Otevřít %s", "%1$s via %2$s" : "%1$s prostřednictvím %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s vám nasdílel(a) %2$s a chce přidat:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "Svou kořenovou složku nemůžete nasdílet", "You are not allowed to share %s" : "Nemáte povoleno sdílet %s", "Valid permissions are required for sharing" : "Pro sdílení je třeba platných oprávnění", + "File shares cannot have create or delete permissions" : "U sdílení souborů nemohou být oprávnění pro vytváření či mazání", "Cannot increase permissions of %s" : "Nelze povýšit oprávnění u %s", "Shares need at least read permissions" : "Sdílení potřebuje alespoň oprávnění pro čtení", "Files cannot be shared with delete permissions" : "Soubory nelze sdílet s oprávněními k odstranění", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Umístění už je této skupině nasdíleno", "Link sharing is not allowed" : "Sdílení odkazů není povoleno", "Public upload is not allowed" : "Veřejné nahrávání není povoleno", - "Path contains files shared with you" : "Popis umístění obsahuje soubory, které vám byly nasdíleny", + "You cannot share a folder that contains other shares" : "Není možné nasdílet složku, která obsahuje další sdílení", "Sharing is disabled" : "Sdílení je vypnuto", "Sharing is disabled for you" : "Máte zakázáno sdílet", "Cannot share with the share owner" : "Nelze sdílet zpět vlastníkovi sdílení", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "Je třeba zadat platné přihlašovací jméno", "Login contains whitespace at the beginning or at the end" : "Přihlašovací jméno je chybné – na jeho začátku či konci se nachází prázdný znak (mezera, tabulátor, atp.)", "Login must not consist of dots only" : "Přihlašovací jméno se nemůže skládat pouze ze samých teček", + "Username is too long" : "Uživatelské jméno je příliš dlouhé", "Login is invalid because files already exist for this user" : "Přihlašovací jméno není platné, protože protože pro tohoto uživatele už existují soubory", "Account disabled" : "Účet znepřístupněn", "Login canceled by app" : "Přihlášení zrušeno aplikací", @@ -311,8 +332,19 @@ OC.L10N.register( "The audio to transcribe" : "Nahrávka k přepisu", "Transcription" : "Přepis do textu", "The transcribed text" : "Přepsaný text", + "Chat with an agent" : "Chatovat s agentem", "Chat message" : "Zpráva v chatu", + "A chat message to send to the agent." : "Zpráva chatu, kterou poslat agentovi.", "Confirmation" : "Potvrzení", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Zda potvrdit dříve vyžádané akce: 0 (nula) pro odepření a 1 pro potvrzení.", + "Conversation token" : "Token konverzace", + "A token representing the conversation." : "Token představující konverzaci.", + "Generated response" : "Vygenerovaná odpověď", + "The response from the chat model." : "Odpověď z modelu chatu.", + "The new conversation token" : "Token nové konverzace", + "Send this along with the next interaction." : "Odeslat toto společně s příští interakcí.", + "Requested actions by the agent" : "Akce vyžádané agentem", + "Actions that the agent would like to carry out in JSON format." : "Akce které by agent rád provedl (v JSON formátu).", "Context write" : "Kontextový zápis", "Writes text in a given style based on the provided source material." : "Napíše text v daném stylu na základě poskytnutého zdrojového materiálu.", "Writing style" : "Styl zápisu", @@ -334,11 +366,22 @@ OC.L10N.register( "How many images to generate" : "Kolik obrázků vytvořit", "Output images" : "Výstupní obrázky", "The generated images" : "Vytvořené obrázky", + "Generate speech" : "Vytvořit řeč", + "Generate speech from a transcript" : "Vytvořit řeč z přepisu", + "Write transcript that you want the assistant to generate speech from" : "Napište přepis, ze kterého chcete, aby asistent vytvořil řeč", + "Output speech" : "Výstupní řeč", + "The generated speech" : "Vytvořená řeč", "Free text to text prompt" : "Volný text na textový prompt", "Runs an arbitrary prompt through a language model that returns a reply" : "Spouští libovolnou výzvu skrze jazykový model který vrací odpověď", "Describe a task that you want the assistant to do or ask a question" : "Popište úkol který chcete aby asistent udělal nebo položte dotaz", "Generated reply" : "Vygenerovaná odpověď", "The generated text from the assistant" : "Text vytvořený pomocníkem", + "Change Tone" : "Změnit tón", + "Change the tone of a piece of text." : "Změnit tón kusu textu.", + "Write a text that you want the assistant to rewrite in another tone." : "Napište text který chcete aby asistent přepsal jiným tónem.", + "Desired tone" : "Požadovaný tón", + "In which tone should your text be rewritten?" : "Ve kterém tónu by měl být váš text přepsán?", + "The rewritten text in the desired tone, written by the assistant:" : "Text přepsaný v požadovaném tónu, napsaný asistentem:", "Chat" : "Chat", "Chat with the assistant" : "Chat s pomocníkem", "System prompt" : "Systémový prompt", @@ -347,6 +390,15 @@ OC.L10N.register( "The history of chat messages before the current message, starting with a message by the user" : "Historie zpráv v chatu před stávající zprávou, počínaje zprávou od uživatele", "Response message" : "Zpráva s odpovědí", "The generated response as part of the conversation" : "Vytvořená odpověď jako součást konverzace", + "Chat with tools" : "Chatovat s nástroji", + "Chat with the language model with tool calling support." : "Chatovat s jazykovým modelem, který podporuje volání nástrojů.", + "Tool message" : "Zpráva nástroje", + "The result of tool calls in the last interaction" : "Výsledek volání nástroje v poslední interakci", + "Available tools" : "Nástroje k dispozici", + "The available tools in JSON format" : "Nástroje k dispozici (v JSON formátu)", + "The response from the chat model" : "Odpověď z modelu chatu", + "Tool calls" : "Volání nástrojů", + "Tools call instructions from the model in JSON format" : "Instrukce volání nástroje z modelu (v JSON formátu)", "Formalize text" : "Formalizovat text", "Takes a text and makes it sound more formal" : "Vezme text a předělá ho aby vyzněl formálněji", "Write a text that you want the assistant to formalize" : "Napište text který chcete, aby asistent formalizoval", @@ -357,6 +409,12 @@ OC.L10N.register( "Original text" : "Původní text", "The original text to generate a headline for" : "Původní text ke kterému vytvořit nadpis", "The generated headline" : "Vytvořený nadpis", + "Proofread" : "Provést korekturu", + "Proofreads a text and lists corrections" : "Provést korekturu textu a vypsat opravy", + "Text" : "Text", + "The text to proofread" : "Text ve kterém provést korekturu", + "Corrections" : "Opravy", + "The corrections that should be made in your text" : "Opravy vašeho textu by měly být hotové", "Reformulate text" : "Přeformulovat text", "Takes a text and reformulates it" : "Vezme text a přeformuluje ho", "Write a text that you want the assistant to reformulate" : "Napište text který chcete aby asistent přeformuloval", @@ -392,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Vytvořit nadpis", "Summarizes text by reducing its length without losing key information." : "Vytvoří stručný souhrn textu tím, že zkrátí jeho délku aniž by byly ztraceny klíčové informace", "Extracts topics from a text and outputs them separated by commas." : "Vyzíská témata z textu a vypíše je oddělované čárkami.", - "Education Edition" : "Vydání pro vzdělávací instituce", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Aby mohl přistupovat k tomuto nastavení je třeba, aby přihlášený uživatel byl správce, dílčí správce nebo obdržel speciální oprávnění", - "Logged in user must be an admin or sub admin" : "Je třeba, aby přihlášený uživatel byl správcem či správcem pro dílčí oblast", - "Logged in user must be an admin" : "Je třeba, aby přihlášený uživatel byl správce", - "File name is a reserved word" : "Název souboru je rezervované slovo", - "File name contains at least one invalid character" : "Název souboru obsahuje přinejmenším jeden neplatný znak", - "File name is too long" : "Název souboru je příliš dlouhý", - "Help" : "Nápověda", - "Users" : "Uživatelé", - "Unknown user" : "Neznámý uživatel", - "Enter the database username and name for %s" : "Zadejte uživatelské jméno v databázi a název pro %s", - "Enter the database username for %s" : "Zadejte uživatelské jméno v databázi pro %s", - "MySQL username and/or password not valid" : "Neplatné uživatelské jméno a/nebo heslo do MySQL", - "Oracle username and/or password not valid" : "Neplatné uživatelské jméno a/nebo heslo do Oracle", - "PostgreSQL username and/or password not valid" : "Neplatné uživatelské jméno a/nebo heslo do PostgreSQL", - "Set an admin username." : "Nastavte uživatelské jméno správce.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s sdílí „%2$s“ a dodává:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s sdílí „%2$s“ a dodává", - "»%s« added a note to a file shared with you" : "„%s“ dodává poznámku k nasdílenému souboru ", - "Open »%s«" : "Otevřít „%s“", - "Sharing %s failed, because this item is already shared with user %s" : "Sdílení %s se nezdařilo, protože tato položka už je sdílena s uživatelem %s", - "%1$s shared »%2$s« with you" : "%1$s vám sdílí „%2$s“", - "%1$s shared »%2$s« with you." : "%1$s vám nasdílel(a) „%2$s“.", - "The username is already being used" : "Uživatelské jméno už je využíváno", - "Could not create user" : "Nepodařilo se vytvořit uživatele", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Pouze následující znaky jsou povoleny pro uživatelské jméno: „a-z“, „A-Z“, „0-9“, mezery a „_.@-'“", - "A valid username must be provided" : "Je třeba zadat platné uživatelské jméno", - "Username contains whitespace at the beginning or at the end" : "Uživatelské jméno je chybné – na jeho začátku či konci se nachází prázdný znak (mezera, tabulátor, atp.)", - "Username must not consist of dots only" : "Uživatelské jméno se nemůže skládat pouze ze samých teček", - "Username is invalid because files already exist for this user" : "Uživatelské jméno není platné, protože protože pro tohoto uživatele už existují soubory", - "User disabled" : "Uživatel zakázán", + "Organisation" : "Organizace", "File is currently busy, please try again later" : "Soubor je nyní používán, zkuste to později", "Cannot download file" : "Soubor se nedaří stáhnout", - "Your data directory is readable by other users." : "Váš adresář data je čitelný ostatním uživatelům.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Změňte práva na 0770, aby obsah adresáře nemohl být vypisován ostatními uživateli.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Ověřte, že v kořeni datového adresáře je soubor s názvem „.ocdata“." + "Login is too long" : "Přihlašovací jméno je příliš dlouhé" }, "nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"); diff --git a/lib/l10n/cs.json b/lib/l10n/cs.json index 647b92da0c9..2b52499b80a 100644 --- a/lib/l10n/cs.json +++ b/lib/l10n/cs.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Je potřeba verze serveru %s nebo novější.", "Server version %s or lower is required." : "Je potřeba verze serveru %s nebo starší.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Aby mohl přistupovat k tomuto nastavení je třeba, aby přihlášený účet byl správce, dílčí správce nebo obdržel speciální oprávnění", - "Your current IP address doesn’t allow you to perform admin actions" : "Pro IP adresu, ze které přistupujete, není umožněno provádět úkony správy", + "Your current IP address doesn't allow you to perform admin actions" : "Pro IP adresu, ze které přistupujete, není umožněno provádět úkony správy", "Logged in account must be an admin or sub admin" : "Je třeba, aby přihlášený účet byl správcem či správcem pro dílčí oblast", "Logged in account must be an admin" : "Je třeba, aby přihlášený účet byl správcem", "Wiping of device %s has started" : "Vymazávání ze zařízení %s zahájeno", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Profilový obrázek není čtvercový", "Files" : "Soubory", "View profile" : "Zobrazit profil ", + "same time" : "stejný čas", + "_%nh_::_%nh_" : ["%nh","%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm","%nm"], + "%s ahead" : "%s před", + "%s behind" : "%s za", "Local time: %s" : "Místní čas: %s", "today" : "dnes", "tomorrow" : "zítra", @@ -79,7 +84,15 @@ "seconds ago" : "před pár sekundami", "Empty file" : "Prázdný soubor", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s identifikátorem: %s neexistuje. Povolte ho v nastavení aplikací, nebo se obraťte na správce.", + "No file conversion providers available" : "Nejsou k dispozici žádní poskytovatelé převádění souborů", + "File is too large to convert" : "Soubor je příliš velký pro převod", + "Destination does not match conversion extension" : "Cíl neodpovídá příponě převodu", + "Could not convert file" : "Soubor není možné převést", + "Destination does not exist" : "Cíl neexistuje", + "Destination is not creatable" : "Cíl není možné vytvořit", "Dot files are not allowed" : "Názvy souborů, začínající na tečku nejsou dovolené", + "%1$s (renamed)" : "%1$s (přejmenované)", + "renamed file" : "přejmenovaný soubor", "\"%1$s\" is a forbidden file or folder name." : "„%1$s“ je zakázáno v názvu souboru nebo složky.", "\"%1$s\" is a forbidden prefix for file or folder names." : "„%1$s“ je zakázaná předpona pro názvy souborů či složek.", "\"%1$s\" is not allowed inside a file or folder name." : "„%1$s“ není povoleno v rámci názvu souboru či složky.", @@ -90,6 +103,13 @@ "Invalid path" : "Neplatný popis umístění", "Failed to create file from template" : "Vytvoření souboru ze šablony se nezdařilo", "Templates" : "Šablony", + "Storage %s cannot be moved" : "Úložiště %s není možné přesunout", + "Moving a share (%s) into a shared folder is not allowed" : "Přesunutí sdílení (%s) do sdílené složky není povoleno", + "Moving a storage (%s) into a shared folder is not allowed" : "Přesunutí úložiště (%s) do sdílené složky není povoleno", + "Moving a share (%s) into another share (%s) is not allowed" : "Přesunutí sdílení (%s) do jiného sdílení (%s) není povoleno", + "Moving a share (%s) into another storage (%s) is not allowed" : "Přesunutí sdílení (%s) do jiného úložiště (%s) není povoleno", + "Moving a storage (%s) into a share (%s) is not allowed" : "Přesunutí úložiště (%s) do sdílení (%s) není povoleno", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Přesunutí úložiště (%s) do jiného úložiště (%s) není povoleno", "Path contains invalid segments" : "Popis umístění obsahuje neplatné úseky", "Filename is a reserved word" : "Název souboru je rezervované slovo", "Filename contains at least one invalid character" : "Název souboru obsahuje přinejmenším jeden neplatný znak", @@ -122,7 +142,7 @@ "About" : "O uživateli", "Display name" : "Zobrazované jméno", "Headline" : "Nadpis", - "Organisation" : "Organizace", + "Organization" : "Organizování", "Role" : "Role", "Pronouns" : "Zájmena", "Unknown account" : "Neznámý účet", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "Spojení s Oracle nemohlo být navázáno", "Oracle Login and/or password not valid" : "Neplatné přihlašovací jméno a/nebo heslo do Oracle", "PostgreSQL Login and/or password not valid" : "Neplatné přihlašovací jméno a/nebo heslo do PostgreSQL", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "macOS není podporován a %s nebude na této platformě správně fungovat. Používejte pouze na vlastní nebezpečí!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "macOS není podporován a %s nebude na této platformě správně fungovat. Používejte pouze na vlastní nebezpečí!", "For the best results, please consider using a GNU/Linux server instead." : "Místo toho zvažte pro nejlepší funkčnost použití GNU/Linux serveru.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Zdá se, že tato instance %s je provozována v 32-bitovém PHP prostředí a v php.ini je nastavena volba open_basedir. Toto povede k problémům se soubory většími než 4 GB a silně není doporučováno.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Odstraňte z php.ini nastavení volby open_basedir nebo přejděte na 64-bitové PHP.", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "Podpůrná vrstva pro sdílení %s nenalezena", "Sharing backend for %s not found" : "Úložiště sdílení pro %s nenalezeno", "%1$s shared %2$s with you" : "%1$s vám nasdílel(a) %2$s", - "Click the button below to open it." : "Pro otevření klikněte na tlačítko níže.", "Open %s" : "Otevřít %s", "%1$s via %2$s" : "%1$s prostřednictvím %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s vám nasdílel(a) %2$s a chce přidat:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "Svou kořenovou složku nemůžete nasdílet", "You are not allowed to share %s" : "Nemáte povoleno sdílet %s", "Valid permissions are required for sharing" : "Pro sdílení je třeba platných oprávnění", + "File shares cannot have create or delete permissions" : "U sdílení souborů nemohou být oprávnění pro vytváření či mazání", "Cannot increase permissions of %s" : "Nelze povýšit oprávnění u %s", "Shares need at least read permissions" : "Sdílení potřebuje alespoň oprávnění pro čtení", "Files cannot be shared with delete permissions" : "Soubory nelze sdílet s oprávněními k odstranění", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "Umístění už je této skupině nasdíleno", "Link sharing is not allowed" : "Sdílení odkazů není povoleno", "Public upload is not allowed" : "Veřejné nahrávání není povoleno", - "Path contains files shared with you" : "Popis umístění obsahuje soubory, které vám byly nasdíleny", + "You cannot share a folder that contains other shares" : "Není možné nasdílet složku, která obsahuje další sdílení", "Sharing is disabled" : "Sdílení je vypnuto", "Sharing is disabled for you" : "Máte zakázáno sdílet", "Cannot share with the share owner" : "Nelze sdílet zpět vlastníkovi sdílení", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "Je třeba zadat platné přihlašovací jméno", "Login contains whitespace at the beginning or at the end" : "Přihlašovací jméno je chybné – na jeho začátku či konci se nachází prázdný znak (mezera, tabulátor, atp.)", "Login must not consist of dots only" : "Přihlašovací jméno se nemůže skládat pouze ze samých teček", + "Username is too long" : "Uživatelské jméno je příliš dlouhé", "Login is invalid because files already exist for this user" : "Přihlašovací jméno není platné, protože protože pro tohoto uživatele už existují soubory", "Account disabled" : "Účet znepřístupněn", "Login canceled by app" : "Přihlášení zrušeno aplikací", @@ -309,8 +330,19 @@ "The audio to transcribe" : "Nahrávka k přepisu", "Transcription" : "Přepis do textu", "The transcribed text" : "Přepsaný text", + "Chat with an agent" : "Chatovat s agentem", "Chat message" : "Zpráva v chatu", + "A chat message to send to the agent." : "Zpráva chatu, kterou poslat agentovi.", "Confirmation" : "Potvrzení", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Zda potvrdit dříve vyžádané akce: 0 (nula) pro odepření a 1 pro potvrzení.", + "Conversation token" : "Token konverzace", + "A token representing the conversation." : "Token představující konverzaci.", + "Generated response" : "Vygenerovaná odpověď", + "The response from the chat model." : "Odpověď z modelu chatu.", + "The new conversation token" : "Token nové konverzace", + "Send this along with the next interaction." : "Odeslat toto společně s příští interakcí.", + "Requested actions by the agent" : "Akce vyžádané agentem", + "Actions that the agent would like to carry out in JSON format." : "Akce které by agent rád provedl (v JSON formátu).", "Context write" : "Kontextový zápis", "Writes text in a given style based on the provided source material." : "Napíše text v daném stylu na základě poskytnutého zdrojového materiálu.", "Writing style" : "Styl zápisu", @@ -332,11 +364,22 @@ "How many images to generate" : "Kolik obrázků vytvořit", "Output images" : "Výstupní obrázky", "The generated images" : "Vytvořené obrázky", + "Generate speech" : "Vytvořit řeč", + "Generate speech from a transcript" : "Vytvořit řeč z přepisu", + "Write transcript that you want the assistant to generate speech from" : "Napište přepis, ze kterého chcete, aby asistent vytvořil řeč", + "Output speech" : "Výstupní řeč", + "The generated speech" : "Vytvořená řeč", "Free text to text prompt" : "Volný text na textový prompt", "Runs an arbitrary prompt through a language model that returns a reply" : "Spouští libovolnou výzvu skrze jazykový model který vrací odpověď", "Describe a task that you want the assistant to do or ask a question" : "Popište úkol který chcete aby asistent udělal nebo položte dotaz", "Generated reply" : "Vygenerovaná odpověď", "The generated text from the assistant" : "Text vytvořený pomocníkem", + "Change Tone" : "Změnit tón", + "Change the tone of a piece of text." : "Změnit tón kusu textu.", + "Write a text that you want the assistant to rewrite in another tone." : "Napište text který chcete aby asistent přepsal jiným tónem.", + "Desired tone" : "Požadovaný tón", + "In which tone should your text be rewritten?" : "Ve kterém tónu by měl být váš text přepsán?", + "The rewritten text in the desired tone, written by the assistant:" : "Text přepsaný v požadovaném tónu, napsaný asistentem:", "Chat" : "Chat", "Chat with the assistant" : "Chat s pomocníkem", "System prompt" : "Systémový prompt", @@ -345,6 +388,15 @@ "The history of chat messages before the current message, starting with a message by the user" : "Historie zpráv v chatu před stávající zprávou, počínaje zprávou od uživatele", "Response message" : "Zpráva s odpovědí", "The generated response as part of the conversation" : "Vytvořená odpověď jako součást konverzace", + "Chat with tools" : "Chatovat s nástroji", + "Chat with the language model with tool calling support." : "Chatovat s jazykovým modelem, který podporuje volání nástrojů.", + "Tool message" : "Zpráva nástroje", + "The result of tool calls in the last interaction" : "Výsledek volání nástroje v poslední interakci", + "Available tools" : "Nástroje k dispozici", + "The available tools in JSON format" : "Nástroje k dispozici (v JSON formátu)", + "The response from the chat model" : "Odpověď z modelu chatu", + "Tool calls" : "Volání nástrojů", + "Tools call instructions from the model in JSON format" : "Instrukce volání nástroje z modelu (v JSON formátu)", "Formalize text" : "Formalizovat text", "Takes a text and makes it sound more formal" : "Vezme text a předělá ho aby vyzněl formálněji", "Write a text that you want the assistant to formalize" : "Napište text který chcete, aby asistent formalizoval", @@ -355,6 +407,12 @@ "Original text" : "Původní text", "The original text to generate a headline for" : "Původní text ke kterému vytvořit nadpis", "The generated headline" : "Vytvořený nadpis", + "Proofread" : "Provést korekturu", + "Proofreads a text and lists corrections" : "Provést korekturu textu a vypsat opravy", + "Text" : "Text", + "The text to proofread" : "Text ve kterém provést korekturu", + "Corrections" : "Opravy", + "The corrections that should be made in your text" : "Opravy vašeho textu by měly být hotové", "Reformulate text" : "Přeformulovat text", "Takes a text and reformulates it" : "Vezme text a přeformuluje ho", "Write a text that you want the assistant to reformulate" : "Napište text který chcete aby asistent přeformuloval", @@ -390,41 +448,9 @@ "Generate headline" : "Vytvořit nadpis", "Summarizes text by reducing its length without losing key information." : "Vytvoří stručný souhrn textu tím, že zkrátí jeho délku aniž by byly ztraceny klíčové informace", "Extracts topics from a text and outputs them separated by commas." : "Vyzíská témata z textu a vypíše je oddělované čárkami.", - "Education Edition" : "Vydání pro vzdělávací instituce", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Aby mohl přistupovat k tomuto nastavení je třeba, aby přihlášený uživatel byl správce, dílčí správce nebo obdržel speciální oprávnění", - "Logged in user must be an admin or sub admin" : "Je třeba, aby přihlášený uživatel byl správcem či správcem pro dílčí oblast", - "Logged in user must be an admin" : "Je třeba, aby přihlášený uživatel byl správce", - "File name is a reserved word" : "Název souboru je rezervované slovo", - "File name contains at least one invalid character" : "Název souboru obsahuje přinejmenším jeden neplatný znak", - "File name is too long" : "Název souboru je příliš dlouhý", - "Help" : "Nápověda", - "Users" : "Uživatelé", - "Unknown user" : "Neznámý uživatel", - "Enter the database username and name for %s" : "Zadejte uživatelské jméno v databázi a název pro %s", - "Enter the database username for %s" : "Zadejte uživatelské jméno v databázi pro %s", - "MySQL username and/or password not valid" : "Neplatné uživatelské jméno a/nebo heslo do MySQL", - "Oracle username and/or password not valid" : "Neplatné uživatelské jméno a/nebo heslo do Oracle", - "PostgreSQL username and/or password not valid" : "Neplatné uživatelské jméno a/nebo heslo do PostgreSQL", - "Set an admin username." : "Nastavte uživatelské jméno správce.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s sdílí „%2$s“ a dodává:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s sdílí „%2$s“ a dodává", - "»%s« added a note to a file shared with you" : "„%s“ dodává poznámku k nasdílenému souboru ", - "Open »%s«" : "Otevřít „%s“", - "Sharing %s failed, because this item is already shared with user %s" : "Sdílení %s se nezdařilo, protože tato položka už je sdílena s uživatelem %s", - "%1$s shared »%2$s« with you" : "%1$s vám sdílí „%2$s“", - "%1$s shared »%2$s« with you." : "%1$s vám nasdílel(a) „%2$s“.", - "The username is already being used" : "Uživatelské jméno už je využíváno", - "Could not create user" : "Nepodařilo se vytvořit uživatele", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Pouze následující znaky jsou povoleny pro uživatelské jméno: „a-z“, „A-Z“, „0-9“, mezery a „_.@-'“", - "A valid username must be provided" : "Je třeba zadat platné uživatelské jméno", - "Username contains whitespace at the beginning or at the end" : "Uživatelské jméno je chybné – na jeho začátku či konci se nachází prázdný znak (mezera, tabulátor, atp.)", - "Username must not consist of dots only" : "Uživatelské jméno se nemůže skládat pouze ze samých teček", - "Username is invalid because files already exist for this user" : "Uživatelské jméno není platné, protože protože pro tohoto uživatele už existují soubory", - "User disabled" : "Uživatel zakázán", + "Organisation" : "Organizace", "File is currently busy, please try again later" : "Soubor je nyní používán, zkuste to později", "Cannot download file" : "Soubor se nedaří stáhnout", - "Your data directory is readable by other users." : "Váš adresář data je čitelný ostatním uživatelům.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Změňte práva na 0770, aby obsah adresáře nemohl být vypisován ostatními uživateli.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Ověřte, že v kořeni datového adresáře je soubor s názvem „.ocdata“." + "Login is too long" : "Přihlašovací jméno je příliš dlouhé" },"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;" }
\ No newline at end of file diff --git a/lib/l10n/cy_GB.js b/lib/l10n/cy_GB.js index 89fa749ccab..f6b0f73ef0a 100644 --- a/lib/l10n/cy_GB.js +++ b/lib/l10n/cy_GB.js @@ -16,7 +16,6 @@ OC.L10N.register( "Address" : "Cyfeiriad", "About" : "Ynghylch", "Set an admin password." : "Gosod cyfrinair y gweinyddwr.", - "Click the button below to open it." : "Cliciwch ar y botwm isod i'w agor.", "%1$s via %2$s" : "%1$s trwy %2$s", "Could not find category \"%s\"" : "Methu canfod categori \"%s\"", "Sunday" : "Sul", @@ -61,12 +60,6 @@ OC.L10N.register( "Authentication error" : "Gwall dilysu", "Token expired. Please reload page." : "Tocyn wedi dod i ben. Ail-lwythwch y dudalen.", "Summary" : "Crynodeb", - "Translate" : "Cyfieithu", - "Help" : "Cymorth", - "Users" : "Defnyddwyr", - "Oracle username and/or password not valid" : "Enw a/neu gyfrinair Oracle annilys", - "PostgreSQL username and/or password not valid" : "Enw a/neu gyfrinair PostgreSQL annilys", - "Set an admin username." : "Creu enw defnyddiwr i'r gweinyddwr.", - "Open »%s«" : "Agor »%s«" + "Translate" : "Cyfieithu" }, "nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;"); diff --git a/lib/l10n/cy_GB.json b/lib/l10n/cy_GB.json index 0fed3ff343b..d3ba0eeaa82 100644 --- a/lib/l10n/cy_GB.json +++ b/lib/l10n/cy_GB.json @@ -14,7 +14,6 @@ "Address" : "Cyfeiriad", "About" : "Ynghylch", "Set an admin password." : "Gosod cyfrinair y gweinyddwr.", - "Click the button below to open it." : "Cliciwch ar y botwm isod i'w agor.", "%1$s via %2$s" : "%1$s trwy %2$s", "Could not find category \"%s\"" : "Methu canfod categori \"%s\"", "Sunday" : "Sul", @@ -59,12 +58,6 @@ "Authentication error" : "Gwall dilysu", "Token expired. Please reload page." : "Tocyn wedi dod i ben. Ail-lwythwch y dudalen.", "Summary" : "Crynodeb", - "Translate" : "Cyfieithu", - "Help" : "Cymorth", - "Users" : "Defnyddwyr", - "Oracle username and/or password not valid" : "Enw a/neu gyfrinair Oracle annilys", - "PostgreSQL username and/or password not valid" : "Enw a/neu gyfrinair PostgreSQL annilys", - "Set an admin username." : "Creu enw defnyddiwr i'r gweinyddwr.", - "Open »%s«" : "Agor »%s«" + "Translate" : "Cyfieithu" },"pluralForm" :"nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;" }
\ No newline at end of file diff --git a/lib/l10n/da.js b/lib/l10n/da.js index b1a85451904..a53f04ac4c9 100644 --- a/lib/l10n/da.js +++ b/lib/l10n/da.js @@ -19,9 +19,11 @@ OC.L10N.register( "%1$s, %2$s and %3$s" : "%1$s, %2$s og %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s og %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s og %5$s", + "Education bundle" : "Uddannelsespakke", "Enterprise bundle" : "Enterprise version", "Groupware bundle" : "Groupware version", "Hub bundle" : "Hub version", + "Public sector bundle" : "Offentlig sektor pakke", "Social sharing bundle" : "SoMe delings version", "PHP %s or higher is required." : "Der kræves PHP %s eller nyere.", "PHP with a version lower than %s is required." : "Der kræves PHP %s eller ældre.", @@ -35,6 +37,10 @@ OC.L10N.register( "The following platforms are supported: %s" : "Følgende platforme understøttes: %s", "Server version %s or higher is required." : "Du skal have server version %s eller nyere.", "Server version %s or lower is required." : "Du skal have server version %s eller ældre.", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "En konto, der er logget på, skal være administrator, underadministrator eller have en særlig rettighed for at få adgang til denne indstilling", + "Your current IP address doesn't allow you to perform admin actions" : "Din nuværende IP-adresse tillader dig ikke at udføre administratorhandlinger", + "Logged in account must be an admin or sub admin" : "Kontoen, der er logget på, skal være en administrator eller underadministrator", + "Logged in account must be an admin" : "Kontoen, der er logget på, skal være en admin", "Wiping of device %s has started" : "Komplet sletning af enhed %s er påbegyndt", "Wiping of device »%s« has started" : "Komplet sletning af enhed »%s« er påbegyndt", "»%s« started remote wipe" : "Fjernsletning påbegyndt af »%s« ", @@ -53,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Avatar billedet er ikke kvadratisk", "Files" : "Filer", "View profile" : "Vis profil", + "same time" : "samme tid", + "_%nh_::_%nh_" : ["%nt","%nt"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s foran", + "%s behind" : "%s bagud", "Local time: %s" : "Lokal tid: %s", "today" : "i dag", "tomorrow" : "i morgen", @@ -75,21 +86,44 @@ OC.L10N.register( "seconds ago" : "få sekunder siden", "Empty file" : "Tom fil", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulet med ID: %s eksisterer ikke. Aktiver det venligst i dine indstillinger eller kontakt din administrator.", + "No file conversion providers available" : "Ingen filkonverteringsudbydere tilgængelige", + "File is too large to convert" : "Filen er for stor til at konvertere", + "Destination does not match conversion extension" : "Destinationen matcher ikke konverteringsudvidelsen", + "Could not convert file" : "Kunne ikke konvertere filen", + "Destination does not exist" : "Placeringen findes ikke", + "Destination is not creatable" : "Placeringen kan ikke oprettes", "Dot files are not allowed" : "Filer med punktummer er ikke tilladt", + "\"%1$s\" is a forbidden file or folder name." : "\" %1$s\" er et forbudt fil- eller mappenavn.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\" %1$s\" er et forbudt præfiks for fil- eller mappenavne.", + "\"%1$s\" is not allowed inside a file or folder name." : "\" %1$s\" er ikke tilladt inde i et fil- eller mappenavn.", + "\"%1$s\" is a forbidden file type." : "\" %1$s\" er en forbudt filtype.", + "Filenames must not end with \"%1$s\"." : "Filnavne må ikke ende på \"%1$s\".", + "Invalid parent path" : "Ugyldig overordnet sti", "File already exists" : "Filen findes allerede", "Invalid path" : "Ugyldig sti", "Failed to create file from template" : "Fejl ved oprettelse af fil fra skabelon", "Templates" : "Skabeloner", - "Filename contains at least one invalid character" : "Filnavnet indeholder mindst ét ugyldigt tegn", + "Storage %s cannot be moved" : "Lager %s kan ikke flyttes", + "Moving a share (%s) into a shared folder is not allowed" : "Flytning af en deling (%s) til en delt mappe er ikke tilladt", + "Moving a storage (%s) into a shared folder is not allowed" : "Flytning af et lager (%s) til en delt mappe er ikke tilladt", + "Moving a share (%s) into another share (%s) is not allowed" : "Flytning af en deling (%s) til en anden deling (%s) er ikke tilladt", + "Moving a share (%s) into another storage (%s) is not allowed" : "Flytning af en deling (%s) til et andet lager (%s) er ikke tilladt", + "Moving a storage (%s) into a share (%s) is not allowed" : "Flytning af et lager (%s) til en deling (%s) er ikke tilladt", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Flytning af et lager (%s) til et andet lager (%s) er ikke tilladt", + "Path contains invalid segments" : "Sti indeholder ugyldige segmenter", + "Filename is a reserved word" : "Filnavn er et reserveret ord", + "Filename contains at least one invalid character" : "Filnavnet indeholder mindst et ugyldigt tegn", + "Filename is too long" : "Filnavn er for langt", "Empty filename is not allowed" : "Tomme filnavne er ikke tilladt", "App \"%s\" cannot be installed because appinfo file cannot be read." : "Appen \"%s\" kan ikke installeres fordi appinfo filen ikke kan læses.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Appen \"%s\" kan ikke installeres fordi den ikke er kompatibel med denne version af serveren.", "__language_name__" : "Dansk", "This is an automatically sent email, please do not reply." : "Dette er en automatisk sendt e-mail, svar venligst ikke.", + "Help & privacy" : "Hjælp & privatliv", "Appearance and accessibility" : "Udseende og tilgængelighed", "Apps" : "Apps", "Personal settings" : "Personlige indstillinger", - "Administration settings" : "System indstillinger", + "Administration settings" : "Systemindstillinger", "Settings" : "Indstillinger", "Log out" : "Log ud", "Accounts" : "Konti", @@ -108,39 +142,85 @@ OC.L10N.register( "About" : "Om", "Display name" : "Vist navn", "Headline" : "Overskrift", - "Organisation" : "Organisation", + "Organization" : "Organisation", "Role" : "Rolle", + "Pronouns" : "Pronominer", "Unknown account" : "Ukendt konto", "Additional settings" : "Yderligere indstillinger", "Enter the database Login and name for %s" : "Indtast database Login og navn for %s", "Enter the database Login for %s" : "Indtast database Login for %s", "Enter the database name for %s" : "Indtast databasenavnet for %s", "You cannot use dots in the database name %s" : "Du må ikke bruge punktummer i databasenavnet %s", - "MySQL Login and/or password not valid" : "MySQL Login og/eller password ikke ikke gyldigt", + "MySQL Login and/or password not valid" : "MySQL login og/eller adgangskode ikke ikke gyldig", "You need to enter details of an existing account." : "Du skal indtaste detaljerne for en eksisterende konto.", "Oracle connection could not be established" : "Oracle forbindelsen kunne ikke etableres", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X understøttes ikke og %s vil ikke virke optimalt på denne platform. Anvend på eget ansvar!", + "Oracle Login and/or password not valid" : "Oracle login og / eller adgangskode ikke gyldig", + "PostgreSQL Login and/or password not valid" : "PostgreSQL login og / eller adgangskode ikke gyldig", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X understøttes ikke, og %s vil ikke fungere korrekt på denne platform. Brug det på eget ansvar!", "For the best results, please consider using a GNU/Linux server instead." : "For de bedste resultater, overvej venligst at bruge en GNU/Linux-server i stedet.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Det ser ud til, at denne %s-instans kører på et 32-bit PHP-miljø, samt at open_basedir er blevet konfigureret gennem php.ini. Dette vil føre til problemer med filer som er større end 4GB, og frarådes kraftigt.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Fjern venligst indstillingen for open_basedir inde i din php.ini eller skift til 64-bit PHP.", + "Set an admin Login." : "Sæt et admin login.", "Set an admin password." : "Angiv et admin kodeord.", "Cannot create or write into the data directory %s" : "Kan ikke oprette eller skrive ind i datamappen %s", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Delingsbackend'en %s skal implementere grænsefladen OCP\\Share_Backend", "Sharing backend %s not found" : "Delingsbackend'en %s blev ikke fundet", "Sharing backend for %s not found" : "Delingsbackend'en for %s blev ikke fundet", - "Click the button below to open it." : "Klik på knappen nedenunder for at åbne.", + "%1$s shared %2$s with you" : " %1$s delte %2$s med dig", + "Open %s" : "Åbn %s", "%1$s via %2$s" : "%1$s via %2$s", + "%1$s shared %2$s with you and wants to add:" : " %1$s delte %2$s med dig og ønsker at tilføje:", + "%1$s shared %2$s with you and wants to add" : " %1$s delte %2$s med dig og ønsker at tilføje", + "%s added a note to a file shared with you" : "%s tilføjede en note til en fil delt med dig", + "Passwords are enforced for link and mail shares" : "Adgangskoder gennemtvinges for link og mail delinger", + "Share recipient is not a valid user" : "Delingsmodtager er ikke en gyldig bruger", + "Share recipient is not a valid group" : "Delingsmodtager er ikke en gyldig gruppe", + "Share recipient should be empty" : "Delingsmodtager skal være tom", + "Share recipient should not be empty" : "Delingsmodtager bør ikke være tom", + "Share recipient is not a valid circle" : "Delingsmodtager er ikke en gyldig cirkel", "Unknown share type" : "Ukendt deletype", + "Share initiator must be set" : "Delingsstarteren skal angives", + "Cannot share with yourself" : "Kan ikke dele med dig selv", + "Shared path must be set" : "Delingssti skal indstilles", + "Shared path must be either a file or a folder" : "Delt sti skal enten være en fil eller en mappe", + "You cannot share your root folder" : "Du kan ikke dele din rodmappe", "You are not allowed to share %s" : "Du har ikke tilladelse til at dele %s", + "Valid permissions are required for sharing" : "Gyldige tilladelser er nødvendige for deling", + "File shares cannot have create or delete permissions" : "Fildelinger kan ikke have oprettelses- eller sletningsrettigheder", "Cannot increase permissions of %s" : "Kan give yderigere rettigheder til %s", + "Shares need at least read permissions" : "Deling skal i det mindste have læsetilladelse", "Files cannot be shared with delete permissions" : "Filer kan ikke deles med rettigheder til at slette", "Files cannot be shared with create permissions" : "Filer kan ikke deles med rettigheder til at oprette", "Expiration date is in the past" : "Udløbsdatoen ligger tilbage i tid", + "Expiration date is enforced" : "Udløbsdato gennemtvinges:", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Udløbsdato kan ikke sættes mere end %n dag ud i fremtiden","Udløbsdato kan ikke sættes mere end %n dage ud i fremtiden"], "Sharing is only allowed with group members" : "Deling er kun tilladt med gruppemedlemmer", + "Sharing %s failed, because this item is already shared with the account %s" : "Deling af %s mislykkedes, fordi dette element allerede er delt med kontoen %s", + "Group sharing is now allowed" : "Gruppedeling er nu tilladt", + "Sharing is only allowed within your own groups" : "Deling er kun tilladt i dine egne grupper", + "Path is already shared with this group" : "Sti deles allerede med denne gruppe", + "Link sharing is not allowed" : "Link deling er ikke tilladt", + "Public upload is not allowed" : "Offentlig upload er ikke tilladt", + "You cannot share a folder that contains other shares" : "Du kan ikke dele en mappe, der indeholder andre delinger", + "Sharing is disabled" : "Deling er deaktiveret", + "Sharing is disabled for you" : "Deling er deaktiveret for dig", + "Cannot share with the share owner" : "Kan ikke dele med delingsejeren", + "Share does not have a full ID" : "Deling har ikke et fuldt ID", + "Cannot change share type" : "Kan ikke ændre delingstype", + "Can only update recipient on user shares" : "Kan kun opdatere modtager på brugerdelinger", + "Cannot enable sending the password by Talk with an empty password" : "Kan ikke aktivere afsendelse af adgangskode via Snak med en tom adgangskode", + "Cannot enable sending the password by Talk without setting a new password" : "Kan ikke aktivere afsendelse af adgangskoden via Snak uden at angive en ny adgangskode", + "Cannot disable sending the password by Talk without setting a new password" : "Kan ikke deaktivere afsendelse af adgangskode via Snak uden at angive en ny adgangskode", + "Share provider does not support accepting" : "Delingsleverandør understøtter ikke accept", + "Cannot change target of link share" : "Kan ikke ændre mål for link deling", + "Invalid share recipient" : "Ugyldig delingsmodtager", + "Group \"%s\" does not exist" : "Gruppe \"%s\" eksisterer ikke", "The requested share does not exist anymore" : "Det delte emne eksisterer ikke længere", + "The requested share comes from a disabled user" : "Den ønskede deling kommer fra en deaktiveret bruger", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Brugeren blev ikke oprettet, fordi brugergrænsen er nået. Tjek dine notifikationer for at få flere oplysninger.", "Could not find category \"%s\"" : "Kunne ikke finde kategorien \"%s\"", + "Input text" : "Inputtekst", + "The input text" : "Inputteksten", "Sunday" : "Søndag", "Monday" : "Mandag", "Tuesday" : "Tirsdag", @@ -187,6 +267,14 @@ OC.L10N.register( "Nov." : "Nov.", "Dec." : "Dec.", "A valid password must be provided" : "En gyldig adgangskode skal angives", + "The Login is already being used" : "Login anvendes allerede", + "Could not create account" : "Kunne ikke oprette konto", + "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kun følgende tegn er tilladt i et login: \"a-z\", \"A-Z\", \"0-9\", mellemrum og \"_. @ -\"", + "A valid Login must be provided" : "Et gyldigt login skal angives", + "Login contains whitespace at the beginning or at the end" : "Login indeholder mellemrum i begyndelsen eller slutningen", + "Login must not consist of dots only" : "Login må ikke kun bestå af prikker", + "Login is invalid because files already exist for this user" : "Login er ugyldigt, fordi filer allerede eksisterer for denne bruger", + "Account disabled" : "Konto deaktiveret", "Login canceled by app" : "Login annulleret af app", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Appen \"%1$s\" kan ikke installeres, da følgende afhængigheder ikke imødekommes: %2$s", "a safe home for all your data" : "et sikkert hjem til alle dine data", @@ -204,7 +292,7 @@ OC.L10N.register( "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Rettigheder kan som regel rettes ved at give webserveren skriveadgang til rodmappen. Se %s.", "Your data directory is not writable." : "Data biblioteket er skrivebeskyttet.", "Setting locale to %s failed." : "Angivelse af %s for lokalitet mislykkedes.", - "Please install one of these locales on your system and restart your web server." : "Installér venligst én af disse lokaliteter på dit system, og genstart din webserver.", + "Please install one of these locales on your system and restart your web server." : "Installer venligst en af disse lokaliteter på dit system, og genstart din webserver.", "PHP module %s not installed." : "PHP-modulet %s er ikke installeret.", "Please ask your server administrator to install the module." : "Du bedes anmode din serveradministrator om at installere modulet.", "PHP setting \"%s\" is not set to \"%s\"." : "PHP-indstillingen \"%s\" er ikke angivet til \"%s\".", @@ -217,14 +305,17 @@ OC.L10N.register( "Please ask your server administrator to restart the web server." : "Du bedes anmode din serveradministrator om at genstarte webserveren.", "The required %s config variable is not configured in the config.php file." : "Den krævede config variabel %s er ikke konfigureret i config.php filen.", "Please ask your server administrator to check the Nextcloud configuration." : "Du bedes anmode din serveradministrator om at kontrollere Nextcloud konfigurationen.", + "Your data directory is readable by other people." : "Din datamappe kan læses af andre.", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Ændr rettighederne til 0770, så mappen ikke kan listes af andre personer.", "Your data directory must be an absolute path." : "Datamappen skal have en absolut sti.", "Check the value of \"datadirectory\" in your configuration." : "Tjek værdien for \"datadictionary\" i din konfiguration.", "Your data directory is invalid." : "Datamappen er ugyldig.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Sørg for at der er en fil kaldet \" %1$s\" i roden af datafilen. Den bør have indholdet: \" %2$s\"", "Action \"%s\" not supported or implemented." : "Aktiviteten \"%s\" er ikke understøttet eller implementeret.", "Authentication failed, wrong token or provider ID given" : "Kunne ikke validere brugeren", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Anmodningen kunne ikke gennemføres pga. manglende parameter: \"%s\"", - "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "ID \"%1$s\" er allerede i brug af cloud federation provider \"%2$s\"", - "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud Federation Provider med ID: \"%s\" eksisterer ikke.", + "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "ID \"%1$s\" already used by cloud sammenkoblingsleverandør \"%2$s\"", + "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud sammenkoblingsleverandør med ID: \"%s\" eksisterer ikke.", "Could not obtain lock type %d on \"%s\"." : "Kunne ikke opnå en låsetype %d på \"%s\".", "Storage unauthorized. %s" : "Lageret er ikke autoriseret. %s", "Storage incomplete configuration. %s" : "Lageret er ikke konfigureret korrekt. %s", @@ -232,54 +323,128 @@ OC.L10N.register( "Storage is temporarily not available" : "Lagerplads er midlertidigt ikke tilgængeligt", "Storage connection timeout. %s" : "Lageret svarer ikke. %s", "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "For at tillade at denne kontrol køres så skal du sikre dig at din webserver kan forbinde til sig selv. Derfor skal den kunne opløse og forbinde til mindst en af dets `trusted_domains` eller `overwrite.cli.url`. Denne fejl kan være resultatet af en server-side DNS mismatch eller udadgående firewall regel.", + "Transcribe audio" : "Transskriber lyd", + "Transcribe the things said in an audio" : "Transskriber de ting, der siges i en lydfil", + "Audio input" : "Lydinput", + "The audio to transcribe" : "Lyden der skal transskriberes", + "Transcription" : "Transskription", + "The transcribed text" : "Den transskriberede tekst", + "Chat with an agent" : "Chat med en agent", + "Chat message" : "Chatbeskeder", + "A chat message to send to the agent." : "En chatbesked til agenten.", "Confirmation" : "Bekræftelse", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Om tidligere forespurgte handlinger skal bekræftes: 0 for nægtelse og 1 for bekræftelse.", + "Conversation token" : "Samtaletoken", + "A token representing the conversation." : "Et token, som repræsenterer samtalen.", + "Generated response" : "Genereret respons", + "The response from the chat model." : "Svaret fra chatmodellen.", + "The new conversation token" : "Det nye samtaletoken", + "Send this along with the next interaction." : "Send dette sammen med den næste interaktion.", + "Requested actions by the agent" : "Krævede handlinger af agenten", + "Actions that the agent would like to carry out in JSON format." : "Handlinger, som agenten gerne vil udføre i JSON-format.", + "Context write" : "Kontekstskrivning", + "Writes text in a given style based on the provided source material." : "Skriver tekst i en given stil baseret på det medfølgende kildemateriale.", + "Writing style" : "Skrivestil", + "Demonstrate a writing style that you would like to immitate" : "Demonstrer en skrivestil, som du gerne vil efterligne", + "Source material" : "Kildemateriale", + "The content that would like to be rewritten in the new writing style" : "Indhold som skal genskrives i den nye skrivestil", + "Generated text" : "Genereret tekst", + "The generated text with content from the source material in the given style" : "Den genererede tekst med indhold fra kildematerialet i den givne stil", + "Emoji generator" : "Emoji generator", + "Takes text and generates a representative emoji for it." : "Tager tekst og genererer en repræsentativ emoji for det.", + "The text to generate an emoji for" : "Teksten der skal genereres en emoji for", + "Generated emoji" : "Genereret emoji", + "The generated emoji based on the input text" : "Den genererede emoji baseret på inputteksten", + "Generate image" : "Generer billede", + "Generate an image from a text prompt" : "Generer et billede fra en tekstprompt", + "Prompt" : "Prompt", + "Describe the image you want to generate" : "Beskriv det billede du vil generere", + "Number of images" : "Antal billeder", + "How many images to generate" : "Hvor mange billeder skal genereres", + "Output images" : "Output billeder", + "The generated images" : "De genererede billeder", + "Free text to text prompt" : "Fritekst til tekstprompt", + "Runs an arbitrary prompt through a language model that returns a reply" : "Kører en vilkårlig prompt gennem en sprogmodel, der returnerer et svar", + "Describe a task that you want the assistant to do or ask a question" : "Beskriv en opgave, som du ønsker at assistenten udføre eller stil et spørgsmål", + "Generated reply" : "Genereret svar", + "The generated text from the assistant" : "Den genererede tekst fra assistenten", + "Change Tone" : "Ændr tone", + "Change the tone of a piece of text." : "Ændre tonen i et stykke tekst.", + "Write a text that you want the assistant to rewrite in another tone." : "Skriv en tekst, som assistenten skal skrive i en anden tone.", + "Desired tone" : "Ønsket tone", + "In which tone should your text be rewritten?" : "I hvilken tone skal din tekst omskrives?", + "The rewritten text in the desired tone, written by the assistant:" : "Den omskrevne tekst i den ønskede tone, skrevet af assistenten:", "Chat" : "cHAT", + "Chat with the assistant" : "Chat med assistent", + "System prompt" : "Systemprompt", + "Define rules and assumptions that the assistant should follow during the conversation." : "Definer regler og antagelser, som assistenten skal følge under samtalen.", + "Chat history" : "Chathistorik", + "The history of chat messages before the current message, starting with a message by the user" : "Historikken for chatbeskeder før den aktuelle besked, startende med en besked fra brugeren", + "Response message" : "Svarmeddelelse", + "The generated response as part of the conversation" : "Det genererede svar som en del af samtalen", + "Chat with tools" : "Chat med værktøjer", + "Chat with the language model with tool calling support." : "Chat med sprogmodellen med værktøj opkaldsunderstøttelse.", + "Tool message" : "Værktøjsbesked", + "The result of tool calls in the last interaction" : "Resultatet af værktøjsopkald i den sidste interaktion", + "Available tools" : "Tilgængelige værktøjer", + "The available tools in JSON format" : "De tilgængelige værktøjer i JSON format", + "The response from the chat model" : "Svaret fra chatmodellen", + "Tool calls" : "Værktøjsopkald", + "Tools call instructions from the model in JSON format" : "Værktøjsopkald instruktioner fra modellen i JSON format", + "Formalize text" : "Formaliser tekst", + "Takes a text and makes it sound more formal" : "Anvender en tekst og får det til at lyde mere formelt", + "Write a text that you want the assistant to formalize" : "Skriv en tekst som du vil have assistenten til at formalisere", + "Formalized text" : "Formaliseret tekst", + "The formalized text" : "Den formaliserede tekst", + "Generate a headline" : "Generer en overskrift", "Generates a possible headline for a text." : "Genererer en mulig overskrift til en tekst.", + "Original text" : "Oprindelig tekst", + "The original text to generate a headline for" : "Den oprindelige tekst til at generere en overskrift for", + "The generated headline" : "Den genererede overskrift", + "Proofread" : "Korrekturlæsning", + "Proofreads a text and lists corrections" : "Korrekturlæser en tekst og lister rettelser", + "Text" : "Tekst", + "The text to proofread" : "Teksten til korrekturlæsning", + "Corrections" : "Rettelser", + "The corrections that should be made in your text" : "De rettelser, der skal foretages i din tekst", + "Reformulate text" : "Omformuler tekst", + "Takes a text and reformulates it" : "Anvender en tekst og omformulerer den", + "Write a text that you want the assistant to reformulate" : "Skriv en tekst som du vil have assistenten til at omformulere", + "Reformulated text" : "Omformuleret tekst", + "The reformulated text, written by the assistant" : "Den omformulerede tekst, skrevet af assistenten", + "Simplify text" : "Forenkel tekst", + "Takes a text and simplifies it" : "Anvender en tekst og forenkler den", + "Write a text that you want the assistant to simplify" : "Skriv en tekst, som du vil have assistenten til at forenkle", + "Simplified text" : "Forenklet tekst", + "The simplified text" : "Den forenklede tekst", "Summarize" : "Opsummer", + "Summarizes a text" : "Sammenfatter en tekst", + "The original text to summarize" : "Den oprindelige tekst der skal sammenfattes", "Summary" : "Oversigt", + "The generated summary" : "Det genererede sammendrag", "Extract topics" : "Uddrag emner", + "Extracts topics from a text and outputs them separated by commas" : "Udtrækker emner fra en tekst og udskriver dem adskilt af kommaer", + "The original text to extract topics from" : "Den oprindelige tekst til at udtrække emner fra", + "Topics" : "Emner", + "The list of extracted topics" : "Listen over udtrukne emner", "Translate" : "Oversæt", + "Translate text from one language to another" : "Oversæt tekst fra et sprog til et andet", + "Origin text" : "Oprindelig tekst", + "The text to translate" : "Teksten der skal oversættes", + "Origin language" : "Oprindelsessprog", + "The language of the origin text" : "Det sprog, der anvendes i oprindelsesteksten", + "Target language" : "Målsprog", + "The desired language to translate the origin text in" : "Det ønskede sprog som oprindelsesteksten skal oversættes til", "Result" : "Resultat", + "The translated text" : "Den oversatte tekst", "Free prompt" : "Gratis prompt", "Runs an arbitrary prompt through the language model." : "Kører en arbitrær prompt gennem sprogmodellen.", "Generate headline" : "Generer overskrift", "Summarizes text by reducing its length without losing key information." : "Opsummerer tekst ved at reducere dens længde uden at miste nøgleinformation.", "Extracts topics from a text and outputs them separated by commas." : "Uddrager emner fra en tekst og skriver dem adskilt af kommaer.", - "Education Edition" : "Uddanelses Version", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Bruger skal være administrator, underadministrator eller have tildelt specielle rettigheder for at have adgang til denne indstilling", - "Logged in user must be an admin or sub admin" : "Bruger skal være administrator eller underadministrator", - "Logged in user must be an admin" : "Brugeren skal være administrator", - "File name is a reserved word" : "Filnavnet er et reserveret ord", - "File name contains at least one invalid character" : "Filnavnet indeholder mindst ét ugyldigt tegn", - "File name is too long" : "Filnavnet er for langt", - "Help" : "Hjælp", - "Users" : "Brugere", - "Unknown user" : "Ukendt bruger", - "Enter the database username and name for %s" : "Indtast navn til databasen og brugernavn for %s", - "Enter the database username for %s" : "Indtast brugernavn til databasen for %s", - "MySQL username and/or password not valid" : "MySQL brugernavn og/eller kodeord er ikke gyldigt", - "Oracle username and/or password not valid" : "Oracle brugernavn og/eller kodeord er ikke gyldigt.", - "PostgreSQL username and/or password not valid" : "PostgreSQL brugernavn og/eller kodeord er ikke gyldigt.", - "Set an admin username." : "Angiv et admin brugernavn.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s delte »%2$s« med dig og vil gerne tilføje:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s delte »%2$s« med dig og vil gerne tilføje", - "»%s« added a note to a file shared with you" : "»%s« tilføjede en note til en fil delt med dig", - "Open »%s«" : "Åbn »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Deling af %s mislykkedes, fordi dette element allerede er delt med brugeren %s", - "%1$s shared »%2$s« with you" : "%1$s delte »%2$s« med dig", - "%1$s shared »%2$s« with you." : "%1$s delte »%2$s« med dig", - "The username is already being used" : "Brugernavnet er allerede i brug", - "Could not create user" : "Kunne ikke oprette bruger", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kun følgende tegn kan indgå i et brugernavn: \"a-z\", \"A-Z\", \"0-9\", mellemrum and \"_.@-'\"", - "A valid username must be provided" : "Et gyldigt brugernavn skal angives", - "Username contains whitespace at the beginning or at the end" : "Brugernavnet har et mellemrum i starten eller slutningen", - "Username must not consist of dots only" : "Brugernavnet må ikke bestå af rene prikker/punktummer", - "Username is invalid because files already exist for this user" : "Brugernavnet er ugyldigt, da der allerede eksisterer filer for denne bruger", - "User disabled" : "Bruger deaktiveret", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "Filen er i øjeblikket optaget - forsøg igen senere", "Cannot download file" : "Kan ikke downloade filen", - "Your data directory is readable by other users." : "Datamappen kan læses af andre brugere.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Tilpas venligst rettigheder til 0770, så mappen ikke fremvises for andre brugere.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Du bedes sikre at filen \".ocdata\" befinder sig i roden af din datamappe." + "Login is too long" : "Login er for lang" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/da.json b/lib/l10n/da.json index 0566e3d38c8..e8163581e60 100644 --- a/lib/l10n/da.json +++ b/lib/l10n/da.json @@ -17,9 +17,11 @@ "%1$s, %2$s and %3$s" : "%1$s, %2$s og %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s og %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s og %5$s", + "Education bundle" : "Uddannelsespakke", "Enterprise bundle" : "Enterprise version", "Groupware bundle" : "Groupware version", "Hub bundle" : "Hub version", + "Public sector bundle" : "Offentlig sektor pakke", "Social sharing bundle" : "SoMe delings version", "PHP %s or higher is required." : "Der kræves PHP %s eller nyere.", "PHP with a version lower than %s is required." : "Der kræves PHP %s eller ældre.", @@ -33,6 +35,10 @@ "The following platforms are supported: %s" : "Følgende platforme understøttes: %s", "Server version %s or higher is required." : "Du skal have server version %s eller nyere.", "Server version %s or lower is required." : "Du skal have server version %s eller ældre.", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "En konto, der er logget på, skal være administrator, underadministrator eller have en særlig rettighed for at få adgang til denne indstilling", + "Your current IP address doesn't allow you to perform admin actions" : "Din nuværende IP-adresse tillader dig ikke at udføre administratorhandlinger", + "Logged in account must be an admin or sub admin" : "Kontoen, der er logget på, skal være en administrator eller underadministrator", + "Logged in account must be an admin" : "Kontoen, der er logget på, skal være en admin", "Wiping of device %s has started" : "Komplet sletning af enhed %s er påbegyndt", "Wiping of device »%s« has started" : "Komplet sletning af enhed »%s« er påbegyndt", "»%s« started remote wipe" : "Fjernsletning påbegyndt af »%s« ", @@ -51,6 +57,11 @@ "Avatar image is not square" : "Avatar billedet er ikke kvadratisk", "Files" : "Filer", "View profile" : "Vis profil", + "same time" : "samme tid", + "_%nh_::_%nh_" : ["%nt","%nt"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s foran", + "%s behind" : "%s bagud", "Local time: %s" : "Lokal tid: %s", "today" : "i dag", "tomorrow" : "i morgen", @@ -73,21 +84,44 @@ "seconds ago" : "få sekunder siden", "Empty file" : "Tom fil", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulet med ID: %s eksisterer ikke. Aktiver det venligst i dine indstillinger eller kontakt din administrator.", + "No file conversion providers available" : "Ingen filkonverteringsudbydere tilgængelige", + "File is too large to convert" : "Filen er for stor til at konvertere", + "Destination does not match conversion extension" : "Destinationen matcher ikke konverteringsudvidelsen", + "Could not convert file" : "Kunne ikke konvertere filen", + "Destination does not exist" : "Placeringen findes ikke", + "Destination is not creatable" : "Placeringen kan ikke oprettes", "Dot files are not allowed" : "Filer med punktummer er ikke tilladt", + "\"%1$s\" is a forbidden file or folder name." : "\" %1$s\" er et forbudt fil- eller mappenavn.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\" %1$s\" er et forbudt præfiks for fil- eller mappenavne.", + "\"%1$s\" is not allowed inside a file or folder name." : "\" %1$s\" er ikke tilladt inde i et fil- eller mappenavn.", + "\"%1$s\" is a forbidden file type." : "\" %1$s\" er en forbudt filtype.", + "Filenames must not end with \"%1$s\"." : "Filnavne må ikke ende på \"%1$s\".", + "Invalid parent path" : "Ugyldig overordnet sti", "File already exists" : "Filen findes allerede", "Invalid path" : "Ugyldig sti", "Failed to create file from template" : "Fejl ved oprettelse af fil fra skabelon", "Templates" : "Skabeloner", - "Filename contains at least one invalid character" : "Filnavnet indeholder mindst ét ugyldigt tegn", + "Storage %s cannot be moved" : "Lager %s kan ikke flyttes", + "Moving a share (%s) into a shared folder is not allowed" : "Flytning af en deling (%s) til en delt mappe er ikke tilladt", + "Moving a storage (%s) into a shared folder is not allowed" : "Flytning af et lager (%s) til en delt mappe er ikke tilladt", + "Moving a share (%s) into another share (%s) is not allowed" : "Flytning af en deling (%s) til en anden deling (%s) er ikke tilladt", + "Moving a share (%s) into another storage (%s) is not allowed" : "Flytning af en deling (%s) til et andet lager (%s) er ikke tilladt", + "Moving a storage (%s) into a share (%s) is not allowed" : "Flytning af et lager (%s) til en deling (%s) er ikke tilladt", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Flytning af et lager (%s) til et andet lager (%s) er ikke tilladt", + "Path contains invalid segments" : "Sti indeholder ugyldige segmenter", + "Filename is a reserved word" : "Filnavn er et reserveret ord", + "Filename contains at least one invalid character" : "Filnavnet indeholder mindst et ugyldigt tegn", + "Filename is too long" : "Filnavn er for langt", "Empty filename is not allowed" : "Tomme filnavne er ikke tilladt", "App \"%s\" cannot be installed because appinfo file cannot be read." : "Appen \"%s\" kan ikke installeres fordi appinfo filen ikke kan læses.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Appen \"%s\" kan ikke installeres fordi den ikke er kompatibel med denne version af serveren.", "__language_name__" : "Dansk", "This is an automatically sent email, please do not reply." : "Dette er en automatisk sendt e-mail, svar venligst ikke.", + "Help & privacy" : "Hjælp & privatliv", "Appearance and accessibility" : "Udseende og tilgængelighed", "Apps" : "Apps", "Personal settings" : "Personlige indstillinger", - "Administration settings" : "System indstillinger", + "Administration settings" : "Systemindstillinger", "Settings" : "Indstillinger", "Log out" : "Log ud", "Accounts" : "Konti", @@ -106,39 +140,85 @@ "About" : "Om", "Display name" : "Vist navn", "Headline" : "Overskrift", - "Organisation" : "Organisation", + "Organization" : "Organisation", "Role" : "Rolle", + "Pronouns" : "Pronominer", "Unknown account" : "Ukendt konto", "Additional settings" : "Yderligere indstillinger", "Enter the database Login and name for %s" : "Indtast database Login og navn for %s", "Enter the database Login for %s" : "Indtast database Login for %s", "Enter the database name for %s" : "Indtast databasenavnet for %s", "You cannot use dots in the database name %s" : "Du må ikke bruge punktummer i databasenavnet %s", - "MySQL Login and/or password not valid" : "MySQL Login og/eller password ikke ikke gyldigt", + "MySQL Login and/or password not valid" : "MySQL login og/eller adgangskode ikke ikke gyldig", "You need to enter details of an existing account." : "Du skal indtaste detaljerne for en eksisterende konto.", "Oracle connection could not be established" : "Oracle forbindelsen kunne ikke etableres", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X understøttes ikke og %s vil ikke virke optimalt på denne platform. Anvend på eget ansvar!", + "Oracle Login and/or password not valid" : "Oracle login og / eller adgangskode ikke gyldig", + "PostgreSQL Login and/or password not valid" : "PostgreSQL login og / eller adgangskode ikke gyldig", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X understøttes ikke, og %s vil ikke fungere korrekt på denne platform. Brug det på eget ansvar!", "For the best results, please consider using a GNU/Linux server instead." : "For de bedste resultater, overvej venligst at bruge en GNU/Linux-server i stedet.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Det ser ud til, at denne %s-instans kører på et 32-bit PHP-miljø, samt at open_basedir er blevet konfigureret gennem php.ini. Dette vil føre til problemer med filer som er større end 4GB, og frarådes kraftigt.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Fjern venligst indstillingen for open_basedir inde i din php.ini eller skift til 64-bit PHP.", + "Set an admin Login." : "Sæt et admin login.", "Set an admin password." : "Angiv et admin kodeord.", "Cannot create or write into the data directory %s" : "Kan ikke oprette eller skrive ind i datamappen %s", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Delingsbackend'en %s skal implementere grænsefladen OCP\\Share_Backend", "Sharing backend %s not found" : "Delingsbackend'en %s blev ikke fundet", "Sharing backend for %s not found" : "Delingsbackend'en for %s blev ikke fundet", - "Click the button below to open it." : "Klik på knappen nedenunder for at åbne.", + "%1$s shared %2$s with you" : " %1$s delte %2$s med dig", + "Open %s" : "Åbn %s", "%1$s via %2$s" : "%1$s via %2$s", + "%1$s shared %2$s with you and wants to add:" : " %1$s delte %2$s med dig og ønsker at tilføje:", + "%1$s shared %2$s with you and wants to add" : " %1$s delte %2$s med dig og ønsker at tilføje", + "%s added a note to a file shared with you" : "%s tilføjede en note til en fil delt med dig", + "Passwords are enforced for link and mail shares" : "Adgangskoder gennemtvinges for link og mail delinger", + "Share recipient is not a valid user" : "Delingsmodtager er ikke en gyldig bruger", + "Share recipient is not a valid group" : "Delingsmodtager er ikke en gyldig gruppe", + "Share recipient should be empty" : "Delingsmodtager skal være tom", + "Share recipient should not be empty" : "Delingsmodtager bør ikke være tom", + "Share recipient is not a valid circle" : "Delingsmodtager er ikke en gyldig cirkel", "Unknown share type" : "Ukendt deletype", + "Share initiator must be set" : "Delingsstarteren skal angives", + "Cannot share with yourself" : "Kan ikke dele med dig selv", + "Shared path must be set" : "Delingssti skal indstilles", + "Shared path must be either a file or a folder" : "Delt sti skal enten være en fil eller en mappe", + "You cannot share your root folder" : "Du kan ikke dele din rodmappe", "You are not allowed to share %s" : "Du har ikke tilladelse til at dele %s", + "Valid permissions are required for sharing" : "Gyldige tilladelser er nødvendige for deling", + "File shares cannot have create or delete permissions" : "Fildelinger kan ikke have oprettelses- eller sletningsrettigheder", "Cannot increase permissions of %s" : "Kan give yderigere rettigheder til %s", + "Shares need at least read permissions" : "Deling skal i det mindste have læsetilladelse", "Files cannot be shared with delete permissions" : "Filer kan ikke deles med rettigheder til at slette", "Files cannot be shared with create permissions" : "Filer kan ikke deles med rettigheder til at oprette", "Expiration date is in the past" : "Udløbsdatoen ligger tilbage i tid", + "Expiration date is enforced" : "Udløbsdato gennemtvinges:", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Udløbsdato kan ikke sættes mere end %n dag ud i fremtiden","Udløbsdato kan ikke sættes mere end %n dage ud i fremtiden"], "Sharing is only allowed with group members" : "Deling er kun tilladt med gruppemedlemmer", + "Sharing %s failed, because this item is already shared with the account %s" : "Deling af %s mislykkedes, fordi dette element allerede er delt med kontoen %s", + "Group sharing is now allowed" : "Gruppedeling er nu tilladt", + "Sharing is only allowed within your own groups" : "Deling er kun tilladt i dine egne grupper", + "Path is already shared with this group" : "Sti deles allerede med denne gruppe", + "Link sharing is not allowed" : "Link deling er ikke tilladt", + "Public upload is not allowed" : "Offentlig upload er ikke tilladt", + "You cannot share a folder that contains other shares" : "Du kan ikke dele en mappe, der indeholder andre delinger", + "Sharing is disabled" : "Deling er deaktiveret", + "Sharing is disabled for you" : "Deling er deaktiveret for dig", + "Cannot share with the share owner" : "Kan ikke dele med delingsejeren", + "Share does not have a full ID" : "Deling har ikke et fuldt ID", + "Cannot change share type" : "Kan ikke ændre delingstype", + "Can only update recipient on user shares" : "Kan kun opdatere modtager på brugerdelinger", + "Cannot enable sending the password by Talk with an empty password" : "Kan ikke aktivere afsendelse af adgangskode via Snak med en tom adgangskode", + "Cannot enable sending the password by Talk without setting a new password" : "Kan ikke aktivere afsendelse af adgangskoden via Snak uden at angive en ny adgangskode", + "Cannot disable sending the password by Talk without setting a new password" : "Kan ikke deaktivere afsendelse af adgangskode via Snak uden at angive en ny adgangskode", + "Share provider does not support accepting" : "Delingsleverandør understøtter ikke accept", + "Cannot change target of link share" : "Kan ikke ændre mål for link deling", + "Invalid share recipient" : "Ugyldig delingsmodtager", + "Group \"%s\" does not exist" : "Gruppe \"%s\" eksisterer ikke", "The requested share does not exist anymore" : "Det delte emne eksisterer ikke længere", + "The requested share comes from a disabled user" : "Den ønskede deling kommer fra en deaktiveret bruger", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Brugeren blev ikke oprettet, fordi brugergrænsen er nået. Tjek dine notifikationer for at få flere oplysninger.", "Could not find category \"%s\"" : "Kunne ikke finde kategorien \"%s\"", + "Input text" : "Inputtekst", + "The input text" : "Inputteksten", "Sunday" : "Søndag", "Monday" : "Mandag", "Tuesday" : "Tirsdag", @@ -185,6 +265,14 @@ "Nov." : "Nov.", "Dec." : "Dec.", "A valid password must be provided" : "En gyldig adgangskode skal angives", + "The Login is already being used" : "Login anvendes allerede", + "Could not create account" : "Kunne ikke oprette konto", + "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kun følgende tegn er tilladt i et login: \"a-z\", \"A-Z\", \"0-9\", mellemrum og \"_. @ -\"", + "A valid Login must be provided" : "Et gyldigt login skal angives", + "Login contains whitespace at the beginning or at the end" : "Login indeholder mellemrum i begyndelsen eller slutningen", + "Login must not consist of dots only" : "Login må ikke kun bestå af prikker", + "Login is invalid because files already exist for this user" : "Login er ugyldigt, fordi filer allerede eksisterer for denne bruger", + "Account disabled" : "Konto deaktiveret", "Login canceled by app" : "Login annulleret af app", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Appen \"%1$s\" kan ikke installeres, da følgende afhængigheder ikke imødekommes: %2$s", "a safe home for all your data" : "et sikkert hjem til alle dine data", @@ -202,7 +290,7 @@ "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Rettigheder kan som regel rettes ved at give webserveren skriveadgang til rodmappen. Se %s.", "Your data directory is not writable." : "Data biblioteket er skrivebeskyttet.", "Setting locale to %s failed." : "Angivelse af %s for lokalitet mislykkedes.", - "Please install one of these locales on your system and restart your web server." : "Installér venligst én af disse lokaliteter på dit system, og genstart din webserver.", + "Please install one of these locales on your system and restart your web server." : "Installer venligst en af disse lokaliteter på dit system, og genstart din webserver.", "PHP module %s not installed." : "PHP-modulet %s er ikke installeret.", "Please ask your server administrator to install the module." : "Du bedes anmode din serveradministrator om at installere modulet.", "PHP setting \"%s\" is not set to \"%s\"." : "PHP-indstillingen \"%s\" er ikke angivet til \"%s\".", @@ -215,14 +303,17 @@ "Please ask your server administrator to restart the web server." : "Du bedes anmode din serveradministrator om at genstarte webserveren.", "The required %s config variable is not configured in the config.php file." : "Den krævede config variabel %s er ikke konfigureret i config.php filen.", "Please ask your server administrator to check the Nextcloud configuration." : "Du bedes anmode din serveradministrator om at kontrollere Nextcloud konfigurationen.", + "Your data directory is readable by other people." : "Din datamappe kan læses af andre.", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Ændr rettighederne til 0770, så mappen ikke kan listes af andre personer.", "Your data directory must be an absolute path." : "Datamappen skal have en absolut sti.", "Check the value of \"datadirectory\" in your configuration." : "Tjek værdien for \"datadictionary\" i din konfiguration.", "Your data directory is invalid." : "Datamappen er ugyldig.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Sørg for at der er en fil kaldet \" %1$s\" i roden af datafilen. Den bør have indholdet: \" %2$s\"", "Action \"%s\" not supported or implemented." : "Aktiviteten \"%s\" er ikke understøttet eller implementeret.", "Authentication failed, wrong token or provider ID given" : "Kunne ikke validere brugeren", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Anmodningen kunne ikke gennemføres pga. manglende parameter: \"%s\"", - "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "ID \"%1$s\" er allerede i brug af cloud federation provider \"%2$s\"", - "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud Federation Provider med ID: \"%s\" eksisterer ikke.", + "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "ID \"%1$s\" already used by cloud sammenkoblingsleverandør \"%2$s\"", + "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud sammenkoblingsleverandør med ID: \"%s\" eksisterer ikke.", "Could not obtain lock type %d on \"%s\"." : "Kunne ikke opnå en låsetype %d på \"%s\".", "Storage unauthorized. %s" : "Lageret er ikke autoriseret. %s", "Storage incomplete configuration. %s" : "Lageret er ikke konfigureret korrekt. %s", @@ -230,54 +321,128 @@ "Storage is temporarily not available" : "Lagerplads er midlertidigt ikke tilgængeligt", "Storage connection timeout. %s" : "Lageret svarer ikke. %s", "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "For at tillade at denne kontrol køres så skal du sikre dig at din webserver kan forbinde til sig selv. Derfor skal den kunne opløse og forbinde til mindst en af dets `trusted_domains` eller `overwrite.cli.url`. Denne fejl kan være resultatet af en server-side DNS mismatch eller udadgående firewall regel.", + "Transcribe audio" : "Transskriber lyd", + "Transcribe the things said in an audio" : "Transskriber de ting, der siges i en lydfil", + "Audio input" : "Lydinput", + "The audio to transcribe" : "Lyden der skal transskriberes", + "Transcription" : "Transskription", + "The transcribed text" : "Den transskriberede tekst", + "Chat with an agent" : "Chat med en agent", + "Chat message" : "Chatbeskeder", + "A chat message to send to the agent." : "En chatbesked til agenten.", "Confirmation" : "Bekræftelse", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Om tidligere forespurgte handlinger skal bekræftes: 0 for nægtelse og 1 for bekræftelse.", + "Conversation token" : "Samtaletoken", + "A token representing the conversation." : "Et token, som repræsenterer samtalen.", + "Generated response" : "Genereret respons", + "The response from the chat model." : "Svaret fra chatmodellen.", + "The new conversation token" : "Det nye samtaletoken", + "Send this along with the next interaction." : "Send dette sammen med den næste interaktion.", + "Requested actions by the agent" : "Krævede handlinger af agenten", + "Actions that the agent would like to carry out in JSON format." : "Handlinger, som agenten gerne vil udføre i JSON-format.", + "Context write" : "Kontekstskrivning", + "Writes text in a given style based on the provided source material." : "Skriver tekst i en given stil baseret på det medfølgende kildemateriale.", + "Writing style" : "Skrivestil", + "Demonstrate a writing style that you would like to immitate" : "Demonstrer en skrivestil, som du gerne vil efterligne", + "Source material" : "Kildemateriale", + "The content that would like to be rewritten in the new writing style" : "Indhold som skal genskrives i den nye skrivestil", + "Generated text" : "Genereret tekst", + "The generated text with content from the source material in the given style" : "Den genererede tekst med indhold fra kildematerialet i den givne stil", + "Emoji generator" : "Emoji generator", + "Takes text and generates a representative emoji for it." : "Tager tekst og genererer en repræsentativ emoji for det.", + "The text to generate an emoji for" : "Teksten der skal genereres en emoji for", + "Generated emoji" : "Genereret emoji", + "The generated emoji based on the input text" : "Den genererede emoji baseret på inputteksten", + "Generate image" : "Generer billede", + "Generate an image from a text prompt" : "Generer et billede fra en tekstprompt", + "Prompt" : "Prompt", + "Describe the image you want to generate" : "Beskriv det billede du vil generere", + "Number of images" : "Antal billeder", + "How many images to generate" : "Hvor mange billeder skal genereres", + "Output images" : "Output billeder", + "The generated images" : "De genererede billeder", + "Free text to text prompt" : "Fritekst til tekstprompt", + "Runs an arbitrary prompt through a language model that returns a reply" : "Kører en vilkårlig prompt gennem en sprogmodel, der returnerer et svar", + "Describe a task that you want the assistant to do or ask a question" : "Beskriv en opgave, som du ønsker at assistenten udføre eller stil et spørgsmål", + "Generated reply" : "Genereret svar", + "The generated text from the assistant" : "Den genererede tekst fra assistenten", + "Change Tone" : "Ændr tone", + "Change the tone of a piece of text." : "Ændre tonen i et stykke tekst.", + "Write a text that you want the assistant to rewrite in another tone." : "Skriv en tekst, som assistenten skal skrive i en anden tone.", + "Desired tone" : "Ønsket tone", + "In which tone should your text be rewritten?" : "I hvilken tone skal din tekst omskrives?", + "The rewritten text in the desired tone, written by the assistant:" : "Den omskrevne tekst i den ønskede tone, skrevet af assistenten:", "Chat" : "cHAT", + "Chat with the assistant" : "Chat med assistent", + "System prompt" : "Systemprompt", + "Define rules and assumptions that the assistant should follow during the conversation." : "Definer regler og antagelser, som assistenten skal følge under samtalen.", + "Chat history" : "Chathistorik", + "The history of chat messages before the current message, starting with a message by the user" : "Historikken for chatbeskeder før den aktuelle besked, startende med en besked fra brugeren", + "Response message" : "Svarmeddelelse", + "The generated response as part of the conversation" : "Det genererede svar som en del af samtalen", + "Chat with tools" : "Chat med værktøjer", + "Chat with the language model with tool calling support." : "Chat med sprogmodellen med værktøj opkaldsunderstøttelse.", + "Tool message" : "Værktøjsbesked", + "The result of tool calls in the last interaction" : "Resultatet af værktøjsopkald i den sidste interaktion", + "Available tools" : "Tilgængelige værktøjer", + "The available tools in JSON format" : "De tilgængelige værktøjer i JSON format", + "The response from the chat model" : "Svaret fra chatmodellen", + "Tool calls" : "Værktøjsopkald", + "Tools call instructions from the model in JSON format" : "Værktøjsopkald instruktioner fra modellen i JSON format", + "Formalize text" : "Formaliser tekst", + "Takes a text and makes it sound more formal" : "Anvender en tekst og får det til at lyde mere formelt", + "Write a text that you want the assistant to formalize" : "Skriv en tekst som du vil have assistenten til at formalisere", + "Formalized text" : "Formaliseret tekst", + "The formalized text" : "Den formaliserede tekst", + "Generate a headline" : "Generer en overskrift", "Generates a possible headline for a text." : "Genererer en mulig overskrift til en tekst.", + "Original text" : "Oprindelig tekst", + "The original text to generate a headline for" : "Den oprindelige tekst til at generere en overskrift for", + "The generated headline" : "Den genererede overskrift", + "Proofread" : "Korrekturlæsning", + "Proofreads a text and lists corrections" : "Korrekturlæser en tekst og lister rettelser", + "Text" : "Tekst", + "The text to proofread" : "Teksten til korrekturlæsning", + "Corrections" : "Rettelser", + "The corrections that should be made in your text" : "De rettelser, der skal foretages i din tekst", + "Reformulate text" : "Omformuler tekst", + "Takes a text and reformulates it" : "Anvender en tekst og omformulerer den", + "Write a text that you want the assistant to reformulate" : "Skriv en tekst som du vil have assistenten til at omformulere", + "Reformulated text" : "Omformuleret tekst", + "The reformulated text, written by the assistant" : "Den omformulerede tekst, skrevet af assistenten", + "Simplify text" : "Forenkel tekst", + "Takes a text and simplifies it" : "Anvender en tekst og forenkler den", + "Write a text that you want the assistant to simplify" : "Skriv en tekst, som du vil have assistenten til at forenkle", + "Simplified text" : "Forenklet tekst", + "The simplified text" : "Den forenklede tekst", "Summarize" : "Opsummer", + "Summarizes a text" : "Sammenfatter en tekst", + "The original text to summarize" : "Den oprindelige tekst der skal sammenfattes", "Summary" : "Oversigt", + "The generated summary" : "Det genererede sammendrag", "Extract topics" : "Uddrag emner", + "Extracts topics from a text and outputs them separated by commas" : "Udtrækker emner fra en tekst og udskriver dem adskilt af kommaer", + "The original text to extract topics from" : "Den oprindelige tekst til at udtrække emner fra", + "Topics" : "Emner", + "The list of extracted topics" : "Listen over udtrukne emner", "Translate" : "Oversæt", + "Translate text from one language to another" : "Oversæt tekst fra et sprog til et andet", + "Origin text" : "Oprindelig tekst", + "The text to translate" : "Teksten der skal oversættes", + "Origin language" : "Oprindelsessprog", + "The language of the origin text" : "Det sprog, der anvendes i oprindelsesteksten", + "Target language" : "Målsprog", + "The desired language to translate the origin text in" : "Det ønskede sprog som oprindelsesteksten skal oversættes til", "Result" : "Resultat", + "The translated text" : "Den oversatte tekst", "Free prompt" : "Gratis prompt", "Runs an arbitrary prompt through the language model." : "Kører en arbitrær prompt gennem sprogmodellen.", "Generate headline" : "Generer overskrift", "Summarizes text by reducing its length without losing key information." : "Opsummerer tekst ved at reducere dens længde uden at miste nøgleinformation.", "Extracts topics from a text and outputs them separated by commas." : "Uddrager emner fra en tekst og skriver dem adskilt af kommaer.", - "Education Edition" : "Uddanelses Version", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Bruger skal være administrator, underadministrator eller have tildelt specielle rettigheder for at have adgang til denne indstilling", - "Logged in user must be an admin or sub admin" : "Bruger skal være administrator eller underadministrator", - "Logged in user must be an admin" : "Brugeren skal være administrator", - "File name is a reserved word" : "Filnavnet er et reserveret ord", - "File name contains at least one invalid character" : "Filnavnet indeholder mindst ét ugyldigt tegn", - "File name is too long" : "Filnavnet er for langt", - "Help" : "Hjælp", - "Users" : "Brugere", - "Unknown user" : "Ukendt bruger", - "Enter the database username and name for %s" : "Indtast navn til databasen og brugernavn for %s", - "Enter the database username for %s" : "Indtast brugernavn til databasen for %s", - "MySQL username and/or password not valid" : "MySQL brugernavn og/eller kodeord er ikke gyldigt", - "Oracle username and/or password not valid" : "Oracle brugernavn og/eller kodeord er ikke gyldigt.", - "PostgreSQL username and/or password not valid" : "PostgreSQL brugernavn og/eller kodeord er ikke gyldigt.", - "Set an admin username." : "Angiv et admin brugernavn.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s delte »%2$s« med dig og vil gerne tilføje:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s delte »%2$s« med dig og vil gerne tilføje", - "»%s« added a note to a file shared with you" : "»%s« tilføjede en note til en fil delt med dig", - "Open »%s«" : "Åbn »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Deling af %s mislykkedes, fordi dette element allerede er delt med brugeren %s", - "%1$s shared »%2$s« with you" : "%1$s delte »%2$s« med dig", - "%1$s shared »%2$s« with you." : "%1$s delte »%2$s« med dig", - "The username is already being used" : "Brugernavnet er allerede i brug", - "Could not create user" : "Kunne ikke oprette bruger", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kun følgende tegn kan indgå i et brugernavn: \"a-z\", \"A-Z\", \"0-9\", mellemrum and \"_.@-'\"", - "A valid username must be provided" : "Et gyldigt brugernavn skal angives", - "Username contains whitespace at the beginning or at the end" : "Brugernavnet har et mellemrum i starten eller slutningen", - "Username must not consist of dots only" : "Brugernavnet må ikke bestå af rene prikker/punktummer", - "Username is invalid because files already exist for this user" : "Brugernavnet er ugyldigt, da der allerede eksisterer filer for denne bruger", - "User disabled" : "Bruger deaktiveret", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "Filen er i øjeblikket optaget - forsøg igen senere", "Cannot download file" : "Kan ikke downloade filen", - "Your data directory is readable by other users." : "Datamappen kan læses af andre brugere.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Tilpas venligst rettigheder til 0770, så mappen ikke fremvises for andre brugere.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Du bedes sikre at filen \".ocdata\" befinder sig i roden af din datamappe." + "Login is too long" : "Login er for lang" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/de.js b/lib/l10n/de.js index 184613c068f..4b3d84bc105 100644 --- a/lib/l10n/de.js +++ b/lib/l10n/de.js @@ -1,18 +1,18 @@ OC.L10N.register( "lib", { - "Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!", + "Cannot write into \"config\" directory!" : "Das Schreiben in das \"config\"-Verzeichnis ist nicht möglich!", "This can usually be fixed by giving the web server write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.", "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Wenn du jedoch möchtest dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true.", "See %s" : "Siehe %s", - "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Die Anwendung %1$s ist nicht vorhanden oder hat eine mit diesem Server nicht kompatible Version. Bitte überprüfe das Apps-Verzeichnis.", + "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Die Anwendung %1$s ist nicht vorhanden oder hat eine mit diesem Server nicht kompatible Version. Bitte das Apps-Verzeichnis überprüfen.", "Sample configuration detected" : "Beispielkonfiguration gefunden", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann deine Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.", "The page could not be found on the server." : "Die Seite konnte auf dem Server nicht gefunden werden.", "%s email verification" : "%s E-Mail-Überprüfung", "Email verification" : "E-Mail-Überprüfung", - "Click the following button to confirm your email." : "Klicke die folgende Schaltfläche, um deine E-Mail-Adresse zu bestätigen.", - "Click the following link to confirm your email." : "Klicke den nachfolgenden Link, um deine E-Mail-Adresse zu bestätigen", + "Click the following button to confirm your email." : "Die folgende Schaltfläche anklicken, um die E-Mail-Adresse zu bestätigen.", + "Click the following link to confirm your email." : "Auf den nachfolgenden Link klicken, um die E-Mail-Adresse zu bestätigen", "Confirm your email" : "Bestätige deine E-Mail-Adresse", "Other activities" : "Andere Aktivitäten", "%1$s and %2$s" : "%1$s und %2$s", @@ -37,9 +37,9 @@ OC.L10N.register( "The following platforms are supported: %s" : "Die folgenden Plattformen werden unterstützt: %s", "Server version %s or higher is required." : "Server Version %s oder höher wird benötigt.", "Server version %s or lower is required." : "Server Version %s oder niedriger wird benötigt.", - "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Das angemeldete Konto muss ein Administrator, ein Teil-Administrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen", - "Your current IP address doesn’t allow you to perform admin actions" : "Unter deiner aktuellen IP-Adresse sind keine Administrationsaktionen erlaubt", - "Logged in account must be an admin or sub admin" : "Das angemeldete Konto muss ein (Sub-)Administrator sein", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Das angemeldete Konto muss ein Administrator, ein Unteradministrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen", + "Your current IP address doesn't allow you to perform admin actions" : "Unter deiner aktuellen IP-Adresse sind keine Administrationsaktionen erlaubt", + "Logged in account must be an admin or sub admin" : "Das angemeldete Konto muss ein (Unter-)Administrator sein", "Logged in account must be an admin" : "Das angemeldete Konto muss ein Administrator sein", "Wiping of device %s has started" : "Löschen von Gerät %s wurde gestartet", "Wiping of device »%s« has started" : "Löschen von Gerät »%s« wurde gestartet", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Benutzerbild ist nicht quadratisch", "Files" : "Dateien", "View profile" : "Profil ansehen", + "same time" : "gleiche Zeit", + "_%nh_::_%nh_" : ["%nStunde","%nStunden"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s voraus", + "%s behind" : "%s zurück", "Local time: %s" : "Ortszeit: %s", "today" : "Heute", "tomorrow" : "Morgen", @@ -80,18 +85,33 @@ OC.L10N.register( "in a few seconds" : "in wenigen Sekunden", "seconds ago" : "Gerade eben", "Empty file" : "Leere Datei", - "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Das Modul mit der ID: %s existiert nicht. Bitte die App in den App-Einstellungen aktivieren oder den Administrator kontaktieren.", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Das Modul mit der ID: %s existiert nicht. Bitte die App in den App-Einstellungen aktivieren oder die Administration kontaktieren.", + "No file conversion providers available" : "Keine Dateikonvertierungsanbieter verfügbar", + "File is too large to convert" : "Die Datei ist zu groß zum Konvertieren", + "Destination does not match conversion extension" : "Das Ziel stimmt nicht mit der Konvertierungs-Erweiterung überein", + "Could not convert file" : "Datei konnte nicht konvertiert werden", + "Destination does not exist" : "Ziel existiert nicht", + "Destination is not creatable" : "Ziel kann nicht erstellt werden", "Dot files are not allowed" : "Dateinamen mit einem Punkt am Anfang sind nicht erlaubt", - "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" ist ein verbotener Datei- oder Ordnername.", - "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" ist ein verbotenes Präfix für Datei- oder Ordnernamen.", + "%1$s (renamed)" : "%1$s (umbenannt)", + "renamed file" : "Umbenannte Datei", + "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" ist ein unzulässiger Datei- oder Ordnername.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" ist ein unzulässiges Präfix für Datei- oder Ordnernamen.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" ist in einem Datei- oder Ordnernamen unzulässig.", "\"%1$s\" is a forbidden file type." : "\"%1$s\" ist ein unzulässiger Dateityp.", "Filenames must not end with \"%1$s\"." : "Dateinamen dürfen nicht mit \"%1$s\" enden.", "Invalid parent path" : "Ungültiger übergeordneter Pfad", "File already exists" : "Datei bereits vorhanden", "Invalid path" : "Ungültiger Pfad", - "Failed to create file from template" : "Fehler beim Erstellen der Datei aus Vorlage", + "Failed to create file from template" : "Datei konnte nicht aus Vorlage erstellt werden", "Templates" : "Vorlagen", + "Storage %s cannot be moved" : "Speicherplatz %s kann nicht verschoben werden", + "Moving a share (%s) into a shared folder is not allowed" : "Verschieben einer Freigabe (%s) in einen freigegebenen Ordner ist unzulässig", + "Moving a storage (%s) into a shared folder is not allowed" : "Verschieben eines Speicherplatzes (%s) in einen freigegebenen Ordner ist unzulässig", + "Moving a share (%s) into another share (%s) is not allowed" : "Verschieben einer Freigabe (%s) in eine andere Freigabe (%s) ist unzulässig.", + "Moving a share (%s) into another storage (%s) is not allowed" : "Verschieben einer Freigabe (%s) in einen anderen Speicherplatz (%s) ist nicht erlaubt", + "Moving a storage (%s) into a share (%s) is not allowed" : "Verschieben eines Speicherplatzes (%s) in eine Freigabe (%s) ist nicht erlaubt", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Verschieben eines Speicherplatzes (%s) in einen anderen Speicherplatz (%s) ist nicht erlaubt", "Path contains invalid segments" : "Pfad enthält ungültige Segmente", "Filename is a reserved word" : "Der Dateiname ist ein reserviertes Wort", "Filename contains at least one invalid character" : "Der Dateiname enthält mindestens ein unzulässiges Zeichen.", @@ -102,10 +122,10 @@ OC.L10N.register( "__language_name__" : "Deutsch (Persönlich: Du)", "This is an automatically sent email, please do not reply." : "Dies ist eine automatisch gesendete E-Mail. Bitte antworte nicht auf diese E-Mail.", "Help & privacy" : "Hilfe & Datenschutz", - "Appearance and accessibility" : "Erscheinungsbild und Barrierefreiheit", + "Appearance and accessibility" : "Aussehen und Barrierefreiheit", "Apps" : "Apps", "Personal settings" : "Persönliche Einstellungen", - "Administration settings" : "Verwaltungseinstellungen", + "Administration settings" : "Administrationseinstellungen", "Settings" : "Einstellungen", "Log out" : "Abmelden", "Accounts" : "Konten", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "Über", "Display name" : "Anzeigename", "Headline" : "Überschrift", - "Organisation" : "Organisation", + "Organization" : "Organisation", "Role" : "Funktion", "Pronouns" : "Pronomen", "Unknown account" : "Unbekanntes Konto", @@ -138,18 +158,17 @@ OC.L10N.register( "Oracle connection could not be established" : "Es konnte keine Verbindung zur Oracle-Datenbank hergestellt werden", "Oracle Login and/or password not valid" : "Oracle-Anmeldename und/oder -Passwort ungültig", "PostgreSQL Login and/or password not valid" : "PostgreSQL-Anmeldename und/oder Passwort ungültig", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X wird nicht unterstützt und %s wird auf dieser Plattform nicht richtig funktionieren. Die Benutzung erfolgt auf eigene Gefahr!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X wird nicht unterstützt und %s wird unter dieser Plattform nicht richtig funktionieren. Verwendung auf eigene Gefahr!", "For the best results, please consider using a GNU/Linux server instead." : "Zur Gewährleistung eines optimalen Betriebs sollte stattdessen ein GNU/Linux-Server verwendet werden.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Es scheint, dass diese %s-Instanz unter einer 32-Bit-PHP-Umgebung läuft und open_basedir in der Datei php.ini konfiguriert worden ist. Von einem solchen Betrieb wird dringend abgeraten, weil es dabei zu Problemen mit Dateien kommt, deren Größe 4 GB übersteigt.", - "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte entferne die open_basedir-Einstellung in deiner php.ini oder wechsele zu 64-Bit-PHP.", + "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte die open_basedir-Einstellung in der php.ini entfernen oder zu 64-Bit-PHP wechseln.", "Set an admin Login." : "Anmeldename für Andministration setzen.", - "Set an admin password." : "Ein Administrator-Passwort setzen.", + "Set an admin password." : "Ein Administrationspasswort setzen.", "Cannot create or write into the data directory %s" : "Das Datenverzeichnis %s kann nicht erstellt oder es kann darin nicht geschrieben werden.", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Freigabe-Backend %s muss in der OCP\\Share_Backend - Schnittstelle implementiert werden", "Sharing backend %s not found" : "Freigabe-Backend %s nicht gefunden", "Sharing backend for %s not found" : "Freigabe-Backend für %s nicht gefunden", "%1$s shared %2$s with you" : "%1$s hat %2$s mit dir geteilt", - "Click the button below to open it." : "Klicke zum Öffnen auf die untere Schaltfläche.", "Open %s" : "%s öffnen", "%1$s via %2$s" : "%1$s über %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s hat %2$s mit dir geteilt und möchte hinzufügen:", @@ -163,12 +182,13 @@ OC.L10N.register( "Share recipient is not a valid circle" : "Freigabeempfänger ist kein gültiger Kreis", "Unknown share type" : "Unbekannter Freigabetyp", "Share initiator must be set" : "Freigabeinitiator muss festgelegt sein", - "Cannot share with yourself" : "Es kann nicht mit dir selbst geteilt werden", + "Cannot share with yourself" : "Es kann nicht mit sich selbst geteilt werden", "Shared path must be set" : "Der freigegebene Pfad muss festgelegt werden", "Shared path must be either a file or a folder" : "Der freigegebene Pfad muss entweder eine Datei oder ein Ordner sein", "You cannot share your root folder" : "Du kannst deinen Stammordner nicht freigeben", "You are not allowed to share %s" : "Du bist nicht berechtigt, %s zu teilen.", "Valid permissions are required for sharing" : "Zum Teilen sind gültige Berechtigungen erforderlich", + "File shares cannot have create or delete permissions" : "Dateifreigaben können keine Berechtigungen zum Erstellen oder Löschen haben", "Cannot increase permissions of %s" : "Kann die Berechtigungen von %s nicht erhöhen", "Shares need at least read permissions" : "Freigaben benötigen mindestens Leseberechtigungen", "Files cannot be shared with delete permissions" : "Dateien mit Lösch-Berechtigungen können nicht geteilt werden", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Der Pfad ist bereits mit dieser Gruppe geteilt", "Link sharing is not allowed" : "Freigabe via Link ist nicht erlaubt", "Public upload is not allowed" : "Öffentliches Hochladen ist nicht erlaubt", - "Path contains files shared with you" : "Der Pfad enthält für dich freigegebene Dateien", + "You cannot share a folder that contains other shares" : "Ein Ordner, der andere Freigaben enthält, kann nicht geteilt werden", "Sharing is disabled" : "Teilen ist deaktiviert", "Sharing is disabled for you" : "Teilen ist für dich deaktiviert", "Cannot share with the share owner" : "Teilen mit dem Freigabeeigentümer nicht möglich", @@ -200,7 +220,7 @@ OC.L10N.register( "The requested share does not exist anymore" : "Die angeforderte Freigabe existiert nicht mehr", "The requested share comes from a disabled user" : "Die angeforderte Freigabe stammt von einem deaktivierten Benutzer", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Der Benutzer wurde nicht erstellt, da das Benutzerlimit erreicht wurde. Überprüfe deine Benachrichtigungen, um mehr zu erfahren.", - "Could not find category \"%s\"" : "Die Kategorie \"%s“ konnte nicht gefunden werden", + "Could not find category \"%s\"" : "Die Kategorie \"%s\" konnte nicht gefunden werden", "Input text" : "Texteingabe", "The input text" : "Der Eingabetext", "Sunday" : "Sonntag", @@ -252,75 +272,75 @@ OC.L10N.register( "The Login is already being used" : "Dieser Anmeldename wird bereits verwendet", "Could not create account" : "Konto konnte nicht erstellt werden", "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Nur die folgenden Zeichen sind in einem Anmeldenamen erlaubt: \"a-z\", \"A-Z\", \"0-9\", Leerzeichen und \"_.@-'\"", - "A valid Login must be provided" : "Ein gültiger Anmeldename muss angegeben werden.", + "A valid Login must be provided" : "Ein gültiger Anmeldename muss eingegeben werden.", "Login contains whitespace at the beginning or at the end" : "Anmeldename enthält Leerzeichen am Anfang oder am Ende", "Login must not consist of dots only" : "Der Anmeldename darf nicht nur aus Punkten bestehen", - "Login is invalid because files already exist for this user" : "Der Anmeldename ist ungültig, da bereits Dateien von diesem Benutzer existieren", + "Username is too long" : "Benutzername ist zu lang", + "Login is invalid because files already exist for this user" : "Der Anmeldename ist ungültig, da bereits Dateien von diesem Konto existieren", "Account disabled" : "Konto deaktiviert", "Login canceled by app" : "Anmeldung durch die App abgebrochen", - "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App „%1$s“ kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s", + "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App \"%1$s\" kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s", "a safe home for all your data" : "ein sicherer Ort für all deine Daten", "Application is not enabled" : "Die Anwendung ist nicht aktiviert", "Authentication error" : "Authentifizierungsfehler", "Token expired. Please reload page." : "Token abgelaufen. Bitte lade die Seite neu.", "No database drivers (sqlite, mysql, or postgresql) installed." : "Keine Datenbanktreiber (SQLite, MySQL oder PostgreSQL) installiert.", - "Cannot write into \"config\" directory." : "Schreiben in das „config“-Verzeichnis ist nicht möglich.", + "Cannot write into \"config\" directory." : "Schreiben in das \"config\"-Verzeichnis ist nicht möglich.", "This can usually be fixed by giving the web server write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Webserver Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s", "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn du lieber möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true. Siehe %s", - "Cannot write into \"apps\" directory." : "Schreiben in das „apps“-Verzeichnis ist nicht möglich.", - "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das App-Verzeichnis gegeben wird oder der App-Store in der Konfigurationsdatei deaktiviert wird.", - "Cannot create \"data\" directory." : "Kann das \"Daten\"-Verzeichnis nicht erstellen.", + "Cannot write into \"apps\" directory." : "Schreiben in das \"apps\"-Verzeichnis ist nicht möglich.", + "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das App-Verzeichnis gegeben wird, oder der App-Store in der Konfigurationsdatei deaktiviert wird.", + "Cannot create \"data\" directory." : "Kann das \"data\"-Verzeichnis nicht erstellen.", "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Dies kann zumeist behoben werden, indem dem Webserver Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s", "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Berechtigungen können zumeist korrigiert werden, indem dem Webserver Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s. ", - "Your data directory is not writable." : "Dein Datenverzeichnis ist schreibgeschützt.", + "Your data directory is not writable." : "Das Datenverzeichnis ist schreibgeschützt.", "Setting locale to %s failed." : "Das Setzen der Spracheeinstellung auf %s ist fehlgeschlagen.", - "Please install one of these locales on your system and restart your web server." : "Bitte installiere eine dieser Sprachen auf deinem System und starte den Webserver neu.", + "Please install one of these locales on your system and restart your web server." : "Bitte eine dieser Sprachen auf dem System installieren und den Webserver neu starten.", "PHP module %s not installed." : "PHP-Modul %s nicht installiert.", - "Please ask your server administrator to install the module." : "Bitte für die Installation des Moduls deinen Server-Administrator kontaktieren.", - "PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung „%s“ ist nicht auf „%s“ gesetzt.", - "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann deine Nextcloud wieder lauffähig machen.", + "Please ask your server administrator to install the module." : "Bitte für die Installation des Moduls die Serveradministration kontaktieren.", + "PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung \"%s\" ist nicht auf \"%s\" gesetzt.", + "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann diese Nextcloud wieder lauffähig machen.", "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> ist auf <code>%s</code> gesetzt und nicht auf den erwarteten Wert <code>0</code>.", - "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in deiner php.ini auf <code>0</code>.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Zum Beheben dieses Problems bitte <code>mbstring.func_overload</code> in der php.ini auf <code>0</code> setzen.", "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ist offenbar so konfiguriert, dass PHPDoc-Blöcke in der Anweisung entfernt werden. Dadurch sind mehrere Kern-Apps nicht erreichbar.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dies wird wahrscheinlich durch Zwischenspeicher/Beschleuniger wie etwa Zend OPcache oder eAccelerator verursacht.", "PHP modules have been installed, but they are still listed as missing?" : "PHP-Module wurden installiert, werden aber als noch fehlend gelistet?", - "Please ask your server administrator to restart the web server." : "Bitte kontaktiere deinen Server-Administrator und bitte um den Neustart des Webservers.", + "Please ask your server administrator to restart the web server." : "Bitte die Serveradministration konatktieren und um Neustart des Webservers bitten.", "The required %s config variable is not configured in the config.php file." : "Die erforderliche %s Konfigurationsvariable ist in der config.php nicht konfiguriert.", - "Please ask your server administrator to check the Nextcloud configuration." : "Bitte deinen Server-Administrator, die Nextcloud-Konfiguration zu überprüfen.", + "Please ask your server administrator to check the Nextcloud configuration." : "Die Serveradministration bitten, die Nextcloud-Konfiguration zu überprüfen.", "Your data directory is readable by other people." : "Dein Datenverzeichnis kann von anderen Benutzern gelesen werden", - "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Bitte ändere die Berechtigungen auf 0770, so dass das Verzeichnis nicht von Anderen angezeigt werden kann.", - "Your data directory must be an absolute path." : "Dein Datenverzeichnis muss einen eindeutigen Pfad haben", - "Check the value of \"datadirectory\" in your configuration." : "Überprüfe bitte die Angabe unter „datadirectory“ in deiner Konfiguration", - "Your data directory is invalid." : "Dein Datenverzeichnis ist ungültig", - "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Stelle sicher, dass eine Datei \"%1$s\" im Wurzelverzeichnis des Datenverzeichnisses existiert. Sie sollte folgenden Inhalt haben: \"%2$s\"", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Bitte die Berechtigungen auf 0770 ändern, so dass das Verzeichnis nicht von Anderen angezeigt werden kann.", + "Your data directory must be an absolute path." : "Das Datenverzeichnis muss einen eindeutigen Pfad haben", + "Check the value of \"datadirectory\" in your configuration." : "Bitte die Angabe unter \"datadirectory\" in der Konfiguration überprüfen.", + "Your data directory is invalid." : "Das Datenverzeichnis ist ungültig", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Bitte sicherstellen, dass eine Datei \"%1$s\" im Wurzelverzeichnis des Datenverzeichnisses existiert. Sie sollte folgenden Inhalt haben: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.", "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder falsche Provider-ID wurde übertragen.", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter, um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"", "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "ID \"%1$s\" wird bereits von Cloud-Federation-Provider \"%2$s\" verwendet", "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.", - "Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.", + "Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf \"%s\" konnte nicht ermittelt werden.", "Storage unauthorized. %s" : "Speicher nicht autorisiert. %s", "Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s", "Storage connection error. %s" : "Verbindungsfehler zum Speicherplatz. %s", "Storage is temporarily not available" : "Speicher ist vorübergehend nicht verfügbar", "Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s", - "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Damit diese Prüfung ausgeführt werden kann, musst du sicherstellen, dass dein Webserver eine Verbindung zu sich selbst herstellen kann. Daher muss er in der Lage sein, mindestens eine seiner `trusted_domains` oder `overwrite.cli.url` aufzulösen und eine Verbindung zu ihnen herzustellen. Dieser Fehler kann das Ergebnis einer serverseitigen DNS-Nichtübereinstimmung oder einer ausgehenden Firewall-Regel sein.", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Damit diese Prüfung ausgeführt werden kann, muß sichergestellt sein, dass der Webserver eine Verbindung zu sich selbst herstellen kann. Daher muss er in der Lage sein, mindestens eine seiner `trusted_domains` oder `overwrite.cli.url` aufzulösen und eine Verbindung zu ihnen herzustellen. Dieser Fehler kann das Ergebnis einer serverseitigen DNS-Nichtübereinstimmung oder einer ausgehenden Firewall-Regel sein.", "Transcribe audio" : "Audio transkribieren", "Transcribe the things said in an audio" : "Inhalt der Audiodatei transkribieren", "Audio input" : "Audioeingang", "The audio to transcribe" : "Die Audio-Datei zum Transkribieren", "Transcription" : "Transkription", "The transcribed text" : "Der transkribierte Text", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "Mit einem Agenten chatten", "Chat message" : "Chatnachricht", - "A chat message to send to the agent." : "Eine Chat-Nachricht, die an den Agenten gesendet wird.", + "A chat message to send to the agent." : "Eine Chatnachricht, die an den Agenten gesendet wird.", "Confirmation" : "Bestätigung", "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Ob zuvor angeforderte Aktionen bestätigt werden sollen: 0 für Verweigerung und 1 für Bestätigung.", "Conversation token" : "Unterhaltungstoken", "A token representing the conversation." : "Ein Token, das die Unterhaltung repräsentiert.", "Generated response" : "Erzeugte Antwort", - "The response from the chat model." : "Die Antwort des Chatmodells.", + "The response from the chat model." : "Die Antwort des Chat-Modells.", "The new conversation token" : "Das neue Unterhaltungstoken", "Send this along with the next interaction." : "Dies zusammen mit der nächsten Interaktion senden.", "Requested actions by the agent" : "Vom Agenten angeforderte Aktionen", @@ -328,7 +348,7 @@ OC.L10N.register( "Context write" : "Kontext schreiben", "Writes text in a given style based on the provided source material." : "Schreibt Text in einem vorgegebenen Stil auf Basis des bereitgestellten Quellmaterials.", "Writing style" : "Schreibstil", - "Demonstrate a writing style that you would like to immitate" : "Zeigen Sie einen Schreibstil, den Sie gerne nachahmen würden", + "Demonstrate a writing style that you would like to immitate" : "Zeige einen Schreibstil, den du gerne nachahmen würden", "Source material" : "Quellmaterial", "The content that would like to be rewritten in the new writing style" : "Der Inhalt, der in den neuen Schreibstil umgeschrieben werden soll", "Generated text" : "Erstellter Text", @@ -341,14 +361,19 @@ OC.L10N.register( "Generate image" : "Bild erstellen", "Generate an image from a text prompt" : "Bild aus einer Texteingabe erstellen", "Prompt" : "Prompt", - "Describe the image you want to generate" : "Beschreibe das Bild, das du erstellen möchtest", + "Describe the image you want to generate" : "Das Bild, das erstellt werden soll, beschreiben", "Number of images" : "Anzahl der Bilder", "How many images to generate" : "Wie viele Bilder erstellt werden sollen", "Output images" : "Ausgegebene Bilder", "The generated images" : "Die erstellten Bilder", + "Generate speech" : "Sprache erstellen", + "Generate speech from a transcript" : "Sprache aus einem Transkript erstellen", + "Write transcript that you want the assistant to generate speech from" : "Schreibe ein Transkript, aus dem der Assistent Sprache erstellen soll", + "Output speech" : "Sprachausgabe", + "The generated speech" : "Die erstellte Sprache", "Free text to text prompt" : "Freie Text-zu-Text-Eingabeaufforderung", "Runs an arbitrary prompt through a language model that returns a reply" : "Führt eine beliebige Eingabeaufforderung mit einem Sprachmodell aus, das eine Antwort zurückgibt", - "Describe a task that you want the assistant to do or ask a question" : "Beschreibe eine Aufgabe, die der Assistent erledigen soll, oder stelle eine Frage", + "Describe a task that you want the assistant to do or ask a question" : "Eine Aufgabe beschreiben, die der Assistent erledigen soll, oder eine Frage stellen", "Generated reply" : "Erstellte Antwort", "The generated text from the assistant" : "Der vom Assistenten erstellte Text", "Change Tone" : "Ton ändern", @@ -384,6 +409,12 @@ OC.L10N.register( "Original text" : "Originaltext", "The original text to generate a headline for" : "Der Originaltext, für den eine Überschrift erstellt werden soll", "The generated headline" : "Die erstellte Überschrift", + "Proofread" : "Korrekturlesen", + "Proofreads a text and lists corrections" : "Liest einen Text Korrektur und listet Korrekturen auf", + "Text" : "Text", + "The text to proofread" : "Der zu korrigierende Text", + "Corrections" : "Korrekturen", + "The corrections that should be made in your text" : "Die Korrekturen, die in deinem Text vorgenommen werden sollten", "Reformulate text" : "Text umformulieren", "Takes a text and reformulates it" : "Formuliert einen Text um", "Write a text that you want the assistant to reformulate" : "Text schreiben, den der Assistent umformulieren soll", @@ -419,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Überschrift erzeugen", "Summarizes text by reducing its length without losing key information." : "Fasst Text zusammen, indem die Länge reduziert wird, ohne dass wichtige Informationen verloren gehen.", "Extracts topics from a text and outputs them separated by commas." : "Extrahiert Themen aus einem Text und gibt sie durch Kommas getrennt aus.", - "Education Edition" : "Bildungsausgabe", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Der angemeldete Benutzer muss ein Administrator, ein Teil-Administrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen. ", - "Logged in user must be an admin or sub admin" : "Der angemeldete Benutzer muss ein (Sub-)Administrator sein", - "Logged in user must be an admin" : "Der angemeldete Benutzer muss ein Administrator sein", - "File name is a reserved word" : "Der Dateiname ist ein reserviertes Wort", - "File name contains at least one invalid character" : "Der Dateiname enthält mindestens ein ungültiges Zeichen", - "File name is too long" : "Dateiname ist zu lang", - "Help" : "Hilfe", - "Users" : "Benutzer", - "Unknown user" : "Unbekannter Benutzer", - "Enter the database username and name for %s" : "Den Datenbankbenutzernamen und den Namen eingeben für %s", - "Enter the database username for %s" : "Den Datenbankbenutzernamen eingeben für %s", - "MySQL username and/or password not valid" : "MySQL-Benutzername und/oder Passwort ungültig", - "Oracle username and/or password not valid" : "Oracle-Benutzername und/oder -Passwort ungültig", - "PostgreSQL username and/or password not valid" : "PostgreSQL-Benutzername und/oder -Passwort ungültig", - "Set an admin username." : "Einen Administrator-Benutzernamen setzen.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s hat »%2$s« mit dir geteilt und möchte folgendes hinzufügen:", - "%1$s shared »%2$s« with you and wants to add" : "%1$shat »%2$s« mit dir geteilt und möchte folgendes hinzufügen", - "»%s« added a note to a file shared with you" : "»%s« hat eine Bemerkung zu einer mit dir geteilten Datei hinzugefügt", - "Open »%s«" : "»%s« öffnen", - "Sharing %s failed, because this item is already shared with user %s" : "Freigabe von %s fehlgeschlagen, da dieses Element schon mit dem Benutzer %s geteilt wird", - "%1$s shared »%2$s« with you" : "%1$s hat »%2$s« mit dir geteilt", - "%1$s shared »%2$s« with you." : "%1$s hat »%2$s« mit dir geteilt.", - "The username is already being used" : "Dieser Benutzername existiert bereits", - "Could not create user" : "Benutzer konnte nicht erstellt werden", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Folgende Zeichen sind im Benutzernamen erlaubt: „a-z“, „A-Z“, „0-9“, Leerzeichen und „_.@-'“", - "A valid username must be provided" : "Es muss ein gültiger Benutzername angegeben werden", - "Username contains whitespace at the beginning or at the end" : "Der Benutzername enthält Leerzeichen am Anfang oder am Ende", - "Username must not consist of dots only" : "Der Benutzername darf nicht nur aus Punkten bestehen", - "Username is invalid because files already exist for this user" : "Der Benutzer ist ungültig, da bereits Dateien von diesem Benutzer existieren", - "User disabled" : "Benutzer deaktiviert", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "Die Datei ist in Benutzung, bitte versuche es später noch einmal", "Cannot download file" : "Datei kann nicht heruntergeladen werden.", - "Your data directory is readable by other users." : "Dein Datenverzeichnis kann von anderen Benutzern gelesen werden", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Bitte ändere die Berechtigungen auf 0770, sodass das Verzeichnis nicht von anderen Benutzern angezeigt werden kann.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stelle sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert." + "Login is too long" : "Die Anmeldung dauert zu lange" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/de.json b/lib/l10n/de.json index 9b7012635c4..a0adeb52553 100644 --- a/lib/l10n/de.json +++ b/lib/l10n/de.json @@ -1,16 +1,16 @@ { "translations": { - "Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!", + "Cannot write into \"config\" directory!" : "Das Schreiben in das \"config\"-Verzeichnis ist nicht möglich!", "This can usually be fixed by giving the web server write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.", "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Wenn du jedoch möchtest dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true.", "See %s" : "Siehe %s", - "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Die Anwendung %1$s ist nicht vorhanden oder hat eine mit diesem Server nicht kompatible Version. Bitte überprüfe das Apps-Verzeichnis.", + "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Die Anwendung %1$s ist nicht vorhanden oder hat eine mit diesem Server nicht kompatible Version. Bitte das Apps-Verzeichnis überprüfen.", "Sample configuration detected" : "Beispielkonfiguration gefunden", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Es wurde festgestellt, dass die Beispielkonfiguration kopiert wurde. Dies kann deine Installation zerstören und wird nicht unterstützt. Bitte die Dokumentation lesen, bevor Änderungen an der config.php vorgenommen werden.", "The page could not be found on the server." : "Die Seite konnte auf dem Server nicht gefunden werden.", "%s email verification" : "%s E-Mail-Überprüfung", "Email verification" : "E-Mail-Überprüfung", - "Click the following button to confirm your email." : "Klicke die folgende Schaltfläche, um deine E-Mail-Adresse zu bestätigen.", - "Click the following link to confirm your email." : "Klicke den nachfolgenden Link, um deine E-Mail-Adresse zu bestätigen", + "Click the following button to confirm your email." : "Die folgende Schaltfläche anklicken, um die E-Mail-Adresse zu bestätigen.", + "Click the following link to confirm your email." : "Auf den nachfolgenden Link klicken, um die E-Mail-Adresse zu bestätigen", "Confirm your email" : "Bestätige deine E-Mail-Adresse", "Other activities" : "Andere Aktivitäten", "%1$s and %2$s" : "%1$s und %2$s", @@ -35,9 +35,9 @@ "The following platforms are supported: %s" : "Die folgenden Plattformen werden unterstützt: %s", "Server version %s or higher is required." : "Server Version %s oder höher wird benötigt.", "Server version %s or lower is required." : "Server Version %s oder niedriger wird benötigt.", - "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Das angemeldete Konto muss ein Administrator, ein Teil-Administrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen", - "Your current IP address doesn’t allow you to perform admin actions" : "Unter deiner aktuellen IP-Adresse sind keine Administrationsaktionen erlaubt", - "Logged in account must be an admin or sub admin" : "Das angemeldete Konto muss ein (Sub-)Administrator sein", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Das angemeldete Konto muss ein Administrator, ein Unteradministrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen", + "Your current IP address doesn't allow you to perform admin actions" : "Unter deiner aktuellen IP-Adresse sind keine Administrationsaktionen erlaubt", + "Logged in account must be an admin or sub admin" : "Das angemeldete Konto muss ein (Unter-)Administrator sein", "Logged in account must be an admin" : "Das angemeldete Konto muss ein Administrator sein", "Wiping of device %s has started" : "Löschen von Gerät %s wurde gestartet", "Wiping of device »%s« has started" : "Löschen von Gerät »%s« wurde gestartet", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Benutzerbild ist nicht quadratisch", "Files" : "Dateien", "View profile" : "Profil ansehen", + "same time" : "gleiche Zeit", + "_%nh_::_%nh_" : ["%nStunde","%nStunden"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s voraus", + "%s behind" : "%s zurück", "Local time: %s" : "Ortszeit: %s", "today" : "Heute", "tomorrow" : "Morgen", @@ -78,18 +83,33 @@ "in a few seconds" : "in wenigen Sekunden", "seconds ago" : "Gerade eben", "Empty file" : "Leere Datei", - "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Das Modul mit der ID: %s existiert nicht. Bitte die App in den App-Einstellungen aktivieren oder den Administrator kontaktieren.", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Das Modul mit der ID: %s existiert nicht. Bitte die App in den App-Einstellungen aktivieren oder die Administration kontaktieren.", + "No file conversion providers available" : "Keine Dateikonvertierungsanbieter verfügbar", + "File is too large to convert" : "Die Datei ist zu groß zum Konvertieren", + "Destination does not match conversion extension" : "Das Ziel stimmt nicht mit der Konvertierungs-Erweiterung überein", + "Could not convert file" : "Datei konnte nicht konvertiert werden", + "Destination does not exist" : "Ziel existiert nicht", + "Destination is not creatable" : "Ziel kann nicht erstellt werden", "Dot files are not allowed" : "Dateinamen mit einem Punkt am Anfang sind nicht erlaubt", - "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" ist ein verbotener Datei- oder Ordnername.", - "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" ist ein verbotenes Präfix für Datei- oder Ordnernamen.", + "%1$s (renamed)" : "%1$s (umbenannt)", + "renamed file" : "Umbenannte Datei", + "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" ist ein unzulässiger Datei- oder Ordnername.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" ist ein unzulässiges Präfix für Datei- oder Ordnernamen.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" ist in einem Datei- oder Ordnernamen unzulässig.", "\"%1$s\" is a forbidden file type." : "\"%1$s\" ist ein unzulässiger Dateityp.", "Filenames must not end with \"%1$s\"." : "Dateinamen dürfen nicht mit \"%1$s\" enden.", "Invalid parent path" : "Ungültiger übergeordneter Pfad", "File already exists" : "Datei bereits vorhanden", "Invalid path" : "Ungültiger Pfad", - "Failed to create file from template" : "Fehler beim Erstellen der Datei aus Vorlage", + "Failed to create file from template" : "Datei konnte nicht aus Vorlage erstellt werden", "Templates" : "Vorlagen", + "Storage %s cannot be moved" : "Speicherplatz %s kann nicht verschoben werden", + "Moving a share (%s) into a shared folder is not allowed" : "Verschieben einer Freigabe (%s) in einen freigegebenen Ordner ist unzulässig", + "Moving a storage (%s) into a shared folder is not allowed" : "Verschieben eines Speicherplatzes (%s) in einen freigegebenen Ordner ist unzulässig", + "Moving a share (%s) into another share (%s) is not allowed" : "Verschieben einer Freigabe (%s) in eine andere Freigabe (%s) ist unzulässig.", + "Moving a share (%s) into another storage (%s) is not allowed" : "Verschieben einer Freigabe (%s) in einen anderen Speicherplatz (%s) ist nicht erlaubt", + "Moving a storage (%s) into a share (%s) is not allowed" : "Verschieben eines Speicherplatzes (%s) in eine Freigabe (%s) ist nicht erlaubt", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Verschieben eines Speicherplatzes (%s) in einen anderen Speicherplatz (%s) ist nicht erlaubt", "Path contains invalid segments" : "Pfad enthält ungültige Segmente", "Filename is a reserved word" : "Der Dateiname ist ein reserviertes Wort", "Filename contains at least one invalid character" : "Der Dateiname enthält mindestens ein unzulässiges Zeichen.", @@ -100,10 +120,10 @@ "__language_name__" : "Deutsch (Persönlich: Du)", "This is an automatically sent email, please do not reply." : "Dies ist eine automatisch gesendete E-Mail. Bitte antworte nicht auf diese E-Mail.", "Help & privacy" : "Hilfe & Datenschutz", - "Appearance and accessibility" : "Erscheinungsbild und Barrierefreiheit", + "Appearance and accessibility" : "Aussehen und Barrierefreiheit", "Apps" : "Apps", "Personal settings" : "Persönliche Einstellungen", - "Administration settings" : "Verwaltungseinstellungen", + "Administration settings" : "Administrationseinstellungen", "Settings" : "Einstellungen", "Log out" : "Abmelden", "Accounts" : "Konten", @@ -122,7 +142,7 @@ "About" : "Über", "Display name" : "Anzeigename", "Headline" : "Überschrift", - "Organisation" : "Organisation", + "Organization" : "Organisation", "Role" : "Funktion", "Pronouns" : "Pronomen", "Unknown account" : "Unbekanntes Konto", @@ -136,18 +156,17 @@ "Oracle connection could not be established" : "Es konnte keine Verbindung zur Oracle-Datenbank hergestellt werden", "Oracle Login and/or password not valid" : "Oracle-Anmeldename und/oder -Passwort ungültig", "PostgreSQL Login and/or password not valid" : "PostgreSQL-Anmeldename und/oder Passwort ungültig", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X wird nicht unterstützt und %s wird auf dieser Plattform nicht richtig funktionieren. Die Benutzung erfolgt auf eigene Gefahr!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X wird nicht unterstützt und %s wird unter dieser Plattform nicht richtig funktionieren. Verwendung auf eigene Gefahr!", "For the best results, please consider using a GNU/Linux server instead." : "Zur Gewährleistung eines optimalen Betriebs sollte stattdessen ein GNU/Linux-Server verwendet werden.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Es scheint, dass diese %s-Instanz unter einer 32-Bit-PHP-Umgebung läuft und open_basedir in der Datei php.ini konfiguriert worden ist. Von einem solchen Betrieb wird dringend abgeraten, weil es dabei zu Problemen mit Dateien kommt, deren Größe 4 GB übersteigt.", - "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte entferne die open_basedir-Einstellung in deiner php.ini oder wechsele zu 64-Bit-PHP.", + "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte die open_basedir-Einstellung in der php.ini entfernen oder zu 64-Bit-PHP wechseln.", "Set an admin Login." : "Anmeldename für Andministration setzen.", - "Set an admin password." : "Ein Administrator-Passwort setzen.", + "Set an admin password." : "Ein Administrationspasswort setzen.", "Cannot create or write into the data directory %s" : "Das Datenverzeichnis %s kann nicht erstellt oder es kann darin nicht geschrieben werden.", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Freigabe-Backend %s muss in der OCP\\Share_Backend - Schnittstelle implementiert werden", "Sharing backend %s not found" : "Freigabe-Backend %s nicht gefunden", "Sharing backend for %s not found" : "Freigabe-Backend für %s nicht gefunden", "%1$s shared %2$s with you" : "%1$s hat %2$s mit dir geteilt", - "Click the button below to open it." : "Klicke zum Öffnen auf die untere Schaltfläche.", "Open %s" : "%s öffnen", "%1$s via %2$s" : "%1$s über %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s hat %2$s mit dir geteilt und möchte hinzufügen:", @@ -161,12 +180,13 @@ "Share recipient is not a valid circle" : "Freigabeempfänger ist kein gültiger Kreis", "Unknown share type" : "Unbekannter Freigabetyp", "Share initiator must be set" : "Freigabeinitiator muss festgelegt sein", - "Cannot share with yourself" : "Es kann nicht mit dir selbst geteilt werden", + "Cannot share with yourself" : "Es kann nicht mit sich selbst geteilt werden", "Shared path must be set" : "Der freigegebene Pfad muss festgelegt werden", "Shared path must be either a file or a folder" : "Der freigegebene Pfad muss entweder eine Datei oder ein Ordner sein", "You cannot share your root folder" : "Du kannst deinen Stammordner nicht freigeben", "You are not allowed to share %s" : "Du bist nicht berechtigt, %s zu teilen.", "Valid permissions are required for sharing" : "Zum Teilen sind gültige Berechtigungen erforderlich", + "File shares cannot have create or delete permissions" : "Dateifreigaben können keine Berechtigungen zum Erstellen oder Löschen haben", "Cannot increase permissions of %s" : "Kann die Berechtigungen von %s nicht erhöhen", "Shares need at least read permissions" : "Freigaben benötigen mindestens Leseberechtigungen", "Files cannot be shared with delete permissions" : "Dateien mit Lösch-Berechtigungen können nicht geteilt werden", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "Der Pfad ist bereits mit dieser Gruppe geteilt", "Link sharing is not allowed" : "Freigabe via Link ist nicht erlaubt", "Public upload is not allowed" : "Öffentliches Hochladen ist nicht erlaubt", - "Path contains files shared with you" : "Der Pfad enthält für dich freigegebene Dateien", + "You cannot share a folder that contains other shares" : "Ein Ordner, der andere Freigaben enthält, kann nicht geteilt werden", "Sharing is disabled" : "Teilen ist deaktiviert", "Sharing is disabled for you" : "Teilen ist für dich deaktiviert", "Cannot share with the share owner" : "Teilen mit dem Freigabeeigentümer nicht möglich", @@ -198,7 +218,7 @@ "The requested share does not exist anymore" : "Die angeforderte Freigabe existiert nicht mehr", "The requested share comes from a disabled user" : "Die angeforderte Freigabe stammt von einem deaktivierten Benutzer", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Der Benutzer wurde nicht erstellt, da das Benutzerlimit erreicht wurde. Überprüfe deine Benachrichtigungen, um mehr zu erfahren.", - "Could not find category \"%s\"" : "Die Kategorie \"%s“ konnte nicht gefunden werden", + "Could not find category \"%s\"" : "Die Kategorie \"%s\" konnte nicht gefunden werden", "Input text" : "Texteingabe", "The input text" : "Der Eingabetext", "Sunday" : "Sonntag", @@ -250,75 +270,75 @@ "The Login is already being used" : "Dieser Anmeldename wird bereits verwendet", "Could not create account" : "Konto konnte nicht erstellt werden", "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Nur die folgenden Zeichen sind in einem Anmeldenamen erlaubt: \"a-z\", \"A-Z\", \"0-9\", Leerzeichen und \"_.@-'\"", - "A valid Login must be provided" : "Ein gültiger Anmeldename muss angegeben werden.", + "A valid Login must be provided" : "Ein gültiger Anmeldename muss eingegeben werden.", "Login contains whitespace at the beginning or at the end" : "Anmeldename enthält Leerzeichen am Anfang oder am Ende", "Login must not consist of dots only" : "Der Anmeldename darf nicht nur aus Punkten bestehen", - "Login is invalid because files already exist for this user" : "Der Anmeldename ist ungültig, da bereits Dateien von diesem Benutzer existieren", + "Username is too long" : "Benutzername ist zu lang", + "Login is invalid because files already exist for this user" : "Der Anmeldename ist ungültig, da bereits Dateien von diesem Konto existieren", "Account disabled" : "Konto deaktiviert", "Login canceled by app" : "Anmeldung durch die App abgebrochen", - "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App „%1$s“ kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s", + "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App \"%1$s\" kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s", "a safe home for all your data" : "ein sicherer Ort für all deine Daten", "Application is not enabled" : "Die Anwendung ist nicht aktiviert", "Authentication error" : "Authentifizierungsfehler", "Token expired. Please reload page." : "Token abgelaufen. Bitte lade die Seite neu.", "No database drivers (sqlite, mysql, or postgresql) installed." : "Keine Datenbanktreiber (SQLite, MySQL oder PostgreSQL) installiert.", - "Cannot write into \"config\" directory." : "Schreiben in das „config“-Verzeichnis ist nicht möglich.", + "Cannot write into \"config\" directory." : "Schreiben in das \"config\"-Verzeichnis ist nicht möglich.", "This can usually be fixed by giving the web server write access to the config directory. See %s" : "Dies kann zumeist behoben werden, indem dem Webserver Schreibzugriff auf das Konfigurationsverzeichnis eingeräumt wird. Siehe auch %s", "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Oder wenn du lieber möchtest, dass die Datei config.php schreibgeschützt bleiben soll, dann setze die Option \"config_is_read_only\" in der Datei auf true. Siehe %s", - "Cannot write into \"apps\" directory." : "Schreiben in das „apps“-Verzeichnis ist nicht möglich.", - "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das App-Verzeichnis gegeben wird oder der App-Store in der Konfigurationsdatei deaktiviert wird.", - "Cannot create \"data\" directory." : "Kann das \"Daten\"-Verzeichnis nicht erstellen.", + "Cannot write into \"apps\" directory." : "Schreiben in das \"apps\"-Verzeichnis ist nicht möglich.", + "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das App-Verzeichnis gegeben wird, oder der App-Store in der Konfigurationsdatei deaktiviert wird.", + "Cannot create \"data\" directory." : "Kann das \"data\"-Verzeichnis nicht erstellen.", "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Dies kann zumeist behoben werden, indem dem Webserver Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s", "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Berechtigungen können zumeist korrigiert werden, indem dem Webserver Schreibzugriff auf das Wurzel-Verzeichnis eingeräumt wird. Siehe auch %s. ", - "Your data directory is not writable." : "Dein Datenverzeichnis ist schreibgeschützt.", + "Your data directory is not writable." : "Das Datenverzeichnis ist schreibgeschützt.", "Setting locale to %s failed." : "Das Setzen der Spracheeinstellung auf %s ist fehlgeschlagen.", - "Please install one of these locales on your system and restart your web server." : "Bitte installiere eine dieser Sprachen auf deinem System und starte den Webserver neu.", + "Please install one of these locales on your system and restart your web server." : "Bitte eine dieser Sprachen auf dem System installieren und den Webserver neu starten.", "PHP module %s not installed." : "PHP-Modul %s nicht installiert.", - "Please ask your server administrator to install the module." : "Bitte für die Installation des Moduls deinen Server-Administrator kontaktieren.", - "PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung „%s“ ist nicht auf „%s“ gesetzt.", - "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann deine Nextcloud wieder lauffähig machen.", + "Please ask your server administrator to install the module." : "Bitte für die Installation des Moduls die Serveradministration kontaktieren.", + "PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung \"%s\" ist nicht auf \"%s\" gesetzt.", + "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann diese Nextcloud wieder lauffähig machen.", "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> ist auf <code>%s</code> gesetzt und nicht auf den erwarteten Wert <code>0</code>.", - "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Bitte setze zum Beheben dieses Problems <code>mbstring.func_overload</code> in deiner php.ini auf <code>0</code>.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Zum Beheben dieses Problems bitte <code>mbstring.func_overload</code> in der php.ini auf <code>0</code> setzen.", "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ist offenbar so konfiguriert, dass PHPDoc-Blöcke in der Anweisung entfernt werden. Dadurch sind mehrere Kern-Apps nicht erreichbar.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dies wird wahrscheinlich durch Zwischenspeicher/Beschleuniger wie etwa Zend OPcache oder eAccelerator verursacht.", "PHP modules have been installed, but they are still listed as missing?" : "PHP-Module wurden installiert, werden aber als noch fehlend gelistet?", - "Please ask your server administrator to restart the web server." : "Bitte kontaktiere deinen Server-Administrator und bitte um den Neustart des Webservers.", + "Please ask your server administrator to restart the web server." : "Bitte die Serveradministration konatktieren und um Neustart des Webservers bitten.", "The required %s config variable is not configured in the config.php file." : "Die erforderliche %s Konfigurationsvariable ist in der config.php nicht konfiguriert.", - "Please ask your server administrator to check the Nextcloud configuration." : "Bitte deinen Server-Administrator, die Nextcloud-Konfiguration zu überprüfen.", + "Please ask your server administrator to check the Nextcloud configuration." : "Die Serveradministration bitten, die Nextcloud-Konfiguration zu überprüfen.", "Your data directory is readable by other people." : "Dein Datenverzeichnis kann von anderen Benutzern gelesen werden", - "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Bitte ändere die Berechtigungen auf 0770, so dass das Verzeichnis nicht von Anderen angezeigt werden kann.", - "Your data directory must be an absolute path." : "Dein Datenverzeichnis muss einen eindeutigen Pfad haben", - "Check the value of \"datadirectory\" in your configuration." : "Überprüfe bitte die Angabe unter „datadirectory“ in deiner Konfiguration", - "Your data directory is invalid." : "Dein Datenverzeichnis ist ungültig", - "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Stelle sicher, dass eine Datei \"%1$s\" im Wurzelverzeichnis des Datenverzeichnisses existiert. Sie sollte folgenden Inhalt haben: \"%2$s\"", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Bitte die Berechtigungen auf 0770 ändern, so dass das Verzeichnis nicht von Anderen angezeigt werden kann.", + "Your data directory must be an absolute path." : "Das Datenverzeichnis muss einen eindeutigen Pfad haben", + "Check the value of \"datadirectory\" in your configuration." : "Bitte die Angabe unter \"datadirectory\" in der Konfiguration überprüfen.", + "Your data directory is invalid." : "Das Datenverzeichnis ist ungültig", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Bitte sicherstellen, dass eine Datei \"%1$s\" im Wurzelverzeichnis des Datenverzeichnisses existiert. Sie sollte folgenden Inhalt haben: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.", "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder falsche Provider-ID wurde übertragen.", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter, um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"", "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "ID \"%1$s\" wird bereits von Cloud-Federation-Provider \"%2$s\" verwendet", "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.", - "Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.", + "Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf \"%s\" konnte nicht ermittelt werden.", "Storage unauthorized. %s" : "Speicher nicht autorisiert. %s", "Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s", "Storage connection error. %s" : "Verbindungsfehler zum Speicherplatz. %s", "Storage is temporarily not available" : "Speicher ist vorübergehend nicht verfügbar", "Storage connection timeout. %s" : "Zeitüberschreitung der Verbindung zum Speicherplatz. %s", - "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Damit diese Prüfung ausgeführt werden kann, musst du sicherstellen, dass dein Webserver eine Verbindung zu sich selbst herstellen kann. Daher muss er in der Lage sein, mindestens eine seiner `trusted_domains` oder `overwrite.cli.url` aufzulösen und eine Verbindung zu ihnen herzustellen. Dieser Fehler kann das Ergebnis einer serverseitigen DNS-Nichtübereinstimmung oder einer ausgehenden Firewall-Regel sein.", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Damit diese Prüfung ausgeführt werden kann, muß sichergestellt sein, dass der Webserver eine Verbindung zu sich selbst herstellen kann. Daher muss er in der Lage sein, mindestens eine seiner `trusted_domains` oder `overwrite.cli.url` aufzulösen und eine Verbindung zu ihnen herzustellen. Dieser Fehler kann das Ergebnis einer serverseitigen DNS-Nichtübereinstimmung oder einer ausgehenden Firewall-Regel sein.", "Transcribe audio" : "Audio transkribieren", "Transcribe the things said in an audio" : "Inhalt der Audiodatei transkribieren", "Audio input" : "Audioeingang", "The audio to transcribe" : "Die Audio-Datei zum Transkribieren", "Transcription" : "Transkription", "The transcribed text" : "Der transkribierte Text", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "Mit einem Agenten chatten", "Chat message" : "Chatnachricht", - "A chat message to send to the agent." : "Eine Chat-Nachricht, die an den Agenten gesendet wird.", + "A chat message to send to the agent." : "Eine Chatnachricht, die an den Agenten gesendet wird.", "Confirmation" : "Bestätigung", "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Ob zuvor angeforderte Aktionen bestätigt werden sollen: 0 für Verweigerung und 1 für Bestätigung.", "Conversation token" : "Unterhaltungstoken", "A token representing the conversation." : "Ein Token, das die Unterhaltung repräsentiert.", "Generated response" : "Erzeugte Antwort", - "The response from the chat model." : "Die Antwort des Chatmodells.", + "The response from the chat model." : "Die Antwort des Chat-Modells.", "The new conversation token" : "Das neue Unterhaltungstoken", "Send this along with the next interaction." : "Dies zusammen mit der nächsten Interaktion senden.", "Requested actions by the agent" : "Vom Agenten angeforderte Aktionen", @@ -326,7 +346,7 @@ "Context write" : "Kontext schreiben", "Writes text in a given style based on the provided source material." : "Schreibt Text in einem vorgegebenen Stil auf Basis des bereitgestellten Quellmaterials.", "Writing style" : "Schreibstil", - "Demonstrate a writing style that you would like to immitate" : "Zeigen Sie einen Schreibstil, den Sie gerne nachahmen würden", + "Demonstrate a writing style that you would like to immitate" : "Zeige einen Schreibstil, den du gerne nachahmen würden", "Source material" : "Quellmaterial", "The content that would like to be rewritten in the new writing style" : "Der Inhalt, der in den neuen Schreibstil umgeschrieben werden soll", "Generated text" : "Erstellter Text", @@ -339,14 +359,19 @@ "Generate image" : "Bild erstellen", "Generate an image from a text prompt" : "Bild aus einer Texteingabe erstellen", "Prompt" : "Prompt", - "Describe the image you want to generate" : "Beschreibe das Bild, das du erstellen möchtest", + "Describe the image you want to generate" : "Das Bild, das erstellt werden soll, beschreiben", "Number of images" : "Anzahl der Bilder", "How many images to generate" : "Wie viele Bilder erstellt werden sollen", "Output images" : "Ausgegebene Bilder", "The generated images" : "Die erstellten Bilder", + "Generate speech" : "Sprache erstellen", + "Generate speech from a transcript" : "Sprache aus einem Transkript erstellen", + "Write transcript that you want the assistant to generate speech from" : "Schreibe ein Transkript, aus dem der Assistent Sprache erstellen soll", + "Output speech" : "Sprachausgabe", + "The generated speech" : "Die erstellte Sprache", "Free text to text prompt" : "Freie Text-zu-Text-Eingabeaufforderung", "Runs an arbitrary prompt through a language model that returns a reply" : "Führt eine beliebige Eingabeaufforderung mit einem Sprachmodell aus, das eine Antwort zurückgibt", - "Describe a task that you want the assistant to do or ask a question" : "Beschreibe eine Aufgabe, die der Assistent erledigen soll, oder stelle eine Frage", + "Describe a task that you want the assistant to do or ask a question" : "Eine Aufgabe beschreiben, die der Assistent erledigen soll, oder eine Frage stellen", "Generated reply" : "Erstellte Antwort", "The generated text from the assistant" : "Der vom Assistenten erstellte Text", "Change Tone" : "Ton ändern", @@ -382,6 +407,12 @@ "Original text" : "Originaltext", "The original text to generate a headline for" : "Der Originaltext, für den eine Überschrift erstellt werden soll", "The generated headline" : "Die erstellte Überschrift", + "Proofread" : "Korrekturlesen", + "Proofreads a text and lists corrections" : "Liest einen Text Korrektur und listet Korrekturen auf", + "Text" : "Text", + "The text to proofread" : "Der zu korrigierende Text", + "Corrections" : "Korrekturen", + "The corrections that should be made in your text" : "Die Korrekturen, die in deinem Text vorgenommen werden sollten", "Reformulate text" : "Text umformulieren", "Takes a text and reformulates it" : "Formuliert einen Text um", "Write a text that you want the assistant to reformulate" : "Text schreiben, den der Assistent umformulieren soll", @@ -417,41 +448,9 @@ "Generate headline" : "Überschrift erzeugen", "Summarizes text by reducing its length without losing key information." : "Fasst Text zusammen, indem die Länge reduziert wird, ohne dass wichtige Informationen verloren gehen.", "Extracts topics from a text and outputs them separated by commas." : "Extrahiert Themen aus einem Text und gibt sie durch Kommas getrennt aus.", - "Education Edition" : "Bildungsausgabe", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Der angemeldete Benutzer muss ein Administrator, ein Teil-Administrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen. ", - "Logged in user must be an admin or sub admin" : "Der angemeldete Benutzer muss ein (Sub-)Administrator sein", - "Logged in user must be an admin" : "Der angemeldete Benutzer muss ein Administrator sein", - "File name is a reserved word" : "Der Dateiname ist ein reserviertes Wort", - "File name contains at least one invalid character" : "Der Dateiname enthält mindestens ein ungültiges Zeichen", - "File name is too long" : "Dateiname ist zu lang", - "Help" : "Hilfe", - "Users" : "Benutzer", - "Unknown user" : "Unbekannter Benutzer", - "Enter the database username and name for %s" : "Den Datenbankbenutzernamen und den Namen eingeben für %s", - "Enter the database username for %s" : "Den Datenbankbenutzernamen eingeben für %s", - "MySQL username and/or password not valid" : "MySQL-Benutzername und/oder Passwort ungültig", - "Oracle username and/or password not valid" : "Oracle-Benutzername und/oder -Passwort ungültig", - "PostgreSQL username and/or password not valid" : "PostgreSQL-Benutzername und/oder -Passwort ungültig", - "Set an admin username." : "Einen Administrator-Benutzernamen setzen.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s hat »%2$s« mit dir geteilt und möchte folgendes hinzufügen:", - "%1$s shared »%2$s« with you and wants to add" : "%1$shat »%2$s« mit dir geteilt und möchte folgendes hinzufügen", - "»%s« added a note to a file shared with you" : "»%s« hat eine Bemerkung zu einer mit dir geteilten Datei hinzugefügt", - "Open »%s«" : "»%s« öffnen", - "Sharing %s failed, because this item is already shared with user %s" : "Freigabe von %s fehlgeschlagen, da dieses Element schon mit dem Benutzer %s geteilt wird", - "%1$s shared »%2$s« with you" : "%1$s hat »%2$s« mit dir geteilt", - "%1$s shared »%2$s« with you." : "%1$s hat »%2$s« mit dir geteilt.", - "The username is already being used" : "Dieser Benutzername existiert bereits", - "Could not create user" : "Benutzer konnte nicht erstellt werden", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Folgende Zeichen sind im Benutzernamen erlaubt: „a-z“, „A-Z“, „0-9“, Leerzeichen und „_.@-'“", - "A valid username must be provided" : "Es muss ein gültiger Benutzername angegeben werden", - "Username contains whitespace at the beginning or at the end" : "Der Benutzername enthält Leerzeichen am Anfang oder am Ende", - "Username must not consist of dots only" : "Der Benutzername darf nicht nur aus Punkten bestehen", - "Username is invalid because files already exist for this user" : "Der Benutzer ist ungültig, da bereits Dateien von diesem Benutzer existieren", - "User disabled" : "Benutzer deaktiviert", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "Die Datei ist in Benutzung, bitte versuche es später noch einmal", "Cannot download file" : "Datei kann nicht heruntergeladen werden.", - "Your data directory is readable by other users." : "Dein Datenverzeichnis kann von anderen Benutzern gelesen werden", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Bitte ändere die Berechtigungen auf 0770, sodass das Verzeichnis nicht von anderen Benutzern angezeigt werden kann.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stelle sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des data-Verzeichnisses existiert." + "Login is too long" : "Die Anmeldung dauert zu lange" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/de_DE.js b/lib/l10n/de_DE.js index a15f81df2e5..bec27235f0a 100644 --- a/lib/l10n/de_DE.js +++ b/lib/l10n/de_DE.js @@ -1,7 +1,7 @@ OC.L10N.register( "lib", { - "Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!", + "Cannot write into \"config\" directory!" : "Das Schreiben in das \"config\"-Verzeichnis ist nicht möglich!", "This can usually be fixed by giving the web server write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.", "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Wenn Sie jedoch möchten, dass die Datei config.php schreibgeschützt bleiben soll, dann setzen Sie die Option \"config_is_read_only\" in der Datei auf true.", "See %s" : "Siehe %s", @@ -12,7 +12,7 @@ OC.L10N.register( "%s email verification" : "%s E-Mail-Überprüfung", "Email verification" : "E-Mail-Überprüfung", "Click the following button to confirm your email." : "Klicken Sie auf die folgende Schaltfläche, um Ihre E-Mail zu bestätigen.", - "Click the following link to confirm your email." : "Auf den nachfolgenden Link klicken um Ihre E-Mail-Adresse zu bestätigen", + "Click the following link to confirm your email." : "Auf den nachfolgenden Link klicken, um Ihre E-Mail-Adresse zu bestätigen", "Confirm your email" : "Ihre E-Mail-Adresse bestätigen", "Other activities" : "Andere Aktivitäten", "%1$s and %2$s" : "%1$s und %2$s", @@ -24,7 +24,7 @@ OC.L10N.register( "Groupware bundle" : "Groupware-Paket", "Hub bundle" : "Hub-Paket", "Public sector bundle" : "Paket für den öffentlichen Sektor", - "Social sharing bundle" : "Paket für das Teilen in sozialen Medien", + "Social sharing bundle" : "Paket für das Teilen auf sozialen Medien", "PHP %s or higher is required." : "PHP %s oder höher wird benötigt.", "PHP with a version lower than %s is required." : "PHP wird in einer früheren Version als %s benötigt.", "%sbit or higher PHP required." : "%sbit oder höheres PHP wird benötigt.", @@ -37,9 +37,9 @@ OC.L10N.register( "The following platforms are supported: %s" : "Folgende Plattformen werden unterstützt: %s", "Server version %s or higher is required." : "Server Version %s oder höher wird benötigt.", "Server version %s or lower is required." : "Server Version %s oder niedriger wird benötigt.", - "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Das angemeldete Konto muss ein Administrator, ein Teil-Administrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen", - "Your current IP address doesn’t allow you to perform admin actions" : "Unter Ihrer aktuellen IP-Adresse sind keine Administrationsaktionen erlaubt", - "Logged in account must be an admin or sub admin" : "Das angemeldete Konto muss ein (Sub-)Administrator sein", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Das angemeldete Konto muss ein Administrator, ein Unteradministrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen", + "Your current IP address doesn't allow you to perform admin actions" : "Unter Ihrer aktuellen IP-Adresse sind keine Administrationsaktionen erlaubt", + "Logged in account must be an admin or sub admin" : "Das angemeldete Konto muss ein (Unter-)Administrator sein", "Logged in account must be an admin" : "Das angemeldete Konto muss ein Administrator sein", "Wiping of device %s has started" : "Löschen von Gerät %s wurde gestartet", "Wiping of device »%s« has started" : "Löschen von Gerät »%s« wurde gestartet", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Avatar-Bild ist nicht quadratisch", "Files" : "Dateien", "View profile" : "Profil ansehen", + "same time" : "gleiche Zeit", + "_%nh_::_%nh_" : ["%n Stunde","%n Std"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s voraus", + "%s behind" : "%s zurück", "Local time: %s" : "Ortszeit: %s", "today" : "Heute", "tomorrow" : "Morgen", @@ -80,8 +85,16 @@ OC.L10N.register( "in a few seconds" : "In wenigen Sekunden", "seconds ago" : "Gerade eben", "Empty file" : "Leere Datei", - "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Das Modul mit der ID: %s existiert nicht. Bitte aktivieren Sie es in Ihren Einstellungen oder kontaktieren Sie Ihren Administrator.", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Das Modul mit der ID: %s existiert nicht. Bitte aktivieren Sie es in Ihren Einstellungen oder kontaktieren Sie Ihre Administration.", + "No file conversion providers available" : "Keine Dateikonvertierungsanbieter verfügbar", + "File is too large to convert" : "Die Datei ist zu groß zum Konvertieren", + "Destination does not match conversion extension" : "Das Ziel stimmt nicht mit der Konvertierungs-Erweiterung überein", + "Could not convert file" : "Datei konnte nicht konvertiert werden", + "Destination does not exist" : "Ziel existiert nicht", + "Destination is not creatable" : "Ziel kann nicht erstellt werden", "Dot files are not allowed" : "Dateinamen mit einem Punkt am Anfang sind nicht erlaubt", + "%1$s (renamed)" : "%1$s (umbenannt)", + "renamed file" : "Umbenannte Datei", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" ist ein verbotener Datei- oder Ordnername.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" ist ein verbotenes Präfix für Datei- oder Ordnernamen.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" ist in einem Datei- oder Ordnernamen unzulässig.", @@ -90,8 +103,15 @@ OC.L10N.register( "Invalid parent path" : "Ungültiger übergeordneter Pfad", "File already exists" : "Datei bereits vorhanden", "Invalid path" : "Ungültiger Pfad", - "Failed to create file from template" : "Fehler beim Erstellen der Datei aus Vorlage", + "Failed to create file from template" : "Datei konnte nicht aus Vorlage erstellt werden", "Templates" : "Vorlagen", + "Storage %s cannot be moved" : "Speicherplatz %s kann nicht verschoben werden", + "Moving a share (%s) into a shared folder is not allowed" : "Verschieben einer Freigabe (%s) in einen freigegebenen Ordner ist unzulässig", + "Moving a storage (%s) into a shared folder is not allowed" : "Verschieben eines Speicherplatzes (%s) in einen freigegebenen Ordner ist unzulässig", + "Moving a share (%s) into another share (%s) is not allowed" : "Verschieben einer Freigabe (%s) in eine andere Freigabe (%s) ist unzulässig.", + "Moving a share (%s) into another storage (%s) is not allowed" : "Verschieben einer Freigabe (%s) in einen anderen Speicherplatz (%s) ist nicht erlaubt", + "Moving a storage (%s) into a share (%s) is not allowed" : "Verschieben eines Speicherplatzes (%s) in eine Freigabe (%s) ist nicht erlaubt", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Verschieben eines Speicherplatzes (%s) in einen anderen Speicherplatz (%s) ist nicht erlaubt", "Path contains invalid segments" : "Pfad enthält ungültige Segmente", "Filename is a reserved word" : "Der Dateiname ist ein reserviertes Wort", "Filename contains at least one invalid character" : "Der Dateiname enthält mindestens ein unzulässiges Zeichen", @@ -115,7 +135,7 @@ OC.L10N.register( "View %s on the fediverse" : "Zeige %s auf dem Fediverse", "Phone" : "Telefon", "Call %s" : "%s anrufen", - "Twitter" : "Twitter", + "Twitter" : "X", "View %s on Twitter" : "%s auf Twitter anzeigen", "Website" : "Webseite", "Visit %s" : "%s besuchen", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "Über", "Display name" : "Anzeigename", "Headline" : "Überschrift", - "Organisation" : "Organisation", + "Organization" : "Organisation", "Role" : "Funktion", "Pronouns" : "Pronomen", "Unknown account" : "Unbekanntes Konto", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Es konnte keine Verbindung zur Oracle-Datenbank hergestellt werden", "Oracle Login and/or password not valid" : "Oracle-Anmeldename und/oder -Passwort ungültig", "PostgreSQL Login and/or password not valid" : "PostgreSQL-Anmeldename und/oder Passwort ungültig", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X wird nicht unterstützt und %s wird auf dieser Plattform nicht richtig funktionieren. Die Benutzung erfolgt auf eigene Gefahr!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X wird nicht unterstützt und %s wird unter dieser Plattform nicht richtig funktionieren. Verwendung auf eigene Gefahr!", "For the best results, please consider using a GNU/Linux server instead." : "Zur Gewährleistung eines optimalen Betriebs sollte stattdessen ein GNU/Linux-Server verwendet werden.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Es scheint, dass diese %s-Instanz unter einer 32-Bit-PHP-Umgebung läuft und open_basedir in der Datei php.ini konfiguriert worden ist. Von einem solchen Betrieb wird dringend abgeraten, weil es dabei zu Problemen mit Dateien kommt, deren Größe 4 GB übersteigt.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte entfernen Sie die open_basedir-Einstellung in Ihrer php.ini oder wechseln Sie zu 64-Bit-PHP.", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Freigabe-Backend %s nicht gefunden", "Sharing backend for %s not found" : "Freigabe-Backend für %s nicht gefunden", "%1$s shared %2$s with you" : "%1$s hat %2$s mit Ihnen geteilt", - "Click the button below to open it." : "Klicken Sie zum Öffnen auf die untere Schaltfläche.", "Open %s" : "%s öffnen", "%1$s via %2$s" : "%1$s über %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s hat %2$s mit Ihnen geteilt und möchte hinzufügen:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "Sie können Ihren Stammordner nicht freigeben", "You are not allowed to share %s" : "Die Freigabe von %s ist Ihnen nicht erlaubt", "Valid permissions are required for sharing" : "Zum Teilen sind gültige Berechtigungen erforderlich", + "File shares cannot have create or delete permissions" : "Dateifreigaben können keine Berechtigungen zum Erstellen oder Löschen haben", "Cannot increase permissions of %s" : "Kann die Berechtigungen von %s nicht erhöhen", "Shares need at least read permissions" : "Freigaben benötigen mindestens Leseberechtigungen", "Files cannot be shared with delete permissions" : "Dateien mit Lösch-Berechtigungen können nicht geteilt werden", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Der Pfad ist bereits mit dieser Gruppe geteilt", "Link sharing is not allowed" : "Freigabe via Link ist nicht erlaubt", "Public upload is not allowed" : "Öffentliches Hochladen ist nicht erlaubt", - "Path contains files shared with you" : "Der Pfad enthält für Sie freigegebene Dateien", + "You cannot share a folder that contains other shares" : "Ein Ordner, der andere Freigaben enthält, kann nicht geteilt werden", "Sharing is disabled" : "Teilen ist deaktiviert", "Sharing is disabled for you" : "Teilen ist für Sie deaktiviert", "Cannot share with the share owner" : "Teilen mit dem Freigabeeigentümer nicht möglich", @@ -200,7 +220,7 @@ OC.L10N.register( "The requested share does not exist anymore" : "Die angeforderte Freigabe existiert nicht mehr", "The requested share comes from a disabled user" : "Die angeforderte Freigabe stammt von einem deaktivierten Benutzer", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Der Benutzer wurde nicht erstellt, da das Benutzerlimit erreicht wurde. Überprüfen Sie Ihre Benachrichtigungen, um mehr zu erfahren.", - "Could not find category \"%s\"" : "Die Kategorie \"%s“ konnte nicht gefunden werden", + "Could not find category \"%s\"" : "Die Kategorie \"%s\" konnte nicht gefunden werden", "Input text" : "Texteingabe", "The input text" : "Der Eingabetext", "Sunday" : "Sonntag", @@ -255,10 +275,11 @@ OC.L10N.register( "A valid Login must be provided" : "Ein gültiger Anmeldename muss angegeben werden.", "Login contains whitespace at the beginning or at the end" : "Anmeldename enthält Leerzeichen am Anfang oder am Ende", "Login must not consist of dots only" : "Der Anmeldename darf nicht nur aus Punkten bestehen", + "Username is too long" : "Benutzername ist zu lang", "Login is invalid because files already exist for this user" : "Der Anmeldename ist ungültig, da bereits Dateien von diesem Benutzer existieren", "Account disabled" : "Konto deaktiviert", "Login canceled by app" : "Anmeldung durch die App abgebrochen", - "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App „%1$s“ kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s", + "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App \"%1$s\" kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s", "a safe home for all your data" : "ein sicherer Ort für all Ihre Daten", "Application is not enabled" : "Die Anwendung ist nicht aktiviert", "Authentication error" : "Authentifizierungsfehler", @@ -276,29 +297,29 @@ OC.L10N.register( "Setting locale to %s failed." : "Das Setzen der Sprache (locale) auf %s ist fehlgeschlagen.", "Please install one of these locales on your system and restart your web server." : "Bitte installieren Sie eine dieser Sprachen (locales) auf Ihrem System und starten Sie den Webserver neu.", "PHP module %s not installed." : "PHP-Modul %s nicht installiert.", - "Please ask your server administrator to install the module." : "Bitte kontaktieren Sie Ihre Server-Administration und bitten Sie um die Installation des Moduls.", - "PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung „%s“ ist nicht auf „%s“ gesetzt.", + "Please ask your server administrator to install the module." : "Bitte kontaktieren Sie Ihre Serveradministration und bitten Sie um die Installation des Moduls.", + "PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung \"%s\" ist nicht auf \"%s\" gesetzt.", "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann Ihre Nextcloud wieder lauffähig machen.", "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> ist auf <code>%s</code> gesetzt und nicht auf den erwarteten Wert <code>0</code>.", "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Bitte setzen Sie zum Beheben dieses Problems <code>mbstring.func_overload</code> in Ihrer php.ini auf <code>0</code>.", "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ist offenbar so konfiguriert, dass PHPDoc-Blöcke in der Anweisung entfernt werden. Dadurch sind mehrere Kern-Apps nicht erreichbar.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dies wird wahrscheinlich durch Zwischenspeicher/Beschleuniger wie etwa Zend OPcache oder eAccelerator verursacht.", "PHP modules have been installed, but they are still listed as missing?" : "PHP-Module wurden installiert, werden aber als noch fehlend gelistet?", - "Please ask your server administrator to restart the web server." : "Bitte kontaktieren Sie Ihre Server-Administration und bitten Sie um den Neustart des Webservers.", + "Please ask your server administrator to restart the web server." : "Bitte kontaktieren Sie Ihre Serveradministration und bitten Sie um den Neustart des Webservers.", "The required %s config variable is not configured in the config.php file." : "Die erforderliche %s Konfigurationsvariable ist in der config.php nicht konfiguriert.", - "Please ask your server administrator to check the Nextcloud configuration." : "Bitten Sie Ihre Server-Administration, die Nextcloud-Konfiguration zu überprüfen.", + "Please ask your server administrator to check the Nextcloud configuration." : "Bitten Sie Ihre Serveradministration, die Nextcloud-Konfiguration zu überprüfen.", "Your data directory is readable by other people." : "Ihr Datenverzeichnis kann von Anderen gelesen werden.", "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Bitte ändern Sie die Berechtigungen auf 0770, so dass das Verzeichnis nicht von Anderen angezeigt werden kann.", "Your data directory must be an absolute path." : "Ihr Datenverzeichnis muss einen absoluten Pfad haben.", - "Check the value of \"datadirectory\" in your configuration." : "Überprüfen Sie den Wert von „datadirectory“ in Ihrer Konfiguration.", + "Check the value of \"datadirectory\" in your configuration." : "Überprüfen Sie den Wert von \"datadirectory\" in Ihrer Konfiguration.", "Your data directory is invalid." : "Ihr Datenverzeichnis ist ungültig.", "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Stellen Sie sicher, dass eine Datei \"%1$s\" im Wurzelverzeichnis des Datenverzeichnisses existiert. Sie sollte folgenden Inhalt haben: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.", - "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.", + "Authentication failed, wrong token or provider ID given" : "Authentifizierung fehlgeschlagen, falsches Token oder falsche Provider-ID angegeben", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"", "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "ID \"%1$s\" wird bereits von Cloud-Federation-Provider \"%2$s\" verwendet.", "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.", - "Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.", + "Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf \"%s\" konnte nicht ermittelt werden.", "Storage unauthorized. %s" : "Speicher nicht autorisiert. %s", "Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s", "Storage connection error. %s" : "Verbindungsfehler zum Speicherplatz. %s", @@ -311,16 +332,15 @@ OC.L10N.register( "The audio to transcribe" : "Die Audio-Datei zum Transkribieren", "Transcription" : "Transkription", "The transcribed text" : "Der transkribierte Text", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "Chatten Sie mit einem Agenten", "Chat message" : "Chatnachricht", - "A chat message to send to the agent." : "Eine Chat-Nachricht, die an den Agenten gesendet wird.", + "A chat message to send to the agent." : "Eine Chatnachricht, die an den Agenten gesendet wird.", "Confirmation" : "Bestätigung", "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Ob zuvor angeforderte Aktionen bestätigt werden sollen: 0 für Verweigerung und 1 für Bestätigung.", "Conversation token" : "Unterhaltungstoken", "A token representing the conversation." : "Ein Token, das die Unterhaltung repräsentiert.", "Generated response" : "Erzeugte Antwort", - "The response from the chat model." : "Die Antwort des Chatmodells.", + "The response from the chat model." : "Die Antwort des Chat-Modells.", "The new conversation token" : "Das neue Unterhaltungstoken", "Send this along with the next interaction." : "Dies zusammen mit der nächsten Interaktion senden.", "Requested actions by the agent" : "Vom Agenten angeforderte Aktionen", @@ -346,6 +366,11 @@ OC.L10N.register( "How many images to generate" : "Wie viele Bilder erstellt werden sollen", "Output images" : "Ausgegebene Bilder", "The generated images" : "Die erstellten Bilder", + "Generate speech" : "Sprache erstellen", + "Generate speech from a transcript" : "Sprache aus einem Transkript erstellen", + "Write transcript that you want the assistant to generate speech from" : "Schreiben Sie ein Transkript, aus dem der Assistent Sprache erstellen soll", + "Output speech" : "Sprachausgabe", + "The generated speech" : "Die erstellte Sprache", "Free text to text prompt" : "Freie Text-zu-Text-Eingabeaufforderung", "Runs an arbitrary prompt through a language model that returns a reply" : "Führt eine beliebige Eingabeaufforderung mit einem Sprachmodell aus, das eine Antwort zurückgibt", "Describe a task that you want the assistant to do or ask a question" : "Beschreiben Sie eine Aufgabe, die der Assistent erledigen soll, oder stellen Sie eine Frage", @@ -384,6 +409,12 @@ OC.L10N.register( "Original text" : "Originaltext", "The original text to generate a headline for" : "Der Originaltext, für den eine Überschrift erstellt werden soll", "The generated headline" : "Die erstellte Überschrift", + "Proofread" : "Korrekturlesen", + "Proofreads a text and lists corrections" : "Liest einen Text Korrektur und listet Korrekturen auf", + "Text" : "Text", + "The text to proofread" : "Der zu korrigierende Text", + "Corrections" : "Korrekturen", + "The corrections that should be made in your text" : "Die Korrekturen, die in Ihrem Text vorgenommen werden sollten", "Reformulate text" : "Text umformulieren", "Takes a text and reformulates it" : "Formuliert einen Text um", "Write a text that you want the assistant to reformulate" : "Text schreiben, den der Assistent umformulieren soll", @@ -419,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Kopfzeile erzeugen", "Summarizes text by reducing its length without losing key information." : "Fasst Text zusammen, indem die Länge reduziert wird, ohne dass wichtige Informationen verloren gehen.", "Extracts topics from a text and outputs them separated by commas." : "Extrahiert Themen aus einem Text und gibt sie durch Kommas getrennt aus.", - "Education Edition" : "Bildungsausgabe", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Der angemeldete Benutzer muss ein Administrator, ein Teil-Administrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen. ", - "Logged in user must be an admin or sub admin" : "Der angemeldete Benutzer muss ein (Sub-)Administrator sein", - "Logged in user must be an admin" : "Der angemeldete Benutzer muss ein Administrator sein", - "File name is a reserved word" : "Der Dateiname ist ein reserviertes Wort", - "File name contains at least one invalid character" : "Der Dateiname enthält mindestens ein ungültiges Zeichen", - "File name is too long" : "Dateiname ist zu lang", - "Help" : "Hilfe", - "Users" : "Benutzer", - "Unknown user" : "Unbekannter Benutzer", - "Enter the database username and name for %s" : "Den Datenbankbenutzernamen und den Namen eingeben für %s", - "Enter the database username for %s" : "Den Datenbankbenutzernamen eingeben für %s", - "MySQL username and/or password not valid" : "MySQL-Benutzername und/oder Passwort ungültig", - "Oracle username and/or password not valid" : "Oracle-Benutzername und/oder -Passwort ungültig", - "PostgreSQL username and/or password not valid" : "PostgreSQL-Benutzername und/oder -Passwort ungültig", - "Set an admin username." : "Einen Administrations-Benutzernamen setzen.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s hat »%2$s« mit Ihnen geteilt und möchte folgendes hinzufügen:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s hat »%2$s« mit Ihnen geteilt und möchte folgendes hinzufügen", - "»%s« added a note to a file shared with you" : "»%s« hat eine Bemerkung zu einer mit Ihnen geteilten Datei hinzugefügt", - "Open »%s«" : "»%s« öffnen", - "Sharing %s failed, because this item is already shared with user %s" : "Freigabe von %s fehlgeschlagen, da dieses Element schon mit dem Benutzer %s geteilt wird", - "%1$s shared »%2$s« with you" : "%1$s hat »%2$s« mit Ihnen geteilt", - "%1$s shared »%2$s« with you." : "%1$s hat »%2$s« mit Ihnen geteilt.", - "The username is already being used" : "Dieser Benutzername existiert bereits", - "Could not create user" : "Benutzer konnte nicht erstellt werden", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Folgende Zeichen sind im Benutzernamen erlaubt: „a-z“, „A-Z“, „0-9“, Leerzeichen und „_.@-'“", - "A valid username must be provided" : "Es muss ein gültiger Benutzername angegeben werden", - "Username contains whitespace at the beginning or at the end" : "Der Benutzername enthält Leerzeichen am Anfang oder am Ende", - "Username must not consist of dots only" : "Der Benutzername darf nicht nur aus Punkten bestehen", - "Username is invalid because files already exist for this user" : "Der Benutzer ist ungültig, da bereits Dateien von diesem Benutzer existieren", - "User disabled" : "Benutzer deaktiviert", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "Die Datei ist in Benutzung, bitte später erneut versuchen.", "Cannot download file" : "Datei kann nicht heruntergeladen werden", - "Your data directory is readable by other users." : "Ihr Datenverzeichnis kann von anderen Benutzern gelesen werden.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Bitte ändern Sie die Berechtigungen auf 0770, so dass das Verzeichnis nicht von anderen Benutzern angezeigt werden kann.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stellen Sie sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des Datenverzeichnisses existiert." + "Login is too long" : "Der Kontenname ist zu lang" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/de_DE.json b/lib/l10n/de_DE.json index e884f9f7c54..5644ed13baf 100644 --- a/lib/l10n/de_DE.json +++ b/lib/l10n/de_DE.json @@ -1,5 +1,5 @@ { "translations": { - "Cannot write into \"config\" directory!" : "Das Schreiben in das „config“-Verzeichnis ist nicht möglich!", + "Cannot write into \"config\" directory!" : "Das Schreiben in das \"config\"-Verzeichnis ist nicht möglich!", "This can usually be fixed by giving the web server write access to the config directory." : "Dies kann normalerweise behoben werden, indem dem Webserver Schreibzugriff auf das config-Verzeichnis gegeben wird.", "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Wenn Sie jedoch möchten, dass die Datei config.php schreibgeschützt bleiben soll, dann setzen Sie die Option \"config_is_read_only\" in der Datei auf true.", "See %s" : "Siehe %s", @@ -10,7 +10,7 @@ "%s email verification" : "%s E-Mail-Überprüfung", "Email verification" : "E-Mail-Überprüfung", "Click the following button to confirm your email." : "Klicken Sie auf die folgende Schaltfläche, um Ihre E-Mail zu bestätigen.", - "Click the following link to confirm your email." : "Auf den nachfolgenden Link klicken um Ihre E-Mail-Adresse zu bestätigen", + "Click the following link to confirm your email." : "Auf den nachfolgenden Link klicken, um Ihre E-Mail-Adresse zu bestätigen", "Confirm your email" : "Ihre E-Mail-Adresse bestätigen", "Other activities" : "Andere Aktivitäten", "%1$s and %2$s" : "%1$s und %2$s", @@ -22,7 +22,7 @@ "Groupware bundle" : "Groupware-Paket", "Hub bundle" : "Hub-Paket", "Public sector bundle" : "Paket für den öffentlichen Sektor", - "Social sharing bundle" : "Paket für das Teilen in sozialen Medien", + "Social sharing bundle" : "Paket für das Teilen auf sozialen Medien", "PHP %s or higher is required." : "PHP %s oder höher wird benötigt.", "PHP with a version lower than %s is required." : "PHP wird in einer früheren Version als %s benötigt.", "%sbit or higher PHP required." : "%sbit oder höheres PHP wird benötigt.", @@ -35,9 +35,9 @@ "The following platforms are supported: %s" : "Folgende Plattformen werden unterstützt: %s", "Server version %s or higher is required." : "Server Version %s oder höher wird benötigt.", "Server version %s or lower is required." : "Server Version %s oder niedriger wird benötigt.", - "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Das angemeldete Konto muss ein Administrator, ein Teil-Administrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen", - "Your current IP address doesn’t allow you to perform admin actions" : "Unter Ihrer aktuellen IP-Adresse sind keine Administrationsaktionen erlaubt", - "Logged in account must be an admin or sub admin" : "Das angemeldete Konto muss ein (Sub-)Administrator sein", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Das angemeldete Konto muss ein Administrator, ein Unteradministrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen", + "Your current IP address doesn't allow you to perform admin actions" : "Unter Ihrer aktuellen IP-Adresse sind keine Administrationsaktionen erlaubt", + "Logged in account must be an admin or sub admin" : "Das angemeldete Konto muss ein (Unter-)Administrator sein", "Logged in account must be an admin" : "Das angemeldete Konto muss ein Administrator sein", "Wiping of device %s has started" : "Löschen von Gerät %s wurde gestartet", "Wiping of device »%s« has started" : "Löschen von Gerät »%s« wurde gestartet", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Avatar-Bild ist nicht quadratisch", "Files" : "Dateien", "View profile" : "Profil ansehen", + "same time" : "gleiche Zeit", + "_%nh_::_%nh_" : ["%n Stunde","%n Std"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s voraus", + "%s behind" : "%s zurück", "Local time: %s" : "Ortszeit: %s", "today" : "Heute", "tomorrow" : "Morgen", @@ -78,8 +83,16 @@ "in a few seconds" : "In wenigen Sekunden", "seconds ago" : "Gerade eben", "Empty file" : "Leere Datei", - "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Das Modul mit der ID: %s existiert nicht. Bitte aktivieren Sie es in Ihren Einstellungen oder kontaktieren Sie Ihren Administrator.", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Das Modul mit der ID: %s existiert nicht. Bitte aktivieren Sie es in Ihren Einstellungen oder kontaktieren Sie Ihre Administration.", + "No file conversion providers available" : "Keine Dateikonvertierungsanbieter verfügbar", + "File is too large to convert" : "Die Datei ist zu groß zum Konvertieren", + "Destination does not match conversion extension" : "Das Ziel stimmt nicht mit der Konvertierungs-Erweiterung überein", + "Could not convert file" : "Datei konnte nicht konvertiert werden", + "Destination does not exist" : "Ziel existiert nicht", + "Destination is not creatable" : "Ziel kann nicht erstellt werden", "Dot files are not allowed" : "Dateinamen mit einem Punkt am Anfang sind nicht erlaubt", + "%1$s (renamed)" : "%1$s (umbenannt)", + "renamed file" : "Umbenannte Datei", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" ist ein verbotener Datei- oder Ordnername.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" ist ein verbotenes Präfix für Datei- oder Ordnernamen.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" ist in einem Datei- oder Ordnernamen unzulässig.", @@ -88,8 +101,15 @@ "Invalid parent path" : "Ungültiger übergeordneter Pfad", "File already exists" : "Datei bereits vorhanden", "Invalid path" : "Ungültiger Pfad", - "Failed to create file from template" : "Fehler beim Erstellen der Datei aus Vorlage", + "Failed to create file from template" : "Datei konnte nicht aus Vorlage erstellt werden", "Templates" : "Vorlagen", + "Storage %s cannot be moved" : "Speicherplatz %s kann nicht verschoben werden", + "Moving a share (%s) into a shared folder is not allowed" : "Verschieben einer Freigabe (%s) in einen freigegebenen Ordner ist unzulässig", + "Moving a storage (%s) into a shared folder is not allowed" : "Verschieben eines Speicherplatzes (%s) in einen freigegebenen Ordner ist unzulässig", + "Moving a share (%s) into another share (%s) is not allowed" : "Verschieben einer Freigabe (%s) in eine andere Freigabe (%s) ist unzulässig.", + "Moving a share (%s) into another storage (%s) is not allowed" : "Verschieben einer Freigabe (%s) in einen anderen Speicherplatz (%s) ist nicht erlaubt", + "Moving a storage (%s) into a share (%s) is not allowed" : "Verschieben eines Speicherplatzes (%s) in eine Freigabe (%s) ist nicht erlaubt", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Verschieben eines Speicherplatzes (%s) in einen anderen Speicherplatz (%s) ist nicht erlaubt", "Path contains invalid segments" : "Pfad enthält ungültige Segmente", "Filename is a reserved word" : "Der Dateiname ist ein reserviertes Wort", "Filename contains at least one invalid character" : "Der Dateiname enthält mindestens ein unzulässiges Zeichen", @@ -113,7 +133,7 @@ "View %s on the fediverse" : "Zeige %s auf dem Fediverse", "Phone" : "Telefon", "Call %s" : "%s anrufen", - "Twitter" : "Twitter", + "Twitter" : "X", "View %s on Twitter" : "%s auf Twitter anzeigen", "Website" : "Webseite", "Visit %s" : "%s besuchen", @@ -122,7 +142,7 @@ "About" : "Über", "Display name" : "Anzeigename", "Headline" : "Überschrift", - "Organisation" : "Organisation", + "Organization" : "Organisation", "Role" : "Funktion", "Pronouns" : "Pronomen", "Unknown account" : "Unbekanntes Konto", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "Es konnte keine Verbindung zur Oracle-Datenbank hergestellt werden", "Oracle Login and/or password not valid" : "Oracle-Anmeldename und/oder -Passwort ungültig", "PostgreSQL Login and/or password not valid" : "PostgreSQL-Anmeldename und/oder Passwort ungültig", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X wird nicht unterstützt und %s wird auf dieser Plattform nicht richtig funktionieren. Die Benutzung erfolgt auf eigene Gefahr!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X wird nicht unterstützt und %s wird unter dieser Plattform nicht richtig funktionieren. Verwendung auf eigene Gefahr!", "For the best results, please consider using a GNU/Linux server instead." : "Zur Gewährleistung eines optimalen Betriebs sollte stattdessen ein GNU/Linux-Server verwendet werden.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Es scheint, dass diese %s-Instanz unter einer 32-Bit-PHP-Umgebung läuft und open_basedir in der Datei php.ini konfiguriert worden ist. Von einem solchen Betrieb wird dringend abgeraten, weil es dabei zu Problemen mit Dateien kommt, deren Größe 4 GB übersteigt.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bitte entfernen Sie die open_basedir-Einstellung in Ihrer php.ini oder wechseln Sie zu 64-Bit-PHP.", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "Freigabe-Backend %s nicht gefunden", "Sharing backend for %s not found" : "Freigabe-Backend für %s nicht gefunden", "%1$s shared %2$s with you" : "%1$s hat %2$s mit Ihnen geteilt", - "Click the button below to open it." : "Klicken Sie zum Öffnen auf die untere Schaltfläche.", "Open %s" : "%s öffnen", "%1$s via %2$s" : "%1$s über %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s hat %2$s mit Ihnen geteilt und möchte hinzufügen:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "Sie können Ihren Stammordner nicht freigeben", "You are not allowed to share %s" : "Die Freigabe von %s ist Ihnen nicht erlaubt", "Valid permissions are required for sharing" : "Zum Teilen sind gültige Berechtigungen erforderlich", + "File shares cannot have create or delete permissions" : "Dateifreigaben können keine Berechtigungen zum Erstellen oder Löschen haben", "Cannot increase permissions of %s" : "Kann die Berechtigungen von %s nicht erhöhen", "Shares need at least read permissions" : "Freigaben benötigen mindestens Leseberechtigungen", "Files cannot be shared with delete permissions" : "Dateien mit Lösch-Berechtigungen können nicht geteilt werden", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "Der Pfad ist bereits mit dieser Gruppe geteilt", "Link sharing is not allowed" : "Freigabe via Link ist nicht erlaubt", "Public upload is not allowed" : "Öffentliches Hochladen ist nicht erlaubt", - "Path contains files shared with you" : "Der Pfad enthält für Sie freigegebene Dateien", + "You cannot share a folder that contains other shares" : "Ein Ordner, der andere Freigaben enthält, kann nicht geteilt werden", "Sharing is disabled" : "Teilen ist deaktiviert", "Sharing is disabled for you" : "Teilen ist für Sie deaktiviert", "Cannot share with the share owner" : "Teilen mit dem Freigabeeigentümer nicht möglich", @@ -198,7 +218,7 @@ "The requested share does not exist anymore" : "Die angeforderte Freigabe existiert nicht mehr", "The requested share comes from a disabled user" : "Die angeforderte Freigabe stammt von einem deaktivierten Benutzer", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Der Benutzer wurde nicht erstellt, da das Benutzerlimit erreicht wurde. Überprüfen Sie Ihre Benachrichtigungen, um mehr zu erfahren.", - "Could not find category \"%s\"" : "Die Kategorie \"%s“ konnte nicht gefunden werden", + "Could not find category \"%s\"" : "Die Kategorie \"%s\" konnte nicht gefunden werden", "Input text" : "Texteingabe", "The input text" : "Der Eingabetext", "Sunday" : "Sonntag", @@ -253,10 +273,11 @@ "A valid Login must be provided" : "Ein gültiger Anmeldename muss angegeben werden.", "Login contains whitespace at the beginning or at the end" : "Anmeldename enthält Leerzeichen am Anfang oder am Ende", "Login must not consist of dots only" : "Der Anmeldename darf nicht nur aus Punkten bestehen", + "Username is too long" : "Benutzername ist zu lang", "Login is invalid because files already exist for this user" : "Der Anmeldename ist ungültig, da bereits Dateien von diesem Benutzer existieren", "Account disabled" : "Konto deaktiviert", "Login canceled by app" : "Anmeldung durch die App abgebrochen", - "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App „%1$s“ kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s", + "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Die App \"%1$s\" kann nicht installiert werden, da die folgenden Abhängigkeiten nicht erfüllt sind: %2$s", "a safe home for all your data" : "ein sicherer Ort für all Ihre Daten", "Application is not enabled" : "Die Anwendung ist nicht aktiviert", "Authentication error" : "Authentifizierungsfehler", @@ -274,29 +295,29 @@ "Setting locale to %s failed." : "Das Setzen der Sprache (locale) auf %s ist fehlgeschlagen.", "Please install one of these locales on your system and restart your web server." : "Bitte installieren Sie eine dieser Sprachen (locales) auf Ihrem System und starten Sie den Webserver neu.", "PHP module %s not installed." : "PHP-Modul %s nicht installiert.", - "Please ask your server administrator to install the module." : "Bitte kontaktieren Sie Ihre Server-Administration und bitten Sie um die Installation des Moduls.", - "PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung „%s“ ist nicht auf „%s“ gesetzt.", + "Please ask your server administrator to install the module." : "Bitte kontaktieren Sie Ihre Serveradministration und bitten Sie um die Installation des Moduls.", + "PHP setting \"%s\" is not set to \"%s\"." : "PHP-Einstellung \"%s\" ist nicht auf \"%s\" gesetzt.", "Adjusting this setting in php.ini will make Nextcloud run again" : "Eine Änderung dieser Einstellung in der php.ini kann Ihre Nextcloud wieder lauffähig machen.", "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> ist auf <code>%s</code> gesetzt und nicht auf den erwarteten Wert <code>0</code>.", "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Bitte setzen Sie zum Beheben dieses Problems <code>mbstring.func_overload</code> in Ihrer php.ini auf <code>0</code>.", "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ist offenbar so konfiguriert, dass PHPDoc-Blöcke in der Anweisung entfernt werden. Dadurch sind mehrere Kern-Apps nicht erreichbar.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Dies wird wahrscheinlich durch Zwischenspeicher/Beschleuniger wie etwa Zend OPcache oder eAccelerator verursacht.", "PHP modules have been installed, but they are still listed as missing?" : "PHP-Module wurden installiert, werden aber als noch fehlend gelistet?", - "Please ask your server administrator to restart the web server." : "Bitte kontaktieren Sie Ihre Server-Administration und bitten Sie um den Neustart des Webservers.", + "Please ask your server administrator to restart the web server." : "Bitte kontaktieren Sie Ihre Serveradministration und bitten Sie um den Neustart des Webservers.", "The required %s config variable is not configured in the config.php file." : "Die erforderliche %s Konfigurationsvariable ist in der config.php nicht konfiguriert.", - "Please ask your server administrator to check the Nextcloud configuration." : "Bitten Sie Ihre Server-Administration, die Nextcloud-Konfiguration zu überprüfen.", + "Please ask your server administrator to check the Nextcloud configuration." : "Bitten Sie Ihre Serveradministration, die Nextcloud-Konfiguration zu überprüfen.", "Your data directory is readable by other people." : "Ihr Datenverzeichnis kann von Anderen gelesen werden.", "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Bitte ändern Sie die Berechtigungen auf 0770, so dass das Verzeichnis nicht von Anderen angezeigt werden kann.", "Your data directory must be an absolute path." : "Ihr Datenverzeichnis muss einen absoluten Pfad haben.", - "Check the value of \"datadirectory\" in your configuration." : "Überprüfen Sie den Wert von „datadirectory“ in Ihrer Konfiguration.", + "Check the value of \"datadirectory\" in your configuration." : "Überprüfen Sie den Wert von \"datadirectory\" in Ihrer Konfiguration.", "Your data directory is invalid." : "Ihr Datenverzeichnis ist ungültig.", "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Stellen Sie sicher, dass eine Datei \"%1$s\" im Wurzelverzeichnis des Datenverzeichnisses existiert. Sie sollte folgenden Inhalt haben: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Aktion \"%s\" wird nicht unterstützt oder ist nicht implementiert.", - "Authentication failed, wrong token or provider ID given" : "Authentifizierung ist fehlgeschlagen. Falsches Token oder Provider-ID wurde übertragen.", + "Authentication failed, wrong token or provider ID given" : "Authentifizierung fehlgeschlagen, falsches Token oder falsche Provider-ID angegeben", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Es fehlen Parameter um die Anfrage zu bearbeiten. Fehlende Parameter: \"%s\"", "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "ID \"%1$s\" wird bereits von Cloud-Federation-Provider \"%2$s\" verwendet.", "Cloud Federation Provider with ID: \"%s\" does not exist." : "Cloud-Federation-Provider mit ID: \"%s\" ist nicht vorhanden.", - "Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf „%s“ konnte nicht ermittelt werden.", + "Could not obtain lock type %d on \"%s\"." : "Sperrtyp %d auf \"%s\" konnte nicht ermittelt werden.", "Storage unauthorized. %s" : "Speicher nicht autorisiert. %s", "Storage incomplete configuration. %s" : "Speicher-Konfiguration unvollständig. %s", "Storage connection error. %s" : "Verbindungsfehler zum Speicherplatz. %s", @@ -309,16 +330,15 @@ "The audio to transcribe" : "Die Audio-Datei zum Transkribieren", "Transcription" : "Transkription", "The transcribed text" : "Der transkribierte Text", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "Chatten Sie mit einem Agenten", "Chat message" : "Chatnachricht", - "A chat message to send to the agent." : "Eine Chat-Nachricht, die an den Agenten gesendet wird.", + "A chat message to send to the agent." : "Eine Chatnachricht, die an den Agenten gesendet wird.", "Confirmation" : "Bestätigung", "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Ob zuvor angeforderte Aktionen bestätigt werden sollen: 0 für Verweigerung und 1 für Bestätigung.", "Conversation token" : "Unterhaltungstoken", "A token representing the conversation." : "Ein Token, das die Unterhaltung repräsentiert.", "Generated response" : "Erzeugte Antwort", - "The response from the chat model." : "Die Antwort des Chatmodells.", + "The response from the chat model." : "Die Antwort des Chat-Modells.", "The new conversation token" : "Das neue Unterhaltungstoken", "Send this along with the next interaction." : "Dies zusammen mit der nächsten Interaktion senden.", "Requested actions by the agent" : "Vom Agenten angeforderte Aktionen", @@ -344,6 +364,11 @@ "How many images to generate" : "Wie viele Bilder erstellt werden sollen", "Output images" : "Ausgegebene Bilder", "The generated images" : "Die erstellten Bilder", + "Generate speech" : "Sprache erstellen", + "Generate speech from a transcript" : "Sprache aus einem Transkript erstellen", + "Write transcript that you want the assistant to generate speech from" : "Schreiben Sie ein Transkript, aus dem der Assistent Sprache erstellen soll", + "Output speech" : "Sprachausgabe", + "The generated speech" : "Die erstellte Sprache", "Free text to text prompt" : "Freie Text-zu-Text-Eingabeaufforderung", "Runs an arbitrary prompt through a language model that returns a reply" : "Führt eine beliebige Eingabeaufforderung mit einem Sprachmodell aus, das eine Antwort zurückgibt", "Describe a task that you want the assistant to do or ask a question" : "Beschreiben Sie eine Aufgabe, die der Assistent erledigen soll, oder stellen Sie eine Frage", @@ -382,6 +407,12 @@ "Original text" : "Originaltext", "The original text to generate a headline for" : "Der Originaltext, für den eine Überschrift erstellt werden soll", "The generated headline" : "Die erstellte Überschrift", + "Proofread" : "Korrekturlesen", + "Proofreads a text and lists corrections" : "Liest einen Text Korrektur und listet Korrekturen auf", + "Text" : "Text", + "The text to proofread" : "Der zu korrigierende Text", + "Corrections" : "Korrekturen", + "The corrections that should be made in your text" : "Die Korrekturen, die in Ihrem Text vorgenommen werden sollten", "Reformulate text" : "Text umformulieren", "Takes a text and reformulates it" : "Formuliert einen Text um", "Write a text that you want the assistant to reformulate" : "Text schreiben, den der Assistent umformulieren soll", @@ -417,41 +448,9 @@ "Generate headline" : "Kopfzeile erzeugen", "Summarizes text by reducing its length without losing key information." : "Fasst Text zusammen, indem die Länge reduziert wird, ohne dass wichtige Informationen verloren gehen.", "Extracts topics from a text and outputs them separated by commas." : "Extrahiert Themen aus einem Text und gibt sie durch Kommas getrennt aus.", - "Education Edition" : "Bildungsausgabe", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Der angemeldete Benutzer muss ein Administrator, ein Teil-Administrator sein oder ein Sonderrecht haben, um auf diese Einstellung zuzugreifen. ", - "Logged in user must be an admin or sub admin" : "Der angemeldete Benutzer muss ein (Sub-)Administrator sein", - "Logged in user must be an admin" : "Der angemeldete Benutzer muss ein Administrator sein", - "File name is a reserved word" : "Der Dateiname ist ein reserviertes Wort", - "File name contains at least one invalid character" : "Der Dateiname enthält mindestens ein ungültiges Zeichen", - "File name is too long" : "Dateiname ist zu lang", - "Help" : "Hilfe", - "Users" : "Benutzer", - "Unknown user" : "Unbekannter Benutzer", - "Enter the database username and name for %s" : "Den Datenbankbenutzernamen und den Namen eingeben für %s", - "Enter the database username for %s" : "Den Datenbankbenutzernamen eingeben für %s", - "MySQL username and/or password not valid" : "MySQL-Benutzername und/oder Passwort ungültig", - "Oracle username and/or password not valid" : "Oracle-Benutzername und/oder -Passwort ungültig", - "PostgreSQL username and/or password not valid" : "PostgreSQL-Benutzername und/oder -Passwort ungültig", - "Set an admin username." : "Einen Administrations-Benutzernamen setzen.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s hat »%2$s« mit Ihnen geteilt und möchte folgendes hinzufügen:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s hat »%2$s« mit Ihnen geteilt und möchte folgendes hinzufügen", - "»%s« added a note to a file shared with you" : "»%s« hat eine Bemerkung zu einer mit Ihnen geteilten Datei hinzugefügt", - "Open »%s«" : "»%s« öffnen", - "Sharing %s failed, because this item is already shared with user %s" : "Freigabe von %s fehlgeschlagen, da dieses Element schon mit dem Benutzer %s geteilt wird", - "%1$s shared »%2$s« with you" : "%1$s hat »%2$s« mit Ihnen geteilt", - "%1$s shared »%2$s« with you." : "%1$s hat »%2$s« mit Ihnen geteilt.", - "The username is already being used" : "Dieser Benutzername existiert bereits", - "Could not create user" : "Benutzer konnte nicht erstellt werden", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Folgende Zeichen sind im Benutzernamen erlaubt: „a-z“, „A-Z“, „0-9“, Leerzeichen und „_.@-'“", - "A valid username must be provided" : "Es muss ein gültiger Benutzername angegeben werden", - "Username contains whitespace at the beginning or at the end" : "Der Benutzername enthält Leerzeichen am Anfang oder am Ende", - "Username must not consist of dots only" : "Der Benutzername darf nicht nur aus Punkten bestehen", - "Username is invalid because files already exist for this user" : "Der Benutzer ist ungültig, da bereits Dateien von diesem Benutzer existieren", - "User disabled" : "Benutzer deaktiviert", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "Die Datei ist in Benutzung, bitte später erneut versuchen.", "Cannot download file" : "Datei kann nicht heruntergeladen werden", - "Your data directory is readable by other users." : "Ihr Datenverzeichnis kann von anderen Benutzern gelesen werden.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Bitte ändern Sie die Berechtigungen auf 0770, so dass das Verzeichnis nicht von anderen Benutzern angezeigt werden kann.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Stellen Sie sicher, dass eine Datei \".ocdata\" im Wurzelverzeichnis des Datenverzeichnisses existiert." + "Login is too long" : "Der Kontenname ist zu lang" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/el.js b/lib/l10n/el.js index 8af39c36f7b..58845d72e20 100644 --- a/lib/l10n/el.js +++ b/lib/l10n/el.js @@ -52,6 +52,7 @@ OC.L10N.register( "Avatar image is not square" : "Η εικόνα του άβαταρ δεν είναι τετράγωνη", "Files" : "Αρχεία", "View profile" : "Προβολή προφίλ", + "_%nh_::_%nh_" : ["%nω","%nω"], "Local time: %s" : "Τοπική ώρα: %s", "today" : "σήμερα", "tomorrow" : "αύριο", @@ -104,12 +105,12 @@ OC.L10N.register( "Profile picture" : "Εικόνα προφίλ", "About" : "Σχετικά με", "Headline" : "Τίτλος", - "Organisation" : "Οργανισμός", + "Organization" : "Οργανισμός", "Role" : "Ρόλος/Θέση", + "Pronouns" : "Αντωνυμίες", "Additional settings" : "Επιπρόσθετες ρυθμίσεις", "You need to enter details of an existing account." : "Χρειάζεται να εισάγετε λεπτομέρειες από υπάρχοντα λογαριασμό.", "Oracle connection could not be established" : "Αδυναμία σύνδεσης Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Το Mac OS X δεν υποστηρίζεται και το %s δεν θα λειτουργήσει σωστά σε αυτή την πλατφόρμα. Χρησιμοποιείτε με δική σας ευθύνη!", "For the best results, please consider using a GNU/Linux server instead." : "Για καλύτερα αποτελέσματα, παρακαλούμε εξετάστε την μετατροπή σε έναν διακομιστή GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Φαίνεται ότι η εγκατάσταση %s εκτελείται σε περιβάλλον 32-bit PHP και η επιλογή open_basedir έχει ρυθμιστεί στο αρχείο php.ini. Αυτό θα οδηγήσει σε προβλήματα με αρχεία πάνω από 4 GB και δεν συνίσταται.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Παρακαλούμε αφαιρέστε την ρύθμιση open_basedir μέσα στο αρχείο php.ini ή αλλάξτε σε 64-bit PHP.", @@ -118,7 +119,7 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Το σύστημα διαμοιρασμού %s πρέπει να υλοποιεί την διεπαφή OCP\\Share_Backend", "Sharing backend %s not found" : "Το σύστημα διαμοιρασμού %s δεν βρέθηκε", "Sharing backend for %s not found" : "Το σύστημα διαμοιρασμού για το %s δεν βρέθηκε", - "Click the button below to open it." : "Κάντε κλικ στο παρακάτω κουμπί για να το ανοίξετε.", + "Open %s" : "Άνοιγμα %s", "%1$s via %2$s" : "%1$s μέσω %2$s", "Unknown share type" : "Άγνωστος τύπος διαμοιρασμού", "You are not allowed to share %s" : "Δεν σας επιτρέπεται ο διαμοιρασμός %s", @@ -130,6 +131,7 @@ OC.L10N.register( "Sharing is only allowed with group members" : "Η κοινή χρήση επιτρέπεται μόνο με μέλη της ομάδας", "The requested share does not exist anymore" : "Το διαμοιρασμένο που ζητήθηκε δεν υπάρχει πλέον", "Could not find category \"%s\"" : "Αδυναμία εύρεσης κατηγορίας \"%s\"", + "Input text" : "Κείμενο εισόδου", "Sunday" : "Κυριακή", "Monday" : "Δευτέρα", "Tuesday" : "Τρίτη", @@ -219,42 +221,20 @@ OC.L10N.register( "Storage connection error. %s" : "Σφάλμα σύνδεσης με αποθηκευτικό χώρο. %s", "Storage is temporarily not available" : "Ο χώρος αποθήκευσης δεν είναι διαθέσιμος προσωρινά", "Storage connection timeout. %s" : "Λήξη χρονικού ορίου σύνδεσης με αποθηκευτικό χώρο.%s", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Για να επιτρέψετε αυτόν τον έλεγχο, πρέπει να βεβαιωθείτε ότι ο διακομιστής σας μπορεί να συνδεθεί με τον εαυτό του. Επομένως, πρέπει να μπορεί να επιλύσει και να συνδεθεί με τουλάχιστον ένα από τα `trusted_domains` ή το `overwrite.cli.url`. Αυτή η αποτυχία μπορεί να οφείλεται σε αντιστοιχία DNS από την πλευρά του διακομιστή ή σε κανόνα τείχους προστασίας εξερχομένων.", "Confirmation" : "Επιβεβαίωση", + "Generated response" : "Δημιουργημένη απάντηση", + "Change Tone" : "Αλλαγή Τόνου", + "Write a text that you want the assistant to rewrite in another tone." : "Γράψτε ένα κείμενο που θέλετε ο βοηθός να ξαναγράψει σε διαφορετικό τόνο.", + "Desired tone" : "Επιθυμητός τόνος", + "In which tone should your text be rewritten?" : "Σε ποιον τόνο πρέπει να ξαναγραφεί το κείμενό σας;", + "The rewritten text in the desired tone, written by the assistant:" : "Το ξαναγραμμένο κείμενο στον επιθυμητό τόνο, γραμμένο από τον βοηθό:", + "Text" : "Κείμενο", "Summary" : "Σύνοψη", "Translate" : "Μετάφραση", "Result" : "Αποτέλεσμα", - "Education Edition" : "Εκπαιδευτική Έκδοση", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Ο συνδεδεμένος χρήστης πρέπει να είναι διαχειριστής, υποδιαχειριστής ή να έχει ειδικό δικαίωμα πρόσβασης σε αυτήν τη ρύθμιση", - "Logged in user must be an admin or sub admin" : "Ο συνδεδεμένος χρήστης πρέπει να είναι admin ή subadmin", - "Logged in user must be an admin" : "Ο συνδεδεμένος χρήστης πρέπει να είναι διαχειριστής", - "File name is a reserved word" : "Το όνομα αρχείου είναι λέξη που έχει δεσμευτεί", - "File name contains at least one invalid character" : "Το όνομα αρχείου περιέχει έναν τουλάχιστον μη έγκυρο χαρακτήρα", - "File name is too long" : "Το όνομα αρχείου είναι πολύ μεγάλο", - "Help" : "Βοήθεια", - "Users" : "Χρήστες", - "Unknown user" : "Άγνωστος χρήστης", - "MySQL username and/or password not valid" : "Το όνομα χρήστη και/'η ο κωδικός πρόσβασης MySQL δεν είναι σωστά", - "Oracle username and/or password not valid" : "Μη έγκυρος χρήστης και/ή συνθηματικό της Oracle", - "PostgreSQL username and/or password not valid" : "Μη έγκυρος χρήστης και/ή συνθηματικό της PostgreSQL", - "Set an admin username." : "Εισάγετε όνομα χρήστη διαχειριστή.", - "%1$s shared »%2$s« with you and wants to add:" : "Ο %1$s διαμοιράστηκε το »%2$s« με εσάς και θέλει να προσθέσει:", - "%1$s shared »%2$s« with you and wants to add" : "Ο %1$s διαμοιράστηκε το »%2$s« με εσάς και θέλει να προσθέσει", - "»%s« added a note to a file shared with you" : "Ο »%s« πρόσθεσε μια σημείωση στο κοινόχρηστο αρχείο", - "Open »%s«" : "Άνοιγμα »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Η κοινή χρήση του %s απέτυχε, επειδή αυτό το στοιχείο είναι ήδη κοινόχρηστο με τον χρήστη %s", - "%1$s shared »%2$s« with you" : "Ο/η %1$s διαμοιράστηκε το »%2$s« με εσάς.", - "%1$s shared »%2$s« with you." : "Ο/η %1$s διαμοιράστηκε »%2$s« με εσάς.", - "The username is already being used" : "Το όνομα χρήστη είναι κατειλημμένο", - "Could not create user" : "Αδυναμία δημιουργίας χρήστη", - "A valid username must be provided" : "Πρέπει να δοθεί έγκυρο όνομα χρήστη", - "Username contains whitespace at the beginning or at the end" : "Το όνομα χρήστη περιέχει κενό διάστημα στην αρχή ή στο τέλος", - "Username must not consist of dots only" : "Το όνομα χρήστη δεν πρέπει να περιέχει μόνο τελείες", - "Username is invalid because files already exist for this user" : "Το όνομα χρήστη δεν είναι έγκυρο, επειδή υπάρχουν ήδη αρχεία για αυτόν τον χρήστη", - "User disabled" : "Ο χρήστης απενεργοποιήθηκε", + "Organisation" : "Οργανισμός", "File is currently busy, please try again later" : "Το αρχείο χρησιμοποιείται αυτή τη στιγμή, παρακαλούμε προσπαθήστε αργότερα", - "Cannot download file" : "Δεν είναι δυνατή η λήψη του αρχείου", - "Your data directory is readable by other users." : "Ο κατάλογος δεδομένων σας είναι αναγνώσιμος από άλλους χρήστες.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Παρακαλούμε αλλάξτε τις ρυθμίσεις σε 0770 έτσι ώστε ο κατάλογος να μην μπορεί να προβάλλεται από άλλους χρήστες.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Εξασφαλίστε ότι υπάρχει ένα αρχείο με όνομα \".ocdata\" στον βασικό κατάλογο του καταλόγου δεδομένων." + "Cannot download file" : "Δεν είναι δυνατή η λήψη του αρχείου" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/el.json b/lib/l10n/el.json index d00ce4b82e2..0099a9cca35 100644 --- a/lib/l10n/el.json +++ b/lib/l10n/el.json @@ -50,6 +50,7 @@ "Avatar image is not square" : "Η εικόνα του άβαταρ δεν είναι τετράγωνη", "Files" : "Αρχεία", "View profile" : "Προβολή προφίλ", + "_%nh_::_%nh_" : ["%nω","%nω"], "Local time: %s" : "Τοπική ώρα: %s", "today" : "σήμερα", "tomorrow" : "αύριο", @@ -102,12 +103,12 @@ "Profile picture" : "Εικόνα προφίλ", "About" : "Σχετικά με", "Headline" : "Τίτλος", - "Organisation" : "Οργανισμός", + "Organization" : "Οργανισμός", "Role" : "Ρόλος/Θέση", + "Pronouns" : "Αντωνυμίες", "Additional settings" : "Επιπρόσθετες ρυθμίσεις", "You need to enter details of an existing account." : "Χρειάζεται να εισάγετε λεπτομέρειες από υπάρχοντα λογαριασμό.", "Oracle connection could not be established" : "Αδυναμία σύνδεσης Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Το Mac OS X δεν υποστηρίζεται και το %s δεν θα λειτουργήσει σωστά σε αυτή την πλατφόρμα. Χρησιμοποιείτε με δική σας ευθύνη!", "For the best results, please consider using a GNU/Linux server instead." : "Για καλύτερα αποτελέσματα, παρακαλούμε εξετάστε την μετατροπή σε έναν διακομιστή GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Φαίνεται ότι η εγκατάσταση %s εκτελείται σε περιβάλλον 32-bit PHP και η επιλογή open_basedir έχει ρυθμιστεί στο αρχείο php.ini. Αυτό θα οδηγήσει σε προβλήματα με αρχεία πάνω από 4 GB και δεν συνίσταται.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Παρακαλούμε αφαιρέστε την ρύθμιση open_basedir μέσα στο αρχείο php.ini ή αλλάξτε σε 64-bit PHP.", @@ -116,7 +117,7 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Το σύστημα διαμοιρασμού %s πρέπει να υλοποιεί την διεπαφή OCP\\Share_Backend", "Sharing backend %s not found" : "Το σύστημα διαμοιρασμού %s δεν βρέθηκε", "Sharing backend for %s not found" : "Το σύστημα διαμοιρασμού για το %s δεν βρέθηκε", - "Click the button below to open it." : "Κάντε κλικ στο παρακάτω κουμπί για να το ανοίξετε.", + "Open %s" : "Άνοιγμα %s", "%1$s via %2$s" : "%1$s μέσω %2$s", "Unknown share type" : "Άγνωστος τύπος διαμοιρασμού", "You are not allowed to share %s" : "Δεν σας επιτρέπεται ο διαμοιρασμός %s", @@ -128,6 +129,7 @@ "Sharing is only allowed with group members" : "Η κοινή χρήση επιτρέπεται μόνο με μέλη της ομάδας", "The requested share does not exist anymore" : "Το διαμοιρασμένο που ζητήθηκε δεν υπάρχει πλέον", "Could not find category \"%s\"" : "Αδυναμία εύρεσης κατηγορίας \"%s\"", + "Input text" : "Κείμενο εισόδου", "Sunday" : "Κυριακή", "Monday" : "Δευτέρα", "Tuesday" : "Τρίτη", @@ -217,42 +219,20 @@ "Storage connection error. %s" : "Σφάλμα σύνδεσης με αποθηκευτικό χώρο. %s", "Storage is temporarily not available" : "Ο χώρος αποθήκευσης δεν είναι διαθέσιμος προσωρινά", "Storage connection timeout. %s" : "Λήξη χρονικού ορίου σύνδεσης με αποθηκευτικό χώρο.%s", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Για να επιτρέψετε αυτόν τον έλεγχο, πρέπει να βεβαιωθείτε ότι ο διακομιστής σας μπορεί να συνδεθεί με τον εαυτό του. Επομένως, πρέπει να μπορεί να επιλύσει και να συνδεθεί με τουλάχιστον ένα από τα `trusted_domains` ή το `overwrite.cli.url`. Αυτή η αποτυχία μπορεί να οφείλεται σε αντιστοιχία DNS από την πλευρά του διακομιστή ή σε κανόνα τείχους προστασίας εξερχομένων.", "Confirmation" : "Επιβεβαίωση", + "Generated response" : "Δημιουργημένη απάντηση", + "Change Tone" : "Αλλαγή Τόνου", + "Write a text that you want the assistant to rewrite in another tone." : "Γράψτε ένα κείμενο που θέλετε ο βοηθός να ξαναγράψει σε διαφορετικό τόνο.", + "Desired tone" : "Επιθυμητός τόνος", + "In which tone should your text be rewritten?" : "Σε ποιον τόνο πρέπει να ξαναγραφεί το κείμενό σας;", + "The rewritten text in the desired tone, written by the assistant:" : "Το ξαναγραμμένο κείμενο στον επιθυμητό τόνο, γραμμένο από τον βοηθό:", + "Text" : "Κείμενο", "Summary" : "Σύνοψη", "Translate" : "Μετάφραση", "Result" : "Αποτέλεσμα", - "Education Edition" : "Εκπαιδευτική Έκδοση", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Ο συνδεδεμένος χρήστης πρέπει να είναι διαχειριστής, υποδιαχειριστής ή να έχει ειδικό δικαίωμα πρόσβασης σε αυτήν τη ρύθμιση", - "Logged in user must be an admin or sub admin" : "Ο συνδεδεμένος χρήστης πρέπει να είναι admin ή subadmin", - "Logged in user must be an admin" : "Ο συνδεδεμένος χρήστης πρέπει να είναι διαχειριστής", - "File name is a reserved word" : "Το όνομα αρχείου είναι λέξη που έχει δεσμευτεί", - "File name contains at least one invalid character" : "Το όνομα αρχείου περιέχει έναν τουλάχιστον μη έγκυρο χαρακτήρα", - "File name is too long" : "Το όνομα αρχείου είναι πολύ μεγάλο", - "Help" : "Βοήθεια", - "Users" : "Χρήστες", - "Unknown user" : "Άγνωστος χρήστης", - "MySQL username and/or password not valid" : "Το όνομα χρήστη και/'η ο κωδικός πρόσβασης MySQL δεν είναι σωστά", - "Oracle username and/or password not valid" : "Μη έγκυρος χρήστης και/ή συνθηματικό της Oracle", - "PostgreSQL username and/or password not valid" : "Μη έγκυρος χρήστης και/ή συνθηματικό της PostgreSQL", - "Set an admin username." : "Εισάγετε όνομα χρήστη διαχειριστή.", - "%1$s shared »%2$s« with you and wants to add:" : "Ο %1$s διαμοιράστηκε το »%2$s« με εσάς και θέλει να προσθέσει:", - "%1$s shared »%2$s« with you and wants to add" : "Ο %1$s διαμοιράστηκε το »%2$s« με εσάς και θέλει να προσθέσει", - "»%s« added a note to a file shared with you" : "Ο »%s« πρόσθεσε μια σημείωση στο κοινόχρηστο αρχείο", - "Open »%s«" : "Άνοιγμα »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Η κοινή χρήση του %s απέτυχε, επειδή αυτό το στοιχείο είναι ήδη κοινόχρηστο με τον χρήστη %s", - "%1$s shared »%2$s« with you" : "Ο/η %1$s διαμοιράστηκε το »%2$s« με εσάς.", - "%1$s shared »%2$s« with you." : "Ο/η %1$s διαμοιράστηκε »%2$s« με εσάς.", - "The username is already being used" : "Το όνομα χρήστη είναι κατειλημμένο", - "Could not create user" : "Αδυναμία δημιουργίας χρήστη", - "A valid username must be provided" : "Πρέπει να δοθεί έγκυρο όνομα χρήστη", - "Username contains whitespace at the beginning or at the end" : "Το όνομα χρήστη περιέχει κενό διάστημα στην αρχή ή στο τέλος", - "Username must not consist of dots only" : "Το όνομα χρήστη δεν πρέπει να περιέχει μόνο τελείες", - "Username is invalid because files already exist for this user" : "Το όνομα χρήστη δεν είναι έγκυρο, επειδή υπάρχουν ήδη αρχεία για αυτόν τον χρήστη", - "User disabled" : "Ο χρήστης απενεργοποιήθηκε", + "Organisation" : "Οργανισμός", "File is currently busy, please try again later" : "Το αρχείο χρησιμοποιείται αυτή τη στιγμή, παρακαλούμε προσπαθήστε αργότερα", - "Cannot download file" : "Δεν είναι δυνατή η λήψη του αρχείου", - "Your data directory is readable by other users." : "Ο κατάλογος δεδομένων σας είναι αναγνώσιμος από άλλους χρήστες.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Παρακαλούμε αλλάξτε τις ρυθμίσεις σε 0770 έτσι ώστε ο κατάλογος να μην μπορεί να προβάλλεται από άλλους χρήστες.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Εξασφαλίστε ότι υπάρχει ένα αρχείο με όνομα \".ocdata\" στον βασικό κατάλογο του καταλόγου δεδομένων." + "Cannot download file" : "Δεν είναι δυνατή η λήψη του αρχείου" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/en_GB.js b/lib/l10n/en_GB.js index 8880ee682bd..9fb5272679f 100644 --- a/lib/l10n/en_GB.js +++ b/lib/l10n/en_GB.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Server version %s or higher is required.", "Server version %s or lower is required." : "Server version %s or lower is required.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Logged in account must be an admin, a sub admin or gotten special right to access this setting", - "Your current IP address doesn’t allow you to perform admin actions" : "Your current IP address doesn’t allow you to perform admin actions", + "Your current IP address doesn't allow you to perform admin actions" : "Your current IP address doesn't allow you to perform admin actions", "Logged in account must be an admin or sub admin" : "Logged in account must be an admin or sub admin", "Logged in account must be an admin" : "Logged in account must be an admin", "Wiping of device %s has started" : "Wiping of device %s has started", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Avatar image is not square", "Files" : "Files", "View profile" : "View profile", + "same time" : "same time", + "_%nh_::_%nh_" : ["%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s ahead", + "%s behind" : "%s behind", "Local time: %s" : "Local time: %s", "today" : "today", "tomorrow" : "tomorrow", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "seconds ago", "Empty file" : "Empty file", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator.", + "No file conversion providers available" : "No file conversion providers available", + "File is too large to convert" : "File is too large to convert", + "Destination does not match conversion extension" : "Destination does not match conversion extension", + "Could not convert file" : "Could not convert file", + "Destination does not exist" : "Destination does not exist", + "Destination is not creatable" : "Destination is not creatable", "Dot files are not allowed" : "Dot files are not allowed", + "%1$s (renamed)" : "%1$s (renamed)", + "renamed file" : "renamed file", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" is a forbidden file or folder name.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" is a forbidden prefix for file or folder names.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" is not allowed inside a file or folder name.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Invalid path", "Failed to create file from template" : "Failed to create file from template", "Templates" : "Templates", + "Storage %s cannot be moved" : "Storage %s cannot be moved", + "Moving a share (%s) into a shared folder is not allowed" : "Moving a share (%s) into a shared folder is not allowed", + "Moving a storage (%s) into a shared folder is not allowed" : "Moving a storage (%s) into a shared folder is not allowed", + "Moving a share (%s) into another share (%s) is not allowed" : "Moving a share (%s) into another share (%s) is not allowed", + "Moving a share (%s) into another storage (%s) is not allowed" : "Moving a share (%s) into another storage (%s) is not allowed", + "Moving a storage (%s) into a share (%s) is not allowed" : "Moving a storage (%s) into a share (%s) is not allowed", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Moving a storage (%s) into another storage (%s) is not allowed", "Path contains invalid segments" : "Path contains invalid segments", "Filename is a reserved word" : "Filename is a reserved word", "Filename contains at least one invalid character" : "Filename contains at least one invalid character", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "About", "Display name" : "Display name", "Headline" : "Headline", - "Organisation" : "Organisation", + "Organization" : "Organization", "Role" : "Role", "Pronouns" : "Pronouns", "Unknown account" : "Unknown account", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Oracle connection could not be established", "Oracle Login and/or password not valid" : "Oracle Login and/or password not valid", "PostgreSQL Login and/or password not valid" : "PostgreSQL Login and/or password not valid", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! ", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!", "For the best results, please consider using a GNU/Linux server instead." : "For the best results, please consider using a GNU/Linux server instead.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir setting has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Sharing backend %s not found", "Sharing backend for %s not found" : "Sharing backend for %s not found", "%1$s shared %2$s with you" : "%1$s shared %2$s with you", - "Click the button below to open it." : "Click the button below to open it.", "Open %s" : "Open %s", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s shared %2$s with you and wants to add:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "You cannot share your root folder", "You are not allowed to share %s" : "You are not allowed to share %s", "Valid permissions are required for sharing" : "Valid permissions are required for sharing", + "File shares cannot have create or delete permissions" : "File shares cannot have create or delete permissions", "Cannot increase permissions of %s" : "Cannot increase permissions of %s", "Shares need at least read permissions" : "Shares need at least read permissions", "Files cannot be shared with delete permissions" : "Files cannot be shared with delete permissions", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Path is already shared with this group", "Link sharing is not allowed" : "Link sharing is not allowed", "Public upload is not allowed" : "Public upload is not allowed", - "Path contains files shared with you" : "Path contains files shared with you", + "You cannot share a folder that contains other shares" : "You cannot share a folder that contains other shares", "Sharing is disabled" : "Sharing is disabled", "Sharing is disabled for you" : "Sharing is disabled for you", "Cannot share with the share owner" : "Cannot share with the share owner", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "A valid Login must be provided", "Login contains whitespace at the beginning or at the end" : "Login contains whitespace at the beginning or at the end", "Login must not consist of dots only" : "Login must not consist of dots only", + "Username is too long" : "Username is too long", "Login is invalid because files already exist for this user" : "Login is invalid because files already exist for this user", "Account disabled" : "Account disabled", "Login canceled by app" : "Login cancelled by app", @@ -311,7 +332,6 @@ OC.L10N.register( "The audio to transcribe" : "The audio to transcribe", "Transcription" : "Transcription", "The transcribed text" : "The transcribed text", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "Chat with an agent", "Chat message" : "Chat message", "A chat message to send to the agent." : "A chat message to send to the agent.", @@ -346,6 +366,11 @@ OC.L10N.register( "How many images to generate" : "How many images to generate", "Output images" : "Output images", "The generated images" : "The generated images", + "Generate speech" : "Generate speech", + "Generate speech from a transcript" : "Generate speech from a transcript", + "Write transcript that you want the assistant to generate speech from" : "Write transcript that you want the assistant to generate speech from", + "Output speech" : "Output speech", + "The generated speech" : "The generated speech", "Free text to text prompt" : "Free text to text prompt", "Runs an arbitrary prompt through a language model that returns a reply" : "Runs an arbitrary prompt through a language model that returns a reply", "Describe a task that you want the assistant to do or ask a question" : "Describe a task that you want the assistant to do or ask a question", @@ -384,6 +409,12 @@ OC.L10N.register( "Original text" : "Original text", "The original text to generate a headline for" : "The original text to generate a headline for", "The generated headline" : "The generated headline", + "Proofread" : "Proofread", + "Proofreads a text and lists corrections" : "Proofreads a text and lists corrections", + "Text" : "Text", + "The text to proofread" : "The text to proofread", + "Corrections" : "Corrections", + "The corrections that should be made in your text" : "The corrections that should be made in your text", "Reformulate text" : "Reformulate text", "Takes a text and reformulates it" : "Takes a text and reformulates it", "Write a text that you want the assistant to reformulate" : "Write a text that you want the assistant to reformulate", @@ -419,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Generate headline", "Summarizes text by reducing its length without losing key information." : "Summarizes text by reducing its length without losing key information.", "Extracts topics from a text and outputs them separated by commas." : "Extracts topics from a text and outputs them separated by commas.", - "Education Edition" : "Education Edition", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Logged in user must be an admin, a sub-admin or has special right to access this setting", - "Logged in user must be an admin or sub admin" : "Logged in user must be an admin or sub admin", - "Logged in user must be an admin" : "Logged in user must be an admin", - "File name is a reserved word" : "File name is a reserved word", - "File name contains at least one invalid character" : "File name contains at least one invalid character", - "File name is too long" : "File name is too long", - "Help" : "Help", - "Users" : "Users", - "Unknown user" : "Unknown user", - "Enter the database username and name for %s" : "Enter the database username and name for %s", - "Enter the database username for %s" : "Enter the database username for %s", - "MySQL username and/or password not valid" : "MySQL username and/or password not valid", - "Oracle username and/or password not valid" : "Oracle username and/or password not valid", - "PostgreSQL username and/or password not valid" : "PostgreSQL username and/or password not valid", - "Set an admin username." : "Set an admin username.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s shared »%2$s« with you and wants to add:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s shared »%2$s« with you and wants to add", - "»%s« added a note to a file shared with you" : "»%s« added a note to a file shared with you", - "Open »%s«" : "Open »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Sharing %s failed, because this item is already shared with user %s", - "%1$s shared »%2$s« with you" : "%1$s shared »%2$s« with you", - "%1$s shared »%2$s« with you." : "%1$s shared »%2$s« with you.", - "The username is already being used" : "The username is already being used", - "Could not create user" : "Could not create user", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"", - "A valid username must be provided" : "A valid username must be provided", - "Username contains whitespace at the beginning or at the end" : "Username contains whitespace at the beginning or at the end", - "Username must not consist of dots only" : "Username must not consist of dots only", - "Username is invalid because files already exist for this user" : "Username is invalid because files already exist for this user", - "User disabled" : "User disabled", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "File is currently busy, please try again later", "Cannot download file" : "Cannot download file", - "Your data directory is readable by other users." : "Your data directory is readable by other users.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Please change the permissions to 0770 so that the directory cannot be listed by other users.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Ensure there is a file called \".ocdata\" in the root of the data directory." + "Login is too long" : "Login is too long" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/en_GB.json b/lib/l10n/en_GB.json index 9b808a3ff3c..e18996b6cb5 100644 --- a/lib/l10n/en_GB.json +++ b/lib/l10n/en_GB.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Server version %s or higher is required.", "Server version %s or lower is required." : "Server version %s or lower is required.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Logged in account must be an admin, a sub admin or gotten special right to access this setting", - "Your current IP address doesn’t allow you to perform admin actions" : "Your current IP address doesn’t allow you to perform admin actions", + "Your current IP address doesn't allow you to perform admin actions" : "Your current IP address doesn't allow you to perform admin actions", "Logged in account must be an admin or sub admin" : "Logged in account must be an admin or sub admin", "Logged in account must be an admin" : "Logged in account must be an admin", "Wiping of device %s has started" : "Wiping of device %s has started", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Avatar image is not square", "Files" : "Files", "View profile" : "View profile", + "same time" : "same time", + "_%nh_::_%nh_" : ["%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s ahead", + "%s behind" : "%s behind", "Local time: %s" : "Local time: %s", "today" : "today", "tomorrow" : "tomorrow", @@ -79,7 +84,15 @@ "seconds ago" : "seconds ago", "Empty file" : "Empty file", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator.", + "No file conversion providers available" : "No file conversion providers available", + "File is too large to convert" : "File is too large to convert", + "Destination does not match conversion extension" : "Destination does not match conversion extension", + "Could not convert file" : "Could not convert file", + "Destination does not exist" : "Destination does not exist", + "Destination is not creatable" : "Destination is not creatable", "Dot files are not allowed" : "Dot files are not allowed", + "%1$s (renamed)" : "%1$s (renamed)", + "renamed file" : "renamed file", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" is a forbidden file or folder name.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" is a forbidden prefix for file or folder names.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" is not allowed inside a file or folder name.", @@ -90,6 +103,13 @@ "Invalid path" : "Invalid path", "Failed to create file from template" : "Failed to create file from template", "Templates" : "Templates", + "Storage %s cannot be moved" : "Storage %s cannot be moved", + "Moving a share (%s) into a shared folder is not allowed" : "Moving a share (%s) into a shared folder is not allowed", + "Moving a storage (%s) into a shared folder is not allowed" : "Moving a storage (%s) into a shared folder is not allowed", + "Moving a share (%s) into another share (%s) is not allowed" : "Moving a share (%s) into another share (%s) is not allowed", + "Moving a share (%s) into another storage (%s) is not allowed" : "Moving a share (%s) into another storage (%s) is not allowed", + "Moving a storage (%s) into a share (%s) is not allowed" : "Moving a storage (%s) into a share (%s) is not allowed", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Moving a storage (%s) into another storage (%s) is not allowed", "Path contains invalid segments" : "Path contains invalid segments", "Filename is a reserved word" : "Filename is a reserved word", "Filename contains at least one invalid character" : "Filename contains at least one invalid character", @@ -122,7 +142,7 @@ "About" : "About", "Display name" : "Display name", "Headline" : "Headline", - "Organisation" : "Organisation", + "Organization" : "Organization", "Role" : "Role", "Pronouns" : "Pronouns", "Unknown account" : "Unknown account", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "Oracle connection could not be established", "Oracle Login and/or password not valid" : "Oracle Login and/or password not valid", "PostgreSQL Login and/or password not valid" : "PostgreSQL Login and/or password not valid", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! ", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!", "For the best results, please consider using a GNU/Linux server instead." : "For the best results, please consider using a GNU/Linux server instead.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir setting has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "Sharing backend %s not found", "Sharing backend for %s not found" : "Sharing backend for %s not found", "%1$s shared %2$s with you" : "%1$s shared %2$s with you", - "Click the button below to open it." : "Click the button below to open it.", "Open %s" : "Open %s", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s shared %2$s with you and wants to add:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "You cannot share your root folder", "You are not allowed to share %s" : "You are not allowed to share %s", "Valid permissions are required for sharing" : "Valid permissions are required for sharing", + "File shares cannot have create or delete permissions" : "File shares cannot have create or delete permissions", "Cannot increase permissions of %s" : "Cannot increase permissions of %s", "Shares need at least read permissions" : "Shares need at least read permissions", "Files cannot be shared with delete permissions" : "Files cannot be shared with delete permissions", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "Path is already shared with this group", "Link sharing is not allowed" : "Link sharing is not allowed", "Public upload is not allowed" : "Public upload is not allowed", - "Path contains files shared with you" : "Path contains files shared with you", + "You cannot share a folder that contains other shares" : "You cannot share a folder that contains other shares", "Sharing is disabled" : "Sharing is disabled", "Sharing is disabled for you" : "Sharing is disabled for you", "Cannot share with the share owner" : "Cannot share with the share owner", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "A valid Login must be provided", "Login contains whitespace at the beginning or at the end" : "Login contains whitespace at the beginning or at the end", "Login must not consist of dots only" : "Login must not consist of dots only", + "Username is too long" : "Username is too long", "Login is invalid because files already exist for this user" : "Login is invalid because files already exist for this user", "Account disabled" : "Account disabled", "Login canceled by app" : "Login cancelled by app", @@ -309,7 +330,6 @@ "The audio to transcribe" : "The audio to transcribe", "Transcription" : "Transcription", "The transcribed text" : "The transcribed text", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "Chat with an agent", "Chat message" : "Chat message", "A chat message to send to the agent." : "A chat message to send to the agent.", @@ -344,6 +364,11 @@ "How many images to generate" : "How many images to generate", "Output images" : "Output images", "The generated images" : "The generated images", + "Generate speech" : "Generate speech", + "Generate speech from a transcript" : "Generate speech from a transcript", + "Write transcript that you want the assistant to generate speech from" : "Write transcript that you want the assistant to generate speech from", + "Output speech" : "Output speech", + "The generated speech" : "The generated speech", "Free text to text prompt" : "Free text to text prompt", "Runs an arbitrary prompt through a language model that returns a reply" : "Runs an arbitrary prompt through a language model that returns a reply", "Describe a task that you want the assistant to do or ask a question" : "Describe a task that you want the assistant to do or ask a question", @@ -382,6 +407,12 @@ "Original text" : "Original text", "The original text to generate a headline for" : "The original text to generate a headline for", "The generated headline" : "The generated headline", + "Proofread" : "Proofread", + "Proofreads a text and lists corrections" : "Proofreads a text and lists corrections", + "Text" : "Text", + "The text to proofread" : "The text to proofread", + "Corrections" : "Corrections", + "The corrections that should be made in your text" : "The corrections that should be made in your text", "Reformulate text" : "Reformulate text", "Takes a text and reformulates it" : "Takes a text and reformulates it", "Write a text that you want the assistant to reformulate" : "Write a text that you want the assistant to reformulate", @@ -417,41 +448,9 @@ "Generate headline" : "Generate headline", "Summarizes text by reducing its length without losing key information." : "Summarizes text by reducing its length without losing key information.", "Extracts topics from a text and outputs them separated by commas." : "Extracts topics from a text and outputs them separated by commas.", - "Education Edition" : "Education Edition", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Logged in user must be an admin, a sub-admin or has special right to access this setting", - "Logged in user must be an admin or sub admin" : "Logged in user must be an admin or sub admin", - "Logged in user must be an admin" : "Logged in user must be an admin", - "File name is a reserved word" : "File name is a reserved word", - "File name contains at least one invalid character" : "File name contains at least one invalid character", - "File name is too long" : "File name is too long", - "Help" : "Help", - "Users" : "Users", - "Unknown user" : "Unknown user", - "Enter the database username and name for %s" : "Enter the database username and name for %s", - "Enter the database username for %s" : "Enter the database username for %s", - "MySQL username and/or password not valid" : "MySQL username and/or password not valid", - "Oracle username and/or password not valid" : "Oracle username and/or password not valid", - "PostgreSQL username and/or password not valid" : "PostgreSQL username and/or password not valid", - "Set an admin username." : "Set an admin username.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s shared »%2$s« with you and wants to add:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s shared »%2$s« with you and wants to add", - "»%s« added a note to a file shared with you" : "»%s« added a note to a file shared with you", - "Open »%s«" : "Open »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Sharing %s failed, because this item is already shared with user %s", - "%1$s shared »%2$s« with you" : "%1$s shared »%2$s« with you", - "%1$s shared »%2$s« with you." : "%1$s shared »%2$s« with you.", - "The username is already being used" : "The username is already being used", - "Could not create user" : "Could not create user", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"", - "A valid username must be provided" : "A valid username must be provided", - "Username contains whitespace at the beginning or at the end" : "Username contains whitespace at the beginning or at the end", - "Username must not consist of dots only" : "Username must not consist of dots only", - "Username is invalid because files already exist for this user" : "Username is invalid because files already exist for this user", - "User disabled" : "User disabled", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "File is currently busy, please try again later", "Cannot download file" : "Cannot download file", - "Your data directory is readable by other users." : "Your data directory is readable by other users.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Please change the permissions to 0770 so that the directory cannot be listed by other users.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Ensure there is a file called \".ocdata\" in the root of the data directory." + "Login is too long" : "Login is too long" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/eo.js b/lib/l10n/eo.js index 22d49ca394b..0a8215b9a63 100644 --- a/lib/l10n/eo.js +++ b/lib/l10n/eo.js @@ -90,7 +90,6 @@ OC.L10N.register( "Additional settings" : "Plia agordo", "You need to enter details of an existing account." : "Vi entajpu detalojn pri ekzistanta konto.", "Oracle connection could not be established" : "Konekto al Oracle ne povis stariĝi", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "MacOS X ne estas subtenata kaj %s ne bone funkcios ĉe ĝi. Uzu ĝin je via risko!", "For the best results, please consider using a GNU/Linux server instead." : "Por pli bona funkciado, bv. pripensi uzi GNU-Linuksan servilon anstataŭe.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Ŝajnas, ke tiu servilo %s uzas 32-bitan PHP-version, kaj ke la agordo „open_basedir“ ekzistas. Tio kaŭzos problemojn pri dosieroj pli grandaj ol 4 GB, kaj do estas tre malrekomendita.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bv. forigi la agordon „open_basedir“ de via php.ini, aŭ uzu 64-bitan version de PHP.", @@ -98,7 +97,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Kunhava interna servo %s devas realigi la interfacon „OCP\\Share_Backend“", "Sharing backend %s not found" : "Kunhava interna servo %s ne troviĝas", "Sharing backend for %s not found" : "Kunhava interna servo por %s ne troviĝas", - "Click the button below to open it." : "Alklaku la butonon ĉi-sube por malfermi ĝin.", "%1$s via %2$s" : "%1$s pere de %2$s", "Unknown share type" : "Nekonata kunhava tipo", "You are not allowed to share %s" : "Vi ne permesatas kunhavigi %s", @@ -179,37 +177,9 @@ OC.L10N.register( "Storage connection error. %s" : "Konekta eraro al konservejo. %s", "Storage is temporarily not available" : "Konservejo provizore ne disponeblas", "Storage connection timeout. %s" : "Konekto al konservejo eltempiĝis. %s", + "Text" : "Teksto", "Summary" : "Resumo", "Translate" : "Traduku", - "Education Edition" : "Eldono por edukado", - "Logged in user must be an admin or sub admin" : "La ensalutanta uzanto estu administranto aŭ subadministranto", - "Logged in user must be an admin" : "La ensalutanta uzanto estu administranto", - "File name is a reserved word" : "Dosiernomo estas rezervita vorto", - "File name contains at least one invalid character" : "Dosiernomo enhavas almenaŭ unu nevalidan signon", - "File name is too long" : "La dosiernomo estas tro longa", - "Help" : "Helpo", - "Users" : "Uzantoj", - "Unknown user" : "Nekonata uzanto", - "MySQL username and/or password not valid" : "La uzantnomo kaj/aŭ pasvorto de MySQL ne estas valida", - "Oracle username and/or password not valid" : "La uzantnomo kaj/aŭ la pasvorto de Oracle ne estas valida", - "PostgreSQL username and/or password not valid" : "La uzantnomo aŭ la pasvorto de PostgreSQL ne validas", - "Set an admin username." : "Agordi uzantnomon de administranto.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s kunhavigis „%2$s“ kun vi kaj volas aldoni:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s kunhavigis „%2$s“ kun vi kaj volas aldoni", - "»%s« added a note to a file shared with you" : "„%s“ aldonis noton al dosiero kunhavigita kun vi", - "Open »%s«" : "Malfermi „%s“", - "Sharing %s failed, because this item is already shared with user %s" : "Kunhavigo de %s malsukcesis, ĉar la ero jam kunhaviĝis kun %s", - "%1$s shared »%2$s« with you" : "%1$s kunhavigis „%2$s“ kun vi", - "%1$s shared »%2$s« with you." : "%1$s kunhavigis „%2$s“ kun vi.", - "The username is already being used" : "La uzantnomo jam estas uzata", - "Could not create user" : "Ne povis krei uzanton", - "A valid username must be provided" : "Valida uzantnomo devas esti provizita", - "Username contains whitespace at the beginning or at the end" : "Uzantnomo enhavas spaceton ĉe la komenco aŭ la fino", - "Username must not consist of dots only" : "Uzantnomo ne povas enhavi nur punktojn", - "Username is invalid because files already exist for this user" : "La uzantnomo ne estas valida pro dosieroj por la uzanto jam ekzistas", - "User disabled" : "Uzanto malebligita", - "File is currently busy, please try again later" : "La dosiero estas nun okupita, bv. reprovi poste", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Bv. ŝanĝi la permesojn al 0770, tiel la dosierujo ne listigeblas de aliaj uzantoj.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Certigu, ke estas dosiero nomata „.ocdata“ en la radiko de la dosierujo de datumoj." + "File is currently busy, please try again later" : "La dosiero estas nun okupita, bv. reprovi poste" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/eo.json b/lib/l10n/eo.json index c00c4e9e2a4..d9b2a1ede87 100644 --- a/lib/l10n/eo.json +++ b/lib/l10n/eo.json @@ -88,7 +88,6 @@ "Additional settings" : "Plia agordo", "You need to enter details of an existing account." : "Vi entajpu detalojn pri ekzistanta konto.", "Oracle connection could not be established" : "Konekto al Oracle ne povis stariĝi", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "MacOS X ne estas subtenata kaj %s ne bone funkcios ĉe ĝi. Uzu ĝin je via risko!", "For the best results, please consider using a GNU/Linux server instead." : "Por pli bona funkciado, bv. pripensi uzi GNU-Linuksan servilon anstataŭe.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Ŝajnas, ke tiu servilo %s uzas 32-bitan PHP-version, kaj ke la agordo „open_basedir“ ekzistas. Tio kaŭzos problemojn pri dosieroj pli grandaj ol 4 GB, kaj do estas tre malrekomendita.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bv. forigi la agordon „open_basedir“ de via php.ini, aŭ uzu 64-bitan version de PHP.", @@ -96,7 +95,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Kunhava interna servo %s devas realigi la interfacon „OCP\\Share_Backend“", "Sharing backend %s not found" : "Kunhava interna servo %s ne troviĝas", "Sharing backend for %s not found" : "Kunhava interna servo por %s ne troviĝas", - "Click the button below to open it." : "Alklaku la butonon ĉi-sube por malfermi ĝin.", "%1$s via %2$s" : "%1$s pere de %2$s", "Unknown share type" : "Nekonata kunhava tipo", "You are not allowed to share %s" : "Vi ne permesatas kunhavigi %s", @@ -177,37 +175,9 @@ "Storage connection error. %s" : "Konekta eraro al konservejo. %s", "Storage is temporarily not available" : "Konservejo provizore ne disponeblas", "Storage connection timeout. %s" : "Konekto al konservejo eltempiĝis. %s", + "Text" : "Teksto", "Summary" : "Resumo", "Translate" : "Traduku", - "Education Edition" : "Eldono por edukado", - "Logged in user must be an admin or sub admin" : "La ensalutanta uzanto estu administranto aŭ subadministranto", - "Logged in user must be an admin" : "La ensalutanta uzanto estu administranto", - "File name is a reserved word" : "Dosiernomo estas rezervita vorto", - "File name contains at least one invalid character" : "Dosiernomo enhavas almenaŭ unu nevalidan signon", - "File name is too long" : "La dosiernomo estas tro longa", - "Help" : "Helpo", - "Users" : "Uzantoj", - "Unknown user" : "Nekonata uzanto", - "MySQL username and/or password not valid" : "La uzantnomo kaj/aŭ pasvorto de MySQL ne estas valida", - "Oracle username and/or password not valid" : "La uzantnomo kaj/aŭ la pasvorto de Oracle ne estas valida", - "PostgreSQL username and/or password not valid" : "La uzantnomo aŭ la pasvorto de PostgreSQL ne validas", - "Set an admin username." : "Agordi uzantnomon de administranto.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s kunhavigis „%2$s“ kun vi kaj volas aldoni:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s kunhavigis „%2$s“ kun vi kaj volas aldoni", - "»%s« added a note to a file shared with you" : "„%s“ aldonis noton al dosiero kunhavigita kun vi", - "Open »%s«" : "Malfermi „%s“", - "Sharing %s failed, because this item is already shared with user %s" : "Kunhavigo de %s malsukcesis, ĉar la ero jam kunhaviĝis kun %s", - "%1$s shared »%2$s« with you" : "%1$s kunhavigis „%2$s“ kun vi", - "%1$s shared »%2$s« with you." : "%1$s kunhavigis „%2$s“ kun vi.", - "The username is already being used" : "La uzantnomo jam estas uzata", - "Could not create user" : "Ne povis krei uzanton", - "A valid username must be provided" : "Valida uzantnomo devas esti provizita", - "Username contains whitespace at the beginning or at the end" : "Uzantnomo enhavas spaceton ĉe la komenco aŭ la fino", - "Username must not consist of dots only" : "Uzantnomo ne povas enhavi nur punktojn", - "Username is invalid because files already exist for this user" : "La uzantnomo ne estas valida pro dosieroj por la uzanto jam ekzistas", - "User disabled" : "Uzanto malebligita", - "File is currently busy, please try again later" : "La dosiero estas nun okupita, bv. reprovi poste", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Bv. ŝanĝi la permesojn al 0770, tiel la dosierujo ne listigeblas de aliaj uzantoj.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Certigu, ke estas dosiero nomata „.ocdata“ en la radiko de la dosierujo de datumoj." + "File is currently busy, please try again later" : "La dosiero estas nun okupita, bv. reprovi poste" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/es.js b/lib/l10n/es.js index b83b69b8f01..3c54dd12f3f 100644 --- a/lib/l10n/es.js +++ b/lib/l10n/es.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Se necesita la versión %s o superior del servidor.", "Server version %s or lower is required." : "Se necesita la versión %s o inferior del servidor. ", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "El usuario que ha iniciado sesión debe ser un administrador, un sub-administrador o haber obtenido permisos especiales para acceder a esta configuración", - "Your current IP address doesn’t allow you to perform admin actions" : "Su dirección IP actual no le permite ejecutar funciones de administrador", + "Your current IP address doesn't allow you to perform admin actions" : "Su dirección IP actual no le permite ejecutar funciones de administrador", "Logged in account must be an admin or sub admin" : "La cuenta conectada debe ser de un administrador o un sub-administrador", "Logged in account must be an admin" : "La cuenta conectada debe ser un administrador", "Wiping of device %s has started" : "El borrado del dispositivo %s ha empezado", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "La imagen de avatar no es cuadrada", "Files" : "Archivos", "View profile" : "Ver perfil", + "same time" : "al mismo tiempo", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%n m","%n m","%n m"], + "%s ahead" : "%s adelantado", + "%s behind" : "%s atrasado", "Local time: %s" : "Hora local: %s", "today" : "hoy", "tomorrow" : "mañana", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "hace segundos", "Empty file" : "Archivo vacío", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "El módulo con ID %s no existe. Por favor, actívalo en la configuración de apps o contacta con tu administrador.", + "No file conversion providers available" : "No hay proveedores de conversión de archivos disponibles", + "File is too large to convert" : "El archivo es demasiado grande para convertir", + "Destination does not match conversion extension" : "El destino no coincide con la extensión convertida", + "Could not convert file" : "No se ha podido convertir el archivo", + "Destination does not exist" : "El destino no existe", + "Destination is not creatable" : "El destino no se puede crear", "Dot files are not allowed" : "Los archivos Dot no están permitidos", + "%1$s (renamed)" : "%1$s (renombrado)", + "renamed file" : "archivo renombrado", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" Es un nombre de archivo o carpeta no permitido.", "\"%1$s\" is a forbidden prefix for file or folder names." : "%1$s es un prefijo prohibido para nombres de archivo o carpeta.", "\"%1$s\" is not allowed inside a file or folder name." : "«%1$s» no se permite en el nombre de un archivo o carpeta.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Ruta no válida", "Failed to create file from template" : "Fallo al crear el archivo desde plantilla", "Templates" : "Plantillas", + "Storage %s cannot be moved" : "El almacenamiento %s no ha podido moverse", + "Moving a share (%s) into a shared folder is not allowed" : "No está permitido mover un recurso compartido (%s) a una carpeta compartida", + "Moving a storage (%s) into a shared folder is not allowed" : "No está permitido mover un almacenamiento (%s) a una carpeta compartida", + "Moving a share (%s) into another share (%s) is not allowed" : "No está permitido mover un recurso compartido (%s) a otro recurso compartido (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "No está permitido mover un recurso compartido (%s) a otro almacenamiento (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "No está permitido mover un almacenamiento (%s) a un recurso compartido (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "No está permitido mover un almacenamiento (%s) a otro almacenamiento (%s)", "Path contains invalid segments" : "La ruta contiene segmentos inválidos", "Filename is a reserved word" : "El nombre de archivo es una palabra reservada", "Filename contains at least one invalid character" : "El nombre de archivo contiene al menos un carácter inválido", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "Acerca de", "Display name" : "Nombre para mostrar", "Headline" : "Titular", - "Organisation" : "Organización", + "Organization" : "Organización", "Role" : "Puesto", "Pronouns" : "Pronombres", "Unknown account" : "Cuenta desconocida", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "No se pudo establecer la conexión a Oracle", "Oracle Login and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", "PostgreSQL Login and/or password not valid" : "Usuario y/o contraseña de PostgreSQL inválidos", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X no está soportado y %s no funcionará bien en esta plataforma. ¡Úsala bajo tu propio riesgo! ", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X no está soportado y %s no funcionará bien en esta plataforma. ¡Úsela bajo su propio riesgo! ", "For the best results, please consider using a GNU/Linux server instead." : "Para obtener los mejores resultados, considera utilizar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Parece que esta instancia %s está funcionando en un entorno PHP de 32-bits y el open_basedir se ha configurado en php.ini. Esto acarreará problemas con archivos de tamaño superior a 4GB y resulta totalmente desaconsejado.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, quite el ajuste de open_basedir —dentro de su php.ini— o pásese a PHP de 64 bits.", @@ -148,8 +168,12 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El motor compartido %s debe implementar la interfaz OCP\\Share_Backend", "Sharing backend %s not found" : "El motor compartido %s no se ha encontrado", "Sharing backend for %s not found" : "Motor compartido para %s no encontrado", - "Click the button below to open it." : "Haz clic en el botón de abajo para abrirlo.", + "%1$s shared %2$s with you" : "%1$s ha compartido %2$s contigo", + "Open %s" : "Abrir %s", "%1$s via %2$s" : "%1$s vía %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s ha compartido %2$s contigo y quiere añadir:", + "%1$s shared %2$s with you and wants to add" : "%1$s ha compartido %2$s contigo y quiere añadir", + "%s added a note to a file shared with you" : "%s ha añadido una nota a un archivo compartido contigo", "Passwords are enforced for link and mail shares" : "Las contraseñas son obligatorias para los enlaces y correos compartidos.", "Share recipient is not a valid user" : "El recipiente del recurso compartido no es un usuario válido", "Share recipient is not a valid group" : "El recipiente del recurso compartido no es un grupo válido", @@ -164,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "No puede compartir su carpeta raíz", "You are not allowed to share %s" : "Usted no está autorizado para compartir %s", "Valid permissions are required for sharing" : "Se requieren permisos válidos para compartir", + "File shares cannot have create or delete permissions" : "Las recursos compartidos de archivos no pueden tener permisos de creación o borrado", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", "Shares need at least read permissions" : "Los recursos compartidos requieren al menos permisos de lectura", "Files cannot be shared with delete permissions" : "Los archivos no se pueden compartir con permisos de borrado", @@ -178,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "La ruta ya se encuentra compartida con este grupo", "Link sharing is not allowed" : "La compartición de enlaces no está permitida", "Public upload is not allowed" : "No está permitida la subida de archivos pública", - "Path contains files shared with you" : "La ruta contiene archivos compartidos con Ud.", + "You cannot share a folder that contains other shares" : "No puede compartir una carpeta que contiene otros recursos compartidos", "Sharing is disabled" : "Compartir está deshabilitado", "Sharing is disabled for you" : "Compartir está deshabilitado para Ud.", "Cannot share with the share owner" : "No se puede compartir con el propietario del recurso compartido", @@ -306,8 +331,19 @@ OC.L10N.register( "The audio to transcribe" : "El audio a transcribir", "Transcription" : "Transcripción", "The transcribed text" : "El texto transcrito", + "Chat with an agent" : "Chatea con un agente", "Chat message" : "Mensaje de chat", + "A chat message to send to the agent." : "Un mensaje de chat a escribir al agente", "Confirmation" : "Confirmación", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Si se deben confirmar acciones solicitadas anteriormente: 0 para denegar y 1 para confirmar.", + "Conversation token" : "Token de conversación", + "A token representing the conversation." : "Un token que representa la conversación.", + "Generated response" : "Respuesta generada", + "The response from the chat model." : "La respuesta del modelo de chat.", + "The new conversation token" : "El nuevo token de conversación", + "Send this along with the next interaction." : "Envía esto junto a la siguiente interacción.", + "Requested actions by the agent" : "Acciones solicitadas por el agente", + "Actions that the agent would like to carry out in JSON format." : "Acciones que el agente quiere realizar en formato JSON.", "Context write" : "Escribir contexto", "Writes text in a given style based on the provided source material." : "Escribe el texto en un estilo dado basándose en el material fuente proporcionado.", "Writing style" : "Estilo de escritura", @@ -329,11 +365,22 @@ OC.L10N.register( "How many images to generate" : "Cuántas imágenes se generarán", "Output images" : "Imágenes de salida", "The generated images" : "Las imágenes generadas", + "Generate speech" : "Generar dictado", + "Generate speech from a transcript" : "Generar dictado desde una transcripción", + "Write transcript that you want the assistant to generate speech from" : "Escriba la transcripción desde la que desea que el asistente genere un dictado", + "Output speech" : "Dictado de salida", + "The generated speech" : "El dictado generado", "Free text to text prompt" : "Texto libre a prompt de texto", "Runs an arbitrary prompt through a language model that returns a reply" : "Ejecuta un prompt arbitrario a través de un modelo de lenguaje que retorna una respuesta", "Describe a task that you want the assistant to do or ask a question" : "Describa una tarea que quiere que el asistente realice, o, haga una pregunta", "Generated reply" : "Respuesta generada", "The generated text from the assistant" : "El texto generado por el asistente", + "Change Tone" : "Cambiar tono", + "Change the tone of a piece of text." : "Cambiar el tono de un texto.", + "Write a text that you want the assistant to rewrite in another tone." : "Escribe un texto que quieres que el asistente reescriba en otro tono", + "Desired tone" : "Tono deseado", + "In which tone should your text be rewritten?" : "¿En qué tono debe reescribirse tu texto?", + "The rewritten text in the desired tone, written by the assistant:" : "El texto reescrito en el tono deseado, escrito por el asistente:", "Chat" : "Chat", "Chat with the assistant" : "Chatear con el asistente", "System prompt" : "Prompt del sistema", @@ -342,6 +389,15 @@ OC.L10N.register( "The history of chat messages before the current message, starting with a message by the user" : "El historial de mensajes del chat antes del mensaje actual, empezando con un mensaje del usuario", "Response message" : "Mensaje de respuesta", "The generated response as part of the conversation" : "La respuesta generada como parte de la conversación", + "Chat with tools" : "Chat con herramientas:", + "Chat with the language model with tool calling support." : "Cheatea con el modelo de lenguaje con capacidad para llamar a herramientas.", + "Tool message" : "Mensaje de herramienta", + "The result of tool calls in the last interaction" : "El resultado de llamada a herramientas de la última interacción", + "Available tools" : "Herramientas disponibles", + "The available tools in JSON format" : "Las herramientas disponibles en formato JSON", + "The response from the chat model" : "La respuesta del modelo de chat", + "Tool calls" : "Llamadas a herramientas", + "Tools call instructions from the model in JSON format" : "Instrucciones para llamadas a herramientas del modelo en formato JSON", "Formalize text" : "Formalizar texto", "Takes a text and makes it sound more formal" : "Toma un texto y lo hace sonar más formal", "Write a text that you want the assistant to formalize" : "Escriba un texto que quiere que el asistente formalice", @@ -352,6 +408,12 @@ OC.L10N.register( "Original text" : "Texto original", "The original text to generate a headline for" : "El texto original para el cual generar un titular", "The generated headline" : "El titular generado", + "Proofread" : "Corregir", + "Proofreads a text and lists corrections" : "Corrige un texto y muestra sugerencias", + "Text" : "Texto", + "The text to proofread" : "El texto a corregir", + "Corrections" : "Correcciones", + "The corrections that should be made in your text" : "Las correcciones que deberían aplicarse a tu texto", "Reformulate text" : "Reformular texto", "Takes a text and reformulates it" : "Toma un texto y lo reformula", "Write a text that you want the assistant to reformulate" : "Escriba un texto que quiere que el asistente reformule", @@ -387,41 +449,9 @@ OC.L10N.register( "Generate headline" : "Generar titular", "Summarizes text by reducing its length without losing key information." : "Resume el texto reduciendo su longitud sin perder información clave.", "Extracts topics from a text and outputs them separated by commas." : "Extrae los tópicos de un texto y genera una salida separada por comas. ", - "Education Edition" : "Edición Educación", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "La sesión del usuario debe corresponder a un administrador, subadministrador, o debe tener derechos especiales para acceder a esta configuración.", - "Logged in user must be an admin or sub admin" : "El usuario activo debe ser un administrador o subadministrador", - "Logged in user must be an admin" : "El usuario registrado debe ser un administrador", - "File name is a reserved word" : "El nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un carácter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Usuario desconocido", - "Enter the database username and name for %s" : "Introduzca el nombre de usuario y la contraseña para la base de datos %s", - "Enter the database username for %s" : "Introduzca el nombre de usuario para la base datos %s", - "MySQL username and/or password not valid" : "Usuario y/o contraseña de MySQL no válidos", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle no válidos", - "PostgreSQL username and/or password not valid" : "Usuario y/o contraseña de PostgreSQL no válidos", - "Set an admin username." : "Configurar un nombre de usuario del administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s ha compartido «%2$s» contigo y quiere añadir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s ha compartido «%2$s» contigo y quiere añadir", - "»%s« added a note to a file shared with you" : "«%s» ha añadido una nota a un archivo compartido contigo", - "Open »%s«" : "Abrir »%s« ", - "Sharing %s failed, because this item is already shared with user %s" : "No se pudo compartir %s, porque este elemento ya está compartido con el usuario %s", - "%1$s shared »%2$s« with you" : "%1$s ha compartido «%2$s» contigo", - "%1$s shared »%2$s« with you." : "%1$s ha compartido «%2$s» contigo.", - "The username is already being used" : "El nombre de usuario ya está en uso", - "Could not create user" : "No se ha podido crear el usuario", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Solo los siguientes caracteres están permitidos en un nombre de usuario: \"a-z\", \"A-Z\", \"0-9\", espacios y \"_.@-'\"", - "A valid username must be provided" : "Se debe proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El nombre de usuario contiene espacios en blanco al principio o al final", - "Username must not consist of dots only" : "El nombre de usuario no debe consistir solo de puntos", - "Username is invalid because files already exist for this user" : "El nombre de usuario es incorrecto debido a a que los archivos ya existen para este usuario", - "User disabled" : "Usuario deshabilitado", + "Organisation" : "Organización", "File is currently busy, please try again later" : "El archivo se encuentra actualmente ocupado, por favor inténtelo de nuevo más tarde", "Cannot download file" : "No se puede descargar el archivo", - "Your data directory is readable by other users." : "Su carpeta de datos puede ser leída por otros usuarios.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor, cambie los permisos a 0770 para que el directorio no se pueda ser listado por otros usuarios.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegúrate de que existe un archivo llamado \".ocdata\" en la raíz del directorio de datos." + "Login is too long" : "El nombre de inicio de sesión es demasiado largo" }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es.json b/lib/l10n/es.json index f04a4d44bf4..5c517734ef3 100644 --- a/lib/l10n/es.json +++ b/lib/l10n/es.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Se necesita la versión %s o superior del servidor.", "Server version %s or lower is required." : "Se necesita la versión %s o inferior del servidor. ", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "El usuario que ha iniciado sesión debe ser un administrador, un sub-administrador o haber obtenido permisos especiales para acceder a esta configuración", - "Your current IP address doesn’t allow you to perform admin actions" : "Su dirección IP actual no le permite ejecutar funciones de administrador", + "Your current IP address doesn't allow you to perform admin actions" : "Su dirección IP actual no le permite ejecutar funciones de administrador", "Logged in account must be an admin or sub admin" : "La cuenta conectada debe ser de un administrador o un sub-administrador", "Logged in account must be an admin" : "La cuenta conectada debe ser un administrador", "Wiping of device %s has started" : "El borrado del dispositivo %s ha empezado", @@ -57,6 +57,11 @@ "Avatar image is not square" : "La imagen de avatar no es cuadrada", "Files" : "Archivos", "View profile" : "Ver perfil", + "same time" : "al mismo tiempo", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%n m","%n m","%n m"], + "%s ahead" : "%s adelantado", + "%s behind" : "%s atrasado", "Local time: %s" : "Hora local: %s", "today" : "hoy", "tomorrow" : "mañana", @@ -79,7 +84,15 @@ "seconds ago" : "hace segundos", "Empty file" : "Archivo vacío", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "El módulo con ID %s no existe. Por favor, actívalo en la configuración de apps o contacta con tu administrador.", + "No file conversion providers available" : "No hay proveedores de conversión de archivos disponibles", + "File is too large to convert" : "El archivo es demasiado grande para convertir", + "Destination does not match conversion extension" : "El destino no coincide con la extensión convertida", + "Could not convert file" : "No se ha podido convertir el archivo", + "Destination does not exist" : "El destino no existe", + "Destination is not creatable" : "El destino no se puede crear", "Dot files are not allowed" : "Los archivos Dot no están permitidos", + "%1$s (renamed)" : "%1$s (renombrado)", + "renamed file" : "archivo renombrado", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" Es un nombre de archivo o carpeta no permitido.", "\"%1$s\" is a forbidden prefix for file or folder names." : "%1$s es un prefijo prohibido para nombres de archivo o carpeta.", "\"%1$s\" is not allowed inside a file or folder name." : "«%1$s» no se permite en el nombre de un archivo o carpeta.", @@ -90,6 +103,13 @@ "Invalid path" : "Ruta no válida", "Failed to create file from template" : "Fallo al crear el archivo desde plantilla", "Templates" : "Plantillas", + "Storage %s cannot be moved" : "El almacenamiento %s no ha podido moverse", + "Moving a share (%s) into a shared folder is not allowed" : "No está permitido mover un recurso compartido (%s) a una carpeta compartida", + "Moving a storage (%s) into a shared folder is not allowed" : "No está permitido mover un almacenamiento (%s) a una carpeta compartida", + "Moving a share (%s) into another share (%s) is not allowed" : "No está permitido mover un recurso compartido (%s) a otro recurso compartido (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "No está permitido mover un recurso compartido (%s) a otro almacenamiento (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "No está permitido mover un almacenamiento (%s) a un recurso compartido (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "No está permitido mover un almacenamiento (%s) a otro almacenamiento (%s)", "Path contains invalid segments" : "La ruta contiene segmentos inválidos", "Filename is a reserved word" : "El nombre de archivo es una palabra reservada", "Filename contains at least one invalid character" : "El nombre de archivo contiene al menos un carácter inválido", @@ -122,7 +142,7 @@ "About" : "Acerca de", "Display name" : "Nombre para mostrar", "Headline" : "Titular", - "Organisation" : "Organización", + "Organization" : "Organización", "Role" : "Puesto", "Pronouns" : "Pronombres", "Unknown account" : "Cuenta desconocida", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "No se pudo establecer la conexión a Oracle", "Oracle Login and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", "PostgreSQL Login and/or password not valid" : "Usuario y/o contraseña de PostgreSQL inválidos", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X no está soportado y %s no funcionará bien en esta plataforma. ¡Úsala bajo tu propio riesgo! ", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X no está soportado y %s no funcionará bien en esta plataforma. ¡Úsela bajo su propio riesgo! ", "For the best results, please consider using a GNU/Linux server instead." : "Para obtener los mejores resultados, considera utilizar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Parece que esta instancia %s está funcionando en un entorno PHP de 32-bits y el open_basedir se ha configurado en php.ini. Esto acarreará problemas con archivos de tamaño superior a 4GB y resulta totalmente desaconsejado.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, quite el ajuste de open_basedir —dentro de su php.ini— o pásese a PHP de 64 bits.", @@ -146,8 +166,12 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El motor compartido %s debe implementar la interfaz OCP\\Share_Backend", "Sharing backend %s not found" : "El motor compartido %s no se ha encontrado", "Sharing backend for %s not found" : "Motor compartido para %s no encontrado", - "Click the button below to open it." : "Haz clic en el botón de abajo para abrirlo.", + "%1$s shared %2$s with you" : "%1$s ha compartido %2$s contigo", + "Open %s" : "Abrir %s", "%1$s via %2$s" : "%1$s vía %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s ha compartido %2$s contigo y quiere añadir:", + "%1$s shared %2$s with you and wants to add" : "%1$s ha compartido %2$s contigo y quiere añadir", + "%s added a note to a file shared with you" : "%s ha añadido una nota a un archivo compartido contigo", "Passwords are enforced for link and mail shares" : "Las contraseñas son obligatorias para los enlaces y correos compartidos.", "Share recipient is not a valid user" : "El recipiente del recurso compartido no es un usuario válido", "Share recipient is not a valid group" : "El recipiente del recurso compartido no es un grupo válido", @@ -162,6 +186,7 @@ "You cannot share your root folder" : "No puede compartir su carpeta raíz", "You are not allowed to share %s" : "Usted no está autorizado para compartir %s", "Valid permissions are required for sharing" : "Se requieren permisos válidos para compartir", + "File shares cannot have create or delete permissions" : "Las recursos compartidos de archivos no pueden tener permisos de creación o borrado", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", "Shares need at least read permissions" : "Los recursos compartidos requieren al menos permisos de lectura", "Files cannot be shared with delete permissions" : "Los archivos no se pueden compartir con permisos de borrado", @@ -176,7 +201,7 @@ "Path is already shared with this group" : "La ruta ya se encuentra compartida con este grupo", "Link sharing is not allowed" : "La compartición de enlaces no está permitida", "Public upload is not allowed" : "No está permitida la subida de archivos pública", - "Path contains files shared with you" : "La ruta contiene archivos compartidos con Ud.", + "You cannot share a folder that contains other shares" : "No puede compartir una carpeta que contiene otros recursos compartidos", "Sharing is disabled" : "Compartir está deshabilitado", "Sharing is disabled for you" : "Compartir está deshabilitado para Ud.", "Cannot share with the share owner" : "No se puede compartir con el propietario del recurso compartido", @@ -304,8 +329,19 @@ "The audio to transcribe" : "El audio a transcribir", "Transcription" : "Transcripción", "The transcribed text" : "El texto transcrito", + "Chat with an agent" : "Chatea con un agente", "Chat message" : "Mensaje de chat", + "A chat message to send to the agent." : "Un mensaje de chat a escribir al agente", "Confirmation" : "Confirmación", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Si se deben confirmar acciones solicitadas anteriormente: 0 para denegar y 1 para confirmar.", + "Conversation token" : "Token de conversación", + "A token representing the conversation." : "Un token que representa la conversación.", + "Generated response" : "Respuesta generada", + "The response from the chat model." : "La respuesta del modelo de chat.", + "The new conversation token" : "El nuevo token de conversación", + "Send this along with the next interaction." : "Envía esto junto a la siguiente interacción.", + "Requested actions by the agent" : "Acciones solicitadas por el agente", + "Actions that the agent would like to carry out in JSON format." : "Acciones que el agente quiere realizar en formato JSON.", "Context write" : "Escribir contexto", "Writes text in a given style based on the provided source material." : "Escribe el texto en un estilo dado basándose en el material fuente proporcionado.", "Writing style" : "Estilo de escritura", @@ -327,11 +363,22 @@ "How many images to generate" : "Cuántas imágenes se generarán", "Output images" : "Imágenes de salida", "The generated images" : "Las imágenes generadas", + "Generate speech" : "Generar dictado", + "Generate speech from a transcript" : "Generar dictado desde una transcripción", + "Write transcript that you want the assistant to generate speech from" : "Escriba la transcripción desde la que desea que el asistente genere un dictado", + "Output speech" : "Dictado de salida", + "The generated speech" : "El dictado generado", "Free text to text prompt" : "Texto libre a prompt de texto", "Runs an arbitrary prompt through a language model that returns a reply" : "Ejecuta un prompt arbitrario a través de un modelo de lenguaje que retorna una respuesta", "Describe a task that you want the assistant to do or ask a question" : "Describa una tarea que quiere que el asistente realice, o, haga una pregunta", "Generated reply" : "Respuesta generada", "The generated text from the assistant" : "El texto generado por el asistente", + "Change Tone" : "Cambiar tono", + "Change the tone of a piece of text." : "Cambiar el tono de un texto.", + "Write a text that you want the assistant to rewrite in another tone." : "Escribe un texto que quieres que el asistente reescriba en otro tono", + "Desired tone" : "Tono deseado", + "In which tone should your text be rewritten?" : "¿En qué tono debe reescribirse tu texto?", + "The rewritten text in the desired tone, written by the assistant:" : "El texto reescrito en el tono deseado, escrito por el asistente:", "Chat" : "Chat", "Chat with the assistant" : "Chatear con el asistente", "System prompt" : "Prompt del sistema", @@ -340,6 +387,15 @@ "The history of chat messages before the current message, starting with a message by the user" : "El historial de mensajes del chat antes del mensaje actual, empezando con un mensaje del usuario", "Response message" : "Mensaje de respuesta", "The generated response as part of the conversation" : "La respuesta generada como parte de la conversación", + "Chat with tools" : "Chat con herramientas:", + "Chat with the language model with tool calling support." : "Cheatea con el modelo de lenguaje con capacidad para llamar a herramientas.", + "Tool message" : "Mensaje de herramienta", + "The result of tool calls in the last interaction" : "El resultado de llamada a herramientas de la última interacción", + "Available tools" : "Herramientas disponibles", + "The available tools in JSON format" : "Las herramientas disponibles en formato JSON", + "The response from the chat model" : "La respuesta del modelo de chat", + "Tool calls" : "Llamadas a herramientas", + "Tools call instructions from the model in JSON format" : "Instrucciones para llamadas a herramientas del modelo en formato JSON", "Formalize text" : "Formalizar texto", "Takes a text and makes it sound more formal" : "Toma un texto y lo hace sonar más formal", "Write a text that you want the assistant to formalize" : "Escriba un texto que quiere que el asistente formalice", @@ -350,6 +406,12 @@ "Original text" : "Texto original", "The original text to generate a headline for" : "El texto original para el cual generar un titular", "The generated headline" : "El titular generado", + "Proofread" : "Corregir", + "Proofreads a text and lists corrections" : "Corrige un texto y muestra sugerencias", + "Text" : "Texto", + "The text to proofread" : "El texto a corregir", + "Corrections" : "Correcciones", + "The corrections that should be made in your text" : "Las correcciones que deberían aplicarse a tu texto", "Reformulate text" : "Reformular texto", "Takes a text and reformulates it" : "Toma un texto y lo reformula", "Write a text that you want the assistant to reformulate" : "Escriba un texto que quiere que el asistente reformule", @@ -385,41 +447,9 @@ "Generate headline" : "Generar titular", "Summarizes text by reducing its length without losing key information." : "Resume el texto reduciendo su longitud sin perder información clave.", "Extracts topics from a text and outputs them separated by commas." : "Extrae los tópicos de un texto y genera una salida separada por comas. ", - "Education Edition" : "Edición Educación", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "La sesión del usuario debe corresponder a un administrador, subadministrador, o debe tener derechos especiales para acceder a esta configuración.", - "Logged in user must be an admin or sub admin" : "El usuario activo debe ser un administrador o subadministrador", - "Logged in user must be an admin" : "El usuario registrado debe ser un administrador", - "File name is a reserved word" : "El nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un carácter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Usuario desconocido", - "Enter the database username and name for %s" : "Introduzca el nombre de usuario y la contraseña para la base de datos %s", - "Enter the database username for %s" : "Introduzca el nombre de usuario para la base datos %s", - "MySQL username and/or password not valid" : "Usuario y/o contraseña de MySQL no válidos", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle no válidos", - "PostgreSQL username and/or password not valid" : "Usuario y/o contraseña de PostgreSQL no válidos", - "Set an admin username." : "Configurar un nombre de usuario del administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s ha compartido «%2$s» contigo y quiere añadir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s ha compartido «%2$s» contigo y quiere añadir", - "»%s« added a note to a file shared with you" : "«%s» ha añadido una nota a un archivo compartido contigo", - "Open »%s«" : "Abrir »%s« ", - "Sharing %s failed, because this item is already shared with user %s" : "No se pudo compartir %s, porque este elemento ya está compartido con el usuario %s", - "%1$s shared »%2$s« with you" : "%1$s ha compartido «%2$s» contigo", - "%1$s shared »%2$s« with you." : "%1$s ha compartido «%2$s» contigo.", - "The username is already being used" : "El nombre de usuario ya está en uso", - "Could not create user" : "No se ha podido crear el usuario", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Solo los siguientes caracteres están permitidos en un nombre de usuario: \"a-z\", \"A-Z\", \"0-9\", espacios y \"_.@-'\"", - "A valid username must be provided" : "Se debe proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El nombre de usuario contiene espacios en blanco al principio o al final", - "Username must not consist of dots only" : "El nombre de usuario no debe consistir solo de puntos", - "Username is invalid because files already exist for this user" : "El nombre de usuario es incorrecto debido a a que los archivos ya existen para este usuario", - "User disabled" : "Usuario deshabilitado", + "Organisation" : "Organización", "File is currently busy, please try again later" : "El archivo se encuentra actualmente ocupado, por favor inténtelo de nuevo más tarde", "Cannot download file" : "No se puede descargar el archivo", - "Your data directory is readable by other users." : "Su carpeta de datos puede ser leída por otros usuarios.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor, cambie los permisos a 0770 para que el directorio no se pueda ser listado por otros usuarios.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegúrate de que existe un archivo llamado \".ocdata\" en la raíz del directorio de datos." + "Login is too long" : "El nombre de inicio de sesión es demasiado largo" },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_419.js b/lib/l10n/es_419.js index 7061ade82d3..053881fd07b 100644 --- a/lib/l10n/es_419.js +++ b/lib/l10n/es_419.js @@ -62,10 +62,10 @@ OC.L10N.register( "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca de", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -73,7 +73,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -146,29 +145,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_419.json b/lib/l10n/es_419.json index 8bbd88a5d84..8b0cce581e9 100644 --- a/lib/l10n/es_419.json +++ b/lib/l10n/es_419.json @@ -60,10 +60,10 @@ "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca de", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -71,7 +71,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -144,29 +143,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_AR.js b/lib/l10n/es_AR.js index 2dd6042ff5c..a7f98f5f44e 100644 --- a/lib/l10n/es_AR.js +++ b/lib/l10n/es_AR.js @@ -52,10 +52,12 @@ OC.L10N.register( "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca de", + "Headline" : "Títular", + "Role" : "Rol", + "Pronouns" : "Pronombres", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesita ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Uselo bajo su propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, favor de cosiderar usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Favor de eliminar el ajuste open_basedir de su archivo php.ini o cambie a PHP de 64 bits. ", @@ -63,7 +65,12 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haga click en el botón de abajo para abrirlo.", + "%1$s shared %2$s with you" : "%1$s ha compartido \"%2$s\" con usted", + "Open %s" : "Abrir %s", + "%1$s via %2$s" : "%1$s vía %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s le compartió %2$s y quiere añadir:", + "%1$s shared %2$s with you and wants to add" : "%1$s le compartió %2$s y quiere añadir", + "%s added a note to a file shared with you" : "%s añadió una nota a un archivo compartido con Ud.", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tiene permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -135,26 +142,11 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "Se agotó el tiempo de conexión del almacenamiento. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "El nombre de usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El nombre de usuario y/o contraseña de PostgreSQL inválidos", - "Set an admin username." : "Configurar un nombre de usuario del administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese nombre de usuario ya está en uso", - "A valid username must be provided" : "Se debe proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El nombre del usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El nombre de usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, favor de intentarlo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Favor de cambiar los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. " + "Organisation" : "Organización", + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, favor de intentarlo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_AR.json b/lib/l10n/es_AR.json index 71c74405703..e237e98757f 100644 --- a/lib/l10n/es_AR.json +++ b/lib/l10n/es_AR.json @@ -50,10 +50,12 @@ "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca de", + "Headline" : "Títular", + "Role" : "Rol", + "Pronouns" : "Pronombres", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesita ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Uselo bajo su propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, favor de cosiderar usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Favor de eliminar el ajuste open_basedir de su archivo php.ini o cambie a PHP de 64 bits. ", @@ -61,7 +63,12 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haga click en el botón de abajo para abrirlo.", + "%1$s shared %2$s with you" : "%1$s ha compartido \"%2$s\" con usted", + "Open %s" : "Abrir %s", + "%1$s via %2$s" : "%1$s vía %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s le compartió %2$s y quiere añadir:", + "%1$s shared %2$s with you and wants to add" : "%1$s le compartió %2$s y quiere añadir", + "%s added a note to a file shared with you" : "%s añadió una nota a un archivo compartido con Ud.", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tiene permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -133,26 +140,11 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "Se agotó el tiempo de conexión del almacenamiento. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "El nombre de usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El nombre de usuario y/o contraseña de PostgreSQL inválidos", - "Set an admin username." : "Configurar un nombre de usuario del administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese nombre de usuario ya está en uso", - "A valid username must be provided" : "Se debe proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El nombre del usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El nombre de usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, favor de intentarlo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Favor de cambiar los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. " + "Organisation" : "Organización", + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, favor de intentarlo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_CL.js b/lib/l10n/es_CL.js index 6ba07851af1..c5a52bd6223 100644 --- a/lib/l10n/es_CL.js +++ b/lib/l10n/es_CL.js @@ -62,10 +62,10 @@ OC.L10N.register( "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca de", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -73,7 +73,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -146,30 +145,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_CL.json b/lib/l10n/es_CL.json index ad79e6eb3bc..338d98d949a 100644 --- a/lib/l10n/es_CL.json +++ b/lib/l10n/es_CL.json @@ -60,10 +60,10 @@ "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca de", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -71,7 +71,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -144,30 +143,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_CO.js b/lib/l10n/es_CO.js index 8d0a0e04c37..b41f82239a5 100644 --- a/lib/l10n/es_CO.js +++ b/lib/l10n/es_CO.js @@ -65,7 +65,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -73,7 +72,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -146,30 +144,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_CO.json b/lib/l10n/es_CO.json index 333d1aca5a3..c5f85cce0c2 100644 --- a/lib/l10n/es_CO.json +++ b/lib/l10n/es_CO.json @@ -63,7 +63,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -71,7 +70,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -144,30 +142,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_CR.js b/lib/l10n/es_CR.js index 63a490f5993..ff23d21ef3d 100644 --- a/lib/l10n/es_CR.js +++ b/lib/l10n/es_CR.js @@ -65,7 +65,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -73,7 +72,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -146,30 +144,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_CR.json b/lib/l10n/es_CR.json index 99441762160..f1543683fbd 100644 --- a/lib/l10n/es_CR.json +++ b/lib/l10n/es_CR.json @@ -63,7 +63,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -71,7 +70,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -144,30 +142,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_DO.js b/lib/l10n/es_DO.js index 15722199f0d..d422ddf8f77 100644 --- a/lib/l10n/es_DO.js +++ b/lib/l10n/es_DO.js @@ -65,7 +65,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -73,7 +72,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -146,30 +144,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_DO.json b/lib/l10n/es_DO.json index abfcae74d37..bff8e6ccf95 100644 --- a/lib/l10n/es_DO.json +++ b/lib/l10n/es_DO.json @@ -63,7 +63,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -71,7 +70,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -144,30 +142,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_EC.js b/lib/l10n/es_EC.js index 5659ca4f4e0..554ef16d3b5 100644 --- a/lib/l10n/es_EC.js +++ b/lib/l10n/es_EC.js @@ -53,6 +53,7 @@ OC.L10N.register( "Avatar image is not square" : "La imagen del avatar no es un cuadrado", "Files" : "Archivos", "View profile" : "Ver perfil", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], "Local time: %s" : "Hora local: %s", "today" : "hoy", "tomorrow" : "mañana", @@ -108,14 +109,13 @@ OC.L10N.register( "About" : "Acerca de", "Display name" : "Nombre para mostrar", "Headline" : "Título", - "Organisation" : "Organización", + "Organization" : "Organización", "Role" : "Rol", "Additional settings" : "Configuraciones adicionales", "Enter the database name for %s" : "Introduce el nombre de la base de datos para %s", "You cannot use dots in the database name %s" : "No se pueden utilizar puntos en el nombre de la base de datos %s", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -124,7 +124,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "%1$s via %2$s" : "%1$s a través de %2$s", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", @@ -229,45 +228,13 @@ OC.L10N.register( "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", "Confirmation" : "Confirmación", "Prompt" : "Promoción", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Target language" : "Lenguaje de destino", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "El usuario que ha iniciado sesión debe ser un administrador, un subadministrador o tener permisos especiales para acceder a esta configuración.", - "Logged in user must be an admin or sub admin" : "El usuario que ha iniciado sesión debe ser un administrador o un subadministrador.", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Enter the database username and name for %s" : "Introduce el nombre de usuario y el nombre de la base de datos para %s", - "Enter the database username for %s" : "Introduce el nombre de usuario de la base de datos para %s", - "MySQL username and/or password not valid" : "Nombre de usuario y/o contraseña de MySQL no válidos", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartió »%2$s« contigo y quiere añadir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartió »%2$s« contigo y quiere añadir", - "»%s« added a note to a file shared with you" : "»%s« añadió una nota a un archivo compartido contigo", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "%1$s shared »%2$s« with you" : "%1$s compartió »%2$s« contigo", - "%1$s shared »%2$s« with you." : "%1$s compartió »%2$s« contigo.", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Solo se permiten los siguientes caracteres en un nombre de usuario: \"a-z\", \"A-Z\", \"0-9\", espacios y \"_.@-'\"", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "Username is invalid because files already exist for this user" : "El nombre de usuario no es válido porque ya existen archivos para este usuario", - "User disabled" : "Usuario deshabilitado", + "Organisation" : "Organización", "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Cannot download file" : "No se puede descargar el archivo", - "Your data directory is readable by other users." : "Tu directorio de datos es legible por otros usuarios.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "Cannot download file" : "No se puede descargar el archivo" }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_EC.json b/lib/l10n/es_EC.json index 2decac3f2f9..4fda1eaaeaf 100644 --- a/lib/l10n/es_EC.json +++ b/lib/l10n/es_EC.json @@ -51,6 +51,7 @@ "Avatar image is not square" : "La imagen del avatar no es un cuadrado", "Files" : "Archivos", "View profile" : "Ver perfil", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], "Local time: %s" : "Hora local: %s", "today" : "hoy", "tomorrow" : "mañana", @@ -106,14 +107,13 @@ "About" : "Acerca de", "Display name" : "Nombre para mostrar", "Headline" : "Título", - "Organisation" : "Organización", + "Organization" : "Organización", "Role" : "Rol", "Additional settings" : "Configuraciones adicionales", "Enter the database name for %s" : "Introduce el nombre de la base de datos para %s", "You cannot use dots in the database name %s" : "No se pueden utilizar puntos en el nombre de la base de datos %s", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -122,7 +122,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "%1$s via %2$s" : "%1$s a través de %2$s", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", @@ -227,45 +226,13 @@ "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", "Confirmation" : "Confirmación", "Prompt" : "Promoción", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Target language" : "Lenguaje de destino", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "El usuario que ha iniciado sesión debe ser un administrador, un subadministrador o tener permisos especiales para acceder a esta configuración.", - "Logged in user must be an admin or sub admin" : "El usuario que ha iniciado sesión debe ser un administrador o un subadministrador.", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Enter the database username and name for %s" : "Introduce el nombre de usuario y el nombre de la base de datos para %s", - "Enter the database username for %s" : "Introduce el nombre de usuario de la base de datos para %s", - "MySQL username and/or password not valid" : "Nombre de usuario y/o contraseña de MySQL no válidos", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartió »%2$s« contigo y quiere añadir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartió »%2$s« contigo y quiere añadir", - "»%s« added a note to a file shared with you" : "»%s« añadió una nota a un archivo compartido contigo", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "%1$s shared »%2$s« with you" : "%1$s compartió »%2$s« contigo", - "%1$s shared »%2$s« with you." : "%1$s compartió »%2$s« contigo.", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Solo se permiten los siguientes caracteres en un nombre de usuario: \"a-z\", \"A-Z\", \"0-9\", espacios y \"_.@-'\"", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "Username is invalid because files already exist for this user" : "El nombre de usuario no es válido porque ya existen archivos para este usuario", - "User disabled" : "Usuario deshabilitado", + "Organisation" : "Organización", "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Cannot download file" : "No se puede descargar el archivo", - "Your data directory is readable by other users." : "Tu directorio de datos es legible por otros usuarios.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "Cannot download file" : "No se puede descargar el archivo" },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_GT.js b/lib/l10n/es_GT.js index e1f0fcfc543..c5ddb516258 100644 --- a/lib/l10n/es_GT.js +++ b/lib/l10n/es_GT.js @@ -65,7 +65,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -73,7 +72,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -146,30 +144,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_GT.json b/lib/l10n/es_GT.json index c9478bf33c8..31470583a89 100644 --- a/lib/l10n/es_GT.json +++ b/lib/l10n/es_GT.json @@ -63,7 +63,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -71,7 +70,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -144,30 +142,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_HN.js b/lib/l10n/es_HN.js index 8474bf867cf..72d33d114d4 100644 --- a/lib/l10n/es_HN.js +++ b/lib/l10n/es_HN.js @@ -64,7 +64,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -72,7 +71,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -145,29 +143,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_HN.json b/lib/l10n/es_HN.json index a310e1c5376..3968c31b05f 100644 --- a/lib/l10n/es_HN.json +++ b/lib/l10n/es_HN.json @@ -62,7 +62,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -70,7 +69,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -143,29 +141,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_MX.js b/lib/l10n/es_MX.js index 79e21ce1f47..ec1e4df809b 100644 --- a/lib/l10n/es_MX.js +++ b/lib/l10n/es_MX.js @@ -38,7 +38,6 @@ OC.L10N.register( "Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ", "Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "El usuario que ha iniciado sesión debe ser un administrador, un subadministrador o tener permisos especiales para acceder a esta configuración", - "Your current IP address doesn’t allow you to perform admin actions" : "Su dirección IP actual no le permite realizar acciones de administración", "Logged in account must be an admin or sub admin" : "El usuario conectado debe ser un administrador o un subadministrador", "Logged in account must be an admin" : "El usuario conectado debe ser un administrador", "Wiping of device %s has started" : "La limpieza del dispositivo %s ha comenzado", @@ -59,6 +58,7 @@ OC.L10N.register( "Avatar image is not square" : "La imagen del avatar no es un cuadrado", "Files" : "Archivos", "View profile" : "Ver perfil", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], "Local time: %s" : "Hora local: %s", "today" : "hoy", "tomorrow" : "mañana", @@ -119,7 +119,6 @@ OC.L10N.register( "About" : "Acerca de", "Display name" : "Nombre para mostrar", "Headline" : "Título", - "Organisation" : "Organización", "Role" : "Cargo", "Pronouns" : "Pronombre", "Unknown account" : "Cuenta desconocida", @@ -133,7 +132,6 @@ OC.L10N.register( "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", "Oracle Login and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", "PostgreSQL Login and/or password not valid" : "Usuario y/o contraseña de PostgreSQL inválidos", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -144,7 +142,6 @@ OC.L10N.register( "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", "%1$s shared %2$s with you" : "%1$s le compartió %2$s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Open %s" : "Abrir %s", "%1$s via %2$s" : "%1$s vía %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s le compartió %2$s y quiere añadir:", @@ -178,7 +175,6 @@ OC.L10N.register( "Path is already shared with this group" : "La ruta ya ha sido compartida con este grupo", "Link sharing is not allowed" : "La compartición mediante enlaces no está permitida", "Public upload is not allowed" : "No se permite la subida pública de archivos", - "Path contains files shared with you" : "La ruta contiene archivos compartidos contigo", "Sharing is disabled" : "Compartir está deshabilitado", "Sharing is disabled for you" : "No estás habilitado para compartir", "Cannot share with the share owner" : "No puedes compartir con el propietario del recurso compartido", @@ -345,6 +341,7 @@ OC.L10N.register( "Original text" : "Texto original", "The original text to generate a headline for" : "El texto original para generar un titular", "The generated headline" : "El titular generado", + "Text" : "Texto", "Reformulate text" : "Reformular texto", "Takes a text and reformulates it" : "Toma un texto y lo reformula", "Write a text that you want the assistant to reformulate" : "Escriba un texto que quiere que el asistente reformule", @@ -380,41 +377,8 @@ OC.L10N.register( "Generate headline" : "Generar titular", "Summarizes text by reducing its length without losing key information." : "Resume el texto reduciendo su longitud sin perder información clave.", "Extracts topics from a text and outputs them separated by commas." : "Extrae los temas de un texto y genera una salida separada por comas. ", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "El usuario que ha iniciado sesión debe ser un administrador, un subadministrador o tener permisos especiales para acceder a esta configuración", - "Logged in user must be an admin or sub admin" : "El usuario conectado debe ser un administrador o un subadministrador", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Enter the database username and name for %s" : "Introduzca el usuario y el nombre para la base de datos %s", - "Enter the database username for %s" : "Introduzca el usuario de la base de datos %s", - "MySQL username and/or password not valid" : "Usuario y/o contraseña de MySQL inválidos", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartió »%2$s« contigo y quiere añadir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartió »%2$s« contigo y quiere añadir", - "»%s« added a note to a file shared with you" : "»%s« añadió una nota a un archivo compartido contigo", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "%1$s shared »%2$s« with you" : "%1$s compartió »%2$s« contigo", - "%1$s shared »%2$s« with you." : "%1$s compartió »%2$s« contigo.", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Sólo los siguientes caracteres están permitidos en un nombre de usuario: \"a-z\", \"A-Z\", \"0-9\", espacios y \"_.@-'\"", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "Username is invalid because files already exist for this user" : "El nombre de usuario es inválido porque ya existen archivos para éste", - "User disabled" : "Usuario deshabilitado", + "Organisation" : "Organización", "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Cannot download file" : "No se puede descargar el archivo", - "Your data directory is readable by other users." : "Su directorio de datos puede ser leído por otros usuarios.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "Cannot download file" : "No se puede descargar el archivo" }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_MX.json b/lib/l10n/es_MX.json index 3b8576d0025..4fe2eb666cf 100644 --- a/lib/l10n/es_MX.json +++ b/lib/l10n/es_MX.json @@ -36,7 +36,6 @@ "Server version %s or higher is required." : "Se requiere la versión del servidor %s o superior. ", "Server version %s or lower is required." : "La versión del servidor %s o inferior es requerdia. ", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "El usuario que ha iniciado sesión debe ser un administrador, un subadministrador o tener permisos especiales para acceder a esta configuración", - "Your current IP address doesn’t allow you to perform admin actions" : "Su dirección IP actual no le permite realizar acciones de administración", "Logged in account must be an admin or sub admin" : "El usuario conectado debe ser un administrador o un subadministrador", "Logged in account must be an admin" : "El usuario conectado debe ser un administrador", "Wiping of device %s has started" : "La limpieza del dispositivo %s ha comenzado", @@ -57,6 +56,7 @@ "Avatar image is not square" : "La imagen del avatar no es un cuadrado", "Files" : "Archivos", "View profile" : "Ver perfil", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], "Local time: %s" : "Hora local: %s", "today" : "hoy", "tomorrow" : "mañana", @@ -117,7 +117,6 @@ "About" : "Acerca de", "Display name" : "Nombre para mostrar", "Headline" : "Título", - "Organisation" : "Organización", "Role" : "Cargo", "Pronouns" : "Pronombre", "Unknown account" : "Cuenta desconocida", @@ -131,7 +130,6 @@ "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", "Oracle Login and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", "PostgreSQL Login and/or password not valid" : "Usuario y/o contraseña de PostgreSQL inválidos", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -142,7 +140,6 @@ "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", "%1$s shared %2$s with you" : "%1$s le compartió %2$s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Open %s" : "Abrir %s", "%1$s via %2$s" : "%1$s vía %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s le compartió %2$s y quiere añadir:", @@ -176,7 +173,6 @@ "Path is already shared with this group" : "La ruta ya ha sido compartida con este grupo", "Link sharing is not allowed" : "La compartición mediante enlaces no está permitida", "Public upload is not allowed" : "No se permite la subida pública de archivos", - "Path contains files shared with you" : "La ruta contiene archivos compartidos contigo", "Sharing is disabled" : "Compartir está deshabilitado", "Sharing is disabled for you" : "No estás habilitado para compartir", "Cannot share with the share owner" : "No puedes compartir con el propietario del recurso compartido", @@ -343,6 +339,7 @@ "Original text" : "Texto original", "The original text to generate a headline for" : "El texto original para generar un titular", "The generated headline" : "El titular generado", + "Text" : "Texto", "Reformulate text" : "Reformular texto", "Takes a text and reformulates it" : "Toma un texto y lo reformula", "Write a text that you want the assistant to reformulate" : "Escriba un texto que quiere que el asistente reformule", @@ -378,41 +375,8 @@ "Generate headline" : "Generar titular", "Summarizes text by reducing its length without losing key information." : "Resume el texto reduciendo su longitud sin perder información clave.", "Extracts topics from a text and outputs them separated by commas." : "Extrae los temas de un texto y genera una salida separada por comas. ", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "El usuario que ha iniciado sesión debe ser un administrador, un subadministrador o tener permisos especiales para acceder a esta configuración", - "Logged in user must be an admin or sub admin" : "El usuario conectado debe ser un administrador o un subadministrador", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Enter the database username and name for %s" : "Introduzca el usuario y el nombre para la base de datos %s", - "Enter the database username for %s" : "Introduzca el usuario de la base de datos %s", - "MySQL username and/or password not valid" : "Usuario y/o contraseña de MySQL inválidos", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartió »%2$s« contigo y quiere añadir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartió »%2$s« contigo y quiere añadir", - "»%s« added a note to a file shared with you" : "»%s« añadió una nota a un archivo compartido contigo", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "%1$s shared »%2$s« with you" : "%1$s compartió »%2$s« contigo", - "%1$s shared »%2$s« with you." : "%1$s compartió »%2$s« contigo.", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Sólo los siguientes caracteres están permitidos en un nombre de usuario: \"a-z\", \"A-Z\", \"0-9\", espacios y \"_.@-'\"", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "Username is invalid because files already exist for this user" : "El nombre de usuario es inválido porque ya existen archivos para éste", - "User disabled" : "Usuario deshabilitado", + "Organisation" : "Organización", "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Cannot download file" : "No se puede descargar el archivo", - "Your data directory is readable by other users." : "Su directorio de datos puede ser leído por otros usuarios.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "Cannot download file" : "No se puede descargar el archivo" },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_NI.js b/lib/l10n/es_NI.js index b93bc3ace06..261bdc35d55 100644 --- a/lib/l10n/es_NI.js +++ b/lib/l10n/es_NI.js @@ -64,7 +64,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -72,7 +71,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -145,29 +143,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_NI.json b/lib/l10n/es_NI.json index b223e40951e..b26aebe5212 100644 --- a/lib/l10n/es_NI.json +++ b/lib/l10n/es_NI.json @@ -62,7 +62,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -70,7 +69,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -143,29 +141,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_PA.js b/lib/l10n/es_PA.js index 308fefaf1c5..06f1cc33c5b 100644 --- a/lib/l10n/es_PA.js +++ b/lib/l10n/es_PA.js @@ -64,7 +64,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -72,7 +71,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -145,29 +143,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_PA.json b/lib/l10n/es_PA.json index 21842e363c1..98d2ff2bbf6 100644 --- a/lib/l10n/es_PA.json +++ b/lib/l10n/es_PA.json @@ -62,7 +62,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -70,7 +69,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -143,29 +141,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_PE.js b/lib/l10n/es_PE.js index de8d3ebf963..40fa8517265 100644 --- a/lib/l10n/es_PE.js +++ b/lib/l10n/es_PE.js @@ -61,10 +61,10 @@ OC.L10N.register( "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -72,7 +72,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -145,29 +144,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_PE.json b/lib/l10n/es_PE.json index 86ab9768c5a..3d72d9f3832 100644 --- a/lib/l10n/es_PE.json +++ b/lib/l10n/es_PE.json @@ -59,10 +59,10 @@ "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -70,7 +70,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -143,29 +142,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_PR.js b/lib/l10n/es_PR.js index ef48ac4f84d..a63fb4990b8 100644 --- a/lib/l10n/es_PR.js +++ b/lib/l10n/es_PR.js @@ -64,7 +64,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -72,7 +71,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -145,29 +143,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_PR.json b/lib/l10n/es_PR.json index dd8555b4183..b3769931a30 100644 --- a/lib/l10n/es_PR.json +++ b/lib/l10n/es_PR.json @@ -62,7 +62,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -70,7 +69,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -143,29 +141,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_PY.js b/lib/l10n/es_PY.js index b5c9a7fdd5a..31c20bf701f 100644 --- a/lib/l10n/es_PY.js +++ b/lib/l10n/es_PY.js @@ -61,10 +61,10 @@ OC.L10N.register( "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -72,7 +72,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -145,29 +144,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_PY.json b/lib/l10n/es_PY.json index aed50b44691..09360e92048 100644 --- a/lib/l10n/es_PY.json +++ b/lib/l10n/es_PY.json @@ -59,10 +59,10 @@ "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -70,7 +70,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -143,29 +142,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_SV.js b/lib/l10n/es_SV.js index 5f506f22e2d..0750bcc9762 100644 --- a/lib/l10n/es_SV.js +++ b/lib/l10n/es_SV.js @@ -62,10 +62,10 @@ OC.L10N.register( "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca de", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -73,7 +73,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -146,30 +145,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_SV.json b/lib/l10n/es_SV.json index 3de701f71ac..cddb925b103 100644 --- a/lib/l10n/es_SV.json +++ b/lib/l10n/es_SV.json @@ -60,10 +60,10 @@ "Address" : "Dirección", "Profile picture" : "Foto de perfil", "About" : "Acerca de", + "Organization" : "Organización", "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -71,7 +71,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -144,30 +143,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "Logged in user must be an admin" : "El usuario firmado debe ser un administrador", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/es_UY.js b/lib/l10n/es_UY.js index 73a5ff26066..beb9e3689f7 100644 --- a/lib/l10n/es_UY.js +++ b/lib/l10n/es_UY.js @@ -64,7 +64,6 @@ OC.L10N.register( "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -72,7 +71,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -145,29 +143,10 @@ OC.L10N.register( "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/es_UY.json b/lib/l10n/es_UY.json index 1fb63f5d4a7..68d50d1e194 100644 --- a/lib/l10n/es_UY.json +++ b/lib/l10n/es_UY.json @@ -62,7 +62,6 @@ "Additional settings" : "Configuraciones adicionales", "You need to enter details of an existing account." : "Necesitas ingresar los detalles de una cuenta existente.", "Oracle connection could not be established" : "No fue posible establecer la conexión a Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "OS X de Mac no está soportado y %s no funcionará correctamente en esta plataforma ¡Úsalo bajo tu propio riesgo!", "For the best results, please consider using a GNU/Linux server instead." : "Para mejores resultados, por favor cosidera usar en su lugar un servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Al parecer esta instancia %s está corriendo en un ambiente PHP de 32-bits y el open_basedir ha sido configurado en el archivo php.ini. Esto generará problemas con archivos de más de 4GB de tamaño y es altamente desalentado. ", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor elimina el ajuste open_basedir de tu archivo php.ini o cambia a PHP de 64 bits. ", @@ -70,7 +69,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "El backend %s que comparte debe implementar la interface OCP\\Share_Backend", "Sharing backend %s not found" : "No fue encontrado el Backend que comparte %s ", "Sharing backend for %s not found" : "No fue encontrado el Backend que comparte para %s", - "Click the button below to open it." : "Haz click en el botón inferior para abrirlo. ", "Unknown share type" : "Tipo de elemento compartido desconocido", "You are not allowed to share %s" : "No tienes permitido compartir %s", "Cannot increase permissions of %s" : "No se pueden incrementar los permisos de %s", @@ -143,29 +141,10 @@ "Storage connection error. %s" : "Se presentó un error con la conexión al almacenamiento. %s", "Storage is temporarily not available" : "El almacenamieto se encuentra temporalmente no disponible", "Storage connection timeout. %s" : "El tiempo de la conexión del almacenamiento se agotó. %s", + "Text" : "Texto", "Summary" : "Resumen", "Translate" : "Traducir", "Result" : "Resultado", - "Education Edition" : "Edición Educativa", - "File name is a reserved word" : "Nombre de archivo es una palabra reservada", - "File name contains at least one invalid character" : "El nombre del archivo contiene al menos un caracter inválido", - "File name is too long" : "El nombre del archivo es demasiado largo", - "Help" : "Ayuda", - "Users" : "Usuarios", - "Unknown user" : "Ususario desconocido", - "Oracle username and/or password not valid" : "Usuario y/o contraseña de Oracle inválidos", - "PostgreSQL username and/or password not valid" : "El Usuario y/o Contraseña de PostgreSQL inválido(s)", - "Set an admin username." : "Establecer un Usuario administrador", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Se presento una falla al compartir %s, porque este elemento ya ha sido compartido con el usuario %s", - "The username is already being used" : "Ese usuario ya está en uso", - "Could not create user" : "No fue posible crear el usuario", - "A valid username must be provided" : "Debes proporcionar un nombre de usuario válido", - "Username contains whitespace at the beginning or at the end" : "El usuario contiene un espacio en blanco al inicio o al final", - "Username must not consist of dots only" : "El usuario no debe consistir de solo puntos. ", - "User disabled" : "Usuario deshabilitado", - "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. ", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor cambia los permisos a 0770 para que el directorio no pueda ser enlistado por otros usuarios. ", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegurate de que exista una archivo llamado \".ocdata\" en la raíz del directorio de datos. " + "File is currently busy, please try again later" : "El archivo se encuentra actualmente en uso, por favor intentalo más tarde. " },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/et_EE.js b/lib/l10n/et_EE.js index b0924815f1a..41c0f547eed 100644 --- a/lib/l10n/et_EE.js +++ b/lib/l10n/et_EE.js @@ -1,79 +1,221 @@ OC.L10N.register( "lib", { - "Cannot write into \"config\" directory!" : "Ei saa kirjutada \"config\" kataloogi!", + "Cannot write into \"config\" directory!" : "Ei saa kirjutada „config“ kausta!!", + "This can usually be fixed by giving the web server write access to the config directory." : "Tavaliselt saad selle lahendada andes veebiserverile õigused seadistuse kausta kirjutamiseks", + "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Aga kui soovid, et seadistuste fail ei peaks olema veebiserveri poolt muudetav, siis palun määra seadistusvõtme „config_is_read_only“ väärtuseks true.", "See %s" : "Vaata %s", + "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Rakendust „%1$s“ pole serverisse paigaldatud või pole tema versioon ühilduv selle serveriga. Palun kontrolli paigaldatud rakendusi.", "Sample configuration detected" : "Tuvastati näidisseaded", - "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Tuvastati, et kopeeriti näidisseaded. See võib lõhkuda sinu saidi ja see pole toetatud. Palun loe enne faili config.php muutmist dokumentatsiooni", + "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Tuvastasin, et seadistuse faili kopeeritud näidisseaded. See võib lõhkuda sinu saidi ja see pole toetatud. Palun loe enne faili config.php muutmist dokumentatsiooni", + "The page could not be found on the server." : "Seda lehte ei õnnestunud serverist leida.", + "%s email verification" : "E-postiaadressi kinnitamine: %s", + "Email verification" : "E-postiaadressi kinnitamine", + "Click the following button to confirm your email." : "Oma e-postiaadressi kinnitamiseks klõpsi järgmisel nupul.", + "Click the following link to confirm your email." : "Oma e-postiaadressi kinnitamiseks klõpsi järgmisel lingil.", + "Confirm your email" : "Kiinita oma e-posti aadress", + "Other activities" : "Muud tegevused", "%1$s and %2$s" : "%1$s ja %2$s", "%1$s, %2$s and %3$s" : "%1$s, %2$s ja %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s ja %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s ja %5$s", + "Education bundle" : "Rakenduste komplekt haridusasutustele", + "Enterprise bundle" : "Rakenduste komplekt suurorganisatsioonidele", + "Groupware bundle" : "Rühmatarkvara rakenduste komplekt", + "Hub bundle" : "Rakenduste komplekt Nextcloud Hub", + "Public sector bundle" : "Rakenduste komplekt avaliku sektori asutustele", + "Social sharing bundle" : "Rakenduste komplekt sotsiaalmeedias jagamiseks", "PHP %s or higher is required." : "PHP %s või uuem on nõutav.", "PHP with a version lower than %s is required." : "Nõutud on PHP madalama versiooniga kui %s.", + "%sbit or higher PHP required." : "Vajalik on %s-bitine või parem PHP versioon.", + "The following architectures are supported: %s" : "Toetatud on järgnevad arhitektuurid: %s", + "The following databases are supported: %s" : "Toetatud on järgnevad andmebaasid: %s", "The command line tool %s could not be found" : "Käsurea töövahendit %s ei leitud", "The library %s is not available." : "Teek %s pole saadaval.", - "Server version %s or higher is required." : "Serveri versioon %s või kõrgem on nõutav.", + "Library %1$s with a version higher than %2$s is required - available version %3$s." : "Vajalik on „%1$s“ teek suurema versiooniga kui %2$s - hetkel on versioon %3$s.", + "Library %1$s with a version lower than %2$s is required - available version %3$s." : "Vajalik on „%1$s“ teek väiksema versiooniga kui %2$s - hetkel on versioon %3$s.", + "The following platforms are supported: %s" : "Toetatud on järgmised platvormid: %s", + "Server version %s or higher is required." : "Nõutav on serveri versioon %s või suurem.", "Server version %s or lower is required." : "Serveri versioon %s või madalam on nõutav.", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Sisselogitud kasutajakonto peab olema peakasutajate või selle alamgrupi liige või omama eraldi õiguse selle seadustuse muutmiseks", + "Your current IP address doesn't allow you to perform admin actions" : "Sinu praeguselt e-posti aadressilt ei saa teha haldustoiminguid", + "Logged in account must be an admin or sub admin" : "Sisselogitud kasutajakonto peab olema peakasutajate või selle alamgrupi liige", + "Logged in account must be an admin" : "Sisselogitud kasutajakonto peab olema peakasutajate grupi liige", + "Wiping of device %s has started" : "Andmete kustutamine seadmes „%s“ algas", + "Wiping of device »%s« has started" : "Andmete kustutamine seadmes „%s“ algas", + "»%s« started remote wipe" : "„%s“ alustas kaugseadme andmete kustutamist", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "„%s“ seade või rakendus on alustanud kaugkustutamise protsessi. Selle lõppemisel saad veel ühe teavitava e-kirja", + "Wiping of device %s has finished" : "Andmete kustutamine seadmes „%s“ lõppes", + "Wiping of device »%s« has finished" : "Andmete kustutamine seadmes „%s“ lõppes", + "»%s« finished remote wipe" : "„%s“ lõpetas kaugseadme andmete kustutamise", + "Device or application »%s« has finished the remote wipe process." : "„%s“ seade või rakendus on lõpetanud kaugkustutamise protsessi.", + "Remote wipe started" : "Kaugkustutamine on alanud", + "A remote wipe was started on device %s" : "„%s“ seadme kaugkustutamine on alanud", + "Remote wipe finished" : "Kaugkustutamine on lõppenud", + "The remote wipe on %s has finished" : "„%s“ seadme kaugkustutamine on lõppenud", "Authentication" : "Autentimine", "Unknown filetype" : "Tundmatu failitüüp", "Invalid image" : "Vigane pilt", "Avatar image is not square" : "Avatari pilt pole ruut", "Files" : "Failid", "View profile" : "Vaata profiili", + "same time" : "samas ajas", + "_%nh_::_%nh_" : ["%n t","%n t"], + "_%nm_::_%nm_" : ["%n min","%n min"], + "%s ahead" : "%s ees", + "%s behind" : "%s taga", + "Local time: %s" : "Kohalik aeg: %s", "today" : "täna", "tomorrow" : "homme", "yesterday" : "eile", + "_in %n day_::_in %n days_" : ["%n päeva pärast","%n päeva pärast"], "_%n day ago_::_%n days ago_" : ["%n päev tagasi","%n päeva tagasi"], "next month" : "järgmine kuu", "last month" : "viimasel kuul", + "_in %n month_::_in %n months_" : ["%n kuu pärast","%n kuu pärast"], + "_%n month ago_::_%n months ago_" : ["%n kuu eest","%n kuu eest"], "next year" : "järgmine aasta", "last year" : "viimasel aastal", + "_in %n year_::_in %n years_" : ["%n aasta pärast","%n aasta pärast"], "_%n year ago_::_%n years ago_" : ["%n aasta tagasi","%n aastat tagasi"], + "_in %n hour_::_in %n hours_" : ["%n tunni pärast","%n tunni pärast"], "_%n hour ago_::_%n hours ago_" : ["%n tund tagasi","%n tundi tagasi"], + "_in %n minute_::_in %n minutes_" : ["%n minuti pärast","%n minuti pärast"], + "_%n minute ago_::_%n minutes ago_" : ["%n minut tagasi","%n minutit tagasi"], "in a few seconds" : "mõne sekundi jooksul", "seconds ago" : "sekundit tagasi", "Empty file" : "Tühi fail", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Moodulit tunnusega „%s“ pole pole olemas. Palun taga see oma rakenduste seadistustest või võta ühendust peakasutajaga.", + "No file conversion providers available" : "Ühtegi teisendusteenuse pakkujat pole saadaval", + "File is too large to convert" : "Fail on teisendamiseks liiga suur", + "Destination does not match conversion extension" : "Sihtmeedia ei vasta teisendamislaiendile", + "Could not convert file" : "Faili teisendamine ei õnnestu", + "Destination does not exist" : "Sihtmeediat pole olemas", + "Destination is not creatable" : "Sihtmeedia pole loodav", "Dot files are not allowed" : "Punktiga failid pole lubatud", + "%1$s (renamed)" : "%1$s (nimi on muudetud)", + "renamed file" : "muudetud nimega fail", + "\"%1$s\" is a forbidden file or folder name." : "„%1$s“ on keelatud faili- või kaustanimi.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "„%1$s“ on keelatud faili- või kaustanime eesliide.", + "\"%1$s\" is not allowed inside a file or folder name." : "„%1$s“ pole faili- või kaustanimes lubatud.", + "\"%1$s\" is a forbidden file type." : "„%1$s“ on keelatud failitüüp.", + "Filenames must not end with \"%1$s\"." : "Failinimede lõpus ei tohi olla „%1$s“.", + "Invalid parent path" : "Vigane ülemkaust", "File already exists" : "Fail on juba olemas", - "Invalid path" : "Vigane kataloogirada", + "Invalid path" : "Vigane kausta asukoht", "Failed to create file from template" : "Ei saa luua mallist faili", "Templates" : "Mallid", - "Filename contains at least one invalid character" : "Faili nimes on vähemalt üks keelatud märk", + "Storage %s cannot be moved" : "„%s“ andmeruumi ei saa teisaldada", + "Moving a share (%s) into a shared folder is not allowed" : "Jaosmeedia (%s) teisaldamine jaoskausta pole lubatud", + "Moving a storage (%s) into a shared folder is not allowed" : "Andmeruumi (%s) teisaldamine jaoskausta pole lubatud", + "Moving a share (%s) into another share (%s) is not allowed" : "Jaosmeedia (%s) teisaldamine teise jaosmeediasse (%s) pole lubatud", + "Moving a share (%s) into another storage (%s) is not allowed" : "Jaosmeedia (%s) teisaldamine teise andmeruumi (%s) pole lubatud", + "Moving a storage (%s) into a share (%s) is not allowed" : "Andmeruumi (%s) teisaldamine jaosmeediasse (%s) pole lubatud", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Andmeruumi (%s) teisaldamine andmeruumi (%s) pole lubatud", + "Path contains invalid segments" : "Asukohas on vigaseid segmente", + "Filename is a reserved word" : "Failinimi on reserveeritud sõna", + "Filename contains at least one invalid character" : "Failinimes on vähemalt üks keelatud märk", + "Filename is too long" : "Failinimi on liiga pikk", "Empty filename is not allowed" : "Tühi failinimi pole lubatud", + "App \"%s\" cannot be installed because appinfo file cannot be read." : "Kuna „appinfo“ faili pole võimalik lugeda, siis „%s“ rakendust ei saa paigaldada.", + "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Kuna ta pole ühilduv selle serveri versiooniga, siis „%s“ rakendust ei saa paigaldada.", "__language_name__" : "Eesti", "This is an automatically sent email, please do not reply." : "See on automaatselt saadetud e-kiri, palun ära vasta.", + "Help & privacy" : "Abiteave ja privaatsus", + "Appearance and accessibility" : "Välimus ja hõlpsus", "Apps" : "Rakendused", "Personal settings" : "Isiklikud seaded", "Administration settings" : "Administreerimise seaded", "Settings" : "Seaded", "Log out" : "Logi välja", - "Email" : "Epost", + "Accounts" : "Kasutajakontod", + "Email" : "E-post", + "Mail %s" : "E-post %s", + "Fediverse" : "Födiversum", + "View %s on the fediverse" : "Vaata Födiversumis: %s", "Phone" : "Telefon", - "Twitter" : "Twitter", + "Call %s" : "Helista: %s", + "Twitter" : "X / Twitter", + "View %s on Twitter" : "Vaata X-is / Twitteris: %s", "Website" : "Veebileht", + "Visit %s" : "Külasta veebilehte: %s", "Address" : "Aadress", - "Profile picture" : "Profiili pilt", + "Profile picture" : "Profiilipilt", "About" : "Info", "Display name" : "Kuvatav nimi", - "Organisation" : "Organisatsioon", + "Headline" : "Alapealkiri", + "Organization" : "Organisatsioon", "Role" : "Roll", + "Pronouns" : "Asesõnad pöördumisel", + "Unknown account" : "Tundmatu kasutajakonto", "Additional settings" : "Lisaseaded", + "Enter the database Login and name for %s" : "Andmebaasi kasutajanimi ning nimi %si jaoks", + "Enter the database Login for %s" : "Sisesta andmebaasi %s kasutajatunnus", + "Enter the database name for %s" : "Sisesta andmebaasi %s nimi", + "You cannot use dots in the database name %s" : "Sa ei tohi kasutada „%s“ andmebaasi nimes punkte", + "MySQL Login and/or password not valid" : "MySQLi andmebaasi kasutajatunnus ja/või salasõna pole õiged", "You need to enter details of an existing account." : "Sa pead sisestama olemasoleva konto andmed.", "Oracle connection could not be established" : "Ei suuda luua ühendust Oracle baasiga", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X ei ole toetatud ja %s ei pruugi korralikult toimida sellel platvormil. Kasuta seda omal vastutusel!", + "Oracle Login and/or password not valid" : "Oracle andmebaasi kasutajatunnus ja/või salasõna pole õiged", + "PostgreSQL Login and/or password not valid" : "PostgreSQLi andmebaasi kasutajatunnus ja/või salasõna pole õiged", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X ei ole toetatud ja %s ei pruugi korralikult toimida sellel platvormil. Kasuta seda omal vastutusel!", "For the best results, please consider using a GNU/Linux server instead." : "Parema tulemuse saavitamiseks palun kaalu serveris GNU/Linux kasutamist.", - "Set an admin password." : "Määra admini parool.", + "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Palun eemalda oma serveri seadistustest php.ini failist „open_basedir“ seadistus või võta kasutusele 64-bitisel platvormil põhinev PHP versioon.", + "Set an admin Login." : "Lisa peakasutaja kasutajanimi.", + "Set an admin password." : "Lisa peakasutaja salasõna.", + "Cannot create or write into the data directory %s" : "Ei õnnestu luua „%s“ andmekausta või sealt lugeda", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Jagamise tagarakend %s peab kasutusele võtma OCP\\Share_Backend liidese", "Sharing backend %s not found" : "Jagamise tagarakendit %s ei leitud", "Sharing backend for %s not found" : "Jagamise tagarakendit %s jaoks ei leitud", - "Click the button below to open it." : "Vajuta allolevat nuppu, et see avada.", + "%1$s shared %2$s with you" : "%1$s jagas sinuga: %2$s", + "Open %s" : "Ava %s ", + "%1$s via %2$s" : "%1$s %2$s kaudu", + "%1$s shared %2$s with you and wants to add:" : "%1$s jagas sinuga %2$s ning soovib lisada:", + "%1$s shared %2$s with you and wants to add" : "%1$s jagas sinuga %2$s ning soovib lisada", + "%s added a note to a file shared with you" : "%s jagas koos sulle jagatud failiga ka märget", + "Passwords are enforced for link and mail shares" : "Linkide ja e-posti teel levitatava jaosmeedia puhul on salasõnade kasutamine nõutav", + "Share recipient is not a valid user" : "Jaosmeedia vastuvõtja pole korrektne kasutaja", + "Share recipient is not a valid group" : "Jaosmeedia vastuvõtja pole korrektne grupp", + "Share recipient should be empty" : "Jaosmeedia vastuvõtja peaks jääma tühjaks", + "Share recipient should not be empty" : "Jaosmeedia vastuvõtja ei tohi jääda tühjaks", + "Share recipient is not a valid circle" : "Jaosmeedia vastuvõtja pole korrektne tiim", "Unknown share type" : "Tundmatu jagamise tüüp", + "Share initiator must be set" : "Jagamise alustaja peab olema määratud", + "Cannot share with yourself" : "Sa ei saa iseendale jagada", + "Shared path must be set" : "Jagamise asukoht peab olema teada", + "Shared path must be either a file or a folder" : "Jagamise asukoht peab olema kas kaust või fail", + "You cannot share your root folder" : "Sa ei saa juurkausta jagada", "You are not allowed to share %s" : "Sul pole lubatud %s jagada", + "Valid permissions are required for sharing" : "Jagamiseks peavad olema korrektsed õigused", + "File shares cannot have create or delete permissions" : "Jaosfailidel ei saa olla loomis- või kustutamisõigusi", "Cannot increase permissions of %s" : "Ei saa %s õigusi suurendada", + "Shares need at least read permissions" : "Jaosmeedial peab olema vähemalt lugemisõigus", + "Files cannot be shared with delete permissions" : "Kustutusõigustega faile ei saa jagada", + "Files cannot be shared with create permissions" : "Loomisõigustega faile ei saa jagada", "Expiration date is in the past" : "Aegumise kuupäev on minevikus", + "Expiration date is enforced" : "Aegumiskuupäev on kasutusel", + "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Aegumist ei saa lisada kaugemale, kui %n päev tulevikus.","Aegumist ei saa lisada kaugemale, kui %n päeva tulevikus."], + "Sharing is only allowed with group members" : "Jagamine on lubatud vaid grupi liikmetega", + "Sharing %s failed, because this item is already shared with the account %s" : "%s jagamine ei õnnestunud, kuna seda objekti on juba jagatud kontoga %s", + "Group sharing is now allowed" : "Grupile jagamine on nüüd lubatud", + "Sharing is only allowed within your own groups" : "Jagamine on lubatud vaid sinu oma grupi liikmetega", + "Path is already shared with this group" : "Asukoht on selle grupiga juba jagatud", + "Link sharing is not allowed" : "Lingi jagamine pole lubatud", + "Public upload is not allowed" : "Avalik üleslaadimine pole lubatud", + "You cannot share a folder that contains other shares" : "Sa ei saa jagada jaoskausta, kus sisalduvad muud jaoskaustad", + "Sharing is disabled" : "Jagamine pole kasutusel", + "Sharing is disabled for you" : "Jagamine pole sinu jaoks kasutusel", + "Cannot share with the share owner" : "Sa ei saa jagada jaosmeedia omanikule", + "Share does not have a full ID" : "Jaosmeedial on täismahuline tunnus puudu", + "Cannot change share type" : "Sa ei saa muuta jaosmeedia tüüpi", + "Can only update recipient on user shares" : "Kasutaja jaosmeedia saajat ei õnnestu uuendada", + "Invalid share recipient" : "Vigane jaosmeedia vastuvõtja", + "Group \"%s\" does not exist" : "„%s“ gruppi pole olemas", "The requested share does not exist anymore" : "Soovitud jagamist enam ei eksisteeri", - "Could not find category \"%s\"" : "Ei leia kategooriat \"%s\"", + "The requested share comes from a disabled user" : "Soovitud jaosmeedia on loonud blokeeritud kasutaja", + "Could not find category \"%s\"" : "Ei leia kategooriat „%s“", + "Input text" : "Sisendtekst", + "The input text" : "Sisendtekst", "Sunday" : "Pühapäev", "Monday" : "Esmaspäev", "Tuesday" : "Teisipäev", @@ -119,41 +261,148 @@ OC.L10N.register( "Oct." : "Okt.", "Nov." : "Nov.", "Dec." : "Dets.", - "A valid password must be provided" : "Sisesta nõuetele vastav parool", + "A valid password must be provided" : "Sisesta nõuetele vastav salasõna", + "The Login is already being used" : "See kasutajanimi on juba kasutusel", + "Could not create account" : "Kasutajakonto loomine ei õnnestunud", + "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kasutajanimes on lubatud ainult järgmised tähemärgid: „a-z“, „A-Z“, „0-9“, ja „_.@-'“", + "A valid Login must be provided" : "Palun sisesta korrektne kasutajanimi", + "Login contains whitespace at the beginning or at the end" : "Kasutajanime alguses või lõpus on tühik", + "Login must not consist of dots only" : "Kasutajanimi ei tohi koosneda ainult punktidest", + "Username is too long" : "Kasutajanimi on liiga pikk", + "Login is invalid because files already exist for this user" : "See kasutajanimi ei sobi, kuna sellise kasutaja faile on juba olemas", + "Account disabled" : "Konto pole kasutusel", + "Login canceled by app" : "Rakendus katkestas sisselogimise", + "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "„%1$s“ rakendust ei saa paigaldada, sest järgnev sõltuvus on puudu: %2$s", "a safe home for all your data" : "turvaline koht sinu andmetele", "Application is not enabled" : "Rakendus pole sisse lülitatud", "Authentication error" : "Autentimise viga", - "Token expired. Please reload page." : "Kontrollkood aegus. Paelun lae leht uuesti.", + "Token expired. Please reload page." : "Kontrollkood aegus. Paelun laadi leht uuesti.", "No database drivers (sqlite, mysql, or postgresql) installed." : "Ühtegi andmebaasi (sqlite, mysql või postgresql) draiverit pole paigaldatud.", + "Cannot write into \"config\" directory." : "Pole õigust kirjutada „config“ kausta.", + "This can usually be fixed by giving the web server write access to the config directory. See %s" : "Tavaliselt saad selle lahendada andes veebiserverile õigused seadistuse kausta kirjutamiseks. Vaata siia: %s", + "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Aga kui soovid, et config.pho seadistuste fail ei peaks olema veebiserveri poolt muudetav, siis palun määra seadistusvõtme „config_is_read_only“ väärtuseks true. Lisateavet leiad: %s", + "Cannot write into \"apps\" directory." : "Pole õigust kirjutada „apps“ kausta.", + "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Tavaliselt saad selle lahendada andes veebiserverile õigused rakenduste kausta kirjutamiseks. Alternatiivina võid ka Nextcloudi rakendustepoe kasutamise keelata.", + "Cannot create \"data\" directory." : "„data“ kausta loomine ei õnnestunud.", + "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Tavaliselt saad selle lahendada andes veebiserverile õigused juurkausta kirjutamiseks. Vaata siia: %s", + "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Tavaliselt saad õiguste vea lahendada andes veebiserverile õigused juurkausta kirjutamiseks. Vaata siia: %s", + "Your data directory is not writable." : "Sinu serveri andmekaust pole kirjutatav.", + "Setting locale to %s failed." : "Ei õnnestunud määrata lokaadi väärtuseks „%s“.", + "Please install one of these locales on your system and restart your web server." : "Palun paigalda mõni neist lokaatidest oma serverisse ning taaskäivita veebiserver.", "PHP module %s not installed." : "PHP moodulit %s pole paigaldatud.", "Please ask your server administrator to install the module." : "Palu oma serveri haldajal moodul paigadalda.", - "PHP setting \"%s\" is not set to \"%s\"." : "PHP seade \"%s\" ei ole \"%s\".", + "PHP setting \"%s\" is not set to \"%s\"." : "PHP seadistuse „%s“ väärtuseks ei ole „%s“.", + "Adjusting this setting in php.ini will make Nextcloud run again" : "Selle seadistuse kohendamine php.ini failis võimaldab sul Nextcloudi uuesti tööle saada", + "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> muutuja väärtus on hetkel <code>%s</code>, pigem eeldaks väärtust <code>0</code>.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Vea parandamiseks muuda oma veebiserveri php.ini failis <code>mbstring.func_overload</code> väärtuseks <code>0</code>.", + "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP on seadistatud eemaldama „inline“ dokumendi blokke. See muudab mõned tuumikrakendused kasutamatuteks.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "See on tõenäoliselt põhjustatud puhver/kiirendist nagu Zend OPcache või eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "PHP moodulid on paigaldatud, kuid neid näitatakse endiselt kui puuduolevad?", "Please ask your server administrator to restart the web server." : "Palu oma serveri haldajal veebiserver taaskäivitada.", - "Your data directory is invalid." : "Sinu andmekataloog on vigane", - "Could not obtain lock type %d on \"%s\"." : "Ei suutnud hankida %d tüüpi lukustust \"%s\".", + "The required %s config variable is not configured in the config.php file." : "Nõutav seadistuste muutuja „%s“ puudub sonfig.php failist.", + "Please ask your server administrator to check the Nextcloud configuration." : "Palu oma serveri haldajal Nextcloudi seadistusi kontrollida.", + "Your data directory is readable by other people." : "Sinu andmete kaust on loetav teiste kasutajate poolt.", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Palun muuda kausta õigused 0770-ks, et kausta sisu poleks teistele kasutajatele nähtav.", + "Your data directory must be an absolute path." : "Andmekausta asukoht peab olema absoluutne aadress.", + "Check the value of \"datadirectory\" in your configuration." : "Palun kontrolli „datadirectory“ väärtust selle paigalduse seadistustes.", + "Your data directory is invalid." : "Sinu andmekaust on vigane.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Palun taga, et andmete juurkaustas leidub fail „%1$s“, mille sisuks on „%2$s“", + "Action \"%s\" not supported or implemented." : "„%s“ tegevus pole toetatud või implementeeritud.", + "Authentication failed, wrong token or provider ID given" : "Autentimine ei õnnestunud - kas tunnusluba või teenusepakkuja tunnus on vale", + "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Päringu lõpetamiseks on puudu järgmised parameetrid: „%s“", + "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "„%1$s“ tunnus on juba kasutusel liitpilve serveris „%2$s“", + "Cloud Federation Provider with ID: \"%s\" does not exist." : "Liitpilve teenusepakkujat tunnusega „%s“ pole olemas.", + "Could not obtain lock type %d on \"%s\"." : "Ei suutnud hankida %d tüüpi lukustust asukohas „%s“.", + "Storage unauthorized. %s" : "Andmeruum on autoriseerimata. %s", + "Storage incomplete configuration. %s" : "Andmeruumi poolik seadistus. %s", + "Storage connection error. %s" : "Viga andmeruumi ühenduse loomisel. %s", "Storage is temporarily not available" : "Salvestusruum pole ajutiselt kättesaadav", + "Storage connection timeout. %s" : "Aegumine andmeruumi ühenduse loomisel. %s", + "Transcribe audio" : "Kirjuta heli üles", + "Transcribe the things said in an audio" : "Kirjuta üles helifailis kuuldav jutt", + "Audio input" : "Helisisend", + "The audio to transcribe" : "Üleskirjutatav helifail", + "Transcription" : "Üleskirjutus", + "The transcribed text" : "Üleskirjutatud tekst", + "Chat with an agent" : "Vestle robotagendiga", + "Chat message" : "Vestluse sõnum", + "A chat message to send to the agent." : "Robotagendile saadetav sõnum.", + "Confirmation" : "Kinnitus", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Kas peaksime eelmised tegevuse kinnitama: keeldumist märgib 0 ja nõustumist 1.", + "Conversation token" : "Vestluse tunnusluba", + "A token representing the conversation." : "Tunnusluba vestluse tuvastamiseks.", + "Generated response" : "Loodud vastus", + "The response from the chat model." : "Vastus tehisarupõhise vestluse mudelilt.", + "The new conversation token" : "Vestluse uus tunnusluba", + "Send this along with the next interaction." : "Saada see kaasa järgmise päringuga.", + "Requested actions by the agent" : "Ülesanded tehisaru agendile", + "Actions that the agent would like to carry out in JSON format." : "Tehisaru agendile antavad ülesanded JSON-vormingus.", + "Context write" : "Kontekstuaalne kirjutamine", + "Writes text in a given style based on the provided source material." : "Kirjutab etteantud lähtematerjali lausel teksti üles.", + "Writing style" : "Kirjutamisstiil", + "Demonstrate a writing style that you would like to immitate" : "Näita sellist kirjutamisstiili, mida tahad jäljendada", + "Source material" : "Lähtematerjal", + "The content that would like to be rewritten in the new writing style" : "Sisu, mida tahaksid uues stiilis ümber kirjutada", + "Generated text" : "Koostatud tekst", + "The generated text with content from the source material in the given style" : "Antud stiilis lähtematerjali alusel koostatud tekst", + "Emoji generator" : "Emojide looja", + "Takes text and generates a representative emoji for it." : "Võtab aluseks teksti ja lood selle alusel emoji.", + "The text to generate an emoji for" : "Lähtetekst, millest lood emoji", + "Generated emoji" : "Loodud emoji", + "The generated emoji based on the input text" : "Sisestatud teksti alusel loodud emoji", + "Generate image" : "Pildiloome", + "Generate an image from a text prompt" : "Loo tekstisisendist pilt", + "Prompt" : "Sisendvorm", + "Describe the image you want to generate" : "Kirjelda loodavat pilti", + "Number of images" : "Piltide arv", + "How many images to generate" : "Mitu pilti peaksime tekitama", + "Output images" : "Väljundpildid", + "The generated images" : "Loodud pildid", + "Generate speech" : "Koosta kõne", + "Generate speech from a transcript" : "Koosta üleskirjutusest kõne", + "Write transcript that you want the assistant to generate speech from" : "Kirjuta üles see, mille alusel tahad Abilisel lasta koostada kõne", + "Output speech" : "Kõneväljund", + "The generated speech" : "Koostatud kõne", + "Change Tone" : "Teksti tooni muutmine", + "Change the tone of a piece of text." : "Muuda antud teksti tonaalsust.", + "Write a text that you want the assistant to rewrite in another tone." : "Kirjuta üles see, mille tonaalsust tahad Abilisel lasta ümber kirjutada.", + "Desired tone" : "Soovitud toon", + "In which tone should your text be rewritten?" : "Mis toonis peaks tekst olema ümberkirjutatud?", + "The rewritten text in the desired tone, written by the assistant:" : "Abilise poolt soovitud toonis ümberkirjutatud tekst:", + "Chat" : "Vestle", + "Chat with the assistant" : "Vestle Abilisega", + "System prompt" : "Süsteemi viip", + "Chat history" : "Vestluse ajalugu", + "The history of chat messages before the current message, starting with a message by the user" : "Kasutaja sõnumiga algav vestluse ajalugu enne praegust sõnumit", + "Response message" : "Sõnumi vastus", + "The generated response as part of the conversation" : "Loodud vastus vestluse osana", + "Formalize text" : "Muuda tekst ametlikuks", + "Takes a text and makes it sound more formal" : "Sisestatud teksti vormistamine ametlikuna", + "Generate a headline" : "Alapealkirja loomine", + "Generates a possible headline for a text." : "Võimaldab luua teksti põhjal kokkuvõtliku alapealkirja.", + "Original text" : "Lähtetekst", + "The original text to generate a headline for" : "Lähtetekst, millest lood kokkuvõtliku alapealkirja", + "The generated headline" : "Loodud alapealkiri", + "Proofread" : "Keelekorrektuur", + "Proofreads a text and lists corrections" : "Võimaldab teha tekstide ja loendite korrektuuri", + "Text" : "Tekst", + "The text to proofread" : "Keelekorrektuuri vajav tekst", + "Corrections" : "Korrektuuris tehtud parandused", + "The corrections that should be made in your text" : "Korrektuuris tehtud parandused, mis peaks sinu teksti lisanduma", "Summary" : "Kokkuvõte", "Translate" : "Tõlgi", - "File name is a reserved word" : "Failinimi sisaldab keelatud sõna", - "File name contains at least one invalid character" : "Faili nimesonvähemalt üks keelatud märk", - "File name is too long" : "Faili nimi on liiga pikk", - "Help" : "Abi", - "Users" : "Kasutajad", - "Unknown user" : "Tundmatu kasutaja", - "Oracle username and/or password not valid" : "Oracle kasutajatunnus ja/või parool pole õiged", - "PostgreSQL username and/or password not valid" : "PostgreSQL kasutajatunnus ja/või parool pole õiged", - "Set an admin username." : "Määra admin kasutajanimi.", - "Open »%s«" : "Ava »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "%s jagamine ebaõnnestus, kuna see üksus on juba jagatud kasutajaga %s", - "The username is already being used" : "Kasutajanimi on juba kasutuses", - "Could not create user" : "Ei saanud kasutajat luua", - "A valid username must be provided" : "Sisesta nõuetele vastav kasutajatunnus", - "Username contains whitespace at the beginning or at the end" : "Kasutajanime alguses või lõpus on tühik", - "Username must not consist of dots only" : "Kasutajanimi ei tohi koosneda ainult punktidest", - "User disabled" : "Kasutaja deaktiveeritud", + "Translate text from one language to another" : "Tõlgi teksti ühest keelest teise", + "Origin text" : "Lähtetekst", + "The text to translate" : "Tõlgitav tekst", + "Origin language" : "Lähtekeel", + "The language of the origin text" : "Lähteteksti keel", + "Target language" : "Tõlkekeel", + "The desired language to translate the origin text in" : "Keel, millesse lähteteksti tõlgime", + "Result" : "Tulemus", + "The translated text" : "Tõlgitud tekst", + "Organisation" : "Organisatsioon", "File is currently busy, please try again later" : "Fail on hetkel kasutuses, proovi hiljem uuesti", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Palun muuda kataloogi õigused 0770-ks, et kataloogi sisu poleks teistele kasutajatele nähtav" + "Cannot download file" : "Faili pole võimalik alla laadida", + "Login is too long" : "Kasutajanimi on liiga pikk" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/et_EE.json b/lib/l10n/et_EE.json index 15a201294ea..df487fc4582 100644 --- a/lib/l10n/et_EE.json +++ b/lib/l10n/et_EE.json @@ -1,77 +1,219 @@ { "translations": { - "Cannot write into \"config\" directory!" : "Ei saa kirjutada \"config\" kataloogi!", + "Cannot write into \"config\" directory!" : "Ei saa kirjutada „config“ kausta!!", + "This can usually be fixed by giving the web server write access to the config directory." : "Tavaliselt saad selle lahendada andes veebiserverile õigused seadistuse kausta kirjutamiseks", + "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Aga kui soovid, et seadistuste fail ei peaks olema veebiserveri poolt muudetav, siis palun määra seadistusvõtme „config_is_read_only“ väärtuseks true.", "See %s" : "Vaata %s", + "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Rakendust „%1$s“ pole serverisse paigaldatud või pole tema versioon ühilduv selle serveriga. Palun kontrolli paigaldatud rakendusi.", "Sample configuration detected" : "Tuvastati näidisseaded", - "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Tuvastati, et kopeeriti näidisseaded. See võib lõhkuda sinu saidi ja see pole toetatud. Palun loe enne faili config.php muutmist dokumentatsiooni", + "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Tuvastasin, et seadistuse faili kopeeritud näidisseaded. See võib lõhkuda sinu saidi ja see pole toetatud. Palun loe enne faili config.php muutmist dokumentatsiooni", + "The page could not be found on the server." : "Seda lehte ei õnnestunud serverist leida.", + "%s email verification" : "E-postiaadressi kinnitamine: %s", + "Email verification" : "E-postiaadressi kinnitamine", + "Click the following button to confirm your email." : "Oma e-postiaadressi kinnitamiseks klõpsi järgmisel nupul.", + "Click the following link to confirm your email." : "Oma e-postiaadressi kinnitamiseks klõpsi järgmisel lingil.", + "Confirm your email" : "Kiinita oma e-posti aadress", + "Other activities" : "Muud tegevused", "%1$s and %2$s" : "%1$s ja %2$s", "%1$s, %2$s and %3$s" : "%1$s, %2$s ja %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s ja %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s ja %5$s", + "Education bundle" : "Rakenduste komplekt haridusasutustele", + "Enterprise bundle" : "Rakenduste komplekt suurorganisatsioonidele", + "Groupware bundle" : "Rühmatarkvara rakenduste komplekt", + "Hub bundle" : "Rakenduste komplekt Nextcloud Hub", + "Public sector bundle" : "Rakenduste komplekt avaliku sektori asutustele", + "Social sharing bundle" : "Rakenduste komplekt sotsiaalmeedias jagamiseks", "PHP %s or higher is required." : "PHP %s või uuem on nõutav.", "PHP with a version lower than %s is required." : "Nõutud on PHP madalama versiooniga kui %s.", + "%sbit or higher PHP required." : "Vajalik on %s-bitine või parem PHP versioon.", + "The following architectures are supported: %s" : "Toetatud on järgnevad arhitektuurid: %s", + "The following databases are supported: %s" : "Toetatud on järgnevad andmebaasid: %s", "The command line tool %s could not be found" : "Käsurea töövahendit %s ei leitud", "The library %s is not available." : "Teek %s pole saadaval.", - "Server version %s or higher is required." : "Serveri versioon %s või kõrgem on nõutav.", + "Library %1$s with a version higher than %2$s is required - available version %3$s." : "Vajalik on „%1$s“ teek suurema versiooniga kui %2$s - hetkel on versioon %3$s.", + "Library %1$s with a version lower than %2$s is required - available version %3$s." : "Vajalik on „%1$s“ teek väiksema versiooniga kui %2$s - hetkel on versioon %3$s.", + "The following platforms are supported: %s" : "Toetatud on järgmised platvormid: %s", + "Server version %s or higher is required." : "Nõutav on serveri versioon %s või suurem.", "Server version %s or lower is required." : "Serveri versioon %s või madalam on nõutav.", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Sisselogitud kasutajakonto peab olema peakasutajate või selle alamgrupi liige või omama eraldi õiguse selle seadustuse muutmiseks", + "Your current IP address doesn't allow you to perform admin actions" : "Sinu praeguselt e-posti aadressilt ei saa teha haldustoiminguid", + "Logged in account must be an admin or sub admin" : "Sisselogitud kasutajakonto peab olema peakasutajate või selle alamgrupi liige", + "Logged in account must be an admin" : "Sisselogitud kasutajakonto peab olema peakasutajate grupi liige", + "Wiping of device %s has started" : "Andmete kustutamine seadmes „%s“ algas", + "Wiping of device »%s« has started" : "Andmete kustutamine seadmes „%s“ algas", + "»%s« started remote wipe" : "„%s“ alustas kaugseadme andmete kustutamist", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "„%s“ seade või rakendus on alustanud kaugkustutamise protsessi. Selle lõppemisel saad veel ühe teavitava e-kirja", + "Wiping of device %s has finished" : "Andmete kustutamine seadmes „%s“ lõppes", + "Wiping of device »%s« has finished" : "Andmete kustutamine seadmes „%s“ lõppes", + "»%s« finished remote wipe" : "„%s“ lõpetas kaugseadme andmete kustutamise", + "Device or application »%s« has finished the remote wipe process." : "„%s“ seade või rakendus on lõpetanud kaugkustutamise protsessi.", + "Remote wipe started" : "Kaugkustutamine on alanud", + "A remote wipe was started on device %s" : "„%s“ seadme kaugkustutamine on alanud", + "Remote wipe finished" : "Kaugkustutamine on lõppenud", + "The remote wipe on %s has finished" : "„%s“ seadme kaugkustutamine on lõppenud", "Authentication" : "Autentimine", "Unknown filetype" : "Tundmatu failitüüp", "Invalid image" : "Vigane pilt", "Avatar image is not square" : "Avatari pilt pole ruut", "Files" : "Failid", "View profile" : "Vaata profiili", + "same time" : "samas ajas", + "_%nh_::_%nh_" : ["%n t","%n t"], + "_%nm_::_%nm_" : ["%n min","%n min"], + "%s ahead" : "%s ees", + "%s behind" : "%s taga", + "Local time: %s" : "Kohalik aeg: %s", "today" : "täna", "tomorrow" : "homme", "yesterday" : "eile", + "_in %n day_::_in %n days_" : ["%n päeva pärast","%n päeva pärast"], "_%n day ago_::_%n days ago_" : ["%n päev tagasi","%n päeva tagasi"], "next month" : "järgmine kuu", "last month" : "viimasel kuul", + "_in %n month_::_in %n months_" : ["%n kuu pärast","%n kuu pärast"], + "_%n month ago_::_%n months ago_" : ["%n kuu eest","%n kuu eest"], "next year" : "järgmine aasta", "last year" : "viimasel aastal", + "_in %n year_::_in %n years_" : ["%n aasta pärast","%n aasta pärast"], "_%n year ago_::_%n years ago_" : ["%n aasta tagasi","%n aastat tagasi"], + "_in %n hour_::_in %n hours_" : ["%n tunni pärast","%n tunni pärast"], "_%n hour ago_::_%n hours ago_" : ["%n tund tagasi","%n tundi tagasi"], + "_in %n minute_::_in %n minutes_" : ["%n minuti pärast","%n minuti pärast"], + "_%n minute ago_::_%n minutes ago_" : ["%n minut tagasi","%n minutit tagasi"], "in a few seconds" : "mõne sekundi jooksul", "seconds ago" : "sekundit tagasi", "Empty file" : "Tühi fail", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Moodulit tunnusega „%s“ pole pole olemas. Palun taga see oma rakenduste seadistustest või võta ühendust peakasutajaga.", + "No file conversion providers available" : "Ühtegi teisendusteenuse pakkujat pole saadaval", + "File is too large to convert" : "Fail on teisendamiseks liiga suur", + "Destination does not match conversion extension" : "Sihtmeedia ei vasta teisendamislaiendile", + "Could not convert file" : "Faili teisendamine ei õnnestu", + "Destination does not exist" : "Sihtmeediat pole olemas", + "Destination is not creatable" : "Sihtmeedia pole loodav", "Dot files are not allowed" : "Punktiga failid pole lubatud", + "%1$s (renamed)" : "%1$s (nimi on muudetud)", + "renamed file" : "muudetud nimega fail", + "\"%1$s\" is a forbidden file or folder name." : "„%1$s“ on keelatud faili- või kaustanimi.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "„%1$s“ on keelatud faili- või kaustanime eesliide.", + "\"%1$s\" is not allowed inside a file or folder name." : "„%1$s“ pole faili- või kaustanimes lubatud.", + "\"%1$s\" is a forbidden file type." : "„%1$s“ on keelatud failitüüp.", + "Filenames must not end with \"%1$s\"." : "Failinimede lõpus ei tohi olla „%1$s“.", + "Invalid parent path" : "Vigane ülemkaust", "File already exists" : "Fail on juba olemas", - "Invalid path" : "Vigane kataloogirada", + "Invalid path" : "Vigane kausta asukoht", "Failed to create file from template" : "Ei saa luua mallist faili", "Templates" : "Mallid", - "Filename contains at least one invalid character" : "Faili nimes on vähemalt üks keelatud märk", + "Storage %s cannot be moved" : "„%s“ andmeruumi ei saa teisaldada", + "Moving a share (%s) into a shared folder is not allowed" : "Jaosmeedia (%s) teisaldamine jaoskausta pole lubatud", + "Moving a storage (%s) into a shared folder is not allowed" : "Andmeruumi (%s) teisaldamine jaoskausta pole lubatud", + "Moving a share (%s) into another share (%s) is not allowed" : "Jaosmeedia (%s) teisaldamine teise jaosmeediasse (%s) pole lubatud", + "Moving a share (%s) into another storage (%s) is not allowed" : "Jaosmeedia (%s) teisaldamine teise andmeruumi (%s) pole lubatud", + "Moving a storage (%s) into a share (%s) is not allowed" : "Andmeruumi (%s) teisaldamine jaosmeediasse (%s) pole lubatud", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Andmeruumi (%s) teisaldamine andmeruumi (%s) pole lubatud", + "Path contains invalid segments" : "Asukohas on vigaseid segmente", + "Filename is a reserved word" : "Failinimi on reserveeritud sõna", + "Filename contains at least one invalid character" : "Failinimes on vähemalt üks keelatud märk", + "Filename is too long" : "Failinimi on liiga pikk", "Empty filename is not allowed" : "Tühi failinimi pole lubatud", + "App \"%s\" cannot be installed because appinfo file cannot be read." : "Kuna „appinfo“ faili pole võimalik lugeda, siis „%s“ rakendust ei saa paigaldada.", + "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Kuna ta pole ühilduv selle serveri versiooniga, siis „%s“ rakendust ei saa paigaldada.", "__language_name__" : "Eesti", "This is an automatically sent email, please do not reply." : "See on automaatselt saadetud e-kiri, palun ära vasta.", + "Help & privacy" : "Abiteave ja privaatsus", + "Appearance and accessibility" : "Välimus ja hõlpsus", "Apps" : "Rakendused", "Personal settings" : "Isiklikud seaded", "Administration settings" : "Administreerimise seaded", "Settings" : "Seaded", "Log out" : "Logi välja", - "Email" : "Epost", + "Accounts" : "Kasutajakontod", + "Email" : "E-post", + "Mail %s" : "E-post %s", + "Fediverse" : "Födiversum", + "View %s on the fediverse" : "Vaata Födiversumis: %s", "Phone" : "Telefon", - "Twitter" : "Twitter", + "Call %s" : "Helista: %s", + "Twitter" : "X / Twitter", + "View %s on Twitter" : "Vaata X-is / Twitteris: %s", "Website" : "Veebileht", + "Visit %s" : "Külasta veebilehte: %s", "Address" : "Aadress", - "Profile picture" : "Profiili pilt", + "Profile picture" : "Profiilipilt", "About" : "Info", "Display name" : "Kuvatav nimi", - "Organisation" : "Organisatsioon", + "Headline" : "Alapealkiri", + "Organization" : "Organisatsioon", "Role" : "Roll", + "Pronouns" : "Asesõnad pöördumisel", + "Unknown account" : "Tundmatu kasutajakonto", "Additional settings" : "Lisaseaded", + "Enter the database Login and name for %s" : "Andmebaasi kasutajanimi ning nimi %si jaoks", + "Enter the database Login for %s" : "Sisesta andmebaasi %s kasutajatunnus", + "Enter the database name for %s" : "Sisesta andmebaasi %s nimi", + "You cannot use dots in the database name %s" : "Sa ei tohi kasutada „%s“ andmebaasi nimes punkte", + "MySQL Login and/or password not valid" : "MySQLi andmebaasi kasutajatunnus ja/või salasõna pole õiged", "You need to enter details of an existing account." : "Sa pead sisestama olemasoleva konto andmed.", "Oracle connection could not be established" : "Ei suuda luua ühendust Oracle baasiga", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X ei ole toetatud ja %s ei pruugi korralikult toimida sellel platvormil. Kasuta seda omal vastutusel!", + "Oracle Login and/or password not valid" : "Oracle andmebaasi kasutajatunnus ja/või salasõna pole õiged", + "PostgreSQL Login and/or password not valid" : "PostgreSQLi andmebaasi kasutajatunnus ja/või salasõna pole õiged", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X ei ole toetatud ja %s ei pruugi korralikult toimida sellel platvormil. Kasuta seda omal vastutusel!", "For the best results, please consider using a GNU/Linux server instead." : "Parema tulemuse saavitamiseks palun kaalu serveris GNU/Linux kasutamist.", - "Set an admin password." : "Määra admini parool.", + "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Palun eemalda oma serveri seadistustest php.ini failist „open_basedir“ seadistus või võta kasutusele 64-bitisel platvormil põhinev PHP versioon.", + "Set an admin Login." : "Lisa peakasutaja kasutajanimi.", + "Set an admin password." : "Lisa peakasutaja salasõna.", + "Cannot create or write into the data directory %s" : "Ei õnnestu luua „%s“ andmekausta või sealt lugeda", "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Jagamise tagarakend %s peab kasutusele võtma OCP\\Share_Backend liidese", "Sharing backend %s not found" : "Jagamise tagarakendit %s ei leitud", "Sharing backend for %s not found" : "Jagamise tagarakendit %s jaoks ei leitud", - "Click the button below to open it." : "Vajuta allolevat nuppu, et see avada.", + "%1$s shared %2$s with you" : "%1$s jagas sinuga: %2$s", + "Open %s" : "Ava %s ", + "%1$s via %2$s" : "%1$s %2$s kaudu", + "%1$s shared %2$s with you and wants to add:" : "%1$s jagas sinuga %2$s ning soovib lisada:", + "%1$s shared %2$s with you and wants to add" : "%1$s jagas sinuga %2$s ning soovib lisada", + "%s added a note to a file shared with you" : "%s jagas koos sulle jagatud failiga ka märget", + "Passwords are enforced for link and mail shares" : "Linkide ja e-posti teel levitatava jaosmeedia puhul on salasõnade kasutamine nõutav", + "Share recipient is not a valid user" : "Jaosmeedia vastuvõtja pole korrektne kasutaja", + "Share recipient is not a valid group" : "Jaosmeedia vastuvõtja pole korrektne grupp", + "Share recipient should be empty" : "Jaosmeedia vastuvõtja peaks jääma tühjaks", + "Share recipient should not be empty" : "Jaosmeedia vastuvõtja ei tohi jääda tühjaks", + "Share recipient is not a valid circle" : "Jaosmeedia vastuvõtja pole korrektne tiim", "Unknown share type" : "Tundmatu jagamise tüüp", + "Share initiator must be set" : "Jagamise alustaja peab olema määratud", + "Cannot share with yourself" : "Sa ei saa iseendale jagada", + "Shared path must be set" : "Jagamise asukoht peab olema teada", + "Shared path must be either a file or a folder" : "Jagamise asukoht peab olema kas kaust või fail", + "You cannot share your root folder" : "Sa ei saa juurkausta jagada", "You are not allowed to share %s" : "Sul pole lubatud %s jagada", + "Valid permissions are required for sharing" : "Jagamiseks peavad olema korrektsed õigused", + "File shares cannot have create or delete permissions" : "Jaosfailidel ei saa olla loomis- või kustutamisõigusi", "Cannot increase permissions of %s" : "Ei saa %s õigusi suurendada", + "Shares need at least read permissions" : "Jaosmeedial peab olema vähemalt lugemisõigus", + "Files cannot be shared with delete permissions" : "Kustutusõigustega faile ei saa jagada", + "Files cannot be shared with create permissions" : "Loomisõigustega faile ei saa jagada", "Expiration date is in the past" : "Aegumise kuupäev on minevikus", + "Expiration date is enforced" : "Aegumiskuupäev on kasutusel", + "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Aegumist ei saa lisada kaugemale, kui %n päev tulevikus.","Aegumist ei saa lisada kaugemale, kui %n päeva tulevikus."], + "Sharing is only allowed with group members" : "Jagamine on lubatud vaid grupi liikmetega", + "Sharing %s failed, because this item is already shared with the account %s" : "%s jagamine ei õnnestunud, kuna seda objekti on juba jagatud kontoga %s", + "Group sharing is now allowed" : "Grupile jagamine on nüüd lubatud", + "Sharing is only allowed within your own groups" : "Jagamine on lubatud vaid sinu oma grupi liikmetega", + "Path is already shared with this group" : "Asukoht on selle grupiga juba jagatud", + "Link sharing is not allowed" : "Lingi jagamine pole lubatud", + "Public upload is not allowed" : "Avalik üleslaadimine pole lubatud", + "You cannot share a folder that contains other shares" : "Sa ei saa jagada jaoskausta, kus sisalduvad muud jaoskaustad", + "Sharing is disabled" : "Jagamine pole kasutusel", + "Sharing is disabled for you" : "Jagamine pole sinu jaoks kasutusel", + "Cannot share with the share owner" : "Sa ei saa jagada jaosmeedia omanikule", + "Share does not have a full ID" : "Jaosmeedial on täismahuline tunnus puudu", + "Cannot change share type" : "Sa ei saa muuta jaosmeedia tüüpi", + "Can only update recipient on user shares" : "Kasutaja jaosmeedia saajat ei õnnestu uuendada", + "Invalid share recipient" : "Vigane jaosmeedia vastuvõtja", + "Group \"%s\" does not exist" : "„%s“ gruppi pole olemas", "The requested share does not exist anymore" : "Soovitud jagamist enam ei eksisteeri", - "Could not find category \"%s\"" : "Ei leia kategooriat \"%s\"", + "The requested share comes from a disabled user" : "Soovitud jaosmeedia on loonud blokeeritud kasutaja", + "Could not find category \"%s\"" : "Ei leia kategooriat „%s“", + "Input text" : "Sisendtekst", + "The input text" : "Sisendtekst", "Sunday" : "Pühapäev", "Monday" : "Esmaspäev", "Tuesday" : "Teisipäev", @@ -117,41 +259,148 @@ "Oct." : "Okt.", "Nov." : "Nov.", "Dec." : "Dets.", - "A valid password must be provided" : "Sisesta nõuetele vastav parool", + "A valid password must be provided" : "Sisesta nõuetele vastav salasõna", + "The Login is already being used" : "See kasutajanimi on juba kasutusel", + "Could not create account" : "Kasutajakonto loomine ei õnnestunud", + "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kasutajanimes on lubatud ainult järgmised tähemärgid: „a-z“, „A-Z“, „0-9“, ja „_.@-'“", + "A valid Login must be provided" : "Palun sisesta korrektne kasutajanimi", + "Login contains whitespace at the beginning or at the end" : "Kasutajanime alguses või lõpus on tühik", + "Login must not consist of dots only" : "Kasutajanimi ei tohi koosneda ainult punktidest", + "Username is too long" : "Kasutajanimi on liiga pikk", + "Login is invalid because files already exist for this user" : "See kasutajanimi ei sobi, kuna sellise kasutaja faile on juba olemas", + "Account disabled" : "Konto pole kasutusel", + "Login canceled by app" : "Rakendus katkestas sisselogimise", + "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "„%1$s“ rakendust ei saa paigaldada, sest järgnev sõltuvus on puudu: %2$s", "a safe home for all your data" : "turvaline koht sinu andmetele", "Application is not enabled" : "Rakendus pole sisse lülitatud", "Authentication error" : "Autentimise viga", - "Token expired. Please reload page." : "Kontrollkood aegus. Paelun lae leht uuesti.", + "Token expired. Please reload page." : "Kontrollkood aegus. Paelun laadi leht uuesti.", "No database drivers (sqlite, mysql, or postgresql) installed." : "Ühtegi andmebaasi (sqlite, mysql või postgresql) draiverit pole paigaldatud.", + "Cannot write into \"config\" directory." : "Pole õigust kirjutada „config“ kausta.", + "This can usually be fixed by giving the web server write access to the config directory. See %s" : "Tavaliselt saad selle lahendada andes veebiserverile õigused seadistuse kausta kirjutamiseks. Vaata siia: %s", + "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Aga kui soovid, et config.pho seadistuste fail ei peaks olema veebiserveri poolt muudetav, siis palun määra seadistusvõtme „config_is_read_only“ väärtuseks true. Lisateavet leiad: %s", + "Cannot write into \"apps\" directory." : "Pole õigust kirjutada „apps“ kausta.", + "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Tavaliselt saad selle lahendada andes veebiserverile õigused rakenduste kausta kirjutamiseks. Alternatiivina võid ka Nextcloudi rakendustepoe kasutamise keelata.", + "Cannot create \"data\" directory." : "„data“ kausta loomine ei õnnestunud.", + "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Tavaliselt saad selle lahendada andes veebiserverile õigused juurkausta kirjutamiseks. Vaata siia: %s", + "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Tavaliselt saad õiguste vea lahendada andes veebiserverile õigused juurkausta kirjutamiseks. Vaata siia: %s", + "Your data directory is not writable." : "Sinu serveri andmekaust pole kirjutatav.", + "Setting locale to %s failed." : "Ei õnnestunud määrata lokaadi väärtuseks „%s“.", + "Please install one of these locales on your system and restart your web server." : "Palun paigalda mõni neist lokaatidest oma serverisse ning taaskäivita veebiserver.", "PHP module %s not installed." : "PHP moodulit %s pole paigaldatud.", "Please ask your server administrator to install the module." : "Palu oma serveri haldajal moodul paigadalda.", - "PHP setting \"%s\" is not set to \"%s\"." : "PHP seade \"%s\" ei ole \"%s\".", + "PHP setting \"%s\" is not set to \"%s\"." : "PHP seadistuse „%s“ väärtuseks ei ole „%s“.", + "Adjusting this setting in php.ini will make Nextcloud run again" : "Selle seadistuse kohendamine php.ini failis võimaldab sul Nextcloudi uuesti tööle saada", + "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> muutuja väärtus on hetkel <code>%s</code>, pigem eeldaks väärtust <code>0</code>.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Vea parandamiseks muuda oma veebiserveri php.ini failis <code>mbstring.func_overload</code> väärtuseks <code>0</code>.", + "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP on seadistatud eemaldama „inline“ dokumendi blokke. See muudab mõned tuumikrakendused kasutamatuteks.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "See on tõenäoliselt põhjustatud puhver/kiirendist nagu Zend OPcache või eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "PHP moodulid on paigaldatud, kuid neid näitatakse endiselt kui puuduolevad?", "Please ask your server administrator to restart the web server." : "Palu oma serveri haldajal veebiserver taaskäivitada.", - "Your data directory is invalid." : "Sinu andmekataloog on vigane", - "Could not obtain lock type %d on \"%s\"." : "Ei suutnud hankida %d tüüpi lukustust \"%s\".", + "The required %s config variable is not configured in the config.php file." : "Nõutav seadistuste muutuja „%s“ puudub sonfig.php failist.", + "Please ask your server administrator to check the Nextcloud configuration." : "Palu oma serveri haldajal Nextcloudi seadistusi kontrollida.", + "Your data directory is readable by other people." : "Sinu andmete kaust on loetav teiste kasutajate poolt.", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Palun muuda kausta õigused 0770-ks, et kausta sisu poleks teistele kasutajatele nähtav.", + "Your data directory must be an absolute path." : "Andmekausta asukoht peab olema absoluutne aadress.", + "Check the value of \"datadirectory\" in your configuration." : "Palun kontrolli „datadirectory“ väärtust selle paigalduse seadistustes.", + "Your data directory is invalid." : "Sinu andmekaust on vigane.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Palun taga, et andmete juurkaustas leidub fail „%1$s“, mille sisuks on „%2$s“", + "Action \"%s\" not supported or implemented." : "„%s“ tegevus pole toetatud või implementeeritud.", + "Authentication failed, wrong token or provider ID given" : "Autentimine ei õnnestunud - kas tunnusluba või teenusepakkuja tunnus on vale", + "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Päringu lõpetamiseks on puudu järgmised parameetrid: „%s“", + "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "„%1$s“ tunnus on juba kasutusel liitpilve serveris „%2$s“", + "Cloud Federation Provider with ID: \"%s\" does not exist." : "Liitpilve teenusepakkujat tunnusega „%s“ pole olemas.", + "Could not obtain lock type %d on \"%s\"." : "Ei suutnud hankida %d tüüpi lukustust asukohas „%s“.", + "Storage unauthorized. %s" : "Andmeruum on autoriseerimata. %s", + "Storage incomplete configuration. %s" : "Andmeruumi poolik seadistus. %s", + "Storage connection error. %s" : "Viga andmeruumi ühenduse loomisel. %s", "Storage is temporarily not available" : "Salvestusruum pole ajutiselt kättesaadav", + "Storage connection timeout. %s" : "Aegumine andmeruumi ühenduse loomisel. %s", + "Transcribe audio" : "Kirjuta heli üles", + "Transcribe the things said in an audio" : "Kirjuta üles helifailis kuuldav jutt", + "Audio input" : "Helisisend", + "The audio to transcribe" : "Üleskirjutatav helifail", + "Transcription" : "Üleskirjutus", + "The transcribed text" : "Üleskirjutatud tekst", + "Chat with an agent" : "Vestle robotagendiga", + "Chat message" : "Vestluse sõnum", + "A chat message to send to the agent." : "Robotagendile saadetav sõnum.", + "Confirmation" : "Kinnitus", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Kas peaksime eelmised tegevuse kinnitama: keeldumist märgib 0 ja nõustumist 1.", + "Conversation token" : "Vestluse tunnusluba", + "A token representing the conversation." : "Tunnusluba vestluse tuvastamiseks.", + "Generated response" : "Loodud vastus", + "The response from the chat model." : "Vastus tehisarupõhise vestluse mudelilt.", + "The new conversation token" : "Vestluse uus tunnusluba", + "Send this along with the next interaction." : "Saada see kaasa järgmise päringuga.", + "Requested actions by the agent" : "Ülesanded tehisaru agendile", + "Actions that the agent would like to carry out in JSON format." : "Tehisaru agendile antavad ülesanded JSON-vormingus.", + "Context write" : "Kontekstuaalne kirjutamine", + "Writes text in a given style based on the provided source material." : "Kirjutab etteantud lähtematerjali lausel teksti üles.", + "Writing style" : "Kirjutamisstiil", + "Demonstrate a writing style that you would like to immitate" : "Näita sellist kirjutamisstiili, mida tahad jäljendada", + "Source material" : "Lähtematerjal", + "The content that would like to be rewritten in the new writing style" : "Sisu, mida tahaksid uues stiilis ümber kirjutada", + "Generated text" : "Koostatud tekst", + "The generated text with content from the source material in the given style" : "Antud stiilis lähtematerjali alusel koostatud tekst", + "Emoji generator" : "Emojide looja", + "Takes text and generates a representative emoji for it." : "Võtab aluseks teksti ja lood selle alusel emoji.", + "The text to generate an emoji for" : "Lähtetekst, millest lood emoji", + "Generated emoji" : "Loodud emoji", + "The generated emoji based on the input text" : "Sisestatud teksti alusel loodud emoji", + "Generate image" : "Pildiloome", + "Generate an image from a text prompt" : "Loo tekstisisendist pilt", + "Prompt" : "Sisendvorm", + "Describe the image you want to generate" : "Kirjelda loodavat pilti", + "Number of images" : "Piltide arv", + "How many images to generate" : "Mitu pilti peaksime tekitama", + "Output images" : "Väljundpildid", + "The generated images" : "Loodud pildid", + "Generate speech" : "Koosta kõne", + "Generate speech from a transcript" : "Koosta üleskirjutusest kõne", + "Write transcript that you want the assistant to generate speech from" : "Kirjuta üles see, mille alusel tahad Abilisel lasta koostada kõne", + "Output speech" : "Kõneväljund", + "The generated speech" : "Koostatud kõne", + "Change Tone" : "Teksti tooni muutmine", + "Change the tone of a piece of text." : "Muuda antud teksti tonaalsust.", + "Write a text that you want the assistant to rewrite in another tone." : "Kirjuta üles see, mille tonaalsust tahad Abilisel lasta ümber kirjutada.", + "Desired tone" : "Soovitud toon", + "In which tone should your text be rewritten?" : "Mis toonis peaks tekst olema ümberkirjutatud?", + "The rewritten text in the desired tone, written by the assistant:" : "Abilise poolt soovitud toonis ümberkirjutatud tekst:", + "Chat" : "Vestle", + "Chat with the assistant" : "Vestle Abilisega", + "System prompt" : "Süsteemi viip", + "Chat history" : "Vestluse ajalugu", + "The history of chat messages before the current message, starting with a message by the user" : "Kasutaja sõnumiga algav vestluse ajalugu enne praegust sõnumit", + "Response message" : "Sõnumi vastus", + "The generated response as part of the conversation" : "Loodud vastus vestluse osana", + "Formalize text" : "Muuda tekst ametlikuks", + "Takes a text and makes it sound more formal" : "Sisestatud teksti vormistamine ametlikuna", + "Generate a headline" : "Alapealkirja loomine", + "Generates a possible headline for a text." : "Võimaldab luua teksti põhjal kokkuvõtliku alapealkirja.", + "Original text" : "Lähtetekst", + "The original text to generate a headline for" : "Lähtetekst, millest lood kokkuvõtliku alapealkirja", + "The generated headline" : "Loodud alapealkiri", + "Proofread" : "Keelekorrektuur", + "Proofreads a text and lists corrections" : "Võimaldab teha tekstide ja loendite korrektuuri", + "Text" : "Tekst", + "The text to proofread" : "Keelekorrektuuri vajav tekst", + "Corrections" : "Korrektuuris tehtud parandused", + "The corrections that should be made in your text" : "Korrektuuris tehtud parandused, mis peaks sinu teksti lisanduma", "Summary" : "Kokkuvõte", "Translate" : "Tõlgi", - "File name is a reserved word" : "Failinimi sisaldab keelatud sõna", - "File name contains at least one invalid character" : "Faili nimesonvähemalt üks keelatud märk", - "File name is too long" : "Faili nimi on liiga pikk", - "Help" : "Abi", - "Users" : "Kasutajad", - "Unknown user" : "Tundmatu kasutaja", - "Oracle username and/or password not valid" : "Oracle kasutajatunnus ja/või parool pole õiged", - "PostgreSQL username and/or password not valid" : "PostgreSQL kasutajatunnus ja/või parool pole õiged", - "Set an admin username." : "Määra admin kasutajanimi.", - "Open »%s«" : "Ava »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "%s jagamine ebaõnnestus, kuna see üksus on juba jagatud kasutajaga %s", - "The username is already being used" : "Kasutajanimi on juba kasutuses", - "Could not create user" : "Ei saanud kasutajat luua", - "A valid username must be provided" : "Sisesta nõuetele vastav kasutajatunnus", - "Username contains whitespace at the beginning or at the end" : "Kasutajanime alguses või lõpus on tühik", - "Username must not consist of dots only" : "Kasutajanimi ei tohi koosneda ainult punktidest", - "User disabled" : "Kasutaja deaktiveeritud", + "Translate text from one language to another" : "Tõlgi teksti ühest keelest teise", + "Origin text" : "Lähtetekst", + "The text to translate" : "Tõlgitav tekst", + "Origin language" : "Lähtekeel", + "The language of the origin text" : "Lähteteksti keel", + "Target language" : "Tõlkekeel", + "The desired language to translate the origin text in" : "Keel, millesse lähteteksti tõlgime", + "Result" : "Tulemus", + "The translated text" : "Tõlgitud tekst", + "Organisation" : "Organisatsioon", "File is currently busy, please try again later" : "Fail on hetkel kasutuses, proovi hiljem uuesti", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Palun muuda kataloogi õigused 0770-ks, et kataloogi sisu poleks teistele kasutajatele nähtav" + "Cannot download file" : "Faili pole võimalik alla laadida", + "Login is too long" : "Kasutajanimi on liiga pikk" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/eu.js b/lib/l10n/eu.js index 33a4fe66db9..e84bd72d9a1 100644 --- a/lib/l10n/eu.js +++ b/lib/l10n/eu.js @@ -38,7 +38,6 @@ OC.L10N.register( "Server version %s or higher is required." : "Zerbitzariaren %s bertsioa edo berriagoa behar da.", "Server version %s or lower is required." : "Zerbitzariaren %s bertsioa edo zaharragoa behar da.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Saioa hasitako kontua administratzailea, azpi-administratzailea edo baimen berezi bat duena izan behar da ezarpen hau aldatzeko.", - "Your current IP address doesn’t allow you to perform admin actions" : "Zure uneko IP helbideak ez dizu administratzaile-ekintzak egiten uzten", "Logged in account must be an admin or sub admin" : "Saioa hasitako kontua administratzaile edo azpi-administratzailea izan behar du", "Logged in account must be an admin" : "Saioa hasitako kontua administratzailea izan behar du", "Wiping of device %s has started" : "%s gailuaren garbiketa hasi da", @@ -59,6 +58,7 @@ OC.L10N.register( "Avatar image is not square" : "Abatarreko irudia ez da karratua", "Files" : "Fitxategiak", "View profile" : "Ikusi profila", + "_%nh_::_%nh_" : ["%nh","%nh"], "Local time: %s" : "Ordu lokala: %s", "today" : "gaur", "tomorrow" : "bihar", @@ -92,6 +92,13 @@ OC.L10N.register( "Invalid path" : "Bide-izen baliogabea", "Failed to create file from template" : "Fitxategi berria txantiloitik sortzeak huts egin du", "Templates" : "Txantiloiak", + "Storage %s cannot be moved" : "%s biltegia ezin da mugitu", + "Moving a share (%s) into a shared folder is not allowed" : "Partekatze bat (%s) partekatutako karpeta batera mugitzea ez dago baimenduta", + "Moving a storage (%s) into a shared folder is not allowed" : "Biltegi bat (%s) partekatutako karpeta batera mugitzea ez dago baimenduta", + "Moving a share (%s) into another share (%s) is not allowed" : "Partekatze bat (%s) beste partekatze (%s) batera mugitzea ez dago baimenduta", + "Moving a share (%s) into another storage (%s) is not allowed" : "Biltegi bat (%s) beste biltegi (%s) batera mugitzea ez dago baimenduta", + "Moving a storage (%s) into a share (%s) is not allowed" : "Biltegi bat (%s) partekatze (%s) batera mugitzea ez dago baimenduta", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Biltegi bat (%s) beste biltegi (%s) batera mugitzea ez dago baimenduta", "Path contains invalid segments" : "Bideak segmentu baliogabeak ditu", "Filename is a reserved word" : "Fitxategi izena hitz erreserbatua da", "Filename contains at least one invalid character" : "Fitxategi-izenak karaktere baliogabe bat du gutxienez", @@ -124,7 +131,7 @@ OC.L10N.register( "About" : "Honi buruz", "Display name" : "Erakusteko izena", "Headline" : "Izenburua", - "Organisation" : "Erakundea", + "Organization" : "Antolakuntza", "Role" : "Zeregina", "Pronouns" : "Izenordainak", "Unknown account" : "Kontu ezezaguna", @@ -138,7 +145,6 @@ OC.L10N.register( "Oracle connection could not be established" : "Ezin da Oracle konexioa sortu", "Oracle Login and/or password not valid" : "Oracle saio edota pasahitza baliogabea", "PostgreSQL Login and/or password not valid" : "PostgreSQL saio edota pasahitza baliogabea", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X ez da onartzen eta %s gaizki ibiliko da plataforma honetan. Erabiltzekotan, zure ardurapean.", "For the best results, please consider using a GNU/Linux server instead." : "Emaitza hobeak izateko, mesedez kontsideratu GNU/Linux zerbitzari bat erabiltzea.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Badirudi %s instantzia hau 32 biteko PHP ingurune bat exekutatzen ari dela eta open_basedir aldagaia php.ini fitxategian konfiguratu dela. Honek arazoak sortuko ditu 4 GB baino gehiagoko fitxategiekin eta ez da batere gomendagarria.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Mesedez kendu open_basedir ezarpena zure php.ini-tik edo aldatu 64-biteko PHPra.", @@ -149,7 +155,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Ez da %s partekatze motorra aurkitu", "Sharing backend for %s not found" : "Ez da %s(e)rako partekatze motorrik aurkitu", "%1$s shared %2$s with you" : "%1$sk %2$s partekatu du zurekin", - "Click the button below to open it." : "Egin klik beheko botoian hura irekitzeko.", "Open %s" : "Ireki %s", "%1$s via %2$s" : "%2$s bidez, %1$s", "%1$s shared %2$s with you and wants to add:" : "%1$serabiltzaileak %2$s partekatu du zurekin eta hau gehitu nahi du:", @@ -183,7 +188,6 @@ OC.L10N.register( "Path is already shared with this group" : "Bide-izen hau dagoeneko partekatuta dago talde honekin", "Link sharing is not allowed" : "Esteken partekatzea ez da onartzen", "Public upload is not allowed" : "Igotze publikoa ez da onartzen", - "Path contains files shared with you" : "Bide-izenak zurekin partekatutako fitxategiak dauzka", "Sharing is disabled" : "Partekatzea desgaituta dago", "Sharing is disabled for you" : "Partekatzea zuretzat desgaituta dago", "Cannot share with the share owner" : "Ezin da partekatzearen jabearekin partekatu", @@ -311,10 +315,11 @@ OC.L10N.register( "The audio to transcribe" : "Transkribatzeko audioa", "Transcription" : "Transkripzioa", "The transcribed text" : "Transkribatutako testua", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "Txateatu agente batekin", "Chat message" : "Txat mezua", + "A chat message to send to the agent." : "Agenteari bidaltzeko txat mezu bat.", "Confirmation" : "Berrespena", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Aurretik eskatutako ekintzak berretsi behar diren ala ez: 0 ukatzeko eta 1 berresteko.", "Conversation token" : "Elkarrizketa tokena", "A token representing the conversation." : "Elkarrizketa adierazten duen token bat.", "Generated response" : "Sortutako erantzuna", @@ -322,6 +327,7 @@ OC.L10N.register( "The new conversation token" : "Elkarrizketa token berria", "Send this along with the next interaction." : "Bidali hau hurrengo interakzioarekin.", "Requested actions by the agent" : "Agenteak eskatutako ekintzak", + "Actions that the agent would like to carry out in JSON format." : "Agenteak egin nahi dituen ekintzak JSON formatuan.", "Context write" : "Testuingurua idaztea", "Writes text in a given style based on the provided source material." : "Testua estilo jakin batean idazten du, emandako iturri-materialean oinarrituta.", "Writing style" : "Idazteko estiloa", @@ -349,6 +355,11 @@ OC.L10N.register( "Generated reply" : "Sortutako erantzuna", "The generated text from the assistant" : "Laguntzaileak sortutako testua", "Change Tone" : "Aldatu tonoa", + "Change the tone of a piece of text." : "Aldatu testu-zati baten tonua.", + "Write a text that you want the assistant to rewrite in another tone." : "Idatzi laguntzaileak beste tonu batean berridaztea nahi duzun testua.", + "Desired tone" : "Nahi den tonua", + "In which tone should your text be rewritten?" : "Ze tonuan berridatzi beharko litzateke zure testua?", + "The rewritten text in the desired tone, written by the assistant:" : "Berridatzitako testua nahi den tonuan, laguntzaileak idatzita:", "Chat" : "Chat", "Chat with the assistant" : "Hitz egin txat bidez laguntzailarekin", "System prompt" : "Sistemaren gonbita", @@ -358,11 +369,14 @@ OC.L10N.register( "Response message" : "Erantzun mezua", "The generated response as part of the conversation" : "Sorturiko erantzuna, elkarrizketaren zati gisa", "Chat with tools" : "Txateatu erremintekin", + "Chat with the language model with tool calling support." : "Txateatu hizkuntza-modeloarekin dei-tresna euskarriarekin.", "Tool message" : "Erreminta-mezua", + "The result of tool calls in the last interaction" : "Tresna-deien emaitza azken interakzioan", "Available tools" : "Erreminta erabilgarriak", "The available tools in JSON format" : "Erabilgarri dauden erremintak JSON formatuan", "The response from the chat model" : "Txat modeloaren erantzuna", "Tool calls" : "Erreminta deiak", + "Tools call instructions from the model in JSON format" : "Tresna-deien argibideak modelotik JSON formatuan", "Formalize text" : "Formaldu testua", "Takes a text and makes it sound more formal" : "Testu bat hartzen du eta doinu formalagoa ematen dio.", "Write a text that you want the assistant to formalize" : "Idatz ezazu laguntzaileak formaltzea nahi duzun testu bat", @@ -373,6 +387,12 @@ OC.L10N.register( "Original text" : "Jatorrizko testua", "The original text to generate a headline for" : "Izenburu bat sortzeko jatorrizko testua", "The generated headline" : "Sortutako izenburua", + "Proofread" : "Testu-azterketa", + "Proofreads a text and lists corrections" : "Testu bat aztertzen du eta zuzenketak zerrendatzen ditu", + "Text" : "Testua", + "The text to proofread" : "Aztertzeko testua", + "Corrections" : "Zuzenketak", + "The corrections that should be made in your text" : "Zure testuan egin behar diren zuzenketak", "Reformulate text" : "Birformulatu testua", "Takes a text and reformulates it" : "Testu bat hartu eta birformulatu egiten du", "Write a text that you want the assistant to reformulate" : "Idatz ezazu laguntzaileak birformulatzea nahi duzun testu bat", @@ -408,41 +428,8 @@ OC.L10N.register( "Generate headline" : "Sortu izenburua", "Summarizes text by reducing its length without losing key information." : "Testua laburtzen du bere luzera murrizten informazio baliotsua galdu gabe.", "Extracts topics from a text and outputs them separated by commas." : "Gaiak ateratzen ditu testu batetik eta komaz banatuta erakusten ditu.", - "Education Edition" : "Hezkuntza edizioa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Saioa hasitako erabiltzailea administratzailea, azpi-administratzailea edo baimen berezi bat duena izan behar da ezarpen hau aldatzeko.", - "Logged in user must be an admin or sub admin" : "Saioa hasitako erabiltzailea administratzaile edo azpi-administratzailea izan behar du", - "Logged in user must be an admin" : "Saioa hasitako erabiltzailea administratzailea izan behar da", - "File name is a reserved word" : "Fitxategi izena hitz erreserbatua da", - "File name contains at least one invalid character" : "Fitxategi izenak karaktere baliogabe bat du gutxienez ", - "File name is too long" : "Fitxategi-izena luzeegia da", - "Help" : "Laguntza", - "Users" : "Erabiltzaileak", - "Unknown user" : "Erabiltzaile ezezaguna", - "Enter the database username and name for %s" : "%s sartu datu-basearen izena eta erabiltzaile-izena", - "Enter the database username for %s" : "Sartu %s(r)en datu-base erabiltzaile-izena", - "MySQL username and/or password not valid" : "MySQL erabiltzaile-izen edota pasahitza baliogabea", - "Oracle username and/or password not valid" : "Oracle erabiltzaile edo/eta pasahitza ez dira baliozkoak.", - "PostgreSQL username and/or password not valid" : "PostgreSQL erabiltzailea edo/eta pasahitza ez dira baliozkoak.", - "Set an admin username." : "Ezarri administraziorako erabiltzaile izena.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$serabiltzaileak »%2$s« partekatu du zurekin eta hau gehitu nahi du:", - "%1$s shared »%2$s« with you and wants to add" : "%1$serabiltzaileak »%2$s« partekatu du zurekin eta hau gehitu nahi du", - "»%s« added a note to a file shared with you" : "»%s« erabiltzaileak ohar bat gehitu du partekatu dizun fitxategi batean", - "Open »%s«" : "Ireki »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "%s partekatzeak huts egin du dagoeneko %serabiltzailearekin partekatuta dagoelako", - "%1$s shared »%2$s« with you" : "%1$serabiltzaileak »%2$s« partekatu du zurekin", - "%1$s shared »%2$s« with you." : "%1$serabiltzaileak »%2$s« partekatu du zurekin.", - "The username is already being used" : "Erabiltzaile izena dagoeneko erabilita dago", - "Could not create user" : "Ezin izan da erabiltzailea sortu", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Honako karaktereak bakarrik onartzen dira erabiltzaile izenetan: \"a-z\", \"A-Z\", \"0-9\", zuriuneak eta \"_.@-'\"", - "A valid username must be provided" : "Baliozko erabiltzaile izena eman behar da", - "Username contains whitespace at the beginning or at the end" : "Erabiltzaile-izenak zuriuneren bat du hasieran edo amaieran", - "Username must not consist of dots only" : "Erabiltzaile-izena ezin da puntuz osatuta soilik egon", - "Username is invalid because files already exist for this user" : "Erabiltzaile-izena ez da baliozkoa erabiltzaile honentzako fitxategiak dagoeneko existitzen direlako", - "User disabled" : "Erabiltzaile desgaituta", + "Organisation" : "Erakundea", "File is currently busy, please try again later" : "Fitxategia lanpetuta dago, saiatu berriro geroago", - "Cannot download file" : "Ezin da fitxategia deskargatu", - "Your data directory is readable by other users." : "Zure datuen karpeta beste erabiltzaileek irakur dezakete.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Aldatu baimenak 0770ra beste erabiltzaileek karpetan sartu ezin izateko.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Ziurtatu datu direktorioaren erroan \".ocdata\" izeneko fitxategia dagoela." + "Cannot download file" : "Ezin da fitxategia deskargatu" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/eu.json b/lib/l10n/eu.json index 46189514185..a444e6dfb07 100644 --- a/lib/l10n/eu.json +++ b/lib/l10n/eu.json @@ -36,7 +36,6 @@ "Server version %s or higher is required." : "Zerbitzariaren %s bertsioa edo berriagoa behar da.", "Server version %s or lower is required." : "Zerbitzariaren %s bertsioa edo zaharragoa behar da.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Saioa hasitako kontua administratzailea, azpi-administratzailea edo baimen berezi bat duena izan behar da ezarpen hau aldatzeko.", - "Your current IP address doesn’t allow you to perform admin actions" : "Zure uneko IP helbideak ez dizu administratzaile-ekintzak egiten uzten", "Logged in account must be an admin or sub admin" : "Saioa hasitako kontua administratzaile edo azpi-administratzailea izan behar du", "Logged in account must be an admin" : "Saioa hasitako kontua administratzailea izan behar du", "Wiping of device %s has started" : "%s gailuaren garbiketa hasi da", @@ -57,6 +56,7 @@ "Avatar image is not square" : "Abatarreko irudia ez da karratua", "Files" : "Fitxategiak", "View profile" : "Ikusi profila", + "_%nh_::_%nh_" : ["%nh","%nh"], "Local time: %s" : "Ordu lokala: %s", "today" : "gaur", "tomorrow" : "bihar", @@ -90,6 +90,13 @@ "Invalid path" : "Bide-izen baliogabea", "Failed to create file from template" : "Fitxategi berria txantiloitik sortzeak huts egin du", "Templates" : "Txantiloiak", + "Storage %s cannot be moved" : "%s biltegia ezin da mugitu", + "Moving a share (%s) into a shared folder is not allowed" : "Partekatze bat (%s) partekatutako karpeta batera mugitzea ez dago baimenduta", + "Moving a storage (%s) into a shared folder is not allowed" : "Biltegi bat (%s) partekatutako karpeta batera mugitzea ez dago baimenduta", + "Moving a share (%s) into another share (%s) is not allowed" : "Partekatze bat (%s) beste partekatze (%s) batera mugitzea ez dago baimenduta", + "Moving a share (%s) into another storage (%s) is not allowed" : "Biltegi bat (%s) beste biltegi (%s) batera mugitzea ez dago baimenduta", + "Moving a storage (%s) into a share (%s) is not allowed" : "Biltegi bat (%s) partekatze (%s) batera mugitzea ez dago baimenduta", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Biltegi bat (%s) beste biltegi (%s) batera mugitzea ez dago baimenduta", "Path contains invalid segments" : "Bideak segmentu baliogabeak ditu", "Filename is a reserved word" : "Fitxategi izena hitz erreserbatua da", "Filename contains at least one invalid character" : "Fitxategi-izenak karaktere baliogabe bat du gutxienez", @@ -122,7 +129,7 @@ "About" : "Honi buruz", "Display name" : "Erakusteko izena", "Headline" : "Izenburua", - "Organisation" : "Erakundea", + "Organization" : "Antolakuntza", "Role" : "Zeregina", "Pronouns" : "Izenordainak", "Unknown account" : "Kontu ezezaguna", @@ -136,7 +143,6 @@ "Oracle connection could not be established" : "Ezin da Oracle konexioa sortu", "Oracle Login and/or password not valid" : "Oracle saio edota pasahitza baliogabea", "PostgreSQL Login and/or password not valid" : "PostgreSQL saio edota pasahitza baliogabea", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X ez da onartzen eta %s gaizki ibiliko da plataforma honetan. Erabiltzekotan, zure ardurapean.", "For the best results, please consider using a GNU/Linux server instead." : "Emaitza hobeak izateko, mesedez kontsideratu GNU/Linux zerbitzari bat erabiltzea.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Badirudi %s instantzia hau 32 biteko PHP ingurune bat exekutatzen ari dela eta open_basedir aldagaia php.ini fitxategian konfiguratu dela. Honek arazoak sortuko ditu 4 GB baino gehiagoko fitxategiekin eta ez da batere gomendagarria.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Mesedez kendu open_basedir ezarpena zure php.ini-tik edo aldatu 64-biteko PHPra.", @@ -147,7 +153,6 @@ "Sharing backend %s not found" : "Ez da %s partekatze motorra aurkitu", "Sharing backend for %s not found" : "Ez da %s(e)rako partekatze motorrik aurkitu", "%1$s shared %2$s with you" : "%1$sk %2$s partekatu du zurekin", - "Click the button below to open it." : "Egin klik beheko botoian hura irekitzeko.", "Open %s" : "Ireki %s", "%1$s via %2$s" : "%2$s bidez, %1$s", "%1$s shared %2$s with you and wants to add:" : "%1$serabiltzaileak %2$s partekatu du zurekin eta hau gehitu nahi du:", @@ -181,7 +186,6 @@ "Path is already shared with this group" : "Bide-izen hau dagoeneko partekatuta dago talde honekin", "Link sharing is not allowed" : "Esteken partekatzea ez da onartzen", "Public upload is not allowed" : "Igotze publikoa ez da onartzen", - "Path contains files shared with you" : "Bide-izenak zurekin partekatutako fitxategiak dauzka", "Sharing is disabled" : "Partekatzea desgaituta dago", "Sharing is disabled for you" : "Partekatzea zuretzat desgaituta dago", "Cannot share with the share owner" : "Ezin da partekatzearen jabearekin partekatu", @@ -309,10 +313,11 @@ "The audio to transcribe" : "Transkribatzeko audioa", "Transcription" : "Transkripzioa", "The transcribed text" : "Transkribatutako testua", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "Txateatu agente batekin", "Chat message" : "Txat mezua", + "A chat message to send to the agent." : "Agenteari bidaltzeko txat mezu bat.", "Confirmation" : "Berrespena", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Aurretik eskatutako ekintzak berretsi behar diren ala ez: 0 ukatzeko eta 1 berresteko.", "Conversation token" : "Elkarrizketa tokena", "A token representing the conversation." : "Elkarrizketa adierazten duen token bat.", "Generated response" : "Sortutako erantzuna", @@ -320,6 +325,7 @@ "The new conversation token" : "Elkarrizketa token berria", "Send this along with the next interaction." : "Bidali hau hurrengo interakzioarekin.", "Requested actions by the agent" : "Agenteak eskatutako ekintzak", + "Actions that the agent would like to carry out in JSON format." : "Agenteak egin nahi dituen ekintzak JSON formatuan.", "Context write" : "Testuingurua idaztea", "Writes text in a given style based on the provided source material." : "Testua estilo jakin batean idazten du, emandako iturri-materialean oinarrituta.", "Writing style" : "Idazteko estiloa", @@ -347,6 +353,11 @@ "Generated reply" : "Sortutako erantzuna", "The generated text from the assistant" : "Laguntzaileak sortutako testua", "Change Tone" : "Aldatu tonoa", + "Change the tone of a piece of text." : "Aldatu testu-zati baten tonua.", + "Write a text that you want the assistant to rewrite in another tone." : "Idatzi laguntzaileak beste tonu batean berridaztea nahi duzun testua.", + "Desired tone" : "Nahi den tonua", + "In which tone should your text be rewritten?" : "Ze tonuan berridatzi beharko litzateke zure testua?", + "The rewritten text in the desired tone, written by the assistant:" : "Berridatzitako testua nahi den tonuan, laguntzaileak idatzita:", "Chat" : "Chat", "Chat with the assistant" : "Hitz egin txat bidez laguntzailarekin", "System prompt" : "Sistemaren gonbita", @@ -356,11 +367,14 @@ "Response message" : "Erantzun mezua", "The generated response as part of the conversation" : "Sorturiko erantzuna, elkarrizketaren zati gisa", "Chat with tools" : "Txateatu erremintekin", + "Chat with the language model with tool calling support." : "Txateatu hizkuntza-modeloarekin dei-tresna euskarriarekin.", "Tool message" : "Erreminta-mezua", + "The result of tool calls in the last interaction" : "Tresna-deien emaitza azken interakzioan", "Available tools" : "Erreminta erabilgarriak", "The available tools in JSON format" : "Erabilgarri dauden erremintak JSON formatuan", "The response from the chat model" : "Txat modeloaren erantzuna", "Tool calls" : "Erreminta deiak", + "Tools call instructions from the model in JSON format" : "Tresna-deien argibideak modelotik JSON formatuan", "Formalize text" : "Formaldu testua", "Takes a text and makes it sound more formal" : "Testu bat hartzen du eta doinu formalagoa ematen dio.", "Write a text that you want the assistant to formalize" : "Idatz ezazu laguntzaileak formaltzea nahi duzun testu bat", @@ -371,6 +385,12 @@ "Original text" : "Jatorrizko testua", "The original text to generate a headline for" : "Izenburu bat sortzeko jatorrizko testua", "The generated headline" : "Sortutako izenburua", + "Proofread" : "Testu-azterketa", + "Proofreads a text and lists corrections" : "Testu bat aztertzen du eta zuzenketak zerrendatzen ditu", + "Text" : "Testua", + "The text to proofread" : "Aztertzeko testua", + "Corrections" : "Zuzenketak", + "The corrections that should be made in your text" : "Zure testuan egin behar diren zuzenketak", "Reformulate text" : "Birformulatu testua", "Takes a text and reformulates it" : "Testu bat hartu eta birformulatu egiten du", "Write a text that you want the assistant to reformulate" : "Idatz ezazu laguntzaileak birformulatzea nahi duzun testu bat", @@ -406,41 +426,8 @@ "Generate headline" : "Sortu izenburua", "Summarizes text by reducing its length without losing key information." : "Testua laburtzen du bere luzera murrizten informazio baliotsua galdu gabe.", "Extracts topics from a text and outputs them separated by commas." : "Gaiak ateratzen ditu testu batetik eta komaz banatuta erakusten ditu.", - "Education Edition" : "Hezkuntza edizioa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Saioa hasitako erabiltzailea administratzailea, azpi-administratzailea edo baimen berezi bat duena izan behar da ezarpen hau aldatzeko.", - "Logged in user must be an admin or sub admin" : "Saioa hasitako erabiltzailea administratzaile edo azpi-administratzailea izan behar du", - "Logged in user must be an admin" : "Saioa hasitako erabiltzailea administratzailea izan behar da", - "File name is a reserved word" : "Fitxategi izena hitz erreserbatua da", - "File name contains at least one invalid character" : "Fitxategi izenak karaktere baliogabe bat du gutxienez ", - "File name is too long" : "Fitxategi-izena luzeegia da", - "Help" : "Laguntza", - "Users" : "Erabiltzaileak", - "Unknown user" : "Erabiltzaile ezezaguna", - "Enter the database username and name for %s" : "%s sartu datu-basearen izena eta erabiltzaile-izena", - "Enter the database username for %s" : "Sartu %s(r)en datu-base erabiltzaile-izena", - "MySQL username and/or password not valid" : "MySQL erabiltzaile-izen edota pasahitza baliogabea", - "Oracle username and/or password not valid" : "Oracle erabiltzaile edo/eta pasahitza ez dira baliozkoak.", - "PostgreSQL username and/or password not valid" : "PostgreSQL erabiltzailea edo/eta pasahitza ez dira baliozkoak.", - "Set an admin username." : "Ezarri administraziorako erabiltzaile izena.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$serabiltzaileak »%2$s« partekatu du zurekin eta hau gehitu nahi du:", - "%1$s shared »%2$s« with you and wants to add" : "%1$serabiltzaileak »%2$s« partekatu du zurekin eta hau gehitu nahi du", - "»%s« added a note to a file shared with you" : "»%s« erabiltzaileak ohar bat gehitu du partekatu dizun fitxategi batean", - "Open »%s«" : "Ireki »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "%s partekatzeak huts egin du dagoeneko %serabiltzailearekin partekatuta dagoelako", - "%1$s shared »%2$s« with you" : "%1$serabiltzaileak »%2$s« partekatu du zurekin", - "%1$s shared »%2$s« with you." : "%1$serabiltzaileak »%2$s« partekatu du zurekin.", - "The username is already being used" : "Erabiltzaile izena dagoeneko erabilita dago", - "Could not create user" : "Ezin izan da erabiltzailea sortu", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Honako karaktereak bakarrik onartzen dira erabiltzaile izenetan: \"a-z\", \"A-Z\", \"0-9\", zuriuneak eta \"_.@-'\"", - "A valid username must be provided" : "Baliozko erabiltzaile izena eman behar da", - "Username contains whitespace at the beginning or at the end" : "Erabiltzaile-izenak zuriuneren bat du hasieran edo amaieran", - "Username must not consist of dots only" : "Erabiltzaile-izena ezin da puntuz osatuta soilik egon", - "Username is invalid because files already exist for this user" : "Erabiltzaile-izena ez da baliozkoa erabiltzaile honentzako fitxategiak dagoeneko existitzen direlako", - "User disabled" : "Erabiltzaile desgaituta", + "Organisation" : "Erakundea", "File is currently busy, please try again later" : "Fitxategia lanpetuta dago, saiatu berriro geroago", - "Cannot download file" : "Ezin da fitxategia deskargatu", - "Your data directory is readable by other users." : "Zure datuen karpeta beste erabiltzaileek irakur dezakete.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Aldatu baimenak 0770ra beste erabiltzaileek karpetan sartu ezin izateko.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Ziurtatu datu direktorioaren erroan \".ocdata\" izeneko fitxategia dagoela." + "Cannot download file" : "Ezin da fitxategia deskargatu" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/fa.js b/lib/l10n/fa.js index 7ff71a3152b..12ed6178bcf 100644 --- a/lib/l10n/fa.js +++ b/lib/l10n/fa.js @@ -2,26 +2,28 @@ OC.L10N.register( "lib", { "Cannot write into \"config\" directory!" : "نمیتوانید داخل دایرکتوری \"config\" تغییراتی ایجاد کنید", - "This can usually be fixed by giving the web server write access to the config directory." : "This can usually be fixed by giving the web server write access to the config directory.", - "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it.", + "This can usually be fixed by giving the web server write access to the config directory." : "این مشکل معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری پیکربندی قابل رفع است.", + "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "اما، اگر ترجیح میدهید فایل config.php فقط خواندنی باشد، گزینه \"config_is_read_only\" را در آن به true تنظیم کنید.", "See %s" : "مشاهده %s", - "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory.", + "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "برنامه %1$s موجود نیست یا نسخهای ناسازگار با این سرور دارد. لطفاً دایرکتوری برنامهها را بررسی کنید.", "Sample configuration detected" : "فایل پیکربندی نمونه پیدا شد", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "تشخیص داده شده است که پیکربندی نمونه کپی شده است. این می تواند نصب شما را خراب کند و پشتیبانی نمی شود. لطفاً قبل از انجام تغییرات در config.php ، اسناد را بخوانید", - "The page could not be found on the server." : "The page could not be found on the server.", - "%s email verification" : "%s email verification", - "Email verification" : "Email verification", - "Click the following button to confirm your email." : "Click the following button to confirm your email.", - "Click the following link to confirm your email." : "Click the following link to confirm your email.", - "Confirm your email" : "Confirm your email", + "The page could not be found on the server." : "صفحه در سرور یافت نشد.", + "%s email verification" : "تأیید ایمیل %s", + "Email verification" : "تأیید ایمیل", + "Click the following button to confirm your email." : "برای تأیید ایمیل خود روی دکمه زیر کلیک کنید.", + "Click the following link to confirm your email." : "برای تأیید ایمیل خود روی لینک زیر کلیک کنید.", + "Confirm your email" : "ایمیل خود را تأیید کنید", "Other activities" : "سایر فعالیت ها", - "%1$s and %2$s" : "%1$sو%2$s", - "%1$s, %2$s and %3$s" : "%1$s،%2$sو%3$s", - "%1$s, %2$s, %3$s and %4$s" : "%1$s،%2$s،%3$sو%4$s", - "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s،%2$s،%3$s،%4$sو%5$s", + "%1$s and %2$s" : "%1$s و %2$s", + "%1$s, %2$s and %3$s" : "%1$s، %2$s و %3$s", + "%1$s, %2$s, %3$s and %4$s" : "%1$s، %2$s، %3$s و %4$s", + "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s، %2$s، %3$s، %4$s و %5$s", + "Education bundle" : "بسته آموزشی", "Enterprise bundle" : "بستهٔ سازمانی", "Groupware bundle" : "بستهٔ کار گروهی", "Hub bundle" : "بستهٔ هستهای", + "Public sector bundle" : "بسته بخش عمومی", "Social sharing bundle" : "بستهٔ همرسانی اجتماعی", "PHP %s or higher is required." : "PHP نسخهی %s یا بالاتر نیاز است.", "PHP with a version lower than %s is required." : "نیاز به نگارش پایینتر از %s پیاچپی.", @@ -35,25 +37,34 @@ OC.L10N.register( "The following platforms are supported: %s" : "بنسازههای زیر پشتیبانی میشوند: %s", "Server version %s or higher is required." : "نیاز به کارساز با نگارش %s یا بالاتر.", "Server version %s or lower is required." : "نیاز به کارساز با نگارش %s یا پایینتر.", - "Wiping of device %s has started" : "پاک کردن دستگاه%s شروع شده است", - "Wiping of device »%s« has started" : "پاک کردن دستگاه%s شروع شده است", - "»%s« started remote wipe" : "%sپاک کردن از راه دور", - "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "دستگاه یا برنامه%s فرآیند پاک کردن از راه دور را آغاز کرده است. پس از اتمام مراحل ، ایمیل دیگری دریافت خواهید کرد", - "Wiping of device %s has finished" : "پاک کردن دستگاه %sبه پایان رسیده است", - "Wiping of device »%s« has finished" : "پاک کردن دستگاه %sبه پایان رسیده است", - "»%s« finished remote wipe" : "%sپاک کردن از راه دور", - "Device or application »%s« has finished the remote wipe process." : "دستگاه یا برنامه %sفرآیند پاک کردن از راه دور را به پایان رسانده است.", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "حساب وارد شده باید یک مدیر، یک مدیر فرعی یا دارای حق دسترسی ویژه برای دسترسی به این تنظیم باشد", + "Your current IP address doesn't allow you to perform admin actions" : "آدرس IP فعلی شما اجازه انجام اقدامات مدیریتی را به شما نمیدهد", + "Logged in account must be an admin or sub admin" : "حساب وارد شده باید یک مدیر یا مدیر فرعی باشد", + "Logged in account must be an admin" : "حساب وارد شده باید یک مدیر باشد", + "Wiping of device %s has started" : "پاک کردن دستگاه %s آغاز شد", + "Wiping of device »%s« has started" : "پاک کردن دستگاه «%s» آغاز شد", + "»%s« started remote wipe" : "«%s» پاک کردن از راه دور را آغاز کرد", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "دستگاه یا برنامه «%s» فرآیند پاک کردن از راه دور را آغاز کرده است. پس از اتمام مراحل، ایمیل دیگری دریافت خواهید کرد.", + "Wiping of device %s has finished" : "پاک کردن دستگاه %s به پایان رسید", + "Wiping of device »%s« has finished" : "پاک کردن دستگاه «%s» به پایان رسید", + "»%s« finished remote wipe" : "«%s» پاک کردن از راه دور را به پایان رساند", + "Device or application »%s« has finished the remote wipe process." : "دستگاه یا برنامه «%s» فرآیند پاک کردن از راه دور را به پایان رسانده است.", "Remote wipe started" : "پاک کردن از راه دور شروع شد", - "A remote wipe was started on device %s" : "پاک کردن از راه دور روی دستگاه شروع شد%s", + "A remote wipe was started on device %s" : "پاک کردن از راه دور روی دستگاه %s شروع شد", "Remote wipe finished" : "پاک کردن از راه دور به پایان رسید", - "The remote wipe on %s has finished" : "پاک کردن از راه دور روی%s کار تمام شد", + "The remote wipe on %s has finished" : "پاک کردن از راه دور روی %s کار تمام شد", "Authentication" : "احراز هویت", "Unknown filetype" : "نوع فایل ناشناخته", "Invalid image" : "عکس نامعتبر", "Avatar image is not square" : "تصویر آواتار مربع نیست", "Files" : "پوشهها", "View profile" : "مشاهدهٔ نمایه", - "Local time: %s" : "Local time: %s", + "same time" : "همزمان", + "_%nh_::_%nh_" : ["%n ساعت","%n ساعت"], + "_%nm_::_%nm_" : ["%n دقیقه","%n دقیقه"], + "%s ahead" : "%s جلوتر", + "%s behind" : "%s عقبتر", + "Local time: %s" : "زمان محلی: %s", "today" : "امروز", "tomorrow" : "فردا", "yesterday" : "دیروز", @@ -74,13 +85,37 @@ OC.L10N.register( "in a few seconds" : "در چند ثانیه", "seconds ago" : "ثانیهها پیش", "Empty file" : "پروندهٔ خالی", - "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ماژول با شناسه:%s وجود ندارد. لطفاً آن را در تنظیمات برنامه خود فعال کنید یا با سرپرست خود تماس بگیرید", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ماژول با شناسه: %s وجود ندارد. لطفاً آن را در تنظیمات برنامه خود فعال کنید یا با سرپرست خود تماس بگیرید.", + "No file conversion providers available" : "ارائهدهنده تبدیل فایل در دسترس نیست", + "File is too large to convert" : "فایل برای تبدیل خیلی بزرگ است", + "Destination does not match conversion extension" : "مقصد با پسوند تبدیل مطابقت ندارد", + "Could not convert file" : "فایل قابل تبدیل نبود", + "Destination does not exist" : "مقصد وجود ندارد", + "Destination is not creatable" : "مقصد قابل ایجاد نیست", "Dot files are not allowed" : "پروندههای نقطهدار مجاز نیستند", + "%1$s (renamed)" : "%1$s (تغییر نام داده شد)", + "renamed file" : "فایل تغییر نام داده شد", + "\"%1$s\" is a forbidden file or folder name." : "«%1$s» یک نام فایل یا پوشه ممنوع است.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "«%1$s» یک پیشوند ممنوع برای نام فایل یا پوشه است.", + "\"%1$s\" is not allowed inside a file or folder name." : "«%1$s» در نام فایل یا پوشه مجاز نیست.", + "\"%1$s\" is a forbidden file type." : "«%1$s» یک نوع فایل ممنوع است.", + "Filenames must not end with \"%1$s\"." : "نام فایلها نباید با «%1$s» به پایان برسند.", + "Invalid parent path" : "مسیر والد نامعتبر", "File already exists" : "پرونده از پیش موجود است", "Invalid path" : "مسیر نامعتبر", "Failed to create file from template" : "شکست در ایجاد پرونده از قالب", "Templates" : "قالبها", + "Storage %s cannot be moved" : "حافظه %s قابل جابجایی نیست", + "Moving a share (%s) into a shared folder is not allowed" : "انتقال یک اشتراک (%s) به یک پوشه مشترک مجاز نیست", + "Moving a storage (%s) into a shared folder is not allowed" : "انتقال یک حافظه (%s) به یک پوشه مشترک مجاز نیست", + "Moving a share (%s) into another share (%s) is not allowed" : "انتقال یک اشتراک (%s) به اشتراک دیگر (%s) مجاز نیست", + "Moving a share (%s) into another storage (%s) is not allowed" : "انتقال یک اشتراک (%s) به حافظه دیگر (%s) مجاز نیست", + "Moving a storage (%s) into a share (%s) is not allowed" : "انتقال یک حافظه (%s) به یک اشتراک (%s) مجاز نیست", + "Moving a storage (%s) into another storage (%s) is not allowed" : "انتقال یک حافظه (%s) به حافظه دیگر (%s) مجاز نیست", + "Path contains invalid segments" : "مسیر شامل بخشهای نامعتبر است", + "Filename is a reserved word" : "نام فایل یک کلمه رزرو شده است", "Filename contains at least one invalid character" : "نام فایل حداقل دارای یک کاراکتر نامعتبر است", + "Filename is too long" : "نام فایل بیش از حد طولانی است", "Empty filename is not allowed" : "نام فایل نمیتواند خالی باشد", "App \"%s\" cannot be installed because appinfo file cannot be read." : "کارهٔ «%s» به دلیل ناتوانی در خواندن پروندهٔ appinfo نمیتواند نصب شود.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "کارهٔ «%s» به دلیل سازگار نبودن با این نگارش از کارساز نمیتواند نصب شود.", @@ -96,8 +131,8 @@ OC.L10N.register( "Accounts" : "حسابها", "Email" : "رایانامه", "Mail %s" : "نامه به %s", - "Fediverse" : "Fediverse", - "View %s on the fediverse" : "View %s on the fediverse", + "Fediverse" : "فدیورس", + "View %s on the fediverse" : "مشاهده %s در فدیورس", "Phone" : "تلفن", "Call %s" : "تماس با %s", "Twitter" : "توییتر", @@ -107,37 +142,87 @@ OC.L10N.register( "Address" : "نشانی", "Profile picture" : "تصویر نمایه", "About" : "درباره", - "Display name" : "Display name", + "Display name" : "نام نمایشی", "Headline" : "عنوان", - "Organisation" : "سازمان", + "Organization" : "سازمانی", "Role" : "نقش", + "Pronouns" : "ضمایر", + "Unknown account" : "حساب ناشناخته", "Additional settings" : "تنظیمات اضافی", + "Enter the database Login and name for %s" : "نام کاربری و نام پایگاه داده را برای %s وارد کنید", + "Enter the database Login for %s" : "نام کاربری پایگاه داده را برای %s وارد کنید", "Enter the database name for %s" : "ورود نام پایگاه داده برای %s", "You cannot use dots in the database name %s" : "نمیتوانید در در نام پایگاه دادهٔ %s از نقطه استفاده کنید", + "MySQL Login and/or password not valid" : "نام کاربری و/یا رمز عبور MySQL نامعتبر است", "You need to enter details of an existing account." : "لازم است جزییات یک حساب موحود را وارد کنید.", "Oracle connection could not be established" : "ارتباط اراکل نمیتواند برقرار باشد.", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "مکاواس ۱۰ پشتیبانی نشده و %s روی این بنسازه درست کار نخواهد کرد. با مسئولیت خودتان استفاده کنید!", + "Oracle Login and/or password not valid" : "نام کاربری و/یا رمز عبور Oracle نامعتبر است", + "PostgreSQL Login and/or password not valid" : "نام کاربری و/یا رمز عبور PostgreSQL نامعتبر است", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X پشتیبانی نمیشود و %s روی این پلتفرم به درستی کار نخواهد کرد. با مسئولیت خودتان از آن استفاده کنید!", "For the best results, please consider using a GNU/Linux server instead." : "برای بهترین نتیجه، استفاده از یک کارساز گنو/لینوکسی را در نظر داشته باشید.", - "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "به نظر می رسد%s که این نمونه در یک محیط PHP 32 بیتی در حال اجرا است و open_baseir در php.ini پیکربندی شده است. این مسئله به پرونده هایی با بیش از 4 گیگ منجر می شود و بسیار دلسرد می شود", - "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "لطفاً تنظیمات open_baseir را درون php.ini خود حذف کنید یا به PHP 64 بیتی تغییر دهید.", + "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "به نظر می رسد %s که این نمونه در یک محیط PHP 32 بیتی در حال اجرا است و open_basedir در php.ini پیکربندی شده است. این مسئله به پرونده هایی با بیش از 4 گیگ منجر می شود و بسیار دلسرد می شود.", + "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "لطفاً تنظیمات open_basedir را درون php.ini خود حذف کنید یا به PHP 64 بیتی تغییر دهید.", + "Set an admin Login." : "یک نام کاربری برای مدیر تنظیم کنید.", "Set an admin password." : "یک رمزعبور برای مدیر تنظیم نمایید.", - "Cannot create or write into the data directory %s" : "Cannot create or write into the data directory %s", - "Sharing backend %s must implement the interface OCP\\Share_Backend" : "به اشتراک گذاشتن باطن باید رابط OCP \\ Share_Backend %sرا پیاده سازی کند", - "Sharing backend %s not found" : "به اشتراک گذاشتن باطن%s یافت نشد", - "Sharing backend for %s not found" : "به اشتراک گذاشتن باطن برای%s یافت نشد", - "Click the button below to open it." : "برای باز کردن آن روی دکمه زیر کلیک کنید.", + "Cannot create or write into the data directory %s" : "نمیتوان در دایرکتوری داده %s ایجاد یا نوشت", + "Sharing backend %s must implement the interface OCP\\Share_Backend" : "بکاند اشتراکگذاری %s باید رابط OCP\\Share_Backend را پیادهسازی کند", + "Sharing backend %s not found" : "بکاند اشتراکگذاری %s یافت نشد", + "Sharing backend for %s not found" : "بکاند اشتراکگذاری برای %s یافت نشد", + "%1$s shared %2$s with you" : "%1$s %2$s را با شما به اشتراک گذاشت", + "Open %s" : "باز کردن %s", "%1$s via %2$s" : "%1$s از طریق %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s %2$s را با شما به اشتراک گذاشت و میخواهد اضافه کند:", + "%1$s shared %2$s with you and wants to add" : "%1$s %2$s را با شما به اشتراک گذاشت و میخواهد اضافه کند", + "%s added a note to a file shared with you" : "%s یک یادداشت به فایلی که با شما به اشتراک گذاشته شده است اضافه کرد", + "Passwords are enforced for link and mail shares" : "رمزهای عبور برای اشتراکگذاری لینک و ایمیل اجباری هستند", + "Share recipient is not a valid user" : "گیرنده اشتراک یک کاربر معتبر نیست", + "Share recipient is not a valid group" : "گیرنده اشتراک یک گروه معتبر نیست", + "Share recipient should be empty" : "گیرنده اشتراک باید خالی باشد", + "Share recipient should not be empty" : "گیرنده اشتراک نباید خالی باشد", + "Share recipient is not a valid circle" : "گیرنده اشتراک یک دایره معتبر نیست", "Unknown share type" : "نوع اشتراک ناشناخته", - "You are not allowed to share %s" : "شما مجاز به اشتراک گذاری نیستید%s", - "Cannot increase permissions of %s" : "Cannot increase permissions of %s", - "Files cannot be shared with delete permissions" : "Files cannot be shared with delete permissions", - "Files cannot be shared with create permissions" : "Files cannot be shared with create permissions", + "Share initiator must be set" : "شروعکننده اشتراک باید تنظیم شود", + "Cannot share with yourself" : "نمیتوانید با خودتان به اشتراک بگذارید", + "Shared path must be set" : "مسیر مشترک باید تنظیم شود", + "Shared path must be either a file or a folder" : "مسیر مشترک باید یک فایل یا یک پوشه باشد", + "You cannot share your root folder" : "نمیتوانید پوشه ریشه خود را به اشتراک بگذارید", + "You are not allowed to share %s" : "شما مجاز به اشتراک گذاری %s نیستید", + "Valid permissions are required for sharing" : "مجوزهای معتبر برای اشتراکگذاری لازم است", + "File shares cannot have create or delete permissions" : "اشتراکگذاری فایلها نمیتواند مجوزهای ایجاد یا حذف داشته باشد", + "Cannot increase permissions of %s" : "نمیتوان مجوزهای %s را افزایش داد", + "Shares need at least read permissions" : "اشتراکگذاریها حداقل به مجوزهای خواندن نیاز دارند", + "Files cannot be shared with delete permissions" : "فایلها را نمیتوان با مجوزهای حذف به اشتراک گذاشت", + "Files cannot be shared with create permissions" : "فایلها را نمیتوان با مجوزهای ایجاد به اشتراک گذاشت", "Expiration date is in the past" : "تاریخ انقضا در گذشته است", - "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Cannot set expiration date more than %n day in the future","Cannot set expiration date more than %n days in the future"], - "Sharing is only allowed with group members" : "Sharing is only allowed with group members", + "Expiration date is enforced" : "تاریخ انقضا اجباری است", + "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["نمیتوان تاریخ انقضا را بیش از %n روز در آینده تنظیم کرد","نمیتوان تاریخ انقضا را بیش از %n روز در آینده تنظیم کرد"], + "Sharing is only allowed with group members" : "اشتراکگذاری فقط با اعضای گروه مجاز است", + "Sharing %s failed, because this item is already shared with the account %s" : "اشتراکگذاری %s ناموفق بود، زیرا این مورد قبلاً با حساب %s به اشتراک گذاشته شده است", + "Group sharing is now allowed" : "اشتراکگذاری گروهی اکنون مجاز است", + "Sharing is only allowed within your own groups" : "اشتراکگذاری فقط در گروههای خودتان مجاز است", + "Path is already shared with this group" : "این مسیر قبلاً با این گروه به اشتراک گذاشته شده است", + "Link sharing is not allowed" : "اشتراکگذاری لینک مجاز نیست", + "Public upload is not allowed" : "بارگذاری عمومی مجاز نیست", + "You cannot share a folder that contains other shares" : "نمیتوانید پوشهای را به اشتراک بگذارید که حاوی اشتراکهای دیگر است", + "Sharing is disabled" : "اشتراکگذاری غیرفعال است", + "Sharing is disabled for you" : "اشتراکگذاری برای شما غیرفعال است", + "Cannot share with the share owner" : "نمیتوان با صاحب اشتراک به اشتراک گذاشت", + "Share does not have a full ID" : "اشتراک شناسه کامل ندارد", + "Cannot change share type" : "نمیتوان نوع اشتراک را تغییر داد", + "Can only update recipient on user shares" : "فقط میتوان گیرنده را در اشتراکهای کاربر بهروزرسانی کرد", + "Cannot enable sending the password by Talk with an empty password" : "نمیتوان ارسال رمز عبور از طریق Talk را با رمز عبور خالی فعال کرد", + "Cannot enable sending the password by Talk without setting a new password" : "نمیتوان ارسال رمز عبور از طریق Talk را بدون تنظیم رمز عبور جدید فعال کرد", + "Cannot disable sending the password by Talk without setting a new password" : "نمیتوان ارسال رمز عبور از طریق Talk را بدون تنظیم رمز عبور جدید غیرفعال کرد", + "Share provider does not support accepting" : "ارائهدهنده اشتراک از پذیرش پشتیبانی نمیکند", + "Cannot change target of link share" : "نمیتوان مقصد اشتراک لینک را تغییر داد", + "Invalid share recipient" : "گیرنده اشتراک نامعتبر است", + "Group \"%s\" does not exist" : "گروه «%s» وجود ندارد", "The requested share does not exist anymore" : "سهم درخواست شده دیگر وجود ندارد", - "The user was not created because the user limit has been reached. Check your notifications to learn more." : "The user was not created because the user limit has been reached. Check your notifications to learn more.", + "The requested share comes from a disabled user" : "اشتراک درخواستی از یک کاربر غیرفعال است", + "The user was not created because the user limit has been reached. Check your notifications to learn more." : "کاربر ایجاد نشد زیرا محدودیت کاربر به پایان رسیده است. برای اطلاعات بیشتر اعلانهای خود را بررسی کنید.", "Could not find category \"%s\"" : "دسته بندی %s یافت نشد", + "Input text" : "متن ورودی", + "The input text" : "متن ورودی", "Sunday" : "یکشنبه", "Monday" : "دوشنبه", "Tuesday" : "سهشنبه", @@ -184,6 +269,15 @@ OC.L10N.register( "Nov." : "نو.", "Dec." : "دس.", "A valid password must be provided" : "رمز عبور صحیح باید وارد شود", + "The Login is already being used" : "نام کاربری قبلاً استفاده شده است", + "Could not create account" : "حساب کاربری ایجاد نشد", + "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "فقط کاراکترهای زیر در نام کاربری مجاز هستند: \"a-z\", \"A-Z\", \"0-9\", فاصله و \"_.@-'\"", + "A valid Login must be provided" : "یک نام کاربری معتبر باید ارائه شود", + "Login contains whitespace at the beginning or at the end" : "نام کاربری حاوی فاصله در ابتدا یا انتها است", + "Login must not consist of dots only" : "نام کاربری نباید فقط از نقطه تشکیل شده باشد", + "Username is too long" : "نام کاربری بیش از حد طولانی است", + "Login is invalid because files already exist for this user" : "نام کاربری نامعتبر است زیرا فایلها برای این کاربر از قبل وجود دارند", + "Account disabled" : "حساب کاربری غیرفعال است", "Login canceled by app" : "ورود به دست کاره لغو شد", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "کارهٔ «%1$s» نمیتواند نصب شود؛ چرا که وابستگی زیر تأمین نشده: %2$s", "a safe home for all your data" : "خانهای امن برای تمامی دادههایتان", @@ -191,93 +285,174 @@ OC.L10N.register( "Authentication error" : "خطا در اعتبار سنجی", "Token expired. Please reload page." : "Token منقضی شده است. لطفا دوباره صفحه را بارگذاری نمایید.", "No database drivers (sqlite, mysql, or postgresql) installed." : "هیچ درایور پایگاه داده (sqlite ، mysql یا postgresql) نصب نشده است.", - "Cannot write into \"config\" directory." : "Cannot write into \"config\" directory.", - "This can usually be fixed by giving the web server write access to the config directory. See %s" : "This can usually be fixed by giving the web server write access to the config directory. See %s", - "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "یا اگر ترجیح می دهید پرونده config.php را فقط بخوانید ، گزینه \"config_is_read_only\" را در آن تنظیم کنید. دیدن%s", - "Cannot write into \"apps\" directory." : "Cannot write into \"apps\" directory.", - "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file.", - "Cannot create \"data\" directory." : "Cannot create \"data\" directory.", - "This can usually be fixed by giving the web server write access to the root directory. See %s" : "This can usually be fixed by giving the web server write access to the root directory. See %s", - "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Permissions can usually be fixed by giving the web server write access to the root directory. See %s.", - "Your data directory is not writable." : "Your data directory is not writable.", - "Setting locale to %s failed." : "Setting locale to %s failed.", - "Please install one of these locales on your system and restart your web server." : "Please install one of these locales on your system and restart your web server.", + "Cannot write into \"config\" directory." : "نمیتوان در دایرکتوری «config» نوشت.", + "This can usually be fixed by giving the web server write access to the config directory. See %s" : "این مشکل معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری پیکربندی قابل رفع است. مشاهده %s", + "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "یا اگر ترجیح میدهید فایل config.php فقط خواندنی باشد، گزینه \"config_is_read_only\" را در آن به true تنظیم کنید. مشاهده %s", + "Cannot write into \"apps\" directory." : "نمیتوان در دایرکتوری «apps» نوشت.", + "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "این مشکل معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری برنامهها یا غیرفعال کردن فروشگاه برنامه در فایل پیکربندی قابل رفع است.", + "Cannot create \"data\" directory." : "نمیتوان دایرکتوری «data» را ایجاد کرد.", + "This can usually be fixed by giving the web server write access to the root directory. See %s" : "این مشکل معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری ریشه قابل رفع است. مشاهده %s", + "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "مجوزها معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری ریشه قابل رفع هستند. مشاهده %s.", + "Your data directory is not writable." : "دایرکتوری داده شما قابل نوشتن نیست.", + "Setting locale to %s failed." : "تنظیم محلی به %s ناموفق بود.", + "Please install one of these locales on your system and restart your web server." : "لطفاً یکی از این محلیها را روی سیستم خود نصب کرده و وبسرور خود را مجدداً راهاندازی کنید.", "PHP module %s not installed." : "ماژول PHP %s نصب نشده است.", "Please ask your server administrator to install the module." : "لطفا از مدیر سیستم بخواهید تا ماژول را نصب کند.", - "PHP setting \"%s\" is not set to \"%s\"." : "تنظیمات PHP%s تنظیم نشده است%s", + "PHP setting \"%s\" is not set to \"%s\"." : "تنظیمات PHP «%s» روی «%s» تنظیم نشده است.", "Adjusting this setting in php.ini will make Nextcloud run again" : "تنظیم این تنظیمات در php.ini باعث می شود Nextcloud دوباره اجرا شود", - "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>.", - "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini.", - "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ظاهراً برای خنثی کردن بلوک های اسناد درون خطی تنظیم شده است. این کار چندین برنامه اصلی را غیرقابل دسترسی خواهد کرد.", - "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "این احتمالاً توسط حافظه پنهان / کش مانند Zend OPcache یا eAccelerator ایجاد شده است.", - "PHP modules have been installed, but they are still listed as missing?" : "ماژول های پی اچ پی نصب شده اند ، اما هنوز هم به عنوان مفقود شده ذکر شده اند؟", - "Please ask your server administrator to restart the web server." : "لطفاً از سرور سرور خود بخواهید که وب سرور را مجدداً راه اندازی کند.", - "The required %s config variable is not configured in the config.php file." : "The required %s config variable is not configured in the config.php file.", - "Please ask your server administrator to check the Nextcloud configuration." : "Please ask your server administrator to check the Nextcloud configuration.", - "Your data directory must be an absolute path." : "Your data directory must be an absolute path.", - "Check the value of \"datadirectory\" in your configuration." : "Check the value of \"datadirectory\" in your configuration.", - "Your data directory is invalid." : "Your data directory is invalid.", - "Action \"%s\" not supported or implemented." : "عملی%s پشتیبانی یا اجرا نشده است.", - "Authentication failed, wrong token or provider ID given" : "تأیید اعتبار انجام نشد ، نشانه اشتباه یا شناسه ارائه دهنده داده شد", - "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "پارامترهای موجود برای تکمیل درخواست. پارامترهای موجود نیست%s", - "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "شناسه%1$s قبلاً توسط ارائه دهنده فدراسیون ابر استفاده شده است%2$s", - "Cloud Federation Provider with ID: \"%s\" does not exist." : "ارائه دهنده فدراسیون Cloud با شناسه:%s وجود ندارد.", - "Could not obtain lock type %d on \"%s\"." : "نمی توان نوع%d قفل را به دست آورد%s", - "Storage unauthorized. %s" : "ذخیره سازی غیر مجاز.%s", - "Storage incomplete configuration. %s" : "پیکربندی ناقص ذخیره سازی.%s<br>", - "Storage connection error. %s" : "خطای اتصال ذخیره سازی%s", - "Storage is temporarily not available" : "ذخیره سازی به طور موقت در دسترس نیست", - "Storage connection timeout. %s" : "مدت زمان اتصال ذخیره سازی%s", - "Confirmation" : "Confirmation", - "Prompt" : "Prompt", - "Chat" : "Chat", - "Generates a possible headline for a text." : "Generates a possible headline for a text.", - "Summarize" : "Summarize", + "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> به جای مقدار مورد انتظار <code>0</code> روی <code>%s</code> تنظیم شده است.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "برای رفع این مشکل، <code>mbstring.func_overload</code> را در php.ini خود روی <code>0</code> تنظیم کنید.", + "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ظاهراً برای حذف بلوکهای مستندات درونخطی تنظیم شده است. این کار چندین برنامه اصلی را غیرقابل دسترس خواهد کرد.", + "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "این احتمالاً توسط حافظه پنهان/شتابدهندهای مانند Zend OPcache یا eAccelerator ایجاد شده است.", + "PHP modules have been installed, but they are still listed as missing?" : "ماژولهای PHP نصب شدهاند، اما همچنان به عنوان گمشده لیست شدهاند؟", + "Please ask your server administrator to restart the web server." : "لطفاً از مدیر سرور خود بخواهید که وبسرور را مجدداً راهاندازی کند.", + "The required %s config variable is not configured in the config.php file." : "متغیر پیکربندی مورد نیاز %s در فایل config.php پیکربندی نشده است.", + "Please ask your server administrator to check the Nextcloud configuration." : "لطفاً از مدیر سرور خود بخواهید پیکربندی Nextcloud را بررسی کند.", + "Your data directory is readable by other people." : "دایرکتوری داده شما برای دیگران قابل خواندن است.", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "لطفاً مجوزها را به 0770 تغییر دهید تا دایرکتوری توسط افراد دیگر قابل فهرست شدن نباشد.", + "Your data directory must be an absolute path." : "دایرکتوری داده شما باید یک مسیر مطلق باشد.", + "Check the value of \"datadirectory\" in your configuration." : "مقدار \"datadirectory\" را در پیکربندی خود بررسی کنید.", + "Your data directory is invalid." : "دایرکتوری داده شما نامعتبر است.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "اطمینان حاصل کنید که فایلی به نام «%1$s» در ریشه دایرکتوری داده وجود دارد. این فایل باید حاوی: «%2$s» باشد", + "Action \"%s\" not supported or implemented." : "عملیات «%s» پشتیبانی یا اجرا نشده است.", + "Authentication failed, wrong token or provider ID given" : "تأیید اعتبار انجام نشد، نشانه اشتباه یا شناسه ارائه دهنده داده شد", + "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "پارامترهای مورد نیاز برای تکمیل درخواست وجود ندارند. پارامترهای از دست رفته: «%s»", + "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "شناسه «%1$s» قبلاً توسط ارائهدهنده فدراسیون ابری «%2$s» استفاده شده است", + "Cloud Federation Provider with ID: \"%s\" does not exist." : "ارائهدهنده فدراسیون ابری با شناسه: «%s» وجود ندارد.", + "Could not obtain lock type %d on \"%s\"." : "نمیتوان قفل از نوع %d را روی «%s» به دست آورد.", + "Storage unauthorized. %s" : "دسترسی به حافظه غیرمجاز است. %s", + "Storage incomplete configuration. %s" : "پیکربندی حافظه ناقص است. %s", + "Storage connection error. %s" : "خطای اتصال حافظه. %s", + "Storage is temporarily not available" : "حافظه به طور موقت در دسترس نیست", + "Storage connection timeout. %s" : "مهلت اتصال حافظه به پایان رسید. %s", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "برای اجرای این بررسی، باید مطمئن شوید که وبسرور شما میتواند به خودش متصل شود. بنابراین باید بتواند حداقل یکی از `trusted_domains` یا `overwrite.cli.url` خود را حل و به آن متصل شود. این خطا ممکن است نتیجه عدم تطابق DNS سمت سرور یا قانون فایروال خروجی باشد.", + "Transcribe audio" : "رونوشت صوتی", + "Transcribe the things said in an audio" : "رونوشت چیزهای گفته شده در یک فایل صوتی", + "Audio input" : "ورودی صوتی", + "The audio to transcribe" : "فایل صوتی برای رونوشت", + "Transcription" : "رونوشت", + "The transcribed text" : "متن رونوشت شده", + "Chat with an agent" : "چت با یک عامل", + "Chat message" : "پیام چت", + "A chat message to send to the agent." : "یک پیام چت برای ارسال به عامل.", + "Confirmation" : "تأیید", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "آیا اقدامات قبلاً درخواست شده را تأیید کنید: 0 برای رد و 1 برای تأیید.", + "Conversation token" : "توکن مکالمه", + "A token representing the conversation." : "یک توکن نماینده مکالمه.", + "Generated response" : "پاسخ تولید شده", + "The response from the chat model." : "پاسخ از مدل چت.", + "The new conversation token" : "توکن مکالمه جدید", + "Send this along with the next interaction." : "این را همراه با تعامل بعدی ارسال کنید.", + "Requested actions by the agent" : "اقدامات درخواستی توسط عامل", + "Actions that the agent would like to carry out in JSON format." : "اقدامات که عامل مایل به انجام آنها در قالب JSON است.", + "Context write" : "نوشتن متنی", + "Writes text in a given style based on the provided source material." : "متن را با سبکی مشخص بر اساس محتوای منبع ارائه شده مینویسد.", + "Writing style" : "سبک نگارش", + "Demonstrate a writing style that you would like to immitate" : "یک سبک نگارش را که میخواهید تقلید کنید، نشان دهید", + "Source material" : "محتوای منبع", + "The content that would like to be rewritten in the new writing style" : "محتوایی که میخواهید با سبک نگارش جدید بازنویسی شود", + "Generated text" : "متن تولید شده", + "The generated text with content from the source material in the given style" : "متن تولید شده با محتوای منبع در سبک مشخص شده", + "Emoji generator" : "تولیدکننده اموجی", + "Takes text and generates a representative emoji for it." : "متن را دریافت کرده و یک اموجی مناسب برای آن تولید میکند.", + "The text to generate an emoji for" : "متنی که میخواهید برای آن اموجی تولید شود", + "Generated emoji" : "اموجی تولید شده", + "The generated emoji based on the input text" : "اموجی تولید شده بر اساس متن ورودی", + "Generate image" : "تولید تصویر", + "Generate an image from a text prompt" : "تولید تصویر از یک متن ورودی", + "Prompt" : "درخواست", + "Describe the image you want to generate" : "تصویری که میخواهید تولید شود را توصیف کنید", + "Number of images" : "تعداد تصاویر", + "How many images to generate" : "چه تعداد تصویر تولید شود", + "Output images" : "تصاویر خروجی", + "The generated images" : "تصاویر تولید شده", + "Generate speech" : "تولید گفتار", + "Generate speech from a transcript" : "تولید گفتار از یک رونوشت", + "Write transcript that you want the assistant to generate speech from" : "رونوشتی را بنویسید که میخواهید دستیار از آن گفتار تولید کند", + "Output speech" : "گفتار خروجی", + "The generated speech" : "گفتار تولید شده", + "Free text to text prompt" : "درخواست متن به متن آزاد", + "Runs an arbitrary prompt through a language model that returns a reply" : "یک درخواست دلخواه را از طریق یک مدل زبانی اجرا میکند که پاسخی را برمیگرداند", + "Describe a task that you want the assistant to do or ask a question" : "وظیفهای که میخواهید دستیار انجام دهد را توصیف کنید یا سؤالی بپرسید", + "Generated reply" : "پاسخ تولید شده", + "The generated text from the assistant" : "متن تولید شده توسط دستیار", + "Change Tone" : "تغییر لحن", + "Change the tone of a piece of text." : "لحن یک قطعه متن را تغییر دهید.", + "Write a text that you want the assistant to rewrite in another tone." : "متنی را بنویسید که میخواهید دستیار آن را با لحن دیگری بازنویسی کند.", + "Desired tone" : "لحن مورد نظر", + "In which tone should your text be rewritten?" : "متن شما با چه لحنی بازنویسی شود؟", + "The rewritten text in the desired tone, written by the assistant:" : "متن بازنویسی شده با لحن مورد نظر، نوشته شده توسط دستیار:", + "Chat" : "چت", + "Chat with the assistant" : "چت با دستیار", + "System prompt" : "درخواست سیستمی", + "Define rules and assumptions that the assistant should follow during the conversation." : "قوانین و فرضیاتی را که دستیار باید در طول مکالمه رعایت کند، تعریف کنید.", + "Chat history" : "تاریخچه چت", + "The history of chat messages before the current message, starting with a message by the user" : "تاریخچه پیامهای چت قبل از پیام فعلی، با شروع از یک پیام توسط کاربر", + "Response message" : "پیام پاسخ", + "The generated response as part of the conversation" : "پاسخ تولید شده به عنوان بخشی از مکالمه", + "Chat with tools" : "چت با ابزارها", + "Chat with the language model with tool calling support." : "چت با مدل زبانی با پشتیبانی از فراخوانی ابزار.", + "Tool message" : "پیام ابزار", + "The result of tool calls in the last interaction" : "نتیجه فراخوانی ابزارها در تعامل قبلی", + "Available tools" : "ابزارهای موجود", + "The available tools in JSON format" : "ابزارهای موجود در قالب JSON", + "The response from the chat model" : "پاسخ از مدل چت", + "Tool calls" : "فراخوانی ابزار", + "Tools call instructions from the model in JSON format" : "دستورالعملهای فراخوانی ابزار از مدل در قالب JSON", + "Formalize text" : "رسمی کردن متن", + "Takes a text and makes it sound more formal" : "یک متن را دریافت کرده و آن را رسمیتر میکند", + "Write a text that you want the assistant to formalize" : "متنی را بنویسید که میخواهید دستیار آن را رسمی کند", + "Formalized text" : "متن رسمی شده", + "The formalized text" : "متن رسمی شده", + "Generate a headline" : "تولید یک عنوان", + "Generates a possible headline for a text." : "یک عنوان احتمالی برای یک متن تولید میکند.", + "Original text" : "متن اصلی", + "The original text to generate a headline for" : "متن اصلی برای تولید عنوان", + "The generated headline" : "عنوان تولید شده", + "Proofread" : "ویرایش", + "Proofreads a text and lists corrections" : "یک متن را ویرایش کرده و اصلاحات را لیست میکند", + "Text" : "متن", + "The text to proofread" : "متن برای ویرایش", + "Corrections" : "اصلاحات", + "The corrections that should be made in your text" : "اصلاحاتی که باید در متن شما انجام شود", + "Reformulate text" : "بازنویسی متن", + "Takes a text and reformulates it" : "یک متن را دریافت کرده و آن را بازنویسی میکند", + "Write a text that you want the assistant to reformulate" : "متنی را بنویسید که میخواهید دستیار آن را بازنویسی کند", + "Reformulated text" : "متن بازنویسی شده", + "The reformulated text, written by the assistant" : "متن بازنویسی شده، نوشته شده توسط دستیار", + "Simplify text" : "سادهسازی متن", + "Takes a text and simplifies it" : "یک متن را دریافت کرده و آن را ساده میکند", + "Write a text that you want the assistant to simplify" : "متنی را بنویسید که میخواهید دستیار آن را ساده کند", + "Simplified text" : "متن ساده شده", + "The simplified text" : "متن ساده شده", + "Summarize" : "خلاصهسازی", + "Summarizes a text" : "یک متن را خلاصهسازی میکند", + "The original text to summarize" : "متن اصلی برای خلاصهسازی", "Summary" : "چکیده", - "Extract topics" : "Extract topics", + "The generated summary" : "خلاصه تولید شده", + "Extract topics" : "استخراج موضوعات", + "Extracts topics from a text and outputs them separated by commas" : "موضوعات را از یک متن استخراج کرده و با کاما جدا شده خروجی میدهد", + "The original text to extract topics from" : "متن اصلی برای استخراج موضوعات", + "Topics" : "موضوعات", + "The list of extracted topics" : "لیست موضوعات استخراج شده", "Translate" : "ترجمه", - "Target language" : "Target language", - "Result" : "شروع به اسکنیک", - "Free prompt" : "Free prompt", - "Runs an arbitrary prompt through the language model." : "Runs an arbitrary prompt through the language model.", - "Generate headline" : "Generate headline", - "Summarizes text by reducing its length without losing key information." : "Summarizes text by reducing its length without losing key information.", - "Extracts topics from a text and outputs them separated by commas." : "Extracts topics from a text and outputs them separated by commas.", - "Education Edition" : "نگارش آموزشی", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Logged in user must be an admin, a sub admin or gotten special right to access this setting", - "Logged in user must be an admin or sub admin" : "ورود به سیستم کاربر باید یک مدیر یا مدیر فرعی باشد", - "Logged in user must be an admin" : "ورود به سیستم کاربر باید مدیر سایت باشد", - "File name is a reserved word" : "این نام فایل جزو کلمات رزرو میباشد", - "File name contains at least one invalid character" : "نام فایل دارای حداقل یک کاراکتر نامعتبر است", - "File name is too long" : "نام فایل خیلی بزرگ است", - "Help" : "راهنما", - "Users" : "کاربران", - "Unknown user" : "کاربر نامعلوم", - "Enter the database username and name for %s" : "ورود نام و نام کاربری پایگاه داده برای %s", - "Enter the database username for %s" : "ورود نام کاربری پایگاه داده برای %s", - "MySQL username and/or password not valid" : "نام کاربری یا گذرواژهٔ مایسکول معتبر نیست", - "Oracle username and/or password not valid" : "نام کاربری و / یا رمزعبور اراکل معتبر نیست.", - "PostgreSQL username and/or password not valid" : "PostgreSQL نام کاربری و / یا رمزعبور معتبر نیست.", - "Set an admin username." : "یک نام کاربری برای مدیر تنظیم نمایید.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s به اشتراک گذاشته شده »%2$s« با شماست و می خواهد اضافه کند:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s به اشتراک گذاشته شده »%2$s« با شماست و می خواهد اضافه کند:", - "»%s« added a note to a file shared with you" : "»%s« یادداشتی را به پرونده ای که با شما به اشتراک گذاشته شده است اضافه کرد", - "Open »%s«" : "باز کن »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Sharing %s failed, because this item is already shared with user %s", - "%1$s shared »%2$s« with you" : "%1$s به اشتراک گذاشته » %2$s« با شما", - "%1$s shared »%2$s« with you." : "%1$s به اشتراک گذاشته » %2$s« با شما", - "The username is already being used" : "نامکاربری قبلا استفاده شده است", - "Could not create user" : "نتواسنت کاربر را ایجاد کند", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"", - "A valid username must be provided" : "نام کاربری صحیح باید وارد شود", - "Username contains whitespace at the beginning or at the end" : "نام کاربری دارای فضای سفید در ابتدا یا انتهای آن است", - "Username must not consist of dots only" : "نام کاربری نباید فقط از نقاط تشکیل شده باشد", - "Username is invalid because files already exist for this user" : "Username is invalid because files already exist for this user", - "User disabled" : "کاربر از کار افتاده", + "Translate text from one language to another" : "ترجمه متن از یک زبان به زبان دیگر", + "Origin text" : "متن مبدأ", + "The text to translate" : "متن برای ترجمه", + "Origin language" : "زبان مبدأ", + "The language of the origin text" : "زبان متن مبدأ", + "Target language" : "زبان مقصد", + "The desired language to translate the origin text in" : "زبان مورد نظر برای ترجمه متن مبدأ", + "Result" : "نتیجه", + "The translated text" : "متن ترجمه شده", + "Free prompt" : "درخواست آزاد", + "Runs an arbitrary prompt through the language model." : "یک درخواست دلخواه را از طریق مدل زبانی اجرا میکند.", + "Generate headline" : "تولید عنوان", + "Summarizes text by reducing its length without losing key information." : "متن را با کاهش طول آن و بدون از دست دادن اطلاعات کلیدی، خلاصهسازی میکند.", + "Extracts topics from a text and outputs them separated by commas." : "موضوعات را از یک متن استخراج کرده و با کاما جدا شده خروجی میدهد.", + "Organisation" : "سازمان", "File is currently busy, please try again later" : "فایل در حال حاضر مشغول است، لطفا مجددا تلاش کنید", "Cannot download file" : "نمیتوان پرونده را بارگرفت", - "Your data directory is readable by other users." : "Your data directory is readable by other users.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "لطفاً مجوزها را به 0770 تغییر دهید تا فهرست توسط سایر کاربران فهرست نشود.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "اطمینان حاصل کنید که فایلی به نام \".ocdata\" در ریشه دایرکتوری داده وجود دارد." + "Login is too long" : "نام کاربری بیش از حد طولانی است" }, "nplurals=2; plural=(n > 1);"); diff --git a/lib/l10n/fa.json b/lib/l10n/fa.json index 3f5d2509f01..238a1503b53 100644 --- a/lib/l10n/fa.json +++ b/lib/l10n/fa.json @@ -1,25 +1,27 @@ { "translations": { "Cannot write into \"config\" directory!" : "نمیتوانید داخل دایرکتوری \"config\" تغییراتی ایجاد کنید", - "This can usually be fixed by giving the web server write access to the config directory." : "This can usually be fixed by giving the web server write access to the config directory.", - "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it.", + "This can usually be fixed by giving the web server write access to the config directory." : "این مشکل معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری پیکربندی قابل رفع است.", + "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "اما، اگر ترجیح میدهید فایل config.php فقط خواندنی باشد، گزینه \"config_is_read_only\" را در آن به true تنظیم کنید.", "See %s" : "مشاهده %s", - "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory.", + "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "برنامه %1$s موجود نیست یا نسخهای ناسازگار با این سرور دارد. لطفاً دایرکتوری برنامهها را بررسی کنید.", "Sample configuration detected" : "فایل پیکربندی نمونه پیدا شد", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "تشخیص داده شده است که پیکربندی نمونه کپی شده است. این می تواند نصب شما را خراب کند و پشتیبانی نمی شود. لطفاً قبل از انجام تغییرات در config.php ، اسناد را بخوانید", - "The page could not be found on the server." : "The page could not be found on the server.", - "%s email verification" : "%s email verification", - "Email verification" : "Email verification", - "Click the following button to confirm your email." : "Click the following button to confirm your email.", - "Click the following link to confirm your email." : "Click the following link to confirm your email.", - "Confirm your email" : "Confirm your email", + "The page could not be found on the server." : "صفحه در سرور یافت نشد.", + "%s email verification" : "تأیید ایمیل %s", + "Email verification" : "تأیید ایمیل", + "Click the following button to confirm your email." : "برای تأیید ایمیل خود روی دکمه زیر کلیک کنید.", + "Click the following link to confirm your email." : "برای تأیید ایمیل خود روی لینک زیر کلیک کنید.", + "Confirm your email" : "ایمیل خود را تأیید کنید", "Other activities" : "سایر فعالیت ها", - "%1$s and %2$s" : "%1$sو%2$s", - "%1$s, %2$s and %3$s" : "%1$s،%2$sو%3$s", - "%1$s, %2$s, %3$s and %4$s" : "%1$s،%2$s،%3$sو%4$s", - "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s،%2$s،%3$s،%4$sو%5$s", + "%1$s and %2$s" : "%1$s و %2$s", + "%1$s, %2$s and %3$s" : "%1$s، %2$s و %3$s", + "%1$s, %2$s, %3$s and %4$s" : "%1$s، %2$s، %3$s و %4$s", + "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s، %2$s، %3$s، %4$s و %5$s", + "Education bundle" : "بسته آموزشی", "Enterprise bundle" : "بستهٔ سازمانی", "Groupware bundle" : "بستهٔ کار گروهی", "Hub bundle" : "بستهٔ هستهای", + "Public sector bundle" : "بسته بخش عمومی", "Social sharing bundle" : "بستهٔ همرسانی اجتماعی", "PHP %s or higher is required." : "PHP نسخهی %s یا بالاتر نیاز است.", "PHP with a version lower than %s is required." : "نیاز به نگارش پایینتر از %s پیاچپی.", @@ -33,25 +35,34 @@ "The following platforms are supported: %s" : "بنسازههای زیر پشتیبانی میشوند: %s", "Server version %s or higher is required." : "نیاز به کارساز با نگارش %s یا بالاتر.", "Server version %s or lower is required." : "نیاز به کارساز با نگارش %s یا پایینتر.", - "Wiping of device %s has started" : "پاک کردن دستگاه%s شروع شده است", - "Wiping of device »%s« has started" : "پاک کردن دستگاه%s شروع شده است", - "»%s« started remote wipe" : "%sپاک کردن از راه دور", - "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "دستگاه یا برنامه%s فرآیند پاک کردن از راه دور را آغاز کرده است. پس از اتمام مراحل ، ایمیل دیگری دریافت خواهید کرد", - "Wiping of device %s has finished" : "پاک کردن دستگاه %sبه پایان رسیده است", - "Wiping of device »%s« has finished" : "پاک کردن دستگاه %sبه پایان رسیده است", - "»%s« finished remote wipe" : "%sپاک کردن از راه دور", - "Device or application »%s« has finished the remote wipe process." : "دستگاه یا برنامه %sفرآیند پاک کردن از راه دور را به پایان رسانده است.", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "حساب وارد شده باید یک مدیر، یک مدیر فرعی یا دارای حق دسترسی ویژه برای دسترسی به این تنظیم باشد", + "Your current IP address doesn't allow you to perform admin actions" : "آدرس IP فعلی شما اجازه انجام اقدامات مدیریتی را به شما نمیدهد", + "Logged in account must be an admin or sub admin" : "حساب وارد شده باید یک مدیر یا مدیر فرعی باشد", + "Logged in account must be an admin" : "حساب وارد شده باید یک مدیر باشد", + "Wiping of device %s has started" : "پاک کردن دستگاه %s آغاز شد", + "Wiping of device »%s« has started" : "پاک کردن دستگاه «%s» آغاز شد", + "»%s« started remote wipe" : "«%s» پاک کردن از راه دور را آغاز کرد", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "دستگاه یا برنامه «%s» فرآیند پاک کردن از راه دور را آغاز کرده است. پس از اتمام مراحل، ایمیل دیگری دریافت خواهید کرد.", + "Wiping of device %s has finished" : "پاک کردن دستگاه %s به پایان رسید", + "Wiping of device »%s« has finished" : "پاک کردن دستگاه «%s» به پایان رسید", + "»%s« finished remote wipe" : "«%s» پاک کردن از راه دور را به پایان رساند", + "Device or application »%s« has finished the remote wipe process." : "دستگاه یا برنامه «%s» فرآیند پاک کردن از راه دور را به پایان رسانده است.", "Remote wipe started" : "پاک کردن از راه دور شروع شد", - "A remote wipe was started on device %s" : "پاک کردن از راه دور روی دستگاه شروع شد%s", + "A remote wipe was started on device %s" : "پاک کردن از راه دور روی دستگاه %s شروع شد", "Remote wipe finished" : "پاک کردن از راه دور به پایان رسید", - "The remote wipe on %s has finished" : "پاک کردن از راه دور روی%s کار تمام شد", + "The remote wipe on %s has finished" : "پاک کردن از راه دور روی %s کار تمام شد", "Authentication" : "احراز هویت", "Unknown filetype" : "نوع فایل ناشناخته", "Invalid image" : "عکس نامعتبر", "Avatar image is not square" : "تصویر آواتار مربع نیست", "Files" : "پوشهها", "View profile" : "مشاهدهٔ نمایه", - "Local time: %s" : "Local time: %s", + "same time" : "همزمان", + "_%nh_::_%nh_" : ["%n ساعت","%n ساعت"], + "_%nm_::_%nm_" : ["%n دقیقه","%n دقیقه"], + "%s ahead" : "%s جلوتر", + "%s behind" : "%s عقبتر", + "Local time: %s" : "زمان محلی: %s", "today" : "امروز", "tomorrow" : "فردا", "yesterday" : "دیروز", @@ -72,13 +83,37 @@ "in a few seconds" : "در چند ثانیه", "seconds ago" : "ثانیهها پیش", "Empty file" : "پروندهٔ خالی", - "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ماژول با شناسه:%s وجود ندارد. لطفاً آن را در تنظیمات برنامه خود فعال کنید یا با سرپرست خود تماس بگیرید", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ماژول با شناسه: %s وجود ندارد. لطفاً آن را در تنظیمات برنامه خود فعال کنید یا با سرپرست خود تماس بگیرید.", + "No file conversion providers available" : "ارائهدهنده تبدیل فایل در دسترس نیست", + "File is too large to convert" : "فایل برای تبدیل خیلی بزرگ است", + "Destination does not match conversion extension" : "مقصد با پسوند تبدیل مطابقت ندارد", + "Could not convert file" : "فایل قابل تبدیل نبود", + "Destination does not exist" : "مقصد وجود ندارد", + "Destination is not creatable" : "مقصد قابل ایجاد نیست", "Dot files are not allowed" : "پروندههای نقطهدار مجاز نیستند", + "%1$s (renamed)" : "%1$s (تغییر نام داده شد)", + "renamed file" : "فایل تغییر نام داده شد", + "\"%1$s\" is a forbidden file or folder name." : "«%1$s» یک نام فایل یا پوشه ممنوع است.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "«%1$s» یک پیشوند ممنوع برای نام فایل یا پوشه است.", + "\"%1$s\" is not allowed inside a file or folder name." : "«%1$s» در نام فایل یا پوشه مجاز نیست.", + "\"%1$s\" is a forbidden file type." : "«%1$s» یک نوع فایل ممنوع است.", + "Filenames must not end with \"%1$s\"." : "نام فایلها نباید با «%1$s» به پایان برسند.", + "Invalid parent path" : "مسیر والد نامعتبر", "File already exists" : "پرونده از پیش موجود است", "Invalid path" : "مسیر نامعتبر", "Failed to create file from template" : "شکست در ایجاد پرونده از قالب", "Templates" : "قالبها", + "Storage %s cannot be moved" : "حافظه %s قابل جابجایی نیست", + "Moving a share (%s) into a shared folder is not allowed" : "انتقال یک اشتراک (%s) به یک پوشه مشترک مجاز نیست", + "Moving a storage (%s) into a shared folder is not allowed" : "انتقال یک حافظه (%s) به یک پوشه مشترک مجاز نیست", + "Moving a share (%s) into another share (%s) is not allowed" : "انتقال یک اشتراک (%s) به اشتراک دیگر (%s) مجاز نیست", + "Moving a share (%s) into another storage (%s) is not allowed" : "انتقال یک اشتراک (%s) به حافظه دیگر (%s) مجاز نیست", + "Moving a storage (%s) into a share (%s) is not allowed" : "انتقال یک حافظه (%s) به یک اشتراک (%s) مجاز نیست", + "Moving a storage (%s) into another storage (%s) is not allowed" : "انتقال یک حافظه (%s) به حافظه دیگر (%s) مجاز نیست", + "Path contains invalid segments" : "مسیر شامل بخشهای نامعتبر است", + "Filename is a reserved word" : "نام فایل یک کلمه رزرو شده است", "Filename contains at least one invalid character" : "نام فایل حداقل دارای یک کاراکتر نامعتبر است", + "Filename is too long" : "نام فایل بیش از حد طولانی است", "Empty filename is not allowed" : "نام فایل نمیتواند خالی باشد", "App \"%s\" cannot be installed because appinfo file cannot be read." : "کارهٔ «%s» به دلیل ناتوانی در خواندن پروندهٔ appinfo نمیتواند نصب شود.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "کارهٔ «%s» به دلیل سازگار نبودن با این نگارش از کارساز نمیتواند نصب شود.", @@ -94,8 +129,8 @@ "Accounts" : "حسابها", "Email" : "رایانامه", "Mail %s" : "نامه به %s", - "Fediverse" : "Fediverse", - "View %s on the fediverse" : "View %s on the fediverse", + "Fediverse" : "فدیورس", + "View %s on the fediverse" : "مشاهده %s در فدیورس", "Phone" : "تلفن", "Call %s" : "تماس با %s", "Twitter" : "توییتر", @@ -105,37 +140,87 @@ "Address" : "نشانی", "Profile picture" : "تصویر نمایه", "About" : "درباره", - "Display name" : "Display name", + "Display name" : "نام نمایشی", "Headline" : "عنوان", - "Organisation" : "سازمان", + "Organization" : "سازمانی", "Role" : "نقش", + "Pronouns" : "ضمایر", + "Unknown account" : "حساب ناشناخته", "Additional settings" : "تنظیمات اضافی", + "Enter the database Login and name for %s" : "نام کاربری و نام پایگاه داده را برای %s وارد کنید", + "Enter the database Login for %s" : "نام کاربری پایگاه داده را برای %s وارد کنید", "Enter the database name for %s" : "ورود نام پایگاه داده برای %s", "You cannot use dots in the database name %s" : "نمیتوانید در در نام پایگاه دادهٔ %s از نقطه استفاده کنید", + "MySQL Login and/or password not valid" : "نام کاربری و/یا رمز عبور MySQL نامعتبر است", "You need to enter details of an existing account." : "لازم است جزییات یک حساب موحود را وارد کنید.", "Oracle connection could not be established" : "ارتباط اراکل نمیتواند برقرار باشد.", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "مکاواس ۱۰ پشتیبانی نشده و %s روی این بنسازه درست کار نخواهد کرد. با مسئولیت خودتان استفاده کنید!", + "Oracle Login and/or password not valid" : "نام کاربری و/یا رمز عبور Oracle نامعتبر است", + "PostgreSQL Login and/or password not valid" : "نام کاربری و/یا رمز عبور PostgreSQL نامعتبر است", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X پشتیبانی نمیشود و %s روی این پلتفرم به درستی کار نخواهد کرد. با مسئولیت خودتان از آن استفاده کنید!", "For the best results, please consider using a GNU/Linux server instead." : "برای بهترین نتیجه، استفاده از یک کارساز گنو/لینوکسی را در نظر داشته باشید.", - "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "به نظر می رسد%s که این نمونه در یک محیط PHP 32 بیتی در حال اجرا است و open_baseir در php.ini پیکربندی شده است. این مسئله به پرونده هایی با بیش از 4 گیگ منجر می شود و بسیار دلسرد می شود", - "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "لطفاً تنظیمات open_baseir را درون php.ini خود حذف کنید یا به PHP 64 بیتی تغییر دهید.", + "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "به نظر می رسد %s که این نمونه در یک محیط PHP 32 بیتی در حال اجرا است و open_basedir در php.ini پیکربندی شده است. این مسئله به پرونده هایی با بیش از 4 گیگ منجر می شود و بسیار دلسرد می شود.", + "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "لطفاً تنظیمات open_basedir را درون php.ini خود حذف کنید یا به PHP 64 بیتی تغییر دهید.", + "Set an admin Login." : "یک نام کاربری برای مدیر تنظیم کنید.", "Set an admin password." : "یک رمزعبور برای مدیر تنظیم نمایید.", - "Cannot create or write into the data directory %s" : "Cannot create or write into the data directory %s", - "Sharing backend %s must implement the interface OCP\\Share_Backend" : "به اشتراک گذاشتن باطن باید رابط OCP \\ Share_Backend %sرا پیاده سازی کند", - "Sharing backend %s not found" : "به اشتراک گذاشتن باطن%s یافت نشد", - "Sharing backend for %s not found" : "به اشتراک گذاشتن باطن برای%s یافت نشد", - "Click the button below to open it." : "برای باز کردن آن روی دکمه زیر کلیک کنید.", + "Cannot create or write into the data directory %s" : "نمیتوان در دایرکتوری داده %s ایجاد یا نوشت", + "Sharing backend %s must implement the interface OCP\\Share_Backend" : "بکاند اشتراکگذاری %s باید رابط OCP\\Share_Backend را پیادهسازی کند", + "Sharing backend %s not found" : "بکاند اشتراکگذاری %s یافت نشد", + "Sharing backend for %s not found" : "بکاند اشتراکگذاری برای %s یافت نشد", + "%1$s shared %2$s with you" : "%1$s %2$s را با شما به اشتراک گذاشت", + "Open %s" : "باز کردن %s", "%1$s via %2$s" : "%1$s از طریق %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s %2$s را با شما به اشتراک گذاشت و میخواهد اضافه کند:", + "%1$s shared %2$s with you and wants to add" : "%1$s %2$s را با شما به اشتراک گذاشت و میخواهد اضافه کند", + "%s added a note to a file shared with you" : "%s یک یادداشت به فایلی که با شما به اشتراک گذاشته شده است اضافه کرد", + "Passwords are enforced for link and mail shares" : "رمزهای عبور برای اشتراکگذاری لینک و ایمیل اجباری هستند", + "Share recipient is not a valid user" : "گیرنده اشتراک یک کاربر معتبر نیست", + "Share recipient is not a valid group" : "گیرنده اشتراک یک گروه معتبر نیست", + "Share recipient should be empty" : "گیرنده اشتراک باید خالی باشد", + "Share recipient should not be empty" : "گیرنده اشتراک نباید خالی باشد", + "Share recipient is not a valid circle" : "گیرنده اشتراک یک دایره معتبر نیست", "Unknown share type" : "نوع اشتراک ناشناخته", - "You are not allowed to share %s" : "شما مجاز به اشتراک گذاری نیستید%s", - "Cannot increase permissions of %s" : "Cannot increase permissions of %s", - "Files cannot be shared with delete permissions" : "Files cannot be shared with delete permissions", - "Files cannot be shared with create permissions" : "Files cannot be shared with create permissions", + "Share initiator must be set" : "شروعکننده اشتراک باید تنظیم شود", + "Cannot share with yourself" : "نمیتوانید با خودتان به اشتراک بگذارید", + "Shared path must be set" : "مسیر مشترک باید تنظیم شود", + "Shared path must be either a file or a folder" : "مسیر مشترک باید یک فایل یا یک پوشه باشد", + "You cannot share your root folder" : "نمیتوانید پوشه ریشه خود را به اشتراک بگذارید", + "You are not allowed to share %s" : "شما مجاز به اشتراک گذاری %s نیستید", + "Valid permissions are required for sharing" : "مجوزهای معتبر برای اشتراکگذاری لازم است", + "File shares cannot have create or delete permissions" : "اشتراکگذاری فایلها نمیتواند مجوزهای ایجاد یا حذف داشته باشد", + "Cannot increase permissions of %s" : "نمیتوان مجوزهای %s را افزایش داد", + "Shares need at least read permissions" : "اشتراکگذاریها حداقل به مجوزهای خواندن نیاز دارند", + "Files cannot be shared with delete permissions" : "فایلها را نمیتوان با مجوزهای حذف به اشتراک گذاشت", + "Files cannot be shared with create permissions" : "فایلها را نمیتوان با مجوزهای ایجاد به اشتراک گذاشت", "Expiration date is in the past" : "تاریخ انقضا در گذشته است", - "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Cannot set expiration date more than %n day in the future","Cannot set expiration date more than %n days in the future"], - "Sharing is only allowed with group members" : "Sharing is only allowed with group members", + "Expiration date is enforced" : "تاریخ انقضا اجباری است", + "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["نمیتوان تاریخ انقضا را بیش از %n روز در آینده تنظیم کرد","نمیتوان تاریخ انقضا را بیش از %n روز در آینده تنظیم کرد"], + "Sharing is only allowed with group members" : "اشتراکگذاری فقط با اعضای گروه مجاز است", + "Sharing %s failed, because this item is already shared with the account %s" : "اشتراکگذاری %s ناموفق بود، زیرا این مورد قبلاً با حساب %s به اشتراک گذاشته شده است", + "Group sharing is now allowed" : "اشتراکگذاری گروهی اکنون مجاز است", + "Sharing is only allowed within your own groups" : "اشتراکگذاری فقط در گروههای خودتان مجاز است", + "Path is already shared with this group" : "این مسیر قبلاً با این گروه به اشتراک گذاشته شده است", + "Link sharing is not allowed" : "اشتراکگذاری لینک مجاز نیست", + "Public upload is not allowed" : "بارگذاری عمومی مجاز نیست", + "You cannot share a folder that contains other shares" : "نمیتوانید پوشهای را به اشتراک بگذارید که حاوی اشتراکهای دیگر است", + "Sharing is disabled" : "اشتراکگذاری غیرفعال است", + "Sharing is disabled for you" : "اشتراکگذاری برای شما غیرفعال است", + "Cannot share with the share owner" : "نمیتوان با صاحب اشتراک به اشتراک گذاشت", + "Share does not have a full ID" : "اشتراک شناسه کامل ندارد", + "Cannot change share type" : "نمیتوان نوع اشتراک را تغییر داد", + "Can only update recipient on user shares" : "فقط میتوان گیرنده را در اشتراکهای کاربر بهروزرسانی کرد", + "Cannot enable sending the password by Talk with an empty password" : "نمیتوان ارسال رمز عبور از طریق Talk را با رمز عبور خالی فعال کرد", + "Cannot enable sending the password by Talk without setting a new password" : "نمیتوان ارسال رمز عبور از طریق Talk را بدون تنظیم رمز عبور جدید فعال کرد", + "Cannot disable sending the password by Talk without setting a new password" : "نمیتوان ارسال رمز عبور از طریق Talk را بدون تنظیم رمز عبور جدید غیرفعال کرد", + "Share provider does not support accepting" : "ارائهدهنده اشتراک از پذیرش پشتیبانی نمیکند", + "Cannot change target of link share" : "نمیتوان مقصد اشتراک لینک را تغییر داد", + "Invalid share recipient" : "گیرنده اشتراک نامعتبر است", + "Group \"%s\" does not exist" : "گروه «%s» وجود ندارد", "The requested share does not exist anymore" : "سهم درخواست شده دیگر وجود ندارد", - "The user was not created because the user limit has been reached. Check your notifications to learn more." : "The user was not created because the user limit has been reached. Check your notifications to learn more.", + "The requested share comes from a disabled user" : "اشتراک درخواستی از یک کاربر غیرفعال است", + "The user was not created because the user limit has been reached. Check your notifications to learn more." : "کاربر ایجاد نشد زیرا محدودیت کاربر به پایان رسیده است. برای اطلاعات بیشتر اعلانهای خود را بررسی کنید.", "Could not find category \"%s\"" : "دسته بندی %s یافت نشد", + "Input text" : "متن ورودی", + "The input text" : "متن ورودی", "Sunday" : "یکشنبه", "Monday" : "دوشنبه", "Tuesday" : "سهشنبه", @@ -182,6 +267,15 @@ "Nov." : "نو.", "Dec." : "دس.", "A valid password must be provided" : "رمز عبور صحیح باید وارد شود", + "The Login is already being used" : "نام کاربری قبلاً استفاده شده است", + "Could not create account" : "حساب کاربری ایجاد نشد", + "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "فقط کاراکترهای زیر در نام کاربری مجاز هستند: \"a-z\", \"A-Z\", \"0-9\", فاصله و \"_.@-'\"", + "A valid Login must be provided" : "یک نام کاربری معتبر باید ارائه شود", + "Login contains whitespace at the beginning or at the end" : "نام کاربری حاوی فاصله در ابتدا یا انتها است", + "Login must not consist of dots only" : "نام کاربری نباید فقط از نقطه تشکیل شده باشد", + "Username is too long" : "نام کاربری بیش از حد طولانی است", + "Login is invalid because files already exist for this user" : "نام کاربری نامعتبر است زیرا فایلها برای این کاربر از قبل وجود دارند", + "Account disabled" : "حساب کاربری غیرفعال است", "Login canceled by app" : "ورود به دست کاره لغو شد", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "کارهٔ «%1$s» نمیتواند نصب شود؛ چرا که وابستگی زیر تأمین نشده: %2$s", "a safe home for all your data" : "خانهای امن برای تمامی دادههایتان", @@ -189,93 +283,174 @@ "Authentication error" : "خطا در اعتبار سنجی", "Token expired. Please reload page." : "Token منقضی شده است. لطفا دوباره صفحه را بارگذاری نمایید.", "No database drivers (sqlite, mysql, or postgresql) installed." : "هیچ درایور پایگاه داده (sqlite ، mysql یا postgresql) نصب نشده است.", - "Cannot write into \"config\" directory." : "Cannot write into \"config\" directory.", - "This can usually be fixed by giving the web server write access to the config directory. See %s" : "This can usually be fixed by giving the web server write access to the config directory. See %s", - "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "یا اگر ترجیح می دهید پرونده config.php را فقط بخوانید ، گزینه \"config_is_read_only\" را در آن تنظیم کنید. دیدن%s", - "Cannot write into \"apps\" directory." : "Cannot write into \"apps\" directory.", - "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file.", - "Cannot create \"data\" directory." : "Cannot create \"data\" directory.", - "This can usually be fixed by giving the web server write access to the root directory. See %s" : "This can usually be fixed by giving the web server write access to the root directory. See %s", - "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Permissions can usually be fixed by giving the web server write access to the root directory. See %s.", - "Your data directory is not writable." : "Your data directory is not writable.", - "Setting locale to %s failed." : "Setting locale to %s failed.", - "Please install one of these locales on your system and restart your web server." : "Please install one of these locales on your system and restart your web server.", + "Cannot write into \"config\" directory." : "نمیتوان در دایرکتوری «config» نوشت.", + "This can usually be fixed by giving the web server write access to the config directory. See %s" : "این مشکل معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری پیکربندی قابل رفع است. مشاهده %s", + "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "یا اگر ترجیح میدهید فایل config.php فقط خواندنی باشد، گزینه \"config_is_read_only\" را در آن به true تنظیم کنید. مشاهده %s", + "Cannot write into \"apps\" directory." : "نمیتوان در دایرکتوری «apps» نوشت.", + "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "این مشکل معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری برنامهها یا غیرفعال کردن فروشگاه برنامه در فایل پیکربندی قابل رفع است.", + "Cannot create \"data\" directory." : "نمیتوان دایرکتوری «data» را ایجاد کرد.", + "This can usually be fixed by giving the web server write access to the root directory. See %s" : "این مشکل معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری ریشه قابل رفع است. مشاهده %s", + "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "مجوزها معمولاً با دادن دسترسی نوشتن به وبسرور در دایرکتوری ریشه قابل رفع هستند. مشاهده %s.", + "Your data directory is not writable." : "دایرکتوری داده شما قابل نوشتن نیست.", + "Setting locale to %s failed." : "تنظیم محلی به %s ناموفق بود.", + "Please install one of these locales on your system and restart your web server." : "لطفاً یکی از این محلیها را روی سیستم خود نصب کرده و وبسرور خود را مجدداً راهاندازی کنید.", "PHP module %s not installed." : "ماژول PHP %s نصب نشده است.", "Please ask your server administrator to install the module." : "لطفا از مدیر سیستم بخواهید تا ماژول را نصب کند.", - "PHP setting \"%s\" is not set to \"%s\"." : "تنظیمات PHP%s تنظیم نشده است%s", + "PHP setting \"%s\" is not set to \"%s\"." : "تنظیمات PHP «%s» روی «%s» تنظیم نشده است.", "Adjusting this setting in php.ini will make Nextcloud run again" : "تنظیم این تنظیمات در php.ini باعث می شود Nextcloud دوباره اجرا شود", - "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>.", - "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini.", - "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ظاهراً برای خنثی کردن بلوک های اسناد درون خطی تنظیم شده است. این کار چندین برنامه اصلی را غیرقابل دسترسی خواهد کرد.", - "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "این احتمالاً توسط حافظه پنهان / کش مانند Zend OPcache یا eAccelerator ایجاد شده است.", - "PHP modules have been installed, but they are still listed as missing?" : "ماژول های پی اچ پی نصب شده اند ، اما هنوز هم به عنوان مفقود شده ذکر شده اند؟", - "Please ask your server administrator to restart the web server." : "لطفاً از سرور سرور خود بخواهید که وب سرور را مجدداً راه اندازی کند.", - "The required %s config variable is not configured in the config.php file." : "The required %s config variable is not configured in the config.php file.", - "Please ask your server administrator to check the Nextcloud configuration." : "Please ask your server administrator to check the Nextcloud configuration.", - "Your data directory must be an absolute path." : "Your data directory must be an absolute path.", - "Check the value of \"datadirectory\" in your configuration." : "Check the value of \"datadirectory\" in your configuration.", - "Your data directory is invalid." : "Your data directory is invalid.", - "Action \"%s\" not supported or implemented." : "عملی%s پشتیبانی یا اجرا نشده است.", - "Authentication failed, wrong token or provider ID given" : "تأیید اعتبار انجام نشد ، نشانه اشتباه یا شناسه ارائه دهنده داده شد", - "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "پارامترهای موجود برای تکمیل درخواست. پارامترهای موجود نیست%s", - "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "شناسه%1$s قبلاً توسط ارائه دهنده فدراسیون ابر استفاده شده است%2$s", - "Cloud Federation Provider with ID: \"%s\" does not exist." : "ارائه دهنده فدراسیون Cloud با شناسه:%s وجود ندارد.", - "Could not obtain lock type %d on \"%s\"." : "نمی توان نوع%d قفل را به دست آورد%s", - "Storage unauthorized. %s" : "ذخیره سازی غیر مجاز.%s", - "Storage incomplete configuration. %s" : "پیکربندی ناقص ذخیره سازی.%s<br>", - "Storage connection error. %s" : "خطای اتصال ذخیره سازی%s", - "Storage is temporarily not available" : "ذخیره سازی به طور موقت در دسترس نیست", - "Storage connection timeout. %s" : "مدت زمان اتصال ذخیره سازی%s", - "Confirmation" : "Confirmation", - "Prompt" : "Prompt", - "Chat" : "Chat", - "Generates a possible headline for a text." : "Generates a possible headline for a text.", - "Summarize" : "Summarize", + "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> به جای مقدار مورد انتظار <code>0</code> روی <code>%s</code> تنظیم شده است.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "برای رفع این مشکل، <code>mbstring.func_overload</code> را در php.ini خود روی <code>0</code> تنظیم کنید.", + "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP ظاهراً برای حذف بلوکهای مستندات درونخطی تنظیم شده است. این کار چندین برنامه اصلی را غیرقابل دسترس خواهد کرد.", + "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "این احتمالاً توسط حافظه پنهان/شتابدهندهای مانند Zend OPcache یا eAccelerator ایجاد شده است.", + "PHP modules have been installed, but they are still listed as missing?" : "ماژولهای PHP نصب شدهاند، اما همچنان به عنوان گمشده لیست شدهاند؟", + "Please ask your server administrator to restart the web server." : "لطفاً از مدیر سرور خود بخواهید که وبسرور را مجدداً راهاندازی کند.", + "The required %s config variable is not configured in the config.php file." : "متغیر پیکربندی مورد نیاز %s در فایل config.php پیکربندی نشده است.", + "Please ask your server administrator to check the Nextcloud configuration." : "لطفاً از مدیر سرور خود بخواهید پیکربندی Nextcloud را بررسی کند.", + "Your data directory is readable by other people." : "دایرکتوری داده شما برای دیگران قابل خواندن است.", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "لطفاً مجوزها را به 0770 تغییر دهید تا دایرکتوری توسط افراد دیگر قابل فهرست شدن نباشد.", + "Your data directory must be an absolute path." : "دایرکتوری داده شما باید یک مسیر مطلق باشد.", + "Check the value of \"datadirectory\" in your configuration." : "مقدار \"datadirectory\" را در پیکربندی خود بررسی کنید.", + "Your data directory is invalid." : "دایرکتوری داده شما نامعتبر است.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "اطمینان حاصل کنید که فایلی به نام «%1$s» در ریشه دایرکتوری داده وجود دارد. این فایل باید حاوی: «%2$s» باشد", + "Action \"%s\" not supported or implemented." : "عملیات «%s» پشتیبانی یا اجرا نشده است.", + "Authentication failed, wrong token or provider ID given" : "تأیید اعتبار انجام نشد، نشانه اشتباه یا شناسه ارائه دهنده داده شد", + "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "پارامترهای مورد نیاز برای تکمیل درخواست وجود ندارند. پارامترهای از دست رفته: «%s»", + "ID \"%1$s\" already used by cloud federation provider \"%2$s\"" : "شناسه «%1$s» قبلاً توسط ارائهدهنده فدراسیون ابری «%2$s» استفاده شده است", + "Cloud Federation Provider with ID: \"%s\" does not exist." : "ارائهدهنده فدراسیون ابری با شناسه: «%s» وجود ندارد.", + "Could not obtain lock type %d on \"%s\"." : "نمیتوان قفل از نوع %d را روی «%s» به دست آورد.", + "Storage unauthorized. %s" : "دسترسی به حافظه غیرمجاز است. %s", + "Storage incomplete configuration. %s" : "پیکربندی حافظه ناقص است. %s", + "Storage connection error. %s" : "خطای اتصال حافظه. %s", + "Storage is temporarily not available" : "حافظه به طور موقت در دسترس نیست", + "Storage connection timeout. %s" : "مهلت اتصال حافظه به پایان رسید. %s", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "برای اجرای این بررسی، باید مطمئن شوید که وبسرور شما میتواند به خودش متصل شود. بنابراین باید بتواند حداقل یکی از `trusted_domains` یا `overwrite.cli.url` خود را حل و به آن متصل شود. این خطا ممکن است نتیجه عدم تطابق DNS سمت سرور یا قانون فایروال خروجی باشد.", + "Transcribe audio" : "رونوشت صوتی", + "Transcribe the things said in an audio" : "رونوشت چیزهای گفته شده در یک فایل صوتی", + "Audio input" : "ورودی صوتی", + "The audio to transcribe" : "فایل صوتی برای رونوشت", + "Transcription" : "رونوشت", + "The transcribed text" : "متن رونوشت شده", + "Chat with an agent" : "چت با یک عامل", + "Chat message" : "پیام چت", + "A chat message to send to the agent." : "یک پیام چت برای ارسال به عامل.", + "Confirmation" : "تأیید", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "آیا اقدامات قبلاً درخواست شده را تأیید کنید: 0 برای رد و 1 برای تأیید.", + "Conversation token" : "توکن مکالمه", + "A token representing the conversation." : "یک توکن نماینده مکالمه.", + "Generated response" : "پاسخ تولید شده", + "The response from the chat model." : "پاسخ از مدل چت.", + "The new conversation token" : "توکن مکالمه جدید", + "Send this along with the next interaction." : "این را همراه با تعامل بعدی ارسال کنید.", + "Requested actions by the agent" : "اقدامات درخواستی توسط عامل", + "Actions that the agent would like to carry out in JSON format." : "اقدامات که عامل مایل به انجام آنها در قالب JSON است.", + "Context write" : "نوشتن متنی", + "Writes text in a given style based on the provided source material." : "متن را با سبکی مشخص بر اساس محتوای منبع ارائه شده مینویسد.", + "Writing style" : "سبک نگارش", + "Demonstrate a writing style that you would like to immitate" : "یک سبک نگارش را که میخواهید تقلید کنید، نشان دهید", + "Source material" : "محتوای منبع", + "The content that would like to be rewritten in the new writing style" : "محتوایی که میخواهید با سبک نگارش جدید بازنویسی شود", + "Generated text" : "متن تولید شده", + "The generated text with content from the source material in the given style" : "متن تولید شده با محتوای منبع در سبک مشخص شده", + "Emoji generator" : "تولیدکننده اموجی", + "Takes text and generates a representative emoji for it." : "متن را دریافت کرده و یک اموجی مناسب برای آن تولید میکند.", + "The text to generate an emoji for" : "متنی که میخواهید برای آن اموجی تولید شود", + "Generated emoji" : "اموجی تولید شده", + "The generated emoji based on the input text" : "اموجی تولید شده بر اساس متن ورودی", + "Generate image" : "تولید تصویر", + "Generate an image from a text prompt" : "تولید تصویر از یک متن ورودی", + "Prompt" : "درخواست", + "Describe the image you want to generate" : "تصویری که میخواهید تولید شود را توصیف کنید", + "Number of images" : "تعداد تصاویر", + "How many images to generate" : "چه تعداد تصویر تولید شود", + "Output images" : "تصاویر خروجی", + "The generated images" : "تصاویر تولید شده", + "Generate speech" : "تولید گفتار", + "Generate speech from a transcript" : "تولید گفتار از یک رونوشت", + "Write transcript that you want the assistant to generate speech from" : "رونوشتی را بنویسید که میخواهید دستیار از آن گفتار تولید کند", + "Output speech" : "گفتار خروجی", + "The generated speech" : "گفتار تولید شده", + "Free text to text prompt" : "درخواست متن به متن آزاد", + "Runs an arbitrary prompt through a language model that returns a reply" : "یک درخواست دلخواه را از طریق یک مدل زبانی اجرا میکند که پاسخی را برمیگرداند", + "Describe a task that you want the assistant to do or ask a question" : "وظیفهای که میخواهید دستیار انجام دهد را توصیف کنید یا سؤالی بپرسید", + "Generated reply" : "پاسخ تولید شده", + "The generated text from the assistant" : "متن تولید شده توسط دستیار", + "Change Tone" : "تغییر لحن", + "Change the tone of a piece of text." : "لحن یک قطعه متن را تغییر دهید.", + "Write a text that you want the assistant to rewrite in another tone." : "متنی را بنویسید که میخواهید دستیار آن را با لحن دیگری بازنویسی کند.", + "Desired tone" : "لحن مورد نظر", + "In which tone should your text be rewritten?" : "متن شما با چه لحنی بازنویسی شود؟", + "The rewritten text in the desired tone, written by the assistant:" : "متن بازنویسی شده با لحن مورد نظر، نوشته شده توسط دستیار:", + "Chat" : "چت", + "Chat with the assistant" : "چت با دستیار", + "System prompt" : "درخواست سیستمی", + "Define rules and assumptions that the assistant should follow during the conversation." : "قوانین و فرضیاتی را که دستیار باید در طول مکالمه رعایت کند، تعریف کنید.", + "Chat history" : "تاریخچه چت", + "The history of chat messages before the current message, starting with a message by the user" : "تاریخچه پیامهای چت قبل از پیام فعلی، با شروع از یک پیام توسط کاربر", + "Response message" : "پیام پاسخ", + "The generated response as part of the conversation" : "پاسخ تولید شده به عنوان بخشی از مکالمه", + "Chat with tools" : "چت با ابزارها", + "Chat with the language model with tool calling support." : "چت با مدل زبانی با پشتیبانی از فراخوانی ابزار.", + "Tool message" : "پیام ابزار", + "The result of tool calls in the last interaction" : "نتیجه فراخوانی ابزارها در تعامل قبلی", + "Available tools" : "ابزارهای موجود", + "The available tools in JSON format" : "ابزارهای موجود در قالب JSON", + "The response from the chat model" : "پاسخ از مدل چت", + "Tool calls" : "فراخوانی ابزار", + "Tools call instructions from the model in JSON format" : "دستورالعملهای فراخوانی ابزار از مدل در قالب JSON", + "Formalize text" : "رسمی کردن متن", + "Takes a text and makes it sound more formal" : "یک متن را دریافت کرده و آن را رسمیتر میکند", + "Write a text that you want the assistant to formalize" : "متنی را بنویسید که میخواهید دستیار آن را رسمی کند", + "Formalized text" : "متن رسمی شده", + "The formalized text" : "متن رسمی شده", + "Generate a headline" : "تولید یک عنوان", + "Generates a possible headline for a text." : "یک عنوان احتمالی برای یک متن تولید میکند.", + "Original text" : "متن اصلی", + "The original text to generate a headline for" : "متن اصلی برای تولید عنوان", + "The generated headline" : "عنوان تولید شده", + "Proofread" : "ویرایش", + "Proofreads a text and lists corrections" : "یک متن را ویرایش کرده و اصلاحات را لیست میکند", + "Text" : "متن", + "The text to proofread" : "متن برای ویرایش", + "Corrections" : "اصلاحات", + "The corrections that should be made in your text" : "اصلاحاتی که باید در متن شما انجام شود", + "Reformulate text" : "بازنویسی متن", + "Takes a text and reformulates it" : "یک متن را دریافت کرده و آن را بازنویسی میکند", + "Write a text that you want the assistant to reformulate" : "متنی را بنویسید که میخواهید دستیار آن را بازنویسی کند", + "Reformulated text" : "متن بازنویسی شده", + "The reformulated text, written by the assistant" : "متن بازنویسی شده، نوشته شده توسط دستیار", + "Simplify text" : "سادهسازی متن", + "Takes a text and simplifies it" : "یک متن را دریافت کرده و آن را ساده میکند", + "Write a text that you want the assistant to simplify" : "متنی را بنویسید که میخواهید دستیار آن را ساده کند", + "Simplified text" : "متن ساده شده", + "The simplified text" : "متن ساده شده", + "Summarize" : "خلاصهسازی", + "Summarizes a text" : "یک متن را خلاصهسازی میکند", + "The original text to summarize" : "متن اصلی برای خلاصهسازی", "Summary" : "چکیده", - "Extract topics" : "Extract topics", + "The generated summary" : "خلاصه تولید شده", + "Extract topics" : "استخراج موضوعات", + "Extracts topics from a text and outputs them separated by commas" : "موضوعات را از یک متن استخراج کرده و با کاما جدا شده خروجی میدهد", + "The original text to extract topics from" : "متن اصلی برای استخراج موضوعات", + "Topics" : "موضوعات", + "The list of extracted topics" : "لیست موضوعات استخراج شده", "Translate" : "ترجمه", - "Target language" : "Target language", - "Result" : "شروع به اسکنیک", - "Free prompt" : "Free prompt", - "Runs an arbitrary prompt through the language model." : "Runs an arbitrary prompt through the language model.", - "Generate headline" : "Generate headline", - "Summarizes text by reducing its length without losing key information." : "Summarizes text by reducing its length without losing key information.", - "Extracts topics from a text and outputs them separated by commas." : "Extracts topics from a text and outputs them separated by commas.", - "Education Edition" : "نگارش آموزشی", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Logged in user must be an admin, a sub admin or gotten special right to access this setting", - "Logged in user must be an admin or sub admin" : "ورود به سیستم کاربر باید یک مدیر یا مدیر فرعی باشد", - "Logged in user must be an admin" : "ورود به سیستم کاربر باید مدیر سایت باشد", - "File name is a reserved word" : "این نام فایل جزو کلمات رزرو میباشد", - "File name contains at least one invalid character" : "نام فایل دارای حداقل یک کاراکتر نامعتبر است", - "File name is too long" : "نام فایل خیلی بزرگ است", - "Help" : "راهنما", - "Users" : "کاربران", - "Unknown user" : "کاربر نامعلوم", - "Enter the database username and name for %s" : "ورود نام و نام کاربری پایگاه داده برای %s", - "Enter the database username for %s" : "ورود نام کاربری پایگاه داده برای %s", - "MySQL username and/or password not valid" : "نام کاربری یا گذرواژهٔ مایسکول معتبر نیست", - "Oracle username and/or password not valid" : "نام کاربری و / یا رمزعبور اراکل معتبر نیست.", - "PostgreSQL username and/or password not valid" : "PostgreSQL نام کاربری و / یا رمزعبور معتبر نیست.", - "Set an admin username." : "یک نام کاربری برای مدیر تنظیم نمایید.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s به اشتراک گذاشته شده »%2$s« با شماست و می خواهد اضافه کند:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s به اشتراک گذاشته شده »%2$s« با شماست و می خواهد اضافه کند:", - "»%s« added a note to a file shared with you" : "»%s« یادداشتی را به پرونده ای که با شما به اشتراک گذاشته شده است اضافه کرد", - "Open »%s«" : "باز کن »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Sharing %s failed, because this item is already shared with user %s", - "%1$s shared »%2$s« with you" : "%1$s به اشتراک گذاشته » %2$s« با شما", - "%1$s shared »%2$s« with you." : "%1$s به اشتراک گذاشته » %2$s« با شما", - "The username is already being used" : "نامکاربری قبلا استفاده شده است", - "Could not create user" : "نتواسنت کاربر را ایجاد کند", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"", - "A valid username must be provided" : "نام کاربری صحیح باید وارد شود", - "Username contains whitespace at the beginning or at the end" : "نام کاربری دارای فضای سفید در ابتدا یا انتهای آن است", - "Username must not consist of dots only" : "نام کاربری نباید فقط از نقاط تشکیل شده باشد", - "Username is invalid because files already exist for this user" : "Username is invalid because files already exist for this user", - "User disabled" : "کاربر از کار افتاده", + "Translate text from one language to another" : "ترجمه متن از یک زبان به زبان دیگر", + "Origin text" : "متن مبدأ", + "The text to translate" : "متن برای ترجمه", + "Origin language" : "زبان مبدأ", + "The language of the origin text" : "زبان متن مبدأ", + "Target language" : "زبان مقصد", + "The desired language to translate the origin text in" : "زبان مورد نظر برای ترجمه متن مبدأ", + "Result" : "نتیجه", + "The translated text" : "متن ترجمه شده", + "Free prompt" : "درخواست آزاد", + "Runs an arbitrary prompt through the language model." : "یک درخواست دلخواه را از طریق مدل زبانی اجرا میکند.", + "Generate headline" : "تولید عنوان", + "Summarizes text by reducing its length without losing key information." : "متن را با کاهش طول آن و بدون از دست دادن اطلاعات کلیدی، خلاصهسازی میکند.", + "Extracts topics from a text and outputs them separated by commas." : "موضوعات را از یک متن استخراج کرده و با کاما جدا شده خروجی میدهد.", + "Organisation" : "سازمان", "File is currently busy, please try again later" : "فایل در حال حاضر مشغول است، لطفا مجددا تلاش کنید", "Cannot download file" : "نمیتوان پرونده را بارگرفت", - "Your data directory is readable by other users." : "Your data directory is readable by other users.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "لطفاً مجوزها را به 0770 تغییر دهید تا فهرست توسط سایر کاربران فهرست نشود.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "اطمینان حاصل کنید که فایلی به نام \".ocdata\" در ریشه دایرکتوری داده وجود دارد." + "Login is too long" : "نام کاربری بیش از حد طولانی است" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/lib/l10n/fi.js b/lib/l10n/fi.js index fee6b4424f6..e49b4108310 100644 --- a/lib/l10n/fi.js +++ b/lib/l10n/fi.js @@ -44,6 +44,7 @@ OC.L10N.register( "Avatar image is not square" : "Avatar-kuva ei ole neliö", "Files" : "Tiedostot", "View profile" : "Näytä profiili", + "_%nh_::_%nh_" : ["%nh","%nh"], "Local time: %s" : "Paikallinen aika: %s", "today" : "tänään", "tomorrow" : "huomenna", @@ -66,6 +67,7 @@ OC.L10N.register( "seconds ago" : "sekunteja sitten", "Empty file" : "Tyhjä tiedosto", "Dot files are not allowed" : "Pistetiedostot eivät ole sallittuja", + "%1$s (renamed)" : "%1$s (nimetty uudelleen)", "File already exists" : "Tiedosto on jo olemassa", "Invalid path" : "Virheellinen polku", "Failed to create file from template" : "Tiedoston luominen mallipohjasta epäonnistui", @@ -97,20 +99,17 @@ OC.L10N.register( "About" : "Tietoja", "Display name" : "Näyttönimi", "Headline" : "Otsikko", - "Organisation" : "Organisaatio", "Role" : "Rooli", "Unknown account" : "Tuntematon tili", "Additional settings" : "Lisäasetukset", "You need to enter details of an existing account." : "Anna olemassa olevan tilin tiedot.", "Oracle connection could not be established" : "Oracle-yhteyttä ei voitu muodostaa", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X ei ole tuettu, joten %s ei toimi kunnolla tällä alustalla. Käytä omalla vastuulla!", "For the best results, please consider using a GNU/Linux server instead." : "Käytä parhaan lopputuloksen saamiseksi GNU/Linux-palvelinta.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Vaikuttaa siltä, että tämä %s-instanssi toimii 32-bittisessä PHP-ympäristössä ja open_basedir-asetus on määritetty php.ini-tiedostossa. Tämä johtaa ongelmiin yli 4 gigatavun tiedostojen kanssa, eikä siksi ole suositeltavaa.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Poista open_basedir-asetus php.ini-tiedostosta tai vaihda 64-bittiseen PHP:hen.", "Set an admin password." : "Aseta ylläpitäjän salasana.", "Sharing backend %s not found" : "Jakamisen taustaosaa %s ei löytynyt", "Sharing backend for %s not found" : "Jakamisen taustaosaa kohteelle %s ei löytynyt", - "Click the button below to open it." : "Napsauta alla olevaa painiketta avataksesi sen.", "%1$s via %2$s" : "%1$s palvelun %2$s kautta", "Unknown share type" : "Tuntematon jaon tyyppi", "You are not allowed to share %s" : "Oikeutesi eivät riitä kohteen %s jakamiseen.", @@ -210,6 +209,7 @@ OC.L10N.register( "How many images to generate" : "Kuinka monta kuvaa luodaan", "Output images" : "Valmiit kuvat", "The generated images" : "Luodut kuvat", + "Text" : "Teksti", "Summarize" : "Luo yhteenveto", "Summarizes a text" : "Luo yhteenvedon tekstistä", "The original text to summarize" : "Alkuperäinen teksti, josta yhteenveto muodostetaan", @@ -218,35 +218,8 @@ OC.L10N.register( "Translate" : "Käännä", "Target language" : "Kohdekieli", "Result" : "Tulos", - "Logged in user must be an admin" : "Sisäänkirjautuneen käyttäjän tulee olla ylläpitäjä", - "File name is a reserved word" : "Tiedoston nimi on varattu sana", - "File name contains at least one invalid character" : "Tiedoston nimi sisältää ainakin yhden virheellisen merkin", - "File name is too long" : "Tiedoston nimi on liian pitkä", - "Help" : "Ohje", - "Users" : "Käyttäjät", - "Unknown user" : "Tuntematon käyttäjä", - "MySQL username and/or password not valid" : "MySQL-käyttäjätunnus ja/tai -salasana on väärin", - "Oracle username and/or password not valid" : "Oraclen käyttäjätunnus ja/tai salasana on väärin", - "PostgreSQL username and/or password not valid" : "PostgreSQL:n käyttäjätunnus ja/tai salasana on väärin", - "Set an admin username." : "Aseta ylläpitäjän käyttäjätunnus.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s jakoi kohteen »%2$s« kanssasi ja haluaa lisätä:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s jakoi kohteen »%2$s« kanssasi ja haluaa lisätä", - "»%s« added a note to a file shared with you" : "»%s« lisäsi huomion jakamaasi tiedostoon", - "Open »%s«" : "Avaa »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", - "%1$s shared »%2$s« with you" : "%1$s jakoi kohteen »%2$s« kanssasi", - "%1$s shared »%2$s« with you." : "%1$s jakoi kohteen »%2$s« kanssasi.", - "The username is already being used" : "Käyttäjätunnus on jo käytössä", - "Could not create user" : "Ei voitu luoda käyttäjää", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Vain seuraavat merkit ovat sallittuja käyttäjätunnuksessa: \"a-z\", \"A-Z\", \"0-9\", välilyönnit ja \"_.@-'\"", - "A valid username must be provided" : "Anna kelvollinen käyttäjätunnus", - "Username contains whitespace at the beginning or at the end" : "Käyttäjätunnus sisältää tyhjätilaa joko alussa tai lopussa", - "Username must not consist of dots only" : "Käyttäjänimi ei voi koostua vain pisteistä", - "Username is invalid because files already exist for this user" : "Käyttäjänimi on virheellinen koska tiedostoja on olemassa tälle käyttäjälle", - "User disabled" : "Käyttäjä poistettu käytöstä", + "Organisation" : "Organisaatio", "File is currently busy, please try again later" : "Tiedosto on parhaillaan käytössä, yritä myöhemmin uudelleen", - "Cannot download file" : "Tiedostoa ei voi ladata", - "Your data directory is readable by other users." : "Datahakemistosi on muiden käyttäjien luettavissa.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Varmista että datahakemiston juuressa on tiedosto nimeltä \".ocdata\"." + "Cannot download file" : "Tiedostoa ei voi ladata" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/fi.json b/lib/l10n/fi.json index f6a0b76c7a9..ddd61ef1eb9 100644 --- a/lib/l10n/fi.json +++ b/lib/l10n/fi.json @@ -42,6 +42,7 @@ "Avatar image is not square" : "Avatar-kuva ei ole neliö", "Files" : "Tiedostot", "View profile" : "Näytä profiili", + "_%nh_::_%nh_" : ["%nh","%nh"], "Local time: %s" : "Paikallinen aika: %s", "today" : "tänään", "tomorrow" : "huomenna", @@ -64,6 +65,7 @@ "seconds ago" : "sekunteja sitten", "Empty file" : "Tyhjä tiedosto", "Dot files are not allowed" : "Pistetiedostot eivät ole sallittuja", + "%1$s (renamed)" : "%1$s (nimetty uudelleen)", "File already exists" : "Tiedosto on jo olemassa", "Invalid path" : "Virheellinen polku", "Failed to create file from template" : "Tiedoston luominen mallipohjasta epäonnistui", @@ -95,20 +97,17 @@ "About" : "Tietoja", "Display name" : "Näyttönimi", "Headline" : "Otsikko", - "Organisation" : "Organisaatio", "Role" : "Rooli", "Unknown account" : "Tuntematon tili", "Additional settings" : "Lisäasetukset", "You need to enter details of an existing account." : "Anna olemassa olevan tilin tiedot.", "Oracle connection could not be established" : "Oracle-yhteyttä ei voitu muodostaa", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X ei ole tuettu, joten %s ei toimi kunnolla tällä alustalla. Käytä omalla vastuulla!", "For the best results, please consider using a GNU/Linux server instead." : "Käytä parhaan lopputuloksen saamiseksi GNU/Linux-palvelinta.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Vaikuttaa siltä, että tämä %s-instanssi toimii 32-bittisessä PHP-ympäristössä ja open_basedir-asetus on määritetty php.ini-tiedostossa. Tämä johtaa ongelmiin yli 4 gigatavun tiedostojen kanssa, eikä siksi ole suositeltavaa.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Poista open_basedir-asetus php.ini-tiedostosta tai vaihda 64-bittiseen PHP:hen.", "Set an admin password." : "Aseta ylläpitäjän salasana.", "Sharing backend %s not found" : "Jakamisen taustaosaa %s ei löytynyt", "Sharing backend for %s not found" : "Jakamisen taustaosaa kohteelle %s ei löytynyt", - "Click the button below to open it." : "Napsauta alla olevaa painiketta avataksesi sen.", "%1$s via %2$s" : "%1$s palvelun %2$s kautta", "Unknown share type" : "Tuntematon jaon tyyppi", "You are not allowed to share %s" : "Oikeutesi eivät riitä kohteen %s jakamiseen.", @@ -208,6 +207,7 @@ "How many images to generate" : "Kuinka monta kuvaa luodaan", "Output images" : "Valmiit kuvat", "The generated images" : "Luodut kuvat", + "Text" : "Teksti", "Summarize" : "Luo yhteenveto", "Summarizes a text" : "Luo yhteenvedon tekstistä", "The original text to summarize" : "Alkuperäinen teksti, josta yhteenveto muodostetaan", @@ -216,35 +216,8 @@ "Translate" : "Käännä", "Target language" : "Kohdekieli", "Result" : "Tulos", - "Logged in user must be an admin" : "Sisäänkirjautuneen käyttäjän tulee olla ylläpitäjä", - "File name is a reserved word" : "Tiedoston nimi on varattu sana", - "File name contains at least one invalid character" : "Tiedoston nimi sisältää ainakin yhden virheellisen merkin", - "File name is too long" : "Tiedoston nimi on liian pitkä", - "Help" : "Ohje", - "Users" : "Käyttäjät", - "Unknown user" : "Tuntematon käyttäjä", - "MySQL username and/or password not valid" : "MySQL-käyttäjätunnus ja/tai -salasana on väärin", - "Oracle username and/or password not valid" : "Oraclen käyttäjätunnus ja/tai salasana on väärin", - "PostgreSQL username and/or password not valid" : "PostgreSQL:n käyttäjätunnus ja/tai salasana on väärin", - "Set an admin username." : "Aseta ylläpitäjän käyttäjätunnus.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s jakoi kohteen »%2$s« kanssasi ja haluaa lisätä:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s jakoi kohteen »%2$s« kanssasi ja haluaa lisätä", - "»%s« added a note to a file shared with you" : "»%s« lisäsi huomion jakamaasi tiedostoon", - "Open »%s«" : "Avaa »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Kohteen %s jakaminen epäonnistui, koska kohde on jo jaettu käyttäjän %s kanssa", - "%1$s shared »%2$s« with you" : "%1$s jakoi kohteen »%2$s« kanssasi", - "%1$s shared »%2$s« with you." : "%1$s jakoi kohteen »%2$s« kanssasi.", - "The username is already being used" : "Käyttäjätunnus on jo käytössä", - "Could not create user" : "Ei voitu luoda käyttäjää", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Vain seuraavat merkit ovat sallittuja käyttäjätunnuksessa: \"a-z\", \"A-Z\", \"0-9\", välilyönnit ja \"_.@-'\"", - "A valid username must be provided" : "Anna kelvollinen käyttäjätunnus", - "Username contains whitespace at the beginning or at the end" : "Käyttäjätunnus sisältää tyhjätilaa joko alussa tai lopussa", - "Username must not consist of dots only" : "Käyttäjänimi ei voi koostua vain pisteistä", - "Username is invalid because files already exist for this user" : "Käyttäjänimi on virheellinen koska tiedostoja on olemassa tälle käyttäjälle", - "User disabled" : "Käyttäjä poistettu käytöstä", + "Organisation" : "Organisaatio", "File is currently busy, please try again later" : "Tiedosto on parhaillaan käytössä, yritä myöhemmin uudelleen", - "Cannot download file" : "Tiedostoa ei voi ladata", - "Your data directory is readable by other users." : "Datahakemistosi on muiden käyttäjien luettavissa.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Varmista että datahakemiston juuressa on tiedosto nimeltä \".ocdata\"." + "Cannot download file" : "Tiedostoa ei voi ladata" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/fr.js b/lib/l10n/fr.js index 50f56748882..285387d94a1 100644 --- a/lib/l10n/fr.js +++ b/lib/l10n/fr.js @@ -38,15 +38,15 @@ OC.L10N.register( "Server version %s or higher is required." : "Un serveur de version %s ou supérieure est requis.", "Server version %s or lower is required." : "Un serveur de version %s ou inférieure est requis.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Le compte connecté doit être un administrateur, un sous-administrateur ou se voir accorder des droits spéciaux pour accéder à ce réglage", - "Your current IP address doesn’t allow you to perform admin actions" : "Votre adresse IP actuelle ne vous permet pas d'effectuer des actions d'administration", + "Your current IP address doesn't allow you to perform admin actions" : "Votre adresse IP actuelle ne vous permet pas d'effectuer des actions d'administration", "Logged in account must be an admin or sub admin" : "Le compte connecté doit être administrateur ou sous-administrateur", "Logged in account must be an admin" : "Le compte connecté doit être un administrateur", "Wiping of device %s has started" : "L'effaçage de l'appareil %s a démarré", - "Wiping of device »%s« has started" : "L'effaçage de l'appareil »%s« a démarré", + "Wiping of device »%s« has started" : "L'effaçage de l'appareil « %s » a démarré", "»%s« started remote wipe" : "« %s » a démarré l'effaçage distant", "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "L'appareil ou l'application « %s » a démarré le processus d'effaçage distant. Vous recevrez un autre e-mail une fois le processus terminé", "Wiping of device %s has finished" : "L'effaçage de l'appareil %s est terminé", - "Wiping of device »%s« has finished" : "L'effaçage de l'appareil »%s« est terminé", + "Wiping of device »%s« has finished" : "L'effaçage de l'appareil « %s » est terminé", "»%s« finished remote wipe" : "« %s » a terminé l'effaçage distant", "Device or application »%s« has finished the remote wipe process." : "L'appareil ou l'application « %s » a terminé le processus d'effaçage distant.", "Remote wipe started" : "Nettoyage à distance lancé", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "L'image d'avatar n'est pas carrée", "Files" : "Fichiers", "View profile" : "Voir le profil", + "same time" : "même moment", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm"], + "%s ahead" : "%s en plus", + "%s behind" : "%s en moins", "Local time: %s" : "Heure locale : %s", "today" : "aujourd’hui", "tomorrow" : "demain", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "il y a quelques secondes", "Empty file" : "Fichier vide", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Le module avec l'ID: %s n'existe pas. Merci de l'activer dans les paramètres d'applications ou de contacter votre administrateur.", + "No file conversion providers available" : "Pas de fournisseur de conversion de fichier disponible", + "File is too large to convert" : "Le fichier est trop gros pour être converti", + "Destination does not match conversion extension" : "L'extension du fichier de destination ne correspond pas à la conversion", + "Could not convert file" : "Impossible de convertir le fichier", + "Destination does not exist" : "La destination n'existe pas", + "Destination is not creatable" : "La destination ne peut pas être créée", "Dot files are not allowed" : "Le nom de fichier ne peut pas commencer par un point", + "%1$s (renamed)" : "%1$s (renommé)", + "renamed file" : "fichier renommé", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" est un nom de fichier ou de dossier interdit.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" est un préfixe interdit pour les noms de fichiers ou de dossiers.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" n'est pas autorisé dans un nom de fichier ou de dossier.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Chemin incorrect", "Failed to create file from template" : "Impossible de créer le fichier à partir du modèle", "Templates" : "Modèles", + "Storage %s cannot be moved" : "L'emplacement de stockage %s ne peut être déplacé", + "Moving a share (%s) into a shared folder is not allowed" : "Déplacer un partage (%s) dans un dossier partagé n'est pas autorisé", + "Moving a storage (%s) into a shared folder is not allowed" : "Déplacer un emplacement de stockage (%s) dans un dossier partagé n'est pas autorisé", + "Moving a share (%s) into another share (%s) is not allowed" : "Déplacer un partage (%s) dans un autre partage (%s) n'est pas autorisé", + "Moving a share (%s) into another storage (%s) is not allowed" : "Déplacer un partage (%s) dans un autre emplacement (%s) n'est pas autorisé", + "Moving a storage (%s) into a share (%s) is not allowed" : "Déplacer un emplacement de stockage (%s) dans un partage (%s) n'est pas autorisé", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Déplacer un emplacement de stockage (%s) dans un autre emplacement de stockage (%s) n'est pas autorisé", "Path contains invalid segments" : "Le chemin contient des segments invalides", "Filename is a reserved word" : "Le nom de fichier est un mot réservé", "Filename contains at least one invalid character" : "Le nom du fichier contient au moins un caractère invalide", @@ -117,14 +137,14 @@ OC.L10N.register( "Call %s" : "Appel %s", "Twitter" : "Twitter", "View %s on Twitter" : "Voir %s sur Twitter", - "Website" : "Site web", + "Website" : "Site internet", "Visit %s" : "Visiter %s", "Address" : "Adresse", "Profile picture" : "Photo de profil", "About" : "À propos", "Display name" : "Nom d'affichage", "Headline" : "Titre", - "Organisation" : "Organisme", + "Organization" : "Organisation", "Role" : "Fonction", "Pronouns" : "Pronoms", "Unknown account" : "Compte inconnu", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "La connexion Oracle ne peut être établie", "Oracle Login and/or password not valid" : "Identifiant et/ou mot de passe Oracle invalide", "PostgreSQL Login and/or password not valid" : "Identifiant et/ou mot de passe PostgreSQL invalide", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X n'est pas pris en charge et %s ne fonctionnera pas correctement sur cette plate-forme. Son utilisation est à vos risques et périls !", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X n'est pas pris en charge et %s ne fonctionnera pas correctement sur cette plateforme. Vous l'utilisez à vos risques et périls ! ", "For the best results, please consider using a GNU/Linux server instead." : "Pour obtenir les meilleurs résultats, vous devriez utiliser un serveur GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Il semble que cette instance %s fonctionne sur un environnement PHP 32 bits et open_basedir a été configuré dans php.ini. Cela engendre des problèmes avec les fichiers de taille supérieure à 4 Go et est donc fortement déconseillé.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Veuillez retirer la configuration open_basedir de votre php.ini ou utiliser une version PHP 64-bit.", @@ -148,13 +168,12 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Le service de partage %s doit implémenter l'interface OCP\\Share_Backend", "Sharing backend %s not found" : "Service de partage %s non trouvé", "Sharing backend for %s not found" : "Le service de partage pour %s est introuvable", - "%1$s shared %2$s with you" : "%1$s à partagé %2$s avec vous", - "Click the button below to open it." : "Cliquez sur le bouton ci-dessous pour l'ouvrir", + "%1$s shared %2$s with you" : "%1$s a partagé %2$s avec vous", "Open %s" : "Ouvrir %s", "%1$s via %2$s" : "%1$s via %2$s", - "%1$s shared %2$s with you and wants to add:" : "%1$s a partagé %2$s avec vous et souhaite ajouter:", + "%1$s shared %2$s with you and wants to add:" : "%1$s a partagé %2$s avec vous et souhaite ajouter :", "%1$s shared %2$s with you and wants to add" : "%1$s a partagé %2$s avec vous et souhaite ajouter", - "%s added a note to a file shared with you" : "%s ajouté une note à un fichier partagé avec vous", + "%s added a note to a file shared with you" : "%s a ajouté une note à un fichier partagé avec vous", "Passwords are enforced for link and mail shares" : "Les mots de passe sont appliqués pour les partages de liens et de courriers électroniques", "Share recipient is not a valid user" : "Le destinataire du partage n'est pas un utilisateur valide", "Share recipient is not a valid group" : "Le destinataire du partage n'est pas un groupe valide", @@ -163,12 +182,13 @@ OC.L10N.register( "Share recipient is not a valid circle" : "Le destinataire du partage n'est pas un cercle valide", "Unknown share type" : "Type de partage inconnu", "Share initiator must be set" : "L'initiateur du partage doit être défini", - "Cannot share with yourself" : "Je ne peux pas être partager avec vous-même", + "Cannot share with yourself" : "Vous ne pouvez pas partager avec vous-même", "Shared path must be set" : "Le chemin partagé doit être défini", "Shared path must be either a file or a folder" : "Le chemin partagé doit être soit un fichier, soit un dossier", "You cannot share your root folder" : "Vous ne pouvez pas partager votre dossier racine", "You are not allowed to share %s" : "Vous n’êtes pas autorisé à partager %s", "Valid permissions are required for sharing" : "Des autorisations valides sont requises pour le partage", + "File shares cannot have create or delete permissions" : "Les partages de fichier ne peuvent avoir de permission de création ou de suppression", "Cannot increase permissions of %s" : "Impossible d'augmenter les permissions de %s", "Shares need at least read permissions" : "Les partages nécessitent au moins des autorisations de lecture", "Files cannot be shared with delete permissions" : "Les fichiers ne peuvent pas être partagés avec les autorisations de suppression", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Le chemin est déjà partagé avec ce groupe", "Link sharing is not allowed" : "Le partage de liens n'est pas autorisé", "Public upload is not allowed" : "Le téléversement public n'est pas autorisé", - "Path contains files shared with you" : "Le chemin contient des fichiers partagés avec vous", + "You cannot share a folder that contains other shares" : "Vous ne pouvez pas partager un dossier qui contient déjà d'autres partages.", "Sharing is disabled" : "Le partage est désactivé", "Sharing is disabled for you" : "Le partage est désactivé pour vous", "Cannot share with the share owner" : "Impossible de partager avec le propriétaire de l'action", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "Un identifiant valide doit être saisi", "Login contains whitespace at the beginning or at the end" : "L'identifiant contient des espaces au début ou à la fin", "Login must not consist of dots only" : "L'identifiant ne doit pas être composé uniquement de points", + "Username is too long" : "Le nom d'utilisateur est trop long", "Login is invalid because files already exist for this user" : "L’identifiant n'est pas valide car des fichiers existent déjà pour cet utilisateur", "Account disabled" : "Compte désactivé", "Login canceled by app" : "L'authentification a été annulée par l'application", @@ -311,9 +332,19 @@ OC.L10N.register( "The audio to transcribe" : "Audio à retranscrire", "Transcription" : "Transcription", "The transcribed text" : "Le texte transcrit", + "Chat with an agent" : "Discuter avec un agent conversationnel", "Chat message" : "Message de discussion", + "A chat message to send to the agent." : "Un message instantané à envoyer à l'agent.", "Confirmation" : "Confirmation", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Confirmation des actions demandées précédemment : 0 pour refuser et 1 pour confirmer.", + "Conversation token" : "Jeton de conversation", + "A token representing the conversation." : "Un jeton représentant la conversation.", "Generated response" : "Réponse générée", + "The response from the chat model." : "La réponse du modèle de messagerie instantanée", + "The new conversation token" : "Le nouveau jeton de conversation", + "Send this along with the next interaction." : "Envoyer ceci lors de la prochaine interaction.", + "Requested actions by the agent" : "Actions demandées par l'agent", + "Actions that the agent would like to carry out in JSON format." : "Actions que l'agent souhaiterait effectuer au format JSON.", "Context write" : "Écrire contextuellement", "Writes text in a given style based on the provided source material." : "Écrit un texte dans un style donné, basé sur des données initiales préalablement fournies.", "Writing style" : "Style rédactionnel", @@ -335,11 +366,22 @@ OC.L10N.register( "How many images to generate" : "Nombre d'images à générer", "Output images" : "Images de sortie", "The generated images" : "Les images générées", + "Generate speech" : "Générer la vocalisation", + "Generate speech from a transcript" : "Générer la vocalisation à partir d'une transcription", + "Write transcript that you want the assistant to generate speech from" : "Écrire la transcription à partir de laquelle vous voulez générer la vocalisation", + "Output speech" : "Sortie de la vocalisation", + "The generated speech" : "La vocalisation générée", "Free text to text prompt" : "Texte libre à texte libre", "Runs an arbitrary prompt through a language model that returns a reply" : "Exécute une commande arbitraire à l'aide d'un modèle linguistique qui génère une réponse", "Describe a task that you want the assistant to do or ask a question" : "Décrivez une tâche que vous voulez que l'assistant effectue ou posez une question", "Generated reply" : "Réponse générée", "The generated text from the assistant" : "Texte généré par l'assistant", + "Change Tone" : "Changer de ton", + "Change the tone of a piece of text." : "Changer le ton d'un morceau de texte.", + "Write a text that you want the assistant to rewrite in another tone." : "Écrivez un texte que vous souhaitez voir réécrit dans un autre ton par l'assistant", + "Desired tone" : "Ton souhaité", + "In which tone should your text be rewritten?" : "Dans quel ton souhaitez-vous que votre texte soit réécrit ?", + "The rewritten text in the desired tone, written by the assistant:" : "Le texte réécrit dans le ton souhaité par l'assistant : ", "Chat" : "Discussion instantanée ", "Chat with the assistant" : "Discuter avec l'assistant", "System prompt" : "Invite du système", @@ -348,6 +390,15 @@ OC.L10N.register( "The history of chat messages before the current message, starting with a message by the user" : "Historique des messages de discussion avant le message actuel, commençant par un message de l'utilisateur", "Response message" : "Message de réponse", "The generated response as part of the conversation" : "Réponse générée comme partie de la conversation", + "Chat with tools" : "Discuter en utilisant les fonctions", + "Chat with the language model with tool calling support." : "Discuter avec le modèle de langage en utilisant les fonctions", + "Tool message" : "Message d'outil", + "The result of tool calls in the last interaction" : "Le résultat des appels de fonction lors de la dernière interaction", + "Available tools" : "Fonctions de rappel disponibles", + "The available tools in JSON format" : "Les fonctions disponibles en format JSON", + "The response from the chat model" : "La réponse du modèle de discussion instantanée", + "Tool calls" : "Appels de fonction", + "Tools call instructions from the model in JSON format" : "Instructions d'appel d'outil depuis le modèle au format JSON", "Formalize text" : "Formaliser un texte", "Takes a text and makes it sound more formal" : "Prend un texte et le rend plus formel", "Write a text that you want the assistant to formalize" : "Rédigez un texte que vous souhaitez que l'assistant formalise", @@ -358,6 +409,12 @@ OC.L10N.register( "Original text" : "Texte original", "The original text to generate a headline for" : "Texte original pour lequel générer un titre", "The generated headline" : "Titre généré", + "Proofread" : "Relire", + "Proofreads a text and lists corrections" : "Relit un texte et liste les corrections", + "Text" : "Texte", + "The text to proofread" : "Le texte à relire", + "Corrections" : "Corrections", + "The corrections that should be made in your text" : "Les corrections que vous devriez apporter à votre texte", "Reformulate text" : "Reformuler un texte", "Takes a text and reformulates it" : "Prend un texte et le reformule", "Write a text that you want the assistant to reformulate" : "Rédigez un texte que vous souhaitez que l'assistant reformule", @@ -393,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Générer un titre", "Summarizes text by reducing its length without losing key information." : "Résume un texte en réduisant sa longueur sans perdre d’informations essentielles.", "Extracts topics from a text and outputs them separated by commas." : "Extrait les thèmes d'un texte et les restitue séparés par des virgules.", - "Education Edition" : "Édition pour l'éducation ", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "L'utilisateur connecté doit être un administrateur, un sous-administrateur ou se voir accorder des droits spéciaux pour accéder à ce réglage", - "Logged in user must be an admin or sub admin" : "L'utilisateur connecté doit être administrateur ou sous-administrateur", - "Logged in user must be an admin" : "L'utilisateur connecté doit être un administrateur", - "File name is a reserved word" : "Ce nom de fichier est un mot réservé", - "File name contains at least one invalid character" : "Le nom de fichier contient au moins un caractère invalide", - "File name is too long" : "Nom de fichier trop long", - "Help" : "Aide", - "Users" : "Utilisateurs", - "Unknown user" : "Utilisateur inconnu", - "Enter the database username and name for %s" : "Entrez le nom d'utilisateur et le nom de la base de données pour %s", - "Enter the database username for %s" : "Entrez le nom d'utilisateur de la base de données pour %s", - "MySQL username and/or password not valid" : "Nom d’utilisateur et/ou mot de passe de la base MySQL non valide(s)", - "Oracle username and/or password not valid" : "Nom d'utilisateur et/ou mot de passe de la base Oracle non valide(s)", - "PostgreSQL username and/or password not valid" : "Nom d'utilisateur et/ou mot de passe de la base PostgreSQL non valide(s)", - "Set an admin username." : "Spécifiez un nom d'utilisateur pour l'administrateur.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s a partagé »%2$s« avec vous et souhaite ajouter :", - "%1$s shared »%2$s« with you and wants to add" : "%1$s a partagé »%2$s« avec vous et souhaite ajouter", - "»%s« added a note to a file shared with you" : "»%s« a ajouté une note à un fichier partagé avec vous", - "Open »%s«" : "Ouvrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Impossible de partager %s car il est déjà partagé avec l'utilisateur %s", - "%1$s shared »%2$s« with you" : "%1$s a partagé »%2$s« avec vous", - "%1$s shared »%2$s« with you." : "%1$s a partagé »%2$s« avec vous.", - "The username is already being used" : "Ce nom d’utilisateur est déjà utilisé", - "Could not create user" : "Impossible de créer l'utilisateur", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Seuls les caractères suivants sont autorisés dans un nom d'utilisateur : \"a-z\", \"A-Z\", \"0-9\", espaces et \"_.@-'\"", - "A valid username must be provided" : "Un nom d’utilisateur valide doit être saisi", - "Username contains whitespace at the beginning or at the end" : "Le nom d’utilisateur contient des espaces au début ou à la fin", - "Username must not consist of dots only" : "Le nom d'utilisateur ne doit pas être composé uniquement de points", - "Username is invalid because files already exist for this user" : "Ce nom d’utilisateur n’est pas valide car des fichiers existent déjà pour cet utilisateur", - "User disabled" : "Utilisateur désactivé", + "Organisation" : "Organisme", "File is currently busy, please try again later" : "Le fichier est actuellement utilisé, veuillez réessayer plus tard", "Cannot download file" : "Impossible de télécharger le fichier", - "Your data directory is readable by other users." : "Votre répertoire est lisible par d'autres utilisateurs.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Veuillez changer les permissions du répertoire en mode 0770 afin que son contenu ne puisse pas être listé par les autres utilisateurs.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assurez-vous que le répertoire de données contient un fichier \".ocdata\" à sa racine." + "Login is too long" : "L'authentification est trop longue" }, "nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/fr.json b/lib/l10n/fr.json index a33339c3070..7405ab4d990 100644 --- a/lib/l10n/fr.json +++ b/lib/l10n/fr.json @@ -36,15 +36,15 @@ "Server version %s or higher is required." : "Un serveur de version %s ou supérieure est requis.", "Server version %s or lower is required." : "Un serveur de version %s ou inférieure est requis.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Le compte connecté doit être un administrateur, un sous-administrateur ou se voir accorder des droits spéciaux pour accéder à ce réglage", - "Your current IP address doesn’t allow you to perform admin actions" : "Votre adresse IP actuelle ne vous permet pas d'effectuer des actions d'administration", + "Your current IP address doesn't allow you to perform admin actions" : "Votre adresse IP actuelle ne vous permet pas d'effectuer des actions d'administration", "Logged in account must be an admin or sub admin" : "Le compte connecté doit être administrateur ou sous-administrateur", "Logged in account must be an admin" : "Le compte connecté doit être un administrateur", "Wiping of device %s has started" : "L'effaçage de l'appareil %s a démarré", - "Wiping of device »%s« has started" : "L'effaçage de l'appareil »%s« a démarré", + "Wiping of device »%s« has started" : "L'effaçage de l'appareil « %s » a démarré", "»%s« started remote wipe" : "« %s » a démarré l'effaçage distant", "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "L'appareil ou l'application « %s » a démarré le processus d'effaçage distant. Vous recevrez un autre e-mail une fois le processus terminé", "Wiping of device %s has finished" : "L'effaçage de l'appareil %s est terminé", - "Wiping of device »%s« has finished" : "L'effaçage de l'appareil »%s« est terminé", + "Wiping of device »%s« has finished" : "L'effaçage de l'appareil « %s » est terminé", "»%s« finished remote wipe" : "« %s » a terminé l'effaçage distant", "Device or application »%s« has finished the remote wipe process." : "L'appareil ou l'application « %s » a terminé le processus d'effaçage distant.", "Remote wipe started" : "Nettoyage à distance lancé", @@ -57,6 +57,11 @@ "Avatar image is not square" : "L'image d'avatar n'est pas carrée", "Files" : "Fichiers", "View profile" : "Voir le profil", + "same time" : "même moment", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm"], + "%s ahead" : "%s en plus", + "%s behind" : "%s en moins", "Local time: %s" : "Heure locale : %s", "today" : "aujourd’hui", "tomorrow" : "demain", @@ -79,7 +84,15 @@ "seconds ago" : "il y a quelques secondes", "Empty file" : "Fichier vide", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Le module avec l'ID: %s n'existe pas. Merci de l'activer dans les paramètres d'applications ou de contacter votre administrateur.", + "No file conversion providers available" : "Pas de fournisseur de conversion de fichier disponible", + "File is too large to convert" : "Le fichier est trop gros pour être converti", + "Destination does not match conversion extension" : "L'extension du fichier de destination ne correspond pas à la conversion", + "Could not convert file" : "Impossible de convertir le fichier", + "Destination does not exist" : "La destination n'existe pas", + "Destination is not creatable" : "La destination ne peut pas être créée", "Dot files are not allowed" : "Le nom de fichier ne peut pas commencer par un point", + "%1$s (renamed)" : "%1$s (renommé)", + "renamed file" : "fichier renommé", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" est un nom de fichier ou de dossier interdit.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" est un préfixe interdit pour les noms de fichiers ou de dossiers.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" n'est pas autorisé dans un nom de fichier ou de dossier.", @@ -90,6 +103,13 @@ "Invalid path" : "Chemin incorrect", "Failed to create file from template" : "Impossible de créer le fichier à partir du modèle", "Templates" : "Modèles", + "Storage %s cannot be moved" : "L'emplacement de stockage %s ne peut être déplacé", + "Moving a share (%s) into a shared folder is not allowed" : "Déplacer un partage (%s) dans un dossier partagé n'est pas autorisé", + "Moving a storage (%s) into a shared folder is not allowed" : "Déplacer un emplacement de stockage (%s) dans un dossier partagé n'est pas autorisé", + "Moving a share (%s) into another share (%s) is not allowed" : "Déplacer un partage (%s) dans un autre partage (%s) n'est pas autorisé", + "Moving a share (%s) into another storage (%s) is not allowed" : "Déplacer un partage (%s) dans un autre emplacement (%s) n'est pas autorisé", + "Moving a storage (%s) into a share (%s) is not allowed" : "Déplacer un emplacement de stockage (%s) dans un partage (%s) n'est pas autorisé", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Déplacer un emplacement de stockage (%s) dans un autre emplacement de stockage (%s) n'est pas autorisé", "Path contains invalid segments" : "Le chemin contient des segments invalides", "Filename is a reserved word" : "Le nom de fichier est un mot réservé", "Filename contains at least one invalid character" : "Le nom du fichier contient au moins un caractère invalide", @@ -115,14 +135,14 @@ "Call %s" : "Appel %s", "Twitter" : "Twitter", "View %s on Twitter" : "Voir %s sur Twitter", - "Website" : "Site web", + "Website" : "Site internet", "Visit %s" : "Visiter %s", "Address" : "Adresse", "Profile picture" : "Photo de profil", "About" : "À propos", "Display name" : "Nom d'affichage", "Headline" : "Titre", - "Organisation" : "Organisme", + "Organization" : "Organisation", "Role" : "Fonction", "Pronouns" : "Pronoms", "Unknown account" : "Compte inconnu", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "La connexion Oracle ne peut être établie", "Oracle Login and/or password not valid" : "Identifiant et/ou mot de passe Oracle invalide", "PostgreSQL Login and/or password not valid" : "Identifiant et/ou mot de passe PostgreSQL invalide", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X n'est pas pris en charge et %s ne fonctionnera pas correctement sur cette plate-forme. Son utilisation est à vos risques et périls !", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X n'est pas pris en charge et %s ne fonctionnera pas correctement sur cette plateforme. Vous l'utilisez à vos risques et périls ! ", "For the best results, please consider using a GNU/Linux server instead." : "Pour obtenir les meilleurs résultats, vous devriez utiliser un serveur GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Il semble que cette instance %s fonctionne sur un environnement PHP 32 bits et open_basedir a été configuré dans php.ini. Cela engendre des problèmes avec les fichiers de taille supérieure à 4 Go et est donc fortement déconseillé.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Veuillez retirer la configuration open_basedir de votre php.ini ou utiliser une version PHP 64-bit.", @@ -146,13 +166,12 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Le service de partage %s doit implémenter l'interface OCP\\Share_Backend", "Sharing backend %s not found" : "Service de partage %s non trouvé", "Sharing backend for %s not found" : "Le service de partage pour %s est introuvable", - "%1$s shared %2$s with you" : "%1$s à partagé %2$s avec vous", - "Click the button below to open it." : "Cliquez sur le bouton ci-dessous pour l'ouvrir", + "%1$s shared %2$s with you" : "%1$s a partagé %2$s avec vous", "Open %s" : "Ouvrir %s", "%1$s via %2$s" : "%1$s via %2$s", - "%1$s shared %2$s with you and wants to add:" : "%1$s a partagé %2$s avec vous et souhaite ajouter:", + "%1$s shared %2$s with you and wants to add:" : "%1$s a partagé %2$s avec vous et souhaite ajouter :", "%1$s shared %2$s with you and wants to add" : "%1$s a partagé %2$s avec vous et souhaite ajouter", - "%s added a note to a file shared with you" : "%s ajouté une note à un fichier partagé avec vous", + "%s added a note to a file shared with you" : "%s a ajouté une note à un fichier partagé avec vous", "Passwords are enforced for link and mail shares" : "Les mots de passe sont appliqués pour les partages de liens et de courriers électroniques", "Share recipient is not a valid user" : "Le destinataire du partage n'est pas un utilisateur valide", "Share recipient is not a valid group" : "Le destinataire du partage n'est pas un groupe valide", @@ -161,12 +180,13 @@ "Share recipient is not a valid circle" : "Le destinataire du partage n'est pas un cercle valide", "Unknown share type" : "Type de partage inconnu", "Share initiator must be set" : "L'initiateur du partage doit être défini", - "Cannot share with yourself" : "Je ne peux pas être partager avec vous-même", + "Cannot share with yourself" : "Vous ne pouvez pas partager avec vous-même", "Shared path must be set" : "Le chemin partagé doit être défini", "Shared path must be either a file or a folder" : "Le chemin partagé doit être soit un fichier, soit un dossier", "You cannot share your root folder" : "Vous ne pouvez pas partager votre dossier racine", "You are not allowed to share %s" : "Vous n’êtes pas autorisé à partager %s", "Valid permissions are required for sharing" : "Des autorisations valides sont requises pour le partage", + "File shares cannot have create or delete permissions" : "Les partages de fichier ne peuvent avoir de permission de création ou de suppression", "Cannot increase permissions of %s" : "Impossible d'augmenter les permissions de %s", "Shares need at least read permissions" : "Les partages nécessitent au moins des autorisations de lecture", "Files cannot be shared with delete permissions" : "Les fichiers ne peuvent pas être partagés avec les autorisations de suppression", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "Le chemin est déjà partagé avec ce groupe", "Link sharing is not allowed" : "Le partage de liens n'est pas autorisé", "Public upload is not allowed" : "Le téléversement public n'est pas autorisé", - "Path contains files shared with you" : "Le chemin contient des fichiers partagés avec vous", + "You cannot share a folder that contains other shares" : "Vous ne pouvez pas partager un dossier qui contient déjà d'autres partages.", "Sharing is disabled" : "Le partage est désactivé", "Sharing is disabled for you" : "Le partage est désactivé pour vous", "Cannot share with the share owner" : "Impossible de partager avec le propriétaire de l'action", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "Un identifiant valide doit être saisi", "Login contains whitespace at the beginning or at the end" : "L'identifiant contient des espaces au début ou à la fin", "Login must not consist of dots only" : "L'identifiant ne doit pas être composé uniquement de points", + "Username is too long" : "Le nom d'utilisateur est trop long", "Login is invalid because files already exist for this user" : "L’identifiant n'est pas valide car des fichiers existent déjà pour cet utilisateur", "Account disabled" : "Compte désactivé", "Login canceled by app" : "L'authentification a été annulée par l'application", @@ -309,9 +330,19 @@ "The audio to transcribe" : "Audio à retranscrire", "Transcription" : "Transcription", "The transcribed text" : "Le texte transcrit", + "Chat with an agent" : "Discuter avec un agent conversationnel", "Chat message" : "Message de discussion", + "A chat message to send to the agent." : "Un message instantané à envoyer à l'agent.", "Confirmation" : "Confirmation", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Confirmation des actions demandées précédemment : 0 pour refuser et 1 pour confirmer.", + "Conversation token" : "Jeton de conversation", + "A token representing the conversation." : "Un jeton représentant la conversation.", "Generated response" : "Réponse générée", + "The response from the chat model." : "La réponse du modèle de messagerie instantanée", + "The new conversation token" : "Le nouveau jeton de conversation", + "Send this along with the next interaction." : "Envoyer ceci lors de la prochaine interaction.", + "Requested actions by the agent" : "Actions demandées par l'agent", + "Actions that the agent would like to carry out in JSON format." : "Actions que l'agent souhaiterait effectuer au format JSON.", "Context write" : "Écrire contextuellement", "Writes text in a given style based on the provided source material." : "Écrit un texte dans un style donné, basé sur des données initiales préalablement fournies.", "Writing style" : "Style rédactionnel", @@ -333,11 +364,22 @@ "How many images to generate" : "Nombre d'images à générer", "Output images" : "Images de sortie", "The generated images" : "Les images générées", + "Generate speech" : "Générer la vocalisation", + "Generate speech from a transcript" : "Générer la vocalisation à partir d'une transcription", + "Write transcript that you want the assistant to generate speech from" : "Écrire la transcription à partir de laquelle vous voulez générer la vocalisation", + "Output speech" : "Sortie de la vocalisation", + "The generated speech" : "La vocalisation générée", "Free text to text prompt" : "Texte libre à texte libre", "Runs an arbitrary prompt through a language model that returns a reply" : "Exécute une commande arbitraire à l'aide d'un modèle linguistique qui génère une réponse", "Describe a task that you want the assistant to do or ask a question" : "Décrivez une tâche que vous voulez que l'assistant effectue ou posez une question", "Generated reply" : "Réponse générée", "The generated text from the assistant" : "Texte généré par l'assistant", + "Change Tone" : "Changer de ton", + "Change the tone of a piece of text." : "Changer le ton d'un morceau de texte.", + "Write a text that you want the assistant to rewrite in another tone." : "Écrivez un texte que vous souhaitez voir réécrit dans un autre ton par l'assistant", + "Desired tone" : "Ton souhaité", + "In which tone should your text be rewritten?" : "Dans quel ton souhaitez-vous que votre texte soit réécrit ?", + "The rewritten text in the desired tone, written by the assistant:" : "Le texte réécrit dans le ton souhaité par l'assistant : ", "Chat" : "Discussion instantanée ", "Chat with the assistant" : "Discuter avec l'assistant", "System prompt" : "Invite du système", @@ -346,6 +388,15 @@ "The history of chat messages before the current message, starting with a message by the user" : "Historique des messages de discussion avant le message actuel, commençant par un message de l'utilisateur", "Response message" : "Message de réponse", "The generated response as part of the conversation" : "Réponse générée comme partie de la conversation", + "Chat with tools" : "Discuter en utilisant les fonctions", + "Chat with the language model with tool calling support." : "Discuter avec le modèle de langage en utilisant les fonctions", + "Tool message" : "Message d'outil", + "The result of tool calls in the last interaction" : "Le résultat des appels de fonction lors de la dernière interaction", + "Available tools" : "Fonctions de rappel disponibles", + "The available tools in JSON format" : "Les fonctions disponibles en format JSON", + "The response from the chat model" : "La réponse du modèle de discussion instantanée", + "Tool calls" : "Appels de fonction", + "Tools call instructions from the model in JSON format" : "Instructions d'appel d'outil depuis le modèle au format JSON", "Formalize text" : "Formaliser un texte", "Takes a text and makes it sound more formal" : "Prend un texte et le rend plus formel", "Write a text that you want the assistant to formalize" : "Rédigez un texte que vous souhaitez que l'assistant formalise", @@ -356,6 +407,12 @@ "Original text" : "Texte original", "The original text to generate a headline for" : "Texte original pour lequel générer un titre", "The generated headline" : "Titre généré", + "Proofread" : "Relire", + "Proofreads a text and lists corrections" : "Relit un texte et liste les corrections", + "Text" : "Texte", + "The text to proofread" : "Le texte à relire", + "Corrections" : "Corrections", + "The corrections that should be made in your text" : "Les corrections que vous devriez apporter à votre texte", "Reformulate text" : "Reformuler un texte", "Takes a text and reformulates it" : "Prend un texte et le reformule", "Write a text that you want the assistant to reformulate" : "Rédigez un texte que vous souhaitez que l'assistant reformule", @@ -391,41 +448,9 @@ "Generate headline" : "Générer un titre", "Summarizes text by reducing its length without losing key information." : "Résume un texte en réduisant sa longueur sans perdre d’informations essentielles.", "Extracts topics from a text and outputs them separated by commas." : "Extrait les thèmes d'un texte et les restitue séparés par des virgules.", - "Education Edition" : "Édition pour l'éducation ", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "L'utilisateur connecté doit être un administrateur, un sous-administrateur ou se voir accorder des droits spéciaux pour accéder à ce réglage", - "Logged in user must be an admin or sub admin" : "L'utilisateur connecté doit être administrateur ou sous-administrateur", - "Logged in user must be an admin" : "L'utilisateur connecté doit être un administrateur", - "File name is a reserved word" : "Ce nom de fichier est un mot réservé", - "File name contains at least one invalid character" : "Le nom de fichier contient au moins un caractère invalide", - "File name is too long" : "Nom de fichier trop long", - "Help" : "Aide", - "Users" : "Utilisateurs", - "Unknown user" : "Utilisateur inconnu", - "Enter the database username and name for %s" : "Entrez le nom d'utilisateur et le nom de la base de données pour %s", - "Enter the database username for %s" : "Entrez le nom d'utilisateur de la base de données pour %s", - "MySQL username and/or password not valid" : "Nom d’utilisateur et/ou mot de passe de la base MySQL non valide(s)", - "Oracle username and/or password not valid" : "Nom d'utilisateur et/ou mot de passe de la base Oracle non valide(s)", - "PostgreSQL username and/or password not valid" : "Nom d'utilisateur et/ou mot de passe de la base PostgreSQL non valide(s)", - "Set an admin username." : "Spécifiez un nom d'utilisateur pour l'administrateur.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s a partagé »%2$s« avec vous et souhaite ajouter :", - "%1$s shared »%2$s« with you and wants to add" : "%1$s a partagé »%2$s« avec vous et souhaite ajouter", - "»%s« added a note to a file shared with you" : "»%s« a ajouté une note à un fichier partagé avec vous", - "Open »%s«" : "Ouvrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Impossible de partager %s car il est déjà partagé avec l'utilisateur %s", - "%1$s shared »%2$s« with you" : "%1$s a partagé »%2$s« avec vous", - "%1$s shared »%2$s« with you." : "%1$s a partagé »%2$s« avec vous.", - "The username is already being used" : "Ce nom d’utilisateur est déjà utilisé", - "Could not create user" : "Impossible de créer l'utilisateur", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Seuls les caractères suivants sont autorisés dans un nom d'utilisateur : \"a-z\", \"A-Z\", \"0-9\", espaces et \"_.@-'\"", - "A valid username must be provided" : "Un nom d’utilisateur valide doit être saisi", - "Username contains whitespace at the beginning or at the end" : "Le nom d’utilisateur contient des espaces au début ou à la fin", - "Username must not consist of dots only" : "Le nom d'utilisateur ne doit pas être composé uniquement de points", - "Username is invalid because files already exist for this user" : "Ce nom d’utilisateur n’est pas valide car des fichiers existent déjà pour cet utilisateur", - "User disabled" : "Utilisateur désactivé", + "Organisation" : "Organisme", "File is currently busy, please try again later" : "Le fichier est actuellement utilisé, veuillez réessayer plus tard", "Cannot download file" : "Impossible de télécharger le fichier", - "Your data directory is readable by other users." : "Votre répertoire est lisible par d'autres utilisateurs.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Veuillez changer les permissions du répertoire en mode 0770 afin que son contenu ne puisse pas être listé par les autres utilisateurs.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assurez-vous que le répertoire de données contient un fichier \".ocdata\" à sa racine." + "Login is too long" : "L'authentification est trop longue" },"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/ga.js b/lib/l10n/ga.js index 828b8332f9d..4815f14d0a1 100644 --- a/lib/l10n/ga.js +++ b/lib/l10n/ga.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Tá leagan freastalaí %s nó níos airde ag teastáil.", "Server version %s or lower is required." : "Tá leagan freastalaí %s nó níos ísle ag teastáil.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Ní mór gur riarthóir, fo-riarthóir é cuntas logáilte isteach nó go bhfuil ceart speisialta faighte aige chun an socrú seo a rochtain", - "Your current IP address doesn’t allow you to perform admin actions" : "Ní cheadaíonn do sheoladh IP reatha duit gníomhartha riaracháin a dhéanamh", + "Your current IP address doesn't allow you to perform admin actions" : "Ní cheadaíonn do sheoladh IP reatha duit gníomhartha riaracháin a dhéanamh", "Logged in account must be an admin or sub admin" : "Ní mór gur riarthóir nó fo-riarthóir é cuntas logáilte isteach", "Logged in account must be an admin" : "Ní mór gur riarthóir é cuntas logáilte isteach", "Wiping of device %s has started" : "Tá tús curtha le glanadh an ghléis %s", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Níl an íomhá avatar cearnach", "Files" : "Comhaid", "View profile" : "Féach ar phróifíl", + "same time" : "am céanna", + "_%nh_::_%nh_" : ["%nuair","%nuair","%nuair","%nuair","%nuair"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm","%nm","%nm"], + "%s ahead" : "%s romhainn", + "%s behind" : "%s taobh thiar", "Local time: %s" : "Am áitiúil: %s", "today" : "inniu", "tomorrow" : "amárach", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "soicind ó shin", "Empty file" : "Comhad folamh", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modúl le haitheantas: níl %s ann. Cumasaigh é i socruithe d'aipeanna nó déan teagmháil le do riarthóir le do thoil.", + "No file conversion providers available" : "Níl soláthraithe comhshó comhad ar fáil", + "File is too large to convert" : "Tá an comhad rómhór le tiontú", + "Destination does not match conversion extension" : "Ní hionann an ceann scríbe agus an síneadh tiontaithe", + "Could not convert file" : "Níorbh fhéidir an comhad a thiontú", + "Destination does not exist" : "Níl ceann scríbe ann", + "Destination is not creatable" : "Níl ceann scríbe cruthaithe", "Dot files are not allowed" : "Ní cheadaítear comhaid ponc", + "%1$s (renamed)" : "%1$s (athainmnithe)", + "renamed file" : "comhad athainmnithe", "\"%1$s\" is a forbidden file or folder name." : "Is ainm toirmiscthe comhaid nó fillteáin é \"%1$s\".", "\"%1$s\" is a forbidden prefix for file or folder names." : "Réimír toirmiscthe é \"%1$s\" d'ainmneacha comhaid nó fillteán.", "\"%1$s\" is not allowed inside a file or folder name." : "Ní cheadaítear \"%1$s\" taobh istigh d'ainm comhaid nó fillteáin.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Conair neamhbhailí", "Failed to create file from template" : "Theip ar chruthú comhad ón teimpléad", "Templates" : "Teimpléid", + "Storage %s cannot be moved" : "Ní féidir stóráil %s a bhogadh", + "Moving a share (%s) into a shared folder is not allowed" : "Ní cheadaítear sciar (%s) a bhogadh isteach i bhfillteán comhroinnte", + "Moving a storage (%s) into a shared folder is not allowed" : "Ní cheadaítear stóras (%s) a bhogadh isteach i bhfillteán comhroinnte", + "Moving a share (%s) into another share (%s) is not allowed" : "Ní cheadaítear sciar (%s) a aistriú go sciar eile (%s).", + "Moving a share (%s) into another storage (%s) is not allowed" : "Ní cheadaítear sciar (%s) a aistriú go stóras eile (%s).", + "Moving a storage (%s) into a share (%s) is not allowed" : "Ní cheadaítear stóras (%s) a aistriú go sciar (%s).", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Ní cheadaítear stóras (%s) a aistriú go stóras eile (%s).", "Path contains invalid segments" : "Tá míreanna neamhbhailí sa chonair", "Filename is a reserved word" : "Focal forchoimeádta is ea ainm comhaid", "Filename contains at least one invalid character" : "Tá carachtar neamhbhailí amháin ar a laghad san ainm comhaid", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "Faoi", "Display name" : "Ainm taispeána", "Headline" : "Ceannlíne", - "Organisation" : "Eagraíocht", + "Organization" : "Eagraíocht", "Role" : "Ról", "Pronouns" : "Forainmneacha", "Unknown account" : "Cuntas anaithnid", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Níorbh fhéidir nasc Oracle a bhunú", "Oracle Login and/or password not valid" : "Níl logáil isteach Oracle agus/nó pasfhocal bailí", "PostgreSQL Login and/or password not valid" : "Níl logáil isteach agus/nó pasfhocal PostgreSQL bailí", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Ní thacaítear le Mac OS X agus ní oibreoidh %s i gceart ar an ardán seo. Bain úsáid as ar do phriacal féin!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Ní thacaítear le Mac OS X agus ní oibreoidh %s i gceart ar an ardán seo. Bain úsáid as ar do phriacal féin!", "For the best results, please consider using a GNU/Linux server instead." : "Chun na torthaí is fearr a fháil, smaoinigh le do thoil ar fhreastalaí GNU/Linux a úsáid ina ionad.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Is cosúil go bhfuil an cás %s seo ag rith ar thimpeallacht PHP 32-giotán agus tá an open_basedir cumraithe i php.ini. Beidh fadhbanna le comhaid os cionn 4 GB mar thoradh air seo agus tá sé an-díspreagadh.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bain an socrú open_basedir laistigh de do php.ini nó aistrigh go PHP 64-giotán le do thoil.", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Ní bhfuarthas inneall comhroinnte %s", "Sharing backend for %s not found" : "Ní bhfuarthas inneall roinnte le haghaidh %s", "%1$s shared %2$s with you" : "%1$s roinnte %2$s leat", - "Click the button below to open it." : "Cliceáil ar an gcnaipe thíos chun é a oscailt.", "Open %s" : "Oscailte %s", "%1$s via %2$s" : "%1$s trí %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$sroinnte%2$sleat agus ba mhaith leat a chur leis:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "Ní féidir leat do fhréamhfhillteán a roinnt", "You are not allowed to share %s" : "Níl cead agat %s a roinnt", "Valid permissions are required for sharing" : "Teastaíonn ceadanna bailí chun comhroinnt", + "File shares cannot have create or delete permissions" : "Ní féidir ceadanna cruthaithe nó scriosta a bheith ag scaireanna comhaid", "Cannot increase permissions of %s" : "Ní féidir ceadanna %s a mhéadú", "Shares need at least read permissions" : "Teastaíonn ceadanna léite ar a laghad ó scaireanna", "Files cannot be shared with delete permissions" : "Ní féidir comhaid a roinnt le ceadanna scriosta", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Tá an chonair roinnte leis an ngrúpa seo cheana féin", "Link sharing is not allowed" : "Ní cheadaítear nasc a roinnt", "Public upload is not allowed" : "Ní cheadaítear uaslódáil phoiblí", - "Path contains files shared with you" : "Tá comhaid a roinntear leat sa chonair", + "You cannot share a folder that contains other shares" : "Ní féidir leat fillteán a roinnt ina bhfuil scaireanna eile", "Sharing is disabled" : "Tá roinnt díchumasaithe", "Sharing is disabled for you" : "Tá comhroinnt díchumasaithe duit", "Cannot share with the share owner" : "Ní féidir a roinnt leis an úinéir na scaireanna", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "Ní mór Logáil Isteach bailí a sholáthar", "Login contains whitespace at the beginning or at the end" : "Tá spás bán sa logáil isteach ag an tús nó ag an deireadh", "Login must not consist of dots only" : "Níor cheart go gcuimseodh logáil isteach poncanna amháin", + "Username is too long" : "Tá an t-ainm úsáideora rófhada", "Login is invalid because files already exist for this user" : "Tá logáil isteach neamhbhailí toisc go bhfuil comhaid ann cheana don úsáideoir seo", "Account disabled" : "Díchumasaíodh an cuntas", "Login canceled by app" : "Cealaíodh logáil isteach ag an aip", @@ -311,7 +332,6 @@ OC.L10N.register( "The audio to transcribe" : "Fuaime le tras-scríobh", "Transcription" : "Trascríobh", "The transcribed text" : "An téacs tras-scríofa", - "ContextAgent" : "Gníomhaire Comhthéacs", "Chat with an agent" : "Déan comhrá le gníomhaire", "Chat message" : "Teachtaireacht comhrá", "A chat message to send to the agent." : "Teachtaireacht comhrá le seoladh chuig an ngníomhaire.", @@ -346,6 +366,11 @@ OC.L10N.register( "How many images to generate" : "Cé mhéad íomhánna atá le giniúint", "Output images" : "Íomhánna aschuir", "The generated images" : "Na híomhánna a ghintear", + "Generate speech" : "Gin urlabhra", + "Generate speech from a transcript" : "Gin urlabhra ó thrascríbhinn", + "Write transcript that you want the assistant to generate speech from" : "Scríobh an tras-scríbhinn ar mhaith leat go nginfeadh an cúntóir urlabhra uaidh", + "Output speech" : "Aschur cainte", + "The generated speech" : "An chaint ghinte", "Free text to text prompt" : "Teimpléad téacs go téacs saor in aisce,", "Runs an arbitrary prompt through a language model that returns a reply" : "Ritheann leid treallach trí mhúnla teanga a sheolann freagra ar ais", "Describe a task that you want the assistant to do or ask a question" : "Déan cur síos ar thasc a theastaíonn uait don chúntóir a dhéanamh nó ceist a chur", @@ -384,6 +409,12 @@ OC.L10N.register( "Original text" : "Téacs bunaidh", "The original text to generate a headline for" : "An téacs bunaidh chun ceannlíne a ghiniúint le haghaidh", "The generated headline" : "An ceannlíne ginte", + "Proofread" : "Promhléamh", + "Proofreads a text and lists corrections" : "Léann profaí téacs agus liostaíonn sé ceartúcháin", + "Text" : "Téacs", + "The text to proofread" : "An téacs le léamh profaí", + "Corrections" : "Ceartúcháin", + "The corrections that should be made in your text" : "Na ceartúcháin ba chóir a dhéanamh i do théacs", "Reformulate text" : "Téacs a athchóiriú", "Takes a text and reformulates it" : "Glacann sé téacs agus athfhoirmíonn sé é", "Write a text that you want the assistant to reformulate" : "Scríobh téacs a theastaíonn uait go ndéanfadh an cúntóir athfhoirmliú", @@ -419,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Gin ceannlíne", "Summarizes text by reducing its length without losing key information." : "Déanann sé achoimre ar théacs trína fhad a laghdú gan eochairfhaisnéis a chailliúint.", "Extracts topics from a text and outputs them separated by commas." : "Sliocht topaicí as téacs agus aschuir iad scartha le camóga.", - "Education Edition" : "Eagrán Oideachais", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Ní mór gur riarthóir, fo-riarthóir é an t-úsáideoir logáilte isteach nó go raibh ceart speisialta faighte aige chun an socrú seo a rochtain", - "Logged in user must be an admin or sub admin" : "Caithfidh úsáideoir logáilte isteach a bheith ina riarthóir nó ina fho-riarthóir", - "Logged in user must be an admin" : "Caithfidh úsáideoir logáilte isteach a bheith ina riarthóir", - "File name is a reserved word" : "Focal in áirithe is ea ainm comhaid", - "File name contains at least one invalid character" : "Tá carachtar neamhbhailí amháin ar a laghad san ainm comhaid", - "File name is too long" : "Tá ainm an chomhaid rófhada", - "Help" : "Cabhrú", - "Users" : "Úsáideoirí", - "Unknown user" : "Úsáideoir anaithnid", - "Enter the database username and name for %s" : "Cuir isteach ainm úsáideora agus ainm an bhunachair shonraí do %s", - "Enter the database username for %s" : "Cuir isteach ainm úsáideora an bhunachair shonraí le haghaidh %s", - "MySQL username and/or password not valid" : "Níl ainm úsáideora agus/nó pasfhocal MySQL bailí", - "Oracle username and/or password not valid" : "Ainm úsáideora agus/nó pasfhocal Oracle neamhbhailí", - "PostgreSQL username and/or password not valid" : "Ainm úsáideora agus/nó pasfhocal PostgreSQL neamhbhailí", - "Set an admin username." : "Socraigh ainm úsáideora admin.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s shared »%2$s« with you and wants to add:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s shared »%2$s« with you and wants to add", - "»%s« added a note to a file shared with you" : "»%s« added a note to a file shared with you", - "Open »%s«" : "Oscail »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Theip ar chomhroinnt %s, toisc go bhfuil an mhír seo roinnte le húsáideoir %s cheana féin", - "%1$s shared »%2$s« with you" : "Roinn %1$s »%2$s« leat", - "%1$s shared »%2$s« with you." : "Roinn %1$s »%2$s« leat.", - "The username is already being used" : "Tá an t-ainm úsáideora á úsáid cheana féin", - "Could not create user" : "Níorbh fhéidir úsáideoir a chruthú", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Ní cheadaítear ach na carachtair seo a leanas in ainm úsáideora: \"a-z\", \"A-Z\", \"0-9\", spásanna agus \"_.@-'\"", - "A valid username must be provided" : "Ní mór ainm úsáideora bailí a sholáthar", - "Username contains whitespace at the beginning or at the end" : "Tá spás bán san ainm úsáideora ag an tús nó ag an deireadh", - "Username must not consist of dots only" : "Ní ceadmhach poncanna amháin a bheith san ainm úsáideora", - "Username is invalid because files already exist for this user" : "Tá an t-ainm úsáideora neamhbhailí toisc go bhfuil comhaid ann cheana don úsáideoir seo", - "User disabled" : "Díchumasaíodh an t-úsáideoir", + "Organisation" : "Eagraíocht", "File is currently busy, please try again later" : "Tá an comhad gnóthach faoi láthair, bain triail eile as ar ball le do thoil", "Cannot download file" : "Ní féidir an comhad a íoslódáil", - "Your data directory is readable by other users." : "Tá d'eolaire sonraí inléite ag úsáideoirí eile.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Athraigh na ceadanna go 0770 le do thoil ionas nach féidir le húsáideoirí eile an t-eolaire a liostú.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Cinntigh go bhfuil comhad darb ainm \".ocdata\" i bhfréamh an eolaire sonraí." + "Login is too long" : "Tá logáil isteach ró-fhada" }, "nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);"); diff --git a/lib/l10n/ga.json b/lib/l10n/ga.json index 6f34f3240d6..b601cb06aca 100644 --- a/lib/l10n/ga.json +++ b/lib/l10n/ga.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Tá leagan freastalaí %s nó níos airde ag teastáil.", "Server version %s or lower is required." : "Tá leagan freastalaí %s nó níos ísle ag teastáil.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Ní mór gur riarthóir, fo-riarthóir é cuntas logáilte isteach nó go bhfuil ceart speisialta faighte aige chun an socrú seo a rochtain", - "Your current IP address doesn’t allow you to perform admin actions" : "Ní cheadaíonn do sheoladh IP reatha duit gníomhartha riaracháin a dhéanamh", + "Your current IP address doesn't allow you to perform admin actions" : "Ní cheadaíonn do sheoladh IP reatha duit gníomhartha riaracháin a dhéanamh", "Logged in account must be an admin or sub admin" : "Ní mór gur riarthóir nó fo-riarthóir é cuntas logáilte isteach", "Logged in account must be an admin" : "Ní mór gur riarthóir é cuntas logáilte isteach", "Wiping of device %s has started" : "Tá tús curtha le glanadh an ghléis %s", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Níl an íomhá avatar cearnach", "Files" : "Comhaid", "View profile" : "Féach ar phróifíl", + "same time" : "am céanna", + "_%nh_::_%nh_" : ["%nuair","%nuair","%nuair","%nuair","%nuair"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm","%nm","%nm"], + "%s ahead" : "%s romhainn", + "%s behind" : "%s taobh thiar", "Local time: %s" : "Am áitiúil: %s", "today" : "inniu", "tomorrow" : "amárach", @@ -79,7 +84,15 @@ "seconds ago" : "soicind ó shin", "Empty file" : "Comhad folamh", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modúl le haitheantas: níl %s ann. Cumasaigh é i socruithe d'aipeanna nó déan teagmháil le do riarthóir le do thoil.", + "No file conversion providers available" : "Níl soláthraithe comhshó comhad ar fáil", + "File is too large to convert" : "Tá an comhad rómhór le tiontú", + "Destination does not match conversion extension" : "Ní hionann an ceann scríbe agus an síneadh tiontaithe", + "Could not convert file" : "Níorbh fhéidir an comhad a thiontú", + "Destination does not exist" : "Níl ceann scríbe ann", + "Destination is not creatable" : "Níl ceann scríbe cruthaithe", "Dot files are not allowed" : "Ní cheadaítear comhaid ponc", + "%1$s (renamed)" : "%1$s (athainmnithe)", + "renamed file" : "comhad athainmnithe", "\"%1$s\" is a forbidden file or folder name." : "Is ainm toirmiscthe comhaid nó fillteáin é \"%1$s\".", "\"%1$s\" is a forbidden prefix for file or folder names." : "Réimír toirmiscthe é \"%1$s\" d'ainmneacha comhaid nó fillteán.", "\"%1$s\" is not allowed inside a file or folder name." : "Ní cheadaítear \"%1$s\" taobh istigh d'ainm comhaid nó fillteáin.", @@ -90,6 +103,13 @@ "Invalid path" : "Conair neamhbhailí", "Failed to create file from template" : "Theip ar chruthú comhad ón teimpléad", "Templates" : "Teimpléid", + "Storage %s cannot be moved" : "Ní féidir stóráil %s a bhogadh", + "Moving a share (%s) into a shared folder is not allowed" : "Ní cheadaítear sciar (%s) a bhogadh isteach i bhfillteán comhroinnte", + "Moving a storage (%s) into a shared folder is not allowed" : "Ní cheadaítear stóras (%s) a bhogadh isteach i bhfillteán comhroinnte", + "Moving a share (%s) into another share (%s) is not allowed" : "Ní cheadaítear sciar (%s) a aistriú go sciar eile (%s).", + "Moving a share (%s) into another storage (%s) is not allowed" : "Ní cheadaítear sciar (%s) a aistriú go stóras eile (%s).", + "Moving a storage (%s) into a share (%s) is not allowed" : "Ní cheadaítear stóras (%s) a aistriú go sciar (%s).", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Ní cheadaítear stóras (%s) a aistriú go stóras eile (%s).", "Path contains invalid segments" : "Tá míreanna neamhbhailí sa chonair", "Filename is a reserved word" : "Focal forchoimeádta is ea ainm comhaid", "Filename contains at least one invalid character" : "Tá carachtar neamhbhailí amháin ar a laghad san ainm comhaid", @@ -122,7 +142,7 @@ "About" : "Faoi", "Display name" : "Ainm taispeána", "Headline" : "Ceannlíne", - "Organisation" : "Eagraíocht", + "Organization" : "Eagraíocht", "Role" : "Ról", "Pronouns" : "Forainmneacha", "Unknown account" : "Cuntas anaithnid", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "Níorbh fhéidir nasc Oracle a bhunú", "Oracle Login and/or password not valid" : "Níl logáil isteach Oracle agus/nó pasfhocal bailí", "PostgreSQL Login and/or password not valid" : "Níl logáil isteach agus/nó pasfhocal PostgreSQL bailí", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Ní thacaítear le Mac OS X agus ní oibreoidh %s i gceart ar an ardán seo. Bain úsáid as ar do phriacal féin!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Ní thacaítear le Mac OS X agus ní oibreoidh %s i gceart ar an ardán seo. Bain úsáid as ar do phriacal féin!", "For the best results, please consider using a GNU/Linux server instead." : "Chun na torthaí is fearr a fháil, smaoinigh le do thoil ar fhreastalaí GNU/Linux a úsáid ina ionad.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Is cosúil go bhfuil an cás %s seo ag rith ar thimpeallacht PHP 32-giotán agus tá an open_basedir cumraithe i php.ini. Beidh fadhbanna le comhaid os cionn 4 GB mar thoradh air seo agus tá sé an-díspreagadh.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Bain an socrú open_basedir laistigh de do php.ini nó aistrigh go PHP 64-giotán le do thoil.", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "Ní bhfuarthas inneall comhroinnte %s", "Sharing backend for %s not found" : "Ní bhfuarthas inneall roinnte le haghaidh %s", "%1$s shared %2$s with you" : "%1$s roinnte %2$s leat", - "Click the button below to open it." : "Cliceáil ar an gcnaipe thíos chun é a oscailt.", "Open %s" : "Oscailte %s", "%1$s via %2$s" : "%1$s trí %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$sroinnte%2$sleat agus ba mhaith leat a chur leis:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "Ní féidir leat do fhréamhfhillteán a roinnt", "You are not allowed to share %s" : "Níl cead agat %s a roinnt", "Valid permissions are required for sharing" : "Teastaíonn ceadanna bailí chun comhroinnt", + "File shares cannot have create or delete permissions" : "Ní féidir ceadanna cruthaithe nó scriosta a bheith ag scaireanna comhaid", "Cannot increase permissions of %s" : "Ní féidir ceadanna %s a mhéadú", "Shares need at least read permissions" : "Teastaíonn ceadanna léite ar a laghad ó scaireanna", "Files cannot be shared with delete permissions" : "Ní féidir comhaid a roinnt le ceadanna scriosta", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "Tá an chonair roinnte leis an ngrúpa seo cheana féin", "Link sharing is not allowed" : "Ní cheadaítear nasc a roinnt", "Public upload is not allowed" : "Ní cheadaítear uaslódáil phoiblí", - "Path contains files shared with you" : "Tá comhaid a roinntear leat sa chonair", + "You cannot share a folder that contains other shares" : "Ní féidir leat fillteán a roinnt ina bhfuil scaireanna eile", "Sharing is disabled" : "Tá roinnt díchumasaithe", "Sharing is disabled for you" : "Tá comhroinnt díchumasaithe duit", "Cannot share with the share owner" : "Ní féidir a roinnt leis an úinéir na scaireanna", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "Ní mór Logáil Isteach bailí a sholáthar", "Login contains whitespace at the beginning or at the end" : "Tá spás bán sa logáil isteach ag an tús nó ag an deireadh", "Login must not consist of dots only" : "Níor cheart go gcuimseodh logáil isteach poncanna amháin", + "Username is too long" : "Tá an t-ainm úsáideora rófhada", "Login is invalid because files already exist for this user" : "Tá logáil isteach neamhbhailí toisc go bhfuil comhaid ann cheana don úsáideoir seo", "Account disabled" : "Díchumasaíodh an cuntas", "Login canceled by app" : "Cealaíodh logáil isteach ag an aip", @@ -309,7 +330,6 @@ "The audio to transcribe" : "Fuaime le tras-scríobh", "Transcription" : "Trascríobh", "The transcribed text" : "An téacs tras-scríofa", - "ContextAgent" : "Gníomhaire Comhthéacs", "Chat with an agent" : "Déan comhrá le gníomhaire", "Chat message" : "Teachtaireacht comhrá", "A chat message to send to the agent." : "Teachtaireacht comhrá le seoladh chuig an ngníomhaire.", @@ -344,6 +364,11 @@ "How many images to generate" : "Cé mhéad íomhánna atá le giniúint", "Output images" : "Íomhánna aschuir", "The generated images" : "Na híomhánna a ghintear", + "Generate speech" : "Gin urlabhra", + "Generate speech from a transcript" : "Gin urlabhra ó thrascríbhinn", + "Write transcript that you want the assistant to generate speech from" : "Scríobh an tras-scríbhinn ar mhaith leat go nginfeadh an cúntóir urlabhra uaidh", + "Output speech" : "Aschur cainte", + "The generated speech" : "An chaint ghinte", "Free text to text prompt" : "Teimpléad téacs go téacs saor in aisce,", "Runs an arbitrary prompt through a language model that returns a reply" : "Ritheann leid treallach trí mhúnla teanga a sheolann freagra ar ais", "Describe a task that you want the assistant to do or ask a question" : "Déan cur síos ar thasc a theastaíonn uait don chúntóir a dhéanamh nó ceist a chur", @@ -382,6 +407,12 @@ "Original text" : "Téacs bunaidh", "The original text to generate a headline for" : "An téacs bunaidh chun ceannlíne a ghiniúint le haghaidh", "The generated headline" : "An ceannlíne ginte", + "Proofread" : "Promhléamh", + "Proofreads a text and lists corrections" : "Léann profaí téacs agus liostaíonn sé ceartúcháin", + "Text" : "Téacs", + "The text to proofread" : "An téacs le léamh profaí", + "Corrections" : "Ceartúcháin", + "The corrections that should be made in your text" : "Na ceartúcháin ba chóir a dhéanamh i do théacs", "Reformulate text" : "Téacs a athchóiriú", "Takes a text and reformulates it" : "Glacann sé téacs agus athfhoirmíonn sé é", "Write a text that you want the assistant to reformulate" : "Scríobh téacs a theastaíonn uait go ndéanfadh an cúntóir athfhoirmliú", @@ -417,41 +448,9 @@ "Generate headline" : "Gin ceannlíne", "Summarizes text by reducing its length without losing key information." : "Déanann sé achoimre ar théacs trína fhad a laghdú gan eochairfhaisnéis a chailliúint.", "Extracts topics from a text and outputs them separated by commas." : "Sliocht topaicí as téacs agus aschuir iad scartha le camóga.", - "Education Edition" : "Eagrán Oideachais", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Ní mór gur riarthóir, fo-riarthóir é an t-úsáideoir logáilte isteach nó go raibh ceart speisialta faighte aige chun an socrú seo a rochtain", - "Logged in user must be an admin or sub admin" : "Caithfidh úsáideoir logáilte isteach a bheith ina riarthóir nó ina fho-riarthóir", - "Logged in user must be an admin" : "Caithfidh úsáideoir logáilte isteach a bheith ina riarthóir", - "File name is a reserved word" : "Focal in áirithe is ea ainm comhaid", - "File name contains at least one invalid character" : "Tá carachtar neamhbhailí amháin ar a laghad san ainm comhaid", - "File name is too long" : "Tá ainm an chomhaid rófhada", - "Help" : "Cabhrú", - "Users" : "Úsáideoirí", - "Unknown user" : "Úsáideoir anaithnid", - "Enter the database username and name for %s" : "Cuir isteach ainm úsáideora agus ainm an bhunachair shonraí do %s", - "Enter the database username for %s" : "Cuir isteach ainm úsáideora an bhunachair shonraí le haghaidh %s", - "MySQL username and/or password not valid" : "Níl ainm úsáideora agus/nó pasfhocal MySQL bailí", - "Oracle username and/or password not valid" : "Ainm úsáideora agus/nó pasfhocal Oracle neamhbhailí", - "PostgreSQL username and/or password not valid" : "Ainm úsáideora agus/nó pasfhocal PostgreSQL neamhbhailí", - "Set an admin username." : "Socraigh ainm úsáideora admin.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s shared »%2$s« with you and wants to add:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s shared »%2$s« with you and wants to add", - "»%s« added a note to a file shared with you" : "»%s« added a note to a file shared with you", - "Open »%s«" : "Oscail »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Theip ar chomhroinnt %s, toisc go bhfuil an mhír seo roinnte le húsáideoir %s cheana féin", - "%1$s shared »%2$s« with you" : "Roinn %1$s »%2$s« leat", - "%1$s shared »%2$s« with you." : "Roinn %1$s »%2$s« leat.", - "The username is already being used" : "Tá an t-ainm úsáideora á úsáid cheana féin", - "Could not create user" : "Níorbh fhéidir úsáideoir a chruthú", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Ní cheadaítear ach na carachtair seo a leanas in ainm úsáideora: \"a-z\", \"A-Z\", \"0-9\", spásanna agus \"_.@-'\"", - "A valid username must be provided" : "Ní mór ainm úsáideora bailí a sholáthar", - "Username contains whitespace at the beginning or at the end" : "Tá spás bán san ainm úsáideora ag an tús nó ag an deireadh", - "Username must not consist of dots only" : "Ní ceadmhach poncanna amháin a bheith san ainm úsáideora", - "Username is invalid because files already exist for this user" : "Tá an t-ainm úsáideora neamhbhailí toisc go bhfuil comhaid ann cheana don úsáideoir seo", - "User disabled" : "Díchumasaíodh an t-úsáideoir", + "Organisation" : "Eagraíocht", "File is currently busy, please try again later" : "Tá an comhad gnóthach faoi láthair, bain triail eile as ar ball le do thoil", "Cannot download file" : "Ní féidir an comhad a íoslódáil", - "Your data directory is readable by other users." : "Tá d'eolaire sonraí inléite ag úsáideoirí eile.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Athraigh na ceadanna go 0770 le do thoil ionas nach féidir le húsáideoirí eile an t-eolaire a liostú.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Cinntigh go bhfuil comhad darb ainm \".ocdata\" i bhfréamh an eolaire sonraí." + "Login is too long" : "Tá logáil isteach ró-fhada" },"pluralForm" :"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);" }
\ No newline at end of file diff --git a/lib/l10n/gd.js b/lib/l10n/gd.js index c27a6bab48e..06e8f265aa3 100644 --- a/lib/l10n/gd.js +++ b/lib/l10n/gd.js @@ -14,7 +14,6 @@ OC.L10N.register( "Website" : "Làrach-lìn", "Address" : "Seòladh", "About" : "Mu dhèidhinn", - "Translate" : "Eadar-theangaich", - "Help" : "Cobhair" + "Translate" : "Eadar-theangaich" }, "nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;"); diff --git a/lib/l10n/gd.json b/lib/l10n/gd.json index 74dddce2e08..2b2cf5f1813 100644 --- a/lib/l10n/gd.json +++ b/lib/l10n/gd.json @@ -12,7 +12,6 @@ "Website" : "Làrach-lìn", "Address" : "Seòladh", "About" : "Mu dhèidhinn", - "Translate" : "Eadar-theangaich", - "Help" : "Cobhair" + "Translate" : "Eadar-theangaich" },"pluralForm" :"nplurals=4; plural=(n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3;" }
\ No newline at end of file diff --git a/lib/l10n/gl.js b/lib/l10n/gl.js index 93d38329e95..6318028550f 100644 --- a/lib/l10n/gl.js +++ b/lib/l10n/gl.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Precísase da versión %s ou superior do servidor.", "Server version %s or lower is required." : "Precísase da versión %s ou inferior do servidor.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "A conta que accede debe ser de administración, de subadministración ou ter dereitos especiais para acceder a este axuste", - "Your current IP address doesn’t allow you to perform admin actions" : "O seu enderezo IP actual non lle permite realizar accións de administración", + "Your current IP address doesn't allow you to perform admin actions" : "O seu enderezo IP actual non lle permite realizar accións de administración", "Logged in account must be an admin or sub admin" : "A conta que accede debe ser de administración ou de subadministración", "Logged in account must be an admin" : "A conta que accede debe ser de administración", "Wiping of device %s has started" : "Iniciouse a limpeza do dispositivo %s", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "A imaxe do avatar non é cadrada", "Files" : "Ficheiros", "View profile" : "Ver o perfil", + "same time" : "ao mesmo tempo", + "_%nh_::_%nh_" : ["%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s antes", + "%s behind" : "%s após", "Local time: %s" : "Hora local: %s", "today" : "hoxe", "tomorrow" : "mañá", @@ -81,6 +86,12 @@ OC.L10N.register( "seconds ago" : "segundos atrás", "Empty file" : "Ficheiro baleiro", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Non existe o módulo co ID: %s. Actíveo nos axustes das aplicacións ou contacte coa administración desta instancia.", + "No file conversion providers available" : "Non hai ningún provedor de conversión de ficheiros dispoñíbel", + "File is too large to convert" : "O ficheiro é demasiado grande para convertelo", + "Destination does not match conversion extension" : "O destino non coincide coa extensión de conversión", + "Could not convert file" : "Non foi posíbel converter o ficheiro", + "Destination does not exist" : "Non existe ese destino", + "Destination is not creatable" : "Non é posíbel crear o destino", "Dot files are not allowed" : "Non se admiten os ficheiros con punto", "\"%1$s\" is a forbidden file or folder name." : "«%1$s» é un nome de ficheiro ou cartafol prohibido.", "\"%1$s\" is a forbidden prefix for file or folder names." : "«%1$s» é un prefixo prohibido para os nomes de ficheiros ou cartafoles.", @@ -92,9 +103,16 @@ OC.L10N.register( "Invalid path" : "A ruta non é correcta.", "Failed to create file from template" : "Produciuse un fallo ao crear un ficheiro a partir do modelo", "Templates" : "Modelos", + "Storage %s cannot be moved" : "Non é posíbel mover o almacenamento %s", + "Moving a share (%s) into a shared folder is not allowed" : "Non está permitido mover un recurso compartido (%s) a un cartafol compartido", + "Moving a storage (%s) into a shared folder is not allowed" : "Non está permitido mover un almacenamento (%s) a un cartafol compartido", + "Moving a share (%s) into another share (%s) is not allowed" : "Non está permitido mover un recurso compartido (%s) cara a outro recurso compartido (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "Non está permitido mover un recurso compartido (%s) cara a outro almacenamento (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "Non está permitido mover un recurso compartido (%s) cara a un recurso compartido (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Non está permitido mover un almacenamento (%s) cara a outro almacenamento (%s)", "Path contains invalid segments" : "A ruta contén segmentos non válidos", "Filename is a reserved word" : "O nome de ficheiro é unha palabra reservada", - "Filename contains at least one invalid character" : "O nome de ficheiro contén algún carácter incorrecto", + "Filename contains at least one invalid character" : "O nome de ficheiro contén algún carácter non aceptado", "Filename is too long" : "O nome de ficheiro é longo de máis", "Empty filename is not allowed" : "Non está permitido deixar baleiro o nome de ficheiro", "App \"%s\" cannot be installed because appinfo file cannot be read." : "Non é posíbel instalar a aplicación «%s» por mor de non poder ler o ficheiro appinfo.", @@ -124,7 +142,6 @@ OC.L10N.register( "About" : "Sobre", "Display name" : "Nome para amosar", "Headline" : "Titular", - "Organisation" : "Organización", "Role" : "Cargo", "Pronouns" : "Pronomes", "Unknown account" : "Conta descoñecida", @@ -138,8 +155,8 @@ OC.L10N.register( "Oracle connection could not be established" : "Non foi posíbel estabelecer a conexión con Oracle", "Oracle Login and/or password not valid" : "O acceso de Oracle e/ou o contrasinal non son válidos", "PostgreSQL Login and/or password not valid" : "O acceso de PostgreSQL e/ou o contrasinal non son válidos", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X non é compatíbel e %s non funcionará correctamente nesta plataforma. Utilíceo baixo a súa responsabilidade!", - "For the best results, please consider using a GNU/Linux server instead." : "Para obter mellores resultados, considere o emprego dun servidor GNU/Linux no seu canto.", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X non é compatíbel e %s non funcionará correctamente nesta plataforma. Utilíceo baixo a súa responsabilidade!", + "For the best results, please consider using a GNU/Linux server instead." : "Para obter mellores resultados, considere o emprego dun servidor GNU/Linux en troques.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Semella que esta instancia de %s está a funcionar nun contorno PHP de 32 bisst e o open_basedir foi configurado no php.ini. Isto provocará problemas con ficheiros maiores de 4 GB e está absolutamente desaconsellado.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Retire o axuste de open_basedir no php.ini ou cambie a PHP de 64 bits.", "Set an admin Login." : "Definir un acceso de administración", @@ -149,7 +166,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Non se atopou a infraestrutura de compartición %s", "Sharing backend for %s not found" : "Non se atopou a infraestrutura de compartición para %s", "%1$s shared %2$s with you" : "%1$s compartiu %2$s con Vde.", - "Click the button below to open it." : "Prema no botón de embaixo para abrilo.", "Open %s" : "Abrir %s", "%1$s via %2$s" : "%1$s mediante %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s compartiu %2$s con Vde. e quere engadir:", @@ -169,6 +185,7 @@ OC.L10N.register( "You cannot share your root folder" : "Non pode compartir o seu cartafol raíz", "You are not allowed to share %s" : "Non ten permiso para compartir %s", "Valid permissions are required for sharing" : "Precisanse permisos válidos para compartir", + "File shares cannot have create or delete permissions" : "As comparticións de ficheiros non poden crear ou eliminar permisos", "Cannot increase permissions of %s" : "Non é posíbel incrementar os permisos de %s", "Shares need at least read permissions" : "As comparticións necesitan polo menos permisos de lectura", "Files cannot be shared with delete permissions" : "Non é posíbel compartir ficheiros con permisos de eliminación", @@ -183,16 +200,15 @@ OC.L10N.register( "Path is already shared with this group" : "A ruta xa está compartida con este grupo", "Link sharing is not allowed" : "Non se permite compartir ligazóns", "Public upload is not allowed" : "Non se permite o envío público", - "Path contains files shared with you" : "A ruta contén ficheiros compartidos con Vde.", "Sharing is disabled" : "A compartición está desactivada", "Sharing is disabled for you" : "A compartición está desactivada para Vde.", "Cannot share with the share owner" : "Non é posíbel compartir co propietario do compartido", "Share does not have a full ID" : "A compartición non ten unha ID completa", "Cannot change share type" : "Non é posíbel cambiar o tipo de compartición", "Can only update recipient on user shares" : "Só é posíbel actualizar o destinatario nas comparticións por usuarios", - "Cannot enable sending the password by Talk with an empty password" : "Non é posíbel activar o envío do contrasinal por Talk cun contrasinal baleiro", - "Cannot enable sending the password by Talk without setting a new password" : "Non é posíbel activar o envío do contrasinal por Talk sen definir un novo contrasinal", - "Cannot disable sending the password by Talk without setting a new password" : "Non é posíbel desactivar o envío do contrasinal por Talk sen definir un novo contrasinal", + "Cannot enable sending the password by Talk with an empty password" : "Non é posíbel activar o envío do contrasinal mediante Parladoiro cun contrasinal baleiro", + "Cannot enable sending the password by Talk without setting a new password" : "Non é posíbel activar o envío do contrasinal mediante Parladoiro sen definir un novo contrasinal", + "Cannot disable sending the password by Talk without setting a new password" : "Non é posíbel desactivar o envío do contrasinal medainte sen definir un novo contrasinal", "Share provider does not support accepting" : "O provedor de comparticións non admite a aceptación", "Cannot change target of link share" : "Non é posíbel cambiar o destino da ligazón compartida", "Invalid share recipient" : "Destinatario de compartición incorrecto", @@ -311,7 +327,6 @@ OC.L10N.register( "The audio to transcribe" : "O audio para transcribir", "Transcription" : "Transcrición", "The transcribed text" : "O texto transcrito", - "ContextAgent" : "Axente de contexto", "Chat with an agent" : "Parolar cun axente", "Chat message" : "Mensaxe de parola", "A chat message to send to the agent." : "Unha mensaxe de parola para enviar ao axente.", @@ -384,6 +399,12 @@ OC.L10N.register( "Original text" : "Texto orixinal", "The original text to generate a headline for" : "O texto orixinal para xerar un titular", "The generated headline" : "O titular xerado", + "Proofread" : "Revisión", + "Proofreads a text and lists corrections" : "Revisa un texto e enumera as correccións", + "Text" : "Texto", + "The text to proofread" : "O texto para revisar", + "Corrections" : "Correccións", + "The corrections that should be made in your text" : "As correccións que se deben facer no seu texto", "Reformulate text" : "Reformular texto", "Takes a text and reformulates it" : "Toma un texto e reformúlao", "Write a text that you want the assistant to reformulate" : "Escriba un texto que queira que sexa reformulado polo asistente", @@ -419,41 +440,8 @@ OC.L10N.register( "Generate headline" : "Xerar titular", "Summarizes text by reducing its length without losing key information." : "Resume o texto reducindo a súa lonxitude sen perder a información clave.", "Extracts topics from a text and outputs them separated by commas." : "Extrae temas dun texto e amósaos separados por comas.", - "Education Edition" : "Edición para educación", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "O usuario que accede debe ser de administración, de subadministración ou ter dereitos especiais para acceder a este axuste", - "Logged in user must be an admin or sub admin" : "O usuario que accede debe ser de administración ou de subadministración", - "Logged in user must be an admin" : "O usuario que accede debe ser de administración", - "File name is a reserved word" : "O nome de ficheiro é unha palabra reservada", - "File name contains at least one invalid character" : "O nome de ficheiro contén algún carácter incorrecto", - "File name is too long" : "O nome de ficheiro é longo de máis", - "Help" : "Axuda", - "Users" : "Usuarios", - "Unknown user" : "Usuario descoñecido", - "Enter the database username and name for %s" : "Introduza o nome de usuario da base de datos e o nome para %s", - "Enter the database username for %s" : "Introduza o nome de usuario da base de datos para %s", - "MySQL username and/or password not valid" : "Nome de usuario e/ou contrasinal de MySQL incorrecto", - "Oracle username and/or password not valid" : "O nome de usuario e/ou contrasinal de Oracle é incorrecto", - "PostgreSQL username and/or password not valid" : "Nome de usuario e/ou contrasinal de PostgreSQL incorrecto", - "Set an admin username." : "Estabeleza un nome de usuario administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartiu «%2$s» con Vde. e quere engadir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartiu «%2$s» con Vde. e quere engadir", - "»%s« added a note to a file shared with you" : "«%s» engadiu unha nota a un ficheiro compartido con Vde.", - "Open »%s«" : "Abrir «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "Fallou a compartición de %s por mor de que este elemento xa foi compartido co usuario %s", - "%1$s shared »%2$s« with you" : "%1$s compartiu «%2$s» con Vde.", - "%1$s shared »%2$s« with you." : "%1$s compartiu «%2$s» con Vde.", - "The username is already being used" : "Este nome de usuario xa está a ser usado", - "Could not create user" : "Non foi posíbel crear o usuario", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Só se permiten os seguintes caracteres nun nome de usuario: «a-z», «A-Z», «0-9», espazos e «_.@-'»", - "A valid username must be provided" : "Debe fornecer un nome de usuario correcto", - "Username contains whitespace at the beginning or at the end" : "O nome de usuario contén un espazo en branco no inicio ou no final", - "Username must not consist of dots only" : "O nome de usuario non debe consistir só de puntos", - "Username is invalid because files already exist for this user" : "O nome de usuario non é válido porque xa existen ficheiros para este usuario", - "User disabled" : "Usuario desactivado", + "Organisation" : "Organización", "File is currently busy, please try again later" : "O ficheiro está ocupado neste momento, ténteo máis adiante.", - "Cannot download file" : "Non é posíbel descargar o ficheiro", - "Your data directory is readable by other users." : "Outros usuarios poden ler o seu directorio de datos.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Cambie os permisos a 0770 para que o directorio non poida ser listado por outros usuarios.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegúrese de que existe un ficheiro chamado «.ocdata» na raíz do directorio de datos." + "Cannot download file" : "Non é posíbel descargar o ficheiro" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/gl.json b/lib/l10n/gl.json index 4063a06eeb3..dee39bf1ac5 100644 --- a/lib/l10n/gl.json +++ b/lib/l10n/gl.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Precísase da versión %s ou superior do servidor.", "Server version %s or lower is required." : "Precísase da versión %s ou inferior do servidor.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "A conta que accede debe ser de administración, de subadministración ou ter dereitos especiais para acceder a este axuste", - "Your current IP address doesn’t allow you to perform admin actions" : "O seu enderezo IP actual non lle permite realizar accións de administración", + "Your current IP address doesn't allow you to perform admin actions" : "O seu enderezo IP actual non lle permite realizar accións de administración", "Logged in account must be an admin or sub admin" : "A conta que accede debe ser de administración ou de subadministración", "Logged in account must be an admin" : "A conta que accede debe ser de administración", "Wiping of device %s has started" : "Iniciouse a limpeza do dispositivo %s", @@ -57,6 +57,11 @@ "Avatar image is not square" : "A imaxe do avatar non é cadrada", "Files" : "Ficheiros", "View profile" : "Ver o perfil", + "same time" : "ao mesmo tempo", + "_%nh_::_%nh_" : ["%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s antes", + "%s behind" : "%s após", "Local time: %s" : "Hora local: %s", "today" : "hoxe", "tomorrow" : "mañá", @@ -79,6 +84,12 @@ "seconds ago" : "segundos atrás", "Empty file" : "Ficheiro baleiro", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Non existe o módulo co ID: %s. Actíveo nos axustes das aplicacións ou contacte coa administración desta instancia.", + "No file conversion providers available" : "Non hai ningún provedor de conversión de ficheiros dispoñíbel", + "File is too large to convert" : "O ficheiro é demasiado grande para convertelo", + "Destination does not match conversion extension" : "O destino non coincide coa extensión de conversión", + "Could not convert file" : "Non foi posíbel converter o ficheiro", + "Destination does not exist" : "Non existe ese destino", + "Destination is not creatable" : "Non é posíbel crear o destino", "Dot files are not allowed" : "Non se admiten os ficheiros con punto", "\"%1$s\" is a forbidden file or folder name." : "«%1$s» é un nome de ficheiro ou cartafol prohibido.", "\"%1$s\" is a forbidden prefix for file or folder names." : "«%1$s» é un prefixo prohibido para os nomes de ficheiros ou cartafoles.", @@ -90,9 +101,16 @@ "Invalid path" : "A ruta non é correcta.", "Failed to create file from template" : "Produciuse un fallo ao crear un ficheiro a partir do modelo", "Templates" : "Modelos", + "Storage %s cannot be moved" : "Non é posíbel mover o almacenamento %s", + "Moving a share (%s) into a shared folder is not allowed" : "Non está permitido mover un recurso compartido (%s) a un cartafol compartido", + "Moving a storage (%s) into a shared folder is not allowed" : "Non está permitido mover un almacenamento (%s) a un cartafol compartido", + "Moving a share (%s) into another share (%s) is not allowed" : "Non está permitido mover un recurso compartido (%s) cara a outro recurso compartido (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "Non está permitido mover un recurso compartido (%s) cara a outro almacenamento (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "Non está permitido mover un recurso compartido (%s) cara a un recurso compartido (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Non está permitido mover un almacenamento (%s) cara a outro almacenamento (%s)", "Path contains invalid segments" : "A ruta contén segmentos non válidos", "Filename is a reserved word" : "O nome de ficheiro é unha palabra reservada", - "Filename contains at least one invalid character" : "O nome de ficheiro contén algún carácter incorrecto", + "Filename contains at least one invalid character" : "O nome de ficheiro contén algún carácter non aceptado", "Filename is too long" : "O nome de ficheiro é longo de máis", "Empty filename is not allowed" : "Non está permitido deixar baleiro o nome de ficheiro", "App \"%s\" cannot be installed because appinfo file cannot be read." : "Non é posíbel instalar a aplicación «%s» por mor de non poder ler o ficheiro appinfo.", @@ -122,7 +140,6 @@ "About" : "Sobre", "Display name" : "Nome para amosar", "Headline" : "Titular", - "Organisation" : "Organización", "Role" : "Cargo", "Pronouns" : "Pronomes", "Unknown account" : "Conta descoñecida", @@ -136,8 +153,8 @@ "Oracle connection could not be established" : "Non foi posíbel estabelecer a conexión con Oracle", "Oracle Login and/or password not valid" : "O acceso de Oracle e/ou o contrasinal non son válidos", "PostgreSQL Login and/or password not valid" : "O acceso de PostgreSQL e/ou o contrasinal non son válidos", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X non é compatíbel e %s non funcionará correctamente nesta plataforma. Utilíceo baixo a súa responsabilidade!", - "For the best results, please consider using a GNU/Linux server instead." : "Para obter mellores resultados, considere o emprego dun servidor GNU/Linux no seu canto.", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X non é compatíbel e %s non funcionará correctamente nesta plataforma. Utilíceo baixo a súa responsabilidade!", + "For the best results, please consider using a GNU/Linux server instead." : "Para obter mellores resultados, considere o emprego dun servidor GNU/Linux en troques.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Semella que esta instancia de %s está a funcionar nun contorno PHP de 32 bisst e o open_basedir foi configurado no php.ini. Isto provocará problemas con ficheiros maiores de 4 GB e está absolutamente desaconsellado.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Retire o axuste de open_basedir no php.ini ou cambie a PHP de 64 bits.", "Set an admin Login." : "Definir un acceso de administración", @@ -147,7 +164,6 @@ "Sharing backend %s not found" : "Non se atopou a infraestrutura de compartición %s", "Sharing backend for %s not found" : "Non se atopou a infraestrutura de compartición para %s", "%1$s shared %2$s with you" : "%1$s compartiu %2$s con Vde.", - "Click the button below to open it." : "Prema no botón de embaixo para abrilo.", "Open %s" : "Abrir %s", "%1$s via %2$s" : "%1$s mediante %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s compartiu %2$s con Vde. e quere engadir:", @@ -167,6 +183,7 @@ "You cannot share your root folder" : "Non pode compartir o seu cartafol raíz", "You are not allowed to share %s" : "Non ten permiso para compartir %s", "Valid permissions are required for sharing" : "Precisanse permisos válidos para compartir", + "File shares cannot have create or delete permissions" : "As comparticións de ficheiros non poden crear ou eliminar permisos", "Cannot increase permissions of %s" : "Non é posíbel incrementar os permisos de %s", "Shares need at least read permissions" : "As comparticións necesitan polo menos permisos de lectura", "Files cannot be shared with delete permissions" : "Non é posíbel compartir ficheiros con permisos de eliminación", @@ -181,16 +198,15 @@ "Path is already shared with this group" : "A ruta xa está compartida con este grupo", "Link sharing is not allowed" : "Non se permite compartir ligazóns", "Public upload is not allowed" : "Non se permite o envío público", - "Path contains files shared with you" : "A ruta contén ficheiros compartidos con Vde.", "Sharing is disabled" : "A compartición está desactivada", "Sharing is disabled for you" : "A compartición está desactivada para Vde.", "Cannot share with the share owner" : "Non é posíbel compartir co propietario do compartido", "Share does not have a full ID" : "A compartición non ten unha ID completa", "Cannot change share type" : "Non é posíbel cambiar o tipo de compartición", "Can only update recipient on user shares" : "Só é posíbel actualizar o destinatario nas comparticións por usuarios", - "Cannot enable sending the password by Talk with an empty password" : "Non é posíbel activar o envío do contrasinal por Talk cun contrasinal baleiro", - "Cannot enable sending the password by Talk without setting a new password" : "Non é posíbel activar o envío do contrasinal por Talk sen definir un novo contrasinal", - "Cannot disable sending the password by Talk without setting a new password" : "Non é posíbel desactivar o envío do contrasinal por Talk sen definir un novo contrasinal", + "Cannot enable sending the password by Talk with an empty password" : "Non é posíbel activar o envío do contrasinal mediante Parladoiro cun contrasinal baleiro", + "Cannot enable sending the password by Talk without setting a new password" : "Non é posíbel activar o envío do contrasinal mediante Parladoiro sen definir un novo contrasinal", + "Cannot disable sending the password by Talk without setting a new password" : "Non é posíbel desactivar o envío do contrasinal medainte sen definir un novo contrasinal", "Share provider does not support accepting" : "O provedor de comparticións non admite a aceptación", "Cannot change target of link share" : "Non é posíbel cambiar o destino da ligazón compartida", "Invalid share recipient" : "Destinatario de compartición incorrecto", @@ -309,7 +325,6 @@ "The audio to transcribe" : "O audio para transcribir", "Transcription" : "Transcrición", "The transcribed text" : "O texto transcrito", - "ContextAgent" : "Axente de contexto", "Chat with an agent" : "Parolar cun axente", "Chat message" : "Mensaxe de parola", "A chat message to send to the agent." : "Unha mensaxe de parola para enviar ao axente.", @@ -382,6 +397,12 @@ "Original text" : "Texto orixinal", "The original text to generate a headline for" : "O texto orixinal para xerar un titular", "The generated headline" : "O titular xerado", + "Proofread" : "Revisión", + "Proofreads a text and lists corrections" : "Revisa un texto e enumera as correccións", + "Text" : "Texto", + "The text to proofread" : "O texto para revisar", + "Corrections" : "Correccións", + "The corrections that should be made in your text" : "As correccións que se deben facer no seu texto", "Reformulate text" : "Reformular texto", "Takes a text and reformulates it" : "Toma un texto e reformúlao", "Write a text that you want the assistant to reformulate" : "Escriba un texto que queira que sexa reformulado polo asistente", @@ -417,41 +438,8 @@ "Generate headline" : "Xerar titular", "Summarizes text by reducing its length without losing key information." : "Resume o texto reducindo a súa lonxitude sen perder a información clave.", "Extracts topics from a text and outputs them separated by commas." : "Extrae temas dun texto e amósaos separados por comas.", - "Education Edition" : "Edición para educación", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "O usuario que accede debe ser de administración, de subadministración ou ter dereitos especiais para acceder a este axuste", - "Logged in user must be an admin or sub admin" : "O usuario que accede debe ser de administración ou de subadministración", - "Logged in user must be an admin" : "O usuario que accede debe ser de administración", - "File name is a reserved word" : "O nome de ficheiro é unha palabra reservada", - "File name contains at least one invalid character" : "O nome de ficheiro contén algún carácter incorrecto", - "File name is too long" : "O nome de ficheiro é longo de máis", - "Help" : "Axuda", - "Users" : "Usuarios", - "Unknown user" : "Usuario descoñecido", - "Enter the database username and name for %s" : "Introduza o nome de usuario da base de datos e o nome para %s", - "Enter the database username for %s" : "Introduza o nome de usuario da base de datos para %s", - "MySQL username and/or password not valid" : "Nome de usuario e/ou contrasinal de MySQL incorrecto", - "Oracle username and/or password not valid" : "O nome de usuario e/ou contrasinal de Oracle é incorrecto", - "PostgreSQL username and/or password not valid" : "Nome de usuario e/ou contrasinal de PostgreSQL incorrecto", - "Set an admin username." : "Estabeleza un nome de usuario administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartiu «%2$s» con Vde. e quere engadir:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartiu «%2$s» con Vde. e quere engadir", - "»%s« added a note to a file shared with you" : "«%s» engadiu unha nota a un ficheiro compartido con Vde.", - "Open »%s«" : "Abrir «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "Fallou a compartición de %s por mor de que este elemento xa foi compartido co usuario %s", - "%1$s shared »%2$s« with you" : "%1$s compartiu «%2$s» con Vde.", - "%1$s shared »%2$s« with you." : "%1$s compartiu «%2$s» con Vde.", - "The username is already being used" : "Este nome de usuario xa está a ser usado", - "Could not create user" : "Non foi posíbel crear o usuario", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Só se permiten os seguintes caracteres nun nome de usuario: «a-z», «A-Z», «0-9», espazos e «_.@-'»", - "A valid username must be provided" : "Debe fornecer un nome de usuario correcto", - "Username contains whitespace at the beginning or at the end" : "O nome de usuario contén un espazo en branco no inicio ou no final", - "Username must not consist of dots only" : "O nome de usuario non debe consistir só de puntos", - "Username is invalid because files already exist for this user" : "O nome de usuario non é válido porque xa existen ficheiros para este usuario", - "User disabled" : "Usuario desactivado", + "Organisation" : "Organización", "File is currently busy, please try again later" : "O ficheiro está ocupado neste momento, ténteo máis adiante.", - "Cannot download file" : "Non é posíbel descargar o ficheiro", - "Your data directory is readable by other users." : "Outros usuarios poden ler o seu directorio de datos.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Cambie os permisos a 0770 para que o directorio non poida ser listado por outros usuarios.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asegúrese de que existe un ficheiro chamado «.ocdata» na raíz do directorio de datos." + "Cannot download file" : "Non é posíbel descargar o ficheiro" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/he.js b/lib/l10n/he.js index ecab05ae342..f323b3980b3 100644 --- a/lib/l10n/he.js +++ b/lib/l10n/he.js @@ -25,6 +25,7 @@ OC.L10N.register( "Invalid image" : "תמונה לא חוקית", "Avatar image is not square" : "התמונה המייצגת אינה מרובעת", "Files" : "קבצים", + "_%nh_::_%nh_" : ["שעה","שעתיים","%n שע׳"], "today" : "היום", "tomorrow" : "מחר", "yesterday" : "אתמול", @@ -67,7 +68,6 @@ OC.L10N.register( "Additional settings" : "הגדרות נוספות", "You need to enter details of an existing account." : "עליך להקליד פרטים של חשבון קיים.", "Oracle connection could not be established" : "לא ניתן היה ליצור חיבור Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X אינו נתמך ו- %s לא יעבוד כשורה בפלטפורמה זו. ניתן לקחת סיכון ולהשתמש באחריותך! ", "For the best results, please consider using a GNU/Linux server instead." : "לתוצאות הכי טובות, יש לשקול שימוש בשרת GNU/Linux במקום.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "נראה ש- %s עובד על בסיס סביבת 32-bit PHP ושה- open_basedir הוגדר בקובץ php.ini. מצב זה יוביל לבעיות עם קבצים הגדולים מ- 4 GB ואינו מומלץ לחלוטין.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "יש להסיר את הגדרת open_basedir מתוך קובץ php.ini או להחליף לסביבת 64-bit PHP.", @@ -75,7 +75,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "צד אחורי לשיתוף %s חייב ליישם את ממשק OCP\\Share_Backend", "Sharing backend %s not found" : "צד אחורי לשיתוף %s לא נמצא", "Sharing backend for %s not found" : "צד אחורי לשיתוף של %s לא נמצא", - "Click the button below to open it." : "יש ללחוץ על הכפתור להלן כדי לפתוח אותו.", "%1$s via %2$s" : "%1$s דרך %2$s", "Unknown share type" : "סוג שיתוף אינו מוכר", "You are not allowed to share %s" : "אינך רשאי/ת לשתף %s", @@ -153,37 +152,10 @@ OC.L10N.register( "Storage connection error. %s" : "שגיאת חיבור אחסון. %s", "Storage is temporarily not available" : "האחסון אינו זמין כרגע", "Storage connection timeout. %s" : "פסק זמן חיבור אחסון. %s", + "Text" : "טקסט", "Summary" : "תקציר", "Translate" : "תרגום", "Result" : "תוצאה", - "Education Edition" : "מהדורה חינוכית", - "Logged in user must be an admin" : "על המשתמש שנכנס להיות מנהל", - "File name is a reserved word" : "שם קובץ הוא מילה שמורה", - "File name contains at least one invalid character" : "שם הקובץ כולל לפחות תו אחד לא חוקי", - "File name is too long" : "שם קובץ ארוך מדי", - "Help" : "עזרה", - "Users" : "משתמשים", - "Unknown user" : "משתמש לא ידוע", - "MySQL username and/or password not valid" : "שם המשתמש ו/או הססמה של MySQL אינם תקינים", - "Oracle username and/or password not valid" : "שם משתמש ו/או סיסמת Oracle אינם תקפים", - "PostgreSQL username and/or password not valid" : "שם משתמש ו/או סיסמת PostgreSQL אינם תקפים", - "Set an admin username." : "קביעת שם משתמש מנהל", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s שיתף » %2$s« איתך, ורוצה להוסיף:", - "%1$s shared »%2$s« with you and wants to add" : "%1$sשיתף »%2$s« איתך, ורוצה להוסיף:", - "»%s« added a note to a file shared with you" : "התווספה הערה על קובץ ששותף את על ידי „%s”", - "Open »%s«" : "פתיחת „%s”", - "Sharing %s failed, because this item is already shared with user %s" : "השיתוף %s נכשל, כיוון שהפריט כבר משותף עם משתמש %s", - "%1$s shared »%2$s« with you" : "%2$s שותף אתך על ידי %1$s", - "%1$s shared »%2$s« with you." : "„%2$s” שותף אתך על ידי %1$s.", - "The username is already being used" : "השם משתמש כבר בשימוש", - "Could not create user" : "לא ניתן ליצור משתמש", - "A valid username must be provided" : "יש לספק שם משתמש תקני", - "Username contains whitespace at the beginning or at the end" : "שם המשתמש מכיל רווח בתחילתו או בסופו", - "Username must not consist of dots only" : "שם המשתמש לא יכול להיות מורכב מנקודות בלבד", - "Username is invalid because files already exist for this user" : "שם המשתמש שגוי כיוון שכבר קיימים קבצים למשתמש הזה", - "User disabled" : "משתמש מנוטרל", - "File is currently busy, please try again later" : "הקובץ בשימוש כרגע, יש לנסות שוב מאוחר יותר", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "יש לשנות את ההרשאות ל- 0770 כך שהתיקייה לא תרשם על ידי משתמשים אחרים.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "נא לוודא שיש קובץ בשם „.ocdata” בבסיס תיקיית הנתונים שלך." + "File is currently busy, please try again later" : "הקובץ בשימוש כרגע, יש לנסות שוב מאוחר יותר" }, "nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;"); diff --git a/lib/l10n/he.json b/lib/l10n/he.json index b4238dc2f48..68fd61703fd 100644 --- a/lib/l10n/he.json +++ b/lib/l10n/he.json @@ -23,6 +23,7 @@ "Invalid image" : "תמונה לא חוקית", "Avatar image is not square" : "התמונה המייצגת אינה מרובעת", "Files" : "קבצים", + "_%nh_::_%nh_" : ["שעה","שעתיים","%n שע׳"], "today" : "היום", "tomorrow" : "מחר", "yesterday" : "אתמול", @@ -65,7 +66,6 @@ "Additional settings" : "הגדרות נוספות", "You need to enter details of an existing account." : "עליך להקליד פרטים של חשבון קיים.", "Oracle connection could not be established" : "לא ניתן היה ליצור חיבור Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X אינו נתמך ו- %s לא יעבוד כשורה בפלטפורמה זו. ניתן לקחת סיכון ולהשתמש באחריותך! ", "For the best results, please consider using a GNU/Linux server instead." : "לתוצאות הכי טובות, יש לשקול שימוש בשרת GNU/Linux במקום.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "נראה ש- %s עובד על בסיס סביבת 32-bit PHP ושה- open_basedir הוגדר בקובץ php.ini. מצב זה יוביל לבעיות עם קבצים הגדולים מ- 4 GB ואינו מומלץ לחלוטין.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "יש להסיר את הגדרת open_basedir מתוך קובץ php.ini או להחליף לסביבת 64-bit PHP.", @@ -73,7 +73,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "צד אחורי לשיתוף %s חייב ליישם את ממשק OCP\\Share_Backend", "Sharing backend %s not found" : "צד אחורי לשיתוף %s לא נמצא", "Sharing backend for %s not found" : "צד אחורי לשיתוף של %s לא נמצא", - "Click the button below to open it." : "יש ללחוץ על הכפתור להלן כדי לפתוח אותו.", "%1$s via %2$s" : "%1$s דרך %2$s", "Unknown share type" : "סוג שיתוף אינו מוכר", "You are not allowed to share %s" : "אינך רשאי/ת לשתף %s", @@ -151,37 +150,10 @@ "Storage connection error. %s" : "שגיאת חיבור אחסון. %s", "Storage is temporarily not available" : "האחסון אינו זמין כרגע", "Storage connection timeout. %s" : "פסק זמן חיבור אחסון. %s", + "Text" : "טקסט", "Summary" : "תקציר", "Translate" : "תרגום", "Result" : "תוצאה", - "Education Edition" : "מהדורה חינוכית", - "Logged in user must be an admin" : "על המשתמש שנכנס להיות מנהל", - "File name is a reserved word" : "שם קובץ הוא מילה שמורה", - "File name contains at least one invalid character" : "שם הקובץ כולל לפחות תו אחד לא חוקי", - "File name is too long" : "שם קובץ ארוך מדי", - "Help" : "עזרה", - "Users" : "משתמשים", - "Unknown user" : "משתמש לא ידוע", - "MySQL username and/or password not valid" : "שם המשתמש ו/או הססמה של MySQL אינם תקינים", - "Oracle username and/or password not valid" : "שם משתמש ו/או סיסמת Oracle אינם תקפים", - "PostgreSQL username and/or password not valid" : "שם משתמש ו/או סיסמת PostgreSQL אינם תקפים", - "Set an admin username." : "קביעת שם משתמש מנהל", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s שיתף » %2$s« איתך, ורוצה להוסיף:", - "%1$s shared »%2$s« with you and wants to add" : "%1$sשיתף »%2$s« איתך, ורוצה להוסיף:", - "»%s« added a note to a file shared with you" : "התווספה הערה על קובץ ששותף את על ידי „%s”", - "Open »%s«" : "פתיחת „%s”", - "Sharing %s failed, because this item is already shared with user %s" : "השיתוף %s נכשל, כיוון שהפריט כבר משותף עם משתמש %s", - "%1$s shared »%2$s« with you" : "%2$s שותף אתך על ידי %1$s", - "%1$s shared »%2$s« with you." : "„%2$s” שותף אתך על ידי %1$s.", - "The username is already being used" : "השם משתמש כבר בשימוש", - "Could not create user" : "לא ניתן ליצור משתמש", - "A valid username must be provided" : "יש לספק שם משתמש תקני", - "Username contains whitespace at the beginning or at the end" : "שם המשתמש מכיל רווח בתחילתו או בסופו", - "Username must not consist of dots only" : "שם המשתמש לא יכול להיות מורכב מנקודות בלבד", - "Username is invalid because files already exist for this user" : "שם המשתמש שגוי כיוון שכבר קיימים קבצים למשתמש הזה", - "User disabled" : "משתמש מנוטרל", - "File is currently busy, please try again later" : "הקובץ בשימוש כרגע, יש לנסות שוב מאוחר יותר", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "יש לשנות את ההרשאות ל- 0770 כך שהתיקייה לא תרשם על ידי משתמשים אחרים.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "נא לוודא שיש קובץ בשם „.ocdata” בבסיס תיקיית הנתונים שלך." + "File is currently busy, please try again later" : "הקובץ בשימוש כרגע, יש לנסות שוב מאוחר יותר" },"pluralForm" :"nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;" }
\ No newline at end of file diff --git a/lib/l10n/hr.js b/lib/l10n/hr.js index e69eb007a63..792c3ecf87f 100644 --- a/lib/l10n/hr.js +++ b/lib/l10n/hr.js @@ -50,6 +50,7 @@ OC.L10N.register( "Avatar image is not square" : "Slika avatara nije kvadratna", "Files" : "Datoteke", "View profile" : "Prikaži profil", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], "today" : "danas", "tomorrow" : "sutra", "yesterday" : "jučer", @@ -98,12 +99,10 @@ OC.L10N.register( "Profile picture" : "Profilna slika", "About" : "Informacije", "Headline" : "Naslov", - "Organisation" : "Organizacija", "Role" : "Uloga", "Additional settings" : "Dodatne postavke", "You need to enter details of an existing account." : "Trebate unijeti informacije o postojećem računu.", "Oracle connection could not be established" : "Nije moguće uspostaviti vezu s bazom podataka Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nije podržan i %s na ovoj platformi neće raditi kako treba. Koristite na vlastiti rizik!", "For the best results, please consider using a GNU/Linux server instead." : "Za najbolje rezultate razmotrite mogućnost korištenja poslužitelja GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Čini se da se ova %s instanca izvodi u 32-bitnom PHP okruženju, a open_basedir je konfiguriran u php.ini. To će dovesti do problema s datotekama većim od 4 GB i stoga se ne preporučuje.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Uklonite postavku open_basedir iz datoteke php.ini ili se prebacite na 64-bitni PHP.", @@ -112,7 +111,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Pozadina za dijeljenje %s mora implementirati sučelje OCP\\Share_Backend", "Sharing backend %s not found" : "Pozadina za dijeljenje %s nije pronađena", "Sharing backend for %s not found" : "Pozadina za dijeljenje za %s nije pronađena", - "Click the button below to open it." : "Kliknite gumb u nastavku za otvaranje.", "%1$s via %2$s" : "%1$s putem %2$s", "Unknown share type" : "Nepoznata vrsta dijeljenja", "You are not allowed to share %s" : "Nije vam dopušteno dijeliti %s", @@ -197,39 +195,11 @@ OC.L10N.register( "Storage connection error. %s" : "Pogreška veze pohrane. %s", "Storage is temporarily not available" : "Pohrana privremeno nije dostupna", "Storage connection timeout. %s" : "Istek veze pohrane. %s", + "Text" : "Tekst", "Summary" : "Sažetak", "Translate" : "Prevedi", "Result" : "Rezultat", - "Education Edition" : "Obrazovno izdanje", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Prijavljeni korisnik mora biti administrator, podadministrator ili imati posebna prava za pristupanje ovoj postavci", - "Logged in user must be an admin or sub admin" : "Prijavljeni korisnik mora biti administrator ili podadministrator", - "Logged in user must be an admin" : "Korisnik koji je prijavljen mora biti administrator", - "File name is a reserved word" : "Naziv datoteke je rezervirana riječ", - "File name contains at least one invalid character" : "Naziv datoteke sadrži barem jedan nevažeći znak", - "File name is too long" : "Naziv datoteke je predugačak", - "Help" : "Pomoć", - "Users" : "Korisnici", - "Unknown user" : "Nepoznat korisnik", - "MySQL username and/or password not valid" : "Neispravno korisničko ime i/ili zaporka baze podataka MySQL", - "Oracle username and/or password not valid" : "Neispravno korisničko ime i/ili zaporka baze podataka Oracle", - "PostgreSQL username and/or password not valid" : "Neispravno korisničko ime i/ili zaporka baze podataka PostgreSQL", - "Set an admin username." : "Postavite korisničko ime administratora.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s dijeli »%2$s« s vama i želi dodati:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s dijeli »%2$s« s vama i želi dodati", - "»%s« added a note to a file shared with you" : "»%s« je dodao bilješku datoteci koju dijeli s vama", - "Open »%s«" : "Otvori »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Dijeljenje %s nije uspjelo jer je ova stavka već podijeljena s korisnikom %s", - "%1$s shared »%2$s« with you" : "%1$s dijeli »%2$s« s vama", - "%1$s shared »%2$s« with you." : "%1$s dijeli »%2$s« s vama.", - "The username is already being used" : "Korisničko ime se već koristi", - "Could not create user" : "Nije moguće stvoriti korisnika", - "A valid username must be provided" : "Nužno je navesti ispravno korisničko ime", - "Username contains whitespace at the beginning or at the end" : "Korisničko ime sadrži bijeli prostor na početku ili na kraju", - "Username must not consist of dots only" : "Korisničko ime ne smije se sastojati samo od točkica", - "Username is invalid because files already exist for this user" : "Korisničko ime je nevažeće jer već postoje datoteke za ovog korisnika", - "User disabled" : "Korisnik je onemogućen", - "File is currently busy, please try again later" : "Datoteka je trenutno zauzeta, pokušajte ponovo kasnije", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Promijenite dozvole na 0770 tako da se tim direktorijem ne mogu služiti drugi korisnici.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Provjerite postoji li datoteka pod nazivom „.ocdata” u korijenu podatkovnog direktorija." + "Organisation" : "Organizacija", + "File is currently busy, please try again later" : "Datoteka je trenutno zauzeta, pokušajte ponovo kasnije" }, "nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"); diff --git a/lib/l10n/hr.json b/lib/l10n/hr.json index 0a28b48d058..71ea17ced9c 100644 --- a/lib/l10n/hr.json +++ b/lib/l10n/hr.json @@ -48,6 +48,7 @@ "Avatar image is not square" : "Slika avatara nije kvadratna", "Files" : "Datoteke", "View profile" : "Prikaži profil", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], "today" : "danas", "tomorrow" : "sutra", "yesterday" : "jučer", @@ -96,12 +97,10 @@ "Profile picture" : "Profilna slika", "About" : "Informacije", "Headline" : "Naslov", - "Organisation" : "Organizacija", "Role" : "Uloga", "Additional settings" : "Dodatne postavke", "You need to enter details of an existing account." : "Trebate unijeti informacije o postojećem računu.", "Oracle connection could not be established" : "Nije moguće uspostaviti vezu s bazom podataka Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nije podržan i %s na ovoj platformi neće raditi kako treba. Koristite na vlastiti rizik!", "For the best results, please consider using a GNU/Linux server instead." : "Za najbolje rezultate razmotrite mogućnost korištenja poslužitelja GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Čini se da se ova %s instanca izvodi u 32-bitnom PHP okruženju, a open_basedir je konfiguriran u php.ini. To će dovesti do problema s datotekama većim od 4 GB i stoga se ne preporučuje.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Uklonite postavku open_basedir iz datoteke php.ini ili se prebacite na 64-bitni PHP.", @@ -110,7 +109,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Pozadina za dijeljenje %s mora implementirati sučelje OCP\\Share_Backend", "Sharing backend %s not found" : "Pozadina za dijeljenje %s nije pronađena", "Sharing backend for %s not found" : "Pozadina za dijeljenje za %s nije pronađena", - "Click the button below to open it." : "Kliknite gumb u nastavku za otvaranje.", "%1$s via %2$s" : "%1$s putem %2$s", "Unknown share type" : "Nepoznata vrsta dijeljenja", "You are not allowed to share %s" : "Nije vam dopušteno dijeliti %s", @@ -195,39 +193,11 @@ "Storage connection error. %s" : "Pogreška veze pohrane. %s", "Storage is temporarily not available" : "Pohrana privremeno nije dostupna", "Storage connection timeout. %s" : "Istek veze pohrane. %s", + "Text" : "Tekst", "Summary" : "Sažetak", "Translate" : "Prevedi", "Result" : "Rezultat", - "Education Edition" : "Obrazovno izdanje", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Prijavljeni korisnik mora biti administrator, podadministrator ili imati posebna prava za pristupanje ovoj postavci", - "Logged in user must be an admin or sub admin" : "Prijavljeni korisnik mora biti administrator ili podadministrator", - "Logged in user must be an admin" : "Korisnik koji je prijavljen mora biti administrator", - "File name is a reserved word" : "Naziv datoteke je rezervirana riječ", - "File name contains at least one invalid character" : "Naziv datoteke sadrži barem jedan nevažeći znak", - "File name is too long" : "Naziv datoteke je predugačak", - "Help" : "Pomoć", - "Users" : "Korisnici", - "Unknown user" : "Nepoznat korisnik", - "MySQL username and/or password not valid" : "Neispravno korisničko ime i/ili zaporka baze podataka MySQL", - "Oracle username and/or password not valid" : "Neispravno korisničko ime i/ili zaporka baze podataka Oracle", - "PostgreSQL username and/or password not valid" : "Neispravno korisničko ime i/ili zaporka baze podataka PostgreSQL", - "Set an admin username." : "Postavite korisničko ime administratora.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s dijeli »%2$s« s vama i želi dodati:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s dijeli »%2$s« s vama i želi dodati", - "»%s« added a note to a file shared with you" : "»%s« je dodao bilješku datoteci koju dijeli s vama", - "Open »%s«" : "Otvori »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Dijeljenje %s nije uspjelo jer je ova stavka već podijeljena s korisnikom %s", - "%1$s shared »%2$s« with you" : "%1$s dijeli »%2$s« s vama", - "%1$s shared »%2$s« with you." : "%1$s dijeli »%2$s« s vama.", - "The username is already being used" : "Korisničko ime se već koristi", - "Could not create user" : "Nije moguće stvoriti korisnika", - "A valid username must be provided" : "Nužno je navesti ispravno korisničko ime", - "Username contains whitespace at the beginning or at the end" : "Korisničko ime sadrži bijeli prostor na početku ili na kraju", - "Username must not consist of dots only" : "Korisničko ime ne smije se sastojati samo od točkica", - "Username is invalid because files already exist for this user" : "Korisničko ime je nevažeće jer već postoje datoteke za ovog korisnika", - "User disabled" : "Korisnik je onemogućen", - "File is currently busy, please try again later" : "Datoteka je trenutno zauzeta, pokušajte ponovo kasnije", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Promijenite dozvole na 0770 tako da se tim direktorijem ne mogu služiti drugi korisnici.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Provjerite postoji li datoteka pod nazivom „.ocdata” u korijenu podatkovnog direktorija." + "Organisation" : "Organizacija", + "File is currently busy, please try again later" : "Datoteka je trenutno zauzeta, pokušajte ponovo kasnije" },"pluralForm" :"nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/hu.js b/lib/l10n/hu.js index ab48b204b84..886653b9095 100644 --- a/lib/l10n/hu.js +++ b/lib/l10n/hu.js @@ -53,6 +53,7 @@ OC.L10N.register( "Avatar image is not square" : "A profilkép nem négyzetes.", "Files" : "Fájlok", "View profile" : "Profil megtekintése", + "_%nh_::_%nh_" : ["%nó","%nó"], "Local time: %s" : "Helyi idő: %s", "today" : "ma", "tomorrow" : "holnap", @@ -76,6 +77,9 @@ OC.L10N.register( "Empty file" : "Üres fájl", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "A(z) %s azonosítójú modul nem létezik. Engedélyezze az alkalmazásbeállításokban, vagy lépjen kapcsolatba a rendszergazdával.", "Dot files are not allowed" : "A ponttal kezdődő fájlok nem engedélyezettek", + "%1$s (renamed)" : "%1$s (átnevezve)", + "renamed file" : "átnevezett fájl", + "Filenames must not end with \"%1$s\"." : "Fájlnév nem végződhet így: „%1$s”.", "File already exists" : "A fájl már létezik", "Invalid path" : "Érvénytelen útvonal", "Failed to create file from template" : "Nem sikerült létrehozni a fájlt a sablonból", @@ -109,14 +113,13 @@ OC.L10N.register( "About" : "Névjegy", "Display name" : "Megjelenítendő név", "Headline" : "Címsor", - "Organisation" : "Szervezet", + "Organization" : "Szervezet", "Role" : "Szerepkör", "Additional settings" : "További beállítások", "Enter the database name for %s" : "Adja meg a %s adatbázisának nevét", "You cannot use dots in the database name %s" : "A(z) %s adatbázisnév nem tartalmazhat pontot", "You need to enter details of an existing account." : "Egy már létező fiók adatait kell megadnia.", "Oracle connection could not be established" : "Az Oracle kapcsolat nem hozható létre", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "A Mac OS X nem támogatott, és a %s nem lesz teljesen működőképes. Csak saját felelősségre használja.", "For the best results, please consider using a GNU/Linux server instead." : "A legjobb eredmény érdekében érdemes GNU/Linux kiszolgálót használni.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Úgy tűnik, hogy ez a %s példány 32 bites PHP környezetben fut, és az open_basedir be lett állítva a php.ini fájlban. Ez 4 GB-nál nagyobb fájlok esetén problémákat okozhat, így erősen ellenjavallott.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Távolítsa el az open_basedir beállítást a php.ini fájlból, vagy váltson 64 bites PHP-ra.", @@ -125,7 +128,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "A(z) %s megosztási alrendszernek meg kell valósítania az OCP\\Share_Backend interfészt", "Sharing backend %s not found" : "A(z) %s megosztási alrendszer nem található", "Sharing backend for %s not found" : "A(z) %s megosztási alrendszere nem található", - "Click the button below to open it." : "Kattintson a lenti gombra a megnyitáshoz.", "%1$s via %2$s" : "%1$s – %2$s", "Unknown share type" : "Ismeretlen megosztástípus", "You are not allowed to share %s" : "Nincs jogosultsága a(z) %s megosztásához", @@ -135,6 +137,7 @@ OC.L10N.register( "Expiration date is in the past" : "A lejárati dátum már elmúlt", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Nem állítható be %n napnál távolabbi lejárati dátum","Nem állítható be %n napnál távolabbi lejárati dátum"], "Sharing is only allowed with group members" : "A megosztás csak a csoport tagjaival engedélyezett", + "Sharing %s failed, because this item is already shared with the account %s" : "A(z) %s megosztása sikertelen, mert már meg van osztva a(z) %s fiókkal", "The requested share does not exist anymore" : "A kért megosztás már nem létezik", "The requested share comes from a disabled user" : "A kért megosztás letiltott felhasználótól származik", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "A felhasználó nem jött létre, mert elérte a felhasználókorlátot. Nézze meg az értesítéseit, hogy többet tudjon meg.", @@ -230,8 +233,9 @@ OC.L10N.register( "Storage is temporarily not available" : "A tároló átmenetileg nem érhető el", "Storage connection timeout. %s" : "Időtúllépés a tárolókapcsolatban. %s", "Confirmation" : "Megerősítés", - "Prompt" : "Promtp", + "Prompt" : "Prompt", "Generates a possible headline for a text." : "Egy lehetséges címsort állít elő egy szöveghez.", + "Text" : "Szöveg", "Summarize" : "Összesítés", "Summary" : "Összefoglalás", "Extract topics" : "Témák kinyerése", @@ -243,41 +247,8 @@ OC.L10N.register( "Generate headline" : "Címsor előállítása", "Summarizes text by reducing its length without losing key information." : "Összesíti a szöveget a hosszúság csökkentésével anélkül, hogy a kulcsinformációk elvesznének.", "Extracts topics from a text and outputs them separated by commas." : "Kinyeri a témákat a szövegből, és vesszőkkel elválasztva megjeleníti.", - "Education Edition" : "Oktatási kiadás", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "A bejelentkezett felhasználónak rendszergazdának vagy alrendszergazdának kell lennie, vagy speciális hozzáféréssel kell rendelkeznie ehhez a beállításhoz", - "Logged in user must be an admin or sub admin" : "A bejelentkezett felhasználónak rendszergazdának vagy alrendszergazgának kell lennie", - "Logged in user must be an admin" : "A bejelentkezett felhasználónak rendszergazdának kell lennie", - "File name is a reserved word" : "A fájl neve egy fenntartott szó", - "File name contains at least one invalid character" : "A fájlnév legalább egy érvénytelen karaktert tartalmaz", - "File name is too long" : "A fájlnév túl hosszú", - "Help" : "Súgó", - "Users" : "Felhasználók", - "Unknown user" : "Ismeretlen felhasználó", - "Enter the database username and name for %s" : "Adja meg a %s adatbázisának nevét és a hozzá tartozó felhasználónevet", - "Enter the database username for %s" : "Adja meg a %s adatbázisához tartozó felhasználónevet", - "MySQL username and/or password not valid" : "A MySQL felhasználónév vagy jelszó érvénytelen", - "Oracle username and/or password not valid" : "Az Oracle felhasználónév vagy jelszó érvénytelen", - "PostgreSQL username and/or password not valid" : "A PostgreSQL felhasználói név vagy jelszó érvénytelen", - "Set an admin username." : "Állítson be egy rendszergazdai felhasználónevet.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s megosztotta Önnel: „%2$s”, és hozzá akarja adni:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s megosztotta Önnel: „%2$s”, és hozzá akarja adni", - "»%s« added a note to a file shared with you" : "„%s” megjegyzést fűzött az Önnel megosztott fájlhoz", - "Open »%s«" : "A(z) „%s” megnyitása", - "Sharing %s failed, because this item is already shared with user %s" : "A(z) %s megosztása nem sikerült, mert ez az elem már meg van osztva a(z) %s felhasználóval", - "%1$s shared »%2$s« with you" : "%1$s megosztotta Önnel: „%2$s”", - "%1$s shared »%2$s« with you." : "%1$s megosztotta Önnel: „%2$s”.", - "The username is already being used" : "Ez a felhasználónév már foglalt", - "Could not create user" : "Nem sikerült létrehozni a felhasználót", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "A felhasználónévben csak a következő karakterek engedélyezettek: „a-z”, „A-Z”, „0-9”, szóköz és „_.@-'”", - "A valid username must be provided" : "Érvényes felhasználónevet kell megadnia", - "Username contains whitespace at the beginning or at the end" : "A felhasználónév szóközt tartalmaz az elején vagy a végén", - "Username must not consist of dots only" : "A felhasználónév nem állhat csak pontokból", - "Username is invalid because files already exist for this user" : "A felhasználónév érvénytelen, mert már vannak fájlok ehhez a felhasználóhoz", - "User disabled" : "Felhasználó letiltva", + "Organisation" : "Szervezet", "File is currently busy, please try again later" : "A fájl jelenleg foglalt, próbálja újra később", - "Cannot download file" : "A fájl nem tölthető le", - "Your data directory is readable by other users." : "Az adatkönyvtára más felhasználók által is olvasható.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Módosítsa a könyvtár elérhetőségi engedélybeállítását 0770-re, hogy a tartalmát más felhasználók ne listázhassák.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Győződjön meg róla, hogy az adatmappa gyökerében van-e egy „.ocdata” fájl." + "Cannot download file" : "A fájl nem tölthető le" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/hu.json b/lib/l10n/hu.json index d3b81cbad40..266831728ba 100644 --- a/lib/l10n/hu.json +++ b/lib/l10n/hu.json @@ -51,6 +51,7 @@ "Avatar image is not square" : "A profilkép nem négyzetes.", "Files" : "Fájlok", "View profile" : "Profil megtekintése", + "_%nh_::_%nh_" : ["%nó","%nó"], "Local time: %s" : "Helyi idő: %s", "today" : "ma", "tomorrow" : "holnap", @@ -74,6 +75,9 @@ "Empty file" : "Üres fájl", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "A(z) %s azonosítójú modul nem létezik. Engedélyezze az alkalmazásbeállításokban, vagy lépjen kapcsolatba a rendszergazdával.", "Dot files are not allowed" : "A ponttal kezdődő fájlok nem engedélyezettek", + "%1$s (renamed)" : "%1$s (átnevezve)", + "renamed file" : "átnevezett fájl", + "Filenames must not end with \"%1$s\"." : "Fájlnév nem végződhet így: „%1$s”.", "File already exists" : "A fájl már létezik", "Invalid path" : "Érvénytelen útvonal", "Failed to create file from template" : "Nem sikerült létrehozni a fájlt a sablonból", @@ -107,14 +111,13 @@ "About" : "Névjegy", "Display name" : "Megjelenítendő név", "Headline" : "Címsor", - "Organisation" : "Szervezet", + "Organization" : "Szervezet", "Role" : "Szerepkör", "Additional settings" : "További beállítások", "Enter the database name for %s" : "Adja meg a %s adatbázisának nevét", "You cannot use dots in the database name %s" : "A(z) %s adatbázisnév nem tartalmazhat pontot", "You need to enter details of an existing account." : "Egy már létező fiók adatait kell megadnia.", "Oracle connection could not be established" : "Az Oracle kapcsolat nem hozható létre", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "A Mac OS X nem támogatott, és a %s nem lesz teljesen működőképes. Csak saját felelősségre használja.", "For the best results, please consider using a GNU/Linux server instead." : "A legjobb eredmény érdekében érdemes GNU/Linux kiszolgálót használni.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Úgy tűnik, hogy ez a %s példány 32 bites PHP környezetben fut, és az open_basedir be lett állítva a php.ini fájlban. Ez 4 GB-nál nagyobb fájlok esetén problémákat okozhat, így erősen ellenjavallott.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Távolítsa el az open_basedir beállítást a php.ini fájlból, vagy váltson 64 bites PHP-ra.", @@ -123,7 +126,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "A(z) %s megosztási alrendszernek meg kell valósítania az OCP\\Share_Backend interfészt", "Sharing backend %s not found" : "A(z) %s megosztási alrendszer nem található", "Sharing backend for %s not found" : "A(z) %s megosztási alrendszere nem található", - "Click the button below to open it." : "Kattintson a lenti gombra a megnyitáshoz.", "%1$s via %2$s" : "%1$s – %2$s", "Unknown share type" : "Ismeretlen megosztástípus", "You are not allowed to share %s" : "Nincs jogosultsága a(z) %s megosztásához", @@ -133,6 +135,7 @@ "Expiration date is in the past" : "A lejárati dátum már elmúlt", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Nem állítható be %n napnál távolabbi lejárati dátum","Nem állítható be %n napnál távolabbi lejárati dátum"], "Sharing is only allowed with group members" : "A megosztás csak a csoport tagjaival engedélyezett", + "Sharing %s failed, because this item is already shared with the account %s" : "A(z) %s megosztása sikertelen, mert már meg van osztva a(z) %s fiókkal", "The requested share does not exist anymore" : "A kért megosztás már nem létezik", "The requested share comes from a disabled user" : "A kért megosztás letiltott felhasználótól származik", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "A felhasználó nem jött létre, mert elérte a felhasználókorlátot. Nézze meg az értesítéseit, hogy többet tudjon meg.", @@ -228,8 +231,9 @@ "Storage is temporarily not available" : "A tároló átmenetileg nem érhető el", "Storage connection timeout. %s" : "Időtúllépés a tárolókapcsolatban. %s", "Confirmation" : "Megerősítés", - "Prompt" : "Promtp", + "Prompt" : "Prompt", "Generates a possible headline for a text." : "Egy lehetséges címsort állít elő egy szöveghez.", + "Text" : "Szöveg", "Summarize" : "Összesítés", "Summary" : "Összefoglalás", "Extract topics" : "Témák kinyerése", @@ -241,41 +245,8 @@ "Generate headline" : "Címsor előállítása", "Summarizes text by reducing its length without losing key information." : "Összesíti a szöveget a hosszúság csökkentésével anélkül, hogy a kulcsinformációk elvesznének.", "Extracts topics from a text and outputs them separated by commas." : "Kinyeri a témákat a szövegből, és vesszőkkel elválasztva megjeleníti.", - "Education Edition" : "Oktatási kiadás", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "A bejelentkezett felhasználónak rendszergazdának vagy alrendszergazdának kell lennie, vagy speciális hozzáféréssel kell rendelkeznie ehhez a beállításhoz", - "Logged in user must be an admin or sub admin" : "A bejelentkezett felhasználónak rendszergazdának vagy alrendszergazgának kell lennie", - "Logged in user must be an admin" : "A bejelentkezett felhasználónak rendszergazdának kell lennie", - "File name is a reserved word" : "A fájl neve egy fenntartott szó", - "File name contains at least one invalid character" : "A fájlnév legalább egy érvénytelen karaktert tartalmaz", - "File name is too long" : "A fájlnév túl hosszú", - "Help" : "Súgó", - "Users" : "Felhasználók", - "Unknown user" : "Ismeretlen felhasználó", - "Enter the database username and name for %s" : "Adja meg a %s adatbázisának nevét és a hozzá tartozó felhasználónevet", - "Enter the database username for %s" : "Adja meg a %s adatbázisához tartozó felhasználónevet", - "MySQL username and/or password not valid" : "A MySQL felhasználónév vagy jelszó érvénytelen", - "Oracle username and/or password not valid" : "Az Oracle felhasználónév vagy jelszó érvénytelen", - "PostgreSQL username and/or password not valid" : "A PostgreSQL felhasználói név vagy jelszó érvénytelen", - "Set an admin username." : "Állítson be egy rendszergazdai felhasználónevet.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s megosztotta Önnel: „%2$s”, és hozzá akarja adni:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s megosztotta Önnel: „%2$s”, és hozzá akarja adni", - "»%s« added a note to a file shared with you" : "„%s” megjegyzést fűzött az Önnel megosztott fájlhoz", - "Open »%s«" : "A(z) „%s” megnyitása", - "Sharing %s failed, because this item is already shared with user %s" : "A(z) %s megosztása nem sikerült, mert ez az elem már meg van osztva a(z) %s felhasználóval", - "%1$s shared »%2$s« with you" : "%1$s megosztotta Önnel: „%2$s”", - "%1$s shared »%2$s« with you." : "%1$s megosztotta Önnel: „%2$s”.", - "The username is already being used" : "Ez a felhasználónév már foglalt", - "Could not create user" : "Nem sikerült létrehozni a felhasználót", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "A felhasználónévben csak a következő karakterek engedélyezettek: „a-z”, „A-Z”, „0-9”, szóköz és „_.@-'”", - "A valid username must be provided" : "Érvényes felhasználónevet kell megadnia", - "Username contains whitespace at the beginning or at the end" : "A felhasználónév szóközt tartalmaz az elején vagy a végén", - "Username must not consist of dots only" : "A felhasználónév nem állhat csak pontokból", - "Username is invalid because files already exist for this user" : "A felhasználónév érvénytelen, mert már vannak fájlok ehhez a felhasználóhoz", - "User disabled" : "Felhasználó letiltva", + "Organisation" : "Szervezet", "File is currently busy, please try again later" : "A fájl jelenleg foglalt, próbálja újra később", - "Cannot download file" : "A fájl nem tölthető le", - "Your data directory is readable by other users." : "Az adatkönyvtára más felhasználók által is olvasható.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Módosítsa a könyvtár elérhetőségi engedélybeállítását 0770-re, hogy a tartalmát más felhasználók ne listázhassák.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Győződjön meg róla, hogy az adatmappa gyökerében van-e egy „.ocdata” fájl." + "Cannot download file" : "A fájl nem tölthető le" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/hy.js b/lib/l10n/hy.js index 6ec5f1da3d8..2c74b272b2f 100644 --- a/lib/l10n/hy.js +++ b/lib/l10n/hy.js @@ -57,8 +57,6 @@ OC.L10N.register( "Oct." : "Հոկ.", "Nov." : "Նոյ.", "Dec." : "Դեկ.", - "Translate" : "Թարգմանել", - "File name contains at least one invalid character" : "Ֆայլի անունը առնվազն մի անվավեր նիշ է պարունակում", - "Help" : "Օգնություն" + "Translate" : "Թարգմանել" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/hy.json b/lib/l10n/hy.json index 4ac64665170..7284fefe1af 100644 --- a/lib/l10n/hy.json +++ b/lib/l10n/hy.json @@ -55,8 +55,6 @@ "Oct." : "Հոկ.", "Nov." : "Նոյ.", "Dec." : "Դեկ.", - "Translate" : "Թարգմանել", - "File name contains at least one invalid character" : "Ֆայլի անունը առնվազն մի անվավեր նիշ է պարունակում", - "Help" : "Օգնություն" + "Translate" : "Թարգմանել" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/ia.js b/lib/l10n/ia.js index 96c3497f2a9..cc0a431ce3a 100644 --- a/lib/l10n/ia.js +++ b/lib/l10n/ia.js @@ -64,10 +64,6 @@ OC.L10N.register( "A valid password must be provided" : "Un contrasigno valide debe esser providite", "Authentication error" : "Error in authentication", "Storage is temporarily not available" : "Immagazinage es provisorimente non disponibile", - "Summary" : "Summario", - "Help" : "Adjuta", - "Users" : "Usatores", - "Unknown user" : "Usator incognite", - "A valid username must be provided" : "Un nomine de usator valide debe esser providite" + "Summary" : "Summario" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/ia.json b/lib/l10n/ia.json index 6b535386f7a..62ee67dcb63 100644 --- a/lib/l10n/ia.json +++ b/lib/l10n/ia.json @@ -62,10 +62,6 @@ "A valid password must be provided" : "Un contrasigno valide debe esser providite", "Authentication error" : "Error in authentication", "Storage is temporarily not available" : "Immagazinage es provisorimente non disponibile", - "Summary" : "Summario", - "Help" : "Adjuta", - "Users" : "Usatores", - "Unknown user" : "Usator incognite", - "A valid username must be provided" : "Un nomine de usator valide debe esser providite" + "Summary" : "Summario" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/id.js b/lib/l10n/id.js index 7b7a8c705aa..c7c14e71638 100644 --- a/lib/l10n/id.js +++ b/lib/l10n/id.js @@ -49,7 +49,6 @@ OC.L10N.register( "About" : "Tentang.", "Additional settings" : "Setelan tambahan", "Oracle connection could not be established" : "Koneksi Oracle tidak dapat dibuat", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X tidak didukung dan %s tidak akan bekerja dengan baik pada platform ini. Gunakan dengan resiko Anda sendiri!", "For the best results, please consider using a GNU/Linux server instead." : "Untuk hasil terbaik, pertimbangkan untuk menggunakan server GNU/Linux sebagai gantinya. ", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Kelihatannya instansi %s ini berjalan di lingkungan PHP 32-bit dan open_basedir telah dikonfigurasi di php.ini. Hal ini akan menyebabkan masalah dengan berkas lebih dari 4 GB dan sangat tidak disarankan.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Mohon hapus pengaturan open_basedir didalam php.ini atau beralih ke PHP 64-bit.", @@ -128,24 +127,9 @@ OC.L10N.register( "Storage connection error. %s" : "Koneksi penyimpanan bermasalah. %s", "Storage is temporarily not available" : "Penyimpanan sementara tidak tersedia", "Storage connection timeout. %s" : "Koneksi penyimpanan waktu-habis. %s", + "Text" : "Teks", "Summary" : "Kesimpulan", "Translate" : "Terjemahkan", - "File name is a reserved word" : "Nama berkas merupakan kata yang disediakan", - "File name contains at least one invalid character" : "Nama berkas berisi setidaknya satu karakter yang tidak sah.", - "File name is too long" : "Nama berkas terlalu panjang", - "Help" : "Bantuan", - "Users" : "Pengguna", - "Unknown user" : "Pengguna tidak dikenal", - "Oracle username and/or password not valid" : "Nama pengguna dan/atau kata sandi Oracle tidak sah", - "PostgreSQL username and/or password not valid" : "Nama pengguna dan/atau kata sandi PostgreSQL tidak valid", - "Set an admin username." : "Tetapkan nama pengguna admin.", - "Open »%s«" : "Buka »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Berbagi %s gagal karena item ini sudah dibagikan dengan pengguna %s", - "The username is already being used" : "Nama pengguna ini telah digunakan", - "A valid username must be provided" : "Tuliskan nama pengguna yang valid", - "Username contains whitespace at the beginning or at the end" : "Nama pengguna mengandung spasi di depan atau di belakang.", - "User disabled" : "Pengguna dinonaktifkan", - "File is currently busy, please try again later" : "Berkas sedang sibuk, mohon coba lagi nanti", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Mohon ubah perizinan menjadi 0770 sehingga direktori tersebut tidak dapat dilihat oleh pengguna lain." + "File is currently busy, please try again later" : "Berkas sedang sibuk, mohon coba lagi nanti" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/id.json b/lib/l10n/id.json index b7793dc03f8..99bf3880dd6 100644 --- a/lib/l10n/id.json +++ b/lib/l10n/id.json @@ -47,7 +47,6 @@ "About" : "Tentang.", "Additional settings" : "Setelan tambahan", "Oracle connection could not be established" : "Koneksi Oracle tidak dapat dibuat", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X tidak didukung dan %s tidak akan bekerja dengan baik pada platform ini. Gunakan dengan resiko Anda sendiri!", "For the best results, please consider using a GNU/Linux server instead." : "Untuk hasil terbaik, pertimbangkan untuk menggunakan server GNU/Linux sebagai gantinya. ", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Kelihatannya instansi %s ini berjalan di lingkungan PHP 32-bit dan open_basedir telah dikonfigurasi di php.ini. Hal ini akan menyebabkan masalah dengan berkas lebih dari 4 GB dan sangat tidak disarankan.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Mohon hapus pengaturan open_basedir didalam php.ini atau beralih ke PHP 64-bit.", @@ -126,24 +125,9 @@ "Storage connection error. %s" : "Koneksi penyimpanan bermasalah. %s", "Storage is temporarily not available" : "Penyimpanan sementara tidak tersedia", "Storage connection timeout. %s" : "Koneksi penyimpanan waktu-habis. %s", + "Text" : "Teks", "Summary" : "Kesimpulan", "Translate" : "Terjemahkan", - "File name is a reserved word" : "Nama berkas merupakan kata yang disediakan", - "File name contains at least one invalid character" : "Nama berkas berisi setidaknya satu karakter yang tidak sah.", - "File name is too long" : "Nama berkas terlalu panjang", - "Help" : "Bantuan", - "Users" : "Pengguna", - "Unknown user" : "Pengguna tidak dikenal", - "Oracle username and/or password not valid" : "Nama pengguna dan/atau kata sandi Oracle tidak sah", - "PostgreSQL username and/or password not valid" : "Nama pengguna dan/atau kata sandi PostgreSQL tidak valid", - "Set an admin username." : "Tetapkan nama pengguna admin.", - "Open »%s«" : "Buka »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Berbagi %s gagal karena item ini sudah dibagikan dengan pengguna %s", - "The username is already being used" : "Nama pengguna ini telah digunakan", - "A valid username must be provided" : "Tuliskan nama pengguna yang valid", - "Username contains whitespace at the beginning or at the end" : "Nama pengguna mengandung spasi di depan atau di belakang.", - "User disabled" : "Pengguna dinonaktifkan", - "File is currently busy, please try again later" : "Berkas sedang sibuk, mohon coba lagi nanti", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Mohon ubah perizinan menjadi 0770 sehingga direktori tersebut tidak dapat dilihat oleh pengguna lain." + "File is currently busy, please try again later" : "Berkas sedang sibuk, mohon coba lagi nanti" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/is.js b/lib/l10n/is.js index 3624cd9ba89..dca5eeea0c7 100644 --- a/lib/l10n/is.js +++ b/lib/l10n/is.js @@ -19,9 +19,11 @@ OC.L10N.register( "%1$s, %2$s and %3$s" : "%1$s, %2$s og %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s og %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s og %5$s", + "Education bundle" : "Kennsluvöndull", "Enterprise bundle" : "Fyrirtækjavöndull", "Groupware bundle" : "Hópvinnsluvöndull", - "Hub bundle" : "Tengivöndull", + "Hub bundle" : "Miðstöðvarvöndull", + "Public sector bundle" : "Vöndull fyrir opinbera þjónustu", "Social sharing bundle" : "Deilivöndull fyrir samfélagsmiðla", "PHP %s or higher is required." : "Krafist er PHP %s eða hærra.", "PHP with a version lower than %s is required." : "Krafist er PHP útgáfu %s eða lægri.", @@ -35,6 +37,9 @@ OC.L10N.register( "The following platforms are supported: %s" : "Eftirfarandi stýrikerfi eru studd: %s", "Server version %s or higher is required." : "Krafist er þjóns af útgáfu %s eða hærra.", "Server version %s or lower is required." : "Krafist er þjóns af útgáfu %s eða lægri.", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Innskráður notandi verður að vera kerfisstjóri eða undirstjórnandi eða hafa fengið sérstaka aðgangsheimild fyrir þessa stillingu", + "Logged in account must be an admin or sub admin" : "Innskráður notandi verður að vera kerfisstjóri eða undirstjórnandi", + "Logged in account must be an admin" : "Innskráður notandi verður að vera stjórnandi", "Wiping of device %s has started" : "Útþurrkun af tækinu %s er byrjuð", "Wiping of device »%s« has started" : "Útþurrkun af tækinu »%s« er byrjuð", "»%s« started remote wipe" : "»%s« byrjaði fjartengda útþurrkun", @@ -53,6 +58,11 @@ OC.L10N.register( "Avatar image is not square" : "Auðkennismynd er ekki ferningslaga", "Files" : "Skrár", "View profile" : "Skoða notandasnið", + "same time" : "sami tími", + "_%nh_::_%nh_" : ["%nklst","%nklst"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s á undan", + "%s behind" : "%s á eftir", "Local time: %s" : "Staðartími: %s", "today" : "í dag", "tomorrow" : "á morgun", @@ -75,17 +85,30 @@ OC.L10N.register( "seconds ago" : "sekúndum síðan", "Empty file" : "Tóm skrá", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Eining með auðkenni: %s er ekki til. Virkjaðu hana í forritastillingum eða hafðu samband við kerfisstjóra.", + "File is too large to convert" : "Skráin er of stór til að umbreyta henni", + "Could not convert file" : "Gat ekki umbreytt skrá", "Dot files are not allowed" : "Skrár með punkti eru ekki leyfðar", + "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" er bannað sem heiti á skrá eða möppu.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" er bannað sem forskeyti á skrá eða möppu.", + "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" er ekki leyfilegt innan í heiti á skrá eða möppu.", + "\"%1$s\" is a forbidden file type." : "\"%1$s\" er bönnuð skráartegund.", + "Filenames must not end with \"%1$s\"." : "Skráaheiti mega ekki enda á \"%1$s\".", + "Invalid parent path" : "Ógild yfirslóð", "File already exists" : "Skrá er þegar til", "Invalid path" : "Ógild slóð", "Failed to create file from template" : "Mistókst að búa til skrá út frá sniðmáti", "Templates" : "Sniðmát", + "Storage %s cannot be moved" : "Ekki er hægt að færa geymslurýmið %s", + "Path contains invalid segments" : "Slóðin inniheldur ógilda hluta", + "Filename is a reserved word" : "Skráarheiti er þegar frátekið orð", "Filename contains at least one invalid character" : "Skráarheitið inniheldur að minnsta kosti einn ógildan staf", + "Filename is too long" : "Skráarheiti er of langt", "Empty filename is not allowed" : "Autt skráarheiti er ekki leyft.", "App \"%s\" cannot be installed because appinfo file cannot be read." : "Ekki er hægt að setja upp \"%s\" forritið vegna þess að ekki var hægt að lesa appinfo-skrána.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Ekki var hægt að setja upp forritið \"%s\" vegna þess að það er ekki samhæft þessari útgáfu vefþjónsins.", "__language_name__" : "Íslenska", "This is an automatically sent email, please do not reply." : "Þetta er sjálfvirk tölvupóstsending, ekki svara þessu.", + "Help & privacy" : "Aðstoð og gagnaleynd", "Appearance and accessibility" : "Útlit og aðgengi", "Apps" : "Forrit", "Personal settings" : "Persónulegar stillingar", @@ -108,14 +131,15 @@ OC.L10N.register( "About" : "Um hugbúnaðinn", "Display name" : "Birtingarnafn", "Headline" : "Fyrirsögn", - "Organisation" : "Stofnun/Félag/Fyrirtæki", + "Organization" : "Stofnun/Samtök/Félag", "Role" : "Role", - "Additional settings" : "Valfrjálsar stillingar", + "Pronouns" : "Fornöfn", + "Unknown account" : "Óþekktur aðgangur", + "Additional settings" : "Aukastillingar", "Enter the database name for %s" : "Settu inn nafn á gagnagrunni fyrir %s", "You cannot use dots in the database name %s" : "Þú mátt ekki nota punkta í gagnagrunnsheitinu %s", "You need to enter details of an existing account." : "Þú verður að setja inn auðkenni fyrirliggjandi notandaaðgangs.", "Oracle connection could not be established" : "Ekki tókst að koma tengingu á við Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X er ekki stutt og %s mun ekki vinna eðlilega á þessu stýrikerfi. Notaðu þetta því á þína eigin ábyrgð! ", "For the best results, please consider using a GNU/Linux server instead." : "Fyrir bestu útkomu ættirðu að íhuga að nota GNU/Linux þjón í staðinn.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Það lítur út eins og þessi %s uppsetning sé að keyra á 32-bita PHP umhverfi og að open_basedir hafi verið stillt í php.ini. Þetta mun valda vandamálum með skrár stærri en 4 GB og er stranglega mælt gegn því að þetta sé gert.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Fjarlægðu stillinguna open_basedir úr php.ini eða skiptu yfir í 64-bita PHP.", @@ -124,8 +148,12 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Deilingarbakendinn %s verður að vera settur upp fyrir viðmótið OCP\\Share_Backend", "Sharing backend %s not found" : "Deilingarbakendinn %s fannst ekki", "Sharing backend for %s not found" : "Deilingarbakendi fyrir %s fannst ekki", - "Click the button below to open it." : "Smelltu á hnappinn hér fyrir neðan til að opna það.", + "%1$s shared %2$s with you" : "%1$s deildi %2$s með þér", + "Open %s" : "Opna %s", "%1$s via %2$s" : "%1$s með %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s deildi %2$s með þér og vill bæta við:", + "%1$s shared %2$s with you and wants to add" : "%1$s deildi %2$s með þér og vill bæta við", + "%s added a note to a file shared with you" : "%s bætti minnispunkti við skrá sem deilt er með þér", "Unknown share type" : "Óþekkt tegund sameignar", "You are not allowed to share %s" : "Þú hefur ekki heimild til að deila %s", "Cannot increase permissions of %s" : "Get ekki aukið aðgangsheimildir %s", @@ -134,10 +162,15 @@ OC.L10N.register( "Expiration date is in the past" : "Gildistíminn er þegar runninn út", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Ekki er hægt að setja lokadagsetningu meira en %n dag fram í tímann","Ekki er hægt að setja lokadagsetningu meira en %n daga fram í tímann"], "Sharing is only allowed with group members" : "Deiling er aðeins leyfð með meðlimum hópsins", + "Sharing is disabled" : "Deiling er óvirk", + "Invalid share recipient" : "Ógildur viðtakandi sameignar", + "Group \"%s\" does not exist" : "Hópurinn \"%s\" er ekki til", "The requested share does not exist anymore" : "Umbeðin sameign er ekki lengur til", "The requested share comes from a disabled user" : "Umbeðin sameign kemur frá notanda sem er óvirkur", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Notandinn var ekki búinn til þar sem takmörkum á fjölda notenda var náð. Skoðaðu tilkynningarnar þínar til að sjá meira.", "Could not find category \"%s\"" : "Fann ekki flokkinn \"%s\"", + "Input text" : "Inntakstexti", + "The input text" : "Inntakstextinn", "Sunday" : "Sunnudagur", "Monday" : "Mánudagur", "Tuesday" : "Þriðjudagur", @@ -184,6 +217,14 @@ OC.L10N.register( "Nov." : "Nóv.", "Dec." : "Des.", "A valid password must be provided" : "Skráðu inn gilt lykilorð", + "The Login is already being used" : "Innskráningarnafnið er þegar í notkun", + "Could not create account" : "Gat ekki búið til notandaaðgang", + "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Einungis eru leyfilegir eftirfarandi stafir í innskráningarnafni: \"a-z\", \"A-Z\", \"0-9\", bil og \"_.@-'\"", + "A valid Login must be provided" : "Settu inn gilt innskráningarnafn", + "Login contains whitespace at the beginning or at the end" : "Innskráningarnafnið inniheldur bil í upphafi eða enda", + "Login must not consist of dots only" : "Innskráningarnafn má ekki einungis samanstanda af punktum", + "Login is invalid because files already exist for this user" : "Innskráningarnafnið er ógilt vegna þess að þegar eru fyrir hendi skrár sem tilheyra þessum notanda", + "Account disabled" : "Notandaaðgangur óvirkur", "Login canceled by app" : "Forrit hætti við innskráningu", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Ekki var hægt að setja upp \"%1$s\" forritið þar sem eftirfarandi kerfiskröfur eru ekki uppfylltar: %2$s", "a safe home for all your data" : "öruggur staður fyrir öll gögnin þín", @@ -214,9 +255,12 @@ OC.L10N.register( "Please ask your server administrator to restart the web server." : "Biddu kerfisstjórann þinn um að endurræsa vefþjóninn.", "The required %s config variable is not configured in the config.php file." : "Nauðsynleg %s stillingabreyta er ekki stillt í config.php file.", "Please ask your server administrator to check the Nextcloud configuration." : "Biddu kerfisstjórann þinn um að athuga uppsetninguna á Nextcloud.", + "Your data directory is readable by other people." : "Gagnamappn þín er lesanleg fyrir aðra notendur.", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Endilega breyttu heimildunum í 0770 svo að aðrir notendur geti ekki listað upp innihald hennar.", "Your data directory must be an absolute path." : "Gagnamappan þín verður að vera með algilda slóð.", "Check the value of \"datadirectory\" in your configuration." : "Athugaðu gildi \"datadirectory\" í uppsetningunni þinni.", "Your data directory is invalid." : "Gagnamappan þín er ógild.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Gakktu úr skugga um að til staðar sé skrá með heitinu \"%1$s\" í rót gagnageymslunnar. Hún ætti að innihalda eftirfarandi: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Aðgerðin \"%s\" er ekki studd eða útfærð.", "Authentication failed, wrong token or provider ID given" : "Auðkenning mistókst, uppgefið rangt teikn eða auðkenni þjónustuveitu", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Breytur vantar til að geta lokið beiðninni. Breytur sem vantar: \"%s\"", @@ -228,53 +272,42 @@ OC.L10N.register( "Storage connection error. %s" : "Villa í tengingu við gagnageymslu. %s", "Storage is temporarily not available" : "Gagnageymsla ekki tiltæk í augnablikinu", "Storage connection timeout. %s" : "Gagnageymsla féll á tíma. %s", + "Transcribe audio" : "Umrita hljóð", + "Transcribe the things said in an audio" : "Umritaðu það sem sagt er í hljóðspori", + "Audio input" : "Hljóðinntak", + "The audio to transcribe" : "Hljóðið sem á að umrita", + "Transcription" : "Umritun", + "The transcribed text" : "Umritaði textinn", + "Chat message" : "Spjallskilaboð", + "Confirmation" : "Staðfesting", + "Prompt" : "Kvaðning", + "Number of images" : "Fjöldi mynda", + "Chat" : "Spjall", "Generates a possible headline for a text." : "Útbýr mögulega fyrirsögn fyrir texta.", + "Text" : "Texti", + "Simplify text" : "Einfalda texta", + "Simplified text" : "Einfaldaður texti", "Summarize" : "Gera samantekt", "Summary" : "Samantekt", "Extract topics" : "Taka út efnisflokka", + "Topics" : "Umfjöllunarefni", "Translate" : "Þýða", + "Translate text from one language to another" : "Þýddu texta af einu tungumáli yfir á annað", + "Origin text" : "Upprunalegur texti", + "The text to translate" : "Textinn sem á að þýða", + "Origin language" : "Upprunalegt tungumál", + "The language of the origin text" : "Tungumál upprunalega textans", "Target language" : "Marktungumál:", + "The desired language to translate the origin text in" : "Tungumálið sem þýða skal upprunalega textann yfir á", "Result" : "Niðurstöður", + "The translated text" : "Þýddi textinn", "Free prompt" : "Frjáls kvaðning", "Runs an arbitrary prompt through the language model." : "Keyrir óreglulega kvaðningu (prompt) í gegnum tungumálslíkanið.", "Generate headline" : "Útbúa fyrirsögn", "Summarizes text by reducing its length without losing key information." : "Tekur saman aðalatriði texta með því að stytta hann án þess að tapa mikilvægustu upplýsingum.", "Extracts topics from a text and outputs them separated by commas." : "Greinir efnisflokka úr texta og aðskilur þá með kommum.", - "Education Edition" : "Kennsluútgáfa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Innskráður notandi verður að vera kerfisstjóri eða undirstjórnandi eða hafa fengið sérstaka aðgangsheimild fyrir þessa stillingu", - "Logged in user must be an admin or sub admin" : "Innskráður notandi verður að vera kerfisstjóri eða undirstjórnandi", - "Logged in user must be an admin" : "Innskráður notandi verður að vera stjórnandi", - "File name is a reserved word" : "Skráarheiti er þegar frátekið orð", - "File name contains at least one invalid character" : "Skráarheitið inniheldur að minnsta kosti einn ógildan staf", - "File name is too long" : "Skráarheiti er of langt", - "Help" : "Hjálp", - "Users" : "Notendur", - "Unknown user" : "Óþekktur notandi", - "Enter the database username and name for %s" : "Settu inn notandanafn og nafn í gagnagrunni fyrir %s", - "Enter the database username for %s" : "Settu inn notandanafn í gagnagrunni fyrir %s", - "MySQL username and/or password not valid" : "Notandanafn eða lykilorð MySQL er ekki gilt", - "Oracle username and/or password not valid" : "Notandanafn eða lykilorð Oracle er ekki gilt", - "PostgreSQL username and/or password not valid" : "Notandanafn eða lykilorð PostgreSQL er ekki gilt", - "Set an admin username." : "Stilltu notandanafn kerfisstjóra.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s deildi »%2$s« með þér og vill bæta við:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s deildi »%2$s« með þér og vill bæta við", - "»%s« added a note to a file shared with you" : "»%s« bætti minnispunkti við skrá sem deilt er með þér", - "Open »%s«" : "Opna »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Deiling %s mistókst, því þessu atriði er þegar deilt með notandanum %s", - "%1$s shared »%2$s« with you" : "%1$s deildi »%2$s« með þér", - "%1$s shared »%2$s« with you." : "%1$s deildi »%2$s« með þér.", - "The username is already being used" : "Notandanafnið er þegar í notkun", - "Could not create user" : "Gat ekki búið til notanda", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Einungis eru leyfilegir eftirfarandi stafir í notandanafni: \"a-z\", \"A-Z\", \"0-9\", bil og \"_.@-'\"", - "A valid username must be provided" : "Skráðu inn gilt notandanafn", - "Username contains whitespace at the beginning or at the end" : "Notandanafnið inniheldur orðabil í upphafi eða enda", - "Username must not consist of dots only" : "Notandanafn má ekki einungis samanstanda af punktum", - "Username is invalid because files already exist for this user" : "Notandanafnið er ógilt vegna þess að þegar eru fyrir hendi skrár sem tilheyra þessum notanda", - "User disabled" : "Notandi óvirkur", + "Organisation" : "Stofnun/Félag/Fyrirtæki", "File is currently busy, please try again later" : "Skráin er upptekin í augnablikinu, reyndu aftur síðar", - "Cannot download file" : "Get ekki sótt skrá", - "Your data directory is readable by other users." : "Gagnamappn þín er lesanleg fyrir aðra notendur.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Endilega breyttu heimildunum í 0770 svo að aðrir notendur geti ekki listað upp innihald hennar.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Gakktu úr skugga um að til staðar sé skrá með heitinu \".ocdata\" í rót gagnageymslunnar." + "Cannot download file" : "Get ekki sótt skrá" }, "nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"); diff --git a/lib/l10n/is.json b/lib/l10n/is.json index a8d96ca1e86..d49fa292bb1 100644 --- a/lib/l10n/is.json +++ b/lib/l10n/is.json @@ -17,9 +17,11 @@ "%1$s, %2$s and %3$s" : "%1$s, %2$s og %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s og %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s og %5$s", + "Education bundle" : "Kennsluvöndull", "Enterprise bundle" : "Fyrirtækjavöndull", "Groupware bundle" : "Hópvinnsluvöndull", - "Hub bundle" : "Tengivöndull", + "Hub bundle" : "Miðstöðvarvöndull", + "Public sector bundle" : "Vöndull fyrir opinbera þjónustu", "Social sharing bundle" : "Deilivöndull fyrir samfélagsmiðla", "PHP %s or higher is required." : "Krafist er PHP %s eða hærra.", "PHP with a version lower than %s is required." : "Krafist er PHP útgáfu %s eða lægri.", @@ -33,6 +35,9 @@ "The following platforms are supported: %s" : "Eftirfarandi stýrikerfi eru studd: %s", "Server version %s or higher is required." : "Krafist er þjóns af útgáfu %s eða hærra.", "Server version %s or lower is required." : "Krafist er þjóns af útgáfu %s eða lægri.", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Innskráður notandi verður að vera kerfisstjóri eða undirstjórnandi eða hafa fengið sérstaka aðgangsheimild fyrir þessa stillingu", + "Logged in account must be an admin or sub admin" : "Innskráður notandi verður að vera kerfisstjóri eða undirstjórnandi", + "Logged in account must be an admin" : "Innskráður notandi verður að vera stjórnandi", "Wiping of device %s has started" : "Útþurrkun af tækinu %s er byrjuð", "Wiping of device »%s« has started" : "Útþurrkun af tækinu »%s« er byrjuð", "»%s« started remote wipe" : "»%s« byrjaði fjartengda útþurrkun", @@ -51,6 +56,11 @@ "Avatar image is not square" : "Auðkennismynd er ekki ferningslaga", "Files" : "Skrár", "View profile" : "Skoða notandasnið", + "same time" : "sami tími", + "_%nh_::_%nh_" : ["%nklst","%nklst"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s á undan", + "%s behind" : "%s á eftir", "Local time: %s" : "Staðartími: %s", "today" : "í dag", "tomorrow" : "á morgun", @@ -73,17 +83,30 @@ "seconds ago" : "sekúndum síðan", "Empty file" : "Tóm skrá", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Eining með auðkenni: %s er ekki til. Virkjaðu hana í forritastillingum eða hafðu samband við kerfisstjóra.", + "File is too large to convert" : "Skráin er of stór til að umbreyta henni", + "Could not convert file" : "Gat ekki umbreytt skrá", "Dot files are not allowed" : "Skrár með punkti eru ekki leyfðar", + "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" er bannað sem heiti á skrá eða möppu.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" er bannað sem forskeyti á skrá eða möppu.", + "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" er ekki leyfilegt innan í heiti á skrá eða möppu.", + "\"%1$s\" is a forbidden file type." : "\"%1$s\" er bönnuð skráartegund.", + "Filenames must not end with \"%1$s\"." : "Skráaheiti mega ekki enda á \"%1$s\".", + "Invalid parent path" : "Ógild yfirslóð", "File already exists" : "Skrá er þegar til", "Invalid path" : "Ógild slóð", "Failed to create file from template" : "Mistókst að búa til skrá út frá sniðmáti", "Templates" : "Sniðmát", + "Storage %s cannot be moved" : "Ekki er hægt að færa geymslurýmið %s", + "Path contains invalid segments" : "Slóðin inniheldur ógilda hluta", + "Filename is a reserved word" : "Skráarheiti er þegar frátekið orð", "Filename contains at least one invalid character" : "Skráarheitið inniheldur að minnsta kosti einn ógildan staf", + "Filename is too long" : "Skráarheiti er of langt", "Empty filename is not allowed" : "Autt skráarheiti er ekki leyft.", "App \"%s\" cannot be installed because appinfo file cannot be read." : "Ekki er hægt að setja upp \"%s\" forritið vegna þess að ekki var hægt að lesa appinfo-skrána.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Ekki var hægt að setja upp forritið \"%s\" vegna þess að það er ekki samhæft þessari útgáfu vefþjónsins.", "__language_name__" : "Íslenska", "This is an automatically sent email, please do not reply." : "Þetta er sjálfvirk tölvupóstsending, ekki svara þessu.", + "Help & privacy" : "Aðstoð og gagnaleynd", "Appearance and accessibility" : "Útlit og aðgengi", "Apps" : "Forrit", "Personal settings" : "Persónulegar stillingar", @@ -106,14 +129,15 @@ "About" : "Um hugbúnaðinn", "Display name" : "Birtingarnafn", "Headline" : "Fyrirsögn", - "Organisation" : "Stofnun/Félag/Fyrirtæki", + "Organization" : "Stofnun/Samtök/Félag", "Role" : "Role", - "Additional settings" : "Valfrjálsar stillingar", + "Pronouns" : "Fornöfn", + "Unknown account" : "Óþekktur aðgangur", + "Additional settings" : "Aukastillingar", "Enter the database name for %s" : "Settu inn nafn á gagnagrunni fyrir %s", "You cannot use dots in the database name %s" : "Þú mátt ekki nota punkta í gagnagrunnsheitinu %s", "You need to enter details of an existing account." : "Þú verður að setja inn auðkenni fyrirliggjandi notandaaðgangs.", "Oracle connection could not be established" : "Ekki tókst að koma tengingu á við Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X er ekki stutt og %s mun ekki vinna eðlilega á þessu stýrikerfi. Notaðu þetta því á þína eigin ábyrgð! ", "For the best results, please consider using a GNU/Linux server instead." : "Fyrir bestu útkomu ættirðu að íhuga að nota GNU/Linux þjón í staðinn.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Það lítur út eins og þessi %s uppsetning sé að keyra á 32-bita PHP umhverfi og að open_basedir hafi verið stillt í php.ini. Þetta mun valda vandamálum með skrár stærri en 4 GB og er stranglega mælt gegn því að þetta sé gert.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Fjarlægðu stillinguna open_basedir úr php.ini eða skiptu yfir í 64-bita PHP.", @@ -122,8 +146,12 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Deilingarbakendinn %s verður að vera settur upp fyrir viðmótið OCP\\Share_Backend", "Sharing backend %s not found" : "Deilingarbakendinn %s fannst ekki", "Sharing backend for %s not found" : "Deilingarbakendi fyrir %s fannst ekki", - "Click the button below to open it." : "Smelltu á hnappinn hér fyrir neðan til að opna það.", + "%1$s shared %2$s with you" : "%1$s deildi %2$s með þér", + "Open %s" : "Opna %s", "%1$s via %2$s" : "%1$s með %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s deildi %2$s með þér og vill bæta við:", + "%1$s shared %2$s with you and wants to add" : "%1$s deildi %2$s með þér og vill bæta við", + "%s added a note to a file shared with you" : "%s bætti minnispunkti við skrá sem deilt er með þér", "Unknown share type" : "Óþekkt tegund sameignar", "You are not allowed to share %s" : "Þú hefur ekki heimild til að deila %s", "Cannot increase permissions of %s" : "Get ekki aukið aðgangsheimildir %s", @@ -132,10 +160,15 @@ "Expiration date is in the past" : "Gildistíminn er þegar runninn út", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Ekki er hægt að setja lokadagsetningu meira en %n dag fram í tímann","Ekki er hægt að setja lokadagsetningu meira en %n daga fram í tímann"], "Sharing is only allowed with group members" : "Deiling er aðeins leyfð með meðlimum hópsins", + "Sharing is disabled" : "Deiling er óvirk", + "Invalid share recipient" : "Ógildur viðtakandi sameignar", + "Group \"%s\" does not exist" : "Hópurinn \"%s\" er ekki til", "The requested share does not exist anymore" : "Umbeðin sameign er ekki lengur til", "The requested share comes from a disabled user" : "Umbeðin sameign kemur frá notanda sem er óvirkur", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Notandinn var ekki búinn til þar sem takmörkum á fjölda notenda var náð. Skoðaðu tilkynningarnar þínar til að sjá meira.", "Could not find category \"%s\"" : "Fann ekki flokkinn \"%s\"", + "Input text" : "Inntakstexti", + "The input text" : "Inntakstextinn", "Sunday" : "Sunnudagur", "Monday" : "Mánudagur", "Tuesday" : "Þriðjudagur", @@ -182,6 +215,14 @@ "Nov." : "Nóv.", "Dec." : "Des.", "A valid password must be provided" : "Skráðu inn gilt lykilorð", + "The Login is already being used" : "Innskráningarnafnið er þegar í notkun", + "Could not create account" : "Gat ekki búið til notandaaðgang", + "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Einungis eru leyfilegir eftirfarandi stafir í innskráningarnafni: \"a-z\", \"A-Z\", \"0-9\", bil og \"_.@-'\"", + "A valid Login must be provided" : "Settu inn gilt innskráningarnafn", + "Login contains whitespace at the beginning or at the end" : "Innskráningarnafnið inniheldur bil í upphafi eða enda", + "Login must not consist of dots only" : "Innskráningarnafn má ekki einungis samanstanda af punktum", + "Login is invalid because files already exist for this user" : "Innskráningarnafnið er ógilt vegna þess að þegar eru fyrir hendi skrár sem tilheyra þessum notanda", + "Account disabled" : "Notandaaðgangur óvirkur", "Login canceled by app" : "Forrit hætti við innskráningu", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Ekki var hægt að setja upp \"%1$s\" forritið þar sem eftirfarandi kerfiskröfur eru ekki uppfylltar: %2$s", "a safe home for all your data" : "öruggur staður fyrir öll gögnin þín", @@ -212,9 +253,12 @@ "Please ask your server administrator to restart the web server." : "Biddu kerfisstjórann þinn um að endurræsa vefþjóninn.", "The required %s config variable is not configured in the config.php file." : "Nauðsynleg %s stillingabreyta er ekki stillt í config.php file.", "Please ask your server administrator to check the Nextcloud configuration." : "Biddu kerfisstjórann þinn um að athuga uppsetninguna á Nextcloud.", + "Your data directory is readable by other people." : "Gagnamappn þín er lesanleg fyrir aðra notendur.", + "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Endilega breyttu heimildunum í 0770 svo að aðrir notendur geti ekki listað upp innihald hennar.", "Your data directory must be an absolute path." : "Gagnamappan þín verður að vera með algilda slóð.", "Check the value of \"datadirectory\" in your configuration." : "Athugaðu gildi \"datadirectory\" í uppsetningunni þinni.", "Your data directory is invalid." : "Gagnamappan þín er ógild.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Gakktu úr skugga um að til staðar sé skrá með heitinu \"%1$s\" í rót gagnageymslunnar. Hún ætti að innihalda eftirfarandi: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Aðgerðin \"%s\" er ekki studd eða útfærð.", "Authentication failed, wrong token or provider ID given" : "Auðkenning mistókst, uppgefið rangt teikn eða auðkenni þjónustuveitu", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Breytur vantar til að geta lokið beiðninni. Breytur sem vantar: \"%s\"", @@ -226,53 +270,42 @@ "Storage connection error. %s" : "Villa í tengingu við gagnageymslu. %s", "Storage is temporarily not available" : "Gagnageymsla ekki tiltæk í augnablikinu", "Storage connection timeout. %s" : "Gagnageymsla féll á tíma. %s", + "Transcribe audio" : "Umrita hljóð", + "Transcribe the things said in an audio" : "Umritaðu það sem sagt er í hljóðspori", + "Audio input" : "Hljóðinntak", + "The audio to transcribe" : "Hljóðið sem á að umrita", + "Transcription" : "Umritun", + "The transcribed text" : "Umritaði textinn", + "Chat message" : "Spjallskilaboð", + "Confirmation" : "Staðfesting", + "Prompt" : "Kvaðning", + "Number of images" : "Fjöldi mynda", + "Chat" : "Spjall", "Generates a possible headline for a text." : "Útbýr mögulega fyrirsögn fyrir texta.", + "Text" : "Texti", + "Simplify text" : "Einfalda texta", + "Simplified text" : "Einfaldaður texti", "Summarize" : "Gera samantekt", "Summary" : "Samantekt", "Extract topics" : "Taka út efnisflokka", + "Topics" : "Umfjöllunarefni", "Translate" : "Þýða", + "Translate text from one language to another" : "Þýddu texta af einu tungumáli yfir á annað", + "Origin text" : "Upprunalegur texti", + "The text to translate" : "Textinn sem á að þýða", + "Origin language" : "Upprunalegt tungumál", + "The language of the origin text" : "Tungumál upprunalega textans", "Target language" : "Marktungumál:", + "The desired language to translate the origin text in" : "Tungumálið sem þýða skal upprunalega textann yfir á", "Result" : "Niðurstöður", + "The translated text" : "Þýddi textinn", "Free prompt" : "Frjáls kvaðning", "Runs an arbitrary prompt through the language model." : "Keyrir óreglulega kvaðningu (prompt) í gegnum tungumálslíkanið.", "Generate headline" : "Útbúa fyrirsögn", "Summarizes text by reducing its length without losing key information." : "Tekur saman aðalatriði texta með því að stytta hann án þess að tapa mikilvægustu upplýsingum.", "Extracts topics from a text and outputs them separated by commas." : "Greinir efnisflokka úr texta og aðskilur þá með kommum.", - "Education Edition" : "Kennsluútgáfa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Innskráður notandi verður að vera kerfisstjóri eða undirstjórnandi eða hafa fengið sérstaka aðgangsheimild fyrir þessa stillingu", - "Logged in user must be an admin or sub admin" : "Innskráður notandi verður að vera kerfisstjóri eða undirstjórnandi", - "Logged in user must be an admin" : "Innskráður notandi verður að vera stjórnandi", - "File name is a reserved word" : "Skráarheiti er þegar frátekið orð", - "File name contains at least one invalid character" : "Skráarheitið inniheldur að minnsta kosti einn ógildan staf", - "File name is too long" : "Skráarheiti er of langt", - "Help" : "Hjálp", - "Users" : "Notendur", - "Unknown user" : "Óþekktur notandi", - "Enter the database username and name for %s" : "Settu inn notandanafn og nafn í gagnagrunni fyrir %s", - "Enter the database username for %s" : "Settu inn notandanafn í gagnagrunni fyrir %s", - "MySQL username and/or password not valid" : "Notandanafn eða lykilorð MySQL er ekki gilt", - "Oracle username and/or password not valid" : "Notandanafn eða lykilorð Oracle er ekki gilt", - "PostgreSQL username and/or password not valid" : "Notandanafn eða lykilorð PostgreSQL er ekki gilt", - "Set an admin username." : "Stilltu notandanafn kerfisstjóra.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s deildi »%2$s« með þér og vill bæta við:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s deildi »%2$s« með þér og vill bæta við", - "»%s« added a note to a file shared with you" : "»%s« bætti minnispunkti við skrá sem deilt er með þér", - "Open »%s«" : "Opna »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Deiling %s mistókst, því þessu atriði er þegar deilt með notandanum %s", - "%1$s shared »%2$s« with you" : "%1$s deildi »%2$s« með þér", - "%1$s shared »%2$s« with you." : "%1$s deildi »%2$s« með þér.", - "The username is already being used" : "Notandanafnið er þegar í notkun", - "Could not create user" : "Gat ekki búið til notanda", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Einungis eru leyfilegir eftirfarandi stafir í notandanafni: \"a-z\", \"A-Z\", \"0-9\", bil og \"_.@-'\"", - "A valid username must be provided" : "Skráðu inn gilt notandanafn", - "Username contains whitespace at the beginning or at the end" : "Notandanafnið inniheldur orðabil í upphafi eða enda", - "Username must not consist of dots only" : "Notandanafn má ekki einungis samanstanda af punktum", - "Username is invalid because files already exist for this user" : "Notandanafnið er ógilt vegna þess að þegar eru fyrir hendi skrár sem tilheyra þessum notanda", - "User disabled" : "Notandi óvirkur", + "Organisation" : "Stofnun/Félag/Fyrirtæki", "File is currently busy, please try again later" : "Skráin er upptekin í augnablikinu, reyndu aftur síðar", - "Cannot download file" : "Get ekki sótt skrá", - "Your data directory is readable by other users." : "Gagnamappn þín er lesanleg fyrir aðra notendur.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Endilega breyttu heimildunum í 0770 svo að aðrir notendur geti ekki listað upp innihald hennar.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Gakktu úr skugga um að til staðar sé skrá með heitinu \".ocdata\" í rót gagnageymslunnar." + "Cannot download file" : "Get ekki sótt skrá" },"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);" }
\ No newline at end of file diff --git a/lib/l10n/it.js b/lib/l10n/it.js index ac82d735509..8a0eee588fe 100644 --- a/lib/l10n/it.js +++ b/lib/l10n/it.js @@ -19,6 +19,7 @@ OC.L10N.register( "%1$s, %2$s and %3$s" : "%1$s, %2$s e %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s e %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s e %5$s", + "Education bundle" : "Pacchetto istruzione", "Enterprise bundle" : "Pacchetto Enterprise", "Groupware bundle" : "Pacchetto Groupware", "Hub bundle" : "Pacchetto Hub", @@ -35,6 +36,7 @@ OC.L10N.register( "The following platforms are supported: %s" : "Le seguenti piattaforme sono supportate: %s", "Server version %s or higher is required." : "È richiesta la versione %s o successiva.", "Server version %s or lower is required." : "È richiesta la versione %s o precedente.", + "Your current IP address doesn't allow you to perform admin actions" : "Il tuo attuale indirizzo IP non ti permette di eseguire azioni di amministrazione.", "Wiping of device %s has started" : "La cancellazione del dispositivo %s è iniziata", "Wiping of device »%s« has started" : "La cancellazione del dispositivo «%s» è iniziata", "»%s« started remote wipe" : "«%s» ha iniziato la cancellazione remota", @@ -53,6 +55,9 @@ OC.L10N.register( "Avatar image is not square" : "L'immagine personale non è quadrata", "Files" : "File", "View profile" : "Vedi profilo", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], + "%s ahead" : "%s avanti", + "%s behind" : "%s indietro", "Local time: %s" : "Ora locale: %s", "today" : "oggi", "tomorrow" : "domani", @@ -75,7 +80,10 @@ OC.L10N.register( "seconds ago" : "secondi fa", "Empty file" : "File vuoto", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Il modulo con ID: %s non esiste. Abilitalo nelle impostazioni delle applicazioni o contatta il tuo amministratore.", + "File is too large to convert" : "Il file è troppo grande per essere convertito", "Dot files are not allowed" : "I file con un punto iniziale non sono consentiti", + "%1$s (renamed)" : "%1$s (rinominato)", + "renamed file" : "file rinominato", "File already exists" : "Il file esiste già", "Invalid path" : "Percorso non valido", "Failed to create file from template" : "Impossibile creare un file dal modello", @@ -86,6 +94,7 @@ OC.L10N.register( "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "L'applicazione \"%s\" non può essere installata perché non è compatibile con questa versione del server.", "__language_name__" : "Italiano", "This is an automatically sent email, please do not reply." : "Questo è un messaggio di posta inviato automaticamente, non rispondere.", + "Help & privacy" : "Supporto & privacy", "Appearance and accessibility" : "Aspetto e accessibilità", "Apps" : "Applicazioni", "Personal settings" : "Impostazioni personali", @@ -108,15 +117,17 @@ OC.L10N.register( "About" : "Informazioni", "Display name" : "Nome visualizzato", "Headline" : "Titolo", - "Organisation" : "Organizzazione", + "Organization" : "Organizzazione", "Role" : "Ruolo", + "Pronouns" : "Pronomi", "Unknown account" : "Account sconosciuto", "Additional settings" : "Impostazioni aggiuntive", "Enter the database name for %s" : "Inserisci il nome del database per %s", "You cannot use dots in the database name %s" : "Non puoi usare punti nel nome del database %s", + "MySQL Login and/or password not valid" : "Nome utente e/o password non corretta per MySQL", "You need to enter details of an existing account." : "Devi inserire i dettagli di un account esistente.", "Oracle connection could not be established" : "La connessione a Oracle non può essere stabilita", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X non è supportato e %s non funzionerà correttamente su questa piattaforma. Usalo a tuo rischio!", + "PostgreSQL Login and/or password not valid" : "Nome utente e/o password non corretta per PostgreSQL", "For the best results, please consider using a GNU/Linux server instead." : "Per avere il risultato migliore, prendi in considerazione l'utilizzo di un server GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Sembra che questa istanza di %s sia in esecuzione in un ambiente PHP a 32 bit e che open_basedir sia stata configurata in php.ini. Ciò comporterà problemi con i file più grandi di 4 GB ed è altamente sconsigliato.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Rimuovi l'impostazione di open_basedir nel tuo php.ini o passa alla versione a 64 bit di PHP.", @@ -126,13 +137,13 @@ OC.L10N.register( "Sharing backend %s not found" : "Motore di condivisione %s non trovato", "Sharing backend for %s not found" : "Motore di condivisione di %s non trovato", "%1$s shared %2$s with you" : "%1$s condiviso %2$s con te", - "Click the button below to open it." : "Fai clic sul pulsante sotto per aprirlo.", "Open %s" : "Apri %s", "%1$s via %2$s" : "%1$s tramite %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s condiviso %2$s con te e vuole aggiungere:", "%1$s shared %2$s with you and wants to add" : "%1$s condiviso %2$s con te e vuole aggiungere", "%s added a note to a file shared with you" : "%s ha aggiunto una nota a un file condiviso con te", "Unknown share type" : "Tipo di condivisione sconosciuto", + "Cannot share with yourself" : "Non puoi condividere con te stesso.", "You are not allowed to share %s" : "Non ti è consentito condividere %s", "Cannot increase permissions of %s" : "Impossibile aumentare i permessi di %s", "Files cannot be shared with delete permissions" : "I file non possono essere condivisi con permessi di eliminazione", @@ -144,6 +155,7 @@ OC.L10N.register( "The requested share comes from a disabled user" : "La condivisione richiesta proviene da un utente disabilitato", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "L'utente non è stato creato perché il limite è stato raggiunto. Controlla le notifiche per maggiori informazioni.", "Could not find category \"%s\"" : "Impossibile trovare la categoria \"%s\"", + "Input text" : "Testo di input", "Sunday" : "Domenica", "Monday" : "Lunedì", "Tuesday" : "Martedì", @@ -236,7 +248,14 @@ OC.L10N.register( "Storage is temporarily not available" : "L'archiviazione è temporaneamente non disponibile", "Storage connection timeout. %s" : "Timeout di connessione all'archiviazione. %s", "Confirmation" : "Conferma", + "Generated response" : "Risposta generata", + "Change Tone" : "Cambia Tono", + "Write a text that you want the assistant to rewrite in another tone." : "Scrivi un testo che vuoi che l'assistente riscriva con un tono diverso.", + "Desired tone" : "Tono desiderato", + "In which tone should your text be rewritten?" : "Con quale tono dovresti riscrivere il tuo testo?", + "The rewritten text in the desired tone, written by the assistant:" : "Il testo riscritto nel tono desiderato, scritto dall'assistente:", "Generates a possible headline for a text." : "Genera un possibile titolo per un testo.", + "Text" : "Testo", "Summarize" : "Riassumi", "Summary" : "Riepilogo", "Extract topics" : "Estrai argomenti", @@ -248,41 +267,8 @@ OC.L10N.register( "Generate headline" : "Genera titolo", "Summarizes text by reducing its length without losing key information." : "Riassume il testo riducendone la lunghezza senza perdere le informazioni chiave.", "Extracts topics from a text and outputs them separated by commas." : "Estrae gli argomenti da un testo e li elenca separati da virgole.", - "Education Edition" : "Edizione didattica", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "L'utente connesso deve essere un admin, un sub admin o avere il permesso di accedere a questa impostazione", - "Logged in user must be an admin or sub admin" : "L'utente che ha eseguito l'accesso deve essere un amministratore o sub-amministratore", - "Logged in user must be an admin" : "L'utente che ha eseguito l'accesso deve essere un amministratore ", - "File name is a reserved word" : "Il nome del file è una parola riservata", - "File name contains at least one invalid character" : "Il nome del file contiene almeno un carattere non valido", - "File name is too long" : "Il nome del file è troppo lungo", - "Help" : "Aiuto", - "Users" : "Utenti", - "Unknown user" : "Utente sconosciuto", - "Enter the database username and name for %s" : "Inserisci il nome utente del database e il nome per %s", - "Enter the database username for %s" : "Inserisci il nome utente del database per %s", - "MySQL username and/or password not valid" : "Nome utente e/o password di MySQL non validi", - "Oracle username and/or password not valid" : "Nome utente e/o password di Oracle non validi", - "PostgreSQL username and/or password not valid" : "Nome utente e/o password di PostgreSQL non validi", - "Set an admin username." : "Imposta un nome utente di amministrazione.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s ha condiviso «%2$s» con te e vuole aggiungere:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s ha condiviso «%2$s» con te e vuole aggiungere", - "»%s« added a note to a file shared with you" : "«%s» ha aggiunto una nota a un file condiviso con te", - "Open »%s«" : "Apri «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "Condivisione di %s non riuscita, poiché l'oggetto è già condiviso con l'utente %s", - "%1$s shared »%2$s« with you" : "%1$s ha condiviso «%2$s» con te", - "%1$s shared »%2$s« with you." : "%1$s ha condiviso «%2$s» con te.", - "The username is already being used" : "Il nome utente è già utilizzato", - "Could not create user" : "Impossibile creare l'utente", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Solo i seguenti caratteri sono consentiti in un nome utente: \"a-z\", \"A-Z\", \"0-9\", spazi e \"_.@-'\"", - "A valid username must be provided" : "Deve essere fornito un nome utente valido", - "Username contains whitespace at the beginning or at the end" : "Il nome utente contiene spazi all'inizio o alla fine", - "Username must not consist of dots only" : "Il nome utente non può consistere di soli punti", - "Username is invalid because files already exist for this user" : "Il nome utente non è valido poiché esiste già per questo utente", - "User disabled" : "Utente disabilitato", + "Organisation" : "Organizzazione", "File is currently busy, please try again later" : "Il file è attualmente occupato, riprova più tardi", - "Cannot download file" : "Impossibile scaricare il file", - "Your data directory is readable by other users." : "La cartella dei dati è leggibile dagli altri utenti.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Modifica i permessi in 0770 in modo tale che la cartella non sia leggibile dagli altri utenti.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assicurati che ci sia un file \".ocdata\" nella radice della cartella data." + "Cannot download file" : "Impossibile scaricare il file" }, "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/it.json b/lib/l10n/it.json index 6510a457903..a8aa61d17d8 100644 --- a/lib/l10n/it.json +++ b/lib/l10n/it.json @@ -17,6 +17,7 @@ "%1$s, %2$s and %3$s" : "%1$s, %2$s e %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s e %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s e %5$s", + "Education bundle" : "Pacchetto istruzione", "Enterprise bundle" : "Pacchetto Enterprise", "Groupware bundle" : "Pacchetto Groupware", "Hub bundle" : "Pacchetto Hub", @@ -33,6 +34,7 @@ "The following platforms are supported: %s" : "Le seguenti piattaforme sono supportate: %s", "Server version %s or higher is required." : "È richiesta la versione %s o successiva.", "Server version %s or lower is required." : "È richiesta la versione %s o precedente.", + "Your current IP address doesn't allow you to perform admin actions" : "Il tuo attuale indirizzo IP non ti permette di eseguire azioni di amministrazione.", "Wiping of device %s has started" : "La cancellazione del dispositivo %s è iniziata", "Wiping of device »%s« has started" : "La cancellazione del dispositivo «%s» è iniziata", "»%s« started remote wipe" : "«%s» ha iniziato la cancellazione remota", @@ -51,6 +53,9 @@ "Avatar image is not square" : "L'immagine personale non è quadrata", "Files" : "File", "View profile" : "Vedi profilo", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], + "%s ahead" : "%s avanti", + "%s behind" : "%s indietro", "Local time: %s" : "Ora locale: %s", "today" : "oggi", "tomorrow" : "domani", @@ -73,7 +78,10 @@ "seconds ago" : "secondi fa", "Empty file" : "File vuoto", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Il modulo con ID: %s non esiste. Abilitalo nelle impostazioni delle applicazioni o contatta il tuo amministratore.", + "File is too large to convert" : "Il file è troppo grande per essere convertito", "Dot files are not allowed" : "I file con un punto iniziale non sono consentiti", + "%1$s (renamed)" : "%1$s (rinominato)", + "renamed file" : "file rinominato", "File already exists" : "Il file esiste già", "Invalid path" : "Percorso non valido", "Failed to create file from template" : "Impossibile creare un file dal modello", @@ -84,6 +92,7 @@ "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "L'applicazione \"%s\" non può essere installata perché non è compatibile con questa versione del server.", "__language_name__" : "Italiano", "This is an automatically sent email, please do not reply." : "Questo è un messaggio di posta inviato automaticamente, non rispondere.", + "Help & privacy" : "Supporto & privacy", "Appearance and accessibility" : "Aspetto e accessibilità", "Apps" : "Applicazioni", "Personal settings" : "Impostazioni personali", @@ -106,15 +115,17 @@ "About" : "Informazioni", "Display name" : "Nome visualizzato", "Headline" : "Titolo", - "Organisation" : "Organizzazione", + "Organization" : "Organizzazione", "Role" : "Ruolo", + "Pronouns" : "Pronomi", "Unknown account" : "Account sconosciuto", "Additional settings" : "Impostazioni aggiuntive", "Enter the database name for %s" : "Inserisci il nome del database per %s", "You cannot use dots in the database name %s" : "Non puoi usare punti nel nome del database %s", + "MySQL Login and/or password not valid" : "Nome utente e/o password non corretta per MySQL", "You need to enter details of an existing account." : "Devi inserire i dettagli di un account esistente.", "Oracle connection could not be established" : "La connessione a Oracle non può essere stabilita", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X non è supportato e %s non funzionerà correttamente su questa piattaforma. Usalo a tuo rischio!", + "PostgreSQL Login and/or password not valid" : "Nome utente e/o password non corretta per PostgreSQL", "For the best results, please consider using a GNU/Linux server instead." : "Per avere il risultato migliore, prendi in considerazione l'utilizzo di un server GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Sembra che questa istanza di %s sia in esecuzione in un ambiente PHP a 32 bit e che open_basedir sia stata configurata in php.ini. Ciò comporterà problemi con i file più grandi di 4 GB ed è altamente sconsigliato.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Rimuovi l'impostazione di open_basedir nel tuo php.ini o passa alla versione a 64 bit di PHP.", @@ -124,13 +135,13 @@ "Sharing backend %s not found" : "Motore di condivisione %s non trovato", "Sharing backend for %s not found" : "Motore di condivisione di %s non trovato", "%1$s shared %2$s with you" : "%1$s condiviso %2$s con te", - "Click the button below to open it." : "Fai clic sul pulsante sotto per aprirlo.", "Open %s" : "Apri %s", "%1$s via %2$s" : "%1$s tramite %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s condiviso %2$s con te e vuole aggiungere:", "%1$s shared %2$s with you and wants to add" : "%1$s condiviso %2$s con te e vuole aggiungere", "%s added a note to a file shared with you" : "%s ha aggiunto una nota a un file condiviso con te", "Unknown share type" : "Tipo di condivisione sconosciuto", + "Cannot share with yourself" : "Non puoi condividere con te stesso.", "You are not allowed to share %s" : "Non ti è consentito condividere %s", "Cannot increase permissions of %s" : "Impossibile aumentare i permessi di %s", "Files cannot be shared with delete permissions" : "I file non possono essere condivisi con permessi di eliminazione", @@ -142,6 +153,7 @@ "The requested share comes from a disabled user" : "La condivisione richiesta proviene da un utente disabilitato", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "L'utente non è stato creato perché il limite è stato raggiunto. Controlla le notifiche per maggiori informazioni.", "Could not find category \"%s\"" : "Impossibile trovare la categoria \"%s\"", + "Input text" : "Testo di input", "Sunday" : "Domenica", "Monday" : "Lunedì", "Tuesday" : "Martedì", @@ -234,7 +246,14 @@ "Storage is temporarily not available" : "L'archiviazione è temporaneamente non disponibile", "Storage connection timeout. %s" : "Timeout di connessione all'archiviazione. %s", "Confirmation" : "Conferma", + "Generated response" : "Risposta generata", + "Change Tone" : "Cambia Tono", + "Write a text that you want the assistant to rewrite in another tone." : "Scrivi un testo che vuoi che l'assistente riscriva con un tono diverso.", + "Desired tone" : "Tono desiderato", + "In which tone should your text be rewritten?" : "Con quale tono dovresti riscrivere il tuo testo?", + "The rewritten text in the desired tone, written by the assistant:" : "Il testo riscritto nel tono desiderato, scritto dall'assistente:", "Generates a possible headline for a text." : "Genera un possibile titolo per un testo.", + "Text" : "Testo", "Summarize" : "Riassumi", "Summary" : "Riepilogo", "Extract topics" : "Estrai argomenti", @@ -246,41 +265,8 @@ "Generate headline" : "Genera titolo", "Summarizes text by reducing its length without losing key information." : "Riassume il testo riducendone la lunghezza senza perdere le informazioni chiave.", "Extracts topics from a text and outputs them separated by commas." : "Estrae gli argomenti da un testo e li elenca separati da virgole.", - "Education Edition" : "Edizione didattica", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "L'utente connesso deve essere un admin, un sub admin o avere il permesso di accedere a questa impostazione", - "Logged in user must be an admin or sub admin" : "L'utente che ha eseguito l'accesso deve essere un amministratore o sub-amministratore", - "Logged in user must be an admin" : "L'utente che ha eseguito l'accesso deve essere un amministratore ", - "File name is a reserved word" : "Il nome del file è una parola riservata", - "File name contains at least one invalid character" : "Il nome del file contiene almeno un carattere non valido", - "File name is too long" : "Il nome del file è troppo lungo", - "Help" : "Aiuto", - "Users" : "Utenti", - "Unknown user" : "Utente sconosciuto", - "Enter the database username and name for %s" : "Inserisci il nome utente del database e il nome per %s", - "Enter the database username for %s" : "Inserisci il nome utente del database per %s", - "MySQL username and/or password not valid" : "Nome utente e/o password di MySQL non validi", - "Oracle username and/or password not valid" : "Nome utente e/o password di Oracle non validi", - "PostgreSQL username and/or password not valid" : "Nome utente e/o password di PostgreSQL non validi", - "Set an admin username." : "Imposta un nome utente di amministrazione.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s ha condiviso «%2$s» con te e vuole aggiungere:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s ha condiviso «%2$s» con te e vuole aggiungere", - "»%s« added a note to a file shared with you" : "«%s» ha aggiunto una nota a un file condiviso con te", - "Open »%s«" : "Apri «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "Condivisione di %s non riuscita, poiché l'oggetto è già condiviso con l'utente %s", - "%1$s shared »%2$s« with you" : "%1$s ha condiviso «%2$s» con te", - "%1$s shared »%2$s« with you." : "%1$s ha condiviso «%2$s» con te.", - "The username is already being used" : "Il nome utente è già utilizzato", - "Could not create user" : "Impossibile creare l'utente", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Solo i seguenti caratteri sono consentiti in un nome utente: \"a-z\", \"A-Z\", \"0-9\", spazi e \"_.@-'\"", - "A valid username must be provided" : "Deve essere fornito un nome utente valido", - "Username contains whitespace at the beginning or at the end" : "Il nome utente contiene spazi all'inizio o alla fine", - "Username must not consist of dots only" : "Il nome utente non può consistere di soli punti", - "Username is invalid because files already exist for this user" : "Il nome utente non è valido poiché esiste già per questo utente", - "User disabled" : "Utente disabilitato", + "Organisation" : "Organizzazione", "File is currently busy, please try again later" : "Il file è attualmente occupato, riprova più tardi", - "Cannot download file" : "Impossibile scaricare il file", - "Your data directory is readable by other users." : "La cartella dei dati è leggibile dagli altri utenti.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Modifica i permessi in 0770 in modo tale che la cartella non sia leggibile dagli altri utenti.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assicurati che ci sia un file \".ocdata\" nella radice della cartella data." + "Cannot download file" : "Impossibile scaricare il file" },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/ja.js b/lib/l10n/ja.js index 2570e45a060..a97a74306a9 100644 --- a/lib/l10n/ja.js +++ b/lib/l10n/ja.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "サーバーの %s よりも高いバージョンが必要です。", "Server version %s or lower is required." : "サーバーの %s よりも低いバージョンが必要です。", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "この設定にアクセスするには、ログインしたアカウントが管理者、サブ管理者、または特別な権利を持っている必要があります。", - "Your current IP address doesn’t allow you to perform admin actions" : "現在のIPアドレスでは管理アクションを実行できません", + "Your current IP address doesn't allow you to perform admin actions" : "現在のIPアドレスでは管理アクションを実行できません", "Logged in account must be an admin or sub admin" : "ログインアカウントは管理者またはサブ管理者である必要があります", "Logged in account must be an admin" : "ログインアカウントは管理者である必要があります", "Wiping of device %s has started" : "端末%sのワイプを開始しました。", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "アバター画像が正方形ではありません", "Files" : "ファイル", "View profile" : "プロフィールを表示", + "same time" : "同時", + "_%nh_::_%nh_" : ["%n時間"], + "_%nm_::_%nm_" : ["%n分"], + "%s ahead" : "%s先", + "%s behind" : "%s遅れ", "Local time: %s" : "現地時間: %s", "today" : "今日", "tomorrow" : "明日", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "数秒前", "Empty file" : "空白のファイル", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID: %sのモジュールは存在しません。アプリ設定で有効にするか、管理者に問い合わせてください。", + "No file conversion providers available" : "ファイル変換プロバイダーは利用できません", + "File is too large to convert" : "ファイルが大きすぎて変換できません", + "Destination does not match conversion extension" : "変換先の拡張子が一致しません", + "Could not convert file" : "ファイルを変換できませんでした", + "Destination does not exist" : "宛先が存在しません", + "Destination is not creatable" : "宛先は作成できません", "Dot files are not allowed" : "隠しファイルは許可されていません", + "%1$s (renamed)" : "%1$s (リネーム済み)", + "renamed file" : "リネーム済みファイル", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\"は禁止されているファイル名またはフォルダー名です。", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\"は、ファイル名やフォルダー名には使用できない接頭辞です。", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\"はファイル名やフォルダー名の中に入れることはできません。", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "パスが無効", "Failed to create file from template" : "テンプレートからファイルを作成できませんでした", "Templates" : "テンプレート", + "Storage %s cannot be moved" : "ストレージ%sは移動できません", + "Moving a share (%s) into a shared folder is not allowed" : "共有(%s)を共有フォルダに移動することは許可されていません", + "Moving a storage (%s) into a shared folder is not allowed" : "ストレージ(%s)を共有フォルダに移動することは許可されていません", + "Moving a share (%s) into another share (%s) is not allowed" : "共有 (%s) を別の共有 (%s) に移動することは許可されていません", + "Moving a share (%s) into another storage (%s) is not allowed" : "共有(%s)を別のストレージ(%s)に移動することは許可されていません", + "Moving a storage (%s) into a share (%s) is not allowed" : "ストレージ(%s)を共有(%s)に移動することは許可されていません", + "Moving a storage (%s) into another storage (%s) is not allowed" : "ストレージ(%s)を別のストレージ(%s)に移動することは許可されていません。", "Path contains invalid segments" : "パスに無効なセグメントが含まれています", "Filename is a reserved word" : "ファイル名が予約された単語です", "Filename contains at least one invalid character" : "ファイル名に使用できない文字が含まれています", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "詳細", "Display name" : "表示名", "Headline" : "見出し", - "Organisation" : "組織", + "Organization" : "共同作業", "Role" : "ロール", "Pronouns" : "代名詞", "Unknown account" : "不明なアカウント", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Oracleへの接続が確立できませんでした。", "Oracle Login and/or password not valid" : "Oracleのログイン名またはパスワードが有効ではありません", "PostgreSQL Login and/or password not valid" : "PostgreSQLのログイン名またはパスワードが有効ではありません", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X では、サポートされていません。このOSでは、%sは正常に動作しないかもしれません。ご自身の責任においてご利用ください。", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X では、サポートされていません。このOSでは、%sは正常に動作しないかもしれません。ご自身の責任においてご利用ください。", "For the best results, please consider using a GNU/Linux server instead." : "最も良い方法としては、代わりにGNU/Linuxサーバーを利用することをご検討ください。", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "このインスタンス %s は、32bit PHP 環境で動作しており、php.ini に open_basedir が設定されているようです。4GB以上のファイルで問題が発生するため、この設定を利用しないことをお勧めします。", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "php.ini から open_basedir 設定を削除するか、64bit PHPに切り替えてください。", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "共有バックエンド %s が見つかりません", "Sharing backend for %s not found" : "%s のための共有バックエンドが見つかりません", "%1$s shared %2$s with you" : "%1$s は %2$s をあなたと共有しました", - "Click the button below to open it." : "開くには下のボタンをクリック", "Open %s" : "%sを開く", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s さんが %2$s にノートを追加しました:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "ルートルートフォルダーを共有することはできません", "You are not allowed to share %s" : "%s を共有することを許可されていません。", "Valid permissions are required for sharing" : "共有には有効な権限が必要です", + "File shares cannot have create or delete permissions" : "ファイル共有に作成または削除の権限を設定することはできません", "Cannot increase permissions of %s" : "%sの権限を追加できません ", "Shares need at least read permissions" : "共有には少なくとも読み取り権限が必要です", "Files cannot be shared with delete permissions" : "削除権限付きでファイルを共有できません", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "パスはすでにこのグループで共有されています", "Link sharing is not allowed" : "リンクの共有は許可されていません", "Public upload is not allowed" : "公開アップロードは許可されていません", - "Path contains files shared with you" : "パスにはあなたと共有するファイルが含まれています", + "You cannot share a folder that contains other shares" : "他の共有を含むフォルダーを共有することはできません", "Sharing is disabled" : "共有は無効になっています", "Sharing is disabled for you" : "共有は無効になっています", "Cannot share with the share owner" : "共有所有者と共有できません", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "ログイン名を提供する必要があります", "Login contains whitespace at the beginning or at the end" : "ログイン名の最初か最後に空白が含まれています", "Login must not consist of dots only" : "ログイン名はドットのみで構成されてはいけません", + "Username is too long" : "ユーザー名が長すぎます", "Login is invalid because files already exist for this user" : "このユーザのファイルが既に存在するため、このログイン名は使用できません", "Account disabled" : "アカウントは無効", "Login canceled by app" : "アプリによりログインが中止されました", @@ -311,8 +332,19 @@ OC.L10N.register( "The audio to transcribe" : "文字起こしする音声", "Transcription" : "書き起こし", "The transcribed text" : "書き起こされたテキスト", + "Chat with an agent" : "エージェントとチャット", "Chat message" : "チャットメッセージ", + "A chat message to send to the agent." : "エージェントに送信するチャットメッセージ。", "Confirmation" : "確認", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "以前に要求されたアクションを承認するかどうか: 0なら拒否、1なら承認。", + "Conversation token" : "会話トークン", + "A token representing the conversation." : "会話を表すトークン。", + "Generated response" : "生成された応答", + "The response from the chat model." : "チャットモデルからの応答。", + "The new conversation token" : "新しい会話トークン", + "Send this along with the next interaction." : "次の交流と一緒にこれを送る。", + "Requested actions by the agent" : "エージェントが要求するアクション", + "Actions that the agent would like to carry out in JSON format." : "エージェントが JSON 形式で実行したいアクション。", "Context write" : "コンテキストを書く", "Writes text in a given style based on the provided source material." : "提供されたソース資料に基づいて、指定されたスタイルでテキストを作成します。", "Writing style" : "文体", @@ -334,11 +366,22 @@ OC.L10N.register( "How many images to generate" : "生成する画像の数", "Output images" : "出力画像", "The generated images" : "生成された画像", + "Generate speech" : "スピーチの生成", + "Generate speech from a transcript" : "原稿からスピーチを生成する", + "Write transcript that you want the assistant to generate speech from" : "アシスタントに音声を生成させたい原稿を書きます", + "Output speech" : "スピーチの出力", + "The generated speech" : "生成されたスピーチ", "Free text to text prompt" : "フリーテキストからテキストへのプロンプト", "Runs an arbitrary prompt through a language model that returns a reply" : "応答を返す言語モデルを通じて任意のプロンプトを実行します", "Describe a task that you want the assistant to do or ask a question" : "アシスタントに実行してほしいタスクまたは質問を記述します", "Generated reply" : "生成された返信", "The generated text from the assistant" : "アシスタントから生成されたテキスト", + "Change Tone" : "トーンを変更", + "Change the tone of a piece of text." : "文章のトーンを変更する。", + "Write a text that you want the assistant to rewrite in another tone." : "アシスタントに別のトーンで書き直してもらいたい文章を書く。", + "Desired tone" : "希望するトーン", + "In which tone should your text be rewritten?" : "どのトーンで書き直すべきか?", + "The rewritten text in the desired tone, written by the assistant:" : "アシスタントが書き直した、希望するトーンの文章:", "Chat" : "チャット", "Chat with the assistant" : "アシスタントとチャット", "System prompt" : "システムプロンプト", @@ -347,6 +390,15 @@ OC.L10N.register( "The history of chat messages before the current message, starting with a message by the user" : "ユーザーのメッセージから始まる、現在のメッセージより前のチャットメッセージの履歴", "Response message" : "応答メッセージ", "The generated response as part of the conversation" : "会話の一部として生成された応答", + "Chat with tools" : "ツールでチャット", + "Chat with the language model with tool calling support." : "ツール呼び出しサポートを使用して言語モデルとチャット。", + "Tool message" : "ツールメッセージ", + "The result of tool calls in the last interaction" : "直近のインタラクションにおけるツール呼び出しの結果", + "Available tools" : "利用可能なツール", + "The available tools in JSON format" : "JSON形式で利用可能なツール", + "The response from the chat model" : "チャットモデルからの応答", + "Tool calls" : "ツールコール", + "Tools call instructions from the model in JSON format" : "JSON形式のモデルからのツール呼び出し命令", "Formalize text" : "テキストの形式化", "Takes a text and makes it sound more formal" : "テキストを使用して、よりフォーマルに聞こえるようにします", "Write a text that you want the assistant to formalize" : "アシスタントに形式化してもらいたいテキストを入力します", @@ -357,6 +409,12 @@ OC.L10N.register( "Original text" : "原文", "The original text to generate a headline for" : "見出しを生成する元のテキスト", "The generated headline" : "生成された見出し", + "Proofread" : "校正", + "Proofreads a text and lists corrections" : "文章を校正し、訂正箇所をリストアップする", + "Text" : "テキスト", + "The text to proofread" : "校正するテキスト", + "Corrections" : "修正", + "The corrections that should be made in your text" : "テキストに加えるべき修正", "Reformulate text" : "テキストを書き直す", "Takes a text and reformulates it" : "テキストを受け取り、それを書き直す", "Write a text that you want the assistant to reformulate" : "アシスタントに書き直してもらいたいテキストを入力します", @@ -392,41 +450,9 @@ OC.L10N.register( "Generate headline" : "見出しの生成", "Summarizes text by reducing its length without losing key information." : "重要な情報を失わずにテキストの長さを要約して短縮する。", "Extracts topics from a text and outputs them separated by commas." : "テキストからトピックを抽出し、カンマ区切りで出力します。", - "Education Edition" : "教育向けエディション", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "この設定にアクセスするには、ログインしたユーザーが管理者、サブ管理者、または特別な権利が必要です。", - "Logged in user must be an admin or sub admin" : "ログインユーザーは管理者またはサブ管理者である必要があります", - "Logged in user must be an admin" : "ログインユーザーは管理者である必要があります", - "File name is a reserved word" : "ファイル名が予約された単語です", - "File name contains at least one invalid character" : "ファイル名に1文字以上の無効な文字が含まれています", - "File name is too long" : "ファイル名が長すぎます", - "Help" : "ヘルプ", - "Users" : "ユーザー", - "Unknown user" : "不明なユーザー", - "Enter the database username and name for %s" : "%sのデータベース名とユーザー名を入力してください", - "Enter the database username for %s" : "%sのデータベースのユーザー名を指定してください", - "MySQL username and/or password not valid" : "MySQLのユーザー名またはパスワードが有効ではありません", - "Oracle username and/or password not valid" : "Oracleのユーザー名またはパスワードが有効ではありません", - "PostgreSQL username and/or password not valid" : "PostgreSQLのユーザー名またはパスワードが有効ではありません", - "Set an admin username." : "管理者のユーザー名を設定", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s さんが »%2$s« にノートを追加しました。", - "%1$s shared »%2$s« with you and wants to add" : "%1$s shared »%2$s« with you and wants to add", - "»%s« added a note to a file shared with you" : "»%s« があなたと共有しているファイルにノートを追加しました。 ", - "Open »%s«" : "»%s«を開く", - "Sharing %s failed, because this item is already shared with user %s" : "このアイテム%sはすでにユーザー%sと共有されているため、共有に失敗しました", - "%1$s shared »%2$s« with you" : "%1$s は »%2$s« をあなたと共有しました", - "%1$s shared »%2$s« with you." : "%1$sが あなたと »%2$s« を共有しました。", - "The username is already being used" : "このユーザー名はすでに使われています", - "Could not create user" : "ユーザーを作成できませんでした", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "ユーザー名で利用できる文字列: \"a-z\", \"A-Z\", \"0-9\", スペース, \"_.@-\"", - "A valid username must be provided" : "有効なユーザー名を指定する必要があります", - "Username contains whitespace at the beginning or at the end" : "ユーザー名の最初か最後に空白が含まれています", - "Username must not consist of dots only" : "ユーザー名に、ドットのみはつけられません", - "Username is invalid because files already exist for this user" : "このユーザーのファイルが既に存在するため、このユーザー名は使用できません", - "User disabled" : "ユーザーは無効です", + "Organisation" : "組織", "File is currently busy, please try again later" : "現在ファイルはビジーです。後でもう一度試してください。", "Cannot download file" : "ファイルをダウンロードできません", - "Your data directory is readable by other users." : "データディレクトリは他のユーザーからも読み取ることができます", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "ディレクトリが他のユーザーから見えないように、パーミッションを 0770 に変更してください。", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "データディレクトリの直下に \".ocdata\" ファイルがあるのを確認してください。" + "Login is too long" : "ログインが長すぎます" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/ja.json b/lib/l10n/ja.json index 02efe7695bc..e51cabebf36 100644 --- a/lib/l10n/ja.json +++ b/lib/l10n/ja.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "サーバーの %s よりも高いバージョンが必要です。", "Server version %s or lower is required." : "サーバーの %s よりも低いバージョンが必要です。", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "この設定にアクセスするには、ログインしたアカウントが管理者、サブ管理者、または特別な権利を持っている必要があります。", - "Your current IP address doesn’t allow you to perform admin actions" : "現在のIPアドレスでは管理アクションを実行できません", + "Your current IP address doesn't allow you to perform admin actions" : "現在のIPアドレスでは管理アクションを実行できません", "Logged in account must be an admin or sub admin" : "ログインアカウントは管理者またはサブ管理者である必要があります", "Logged in account must be an admin" : "ログインアカウントは管理者である必要があります", "Wiping of device %s has started" : "端末%sのワイプを開始しました。", @@ -57,6 +57,11 @@ "Avatar image is not square" : "アバター画像が正方形ではありません", "Files" : "ファイル", "View profile" : "プロフィールを表示", + "same time" : "同時", + "_%nh_::_%nh_" : ["%n時間"], + "_%nm_::_%nm_" : ["%n分"], + "%s ahead" : "%s先", + "%s behind" : "%s遅れ", "Local time: %s" : "現地時間: %s", "today" : "今日", "tomorrow" : "明日", @@ -79,7 +84,15 @@ "seconds ago" : "数秒前", "Empty file" : "空白のファイル", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID: %sのモジュールは存在しません。アプリ設定で有効にするか、管理者に問い合わせてください。", + "No file conversion providers available" : "ファイル変換プロバイダーは利用できません", + "File is too large to convert" : "ファイルが大きすぎて変換できません", + "Destination does not match conversion extension" : "変換先の拡張子が一致しません", + "Could not convert file" : "ファイルを変換できませんでした", + "Destination does not exist" : "宛先が存在しません", + "Destination is not creatable" : "宛先は作成できません", "Dot files are not allowed" : "隠しファイルは許可されていません", + "%1$s (renamed)" : "%1$s (リネーム済み)", + "renamed file" : "リネーム済みファイル", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\"は禁止されているファイル名またはフォルダー名です。", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\"は、ファイル名やフォルダー名には使用できない接頭辞です。", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\"はファイル名やフォルダー名の中に入れることはできません。", @@ -90,6 +103,13 @@ "Invalid path" : "パスが無効", "Failed to create file from template" : "テンプレートからファイルを作成できませんでした", "Templates" : "テンプレート", + "Storage %s cannot be moved" : "ストレージ%sは移動できません", + "Moving a share (%s) into a shared folder is not allowed" : "共有(%s)を共有フォルダに移動することは許可されていません", + "Moving a storage (%s) into a shared folder is not allowed" : "ストレージ(%s)を共有フォルダに移動することは許可されていません", + "Moving a share (%s) into another share (%s) is not allowed" : "共有 (%s) を別の共有 (%s) に移動することは許可されていません", + "Moving a share (%s) into another storage (%s) is not allowed" : "共有(%s)を別のストレージ(%s)に移動することは許可されていません", + "Moving a storage (%s) into a share (%s) is not allowed" : "ストレージ(%s)を共有(%s)に移動することは許可されていません", + "Moving a storage (%s) into another storage (%s) is not allowed" : "ストレージ(%s)を別のストレージ(%s)に移動することは許可されていません。", "Path contains invalid segments" : "パスに無効なセグメントが含まれています", "Filename is a reserved word" : "ファイル名が予約された単語です", "Filename contains at least one invalid character" : "ファイル名に使用できない文字が含まれています", @@ -122,7 +142,7 @@ "About" : "詳細", "Display name" : "表示名", "Headline" : "見出し", - "Organisation" : "組織", + "Organization" : "共同作業", "Role" : "ロール", "Pronouns" : "代名詞", "Unknown account" : "不明なアカウント", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "Oracleへの接続が確立できませんでした。", "Oracle Login and/or password not valid" : "Oracleのログイン名またはパスワードが有効ではありません", "PostgreSQL Login and/or password not valid" : "PostgreSQLのログイン名またはパスワードが有効ではありません", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X では、サポートされていません。このOSでは、%sは正常に動作しないかもしれません。ご自身の責任においてご利用ください。", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X では、サポートされていません。このOSでは、%sは正常に動作しないかもしれません。ご自身の責任においてご利用ください。", "For the best results, please consider using a GNU/Linux server instead." : "最も良い方法としては、代わりにGNU/Linuxサーバーを利用することをご検討ください。", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "このインスタンス %s は、32bit PHP 環境で動作しており、php.ini に open_basedir が設定されているようです。4GB以上のファイルで問題が発生するため、この設定を利用しないことをお勧めします。", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "php.ini から open_basedir 設定を削除するか、64bit PHPに切り替えてください。", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "共有バックエンド %s が見つかりません", "Sharing backend for %s not found" : "%s のための共有バックエンドが見つかりません", "%1$s shared %2$s with you" : "%1$s は %2$s をあなたと共有しました", - "Click the button below to open it." : "開くには下のボタンをクリック", "Open %s" : "%sを開く", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s さんが %2$s にノートを追加しました:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "ルートルートフォルダーを共有することはできません", "You are not allowed to share %s" : "%s を共有することを許可されていません。", "Valid permissions are required for sharing" : "共有には有効な権限が必要です", + "File shares cannot have create or delete permissions" : "ファイル共有に作成または削除の権限を設定することはできません", "Cannot increase permissions of %s" : "%sの権限を追加できません ", "Shares need at least read permissions" : "共有には少なくとも読み取り権限が必要です", "Files cannot be shared with delete permissions" : "削除権限付きでファイルを共有できません", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "パスはすでにこのグループで共有されています", "Link sharing is not allowed" : "リンクの共有は許可されていません", "Public upload is not allowed" : "公開アップロードは許可されていません", - "Path contains files shared with you" : "パスにはあなたと共有するファイルが含まれています", + "You cannot share a folder that contains other shares" : "他の共有を含むフォルダーを共有することはできません", "Sharing is disabled" : "共有は無効になっています", "Sharing is disabled for you" : "共有は無効になっています", "Cannot share with the share owner" : "共有所有者と共有できません", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "ログイン名を提供する必要があります", "Login contains whitespace at the beginning or at the end" : "ログイン名の最初か最後に空白が含まれています", "Login must not consist of dots only" : "ログイン名はドットのみで構成されてはいけません", + "Username is too long" : "ユーザー名が長すぎます", "Login is invalid because files already exist for this user" : "このユーザのファイルが既に存在するため、このログイン名は使用できません", "Account disabled" : "アカウントは無効", "Login canceled by app" : "アプリによりログインが中止されました", @@ -309,8 +330,19 @@ "The audio to transcribe" : "文字起こしする音声", "Transcription" : "書き起こし", "The transcribed text" : "書き起こされたテキスト", + "Chat with an agent" : "エージェントとチャット", "Chat message" : "チャットメッセージ", + "A chat message to send to the agent." : "エージェントに送信するチャットメッセージ。", "Confirmation" : "確認", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "以前に要求されたアクションを承認するかどうか: 0なら拒否、1なら承認。", + "Conversation token" : "会話トークン", + "A token representing the conversation." : "会話を表すトークン。", + "Generated response" : "生成された応答", + "The response from the chat model." : "チャットモデルからの応答。", + "The new conversation token" : "新しい会話トークン", + "Send this along with the next interaction." : "次の交流と一緒にこれを送る。", + "Requested actions by the agent" : "エージェントが要求するアクション", + "Actions that the agent would like to carry out in JSON format." : "エージェントが JSON 形式で実行したいアクション。", "Context write" : "コンテキストを書く", "Writes text in a given style based on the provided source material." : "提供されたソース資料に基づいて、指定されたスタイルでテキストを作成します。", "Writing style" : "文体", @@ -332,11 +364,22 @@ "How many images to generate" : "生成する画像の数", "Output images" : "出力画像", "The generated images" : "生成された画像", + "Generate speech" : "スピーチの生成", + "Generate speech from a transcript" : "原稿からスピーチを生成する", + "Write transcript that you want the assistant to generate speech from" : "アシスタントに音声を生成させたい原稿を書きます", + "Output speech" : "スピーチの出力", + "The generated speech" : "生成されたスピーチ", "Free text to text prompt" : "フリーテキストからテキストへのプロンプト", "Runs an arbitrary prompt through a language model that returns a reply" : "応答を返す言語モデルを通じて任意のプロンプトを実行します", "Describe a task that you want the assistant to do or ask a question" : "アシスタントに実行してほしいタスクまたは質問を記述します", "Generated reply" : "生成された返信", "The generated text from the assistant" : "アシスタントから生成されたテキスト", + "Change Tone" : "トーンを変更", + "Change the tone of a piece of text." : "文章のトーンを変更する。", + "Write a text that you want the assistant to rewrite in another tone." : "アシスタントに別のトーンで書き直してもらいたい文章を書く。", + "Desired tone" : "希望するトーン", + "In which tone should your text be rewritten?" : "どのトーンで書き直すべきか?", + "The rewritten text in the desired tone, written by the assistant:" : "アシスタントが書き直した、希望するトーンの文章:", "Chat" : "チャット", "Chat with the assistant" : "アシスタントとチャット", "System prompt" : "システムプロンプト", @@ -345,6 +388,15 @@ "The history of chat messages before the current message, starting with a message by the user" : "ユーザーのメッセージから始まる、現在のメッセージより前のチャットメッセージの履歴", "Response message" : "応答メッセージ", "The generated response as part of the conversation" : "会話の一部として生成された応答", + "Chat with tools" : "ツールでチャット", + "Chat with the language model with tool calling support." : "ツール呼び出しサポートを使用して言語モデルとチャット。", + "Tool message" : "ツールメッセージ", + "The result of tool calls in the last interaction" : "直近のインタラクションにおけるツール呼び出しの結果", + "Available tools" : "利用可能なツール", + "The available tools in JSON format" : "JSON形式で利用可能なツール", + "The response from the chat model" : "チャットモデルからの応答", + "Tool calls" : "ツールコール", + "Tools call instructions from the model in JSON format" : "JSON形式のモデルからのツール呼び出し命令", "Formalize text" : "テキストの形式化", "Takes a text and makes it sound more formal" : "テキストを使用して、よりフォーマルに聞こえるようにします", "Write a text that you want the assistant to formalize" : "アシスタントに形式化してもらいたいテキストを入力します", @@ -355,6 +407,12 @@ "Original text" : "原文", "The original text to generate a headline for" : "見出しを生成する元のテキスト", "The generated headline" : "生成された見出し", + "Proofread" : "校正", + "Proofreads a text and lists corrections" : "文章を校正し、訂正箇所をリストアップする", + "Text" : "テキスト", + "The text to proofread" : "校正するテキスト", + "Corrections" : "修正", + "The corrections that should be made in your text" : "テキストに加えるべき修正", "Reformulate text" : "テキストを書き直す", "Takes a text and reformulates it" : "テキストを受け取り、それを書き直す", "Write a text that you want the assistant to reformulate" : "アシスタントに書き直してもらいたいテキストを入力します", @@ -390,41 +448,9 @@ "Generate headline" : "見出しの生成", "Summarizes text by reducing its length without losing key information." : "重要な情報を失わずにテキストの長さを要約して短縮する。", "Extracts topics from a text and outputs them separated by commas." : "テキストからトピックを抽出し、カンマ区切りで出力します。", - "Education Edition" : "教育向けエディション", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "この設定にアクセスするには、ログインしたユーザーが管理者、サブ管理者、または特別な権利が必要です。", - "Logged in user must be an admin or sub admin" : "ログインユーザーは管理者またはサブ管理者である必要があります", - "Logged in user must be an admin" : "ログインユーザーは管理者である必要があります", - "File name is a reserved word" : "ファイル名が予約された単語です", - "File name contains at least one invalid character" : "ファイル名に1文字以上の無効な文字が含まれています", - "File name is too long" : "ファイル名が長すぎます", - "Help" : "ヘルプ", - "Users" : "ユーザー", - "Unknown user" : "不明なユーザー", - "Enter the database username and name for %s" : "%sのデータベース名とユーザー名を入力してください", - "Enter the database username for %s" : "%sのデータベースのユーザー名を指定してください", - "MySQL username and/or password not valid" : "MySQLのユーザー名またはパスワードが有効ではありません", - "Oracle username and/or password not valid" : "Oracleのユーザー名またはパスワードが有効ではありません", - "PostgreSQL username and/or password not valid" : "PostgreSQLのユーザー名またはパスワードが有効ではありません", - "Set an admin username." : "管理者のユーザー名を設定", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s さんが »%2$s« にノートを追加しました。", - "%1$s shared »%2$s« with you and wants to add" : "%1$s shared »%2$s« with you and wants to add", - "»%s« added a note to a file shared with you" : "»%s« があなたと共有しているファイルにノートを追加しました。 ", - "Open »%s«" : "»%s«を開く", - "Sharing %s failed, because this item is already shared with user %s" : "このアイテム%sはすでにユーザー%sと共有されているため、共有に失敗しました", - "%1$s shared »%2$s« with you" : "%1$s は »%2$s« をあなたと共有しました", - "%1$s shared »%2$s« with you." : "%1$sが あなたと »%2$s« を共有しました。", - "The username is already being used" : "このユーザー名はすでに使われています", - "Could not create user" : "ユーザーを作成できませんでした", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "ユーザー名で利用できる文字列: \"a-z\", \"A-Z\", \"0-9\", スペース, \"_.@-\"", - "A valid username must be provided" : "有効なユーザー名を指定する必要があります", - "Username contains whitespace at the beginning or at the end" : "ユーザー名の最初か最後に空白が含まれています", - "Username must not consist of dots only" : "ユーザー名に、ドットのみはつけられません", - "Username is invalid because files already exist for this user" : "このユーザーのファイルが既に存在するため、このユーザー名は使用できません", - "User disabled" : "ユーザーは無効です", + "Organisation" : "組織", "File is currently busy, please try again later" : "現在ファイルはビジーです。後でもう一度試してください。", "Cannot download file" : "ファイルをダウンロードできません", - "Your data directory is readable by other users." : "データディレクトリは他のユーザーからも読み取ることができます", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "ディレクトリが他のユーザーから見えないように、パーミッションを 0770 に変更してください。", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "データディレクトリの直下に \".ocdata\" ファイルがあるのを確認してください。" + "Login is too long" : "ログインが長すぎます" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/ka.js b/lib/l10n/ka.js index f3c0729d5ed..eb341cb81ee 100644 --- a/lib/l10n/ka.js +++ b/lib/l10n/ka.js @@ -108,14 +108,13 @@ OC.L10N.register( "About" : "About", "Display name" : "Display name", "Headline" : "Headline", - "Organisation" : "Organisation", + "Organization" : "Organization", "Role" : "Role", "Additional settings" : "Additional settings", "Enter the database name for %s" : "Enter the database name for %s", "You cannot use dots in the database name %s" : "You cannot use dots in the database name %s", "You need to enter details of an existing account." : "You need to enter details of an existing account.", "Oracle connection could not be established" : "Oracle connection could not be established", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! ", "For the best results, please consider using a GNU/Linux server instead." : "For the best results, please consider using a GNU/Linux server instead.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.", @@ -124,7 +123,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Sharing backend %s must implement the interface OCP\\Share_Backend", "Sharing backend %s not found" : "Sharing backend %s not found", "Sharing backend for %s not found" : "Sharing backend for %s not found", - "Click the button below to open it." : "Click the button below to open it.", "%1$s via %2$s" : "%1$s via %2$s", "Unknown share type" : "Unknown share type", "You are not allowed to share %s" : "You are not allowed to share %s", @@ -230,6 +228,7 @@ OC.L10N.register( "Storage connection timeout. %s" : "Storage connection timeout. %s", "Chat" : "Chat", "Generates a possible headline for a text." : "Generates a possible headline for a text.", + "Text" : "Text", "Summarize" : "Summarize", "Summary" : "Summary", "Extract topics" : "Extract topics", @@ -240,41 +239,8 @@ OC.L10N.register( "Generate headline" : "Generate headline", "Summarizes text by reducing its length without losing key information." : "Summarizes text by reducing its length without losing key information.", "Extracts topics from a text and outputs them separated by commas." : "Extracts topics from a text and outputs them separated by commas.", - "Education Edition" : "Education Edition", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Logged in user must be an admin, a sub admin or gotten special right to access this setting", - "Logged in user must be an admin or sub admin" : "Logged in user must be an admin or sub admin", - "Logged in user must be an admin" : "Logged in user must be an admin", - "File name is a reserved word" : "File name is a reserved word", - "File name contains at least one invalid character" : "File name contains at least one invalid character", - "File name is too long" : "File name is too long", - "Help" : "Help", - "Users" : "Users", - "Unknown user" : "Unknown user", - "Enter the database username and name for %s" : "Enter the database username and name for %s", - "Enter the database username for %s" : "Enter the database username for %s", - "MySQL username and/or password not valid" : "MySQL username and/or password not valid", - "Oracle username and/or password not valid" : "Oracle username and/or password not valid", - "PostgreSQL username and/or password not valid" : "PostgreSQL username and/or password not valid", - "Set an admin username." : "Set an admin username.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s shared »%2$s« with you and wants to add:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s shared »%2$s« with you and wants to add", - "»%s« added a note to a file shared with you" : "»%s« added a note to a file shared with you", - "Open »%s«" : "Open »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Sharing %s failed, because this item is already shared with user %s", - "%1$s shared »%2$s« with you" : "%1$s shared »%2$s« with you", - "%1$s shared »%2$s« with you." : "%1$s shared »%2$s« with you.", - "The username is already being used" : "The username is already being used", - "Could not create user" : "Could not create user", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"", - "A valid username must be provided" : "A valid username must be provided", - "Username contains whitespace at the beginning or at the end" : "Username contains whitespace at the beginning or at the end", - "Username must not consist of dots only" : "Username must not consist of dots only", - "Username is invalid because files already exist for this user" : "Username is invalid because files already exist for this user", - "User disabled" : "User disabled", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "File is currently busy, please try again later", - "Cannot download file" : "Cannot download file", - "Your data directory is readable by other users." : "Your data directory is readable by other users.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Please change the permissions to 0770 so that the directory cannot be listed by other users.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Ensure there is a file called \".ocdata\" in the root of the data directory." + "Cannot download file" : "Cannot download file" }, "nplurals=2; plural=(n!=1);"); diff --git a/lib/l10n/ka.json b/lib/l10n/ka.json index 2e29b840f41..14882187d5d 100644 --- a/lib/l10n/ka.json +++ b/lib/l10n/ka.json @@ -106,14 +106,13 @@ "About" : "About", "Display name" : "Display name", "Headline" : "Headline", - "Organisation" : "Organisation", + "Organization" : "Organization", "Role" : "Role", "Additional settings" : "Additional settings", "Enter the database name for %s" : "Enter the database name for %s", "You cannot use dots in the database name %s" : "You cannot use dots in the database name %s", "You need to enter details of an existing account." : "You need to enter details of an existing account.", "Oracle connection could not be established" : "Oracle connection could not be established", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! ", "For the best results, please consider using a GNU/Linux server instead." : "For the best results, please consider using a GNU/Linux server instead.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.", @@ -122,7 +121,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Sharing backend %s must implement the interface OCP\\Share_Backend", "Sharing backend %s not found" : "Sharing backend %s not found", "Sharing backend for %s not found" : "Sharing backend for %s not found", - "Click the button below to open it." : "Click the button below to open it.", "%1$s via %2$s" : "%1$s via %2$s", "Unknown share type" : "Unknown share type", "You are not allowed to share %s" : "You are not allowed to share %s", @@ -228,6 +226,7 @@ "Storage connection timeout. %s" : "Storage connection timeout. %s", "Chat" : "Chat", "Generates a possible headline for a text." : "Generates a possible headline for a text.", + "Text" : "Text", "Summarize" : "Summarize", "Summary" : "Summary", "Extract topics" : "Extract topics", @@ -238,41 +237,8 @@ "Generate headline" : "Generate headline", "Summarizes text by reducing its length without losing key information." : "Summarizes text by reducing its length without losing key information.", "Extracts topics from a text and outputs them separated by commas." : "Extracts topics from a text and outputs them separated by commas.", - "Education Edition" : "Education Edition", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Logged in user must be an admin, a sub admin or gotten special right to access this setting", - "Logged in user must be an admin or sub admin" : "Logged in user must be an admin or sub admin", - "Logged in user must be an admin" : "Logged in user must be an admin", - "File name is a reserved word" : "File name is a reserved word", - "File name contains at least one invalid character" : "File name contains at least one invalid character", - "File name is too long" : "File name is too long", - "Help" : "Help", - "Users" : "Users", - "Unknown user" : "Unknown user", - "Enter the database username and name for %s" : "Enter the database username and name for %s", - "Enter the database username for %s" : "Enter the database username for %s", - "MySQL username and/or password not valid" : "MySQL username and/or password not valid", - "Oracle username and/or password not valid" : "Oracle username and/or password not valid", - "PostgreSQL username and/or password not valid" : "PostgreSQL username and/or password not valid", - "Set an admin username." : "Set an admin username.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s shared »%2$s« with you and wants to add:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s shared »%2$s« with you and wants to add", - "»%s« added a note to a file shared with you" : "»%s« added a note to a file shared with you", - "Open »%s«" : "Open »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Sharing %s failed, because this item is already shared with user %s", - "%1$s shared »%2$s« with you" : "%1$s shared »%2$s« with you", - "%1$s shared »%2$s« with you." : "%1$s shared »%2$s« with you.", - "The username is already being used" : "The username is already being used", - "Could not create user" : "Could not create user", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"", - "A valid username must be provided" : "A valid username must be provided", - "Username contains whitespace at the beginning or at the end" : "Username contains whitespace at the beginning or at the end", - "Username must not consist of dots only" : "Username must not consist of dots only", - "Username is invalid because files already exist for this user" : "Username is invalid because files already exist for this user", - "User disabled" : "User disabled", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "File is currently busy, please try again later", - "Cannot download file" : "Cannot download file", - "Your data directory is readable by other users." : "Your data directory is readable by other users.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Please change the permissions to 0770 so that the directory cannot be listed by other users.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Ensure there is a file called \".ocdata\" in the root of the data directory." + "Cannot download file" : "Cannot download file" },"pluralForm" :"nplurals=2; plural=(n!=1);" }
\ No newline at end of file diff --git a/lib/l10n/ka_GE.js b/lib/l10n/ka_GE.js index 0f399ec7b21..897e4947af7 100644 --- a/lib/l10n/ka_GE.js +++ b/lib/l10n/ka_GE.js @@ -66,7 +66,6 @@ OC.L10N.register( "Additional settings" : "დამატებითი პარამეტრები", "You need to enter details of an existing account." : "საჭიროა შეიყვანოთ არსებული ანგარიშის დეტალები.", "Oracle connection could not be established" : "Oracle კავშირი ვერ დამყარდა", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X არაა მხარდაჭერილი და %s ამ პლატფორმაზე სწორად არ იმუშავებს. გამოიყენეთ საკუთარი რისკით!", "For the best results, please consider using a GNU/Linux server instead." : "საუკეთესო შედეგებისთვის სანაცვლოდ გამოიყენეთ GNU/Linux სერვერი.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "როგორც ჩანს ეს %s ინსტანცია მოქმედებს 32-ბიტიან PHP გარემოზე და open_basedir php.ini-ში კონფიგურირებულია. ეს 4 გბ-ზე დიდ ფაილებთან გამოიწვევს პრობლემს და რეკომედირებული არაა.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "გთხოვთ ამოშალოთ open_basedir პარამეტრი php.ini-დან ან გადახვიდეთ 64-ბიტიან PHP-ზე.", @@ -74,7 +73,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "გაზიარების ბექენდმა %s-მ მოქმედებაში უნდა მოიყვანოს ინტეფეისი OCP\\Share_Backend", "Sharing backend %s not found" : "გაზიარების ბექენდი %s ვერ იქნა ნაპოვნი", "Sharing backend for %s not found" : "გაზიარების ბექენდი %s-თვის ვერ იქნა ნაპოვნი", - "Click the button below to open it." : "გასახსნელად დააჭირეთ ქვემოთ მყოფ ღილაკს.", "Unknown share type" : "ამოუცნობი გაზიარების სახეობა", "You are not allowed to share %s" : "თქვენ არ გაქვთ უფლება გააზიაროთ %s", "Cannot increase permissions of %s" : "%s-ის უფლებების გაზრდა ვერ ხერხდება", @@ -147,30 +145,10 @@ OC.L10N.register( "Storage connection error. %s" : "საცავის კავშირის შეცდომა. %s", "Storage is temporarily not available" : "საცავი დროებით ხელმიუწვდომელია", "Storage connection timeout. %s" : "საცავის კავშირის დროის ამოწურვა. %s", + "Text" : "ტექსტი", "Summary" : "შეჯამება", "Translate" : "გადათარგმნეთ", "Result" : "შედეგი", - "Education Edition" : "საგანმანათლებლო გამოცემა", - "Logged in user must be an admin" : "ავტორიზირებული მომხმარებელი უნდა იყოს ადმინისტრატორი", - "File name is a reserved word" : "ფაილის სახელი რეზერვირებული სიტყვაა", - "File name contains at least one invalid character" : "ფაილის სახელი მოიცავს დაუშვებელ სიმბოლოს", - "File name is too long" : "ფაილის სახელი ზედმეტად გრძელია", - "Help" : "დახმარება", - "Users" : "მომხმარებლები", - "Unknown user" : "ამოუცნობი მომხმარებელი", - "Oracle username and/or password not valid" : "Oracle მომხმარებლის სახელი და/ან პაროლი არ არის სწორი", - "PostgreSQL username and/or password not valid" : "PostgreSQL მომხმარებლის სახელი და/ან პაროლი არ არის სწორი", - "Set an admin username." : "დააყენეთ ადმინისტრატორის სახელი.", - "Open »%s«" : "გახნსნა »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "%s-ის გაზიარება არ მოხერხდა, რადგან ობიექტი მომხმარებელ %s-თან უკვე გაზიარებულია", - "The username is already being used" : "ესეთი მომხმარებლის სახელი უკვე არსებობს", - "Could not create user" : "მომხმარებლის შექმნა ვერ მოხერხდა", - "A valid username must be provided" : "უნდა მიუთითოთ არსებული მომხმარებლის სახელი", - "Username contains whitespace at the beginning or at the end" : "მომხმარებლის სახელი დასაწყისსში ან დასასრულში მოიცავს სიცარიელეს", - "Username must not consist of dots only" : "მომხმარებლის სახელი ვერ იქნება შემდგარი მხოლოდ წერტილებისგან", - "User disabled" : "მომხმარებელი გათიშულია", - "File is currently busy, please try again later" : "ფაილი ამჟამად დაკავებულია, გთხოვთ მოგვიანებით სცადოთ ახლიდან", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "გთხოვთ შეცვალოთ უფლებები 0770-ზე, რათა დირექტორია სხვა მომხმარებლების მიერ აღარ იყოს კითხვადი.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "დარწმუნდით რომ ფაილი სახელად \".ocdata\" მონაცემების დირექტორიის საწყისშია." + "File is currently busy, please try again later" : "ფაილი ამჟამად დაკავებულია, გთხოვთ მოგვიანებით სცადოთ ახლიდან" }, "nplurals=2; plural=(n!=1);"); diff --git a/lib/l10n/ka_GE.json b/lib/l10n/ka_GE.json index b34f8ee944b..f4ef8658ab4 100644 --- a/lib/l10n/ka_GE.json +++ b/lib/l10n/ka_GE.json @@ -64,7 +64,6 @@ "Additional settings" : "დამატებითი პარამეტრები", "You need to enter details of an existing account." : "საჭიროა შეიყვანოთ არსებული ანგარიშის დეტალები.", "Oracle connection could not be established" : "Oracle კავშირი ვერ დამყარდა", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X არაა მხარდაჭერილი და %s ამ პლატფორმაზე სწორად არ იმუშავებს. გამოიყენეთ საკუთარი რისკით!", "For the best results, please consider using a GNU/Linux server instead." : "საუკეთესო შედეგებისთვის სანაცვლოდ გამოიყენეთ GNU/Linux სერვერი.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "როგორც ჩანს ეს %s ინსტანცია მოქმედებს 32-ბიტიან PHP გარემოზე და open_basedir php.ini-ში კონფიგურირებულია. ეს 4 გბ-ზე დიდ ფაილებთან გამოიწვევს პრობლემს და რეკომედირებული არაა.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "გთხოვთ ამოშალოთ open_basedir პარამეტრი php.ini-დან ან გადახვიდეთ 64-ბიტიან PHP-ზე.", @@ -72,7 +71,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "გაზიარების ბექენდმა %s-მ მოქმედებაში უნდა მოიყვანოს ინტეფეისი OCP\\Share_Backend", "Sharing backend %s not found" : "გაზიარების ბექენდი %s ვერ იქნა ნაპოვნი", "Sharing backend for %s not found" : "გაზიარების ბექენდი %s-თვის ვერ იქნა ნაპოვნი", - "Click the button below to open it." : "გასახსნელად დააჭირეთ ქვემოთ მყოფ ღილაკს.", "Unknown share type" : "ამოუცნობი გაზიარების სახეობა", "You are not allowed to share %s" : "თქვენ არ გაქვთ უფლება გააზიაროთ %s", "Cannot increase permissions of %s" : "%s-ის უფლებების გაზრდა ვერ ხერხდება", @@ -145,30 +143,10 @@ "Storage connection error. %s" : "საცავის კავშირის შეცდომა. %s", "Storage is temporarily not available" : "საცავი დროებით ხელმიუწვდომელია", "Storage connection timeout. %s" : "საცავის კავშირის დროის ამოწურვა. %s", + "Text" : "ტექსტი", "Summary" : "შეჯამება", "Translate" : "გადათარგმნეთ", "Result" : "შედეგი", - "Education Edition" : "საგანმანათლებლო გამოცემა", - "Logged in user must be an admin" : "ავტორიზირებული მომხმარებელი უნდა იყოს ადმინისტრატორი", - "File name is a reserved word" : "ფაილის სახელი რეზერვირებული სიტყვაა", - "File name contains at least one invalid character" : "ფაილის სახელი მოიცავს დაუშვებელ სიმბოლოს", - "File name is too long" : "ფაილის სახელი ზედმეტად გრძელია", - "Help" : "დახმარება", - "Users" : "მომხმარებლები", - "Unknown user" : "ამოუცნობი მომხმარებელი", - "Oracle username and/or password not valid" : "Oracle მომხმარებლის სახელი და/ან პაროლი არ არის სწორი", - "PostgreSQL username and/or password not valid" : "PostgreSQL მომხმარებლის სახელი და/ან პაროლი არ არის სწორი", - "Set an admin username." : "დააყენეთ ადმინისტრატორის სახელი.", - "Open »%s«" : "გახნსნა »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "%s-ის გაზიარება არ მოხერხდა, რადგან ობიექტი მომხმარებელ %s-თან უკვე გაზიარებულია", - "The username is already being used" : "ესეთი მომხმარებლის სახელი უკვე არსებობს", - "Could not create user" : "მომხმარებლის შექმნა ვერ მოხერხდა", - "A valid username must be provided" : "უნდა მიუთითოთ არსებული მომხმარებლის სახელი", - "Username contains whitespace at the beginning or at the end" : "მომხმარებლის სახელი დასაწყისსში ან დასასრულში მოიცავს სიცარიელეს", - "Username must not consist of dots only" : "მომხმარებლის სახელი ვერ იქნება შემდგარი მხოლოდ წერტილებისგან", - "User disabled" : "მომხმარებელი გათიშულია", - "File is currently busy, please try again later" : "ფაილი ამჟამად დაკავებულია, გთხოვთ მოგვიანებით სცადოთ ახლიდან", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "გთხოვთ შეცვალოთ უფლებები 0770-ზე, რათა დირექტორია სხვა მომხმარებლების მიერ აღარ იყოს კითხვადი.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "დარწმუნდით რომ ფაილი სახელად \".ocdata\" მონაცემების დირექტორიის საწყისშია." + "File is currently busy, please try again later" : "ფაილი ამჟამად დაკავებულია, გთხოვთ მოგვიანებით სცადოთ ახლიდან" },"pluralForm" :"nplurals=2; plural=(n!=1);" }
\ No newline at end of file diff --git a/lib/l10n/kab.js b/lib/l10n/kab.js index 3f910bbf965..3d3822ecfef 100644 --- a/lib/l10n/kab.js +++ b/lib/l10n/kab.js @@ -12,8 +12,6 @@ OC.L10N.register( "Website" : "Asmel web", "Address" : "Adresse", "About" : "Γef", - "Translate" : "Suqel", - "Help" : "Tallalt", - "Users" : "Iseqdacen" + "Translate" : "Suqel" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/kab.json b/lib/l10n/kab.json index d121f39e512..f9b7184e1c4 100644 --- a/lib/l10n/kab.json +++ b/lib/l10n/kab.json @@ -10,8 +10,6 @@ "Website" : "Asmel web", "Address" : "Adresse", "About" : "Γef", - "Translate" : "Suqel", - "Help" : "Tallalt", - "Users" : "Iseqdacen" + "Translate" : "Suqel" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/km.js b/lib/l10n/km.js index 11aa3537f19..5f499f816bd 100644 --- a/lib/l10n/km.js +++ b/lib/l10n/km.js @@ -63,12 +63,6 @@ OC.L10N.register( "Dec." : "ធ្នូ", "A valid password must be provided" : "ត្រូវផ្ដល់ពាក្យសម្ងាត់ឲ្យបានត្រឹមត្រូវ", "Application is not enabled" : "មិនបានបើកកម្មវិធី", - "Authentication error" : "កំហុសការផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ", - "Help" : "ជំនួយ", - "Users" : "អ្នកប្រើ", - "Unknown user" : "មិនស្គាល់អ្នកប្រើប្រាស់", - "PostgreSQL username and/or password not valid" : "ឈ្មោះអ្នកប្រើ និង/ឬ ពាក្យសម្ងាត់ PostgreSQL គឺមិនត្រូវទេ", - "Set an admin username." : "កំណត់ឈ្មោះអ្នកគ្រប់គ្រង។", - "A valid username must be provided" : "ត្រូវផ្ដល់ឈ្មោះអ្នកប្រើឲ្យបានត្រឹមត្រូវ" + "Authentication error" : "កំហុសការផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/km.json b/lib/l10n/km.json index 4b85eb8ad64..209a4ab7f5f 100644 --- a/lib/l10n/km.json +++ b/lib/l10n/km.json @@ -61,12 +61,6 @@ "Dec." : "ធ្នូ", "A valid password must be provided" : "ត្រូវផ្ដល់ពាក្យសម្ងាត់ឲ្យបានត្រឹមត្រូវ", "Application is not enabled" : "មិនបានបើកកម្មវិធី", - "Authentication error" : "កំហុសការផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ", - "Help" : "ជំនួយ", - "Users" : "អ្នកប្រើ", - "Unknown user" : "មិនស្គាល់អ្នកប្រើប្រាស់", - "PostgreSQL username and/or password not valid" : "ឈ្មោះអ្នកប្រើ និង/ឬ ពាក្យសម្ងាត់ PostgreSQL គឺមិនត្រូវទេ", - "Set an admin username." : "កំណត់ឈ្មោះអ្នកគ្រប់គ្រង។", - "A valid username must be provided" : "ត្រូវផ្ដល់ឈ្មោះអ្នកប្រើឲ្យបានត្រឹមត្រូវ" + "Authentication error" : "កំហុសការផ្ទៀងផ្ទាត់ភាពត្រឹមត្រូវ" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/kn.js b/lib/l10n/kn.js index 490ea65483e..30b6ed8db54 100644 --- a/lib/l10n/kn.js +++ b/lib/l10n/kn.js @@ -30,9 +30,6 @@ OC.L10N.register( "November" : "ನವೆಂಬರ್", "December" : "ಡಿಸೆಂಬರ್", "A valid password must be provided" : "ಸರಿಯಾದ ಬಳಕೆದಾರ ಗುಪ್ತಪದ ಒದಗಿಸಬೇಕಾಗಿದೆ", - "Authentication error" : "ದೃಢೀಕರಣ ದೋಷ", - "Help" : "ಸಹಾಯ", - "Users" : "ಬಳಕೆದಾರರು", - "A valid username must be provided" : "ಮಾನ್ಯ ಬಳಕೆದಾರ ಹೆಸರು ಒದಗಿಸಬೇಕಾಗುತ್ತದೆ" + "Authentication error" : "ದೃಢೀಕರಣ ದೋಷ" }, "nplurals=2; plural=(n > 1);"); diff --git a/lib/l10n/kn.json b/lib/l10n/kn.json index e7ac74ebf4f..590b685ac63 100644 --- a/lib/l10n/kn.json +++ b/lib/l10n/kn.json @@ -28,9 +28,6 @@ "November" : "ನವೆಂಬರ್", "December" : "ಡಿಸೆಂಬರ್", "A valid password must be provided" : "ಸರಿಯಾದ ಬಳಕೆದಾರ ಗುಪ್ತಪದ ಒದಗಿಸಬೇಕಾಗಿದೆ", - "Authentication error" : "ದೃಢೀಕರಣ ದೋಷ", - "Help" : "ಸಹಾಯ", - "Users" : "ಬಳಕೆದಾರರು", - "A valid username must be provided" : "ಮಾನ್ಯ ಬಳಕೆದಾರ ಹೆಸರು ಒದಗಿಸಬೇಕಾಗುತ್ತದೆ" + "Authentication error" : "ದೃಢೀಕರಣ ದೋಷ" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/lib/l10n/ko.js b/lib/l10n/ko.js index 3f8ceb8646b..f083f57b908 100644 --- a/lib/l10n/ko.js +++ b/lib/l10n/ko.js @@ -110,7 +110,7 @@ OC.L10N.register( "About" : "정보", "Display name" : "표시 이름", "Headline" : "표제", - "Organisation" : "조직", + "Organization" : "개인 정보 관리", "Role" : "직책", "Unknown account" : "알 수 없는 계정", "Additional settings" : "고급 설정", @@ -118,7 +118,6 @@ OC.L10N.register( "You cannot use dots in the database name %s" : "데이터베이스 이름에 점(.)을 사용할 수 없습니다 %s", "You need to enter details of an existing account." : "존재하는 계정 정보를 입력해야 합니다.", "Oracle connection could not be established" : "Oracle 연결을 수립할 수 없습니다.", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X은 지원하지 않으며 %s이(가) 이 플랫폼에서 올바르게 작동하지 않을 수도 있습니다. 본인 책임으로 사용하십시오! ", "For the best results, please consider using a GNU/Linux server instead." : "더 좋은 결과를 얻으려면 GNU/Linux 서버를 사용하는 것을 권장합니다.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "%s 인스턴스가 32비트 PHP 환경에서 실행 중이고 php.ini에 open_basedir이 설정되어 있습니다. 4GB 이상의 파일 처리에 문제가 생길 수 있으므로 추천하지 않습니다.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "php.ini의 open_basedir 설정을 삭제하거나 64비트 PHP로 전환하십시오.", @@ -127,7 +126,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "공유 백엔드 %s에서 OCP\\Share_Backend 인터페이스를 구현해야 함", "Sharing backend %s not found" : "공유 백엔드 %s을(를) 찾을 수 없음", "Sharing backend for %s not found" : "%s의 공유 백엔드를 찾을 수 없음", - "Click the button below to open it." : "아래 단추를 눌러서 열 수 있습니다.", "%1$s via %2$s" : "%1$s(%2$s 경유)", "Unknown share type" : "알 수 없는 공유 형식", "You are not allowed to share %s" : "%s을(를) 공유할 수 있는 권한이 없습니다", @@ -142,6 +140,7 @@ OC.L10N.register( "The requested share comes from a disabled user" : "요청한 공유가 비활성화된 사용자로부터 수신되었습니다", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "사용자 수 제한에 도달하여 사용자를 만들 수 없습니다. 더 자세한 정보는 알림을 참조하십시오.", "Could not find category \"%s\"" : "분류 \"%s\"을(를) 찾을 수 없습니다", + "Input text" : "텍스트를 입력", "Sunday" : "일요일", "Monday" : "월요일", "Tuesday" : "화요일", @@ -236,14 +235,21 @@ OC.L10N.register( "Storage connection timeout. %s" : "저장소 연결 시간이 초과되었습니다. %s", "Audio input" : "음성 입력", "Confirmation" : "확인", + "Generated response" : "생성된 응답", "Context write" : "컨텍스트 쓰기", "Writes text in a given style based on the provided source material." : "제공된 소스 자료를 기반으로 특정 스타일로 텍스트를 작성합니다.", "Writing style" : "작문 스타일", "Source material" : "소스 자료", "Generate image" : "이미지 생성", "Prompt" : "프롬프트", + "Change Tone" : "톤을 변경", + "Write a text that you want the assistant to rewrite in another tone." : "어시스턴트에 다른 톤으로 다시 쓰고 싶은 텍스트를 쓰기", + "Desired tone" : "희망하는 톤", + "In which tone should your text be rewritten?" : "텍스트를 어떤 어조로 다시 씁니까?", + "The rewritten text in the desired tone, written by the assistant:" : "원하는 톤으로 어시스턴트에 의해서 다시 쓴 텍스트:", "Chat" : "대화", "Generates a possible headline for a text." : "내용에 대한 헤드라인을 생성하십시오.", + "Text" : "텍스트", "Summarize" : "요약", "Summary" : "요약", "Extract topics" : "주제 추출", @@ -252,41 +258,8 @@ OC.L10N.register( "Generate headline" : "헤드라인 생성", "Summarizes text by reducing its length without losing key information." : "중요 정보로 내용을 축약하십시오.", "Extracts topics from a text and outputs them separated by commas." : "내용에서 주요 주제를 추출하고 쉼표로 이를 구분하십시오.", - "Education Edition" : "교육용 에디션", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "로그인된 사용자가 관리자, 부 관리자, 또는 이 설정에 접근할 수 있는 권한을 부여받은 사용자일 것입니다.", - "Logged in user must be an admin or sub admin" : "로그인한 사용자는 관리자 또는 부 관리자여야 합니다.", - "Logged in user must be an admin" : "로그인한 사용자는 관리자여야 합니다.", - "File name is a reserved word" : "파일 이름이 예약된 단어임", - "File name contains at least one invalid character" : "파일 이름에 잘못된 글자가 한 자 이상 있음", - "File name is too long" : "파일 이름이 너무 김", - "Help" : "도움말", - "Users" : "사용자", - "Unknown user" : "알려지지 않은 사용자", - "Enter the database username and name for %s" : "%s에 대한 데이터베이스 사용자 이름과 이름을 입력하십시오", - "Enter the database username for %s" : "%s에 대한 데이터베이스 사용자 이름을 입력하십시오", - "MySQL username and/or password not valid" : "MySQL 사용자 이름 또는 암호가 잘못되었습니다", - "Oracle username and/or password not valid" : "Oracle 사용자 이름이나 암호가 잘못되었습니다.", - "PostgreSQL username and/or password not valid" : "PostgreSQL 사용자 이름 또는 암호가 잘못되었습니다", - "Set an admin username." : "관리자의 사용자 이름을 설정합니다.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s님이 %2$s을(를) 당신과 공유하며, 다음을 추가하고자 함:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s님이 %2$s을(를) 당신과 공유하며 다음을 추가하고자 함", - "»%s« added a note to a file shared with you" : "%s님이 당신과 공유한 파일에 메모를 추가함", - "Open »%s«" : "%s 열기", - "Sharing %s failed, because this item is already shared with user %s" : "%s을(를) 공유할 수 없습니다. 이 항목을 이미 %s 님과 공유하고 있습니다", - "%1$s shared »%2$s« with you" : "%1$s 님이 »%2$s« 항목을 공유했습니다", - "%1$s shared »%2$s« with you." : "%1$s 님이 »%2$s« 항목을 공유했습니다", - "The username is already being used" : "사용자 이름이 이미 존재합니다", - "Could not create user" : "사용자를 만들 수 없습니다", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "사용자 이름에는 다음 문자만 사용할 수 있습니다: \"a-z, \"A-Z\", \"0-9\", 공백, \"_.@-'\"", - "A valid username must be provided" : "올바른 사용자 이름을 입력해야 합니다", - "Username contains whitespace at the beginning or at the end" : "사용자 이름의 시작이나 끝에 공백이 있습니다", - "Username must not consist of dots only" : "사용자 이름에 마침표만 있으면 안 됩니다", - "Username is invalid because files already exist for this user" : "무효한 사용자이름. 이미 존재함", - "User disabled" : "사용자 비활성화됨", + "Organisation" : "조직", "File is currently busy, please try again later" : "파일이 현재 사용 중, 나중에 다시 시도하십시오", - "Cannot download file" : "파일을 다운로드할 수 없음", - "Your data directory is readable by other users." : "현재 데이터 디렉토리를 다른 사람이 읽을 수 있습니다.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "권한을 0770으로 변경하여 다른 사용자가 읽을 수 없도록 하십시오.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "데이터 디렉터리의 최상위 디렉터리에 \".ocdata\" 파일이 있는지 확인하십시오." + "Cannot download file" : "파일을 다운로드할 수 없음" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/ko.json b/lib/l10n/ko.json index e4f7398a120..981836aa2ce 100644 --- a/lib/l10n/ko.json +++ b/lib/l10n/ko.json @@ -108,7 +108,7 @@ "About" : "정보", "Display name" : "표시 이름", "Headline" : "표제", - "Organisation" : "조직", + "Organization" : "개인 정보 관리", "Role" : "직책", "Unknown account" : "알 수 없는 계정", "Additional settings" : "고급 설정", @@ -116,7 +116,6 @@ "You cannot use dots in the database name %s" : "데이터베이스 이름에 점(.)을 사용할 수 없습니다 %s", "You need to enter details of an existing account." : "존재하는 계정 정보를 입력해야 합니다.", "Oracle connection could not be established" : "Oracle 연결을 수립할 수 없습니다.", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X은 지원하지 않으며 %s이(가) 이 플랫폼에서 올바르게 작동하지 않을 수도 있습니다. 본인 책임으로 사용하십시오! ", "For the best results, please consider using a GNU/Linux server instead." : "더 좋은 결과를 얻으려면 GNU/Linux 서버를 사용하는 것을 권장합니다.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "%s 인스턴스가 32비트 PHP 환경에서 실행 중이고 php.ini에 open_basedir이 설정되어 있습니다. 4GB 이상의 파일 처리에 문제가 생길 수 있으므로 추천하지 않습니다.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "php.ini의 open_basedir 설정을 삭제하거나 64비트 PHP로 전환하십시오.", @@ -125,7 +124,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "공유 백엔드 %s에서 OCP\\Share_Backend 인터페이스를 구현해야 함", "Sharing backend %s not found" : "공유 백엔드 %s을(를) 찾을 수 없음", "Sharing backend for %s not found" : "%s의 공유 백엔드를 찾을 수 없음", - "Click the button below to open it." : "아래 단추를 눌러서 열 수 있습니다.", "%1$s via %2$s" : "%1$s(%2$s 경유)", "Unknown share type" : "알 수 없는 공유 형식", "You are not allowed to share %s" : "%s을(를) 공유할 수 있는 권한이 없습니다", @@ -140,6 +138,7 @@ "The requested share comes from a disabled user" : "요청한 공유가 비활성화된 사용자로부터 수신되었습니다", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "사용자 수 제한에 도달하여 사용자를 만들 수 없습니다. 더 자세한 정보는 알림을 참조하십시오.", "Could not find category \"%s\"" : "분류 \"%s\"을(를) 찾을 수 없습니다", + "Input text" : "텍스트를 입력", "Sunday" : "일요일", "Monday" : "월요일", "Tuesday" : "화요일", @@ -234,14 +233,21 @@ "Storage connection timeout. %s" : "저장소 연결 시간이 초과되었습니다. %s", "Audio input" : "음성 입력", "Confirmation" : "확인", + "Generated response" : "생성된 응답", "Context write" : "컨텍스트 쓰기", "Writes text in a given style based on the provided source material." : "제공된 소스 자료를 기반으로 특정 스타일로 텍스트를 작성합니다.", "Writing style" : "작문 스타일", "Source material" : "소스 자료", "Generate image" : "이미지 생성", "Prompt" : "프롬프트", + "Change Tone" : "톤을 변경", + "Write a text that you want the assistant to rewrite in another tone." : "어시스턴트에 다른 톤으로 다시 쓰고 싶은 텍스트를 쓰기", + "Desired tone" : "희망하는 톤", + "In which tone should your text be rewritten?" : "텍스트를 어떤 어조로 다시 씁니까?", + "The rewritten text in the desired tone, written by the assistant:" : "원하는 톤으로 어시스턴트에 의해서 다시 쓴 텍스트:", "Chat" : "대화", "Generates a possible headline for a text." : "내용에 대한 헤드라인을 생성하십시오.", + "Text" : "텍스트", "Summarize" : "요약", "Summary" : "요약", "Extract topics" : "주제 추출", @@ -250,41 +256,8 @@ "Generate headline" : "헤드라인 생성", "Summarizes text by reducing its length without losing key information." : "중요 정보로 내용을 축약하십시오.", "Extracts topics from a text and outputs them separated by commas." : "내용에서 주요 주제를 추출하고 쉼표로 이를 구분하십시오.", - "Education Edition" : "교육용 에디션", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "로그인된 사용자가 관리자, 부 관리자, 또는 이 설정에 접근할 수 있는 권한을 부여받은 사용자일 것입니다.", - "Logged in user must be an admin or sub admin" : "로그인한 사용자는 관리자 또는 부 관리자여야 합니다.", - "Logged in user must be an admin" : "로그인한 사용자는 관리자여야 합니다.", - "File name is a reserved word" : "파일 이름이 예약된 단어임", - "File name contains at least one invalid character" : "파일 이름에 잘못된 글자가 한 자 이상 있음", - "File name is too long" : "파일 이름이 너무 김", - "Help" : "도움말", - "Users" : "사용자", - "Unknown user" : "알려지지 않은 사용자", - "Enter the database username and name for %s" : "%s에 대한 데이터베이스 사용자 이름과 이름을 입력하십시오", - "Enter the database username for %s" : "%s에 대한 데이터베이스 사용자 이름을 입력하십시오", - "MySQL username and/or password not valid" : "MySQL 사용자 이름 또는 암호가 잘못되었습니다", - "Oracle username and/or password not valid" : "Oracle 사용자 이름이나 암호가 잘못되었습니다.", - "PostgreSQL username and/or password not valid" : "PostgreSQL 사용자 이름 또는 암호가 잘못되었습니다", - "Set an admin username." : "관리자의 사용자 이름을 설정합니다.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s님이 %2$s을(를) 당신과 공유하며, 다음을 추가하고자 함:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s님이 %2$s을(를) 당신과 공유하며 다음을 추가하고자 함", - "»%s« added a note to a file shared with you" : "%s님이 당신과 공유한 파일에 메모를 추가함", - "Open »%s«" : "%s 열기", - "Sharing %s failed, because this item is already shared with user %s" : "%s을(를) 공유할 수 없습니다. 이 항목을 이미 %s 님과 공유하고 있습니다", - "%1$s shared »%2$s« with you" : "%1$s 님이 »%2$s« 항목을 공유했습니다", - "%1$s shared »%2$s« with you." : "%1$s 님이 »%2$s« 항목을 공유했습니다", - "The username is already being used" : "사용자 이름이 이미 존재합니다", - "Could not create user" : "사용자를 만들 수 없습니다", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "사용자 이름에는 다음 문자만 사용할 수 있습니다: \"a-z, \"A-Z\", \"0-9\", 공백, \"_.@-'\"", - "A valid username must be provided" : "올바른 사용자 이름을 입력해야 합니다", - "Username contains whitespace at the beginning or at the end" : "사용자 이름의 시작이나 끝에 공백이 있습니다", - "Username must not consist of dots only" : "사용자 이름에 마침표만 있으면 안 됩니다", - "Username is invalid because files already exist for this user" : "무효한 사용자이름. 이미 존재함", - "User disabled" : "사용자 비활성화됨", + "Organisation" : "조직", "File is currently busy, please try again later" : "파일이 현재 사용 중, 나중에 다시 시도하십시오", - "Cannot download file" : "파일을 다운로드할 수 없음", - "Your data directory is readable by other users." : "현재 데이터 디렉토리를 다른 사람이 읽을 수 있습니다.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "권한을 0770으로 변경하여 다른 사용자가 읽을 수 없도록 하십시오.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "데이터 디렉터리의 최상위 디렉터리에 \".ocdata\" 파일이 있는지 확인하십시오." + "Cannot download file" : "파일을 다운로드할 수 없음" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/lb.js b/lib/l10n/lb.js index a107b551717..95e013a5895 100644 --- a/lib/l10n/lb.js +++ b/lib/l10n/lb.js @@ -67,8 +67,6 @@ OC.L10N.register( "Dec." : "Dez.", "Authentication error" : "Authentifikatioun's Fehler", "Storage is temporarily not available" : "Späicherplaatz temporär net erreeschbar", - "Translate" : "Iwwersetzen", - "Help" : "Hëllef", - "Users" : "Benotzer" + "Translate" : "Iwwersetzen" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/lb.json b/lib/l10n/lb.json index 144a73b024b..6670b881769 100644 --- a/lib/l10n/lb.json +++ b/lib/l10n/lb.json @@ -65,8 +65,6 @@ "Dec." : "Dez.", "Authentication error" : "Authentifikatioun's Fehler", "Storage is temporarily not available" : "Späicherplaatz temporär net erreeschbar", - "Translate" : "Iwwersetzen", - "Help" : "Hëllef", - "Users" : "Benotzer" + "Translate" : "Iwwersetzen" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/lo.js b/lib/l10n/lo.js index 150cf4f4a57..cdb86b0dd40 100644 --- a/lib/l10n/lo.js +++ b/lib/l10n/lo.js @@ -17,9 +17,6 @@ OC.L10N.register( "Address" : "ທີ່ຢູ່", "About" : "ກ່ຽວກັບ", "Role" : "ພາລະບົດບາດ", - "Translate" : "ແປ", - "Help" : "ການຊ່ວຍເຫຼືອ", - "Users" : "ຜູ້ໃຊ້", - "User disabled" : "ປິດຊື່ຜູ້ໃຊ້" + "Translate" : "ແປ" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/lo.json b/lib/l10n/lo.json index c67941ae01a..443e99a5ed1 100644 --- a/lib/l10n/lo.json +++ b/lib/l10n/lo.json @@ -15,9 +15,6 @@ "Address" : "ທີ່ຢູ່", "About" : "ກ່ຽວກັບ", "Role" : "ພາລະບົດບາດ", - "Translate" : "ແປ", - "Help" : "ການຊ່ວຍເຫຼືອ", - "Users" : "ຜູ້ໃຊ້", - "User disabled" : "ປິດຊື່ຜູ້ໃຊ້" + "Translate" : "ແປ" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/lt_LT.js b/lib/l10n/lt_LT.js index 77e3948d382..a92e6d9a240 100644 --- a/lib/l10n/lt_LT.js +++ b/lib/l10n/lt_LT.js @@ -36,6 +36,7 @@ OC.L10N.register( "Avatar image is not square" : "Avataro paveikslas nėra kvadratinis", "Files" : "Failai", "View profile" : "Rodyti profilį", + "Local time: %s" : "Vietinis laikas: %s", "today" : "šiandien", "tomorrow" : "rytoj", "yesterday" : "vakar", @@ -56,15 +57,19 @@ OC.L10N.register( "seconds ago" : "prieš keletą sekundžių", "Empty file" : "Tuščias failas", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulio, kurio ID: %s, nėra. Prašome jį įjungti savo programėlių nustatymuose arba susisiekti su savo administratoriumi.", + "\"%1$s\" is a forbidden file or folder name." : "„%1$s“ yra draudžiamas failo ar aplanko pavadinimas.", + "\"%1$s\" is a forbidden file type." : "„%1$s“ yra draudžiamas failo tipas.", "File already exists" : "Failas jau yra", "Invalid path" : "Neteisingas kelias", "Templates" : "Šablonai", "Filename contains at least one invalid character" : "Failo pavadinime yra bent vienas neteisingas simbolis", + "Filename is too long" : "Failo pavadinimas per ilgas", "Empty filename is not allowed" : "Tuščias failo pavadinimas nėra leidžiamas", "App \"%s\" cannot be installed because appinfo file cannot be read." : "Programėlė „%s“ negali būti įdiegta, nes nepavyksta perskaityti appinfo failo.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Programėlė „%s“ negali būti įdiegta, nes ji nėra suderinama su šia serverio versija.", "__language_name__" : "Lietuvių", "This is an automatically sent email, please do not reply." : "Tai yra automatinis pranešimas, prašome neatsakyti.", + "Help & privacy" : "Pagalba ir privatumas", "Appearance and accessibility" : "Išvaizda ir prieinamumas", "Apps" : "Programėlės", "Personal settings" : "Asmeniniai nustatymai", @@ -83,21 +88,27 @@ OC.L10N.register( "Profile picture" : "Profilio paveikslėlis", "About" : "Apie", "Headline" : "Antraštė", - "Organisation" : "Organizacija", + "Organization" : "Organizavimas", "Role" : "Vaidmuo", + "Unknown account" : "Nežinoma paskyra", "Additional settings" : "Papildomi nustatymai", "You need to enter details of an existing account." : "Jūs turite suvesti egzistuojančios paskyros duomenis.", "Oracle connection could not be established" : "Nepavyko užmegzti Oracle ryšio", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nėra palaikomas, %s neveiks tinkamai šioje platformoje. Naudodami prisiimate visą riziką !", "For the best results, please consider using a GNU/Linux server instead." : "Geriausiems rezultatams, apsvarstykite galimybę, vietoj šio, naudoti GNU/Linux serverį", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Pašalinkite savo php.ini faile open_basedir nustatymą arba persijunkite į 64-bitų PHP.", "Set an admin password." : "Nustatyti administratoriaus slaptažodį.", - "Click the button below to open it." : "Norėdami atverti failą, spustelėkite mygtuką žemiau.", + "Open %s" : "Atverti %s", "%1$s via %2$s" : "%1$s per %2$s", + "Share recipient is not a valid user" : "Viešinio gavėjas nėra tinkamas naudotojas", + "Share recipient is not a valid group" : "Viešinio gavėjas nėra tinkama grupė", "Unknown share type" : "Nežinomas viešinio tipas", "You are not allowed to share %s" : "Jums neleidžiama bendrinti %s", "Cannot increase permissions of %s" : "Negalima pridėti papildomų %s leidimų", "Expiration date is in the past" : "Bendrinimo pabaigos data yra praėjęs laikas", + "Path is already shared with this group" : "Kelias jau yra bendrinamas su šia grupe", + "Sharing is disabled" : "Bendrinimas yra išjungtas", + "Share does not have a full ID" : "Viešinys neturi viso ID", + "Group \"%s\" does not exist" : "Grupės „%s“ nėra", "The requested share does not exist anymore" : "Pageidaujamas bendrinimas daugiau neegzistuoja.", "Could not find category \"%s\"" : "Nepavyko rasti kategorijos „%s“", "Sunday" : "Sekmadienis", @@ -146,6 +157,8 @@ OC.L10N.register( "Nov." : "Lap.", "Dec." : "Grd.", "A valid password must be provided" : "Slaptažodis turi būti tinkamas", + "Could not create account" : "Nepavyko sukurti paskyros", + "Account disabled" : "Paskyra išjungta", "Login canceled by app" : "Programėlė nutraukė prisijungimo procesą", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Programėlė \"%1$s\" negali būti įdiegta, nes nėra patenkinamos šios priklausomybės: %2$s", "a safe home for all your data" : "saugūs namai visiems jūsų duomenims", @@ -167,34 +180,11 @@ OC.L10N.register( "Storage connection error. %s" : "Saugyklos sujungimo ryšio klaida. %s", "Storage is temporarily not available" : "Saugykla yra laikinai neprieinama", "Storage connection timeout. %s" : "Sujungimo su saugykla laikas baigėsi. %s", + "Text" : "Tekstas", "Summary" : "Santrauka", "Translate" : "Verskite", - "Logged in user must be an admin" : "Prisijungęs naudotojas privalo būti administratoriumi", - "File name is a reserved word" : "Failo pavadinimas negalimas, žodis rezervuotas", - "File name contains at least one invalid character" : "Failo vardas sudarytas iš neleistinų simbolių", - "File name is too long" : "Failo pavadinimas per ilgas", - "Help" : "Pagalba", - "Users" : "Naudotojai", - "Unknown user" : "Nežinomas naudotojas", - "MySQL username and/or password not valid" : "Neteisingas MySQL naudotojo vardas ir/arba slaptažodis", - "Oracle username and/or password not valid" : "Neteisingas Oracle naudotojo vardas ir/arba slaptažodis", - "PostgreSQL username and/or password not valid" : "Neteisingas PostgreSQL naudotojo vardas ir/arba slaptažodis", - "Set an admin username." : "Nustatyti administratoriaus naudotojo vardą.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s pasidalino „%2$s“ su jumis ir parašė pastabą:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s pasidalino „%2$s“ su jumis ir parašė pastabą", - "»%s« added a note to a file shared with you" : "„%s“ parašė pastabą su jumis pasidalintam failui", - "Open »%s«" : "Atverti \"%s\"", - "Sharing %s failed, because this item is already shared with user %s" : "%s bendrinimas nepavyko, kadangi šis elementas jau yra bendrinamas su naudotoju %s", - "%1$s shared »%2$s« with you" : "%1$s pasidalino „%2$s“ su jumis", - "%1$s shared »%2$s« with you." : "%1$s pasidalino „%2$s“ su jumis.", - "The username is already being used" : "Naudotojo vardas jau yra naudojamas", - "Could not create user" : "Nepavyko sukurti naudotojo", - "A valid username must be provided" : "Privalo būti pateiktas tinkamas naudotojo vardas", - "Username contains whitespace at the beginning or at the end" : "Naudotojo varde pradžioje ar pabaigoje yra tarpas", - "Username must not consist of dots only" : "Naudotojo vardas negali būti sudarytas tik iš taškų.", - "User disabled" : "Naudotojas išjungtas", + "Organisation" : "Organizacija", "File is currently busy, please try again later" : "Failas šiuo metu yra užimtas, prašome vėliau pabandyti dar kartą", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Pakeiskite leidimus į 0770, kad šis katalogas negalėtų būti išvardytas kitiems naudotojams.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Įsitikinkite, kad šakniniame duomenų kataloge yra failas, pavadinimu „.ocdata“." + "Cannot download file" : "Nepavyksta atsisiųsti failo" }, "nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"); diff --git a/lib/l10n/lt_LT.json b/lib/l10n/lt_LT.json index 5dfba2d637f..14fd7c57f04 100644 --- a/lib/l10n/lt_LT.json +++ b/lib/l10n/lt_LT.json @@ -34,6 +34,7 @@ "Avatar image is not square" : "Avataro paveikslas nėra kvadratinis", "Files" : "Failai", "View profile" : "Rodyti profilį", + "Local time: %s" : "Vietinis laikas: %s", "today" : "šiandien", "tomorrow" : "rytoj", "yesterday" : "vakar", @@ -54,15 +55,19 @@ "seconds ago" : "prieš keletą sekundžių", "Empty file" : "Tuščias failas", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulio, kurio ID: %s, nėra. Prašome jį įjungti savo programėlių nustatymuose arba susisiekti su savo administratoriumi.", + "\"%1$s\" is a forbidden file or folder name." : "„%1$s“ yra draudžiamas failo ar aplanko pavadinimas.", + "\"%1$s\" is a forbidden file type." : "„%1$s“ yra draudžiamas failo tipas.", "File already exists" : "Failas jau yra", "Invalid path" : "Neteisingas kelias", "Templates" : "Šablonai", "Filename contains at least one invalid character" : "Failo pavadinime yra bent vienas neteisingas simbolis", + "Filename is too long" : "Failo pavadinimas per ilgas", "Empty filename is not allowed" : "Tuščias failo pavadinimas nėra leidžiamas", "App \"%s\" cannot be installed because appinfo file cannot be read." : "Programėlė „%s“ negali būti įdiegta, nes nepavyksta perskaityti appinfo failo.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Programėlė „%s“ negali būti įdiegta, nes ji nėra suderinama su šia serverio versija.", "__language_name__" : "Lietuvių", "This is an automatically sent email, please do not reply." : "Tai yra automatinis pranešimas, prašome neatsakyti.", + "Help & privacy" : "Pagalba ir privatumas", "Appearance and accessibility" : "Išvaizda ir prieinamumas", "Apps" : "Programėlės", "Personal settings" : "Asmeniniai nustatymai", @@ -81,21 +86,27 @@ "Profile picture" : "Profilio paveikslėlis", "About" : "Apie", "Headline" : "Antraštė", - "Organisation" : "Organizacija", + "Organization" : "Organizavimas", "Role" : "Vaidmuo", + "Unknown account" : "Nežinoma paskyra", "Additional settings" : "Papildomi nustatymai", "You need to enter details of an existing account." : "Jūs turite suvesti egzistuojančios paskyros duomenis.", "Oracle connection could not be established" : "Nepavyko užmegzti Oracle ryšio", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nėra palaikomas, %s neveiks tinkamai šioje platformoje. Naudodami prisiimate visą riziką !", "For the best results, please consider using a GNU/Linux server instead." : "Geriausiems rezultatams, apsvarstykite galimybę, vietoj šio, naudoti GNU/Linux serverį", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Pašalinkite savo php.ini faile open_basedir nustatymą arba persijunkite į 64-bitų PHP.", "Set an admin password." : "Nustatyti administratoriaus slaptažodį.", - "Click the button below to open it." : "Norėdami atverti failą, spustelėkite mygtuką žemiau.", + "Open %s" : "Atverti %s", "%1$s via %2$s" : "%1$s per %2$s", + "Share recipient is not a valid user" : "Viešinio gavėjas nėra tinkamas naudotojas", + "Share recipient is not a valid group" : "Viešinio gavėjas nėra tinkama grupė", "Unknown share type" : "Nežinomas viešinio tipas", "You are not allowed to share %s" : "Jums neleidžiama bendrinti %s", "Cannot increase permissions of %s" : "Negalima pridėti papildomų %s leidimų", "Expiration date is in the past" : "Bendrinimo pabaigos data yra praėjęs laikas", + "Path is already shared with this group" : "Kelias jau yra bendrinamas su šia grupe", + "Sharing is disabled" : "Bendrinimas yra išjungtas", + "Share does not have a full ID" : "Viešinys neturi viso ID", + "Group \"%s\" does not exist" : "Grupės „%s“ nėra", "The requested share does not exist anymore" : "Pageidaujamas bendrinimas daugiau neegzistuoja.", "Could not find category \"%s\"" : "Nepavyko rasti kategorijos „%s“", "Sunday" : "Sekmadienis", @@ -144,6 +155,8 @@ "Nov." : "Lap.", "Dec." : "Grd.", "A valid password must be provided" : "Slaptažodis turi būti tinkamas", + "Could not create account" : "Nepavyko sukurti paskyros", + "Account disabled" : "Paskyra išjungta", "Login canceled by app" : "Programėlė nutraukė prisijungimo procesą", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Programėlė \"%1$s\" negali būti įdiegta, nes nėra patenkinamos šios priklausomybės: %2$s", "a safe home for all your data" : "saugūs namai visiems jūsų duomenims", @@ -165,34 +178,11 @@ "Storage connection error. %s" : "Saugyklos sujungimo ryšio klaida. %s", "Storage is temporarily not available" : "Saugykla yra laikinai neprieinama", "Storage connection timeout. %s" : "Sujungimo su saugykla laikas baigėsi. %s", + "Text" : "Tekstas", "Summary" : "Santrauka", "Translate" : "Verskite", - "Logged in user must be an admin" : "Prisijungęs naudotojas privalo būti administratoriumi", - "File name is a reserved word" : "Failo pavadinimas negalimas, žodis rezervuotas", - "File name contains at least one invalid character" : "Failo vardas sudarytas iš neleistinų simbolių", - "File name is too long" : "Failo pavadinimas per ilgas", - "Help" : "Pagalba", - "Users" : "Naudotojai", - "Unknown user" : "Nežinomas naudotojas", - "MySQL username and/or password not valid" : "Neteisingas MySQL naudotojo vardas ir/arba slaptažodis", - "Oracle username and/or password not valid" : "Neteisingas Oracle naudotojo vardas ir/arba slaptažodis", - "PostgreSQL username and/or password not valid" : "Neteisingas PostgreSQL naudotojo vardas ir/arba slaptažodis", - "Set an admin username." : "Nustatyti administratoriaus naudotojo vardą.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s pasidalino „%2$s“ su jumis ir parašė pastabą:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s pasidalino „%2$s“ su jumis ir parašė pastabą", - "»%s« added a note to a file shared with you" : "„%s“ parašė pastabą su jumis pasidalintam failui", - "Open »%s«" : "Atverti \"%s\"", - "Sharing %s failed, because this item is already shared with user %s" : "%s bendrinimas nepavyko, kadangi šis elementas jau yra bendrinamas su naudotoju %s", - "%1$s shared »%2$s« with you" : "%1$s pasidalino „%2$s“ su jumis", - "%1$s shared »%2$s« with you." : "%1$s pasidalino „%2$s“ su jumis.", - "The username is already being used" : "Naudotojo vardas jau yra naudojamas", - "Could not create user" : "Nepavyko sukurti naudotojo", - "A valid username must be provided" : "Privalo būti pateiktas tinkamas naudotojo vardas", - "Username contains whitespace at the beginning or at the end" : "Naudotojo varde pradžioje ar pabaigoje yra tarpas", - "Username must not consist of dots only" : "Naudotojo vardas negali būti sudarytas tik iš taškų.", - "User disabled" : "Naudotojas išjungtas", + "Organisation" : "Organizacija", "File is currently busy, please try again later" : "Failas šiuo metu yra užimtas, prašome vėliau pabandyti dar kartą", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Pakeiskite leidimus į 0770, kad šis katalogas negalėtų būti išvardytas kitiems naudotojams.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Įsitikinkite, kad šakniniame duomenų kataloge yra failas, pavadinimu „.ocdata“." + "Cannot download file" : "Nepavyksta atsisiųsti failo" },"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);" }
\ No newline at end of file diff --git a/lib/l10n/lv.js b/lib/l10n/lv.js index fdd42baa07a..d70b713b15f 100644 --- a/lib/l10n/lv.js +++ b/lib/l10n/lv.js @@ -5,11 +5,12 @@ OC.L10N.register( "See %s" : "Skatīt %s", "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Lietotne %1$s nav pieejama vai tai ir ar šo serveri nesaderīga versija. Lūgums pārbaudīt lietotņu mapi.", "Sample configuration detected" : "Atrasta konfigurācijas paraugs", - "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Konstatēts, ka paraug konfigurācija ir nokopēta. Tas var izjaukt jūsu instalāciju un nav atbalstīts. Lūdzu, izlasiet dokumentāciju, pirms veicat izmaiņas config.php", + "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Tika noteikts, ka tika kopēta paraugkonfigurācija. Tas var salauzt uzstādīto un netiek atbalstīts. Lūgums pirms izmaiņu veikšanas config.php izlasīt dokumentāciju", "%s email verification" : "%s e-pasta pārbaude", "Email verification" : "E-pasta pārbaude", - "Click the following button to confirm your email." : "Noklikšķiniet uz šīs pogas, lai apstiprinātu savu e-pastu.", - "Confirm your email" : "Apstipriniet savu e-pastu", + "Click the following button to confirm your email." : "Jāklikšķina zemā esošā poga, lai apstiprinātu savu e-pasta adresi.", + "Click the following link to confirm your email." : "Jāklikšķina uz zemāk esošās saites, lai apstiprinātu savu e-pasta adresi.", + "Confirm your email" : "Apstiprināt savu e-pasta adresi", "%1$s and %2$s" : "%1$s un %2$s", "%1$s, %2$s and %3$s" : "%1$s, %2$s un %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s un %4$s", @@ -19,28 +20,34 @@ OC.L10N.register( "%sbit or higher PHP required." : "Nepieciešams %sbit vai jaunāks PHP.", "The command line tool %s could not be found" : "Komandrindas rīku %s nevarēja atrast", "The library %s is not available." : "Bibliotēka %s nav pieejama.", - "Server version %s or higher is required." : "Ir vajadzīga servera versija %s vai jaunāka.", - "Server version %s or lower is required." : "Ir vajadzīga servera versija %s vai vecāka.", + "The following platforms are supported: %s" : "Tiek atbalstītas šīs platformas: %s", + "Server version %s or higher is required." : "Ir nepieciešama servera versija %s vai jaunāka.", + "Server version %s or lower is required." : "Ir nepieciešama servera versija %s vai vecāka.", "Authentication" : "Autentifikācija", "Unknown filetype" : "Nezināms datnes veids", "Invalid image" : "Nederīgs attēls", - "Avatar image is not square" : "Avatar attēls nav kvadrāts", + "Avatar image is not square" : "Profila attēls nav kvadrāts", "Files" : "Datnes", "View profile" : "Skatīt profilu", "today" : "šodien", "yesterday" : "vakar", - "_%n day ago_::_%n days ago_" : ["%n dienas atpakaļ","%n dienas atpakaļ","%n dienām"], + "_%n day ago_::_%n days ago_" : ["pirms %n dienām","pirms %n dienas","pirms %n dienām"], "last month" : "pagājušajā mēnesī", - "_%n month ago_::_%n months ago_" : ["%n mēneši atpakaļ","%n mēneši atpakaļ","%n mēnešiem"], + "_%n month ago_::_%n months ago_" : ["pirms %n mēnešiem","pirms %n mēneša","pirms %n mēnešiem"], "last year" : "gājušajā gadā", - "_%n year ago_::_%n years ago_" : ["%n gadiem","%n gadiem","%n gadiem"], - "_%n hour ago_::_%n hours ago_" : ["%n stundas atpakaļ","%n stundas atpakaļ","%n stundām"], - "_%n minute ago_::_%n minutes ago_" : ["%n minūtes atpakaļ","%n minūtes atpakaļ","%n minūtēm"], - "seconds ago" : "sekundēm", + "_%n year ago_::_%n years ago_" : ["pirms %n gadiem","pirms %n gada","pirms %n gadiem"], + "_%n hour ago_::_%n hours ago_" : ["pirms %n stundām","pirms %n stundas","pirms %n stundām"], + "_%n minute ago_::_%n minutes ago_" : ["pirms %n minūtēm","pirms %n minūtes","pirms %n minūtēm"], + "seconds ago" : "pirms vairākām sekundēm", + "Empty file" : "Tukša datne", + "%1$s (renamed)" : "%1$s (pārdēvēta)", + "renamed file" : "pārdēvēja datni", "File already exists" : "Datne jau pastāv", "Filename contains at least one invalid character" : "Datnes nosaukums satur vismaz vienu nederīgu rakstzīmi", "Empty filename is not allowed" : "Tukšs datnes nosaukums nav atļauts", + "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Lietotni \"%s\" nevar uzstādīt, jo tā nav saderīga ar šo servera versiju.", "__language_name__" : "Latviešu", + "This is an automatically sent email, please do not reply." : "Šis ir automātiski nosūtīts e-pasta ziņojums, lūgums neatbildēt.", "Help & privacy" : "Palīdzība un privātums", "Appearance and accessibility" : "Izskats un piekļūstamība", "Apps" : "Lietotnes", @@ -61,8 +68,9 @@ OC.L10N.register( "Additional settings" : "Papildu iestatījumi", "Oracle connection could not be established" : "Nevar izveidot savienojumu ar Oracle", "Set an admin password." : "Iestatīt pārvaldītāja paroli.", + "Open %s" : "Atvērt %s", "Unknown share type" : "Nezināms kopīgošanas veids", - "You are not allowed to share %s" : "Tev nav ļauts dalīties ar %s", + "You are not allowed to share %s" : "Tev nav ļauts kopīgot %s", "Could not find category \"%s\"" : "Nevarēja atrast kategoriju “%s”", "Sunday" : "Svētdiena", "Monday" : "Pirmdiena", @@ -110,12 +118,12 @@ OC.L10N.register( "Nov." : "Nov.", "Dec." : "Dec.", "A valid password must be provided" : "Jānorāda derīga parole", - "Login canceled by app" : "Pieteikšanos atcelā lietotne", + "Login canceled by app" : "Lietotne atcēla pieteikšanos", "a safe home for all your data" : "droša vieta visiem Taviem datiem", "Application is not enabled" : "Lietotne nav iespējota", - "Authentication error" : "Autentifikācijas kļūda", + "Authentication error" : "Autentificēšanās kļūda", "Token expired. Please reload page." : "Pilnvarai ir beidzies derīgums. Lūgums pārlādēt lapu.", - "PHP module %s not installed." : "PHP modulis %s nav instalēts.", + "PHP module %s not installed." : "Nav uzstādīts PHP modulis %s.", "Please ask your server administrator to install the module." : "Lūgums vaicāt savam servera pārvaldītāja, lai uzstāda moduli.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Tas ir iespējams, kešatmiņa / paātrinātājs, piemēram, Zend OPcache vai eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "PHP modulis ir uzstādīts, taču tas joprojām ir uzskatāms kā trūkstošs, pazudis?", @@ -123,22 +131,11 @@ OC.L10N.register( "Storage unauthorized. %s" : "Krātuve neautorizēta. %s", "Storage incomplete configuration. %s" : "Storage incomplete configuration. %s", "Storage connection error. %s" : "Datu savienojuma kļūda. %s", - "Storage is temporarily not available" : "Glabātuve īslaicīgi nav pieejama", + "Storage is temporarily not available" : "Krātuve īslaicīgi nav pieejama", "Storage connection timeout. %s" : "Datu savienojuma taimauts. %s", + "Text" : "Teksts", "Summary" : "Kopsavilkums", "Translate" : "Tulkot", - "File name is a reserved word" : "Datnes nosaukums ir aizņemts vārds", - "File name is too long" : "Datnes nosaukums ir pārāk garš", - "Help" : "Palīdzība", - "Users" : "Lietotāji", - "Unknown user" : "Nezināms lietotājs", - "Oracle username and/or password not valid" : "Nav derīga Oracle parole un/vai lietotājvārds", - "PostgreSQL username and/or password not valid" : "Nav derīga PostgreSQL parole un/vai lietotājvārds", - "Set an admin username." : "Iestatīt pārvaldītāja lietotājvārdu.", - "Open »%s«" : "Atvērt »%s«", - "The username is already being used" : "Šāds lietotājvārds jau tiek izmantots", - "A valid username must be provided" : "Jānorāda derīgs lietotājvārds", - "User disabled" : "Lietotājs deaktivizēts", - "File is currently busy, please try again later" : "Datne pašlaik ir aizņemta. Lūdzu, vēlāk mēģiniet vēlreiz" + "File is currently busy, please try again later" : "Datne pašlaik ir aizņemta. Lūgums vēlāk mēģināt vēlreiz" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"); diff --git a/lib/l10n/lv.json b/lib/l10n/lv.json index a6d0585af13..985ca12e30a 100644 --- a/lib/l10n/lv.json +++ b/lib/l10n/lv.json @@ -3,11 +3,12 @@ "See %s" : "Skatīt %s", "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Lietotne %1$s nav pieejama vai tai ir ar šo serveri nesaderīga versija. Lūgums pārbaudīt lietotņu mapi.", "Sample configuration detected" : "Atrasta konfigurācijas paraugs", - "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Konstatēts, ka paraug konfigurācija ir nokopēta. Tas var izjaukt jūsu instalāciju un nav atbalstīts. Lūdzu, izlasiet dokumentāciju, pirms veicat izmaiņas config.php", + "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Tika noteikts, ka tika kopēta paraugkonfigurācija. Tas var salauzt uzstādīto un netiek atbalstīts. Lūgums pirms izmaiņu veikšanas config.php izlasīt dokumentāciju", "%s email verification" : "%s e-pasta pārbaude", "Email verification" : "E-pasta pārbaude", - "Click the following button to confirm your email." : "Noklikšķiniet uz šīs pogas, lai apstiprinātu savu e-pastu.", - "Confirm your email" : "Apstipriniet savu e-pastu", + "Click the following button to confirm your email." : "Jāklikšķina zemā esošā poga, lai apstiprinātu savu e-pasta adresi.", + "Click the following link to confirm your email." : "Jāklikšķina uz zemāk esošās saites, lai apstiprinātu savu e-pasta adresi.", + "Confirm your email" : "Apstiprināt savu e-pasta adresi", "%1$s and %2$s" : "%1$s un %2$s", "%1$s, %2$s and %3$s" : "%1$s, %2$s un %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s un %4$s", @@ -17,28 +18,34 @@ "%sbit or higher PHP required." : "Nepieciešams %sbit vai jaunāks PHP.", "The command line tool %s could not be found" : "Komandrindas rīku %s nevarēja atrast", "The library %s is not available." : "Bibliotēka %s nav pieejama.", - "Server version %s or higher is required." : "Ir vajadzīga servera versija %s vai jaunāka.", - "Server version %s or lower is required." : "Ir vajadzīga servera versija %s vai vecāka.", + "The following platforms are supported: %s" : "Tiek atbalstītas šīs platformas: %s", + "Server version %s or higher is required." : "Ir nepieciešama servera versija %s vai jaunāka.", + "Server version %s or lower is required." : "Ir nepieciešama servera versija %s vai vecāka.", "Authentication" : "Autentifikācija", "Unknown filetype" : "Nezināms datnes veids", "Invalid image" : "Nederīgs attēls", - "Avatar image is not square" : "Avatar attēls nav kvadrāts", + "Avatar image is not square" : "Profila attēls nav kvadrāts", "Files" : "Datnes", "View profile" : "Skatīt profilu", "today" : "šodien", "yesterday" : "vakar", - "_%n day ago_::_%n days ago_" : ["%n dienas atpakaļ","%n dienas atpakaļ","%n dienām"], + "_%n day ago_::_%n days ago_" : ["pirms %n dienām","pirms %n dienas","pirms %n dienām"], "last month" : "pagājušajā mēnesī", - "_%n month ago_::_%n months ago_" : ["%n mēneši atpakaļ","%n mēneši atpakaļ","%n mēnešiem"], + "_%n month ago_::_%n months ago_" : ["pirms %n mēnešiem","pirms %n mēneša","pirms %n mēnešiem"], "last year" : "gājušajā gadā", - "_%n year ago_::_%n years ago_" : ["%n gadiem","%n gadiem","%n gadiem"], - "_%n hour ago_::_%n hours ago_" : ["%n stundas atpakaļ","%n stundas atpakaļ","%n stundām"], - "_%n minute ago_::_%n minutes ago_" : ["%n minūtes atpakaļ","%n minūtes atpakaļ","%n minūtēm"], - "seconds ago" : "sekundēm", + "_%n year ago_::_%n years ago_" : ["pirms %n gadiem","pirms %n gada","pirms %n gadiem"], + "_%n hour ago_::_%n hours ago_" : ["pirms %n stundām","pirms %n stundas","pirms %n stundām"], + "_%n minute ago_::_%n minutes ago_" : ["pirms %n minūtēm","pirms %n minūtes","pirms %n minūtēm"], + "seconds ago" : "pirms vairākām sekundēm", + "Empty file" : "Tukša datne", + "%1$s (renamed)" : "%1$s (pārdēvēta)", + "renamed file" : "pārdēvēja datni", "File already exists" : "Datne jau pastāv", "Filename contains at least one invalid character" : "Datnes nosaukums satur vismaz vienu nederīgu rakstzīmi", "Empty filename is not allowed" : "Tukšs datnes nosaukums nav atļauts", + "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "Lietotni \"%s\" nevar uzstādīt, jo tā nav saderīga ar šo servera versiju.", "__language_name__" : "Latviešu", + "This is an automatically sent email, please do not reply." : "Šis ir automātiski nosūtīts e-pasta ziņojums, lūgums neatbildēt.", "Help & privacy" : "Palīdzība un privātums", "Appearance and accessibility" : "Izskats un piekļūstamība", "Apps" : "Lietotnes", @@ -59,8 +66,9 @@ "Additional settings" : "Papildu iestatījumi", "Oracle connection could not be established" : "Nevar izveidot savienojumu ar Oracle", "Set an admin password." : "Iestatīt pārvaldītāja paroli.", + "Open %s" : "Atvērt %s", "Unknown share type" : "Nezināms kopīgošanas veids", - "You are not allowed to share %s" : "Tev nav ļauts dalīties ar %s", + "You are not allowed to share %s" : "Tev nav ļauts kopīgot %s", "Could not find category \"%s\"" : "Nevarēja atrast kategoriju “%s”", "Sunday" : "Svētdiena", "Monday" : "Pirmdiena", @@ -108,12 +116,12 @@ "Nov." : "Nov.", "Dec." : "Dec.", "A valid password must be provided" : "Jānorāda derīga parole", - "Login canceled by app" : "Pieteikšanos atcelā lietotne", + "Login canceled by app" : "Lietotne atcēla pieteikšanos", "a safe home for all your data" : "droša vieta visiem Taviem datiem", "Application is not enabled" : "Lietotne nav iespējota", - "Authentication error" : "Autentifikācijas kļūda", + "Authentication error" : "Autentificēšanās kļūda", "Token expired. Please reload page." : "Pilnvarai ir beidzies derīgums. Lūgums pārlādēt lapu.", - "PHP module %s not installed." : "PHP modulis %s nav instalēts.", + "PHP module %s not installed." : "Nav uzstādīts PHP modulis %s.", "Please ask your server administrator to install the module." : "Lūgums vaicāt savam servera pārvaldītāja, lai uzstāda moduli.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Tas ir iespējams, kešatmiņa / paātrinātājs, piemēram, Zend OPcache vai eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "PHP modulis ir uzstādīts, taču tas joprojām ir uzskatāms kā trūkstošs, pazudis?", @@ -121,22 +129,11 @@ "Storage unauthorized. %s" : "Krātuve neautorizēta. %s", "Storage incomplete configuration. %s" : "Storage incomplete configuration. %s", "Storage connection error. %s" : "Datu savienojuma kļūda. %s", - "Storage is temporarily not available" : "Glabātuve īslaicīgi nav pieejama", + "Storage is temporarily not available" : "Krātuve īslaicīgi nav pieejama", "Storage connection timeout. %s" : "Datu savienojuma taimauts. %s", + "Text" : "Teksts", "Summary" : "Kopsavilkums", "Translate" : "Tulkot", - "File name is a reserved word" : "Datnes nosaukums ir aizņemts vārds", - "File name is too long" : "Datnes nosaukums ir pārāk garš", - "Help" : "Palīdzība", - "Users" : "Lietotāji", - "Unknown user" : "Nezināms lietotājs", - "Oracle username and/or password not valid" : "Nav derīga Oracle parole un/vai lietotājvārds", - "PostgreSQL username and/or password not valid" : "Nav derīga PostgreSQL parole un/vai lietotājvārds", - "Set an admin username." : "Iestatīt pārvaldītāja lietotājvārdu.", - "Open »%s«" : "Atvērt »%s«", - "The username is already being used" : "Šāds lietotājvārds jau tiek izmantots", - "A valid username must be provided" : "Jānorāda derīgs lietotājvārds", - "User disabled" : "Lietotājs deaktivizēts", - "File is currently busy, please try again later" : "Datne pašlaik ir aizņemta. Lūdzu, vēlāk mēģiniet vēlreiz" + "File is currently busy, please try again later" : "Datne pašlaik ir aizņemta. Lūgums vēlāk mēģināt vēlreiz" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" }
\ No newline at end of file diff --git a/lib/l10n/mk.js b/lib/l10n/mk.js index 31662ffbfb9..24487bf9aa6 100644 --- a/lib/l10n/mk.js +++ b/lib/l10n/mk.js @@ -52,6 +52,8 @@ OC.L10N.register( "Avatar image is not square" : "Сликата за Аватар не е квадратна", "Files" : "Датотеки", "View profile" : "Прегледај профил", + "_%nh_::_%nh_" : ["%nч","%nч"], + "_%nm_::_%nm_" : ["%nм","%nм"], "Local time: %s" : "Локално време: %s", "today" : "денес", "tomorrow" : "утре", @@ -107,14 +109,12 @@ OC.L10N.register( "About" : "За", "Display name" : "Име и презиме", "Headline" : "Наслов", - "Organisation" : "Организација", "Role" : "Улога", "Additional settings" : "Дополнителни параметри", "Enter the database name for %s" : "Внесете го името на базата за %s", "You cannot use dots in the database name %s" : "Не можеш да користиш точки во името на базата %s", "You need to enter details of an existing account." : "Потребно е да внесете детали од постоечката сметка.", "Oracle connection could not be established" : "Oracle врската неможе да се воспостави", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не е поддржана и %s нема да работи соодветно на оваа платформа. Користењето е на ваш ризик! ", "For the best results, please consider using a GNU/Linux server instead." : "За најдобри резултати, размислете за користење на сервер со GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Највероватно оваа истанца %s е стартувана на 32-битна PHP средина и open_basedir е конфигурано во php.ini. Ова ќе прави проблеми со датотеки поголеми од 4 GB.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Отстранете го параметарот open_basedir од php.ini или преминете на 64-битна PHP средина.", @@ -123,7 +123,8 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "За позадинското споделување %s мора се имплементира интерфејсот OCP\\Share_Backend", "Sharing backend %s not found" : "Не е пронајдено позадинско споделување %s", "Sharing backend for %s not found" : "Не е пронајдено позадинско споделување за %s.", - "Click the button below to open it." : "Кликнете на копчето подолу за да ја отворите.", + "%1$s shared %2$s with you" : "%1$s сподели %2$s со вас", + "Open %s" : "Отвори %s", "%1$s via %2$s" : "%1$s преку %2$s", "Unknown share type" : "Непознат вид на споделување", "You are not allowed to share %s" : "Не сте овластени да ја споделите %s", @@ -226,44 +227,12 @@ OC.L10N.register( "Storage connection error. %s" : "Грешка во конекција до складиштето. %s", "Storage is temporarily not available" : "Складиштето моментално не е достапно", "Storage connection timeout. %s" : "Поврзувањето со складиштето не успеа. %s", + "Text" : "Текст", "Summary" : "Резиме", "Translate" : "Преведи", "Generate headline" : "Генерирај заглавие", - "Education Edition" : "Едукативно издание", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Најавените корисници мора да бидат администратори, ко-администратори или да имаат специјални дозволи за да пристапат до овие поставки", - "Logged in user must be an admin or sub admin" : "Најавениот корисник мора да биде администратор или заменик администратор", - "Logged in user must be an admin" : "Најавениот корисник мора да биде администратор", - "File name is a reserved word" : "Името на датотеката е резервиран збор", - "File name contains at least one invalid character" : "Името на датотеката соджи невалиден карактер", - "File name is too long" : "Името на датотеката е премногу долго", - "Help" : "Помош", - "Users" : "Корисници", - "Unknown user" : "Непознат корисник", - "Enter the database username and name for %s" : "Внесете го корисничкото име и името на базата за %s", - "Enter the database username for %s" : "Внесете го корисничкото име на базата за %s", - "MySQL username and/or password not valid" : "Погрешно MySQL корисничко име и/или лозинка", - "Oracle username and/or password not valid" : "Oracle корисничкото име и/или лозинката не се валидни", - "PostgreSQL username and/or password not valid" : "PostgreSQL корисничкото име и/или лозинка не се валидни", - "Set an admin username." : "Постави администраторско корисничко име", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s ја сподели папката »%2$s« и додаде:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s ја сподели папката »%2$s« и додаде", - "»%s« added a note to a file shared with you" : "»%s« додаде белешка до датотеката што ја сподели со вас", - "Open »%s«" : "Отвори »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Споделувањето на %s е неуспешно, бидејќи истото веќе е споделено со корисникот %s", - "%1$s shared »%2$s« with you" : "%1$s сподели »%2$s« со вас", - "%1$s shared »%2$s« with you." : "%1$s сподели »%2$s« со вас.", - "The username is already being used" : "Корисничкото име е веќе во употреба", - "Could not create user" : "Неможе да се креира корисник", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Само следниве карактери се дозволени во корисничкото име: \"a-z\", \"A-Z\", \"0-9\", празно место и \"_.@-'\"", - "A valid username must be provided" : "Мора да се внесе валидно корисничко име ", - "Username contains whitespace at the beginning or at the end" : "Корисничкото име содржи празно место на почетокот или на крајот", - "Username must not consist of dots only" : "Корисничкото име не смее да се состои само од точки", - "Username is invalid because files already exist for this user" : "Невалидно корисничкото име бидејќи веќе постојат датотеки за овој корисник", - "User disabled" : "Оневозможен корисник", + "Organisation" : "Организација", "File is currently busy, please try again later" : "Датотеката моментално е зафатена, обидете се повторно", - "Cannot download file" : "Не може да се преземе датотеката", - "Your data directory is readable by other users." : "Вашата папка со податоци може да се чита и од други корисници.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Поставете дозвола на папката 0770, за да неможе да се чита од други корисници.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Осигурете се дека има датотека наречена \".ocdata\" во главната папка со податоци." + "Cannot download file" : "Не може да се преземе датотеката" }, "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"); diff --git a/lib/l10n/mk.json b/lib/l10n/mk.json index f88a3e1f35b..465323a1513 100644 --- a/lib/l10n/mk.json +++ b/lib/l10n/mk.json @@ -50,6 +50,8 @@ "Avatar image is not square" : "Сликата за Аватар не е квадратна", "Files" : "Датотеки", "View profile" : "Прегледај профил", + "_%nh_::_%nh_" : ["%nч","%nч"], + "_%nm_::_%nm_" : ["%nм","%nм"], "Local time: %s" : "Локално време: %s", "today" : "денес", "tomorrow" : "утре", @@ -105,14 +107,12 @@ "About" : "За", "Display name" : "Име и презиме", "Headline" : "Наслов", - "Organisation" : "Организација", "Role" : "Улога", "Additional settings" : "Дополнителни параметри", "Enter the database name for %s" : "Внесете го името на базата за %s", "You cannot use dots in the database name %s" : "Не можеш да користиш точки во името на базата %s", "You need to enter details of an existing account." : "Потребно е да внесете детали од постоечката сметка.", "Oracle connection could not be established" : "Oracle врската неможе да се воспостави", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не е поддржана и %s нема да работи соодветно на оваа платформа. Користењето е на ваш ризик! ", "For the best results, please consider using a GNU/Linux server instead." : "За најдобри резултати, размислете за користење на сервер со GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Највероватно оваа истанца %s е стартувана на 32-битна PHP средина и open_basedir е конфигурано во php.ini. Ова ќе прави проблеми со датотеки поголеми од 4 GB.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Отстранете го параметарот open_basedir од php.ini или преминете на 64-битна PHP средина.", @@ -121,7 +121,8 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "За позадинското споделување %s мора се имплементира интерфејсот OCP\\Share_Backend", "Sharing backend %s not found" : "Не е пронајдено позадинско споделување %s", "Sharing backend for %s not found" : "Не е пронајдено позадинско споделување за %s.", - "Click the button below to open it." : "Кликнете на копчето подолу за да ја отворите.", + "%1$s shared %2$s with you" : "%1$s сподели %2$s со вас", + "Open %s" : "Отвори %s", "%1$s via %2$s" : "%1$s преку %2$s", "Unknown share type" : "Непознат вид на споделување", "You are not allowed to share %s" : "Не сте овластени да ја споделите %s", @@ -224,44 +225,12 @@ "Storage connection error. %s" : "Грешка во конекција до складиштето. %s", "Storage is temporarily not available" : "Складиштето моментално не е достапно", "Storage connection timeout. %s" : "Поврзувањето со складиштето не успеа. %s", + "Text" : "Текст", "Summary" : "Резиме", "Translate" : "Преведи", "Generate headline" : "Генерирај заглавие", - "Education Edition" : "Едукативно издание", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Најавените корисници мора да бидат администратори, ко-администратори или да имаат специјални дозволи за да пристапат до овие поставки", - "Logged in user must be an admin or sub admin" : "Најавениот корисник мора да биде администратор или заменик администратор", - "Logged in user must be an admin" : "Најавениот корисник мора да биде администратор", - "File name is a reserved word" : "Името на датотеката е резервиран збор", - "File name contains at least one invalid character" : "Името на датотеката соджи невалиден карактер", - "File name is too long" : "Името на датотеката е премногу долго", - "Help" : "Помош", - "Users" : "Корисници", - "Unknown user" : "Непознат корисник", - "Enter the database username and name for %s" : "Внесете го корисничкото име и името на базата за %s", - "Enter the database username for %s" : "Внесете го корисничкото име на базата за %s", - "MySQL username and/or password not valid" : "Погрешно MySQL корисничко име и/или лозинка", - "Oracle username and/or password not valid" : "Oracle корисничкото име и/или лозинката не се валидни", - "PostgreSQL username and/or password not valid" : "PostgreSQL корисничкото име и/или лозинка не се валидни", - "Set an admin username." : "Постави администраторско корисничко име", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s ја сподели папката »%2$s« и додаде:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s ја сподели папката »%2$s« и додаде", - "»%s« added a note to a file shared with you" : "»%s« додаде белешка до датотеката што ја сподели со вас", - "Open »%s«" : "Отвори »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Споделувањето на %s е неуспешно, бидејќи истото веќе е споделено со корисникот %s", - "%1$s shared »%2$s« with you" : "%1$s сподели »%2$s« со вас", - "%1$s shared »%2$s« with you." : "%1$s сподели »%2$s« со вас.", - "The username is already being used" : "Корисничкото име е веќе во употреба", - "Could not create user" : "Неможе да се креира корисник", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Само следниве карактери се дозволени во корисничкото име: \"a-z\", \"A-Z\", \"0-9\", празно место и \"_.@-'\"", - "A valid username must be provided" : "Мора да се внесе валидно корисничко име ", - "Username contains whitespace at the beginning or at the end" : "Корисничкото име содржи празно место на почетокот или на крајот", - "Username must not consist of dots only" : "Корисничкото име не смее да се состои само од точки", - "Username is invalid because files already exist for this user" : "Невалидно корисничкото име бидејќи веќе постојат датотеки за овој корисник", - "User disabled" : "Оневозможен корисник", + "Organisation" : "Организација", "File is currently busy, please try again later" : "Датотеката моментално е зафатена, обидете се повторно", - "Cannot download file" : "Не може да се преземе датотеката", - "Your data directory is readable by other users." : "Вашата папка со податоци може да се чита и од други корисници.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Поставете дозвола на папката 0770, за да неможе да се чита од други корисници.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Осигурете се дека има датотека наречена \".ocdata\" во главната папка со податоци." + "Cannot download file" : "Не може да се преземе датотеката" },"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;" }
\ No newline at end of file diff --git a/lib/l10n/mn.js b/lib/l10n/mn.js index 0cace9e812b..29ae48cf228 100644 --- a/lib/l10n/mn.js +++ b/lib/l10n/mn.js @@ -36,13 +36,6 @@ OC.L10N.register( "Authentication error" : "Нотолгооны алдаа", "Storage is temporarily not available" : "Хадгалах төхөөрөмж нь түр хугацаанд ашиглах боломжгүй байна", "Summary" : "Хураангуй", - "Translate" : "Орчуулга", - "File name is a reserved word" : "Файлын нэр нь нийцгүй үг", - "File name contains at least one invalid character" : "файлын нэр нь хамгийн багадаа нэг нь хүчингүй тэмдэгт агуулж байна", - "File name is too long" : "Файлын нэр хэтэрхий урт байна", - "Help" : "Туслах", - "Users" : "хэрэглэгч", - "Unknown user" : "Тодорхойгүй хэрэглэгч", - "Open »%s«" : "»%s« нээх" + "Translate" : "Орчуулга" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/mn.json b/lib/l10n/mn.json index 807881c57d9..e47604ac8e8 100644 --- a/lib/l10n/mn.json +++ b/lib/l10n/mn.json @@ -34,13 +34,6 @@ "Authentication error" : "Нотолгооны алдаа", "Storage is temporarily not available" : "Хадгалах төхөөрөмж нь түр хугацаанд ашиглах боломжгүй байна", "Summary" : "Хураангуй", - "Translate" : "Орчуулга", - "File name is a reserved word" : "Файлын нэр нь нийцгүй үг", - "File name contains at least one invalid character" : "файлын нэр нь хамгийн багадаа нэг нь хүчингүй тэмдэгт агуулж байна", - "File name is too long" : "Файлын нэр хэтэрхий урт байна", - "Help" : "Туслах", - "Users" : "хэрэглэгч", - "Unknown user" : "Тодорхойгүй хэрэглэгч", - "Open »%s«" : "»%s« нээх" + "Translate" : "Орчуулга" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/ms_MY.js b/lib/l10n/ms_MY.js index bec5f0dfe3f..a62db456f42 100644 --- a/lib/l10n/ms_MY.js +++ b/lib/l10n/ms_MY.js @@ -49,8 +49,6 @@ OC.L10N.register( "Oct." : "Okt.", "Nov." : "Nov.", "Dec." : "Dis.", - "Authentication error" : "Ralat pengesahan", - "Help" : "Bantuan", - "Users" : "Pengguna" + "Authentication error" : "Ralat pengesahan" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/ms_MY.json b/lib/l10n/ms_MY.json index 2bc8cbe8f97..cb2e2f402ce 100644 --- a/lib/l10n/ms_MY.json +++ b/lib/l10n/ms_MY.json @@ -47,8 +47,6 @@ "Oct." : "Okt.", "Nov." : "Nov.", "Dec." : "Dis.", - "Authentication error" : "Ralat pengesahan", - "Help" : "Bantuan", - "Users" : "Pengguna" + "Authentication error" : "Ralat pengesahan" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/nb.js b/lib/l10n/nb.js index 0230a8d1177..da8613ccafb 100644 --- a/lib/l10n/nb.js +++ b/lib/l10n/nb.js @@ -38,7 +38,6 @@ OC.L10N.register( "Server version %s or higher is required." : "Serverversjon %s eller høyere kreves.", "Server version %s or lower is required." : "Serverversjon %s eller lavere kreves.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Innlogget konto må være administrator, underadministrator eller ha fått spesiell rett til å få tilgang til denne innstillingen.", - "Your current IP address doesn’t allow you to perform admin actions" : "Den nåværende IP-adressen din lar deg ikke utføre administratorhandlinger", "Logged in account must be an admin or sub admin" : "Innlogget konto må være administrator eller en underadministrator.", "Logged in account must be an admin" : "Innlogget konto må være administrator", "Wiping of device %s has started" : "Sikker sletting av enhet %s er startet", @@ -59,6 +58,7 @@ OC.L10N.register( "Avatar image is not square" : "Avatarbilde er ikke firkantet", "Files" : "Filer", "View profile" : "Vis profil", + "_%nh_::_%nh_" : ["%nh","%nh"], "Local time: %s" : "Lokal tid: %s", "today" : "i dag", "tomorrow" : "I morgen", @@ -124,7 +124,7 @@ OC.L10N.register( "About" : "Om", "Display name" : "Visningsnavn", "Headline" : "Overskrift", - "Organisation" : "Organisasion", + "Organization" : "Organisering", "Role" : "Rolle", "Pronouns" : "Pronomen", "Unknown account" : "Ukjent konto", @@ -138,7 +138,6 @@ OC.L10N.register( "Oracle connection could not be established" : "Klarte ikke å etablere forbindelse til Oracle", "Oracle Login and/or password not valid" : "Oracle-pålogging og/eller passord ikke gyldig", "PostgreSQL Login and/or password not valid" : "PostgreSQL-pålogging og/eller passord ikke gyldig", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X støttes ikke og %s vil ikke fungere korrekt på denne plattformen. Bruk på egen risiko!", "For the best results, please consider using a GNU/Linux server instead." : "For beste resultat, vurder å bruke en GNU/Linux-server i stedet.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Det ser ut for at %s-instansen kjører i et 32-bit PHP-miljø med open_basedir satt opp i php.ini. Dette vil føre til problemer med filer over 4 GB og frarådes på det sterkeste.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Fjern innstillingen open_basedir i php.ini eller bytt til 64-bit PHP.", @@ -149,7 +148,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Delings-server %s ikke funnet", "Sharing backend for %s not found" : "Delings-server for %s ikke funnet", "%1$s shared %2$s with you" : "%1$s delte %2$s med deg", - "Click the button below to open it." : "Klikk på knappen nedenfor for å åpne den.", "Open %s" : "Åpne %s", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s delte %2$s med deg og ønsker å legge til:", @@ -162,7 +160,10 @@ OC.L10N.register( "Share recipient should not be empty" : "Delingsmottakeren skal ikke være tom", "Share recipient is not a valid circle" : "Delingsmottakeren er ikke en gyldig sirkel", "Unknown share type" : "Ukjent ressurstype", + "Cannot share with yourself" : "Kan ikke dele med deg selv", + "You cannot share your root folder" : "Du kan ikke dele rot-mappen din", "You are not allowed to share %s" : "Du har ikke lov til å dele %s", + "Valid permissions are required for sharing" : "Gyldige tillatelser kreves for deling", "Cannot increase permissions of %s" : "Kan ikke øke tillatelser for %s", "Files cannot be shared with delete permissions" : "Filer kan ikke deles med slett-rettigheter", "Files cannot be shared with create permissions" : "Filer kan ikke deles med opprettingstillatelser", @@ -170,6 +171,7 @@ OC.L10N.register( "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Kan ikke sette utløpsdato mer enn %n dag i fremtiden","Kan ikke sette utløpsdato mer enn %n dager i fremtiden"], "Sharing is only allowed with group members" : "Deling er kun tillatt med gruppemedlemmer", "Sharing %s failed, because this item is already shared with the account %s" : "Deling av %s feilet, fordi dette elementet er allerede delt med kontoen %s", + "Group \"%s\" does not exist" : "Gruppen «%s» finnes ikke.", "The requested share does not exist anymore" : "Forespurt ressurs finnes ikke lenger", "The requested share comes from a disabled user" : "Den forespurte delingen kommer fra en deaktivert bruker", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Brukeren ble ikke opprettet fordi brukergrensen er nådd. Sjekk varslene dine for å finne ut mer.", @@ -330,6 +332,7 @@ OC.L10N.register( "Original text" : "Opprinnelig tekst", "The original text to generate a headline for" : "Den opprinnelige teksten som skal genereres en overskrift for", "The generated headline" : "Den genererte overskriften", + "Text" : "Tekst", "Reformulate text" : "Omformulere tekst", "Takes a text and reformulates it" : "Tar en tekst og omformulerer den", "Write a text that you want the assistant to reformulate" : "Skriv en tekst som du vil at assistenten skal omformulere", @@ -365,41 +368,8 @@ OC.L10N.register( "Generate headline" : "Generer overskrift", "Summarizes text by reducing its length without losing key information." : "Oppsummerer tekst ved å redusere lengden uten å miste nøkkelinformasjon.", "Extracts topics from a text and outputs them separated by commas." : "Trekker ut emner fra en tekst og sender dem ut atskilt med komma.", - "Education Edition" : "Utdanningsversjon", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Innlogget bruker må være administrator, underadministrator eller ha fått spesiell rett til å få tilgang til denne innstillingen.", - "Logged in user must be an admin or sub admin" : "Innlogget bruker må være administrator eller en underadministrator.", - "Logged in user must be an admin" : "Innlogget bruker må være administrator", - "File name is a reserved word" : "Filnavnet er et reservert ord", - "File name contains at least one invalid character" : "Filnavnet inneholder minst ett ulovlig tegn", - "File name is too long" : "Filnavnet er for langt", - "Help" : "Hjelp", - "Users" : "Brukere", - "Unknown user" : "Ukjent bruker", - "Enter the database username and name for %s" : "Skriv inn databasens brukernavn og navn for %s", - "Enter the database username for %s" : "Skriv inn databasens brukernavn for %s", - "MySQL username and/or password not valid" : "MySQL-brukernavn og/eller passord ikke gyldig", - "Oracle username and/or password not valid" : "Oracle-brukernavn og/eller passord er ikke gyldig", - "PostgreSQL username and/or password not valid" : "PostgreSQL-brukernavn og/eller passord er ikke gyldig", - "Set an admin username." : "Sett et admin-brukernavn.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s delte »%2$s« med deg og vil legge til:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s delte »%2$s« med deg og vil legge til", - "»%s« added a note to a file shared with you" : "»%s« la til en melding til en fil delt med deg", - "Open »%s«" : "Åpne »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Deling av %s mislyktes, fordi dette elementet allerede er delt med bruker %s", - "%1$s shared »%2$s« with you" : "%1$s delte »%2$s« med deg", - "%1$s shared »%2$s« with you." : "%1$s delte »%2$s« med deg.", - "The username is already being used" : "Brukernavnet er allerede i bruk", - "Could not create user" : "Kunne ikke opprette bruker", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kun følgende tegn er tillatt i et brukernavn: \"a-z\", \"A-Z\", \"0-9\", mellomrom og \"_.@-'\"", - "A valid username must be provided" : "Oppgi et gyldig brukernavn", - "Username contains whitespace at the beginning or at the end" : "Brukernavn inneholder blanke på begynnelsen eller slutten", - "Username must not consist of dots only" : "Brukernavn kan ikke bare bestå av punktum", - "Username is invalid because files already exist for this user" : "Brukernavnet er ugyldig fordi det finnes allerede filer for denne brukeren.", - "User disabled" : "Brukeren er deaktivert", + "Organisation" : "Organisasion", "File is currently busy, please try again later" : "Filen er opptatt for øyeblikket, prøv igjen senere", - "Cannot download file" : "Kan ikke laste ned fil", - "Your data directory is readable by other users." : "Datakatalogen din kan leses av andre brukere.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Endre tillatelsene til 0770 slik at mappen ikke kan listes av andre brukere.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Forsikre deg om at det finnes ei fil kalt \".ocdata\" på rota av datamappa." + "Cannot download file" : "Kan ikke laste ned fil" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/nb.json b/lib/l10n/nb.json index 9a378035c80..b9442e11952 100644 --- a/lib/l10n/nb.json +++ b/lib/l10n/nb.json @@ -36,7 +36,6 @@ "Server version %s or higher is required." : "Serverversjon %s eller høyere kreves.", "Server version %s or lower is required." : "Serverversjon %s eller lavere kreves.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Innlogget konto må være administrator, underadministrator eller ha fått spesiell rett til å få tilgang til denne innstillingen.", - "Your current IP address doesn’t allow you to perform admin actions" : "Den nåværende IP-adressen din lar deg ikke utføre administratorhandlinger", "Logged in account must be an admin or sub admin" : "Innlogget konto må være administrator eller en underadministrator.", "Logged in account must be an admin" : "Innlogget konto må være administrator", "Wiping of device %s has started" : "Sikker sletting av enhet %s er startet", @@ -57,6 +56,7 @@ "Avatar image is not square" : "Avatarbilde er ikke firkantet", "Files" : "Filer", "View profile" : "Vis profil", + "_%nh_::_%nh_" : ["%nh","%nh"], "Local time: %s" : "Lokal tid: %s", "today" : "i dag", "tomorrow" : "I morgen", @@ -122,7 +122,7 @@ "About" : "Om", "Display name" : "Visningsnavn", "Headline" : "Overskrift", - "Organisation" : "Organisasion", + "Organization" : "Organisering", "Role" : "Rolle", "Pronouns" : "Pronomen", "Unknown account" : "Ukjent konto", @@ -136,7 +136,6 @@ "Oracle connection could not be established" : "Klarte ikke å etablere forbindelse til Oracle", "Oracle Login and/or password not valid" : "Oracle-pålogging og/eller passord ikke gyldig", "PostgreSQL Login and/or password not valid" : "PostgreSQL-pålogging og/eller passord ikke gyldig", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X støttes ikke og %s vil ikke fungere korrekt på denne plattformen. Bruk på egen risiko!", "For the best results, please consider using a GNU/Linux server instead." : "For beste resultat, vurder å bruke en GNU/Linux-server i stedet.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Det ser ut for at %s-instansen kjører i et 32-bit PHP-miljø med open_basedir satt opp i php.ini. Dette vil føre til problemer med filer over 4 GB og frarådes på det sterkeste.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Fjern innstillingen open_basedir i php.ini eller bytt til 64-bit PHP.", @@ -147,7 +146,6 @@ "Sharing backend %s not found" : "Delings-server %s ikke funnet", "Sharing backend for %s not found" : "Delings-server for %s ikke funnet", "%1$s shared %2$s with you" : "%1$s delte %2$s med deg", - "Click the button below to open it." : "Klikk på knappen nedenfor for å åpne den.", "Open %s" : "Åpne %s", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s delte %2$s med deg og ønsker å legge til:", @@ -160,7 +158,10 @@ "Share recipient should not be empty" : "Delingsmottakeren skal ikke være tom", "Share recipient is not a valid circle" : "Delingsmottakeren er ikke en gyldig sirkel", "Unknown share type" : "Ukjent ressurstype", + "Cannot share with yourself" : "Kan ikke dele med deg selv", + "You cannot share your root folder" : "Du kan ikke dele rot-mappen din", "You are not allowed to share %s" : "Du har ikke lov til å dele %s", + "Valid permissions are required for sharing" : "Gyldige tillatelser kreves for deling", "Cannot increase permissions of %s" : "Kan ikke øke tillatelser for %s", "Files cannot be shared with delete permissions" : "Filer kan ikke deles med slett-rettigheter", "Files cannot be shared with create permissions" : "Filer kan ikke deles med opprettingstillatelser", @@ -168,6 +169,7 @@ "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Kan ikke sette utløpsdato mer enn %n dag i fremtiden","Kan ikke sette utløpsdato mer enn %n dager i fremtiden"], "Sharing is only allowed with group members" : "Deling er kun tillatt med gruppemedlemmer", "Sharing %s failed, because this item is already shared with the account %s" : "Deling av %s feilet, fordi dette elementet er allerede delt med kontoen %s", + "Group \"%s\" does not exist" : "Gruppen «%s» finnes ikke.", "The requested share does not exist anymore" : "Forespurt ressurs finnes ikke lenger", "The requested share comes from a disabled user" : "Den forespurte delingen kommer fra en deaktivert bruker", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Brukeren ble ikke opprettet fordi brukergrensen er nådd. Sjekk varslene dine for å finne ut mer.", @@ -328,6 +330,7 @@ "Original text" : "Opprinnelig tekst", "The original text to generate a headline for" : "Den opprinnelige teksten som skal genereres en overskrift for", "The generated headline" : "Den genererte overskriften", + "Text" : "Tekst", "Reformulate text" : "Omformulere tekst", "Takes a text and reformulates it" : "Tar en tekst og omformulerer den", "Write a text that you want the assistant to reformulate" : "Skriv en tekst som du vil at assistenten skal omformulere", @@ -363,41 +366,8 @@ "Generate headline" : "Generer overskrift", "Summarizes text by reducing its length without losing key information." : "Oppsummerer tekst ved å redusere lengden uten å miste nøkkelinformasjon.", "Extracts topics from a text and outputs them separated by commas." : "Trekker ut emner fra en tekst og sender dem ut atskilt med komma.", - "Education Edition" : "Utdanningsversjon", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Innlogget bruker må være administrator, underadministrator eller ha fått spesiell rett til å få tilgang til denne innstillingen.", - "Logged in user must be an admin or sub admin" : "Innlogget bruker må være administrator eller en underadministrator.", - "Logged in user must be an admin" : "Innlogget bruker må være administrator", - "File name is a reserved word" : "Filnavnet er et reservert ord", - "File name contains at least one invalid character" : "Filnavnet inneholder minst ett ulovlig tegn", - "File name is too long" : "Filnavnet er for langt", - "Help" : "Hjelp", - "Users" : "Brukere", - "Unknown user" : "Ukjent bruker", - "Enter the database username and name for %s" : "Skriv inn databasens brukernavn og navn for %s", - "Enter the database username for %s" : "Skriv inn databasens brukernavn for %s", - "MySQL username and/or password not valid" : "MySQL-brukernavn og/eller passord ikke gyldig", - "Oracle username and/or password not valid" : "Oracle-brukernavn og/eller passord er ikke gyldig", - "PostgreSQL username and/or password not valid" : "PostgreSQL-brukernavn og/eller passord er ikke gyldig", - "Set an admin username." : "Sett et admin-brukernavn.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s delte »%2$s« med deg og vil legge til:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s delte »%2$s« med deg og vil legge til", - "»%s« added a note to a file shared with you" : "»%s« la til en melding til en fil delt med deg", - "Open »%s«" : "Åpne »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Deling av %s mislyktes, fordi dette elementet allerede er delt med bruker %s", - "%1$s shared »%2$s« with you" : "%1$s delte »%2$s« med deg", - "%1$s shared »%2$s« with you." : "%1$s delte »%2$s« med deg.", - "The username is already being used" : "Brukernavnet er allerede i bruk", - "Could not create user" : "Kunne ikke opprette bruker", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kun følgende tegn er tillatt i et brukernavn: \"a-z\", \"A-Z\", \"0-9\", mellomrom og \"_.@-'\"", - "A valid username must be provided" : "Oppgi et gyldig brukernavn", - "Username contains whitespace at the beginning or at the end" : "Brukernavn inneholder blanke på begynnelsen eller slutten", - "Username must not consist of dots only" : "Brukernavn kan ikke bare bestå av punktum", - "Username is invalid because files already exist for this user" : "Brukernavnet er ugyldig fordi det finnes allerede filer for denne brukeren.", - "User disabled" : "Brukeren er deaktivert", + "Organisation" : "Organisasion", "File is currently busy, please try again later" : "Filen er opptatt for øyeblikket, prøv igjen senere", - "Cannot download file" : "Kan ikke laste ned fil", - "Your data directory is readable by other users." : "Datakatalogen din kan leses av andre brukere.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Endre tillatelsene til 0770 slik at mappen ikke kan listes av andre brukere.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Forsikre deg om at det finnes ei fil kalt \".ocdata\" på rota av datamappa." + "Cannot download file" : "Kan ikke laste ned fil" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/nl.js b/lib/l10n/nl.js index 5e99769018b..f5c0fd369f2 100644 --- a/lib/l10n/nl.js +++ b/lib/l10n/nl.js @@ -52,6 +52,8 @@ OC.L10N.register( "Avatar image is not square" : "Avatar afbeelding is niet vierkant", "Files" : "Bestanden", "View profile" : "Bekijk profiel", + "_%nh_::_%nh_" : ["%nh","%nh"], + "Local time: %s" : "Lokale tijd: %s", "today" : "vandaag", "tomorrow" : "morgen", "yesterday" : "gisteren", @@ -74,6 +76,8 @@ OC.L10N.register( "Empty file" : "Leeg bestand", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Module met ID: %s bestaat niet. Schakel die in binnen de app-instellingen of neem contact op met je beheerder.", "Dot files are not allowed" : "Punt-bestanden zijn niet toegestaan", + "%1$s (renamed)" : "%1$s (hernoemd)", + "renamed file" : "bestand hernoemd", "File already exists" : "Bestand bestaat al", "Invalid path" : "Ongeldig pad", "Failed to create file from template" : "Kon geen bestand van het sjabloon maken", @@ -102,13 +106,13 @@ OC.L10N.register( "Address" : "Adres", "Profile picture" : "Profielafbeelding", "About" : "Over", + "Display name" : "Weergave naam", "Headline" : "Hoofdlijn", - "Organisation" : "Organisatie", + "Organization" : "Organisatie", "Role" : "Rol", "Additional settings" : "Aanvullende instellingen", "You need to enter details of an existing account." : "Geef de details van een bestaand account op.", "Oracle connection could not be established" : "Er kon geen verbinding met Oracle worden gemaakt.", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OSX wordt niet ondersteund en %s zal niet goed werken op dit platform. Gebruik het op eigen risico!", "For the best results, please consider using a GNU/Linux server instead." : "Voor het beste resultaat adviseren wij het gebruik van een GNU/Linux server.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Het lijkt erop dat deze %s versie draait in een 32 bits PHP omgeving en dat open_basedir is geconfigureerd in php.ini. Dat zal leiden tot problemen met bestanden groter dan 4 GB en wordt dus sterk afgeraden.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Verwijder de open_basedir instelling in php.ini of schakel over op de 64bit PHP.", @@ -117,8 +121,12 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "De gedeelde achtergrond %s moet de OCP\\Share_Backend interface implementeren", "Sharing backend %s not found" : "De gedeelde backend %s is niet gevonden", "Sharing backend for %s not found" : "De gedeelde backend voor %s is niet gevonden", - "Click the button below to open it." : "Klik de onderstaande button om te openen.", + "%1$s shared %2$s with you" : "%1$s deelde %2$s met jou", + "Open %s" : "%s openen", "%1$s via %2$s" : "%1$s via %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s deelde %2$s met jou en wil toevoegen:", + "%1$s shared %2$s with you and wants to add" : "%1$s deelde %2$s met jou en wil toevoegen", + "%s added a note to a file shared with you" : "%s heeft een notitie toegevoegd aan een bestand dat met jou werd gedeeld", "Unknown share type" : "Onbekend type gedeelde folder", "You are not allowed to share %s" : "Je bent niet bevoegd om %s te delen", "Cannot increase permissions of %s" : "Kan de machtiging van %s niet verhogen.", @@ -127,6 +135,7 @@ OC.L10N.register( "Expiration date is in the past" : "De vervaldatum ligt in het verleden", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Kan de vervaldatum niet meer dan %s dag in de toekomst instellen","Kan de vervaldatum niet meer dan %s dagen in de toekomst instellen"], "Sharing is only allowed with group members" : "Delen kan alleen met groepsleden", + "Sharing %s failed, because this item is already shared with the account %s" : "Het delen van%s is mislukt, omdat dit item al gedeeld wordt met het account %s", "The requested share does not exist anymore" : "De toegang tot de gedeelde folder bestaat niet meer", "Could not find category \"%s\"" : "Kan categorie \"%s\" niet vinden", "Sunday" : "Zondag", @@ -218,40 +227,11 @@ OC.L10N.register( "Storage is temporarily not available" : "Opslag is tijdelijk niet beschikbaar", "Storage connection timeout. %s" : "Opslag verbinding time-out. %s", "Confirmation" : "Bevestiging", + "Text" : "Tekst", "Summary" : "Samenvatting", "Translate" : "Vertaal", "Result" : "Resultaat", - "Education Edition" : "Onderwijs Editie", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Ingelogde gebruiken moet beheerder, sub-beheerder of gebruiker met speciale rechten om deze instelling te veranderen zijn", - "Logged in user must be an admin or sub admin" : "Ingelogde gebruiker moet een beheerder of subbeheerder zijn", - "Logged in user must be an admin" : "Ingelogde gebruiker moet een beheerder zijn", - "File name is a reserved word" : "Bestandsnaam is een gereserveerd woord", - "File name contains at least one invalid character" : "De bestandsnaam bevat in ieder geval één verboden teken", - "File name is too long" : "De bestandsnaam is te lang", - "Help" : "Help", - "Users" : "Gebruikers", - "Unknown user" : "Onbekende gebruiker", - "MySQL username and/or password not valid" : "MySQL gebruikersnaam en/of wachtwoord ongeldig", - "Oracle username and/or password not valid" : "Oracle gebruikersnaam en/of wachtwoord ongeldig", - "PostgreSQL username and/or password not valid" : "PostgreSQL gebruikersnaam en/of wachtwoord ongeldig", - "Set an admin username." : "Stel de gebruikersnaam van de beheerder in.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s deelde \"%2$s\" met jou en wil toevoegen:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s deelde \"%2$s\" met jou en wil toevoegen", - "»%s« added a note to a file shared with you" : "\"%s\" voegde een notitie toe aan een bestand dat met jou is gedeeld", - "Open »%s«" : "Open \"%s\"", - "Sharing %s failed, because this item is already shared with user %s" : "Delen van %s is mislukt, omdat het object al wordt gedeeld met gebruiker %s", - "%1$s shared »%2$s« with you" : "%1$s deelde \"%2$s\" met jou", - "%1$s shared »%2$s« with you." : "%1$s deelde \"%2$s\" met jou.", - "The username is already being used" : "De gebruikersnaam bestaat al", - "Could not create user" : "Kan gebruiker niet aanmaken.", - "A valid username must be provided" : "Er moet een geldige gebruikersnaam worden opgegeven", - "Username contains whitespace at the beginning or at the end" : "De gebruikersnaam bevat spaties aan het begin of aan het eind", - "Username must not consist of dots only" : "De gebruikersnaam mag niet uit alleen punten bestaan", - "Username is invalid because files already exist for this user" : "Gebruikersnaam is ongeldig omdat er al bestanden voor deze gebruiker bestaan", - "User disabled" : "Gebruiker uitgeschakeld", - "File is currently busy, please try again later" : "Bestandsverwerking bezig, probeer het later opnieuw", - "Your data directory is readable by other users." : "Je datamap is leesbaar voor andere gebruikers.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Wijzig de machtiging in 0770 zodat de directory niet door andere gebruikers bekeken kan worden.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Zorg dat er een bestand genaamd \".ocdata\" in de hoofddirectory aanwezig is." + "Organisation" : "Organisatie", + "File is currently busy, please try again later" : "Bestandsverwerking bezig, probeer het later opnieuw" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/nl.json b/lib/l10n/nl.json index 827867db251..3251a757fe6 100644 --- a/lib/l10n/nl.json +++ b/lib/l10n/nl.json @@ -50,6 +50,8 @@ "Avatar image is not square" : "Avatar afbeelding is niet vierkant", "Files" : "Bestanden", "View profile" : "Bekijk profiel", + "_%nh_::_%nh_" : ["%nh","%nh"], + "Local time: %s" : "Lokale tijd: %s", "today" : "vandaag", "tomorrow" : "morgen", "yesterday" : "gisteren", @@ -72,6 +74,8 @@ "Empty file" : "Leeg bestand", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Module met ID: %s bestaat niet. Schakel die in binnen de app-instellingen of neem contact op met je beheerder.", "Dot files are not allowed" : "Punt-bestanden zijn niet toegestaan", + "%1$s (renamed)" : "%1$s (hernoemd)", + "renamed file" : "bestand hernoemd", "File already exists" : "Bestand bestaat al", "Invalid path" : "Ongeldig pad", "Failed to create file from template" : "Kon geen bestand van het sjabloon maken", @@ -100,13 +104,13 @@ "Address" : "Adres", "Profile picture" : "Profielafbeelding", "About" : "Over", + "Display name" : "Weergave naam", "Headline" : "Hoofdlijn", - "Organisation" : "Organisatie", + "Organization" : "Organisatie", "Role" : "Rol", "Additional settings" : "Aanvullende instellingen", "You need to enter details of an existing account." : "Geef de details van een bestaand account op.", "Oracle connection could not be established" : "Er kon geen verbinding met Oracle worden gemaakt.", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OSX wordt niet ondersteund en %s zal niet goed werken op dit platform. Gebruik het op eigen risico!", "For the best results, please consider using a GNU/Linux server instead." : "Voor het beste resultaat adviseren wij het gebruik van een GNU/Linux server.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Het lijkt erop dat deze %s versie draait in een 32 bits PHP omgeving en dat open_basedir is geconfigureerd in php.ini. Dat zal leiden tot problemen met bestanden groter dan 4 GB en wordt dus sterk afgeraden.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Verwijder de open_basedir instelling in php.ini of schakel over op de 64bit PHP.", @@ -115,8 +119,12 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "De gedeelde achtergrond %s moet de OCP\\Share_Backend interface implementeren", "Sharing backend %s not found" : "De gedeelde backend %s is niet gevonden", "Sharing backend for %s not found" : "De gedeelde backend voor %s is niet gevonden", - "Click the button below to open it." : "Klik de onderstaande button om te openen.", + "%1$s shared %2$s with you" : "%1$s deelde %2$s met jou", + "Open %s" : "%s openen", "%1$s via %2$s" : "%1$s via %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s deelde %2$s met jou en wil toevoegen:", + "%1$s shared %2$s with you and wants to add" : "%1$s deelde %2$s met jou en wil toevoegen", + "%s added a note to a file shared with you" : "%s heeft een notitie toegevoegd aan een bestand dat met jou werd gedeeld", "Unknown share type" : "Onbekend type gedeelde folder", "You are not allowed to share %s" : "Je bent niet bevoegd om %s te delen", "Cannot increase permissions of %s" : "Kan de machtiging van %s niet verhogen.", @@ -125,6 +133,7 @@ "Expiration date is in the past" : "De vervaldatum ligt in het verleden", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Kan de vervaldatum niet meer dan %s dag in de toekomst instellen","Kan de vervaldatum niet meer dan %s dagen in de toekomst instellen"], "Sharing is only allowed with group members" : "Delen kan alleen met groepsleden", + "Sharing %s failed, because this item is already shared with the account %s" : "Het delen van%s is mislukt, omdat dit item al gedeeld wordt met het account %s", "The requested share does not exist anymore" : "De toegang tot de gedeelde folder bestaat niet meer", "Could not find category \"%s\"" : "Kan categorie \"%s\" niet vinden", "Sunday" : "Zondag", @@ -216,40 +225,11 @@ "Storage is temporarily not available" : "Opslag is tijdelijk niet beschikbaar", "Storage connection timeout. %s" : "Opslag verbinding time-out. %s", "Confirmation" : "Bevestiging", + "Text" : "Tekst", "Summary" : "Samenvatting", "Translate" : "Vertaal", "Result" : "Resultaat", - "Education Edition" : "Onderwijs Editie", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Ingelogde gebruiken moet beheerder, sub-beheerder of gebruiker met speciale rechten om deze instelling te veranderen zijn", - "Logged in user must be an admin or sub admin" : "Ingelogde gebruiker moet een beheerder of subbeheerder zijn", - "Logged in user must be an admin" : "Ingelogde gebruiker moet een beheerder zijn", - "File name is a reserved word" : "Bestandsnaam is een gereserveerd woord", - "File name contains at least one invalid character" : "De bestandsnaam bevat in ieder geval één verboden teken", - "File name is too long" : "De bestandsnaam is te lang", - "Help" : "Help", - "Users" : "Gebruikers", - "Unknown user" : "Onbekende gebruiker", - "MySQL username and/or password not valid" : "MySQL gebruikersnaam en/of wachtwoord ongeldig", - "Oracle username and/or password not valid" : "Oracle gebruikersnaam en/of wachtwoord ongeldig", - "PostgreSQL username and/or password not valid" : "PostgreSQL gebruikersnaam en/of wachtwoord ongeldig", - "Set an admin username." : "Stel de gebruikersnaam van de beheerder in.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s deelde \"%2$s\" met jou en wil toevoegen:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s deelde \"%2$s\" met jou en wil toevoegen", - "»%s« added a note to a file shared with you" : "\"%s\" voegde een notitie toe aan een bestand dat met jou is gedeeld", - "Open »%s«" : "Open \"%s\"", - "Sharing %s failed, because this item is already shared with user %s" : "Delen van %s is mislukt, omdat het object al wordt gedeeld met gebruiker %s", - "%1$s shared »%2$s« with you" : "%1$s deelde \"%2$s\" met jou", - "%1$s shared »%2$s« with you." : "%1$s deelde \"%2$s\" met jou.", - "The username is already being used" : "De gebruikersnaam bestaat al", - "Could not create user" : "Kan gebruiker niet aanmaken.", - "A valid username must be provided" : "Er moet een geldige gebruikersnaam worden opgegeven", - "Username contains whitespace at the beginning or at the end" : "De gebruikersnaam bevat spaties aan het begin of aan het eind", - "Username must not consist of dots only" : "De gebruikersnaam mag niet uit alleen punten bestaan", - "Username is invalid because files already exist for this user" : "Gebruikersnaam is ongeldig omdat er al bestanden voor deze gebruiker bestaan", - "User disabled" : "Gebruiker uitgeschakeld", - "File is currently busy, please try again later" : "Bestandsverwerking bezig, probeer het later opnieuw", - "Your data directory is readable by other users." : "Je datamap is leesbaar voor andere gebruikers.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Wijzig de machtiging in 0770 zodat de directory niet door andere gebruikers bekeken kan worden.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Zorg dat er een bestand genaamd \".ocdata\" in de hoofddirectory aanwezig is." + "Organisation" : "Organisatie", + "File is currently busy, please try again later" : "Bestandsverwerking bezig, probeer het later opnieuw" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/nn_NO.js b/lib/l10n/nn_NO.js index 680b671b105..16fb2f1d6fe 100644 --- a/lib/l10n/nn_NO.js +++ b/lib/l10n/nn_NO.js @@ -74,13 +74,6 @@ OC.L10N.register( "A valid password must be provided" : "Du må oppgje eit gyldig passord", "Login canceled by app" : "Innlogging avbroten av app", "Authentication error" : "Feil i autentisering", - "Summary" : "Oppsumering", - "File name is too long" : "Filnamnet er for langt", - "Help" : "Hjelp", - "Users" : "Brukarar", - "Unknown user" : "Ukjend brukar", - "Open »%s«" : "Opna »%s«", - "A valid username must be provided" : "Du må oppgje eit gyldig brukarnamn", - "User disabled" : "Brukar deaktivert" + "Summary" : "Oppsumering" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/nn_NO.json b/lib/l10n/nn_NO.json index 97652b01724..74228b09624 100644 --- a/lib/l10n/nn_NO.json +++ b/lib/l10n/nn_NO.json @@ -72,13 +72,6 @@ "A valid password must be provided" : "Du må oppgje eit gyldig passord", "Login canceled by app" : "Innlogging avbroten av app", "Authentication error" : "Feil i autentisering", - "Summary" : "Oppsumering", - "File name is too long" : "Filnamnet er for langt", - "Help" : "Hjelp", - "Users" : "Brukarar", - "Unknown user" : "Ukjend brukar", - "Open »%s«" : "Opna »%s«", - "A valid username must be provided" : "Du må oppgje eit gyldig brukarnamn", - "User disabled" : "Brukar deaktivert" + "Summary" : "Oppsumering" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/oc.js b/lib/l10n/oc.js index e16ab144e85..2e477fe89ca 100644 --- a/lib/l10n/oc.js +++ b/lib/l10n/oc.js @@ -42,7 +42,6 @@ OC.L10N.register( "Profile picture" : "Imatge de perfil", "About" : "A prepaus", "Headline" : "Títol", - "Organisation" : "Organizacion", "Role" : "Ròtle", "Additional settings" : "Paramètres addicionals", "Set an admin password." : "Definir un senhal admin.", @@ -70,10 +69,8 @@ OC.L10N.register( "Authentication error" : "Error d’autentificacion", "Storage is temporarily not available" : "Emmagazinatge temporàriament indisponible", "Chat" : "Messatjariá", + "Text" : "Tèxt", "Translate" : "Tradurre", - "Help" : "Ajuda", - "Users" : "Utilizaires", - "Open »%s«" : "Dobrir « %s »", - "User disabled" : "Utilizaire desactivat" + "Organisation" : "Organizacion" }, "nplurals=2; plural=(n > 1);"); diff --git a/lib/l10n/oc.json b/lib/l10n/oc.json index 24ebda471aa..026f70b6b19 100644 --- a/lib/l10n/oc.json +++ b/lib/l10n/oc.json @@ -40,7 +40,6 @@ "Profile picture" : "Imatge de perfil", "About" : "A prepaus", "Headline" : "Títol", - "Organisation" : "Organizacion", "Role" : "Ròtle", "Additional settings" : "Paramètres addicionals", "Set an admin password." : "Definir un senhal admin.", @@ -68,10 +67,8 @@ "Authentication error" : "Error d’autentificacion", "Storage is temporarily not available" : "Emmagazinatge temporàriament indisponible", "Chat" : "Messatjariá", + "Text" : "Tèxt", "Translate" : "Tradurre", - "Help" : "Ajuda", - "Users" : "Utilizaires", - "Open »%s«" : "Dobrir « %s »", - "User disabled" : "Utilizaire desactivat" + "Organisation" : "Organizacion" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/lib/l10n/pl.js b/lib/l10n/pl.js index e0d5a386c22..18d48c362b1 100644 --- a/lib/l10n/pl.js +++ b/lib/l10n/pl.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Wymagana jest wersja serwera %s lub wyższa.", "Server version %s or lower is required." : "Wymagana jest wersja serwera %s lub niższa.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Zalogowane konto musi być administratorem, subadministratorem lub posiadać specjalne uprawnienia, aby uzyskać dostęp do tego ustawienia", - "Your current IP address doesn’t allow you to perform admin actions" : "Twój obecny adres IP nie pozwala na wykonywanie czynności administracyjnych", + "Your current IP address doesn't allow you to perform admin actions" : "Twój obecny adres IP nie pozwala na wykonywanie działań administracyjnych", "Logged in account must be an admin or sub admin" : "Zalogowane konto musi być administratorem lub subadministratorem", "Logged in account must be an admin" : "Zalogowane konto musi być administratorem", "Wiping of device %s has started" : "Rozpoczęto czyszczenie urządzenia %s", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Obraz awatara nie jest kwadratowy", "Files" : "Pliki", "View profile" : "Zobacz profil", + "same time" : "jednocześnie", + "_%nh_::_%nh_" : ["%nh","%nh","%nh","%ngodz."], + "_%nm_::_%nm_" : ["%nmin","%nmin","%nmin","%nmin"], + "%s ahead" : "o %s wcześniej", + "%s behind" : "o %s później", "Local time: %s" : "Czas lokalny: %s", "today" : "dzisiaj", "tomorrow" : "jutro", @@ -81,12 +86,32 @@ OC.L10N.register( "seconds ago" : "przed chwilą", "Empty file" : "Pusty plik", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Moduł o ID: %s nie istnieje. Włącz go w ustawieniach aplikacji lub skontaktuj się z administratorem.", - "Dot files are not allowed" : "Pliki z kropką są nie dozwolone", + "No file conversion providers available" : "Brak dostępnych usług konwersji plików.", + "File is too large to convert" : "Plik jest zbyt duży, aby go przekonwertować.", + "Destination does not match conversion extension" : "Docelowy format nie odpowiada rozszerzeniu konwersji", + "Could not convert file" : "Nie można przekonwertować pliku", + "Destination does not exist" : "Folder docelowy nie istnieje", + "Destination is not creatable" : "Nie można utworzyć folderu docelowego", + "Dot files are not allowed" : "Pliki z kropką są niedozwolone", + "%1$s (renamed)" : "%1$s (zmieniona nazwa)", + "renamed file" : "zmieniona nazwa pliku", + "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" jest zabronioną nazwą pliku lub folderu.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" jest zabronionym przedrostkiem dla nazw plików lub folderów.", + "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" nie jest dozwolone w nazwie pliku ani folderu.", + "\"%1$s\" is a forbidden file type." : "\"%1$s\" jest zabronionym typem pliku.", + "Filenames must not end with \"%1$s\"." : "Nazwa pliku nie może być zakończona znakiem \"%1$s\"", "Invalid parent path" : "Nieprawidłowa ścieżka nadrzędna", "File already exists" : "Plik już istnieje", "Invalid path" : "Niewłaściwa ścieżka", "Failed to create file from template" : "Nie udało się utworzyć pliku z szablonu", "Templates" : "Szablony", + "Storage %s cannot be moved" : "Magazynu %s nie można przenieść", + "Moving a share (%s) into a shared folder is not allowed" : "Przenoszenie udziału (%s) do folderu współdzielonego jest niedozwolone", + "Moving a storage (%s) into a shared folder is not allowed" : "Przenoszenie magazynu (%s) do folderu współdzielonego jest niedozwolone", + "Moving a share (%s) into another share (%s) is not allowed" : "Przenoszenie udziału (%s) do innego udziału (%s) jest niedozwolone", + "Moving a share (%s) into another storage (%s) is not allowed" : "Przenoszenie udziału (%s) do innego magazynu (%s) jest niedozwolone", + "Moving a storage (%s) into a share (%s) is not allowed" : "Przenoszenie magazynu (%s) do udziału (%s) jest niedozwolone", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Przenoszenie magazynu (%s) do innego magazynu (%s) jest niedozwolone", "Path contains invalid segments" : "Ścieżka zawiera nieprawidłowe segmenty", "Filename is a reserved word" : "Nazwa pliku jest słowem zastrzeżonym", "Filename contains at least one invalid character" : "Nazwa pliku zawiera co najmniej jeden nieprawidłowy znak", @@ -119,7 +144,7 @@ OC.L10N.register( "About" : "Informacje", "Display name" : "Wyświetlana nazwa", "Headline" : "Nagłówek", - "Organisation" : "Organizacja", + "Organization" : "Organizacja", "Role" : "Rola społeczna", "Pronouns" : "Zaimki", "Unknown account" : "Nieznane konto", @@ -128,9 +153,12 @@ OC.L10N.register( "Enter the database Login for %s" : "Wpisz logowanie do bazy danych dla %s", "Enter the database name for %s" : "Podaj nazwę bazy danych dla %s", "You cannot use dots in the database name %s" : "Nie można używać kropek w nazwie bazy danych %s", + "MySQL Login and/or password not valid" : "Nieprawidłowy login i/lub hasło do MySQL", "You need to enter details of an existing account." : "Musisz wprowadzić szczegółowe dane dla istniejącego konta.", "Oracle connection could not be established" : "Nie można nawiązać połączenia z bazą danych Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nie jest wspierany i %s nie będzie działać poprawnie na tej platformie. Używasz go na własne ryzyko!", + "Oracle Login and/or password not valid" : "Nieprawidłowy login i/lub hasło do Oracle", + "PostgreSQL Login and/or password not valid" : "Nieprawidłowy login i/lub hasło do PostgreSQL", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X nie jest obsługiwany i %s może nie działać poprawnie na tej platformie. Używasz na własne ryzyko!", "For the best results, please consider using a GNU/Linux server instead." : "Aby uzyskać najlepszy efekt, rozważ użycie serwera GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Wydaje się, że ta instancja %s używa PHP dla 32-bitowego środowiska, ponieważ open_basedir został tak skonfigurowany w php.ini. Doprowadzi to do problemów z plikami powyżej 4 GB i jest bardzo niezalecane.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Usuń ustawienie open_basedir w php.ini lub przełącz na PHP 64-bitowe.", @@ -140,8 +168,12 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Zaplecze do udostępniania %s musi implementować interfejs OCP\\Share_Backend", "Sharing backend %s not found" : "Zaplecze %s do udostępniania nie zostało znalezione", "Sharing backend for %s not found" : "Zaplecze do udostępniania dla %s nie zostało znalezione", - "Click the button below to open it." : "Kliknij przycisk poniżej, aby otworzyć.", + "%1$s shared %2$s with you" : "%1$s udostępnił %2$s Tobie", + "Open %s" : "Otwórz %s", "%1$s via %2$s" : "%1$s przez %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s udostępnił Ci %2$s i chce dodać:", + "%1$s shared %2$s with you and wants to add" : "%1$s udostępnił Ci %2$s i chce dodać", + "%s added a note to a file shared with you" : "%s dodał notatkę do pliku udostępnionego Tobie", "Passwords are enforced for link and mail shares" : "Hasła są wymuszane w przypadku udostępniania łączy i poczty", "Share recipient is not a valid user" : "Odbiorca udostępnienia nie jest prawidłowym użytkownikiem", "Share recipient is not a valid group" : "Odbiorca udostępnienia nie jest prawidłową grupą", @@ -149,12 +181,14 @@ OC.L10N.register( "Share recipient should not be empty" : "Odbiorca udostępnienia nie powinien być pusty", "Share recipient is not a valid circle" : "Odbiorca udostępnienia nie jest prawidłowym kręgiem", "Unknown share type" : "Nieznany typ udostępnienia", + "Share initiator must be set" : "Należy ustawić inicjatora współdzielenia", "Cannot share with yourself" : "Nie można dzielić się ze sobą", "Shared path must be set" : "Należy ustawić ścieżkę współdzieloną", "Shared path must be either a file or a folder" : "Udostępniona ścieżka musi być plikiem lub katalogiem", "You cannot share your root folder" : "Nie możesz udostępnić swojego katalogu głównego root", "You are not allowed to share %s" : "Nie możesz udostępnić %s", "Valid permissions are required for sharing" : "Do udostępniania wymagane są ważne uprawnienia", + "File shares cannot have create or delete permissions" : "Udostępnione pliki nie mogą mieć uprawnień do tworzenia ani usuwania", "Cannot increase permissions of %s" : "Nie można zwiększyć uprawnień %s", "Shares need at least read permissions" : "Udostępnianie wymaga co najmniej uprawnień do odczytu", "Files cannot be shared with delete permissions" : "Pliki nie mogą zostać udostępnione z prawem do usuwania", @@ -163,19 +197,26 @@ OC.L10N.register( "Expiration date is enforced" : "Obowiązuje data ważności", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Nie można utworzyć daty wygaśnięcia na %n dzień do przodu","Nie można utworzyć daty wygaśnięcia na %n dni do przodu","Nie można utworzyć daty wygaśnięcia na %n dni do przodu","Nie można utworzyć daty wygaśnięcia na %n dni do przodu"], "Sharing is only allowed with group members" : "Udostępnianie jest dozwolone tylko członkom grupy", + "Sharing %s failed, because this item is already shared with the account %s" : "Udostępnianie %s nie powiodło się, ponieważ ten element jest już współdzielony z kontem %s", "Group sharing is now allowed" : "Udostępnianie grupowe jest teraz dozwolone", "Sharing is only allowed within your own groups" : "Udostępnianie jest dozwolone wyłącznie w obrębie własnych grup", "Path is already shared with this group" : "Ścieżka jest już udostępniona tej grupie", "Link sharing is not allowed" : "Udostępnianie odnośników jest niedozwolone", "Public upload is not allowed" : "Przesyłanie publiczne nie jest dozwolone", - "Path contains files shared with you" : "Ścieżka zawiera pliki udostępnione Tobie", + "You cannot share a folder that contains other shares" : "Nie można udostępnić folderu zawierającego inne udostępnienia", "Sharing is disabled" : "Udostępnianie jest wyłączone", "Sharing is disabled for you" : "Udostępnianie jest dla Ciebie wyłączone", "Cannot share with the share owner" : "Nie można udostępnić właścicielowi udziału", "Share does not have a full ID" : "Udział nie ma pełnego identyfikatora", "Cannot change share type" : "Nie można zmienić typu udziału", "Can only update recipient on user shares" : "Może aktualizować odbiorców tylko w przypadku udziałów użytkownika", + "Cannot enable sending the password by Talk with an empty password" : "Nie można włączyć wysyłania hasła przez Talk przy pustym haśle", + "Cannot enable sending the password by Talk without setting a new password" : "Nie można włączyć wysyłania hasła przez Talk bez ustawienia nowego hasła", + "Cannot disable sending the password by Talk without setting a new password" : "Nie można wyłączyć wysyłania hasła przez Talk bez ustawienia nowego hasła", + "Share provider does not support accepting" : "Dostawca współdzielenia nie obsługuje przyjmowania", + "Cannot change target of link share" : "Nie można zmienić celu współdzielonego linku", "Invalid share recipient" : "Nieprawidłowy odbiorca udostępnienia", + "Group \"%s\" does not exist" : "Grupa \"%s\" nie istnieje", "The requested share does not exist anymore" : "Żądane udostępnienie już nie istnieje", "The requested share comes from a disabled user" : "Żądane udostępnienie pochodzi od wyłączonego użytkownika", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Użytkownik nie został utworzony, ponieważ osiągnięto limit użytkowników. Sprawdź swoje powiadomienia, aby dowiedzieć się więcej.", @@ -234,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "Należy podać poprawny login", "Login contains whitespace at the beginning or at the end" : "Login zawiera spacje na początku lub na końcu", "Login must not consist of dots only" : "Login nie może składać się wyłącznie z kropek", + "Username is too long" : "Nazwa użytkownika jest zbyt długa", "Login is invalid because files already exist for this user" : "Login jest nieprawidłowy, ponieważ dla tego użytkownika istnieją już pliki", "Account disabled" : "Konto wyłączone", "Login canceled by app" : "Logowanie anulowane przez aplikację", @@ -271,6 +313,7 @@ OC.L10N.register( "Your data directory must be an absolute path." : "Katalog danych musi mieć ścieżkę absolutną.", "Check the value of \"datadirectory\" in your configuration." : "Sprawdź wartość \"datadirectory\" w swojej konfiguracji.", "Your data directory is invalid." : "Katalog danych jest nieprawidłowy.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Upewnij się, że w katalogu głównym danych znajduje się plik o nazwie \"%1$s\". Powinien on zawierać: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Akcja \"%s\" jest niewspierana lub niezaimplementowana.", "Authentication failed, wrong token or provider ID given" : "Uwierzytelnienie nie powiodło się, podano nieprawidłowy token lub ID dostawcy", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Brak parametrów w celu uzupełnienia żądania. Brakujące parametry: \"%s\"", @@ -282,26 +325,114 @@ OC.L10N.register( "Storage connection error. %s" : "Błąd połączenia z magazynem. %s", "Storage is temporarily not available" : "Magazyn jest tymczasowo niedostępny", "Storage connection timeout. %s" : "Limit czasu połączenia do magazynu. %s", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Aby umożliwić wykonanie tego sprawdzenia, upewnij się, że serwer WWW może połączyć się sam ze sobą. Musi on być w stanie rozpoznać i połączyć się przynajmniej z jedną z wartości 'trusted_domains' lub 'overwrite.cli.url'. Błąd ten może być wynikiem niezgodności DNS po stronie serwera lub reguły zapory sieciowej wychodzącej.", "Transcribe audio" : "Transkrypcja dźwięku", "Transcribe the things said in an audio" : "Transkrypcja wypowiedzi w formie audio", "Audio input" : "Wejście dźwięku", "The audio to transcribe" : "Dźwięk do transkrypcji", "Transcription" : "Transkrypcja", "The transcribed text" : "Tekst transkrypcji", + "Chat with an agent" : "Czat z agentem", + "Chat message" : "Wiadomość czatu", + "A chat message to send to the agent." : "Wiadomość czatu do wysłania do agenta.", "Confirmation" : "Potwierdzenie", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Czy potwierdzić wcześniej żądane działania: 0 — odmowa, 1 — potwierdzenie.", + "Conversation token" : "Token konwersacji", + "A token representing the conversation." : "Token reprezentujący konwersację.", + "Generated response" : "Wygenerowana odpowiedź", + "The response from the chat model." : "Odpowiedź z modelu czatu.", + "The new conversation token" : "Nowy token konwersacji", + "Send this along with the next interaction." : "Wyślij to razem z następną interakcją.", + "Requested actions by the agent" : "Żądane działania agenta", + "Actions that the agent would like to carry out in JSON format." : "Działania, które agent chciałby wykonać w formacie JSON.", + "Context write" : "Zapis kontekstu", + "Writes text in a given style based on the provided source material." : "Tworzy tekst w określonym stylu na podstawie dostarczonego materiału źródłowego.", "Writing style" : "Styl pisania", + "Demonstrate a writing style that you would like to immitate" : "Zaprezentuj styl pisania, który chciałbyś naśladować", "Source material" : "Materiał źródłowy", + "The content that would like to be rewritten in the new writing style" : "Treść, która ma zostać przepisana w nowym stylu pisania", + "Generated text" : "Wygenerowany tekst", + "The generated text with content from the source material in the given style" : "Wygenerowany tekst z treścią z materiału źródłowego w określonym stylu", + "Emoji generator" : "Generator emoji", + "Takes text and generates a representative emoji for it." : "Przyjmuje tekst i generuje pasującą emoji.", + "The text to generate an emoji for" : "Tekst, dla którego ma zostać wygenerowana emoji", + "Generated emoji" : "Wygenerowane emoji", + "The generated emoji based on the input text" : "Wygenerowana emoji na podstawie wprowadzonego tekstu", + "Generate image" : "Generuj obraz", + "Generate an image from a text prompt" : "Wygeneruj obraz z opisu tekstowego", + "Prompt" : "Polecenie", "Describe the image you want to generate" : "Opisz obraz, który chcesz wygenerować", "Number of images" : "Liczba obrazów", "How many images to generate" : "Ile obrazów wygenerować", "Output images" : "Obrazy wyjściowe", "The generated images" : "Wygenerowane obrazy", + "Generate speech" : "Generuj mowę", + "Generate speech from a transcript" : "Wygeneruj mowę z transkryptu", + "Write transcript that you want the assistant to generate speech from" : "Napisz transkrypt, na podstawie którego asystent ma wygenerować mowę", + "Output speech" : "Wygenerowana mowa", + "The generated speech" : "Wygenerowana mowa", + "Free text to text prompt" : "Dowolny tekst jako polecenie wejściowe", + "Runs an arbitrary prompt through a language model that returns a reply" : "Przetwarza dowolne polecenie za pomocą modelu językowego, który zwraca odpowiedź", + "Describe a task that you want the assistant to do or ask a question" : "Opisz zadanie, które ma wykonać asystent, lub zadaj pytanie", + "Generated reply" : "Wygenerowana odpowiedź", + "The generated text from the assistant" : "Wygenerowany tekst od asystenta", + "Change Tone" : "Zmień ton wypowiedzi", + "Change the tone of a piece of text." : "Zmień ton fragmentu tekstu", + "Write a text that you want the assistant to rewrite in another tone." : "Napisz tekst, który chcesz, aby asystent napisał inaczej.", + "Desired tone" : "Pożądany ton wypowiedzi", + "In which tone should your text be rewritten?" : "W jakim tonie powinien zostać napisany Twój tekst?", + "The rewritten text in the desired tone, written by the assistant:" : "Przepisany tekst w pożądanym tonie, napisany przez asystenta:", "Chat" : "Rozmowa", + "Chat with the assistant" : "Czat z asystentem", + "System prompt" : "Polecenie systemowe", + "Define rules and assumptions that the assistant should follow during the conversation." : "Określ zasady i założenia, których asystent powinien przestrzegać podczas rozmowy", "Chat history" : "Historia rozmów", + "The history of chat messages before the current message, starting with a message by the user" : "Historia wiadomości czatu przed bieżącą wiadomością, zaczynając od wiadomości użytkownika", + "Response message" : "Wiadomość odpowiedzi", + "The generated response as part of the conversation" : "Wygenerowana odpowiedź jako część rozmowy", + "Chat with tools" : "Czat z użyciem narzędzi", + "Chat with the language model with tool calling support." : "Czat z modelem językowym z obsługą wywoływania narzędzi", + "Tool message" : "Wiadomość narzędzia", + "The result of tool calls in the last interaction" : "Wynik wywołań narzędzi w ostatniej interakcji", + "Available tools" : "Dostępne narzędzia", + "The available tools in JSON format" : "Dostępne narzędzia w formacie JSON", + "The response from the chat model" : "Odpowiedź z modelu czatu", + "Tool calls" : "Wywołania narzędzi", + "Tools call instructions from the model in JSON format" : "Instrukcje wywołań narzędzi z modelu w formacie JSON", + "Formalize text" : "Sformalizuj tekst", + "Takes a text and makes it sound more formal" : "Pobiera tekst i sprawia, że brzmi bardziej formalnie", + "Write a text that you want the assistant to formalize" : "Napisz tekst, który chcesz, aby asystent sformalizował", + "Formalized text" : "Sformalizowany tekst", + "The formalized text" : "Sformalizowany tekst", + "Generate a headline" : "Wygeneruj nagłówek", "Generates a possible headline for a text." : "Generuje możliwy nagłówek tekstu.", + "Original text" : "Tekst oryginalny", + "The original text to generate a headline for" : "Oryginalny tekst, do którego ma zostać wygenerowany nagłówek", + "The generated headline" : "Wygenerowany nagłówek", + "Proofread" : "Korekta", + "Proofreads a text and lists corrections" : "Sprawdza tekst i podaje poprawki", + "Text" : "Tekst", + "The text to proofread" : "Tekst do korekty", + "Corrections" : "Poprawki", + "The corrections that should be made in your text" : "Poprawki, które należy wprowadzić w Twoim tekście", + "Reformulate text" : "Przekształć tekst", + "Takes a text and reformulates it" : "Pobiera tekst i przekształca go", + "Write a text that you want the assistant to reformulate" : "Napisz tekst, który chcesz, aby asystent przekształcił", + "Reformulated text" : "Przekształcony tekst", + "The reformulated text, written by the assistant" : "Przekształcony tekst napisany przez asystenta", + "Simplify text" : "Uprość tekst", + "Takes a text and simplifies it" : "Pobiera tekst i upraszcza go", + "Write a text that you want the assistant to simplify" : "Napisz tekst, który chcesz, aby asystent uprościł", + "Simplified text" : "Uproszczony tekst", + "The simplified text" : "Uproszczony tekst", "Summarize" : "Podsumuj", + "Summarizes a text" : "Tworzy podsumowanie tekstu", + "The original text to summarize" : "Oryginalny tekst do podsumowania", "Summary" : "Podsumowanie", + "The generated summary" : "Wygenerowane podsumowanie", "Extract topics" : "Wyodrębnij tematy", + "Extracts topics from a text and outputs them separated by commas" : "Wydobywa tematy z tekstu i zwraca je oddzielone przecinkami", + "The original text to extract topics from" : "Oryginalny tekst, z którego mają zostać wydobyte tematy", "Topics" : "Tematy", "The list of extracted topics" : "Lista wyodrębnionych tematów", "Translate" : "Tłumaczenie", @@ -319,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Wygeneruj nagłówek", "Summarizes text by reducing its length without losing key information." : "Podsumowuje tekst, zmniejszając jego długość bez utraty kluczowych informacji.", "Extracts topics from a text and outputs them separated by commas." : "Wyodrębnia tematy z tekstu i wyświetla je oddzielone przecinkami.", - "Education Edition" : "Edycja edukacyjna", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Zalogowany użytkownik musi być administratorem, subadministratorem lub mieć specjalne uprawnienia dostępu do tego ustawienia", - "Logged in user must be an admin or sub admin" : "Zalogowany użytkownik musi być administratorem lub współadministratorem", - "Logged in user must be an admin" : "Zalogowany użytkownik musi być administratorem", - "File name is a reserved word" : "Nazwa pliku jest zarezerwowana", - "File name contains at least one invalid character" : "Nazwa pliku zawiera co najmniej jeden nieprawidłowy znak", - "File name is too long" : "Nazwa pliku jest za długa", - "Help" : "Pomoc", - "Users" : "Użytkownicy", - "Unknown user" : "Nieznany użytkownik", - "Enter the database username and name for %s" : "Podaj nazwę użytkownika i nazwę bazy danych dla %s", - "Enter the database username for %s" : "Podaj nazwę użytkownika bazy danych dla %s", - "MySQL username and/or password not valid" : "Błędna nazwa użytkownika i/lub hasło do bazy danych MySQL", - "Oracle username and/or password not valid" : "Zła nazwa użytkownika i/lub hasło do bazy danych Oracle", - "PostgreSQL username and/or password not valid" : "Zła nazwa użytkownika i/lub hasło do bazy danych PostgreSQL", - "Set an admin username." : "Ustaw nazwę administratora.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s udostępnił Tobie »%2$s« i chce dodać: ", - "%1$s shared »%2$s« with you and wants to add" : " %1$s udostępnił Tobie »%2$s« i chce dodać", - "»%s« added a note to a file shared with you" : "»%s« dodał notatkę do udostępnionego dla Ciebie pliku", - "Open »%s«" : "Otwórz »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Udostępnianie %s nie powiodło się, ponieważ element jest już udostępniony użytkownikowi %s", - "%1$s shared »%2$s« with you" : "%1$s udostępnił Tobie »%2$s«", - "%1$s shared »%2$s« with you." : "%1$s udostępnił Tobie »%2$s«.", - "The username is already being used" : "Ta nazwa użytkownika jest już używana", - "Could not create user" : "Nie można utworzyć użytkownika", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "W nazwie użytkownika dozwolone są tylko następujące znaki : \"a-z\", \"A-Z\", \"0-9\", spacje i \"_.@-'\"", - "A valid username must be provided" : "Należy podać prawidłową nazwę użytkownika", - "Username contains whitespace at the beginning or at the end" : "Nazwa użytkownika zawiera spację na początku albo na końcu", - "Username must not consist of dots only" : "Nazwa użytkownika nie może się składać tylko z kropek", - "Username is invalid because files already exist for this user" : "Nazwa użytkownika jest nieprawidłowa, ponieważ pliki już istnieją dla tego użytkownika", - "User disabled" : "Użytkownik zablokowany", + "Organisation" : "Organizacja", "File is currently busy, please try again later" : "Plik jest obecnie niedostępny, spróbuj później", "Cannot download file" : "Nie można pobrać pliku", - "Your data directory is readable by other users." : "Twój katalog danych jest widoczny dla innych użytkowników.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Zmień uprawnienia na 0770, aby katalog nie był widoczny dla innych użytkowników.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Upewnij się, że w katalogu \"data\" znajduje się plik o nazwie \".ocdata\"." + "Login is too long" : "Login jest zbyt długi" }, "nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);"); diff --git a/lib/l10n/pl.json b/lib/l10n/pl.json index aeefba36b8a..63a92848d4c 100644 --- a/lib/l10n/pl.json +++ b/lib/l10n/pl.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Wymagana jest wersja serwera %s lub wyższa.", "Server version %s or lower is required." : "Wymagana jest wersja serwera %s lub niższa.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Zalogowane konto musi być administratorem, subadministratorem lub posiadać specjalne uprawnienia, aby uzyskać dostęp do tego ustawienia", - "Your current IP address doesn’t allow you to perform admin actions" : "Twój obecny adres IP nie pozwala na wykonywanie czynności administracyjnych", + "Your current IP address doesn't allow you to perform admin actions" : "Twój obecny adres IP nie pozwala na wykonywanie działań administracyjnych", "Logged in account must be an admin or sub admin" : "Zalogowane konto musi być administratorem lub subadministratorem", "Logged in account must be an admin" : "Zalogowane konto musi być administratorem", "Wiping of device %s has started" : "Rozpoczęto czyszczenie urządzenia %s", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Obraz awatara nie jest kwadratowy", "Files" : "Pliki", "View profile" : "Zobacz profil", + "same time" : "jednocześnie", + "_%nh_::_%nh_" : ["%nh","%nh","%nh","%ngodz."], + "_%nm_::_%nm_" : ["%nmin","%nmin","%nmin","%nmin"], + "%s ahead" : "o %s wcześniej", + "%s behind" : "o %s później", "Local time: %s" : "Czas lokalny: %s", "today" : "dzisiaj", "tomorrow" : "jutro", @@ -79,12 +84,32 @@ "seconds ago" : "przed chwilą", "Empty file" : "Pusty plik", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Moduł o ID: %s nie istnieje. Włącz go w ustawieniach aplikacji lub skontaktuj się z administratorem.", - "Dot files are not allowed" : "Pliki z kropką są nie dozwolone", + "No file conversion providers available" : "Brak dostępnych usług konwersji plików.", + "File is too large to convert" : "Plik jest zbyt duży, aby go przekonwertować.", + "Destination does not match conversion extension" : "Docelowy format nie odpowiada rozszerzeniu konwersji", + "Could not convert file" : "Nie można przekonwertować pliku", + "Destination does not exist" : "Folder docelowy nie istnieje", + "Destination is not creatable" : "Nie można utworzyć folderu docelowego", + "Dot files are not allowed" : "Pliki z kropką są niedozwolone", + "%1$s (renamed)" : "%1$s (zmieniona nazwa)", + "renamed file" : "zmieniona nazwa pliku", + "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" jest zabronioną nazwą pliku lub folderu.", + "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" jest zabronionym przedrostkiem dla nazw plików lub folderów.", + "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" nie jest dozwolone w nazwie pliku ani folderu.", + "\"%1$s\" is a forbidden file type." : "\"%1$s\" jest zabronionym typem pliku.", + "Filenames must not end with \"%1$s\"." : "Nazwa pliku nie może być zakończona znakiem \"%1$s\"", "Invalid parent path" : "Nieprawidłowa ścieżka nadrzędna", "File already exists" : "Plik już istnieje", "Invalid path" : "Niewłaściwa ścieżka", "Failed to create file from template" : "Nie udało się utworzyć pliku z szablonu", "Templates" : "Szablony", + "Storage %s cannot be moved" : "Magazynu %s nie można przenieść", + "Moving a share (%s) into a shared folder is not allowed" : "Przenoszenie udziału (%s) do folderu współdzielonego jest niedozwolone", + "Moving a storage (%s) into a shared folder is not allowed" : "Przenoszenie magazynu (%s) do folderu współdzielonego jest niedozwolone", + "Moving a share (%s) into another share (%s) is not allowed" : "Przenoszenie udziału (%s) do innego udziału (%s) jest niedozwolone", + "Moving a share (%s) into another storage (%s) is not allowed" : "Przenoszenie udziału (%s) do innego magazynu (%s) jest niedozwolone", + "Moving a storage (%s) into a share (%s) is not allowed" : "Przenoszenie magazynu (%s) do udziału (%s) jest niedozwolone", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Przenoszenie magazynu (%s) do innego magazynu (%s) jest niedozwolone", "Path contains invalid segments" : "Ścieżka zawiera nieprawidłowe segmenty", "Filename is a reserved word" : "Nazwa pliku jest słowem zastrzeżonym", "Filename contains at least one invalid character" : "Nazwa pliku zawiera co najmniej jeden nieprawidłowy znak", @@ -117,7 +142,7 @@ "About" : "Informacje", "Display name" : "Wyświetlana nazwa", "Headline" : "Nagłówek", - "Organisation" : "Organizacja", + "Organization" : "Organizacja", "Role" : "Rola społeczna", "Pronouns" : "Zaimki", "Unknown account" : "Nieznane konto", @@ -126,9 +151,12 @@ "Enter the database Login for %s" : "Wpisz logowanie do bazy danych dla %s", "Enter the database name for %s" : "Podaj nazwę bazy danych dla %s", "You cannot use dots in the database name %s" : "Nie można używać kropek w nazwie bazy danych %s", + "MySQL Login and/or password not valid" : "Nieprawidłowy login i/lub hasło do MySQL", "You need to enter details of an existing account." : "Musisz wprowadzić szczegółowe dane dla istniejącego konta.", "Oracle connection could not be established" : "Nie można nawiązać połączenia z bazą danych Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nie jest wspierany i %s nie będzie działać poprawnie na tej platformie. Używasz go na własne ryzyko!", + "Oracle Login and/or password not valid" : "Nieprawidłowy login i/lub hasło do Oracle", + "PostgreSQL Login and/or password not valid" : "Nieprawidłowy login i/lub hasło do PostgreSQL", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X nie jest obsługiwany i %s może nie działać poprawnie na tej platformie. Używasz na własne ryzyko!", "For the best results, please consider using a GNU/Linux server instead." : "Aby uzyskać najlepszy efekt, rozważ użycie serwera GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Wydaje się, że ta instancja %s używa PHP dla 32-bitowego środowiska, ponieważ open_basedir został tak skonfigurowany w php.ini. Doprowadzi to do problemów z plikami powyżej 4 GB i jest bardzo niezalecane.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Usuń ustawienie open_basedir w php.ini lub przełącz na PHP 64-bitowe.", @@ -138,8 +166,12 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Zaplecze do udostępniania %s musi implementować interfejs OCP\\Share_Backend", "Sharing backend %s not found" : "Zaplecze %s do udostępniania nie zostało znalezione", "Sharing backend for %s not found" : "Zaplecze do udostępniania dla %s nie zostało znalezione", - "Click the button below to open it." : "Kliknij przycisk poniżej, aby otworzyć.", + "%1$s shared %2$s with you" : "%1$s udostępnił %2$s Tobie", + "Open %s" : "Otwórz %s", "%1$s via %2$s" : "%1$s przez %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s udostępnił Ci %2$s i chce dodać:", + "%1$s shared %2$s with you and wants to add" : "%1$s udostępnił Ci %2$s i chce dodać", + "%s added a note to a file shared with you" : "%s dodał notatkę do pliku udostępnionego Tobie", "Passwords are enforced for link and mail shares" : "Hasła są wymuszane w przypadku udostępniania łączy i poczty", "Share recipient is not a valid user" : "Odbiorca udostępnienia nie jest prawidłowym użytkownikiem", "Share recipient is not a valid group" : "Odbiorca udostępnienia nie jest prawidłową grupą", @@ -147,12 +179,14 @@ "Share recipient should not be empty" : "Odbiorca udostępnienia nie powinien być pusty", "Share recipient is not a valid circle" : "Odbiorca udostępnienia nie jest prawidłowym kręgiem", "Unknown share type" : "Nieznany typ udostępnienia", + "Share initiator must be set" : "Należy ustawić inicjatora współdzielenia", "Cannot share with yourself" : "Nie można dzielić się ze sobą", "Shared path must be set" : "Należy ustawić ścieżkę współdzieloną", "Shared path must be either a file or a folder" : "Udostępniona ścieżka musi być plikiem lub katalogiem", "You cannot share your root folder" : "Nie możesz udostępnić swojego katalogu głównego root", "You are not allowed to share %s" : "Nie możesz udostępnić %s", "Valid permissions are required for sharing" : "Do udostępniania wymagane są ważne uprawnienia", + "File shares cannot have create or delete permissions" : "Udostępnione pliki nie mogą mieć uprawnień do tworzenia ani usuwania", "Cannot increase permissions of %s" : "Nie można zwiększyć uprawnień %s", "Shares need at least read permissions" : "Udostępnianie wymaga co najmniej uprawnień do odczytu", "Files cannot be shared with delete permissions" : "Pliki nie mogą zostać udostępnione z prawem do usuwania", @@ -161,19 +195,26 @@ "Expiration date is enforced" : "Obowiązuje data ważności", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Nie można utworzyć daty wygaśnięcia na %n dzień do przodu","Nie można utworzyć daty wygaśnięcia na %n dni do przodu","Nie można utworzyć daty wygaśnięcia na %n dni do przodu","Nie można utworzyć daty wygaśnięcia na %n dni do przodu"], "Sharing is only allowed with group members" : "Udostępnianie jest dozwolone tylko członkom grupy", + "Sharing %s failed, because this item is already shared with the account %s" : "Udostępnianie %s nie powiodło się, ponieważ ten element jest już współdzielony z kontem %s", "Group sharing is now allowed" : "Udostępnianie grupowe jest teraz dozwolone", "Sharing is only allowed within your own groups" : "Udostępnianie jest dozwolone wyłącznie w obrębie własnych grup", "Path is already shared with this group" : "Ścieżka jest już udostępniona tej grupie", "Link sharing is not allowed" : "Udostępnianie odnośników jest niedozwolone", "Public upload is not allowed" : "Przesyłanie publiczne nie jest dozwolone", - "Path contains files shared with you" : "Ścieżka zawiera pliki udostępnione Tobie", + "You cannot share a folder that contains other shares" : "Nie można udostępnić folderu zawierającego inne udostępnienia", "Sharing is disabled" : "Udostępnianie jest wyłączone", "Sharing is disabled for you" : "Udostępnianie jest dla Ciebie wyłączone", "Cannot share with the share owner" : "Nie można udostępnić właścicielowi udziału", "Share does not have a full ID" : "Udział nie ma pełnego identyfikatora", "Cannot change share type" : "Nie można zmienić typu udziału", "Can only update recipient on user shares" : "Może aktualizować odbiorców tylko w przypadku udziałów użytkownika", + "Cannot enable sending the password by Talk with an empty password" : "Nie można włączyć wysyłania hasła przez Talk przy pustym haśle", + "Cannot enable sending the password by Talk without setting a new password" : "Nie można włączyć wysyłania hasła przez Talk bez ustawienia nowego hasła", + "Cannot disable sending the password by Talk without setting a new password" : "Nie można wyłączyć wysyłania hasła przez Talk bez ustawienia nowego hasła", + "Share provider does not support accepting" : "Dostawca współdzielenia nie obsługuje przyjmowania", + "Cannot change target of link share" : "Nie można zmienić celu współdzielonego linku", "Invalid share recipient" : "Nieprawidłowy odbiorca udostępnienia", + "Group \"%s\" does not exist" : "Grupa \"%s\" nie istnieje", "The requested share does not exist anymore" : "Żądane udostępnienie już nie istnieje", "The requested share comes from a disabled user" : "Żądane udostępnienie pochodzi od wyłączonego użytkownika", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "Użytkownik nie został utworzony, ponieważ osiągnięto limit użytkowników. Sprawdź swoje powiadomienia, aby dowiedzieć się więcej.", @@ -232,6 +273,7 @@ "A valid Login must be provided" : "Należy podać poprawny login", "Login contains whitespace at the beginning or at the end" : "Login zawiera spacje na początku lub na końcu", "Login must not consist of dots only" : "Login nie może składać się wyłącznie z kropek", + "Username is too long" : "Nazwa użytkownika jest zbyt długa", "Login is invalid because files already exist for this user" : "Login jest nieprawidłowy, ponieważ dla tego użytkownika istnieją już pliki", "Account disabled" : "Konto wyłączone", "Login canceled by app" : "Logowanie anulowane przez aplikację", @@ -269,6 +311,7 @@ "Your data directory must be an absolute path." : "Katalog danych musi mieć ścieżkę absolutną.", "Check the value of \"datadirectory\" in your configuration." : "Sprawdź wartość \"datadirectory\" w swojej konfiguracji.", "Your data directory is invalid." : "Katalog danych jest nieprawidłowy.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Upewnij się, że w katalogu głównym danych znajduje się plik o nazwie \"%1$s\". Powinien on zawierać: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Akcja \"%s\" jest niewspierana lub niezaimplementowana.", "Authentication failed, wrong token or provider ID given" : "Uwierzytelnienie nie powiodło się, podano nieprawidłowy token lub ID dostawcy", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Brak parametrów w celu uzupełnienia żądania. Brakujące parametry: \"%s\"", @@ -280,26 +323,114 @@ "Storage connection error. %s" : "Błąd połączenia z magazynem. %s", "Storage is temporarily not available" : "Magazyn jest tymczasowo niedostępny", "Storage connection timeout. %s" : "Limit czasu połączenia do magazynu. %s", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Aby umożliwić wykonanie tego sprawdzenia, upewnij się, że serwer WWW może połączyć się sam ze sobą. Musi on być w stanie rozpoznać i połączyć się przynajmniej z jedną z wartości 'trusted_domains' lub 'overwrite.cli.url'. Błąd ten może być wynikiem niezgodności DNS po stronie serwera lub reguły zapory sieciowej wychodzącej.", "Transcribe audio" : "Transkrypcja dźwięku", "Transcribe the things said in an audio" : "Transkrypcja wypowiedzi w formie audio", "Audio input" : "Wejście dźwięku", "The audio to transcribe" : "Dźwięk do transkrypcji", "Transcription" : "Transkrypcja", "The transcribed text" : "Tekst transkrypcji", + "Chat with an agent" : "Czat z agentem", + "Chat message" : "Wiadomość czatu", + "A chat message to send to the agent." : "Wiadomość czatu do wysłania do agenta.", "Confirmation" : "Potwierdzenie", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Czy potwierdzić wcześniej żądane działania: 0 — odmowa, 1 — potwierdzenie.", + "Conversation token" : "Token konwersacji", + "A token representing the conversation." : "Token reprezentujący konwersację.", + "Generated response" : "Wygenerowana odpowiedź", + "The response from the chat model." : "Odpowiedź z modelu czatu.", + "The new conversation token" : "Nowy token konwersacji", + "Send this along with the next interaction." : "Wyślij to razem z następną interakcją.", + "Requested actions by the agent" : "Żądane działania agenta", + "Actions that the agent would like to carry out in JSON format." : "Działania, które agent chciałby wykonać w formacie JSON.", + "Context write" : "Zapis kontekstu", + "Writes text in a given style based on the provided source material." : "Tworzy tekst w określonym stylu na podstawie dostarczonego materiału źródłowego.", "Writing style" : "Styl pisania", + "Demonstrate a writing style that you would like to immitate" : "Zaprezentuj styl pisania, który chciałbyś naśladować", "Source material" : "Materiał źródłowy", + "The content that would like to be rewritten in the new writing style" : "Treść, która ma zostać przepisana w nowym stylu pisania", + "Generated text" : "Wygenerowany tekst", + "The generated text with content from the source material in the given style" : "Wygenerowany tekst z treścią z materiału źródłowego w określonym stylu", + "Emoji generator" : "Generator emoji", + "Takes text and generates a representative emoji for it." : "Przyjmuje tekst i generuje pasującą emoji.", + "The text to generate an emoji for" : "Tekst, dla którego ma zostać wygenerowana emoji", + "Generated emoji" : "Wygenerowane emoji", + "The generated emoji based on the input text" : "Wygenerowana emoji na podstawie wprowadzonego tekstu", + "Generate image" : "Generuj obraz", + "Generate an image from a text prompt" : "Wygeneruj obraz z opisu tekstowego", + "Prompt" : "Polecenie", "Describe the image you want to generate" : "Opisz obraz, który chcesz wygenerować", "Number of images" : "Liczba obrazów", "How many images to generate" : "Ile obrazów wygenerować", "Output images" : "Obrazy wyjściowe", "The generated images" : "Wygenerowane obrazy", + "Generate speech" : "Generuj mowę", + "Generate speech from a transcript" : "Wygeneruj mowę z transkryptu", + "Write transcript that you want the assistant to generate speech from" : "Napisz transkrypt, na podstawie którego asystent ma wygenerować mowę", + "Output speech" : "Wygenerowana mowa", + "The generated speech" : "Wygenerowana mowa", + "Free text to text prompt" : "Dowolny tekst jako polecenie wejściowe", + "Runs an arbitrary prompt through a language model that returns a reply" : "Przetwarza dowolne polecenie za pomocą modelu językowego, który zwraca odpowiedź", + "Describe a task that you want the assistant to do or ask a question" : "Opisz zadanie, które ma wykonać asystent, lub zadaj pytanie", + "Generated reply" : "Wygenerowana odpowiedź", + "The generated text from the assistant" : "Wygenerowany tekst od asystenta", + "Change Tone" : "Zmień ton wypowiedzi", + "Change the tone of a piece of text." : "Zmień ton fragmentu tekstu", + "Write a text that you want the assistant to rewrite in another tone." : "Napisz tekst, który chcesz, aby asystent napisał inaczej.", + "Desired tone" : "Pożądany ton wypowiedzi", + "In which tone should your text be rewritten?" : "W jakim tonie powinien zostać napisany Twój tekst?", + "The rewritten text in the desired tone, written by the assistant:" : "Przepisany tekst w pożądanym tonie, napisany przez asystenta:", "Chat" : "Rozmowa", + "Chat with the assistant" : "Czat z asystentem", + "System prompt" : "Polecenie systemowe", + "Define rules and assumptions that the assistant should follow during the conversation." : "Określ zasady i założenia, których asystent powinien przestrzegać podczas rozmowy", "Chat history" : "Historia rozmów", + "The history of chat messages before the current message, starting with a message by the user" : "Historia wiadomości czatu przed bieżącą wiadomością, zaczynając od wiadomości użytkownika", + "Response message" : "Wiadomość odpowiedzi", + "The generated response as part of the conversation" : "Wygenerowana odpowiedź jako część rozmowy", + "Chat with tools" : "Czat z użyciem narzędzi", + "Chat with the language model with tool calling support." : "Czat z modelem językowym z obsługą wywoływania narzędzi", + "Tool message" : "Wiadomość narzędzia", + "The result of tool calls in the last interaction" : "Wynik wywołań narzędzi w ostatniej interakcji", + "Available tools" : "Dostępne narzędzia", + "The available tools in JSON format" : "Dostępne narzędzia w formacie JSON", + "The response from the chat model" : "Odpowiedź z modelu czatu", + "Tool calls" : "Wywołania narzędzi", + "Tools call instructions from the model in JSON format" : "Instrukcje wywołań narzędzi z modelu w formacie JSON", + "Formalize text" : "Sformalizuj tekst", + "Takes a text and makes it sound more formal" : "Pobiera tekst i sprawia, że brzmi bardziej formalnie", + "Write a text that you want the assistant to formalize" : "Napisz tekst, który chcesz, aby asystent sformalizował", + "Formalized text" : "Sformalizowany tekst", + "The formalized text" : "Sformalizowany tekst", + "Generate a headline" : "Wygeneruj nagłówek", "Generates a possible headline for a text." : "Generuje możliwy nagłówek tekstu.", + "Original text" : "Tekst oryginalny", + "The original text to generate a headline for" : "Oryginalny tekst, do którego ma zostać wygenerowany nagłówek", + "The generated headline" : "Wygenerowany nagłówek", + "Proofread" : "Korekta", + "Proofreads a text and lists corrections" : "Sprawdza tekst i podaje poprawki", + "Text" : "Tekst", + "The text to proofread" : "Tekst do korekty", + "Corrections" : "Poprawki", + "The corrections that should be made in your text" : "Poprawki, które należy wprowadzić w Twoim tekście", + "Reformulate text" : "Przekształć tekst", + "Takes a text and reformulates it" : "Pobiera tekst i przekształca go", + "Write a text that you want the assistant to reformulate" : "Napisz tekst, który chcesz, aby asystent przekształcił", + "Reformulated text" : "Przekształcony tekst", + "The reformulated text, written by the assistant" : "Przekształcony tekst napisany przez asystenta", + "Simplify text" : "Uprość tekst", + "Takes a text and simplifies it" : "Pobiera tekst i upraszcza go", + "Write a text that you want the assistant to simplify" : "Napisz tekst, który chcesz, aby asystent uprościł", + "Simplified text" : "Uproszczony tekst", + "The simplified text" : "Uproszczony tekst", "Summarize" : "Podsumuj", + "Summarizes a text" : "Tworzy podsumowanie tekstu", + "The original text to summarize" : "Oryginalny tekst do podsumowania", "Summary" : "Podsumowanie", + "The generated summary" : "Wygenerowane podsumowanie", "Extract topics" : "Wyodrębnij tematy", + "Extracts topics from a text and outputs them separated by commas" : "Wydobywa tematy z tekstu i zwraca je oddzielone przecinkami", + "The original text to extract topics from" : "Oryginalny tekst, z którego mają zostać wydobyte tematy", "Topics" : "Tematy", "The list of extracted topics" : "Lista wyodrębnionych tematów", "Translate" : "Tłumaczenie", @@ -317,41 +448,9 @@ "Generate headline" : "Wygeneruj nagłówek", "Summarizes text by reducing its length without losing key information." : "Podsumowuje tekst, zmniejszając jego długość bez utraty kluczowych informacji.", "Extracts topics from a text and outputs them separated by commas." : "Wyodrębnia tematy z tekstu i wyświetla je oddzielone przecinkami.", - "Education Edition" : "Edycja edukacyjna", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Zalogowany użytkownik musi być administratorem, subadministratorem lub mieć specjalne uprawnienia dostępu do tego ustawienia", - "Logged in user must be an admin or sub admin" : "Zalogowany użytkownik musi być administratorem lub współadministratorem", - "Logged in user must be an admin" : "Zalogowany użytkownik musi być administratorem", - "File name is a reserved word" : "Nazwa pliku jest zarezerwowana", - "File name contains at least one invalid character" : "Nazwa pliku zawiera co najmniej jeden nieprawidłowy znak", - "File name is too long" : "Nazwa pliku jest za długa", - "Help" : "Pomoc", - "Users" : "Użytkownicy", - "Unknown user" : "Nieznany użytkownik", - "Enter the database username and name for %s" : "Podaj nazwę użytkownika i nazwę bazy danych dla %s", - "Enter the database username for %s" : "Podaj nazwę użytkownika bazy danych dla %s", - "MySQL username and/or password not valid" : "Błędna nazwa użytkownika i/lub hasło do bazy danych MySQL", - "Oracle username and/or password not valid" : "Zła nazwa użytkownika i/lub hasło do bazy danych Oracle", - "PostgreSQL username and/or password not valid" : "Zła nazwa użytkownika i/lub hasło do bazy danych PostgreSQL", - "Set an admin username." : "Ustaw nazwę administratora.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s udostępnił Tobie »%2$s« i chce dodać: ", - "%1$s shared »%2$s« with you and wants to add" : " %1$s udostępnił Tobie »%2$s« i chce dodać", - "»%s« added a note to a file shared with you" : "»%s« dodał notatkę do udostępnionego dla Ciebie pliku", - "Open »%s«" : "Otwórz »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Udostępnianie %s nie powiodło się, ponieważ element jest już udostępniony użytkownikowi %s", - "%1$s shared »%2$s« with you" : "%1$s udostępnił Tobie »%2$s«", - "%1$s shared »%2$s« with you." : "%1$s udostępnił Tobie »%2$s«.", - "The username is already being used" : "Ta nazwa użytkownika jest już używana", - "Could not create user" : "Nie można utworzyć użytkownika", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "W nazwie użytkownika dozwolone są tylko następujące znaki : \"a-z\", \"A-Z\", \"0-9\", spacje i \"_.@-'\"", - "A valid username must be provided" : "Należy podać prawidłową nazwę użytkownika", - "Username contains whitespace at the beginning or at the end" : "Nazwa użytkownika zawiera spację na początku albo na końcu", - "Username must not consist of dots only" : "Nazwa użytkownika nie może się składać tylko z kropek", - "Username is invalid because files already exist for this user" : "Nazwa użytkownika jest nieprawidłowa, ponieważ pliki już istnieją dla tego użytkownika", - "User disabled" : "Użytkownik zablokowany", + "Organisation" : "Organizacja", "File is currently busy, please try again later" : "Plik jest obecnie niedostępny, spróbuj później", "Cannot download file" : "Nie można pobrać pliku", - "Your data directory is readable by other users." : "Twój katalog danych jest widoczny dla innych użytkowników.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Zmień uprawnienia na 0770, aby katalog nie był widoczny dla innych użytkowników.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Upewnij się, że w katalogu \"data\" znajduje się plik o nazwie \".ocdata\"." + "Login is too long" : "Login jest zbyt długi" },"pluralForm" :"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);" }
\ No newline at end of file diff --git a/lib/l10n/ps.js b/lib/l10n/ps.js index 869fe674bf5..8a92f63f40e 100644 --- a/lib/l10n/ps.js +++ b/lib/l10n/ps.js @@ -7,8 +7,6 @@ OC.L10N.register( "Files" : "فایلونه", "Apps" : "اپلېکشنونه", "Settings" : "سمونې", - "Storage is temporarily not available" : "ذخیره د لنډې مودې لپاره نشته", - "Help" : "مرسته", - "Users" : "کارنان" + "Storage is temporarily not available" : "ذخیره د لنډې مودې لپاره نشته" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/ps.json b/lib/l10n/ps.json index 479bab99040..2a4c66c3e43 100644 --- a/lib/l10n/ps.json +++ b/lib/l10n/ps.json @@ -5,8 +5,6 @@ "Files" : "فایلونه", "Apps" : "اپلېکشنونه", "Settings" : "سمونې", - "Storage is temporarily not available" : "ذخیره د لنډې مودې لپاره نشته", - "Help" : "مرسته", - "Users" : "کارنان" + "Storage is temporarily not available" : "ذخیره د لنډې مودې لپاره نشته" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/pt_BR.js b/lib/l10n/pt_BR.js index 3342a6467ef..e4759d1262f 100644 --- a/lib/l10n/pt_BR.js +++ b/lib/l10n/pt_BR.js @@ -2,29 +2,29 @@ OC.L10N.register( "lib", { "Cannot write into \"config\" directory!" : "Não é possível gravar no diretório \"config\"!", - "This can usually be fixed by giving the web server write access to the config directory." : "Isso geralmente pode ser corrigido dando ao servidor web acesso de gravação ao diretório de configuração.", + "This can usually be fixed by giving the web server write access to the config directory." : "Geralmente, isso pode ser corrigido dando ao servidor web acesso de gravação ao diretório de configuração.", "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Mas, se você preferir manter o arquivo config.php somente para leitura, defina a opção \"config_is_read_only\" como true nele. ", "See %s" : "Ver %s", - "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Aplicação %1$s não está presente ou possui uma versão não compatível com este servidor. Verifique o diretório de aplicativos.", + "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "O aplicativo %1$s não está presente ou tem uma versão não compatível com este servidor. Verifique o diretório de aplicativos.", "Sample configuration detected" : "Configuração de exemplo detectada", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Foi detectado que a configuração de exemplo foi copiada. Isso pode terminar sua instalação e não é suportado. Por favor leia a documentação antes de realizar mudanças no config.php", "The page could not be found on the server." : "A página não pôde ser encontrada no servidor.", - "%s email verification" : "%s e-mail de verificação", - "Email verification" : "E-mail de verificação", - "Click the following button to confirm your email." : "Clique no botão a seguir para confirmar seu e-mail.", - "Click the following link to confirm your email." : "Clique no link a seguir para confirmar seu e-mail.", - "Confirm your email" : "Confirme seu e-mail", + "%s email verification" : "Verificação de e-mail de %s", + "Email verification" : "Verificação do endereço de e-mail", + "Click the following button to confirm your email." : "Clique no botão a seguir para confirmar seu endereço de e-mail.", + "Click the following link to confirm your email." : "Clique no link a seguir para confirmar seu endereço de e-mail.", + "Confirm your email" : "Confirmar seu e-mail", "Other activities" : "Outras atividades", "%1$s and %2$s" : "%1$s e %2$s", "%1$s, %2$s and %3$s" : "%1$s, %2$s e %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s e %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s e %5$s", - "Education bundle" : "Pacote educacional", - "Enterprise bundle" : "Pacote Enterprise", + "Education bundle" : "Pacote Educação", + "Enterprise bundle" : "Pacote Empresarial", "Groupware bundle" : "Pacote Groupware", - "Hub bundle" : "Pacote de hub", - "Public sector bundle" : "Pacote do setor público", - "Social sharing bundle" : "Pacote de compartilhamento social", + "Hub bundle" : "Pacote Hub", + "Public sector bundle" : "Pacote Setor Público", + "Social sharing bundle" : "Pacote Compartilhamento Social", "PHP %s or higher is required." : "PHP %s ou superior é necessário.", "PHP with a version lower than %s is required." : "É necessária uma versão PHP mais antiga que a %s.", "%sbit or higher PHP required." : "%sbit ou PHP maior é requerido.", @@ -37,10 +37,10 @@ OC.L10N.register( "The following platforms are supported: %s" : "As seguintes plataformas são suportadas: %s", "Server version %s or higher is required." : "É requerido um servidor da versão %s ou superior.", "Server version %s or lower is required." : "É requerido um servidor da versão %s ou abaixo.", - "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "A conta conectada deve ser um administrador, um subadministrador ou ter direito especial para acessar esta configuração", - "Your current IP address doesn’t allow you to perform admin actions" : "Seu endereço IP atual não permite que você execute ações administrativas", - "Logged in account must be an admin or sub admin" : "A conta conectada deve ser de um administrador ou subadministrador", - "Logged in account must be an admin" : "A conta logada deve ser de um administrador", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "A conta logada deve ser um administrador, um subadministrador ou ter direito especial para acessar esta configuração", + "Your current IP address doesn't allow you to perform admin actions" : "Seu endereço IP atual não permite que você execute ações administrativas", + "Logged in account must be an admin or sub admin" : "A conta logada deve ser um administrador ou subadministrador", + "Logged in account must be an admin" : "A conta logada deve ser um administrador", "Wiping of device %s has started" : "Limpeza do dispositivo %s iniciou", "Wiping of device »%s« has started" : "A limpeza do dispositivo »%s« terminou", "»%s« started remote wipe" : "»%s« iniciou a limpeza remota", @@ -59,7 +59,12 @@ OC.L10N.register( "Avatar image is not square" : "A imagem do avatar não é quadrada", "Files" : "Arquivos", "View profile" : "Visualizar perfil", - "Local time: %s" : "Hora local: %s", + "same time" : "mesmo horário", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm"], + "%s ahead" : "%s à frente", + "%s behind" : "%s atrás", + "Local time: %s" : "Horário local: %s", "today" : "hoje", "tomorrow" : "amanhã", "yesterday" : "ontem", @@ -68,30 +73,45 @@ OC.L10N.register( "next month" : "Mês que vem", "last month" : "último mês", "_in %n month_::_in %n months_" : ["em %n mês","em %n meses","em %n meses"], - "_%n month ago_::_%n months ago_" : ["há %n mês atrás","há %n meses","há %n meses"], - "next year" : "ano que vem", + "_%n month ago_::_%n months ago_" : ["%n mês atrás","%n meses atrás","%n meses atrás"], + "next year" : "próximo ano", "last year" : "último ano", "_in %n year_::_in %n years_" : ["em %n ano","em %n anos","em %n anos"], "_%n year ago_::_%n years ago_" : ["%n ano atrás","%n anos atrás","%n anos atrás"], "_in %n hour_::_in %n hours_" : ["em %n hora","em %n horas","em %n horas"], - "_%n hour ago_::_%n hours ago_" : ["há %n hora atrás","há %n horas","há %n horas"], + "_%n hour ago_::_%n hours ago_" : ["%n hora atrás","%n horas atrás","%n horas atrás"], "_in %n minute_::_in %n minutes_" : ["em %n minuto","em %n minutos","em %n minutos"], - "_%n minute ago_::_%n minutes ago_" : ["há %n minuto atrás","há %n minutos","há %n minutos"], + "_%n minute ago_::_%n minutes ago_" : ["%n minuto atrás","%n minutos atrás","%n minutos atrás"], "in a few seconds" : "Em alguns segundos", "seconds ago" : "segundos atrás", "Empty file" : "Arquivo vazio", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "O módulo com a ID: %s não existe. Por favor, habilite-o nas configurações de seu aplicativo ou contacte o administrador.", + "No file conversion providers available" : "Não há provedores de conversão de arquivos disponíveis", + "File is too large to convert" : "O arquivo é muito grande para converter", + "Destination does not match conversion extension" : "O destino não corresponde à extensão de conversão", + "Could not convert file" : "Não foi possível converter o arquivo", + "Destination does not exist" : "Destino não existe", + "Destination is not creatable" : "Destino não pode ser criado", "Dot files are not allowed" : "Arquivos Dot não são permitidos", + "%1$s (renamed)" : "%1$s (renomeado)", + "renamed file" : "arquivo renomeado", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" é um nome de arquivo ou pasta proibido.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" é um prefixo proibido para nomes de arquivos ou pastas.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" não é permitido dentro de um nome de arquivo ou pasta.", "\"%1$s\" is a forbidden file type." : "\"%1$s\" é um tipo de arquivo proibido.", "Filenames must not end with \"%1$s\"." : "Os nomes dos arquivos não devem terminar com \"%1$s\".", - "Invalid parent path" : "Caminho mãe inválido", + "Invalid parent path" : "Caminho pai inválido", "File already exists" : "O arquivo já existe", - "Invalid path" : "Diretório inválido", - "Failed to create file from template" : "Falha ao criar arquivo do modelo ", + "Invalid path" : "Caminho inválido", + "Failed to create file from template" : "Falha ao criar arquivo a partir do modelo", "Templates" : "Modelos ", + "Storage %s cannot be moved" : "O armazenamento %s não pode ser movido", + "Moving a share (%s) into a shared folder is not allowed" : "Não é permitido mover um compartilhamento (%s) para uma pasta compartilhada", + "Moving a storage (%s) into a shared folder is not allowed" : "Não é permitido mover um armazenamento (%s) para uma pasta compartilhada", + "Moving a share (%s) into another share (%s) is not allowed" : "Não é permitido mover um compartilhamento (%s) para outro compartilhamento (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "Não é permitido mover um compartilhamento (%s) para outro armazenamento (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "Não é permitido mover um armazenamento (%s) para um compartilhamento (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Não é permitido mover um armazenamento (%s) para outro armazenamento (%s)", "Path contains invalid segments" : "O caminho contém segmentos inválidos", "Filename is a reserved word" : "Nome do arquivo é uma palavra reservada", "Filename contains at least one invalid character" : "O nome do arquivo contém pelo menos um caractere inválido ", @@ -110,35 +130,35 @@ OC.L10N.register( "Log out" : "Sair", "Accounts" : "Contas", "Email" : "E-mail", - "Mail %s" : "E-Mail %s", - "Fediverse" : "Fediverse", - "View %s on the fediverse" : "Ver %s no fediverse", + "Mail %s" : "Enviar e-mail para %s", + "Fediverse" : "Fediverso", + "View %s on the fediverse" : "Ver %s no fediverso", "Phone" : "Fone", - "Call %s" : "Chamar %s", + "Call %s" : "Ligar para %s", "Twitter" : "Twitter", - "View %s on Twitter" : "Visualizar %s no Twitter", - "Website" : "Website", + "View %s on Twitter" : "Ver %s no Twitter", + "Website" : "Site", "Visit %s" : "Visitar %s", "Address" : "Endereço", "Profile picture" : "Foto do perfil", "About" : "Sobre", "Display name" : "Nome de exibição", - "Headline" : "Título ", - "Organisation" : "Organização", + "Headline" : "Título", + "Organization" : "Organização", "Role" : "Função", "Pronouns" : "Pronomes", "Unknown account" : "Conta desconhecida", "Additional settings" : "Configurações adicionais", "Enter the database Login and name for %s" : "Insira o login e o nome do banco de dados para %s", "Enter the database Login for %s" : "Insira o login do banco de dados para %s", - "Enter the database name for %s" : "Digite o nome do banco de dados para %s", + "Enter the database name for %s" : "Insira o nome do banco de dados para %s", "You cannot use dots in the database name %s" : "Você não pode usar pontos no nome do banco de dados %s", "MySQL Login and/or password not valid" : "Login e/ou senha do MySQL inválidos", "You need to enter details of an existing account." : "Você necessita entrar detalhes de uma conta existente.", "Oracle connection could not be established" : "Conexão Oracle não pôde ser estabelecida", - "Oracle Login and/or password not valid" : "Login e/ou senha Oracle inválidos", + "Oracle Login and/or password not valid" : "Login e/ou senha do Oracle inválidos", "PostgreSQL Login and/or password not valid" : "Login e/ou senha do PostgreSQL inválidos", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X não é suportado e %s não funcionará corretamente nesta plataforma. Use-o por sua conta e risco!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "O Mac OS X não é compatível e %s não funcionará corretamente nessa plataforma. Use-o por sua própria conta e risco!", "For the best results, please consider using a GNU/Linux server instead." : "Para obter melhores resultados, por favor considere o uso de um servidor GNU/Linux em seu lugar.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Aparentemente a instância %s está rodando em um ambiente PHP de 32 bits e o open_basedir foi configurado no php.ini. Isto pode gerar problemas com arquivos maiores que 4GB e é altamente não recomendável.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, remova a configuração de open_basedir de seu php.ini ou mude o PHP para 64bit.", @@ -149,41 +169,41 @@ OC.L10N.register( "Sharing backend %s not found" : "Plataforma de serviço de compartilhamento %s não encontrada", "Sharing backend for %s not found" : "Plataforma de compartilhamento para %s não foi encontrada", "%1$s shared %2$s with you" : "%1$s compartilhou %2$s com você", - "Click the button below to open it." : "Clique no botão abaixo para abri-lo.", "Open %s" : "Abrir %s", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s compartilhou %2$s com você e deseja adicionar:", "%1$s shared %2$s with you and wants to add" : "%1$s compartilhou %2$s com você e deseja adicionar", "%s added a note to a file shared with you" : "%s adicionou uma nota a um arquivo compartilhado com você", - "Passwords are enforced for link and mail shares" : "As senhas são aplicadas para compartilhamentos de links e e-mails", + "Passwords are enforced for link and mail shares" : "As senhas são obrigatórias para compartilhamentos de links e e-mails", "Share recipient is not a valid user" : "O destinatário do compartilhamento não é um usuário válido", "Share recipient is not a valid group" : "O destinatário do compartilhamento não é um grupo válido", - "Share recipient should be empty" : "O destinatário do compartilhamento pode estar vazio", - "Share recipient should not be empty" : "O destinatário do compartilhamento não pode estar vazio", + "Share recipient should be empty" : "O destinatário do compartilhamento deve estar vazio", + "Share recipient should not be empty" : "O destinatário do compartilhamento não deve estar vazio", "Share recipient is not a valid circle" : "O destinatário do compartilhamento não é um círculo válido", "Unknown share type" : "Tipo de compartilhamento desconhecido", "Share initiator must be set" : "O iniciador de compartilhamento deve estar definido", "Cannot share with yourself" : "Não é possível compartilhar consigo mesmo", "Shared path must be set" : "O caminho do compartilhamento deve estar definido", - "Shared path must be either a file or a folder" : "O caminho do compartilhamento deve ser um arquivo ou uma pasta", + "Shared path must be either a file or a folder" : "O caminho do compartilhamento deve ser ou um arquivo ou uma pasta", "You cannot share your root folder" : "Você não pode compartilhar sua pasta raiz", "You are not allowed to share %s" : "Você não tem permissão para compartilhar %s", "Valid permissions are required for sharing" : "Permissões válidas são necessárias para compartilhamento", + "File shares cannot have create or delete permissions" : "Os compartilhamentos de arquivos não podem ter permissões de criação ou exclusão", "Cannot increase permissions of %s" : "Não foi possível aumentar as permissões de %s", "Shares need at least read permissions" : "Compartilhamentos precisam pelo menos permissões de leitura", "Files cannot be shared with delete permissions" : "Arquivos não podem ser compartilhados com permissões de exclusão", "Files cannot be shared with create permissions" : "Arquivos não podem ser compartilhados com permissões de criação", "Expiration date is in the past" : "Data de expiração está no passado", "Expiration date is enforced" : "A data de expiração é aplicada", - "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Não foi possível definir a data de expiração superior que %n dias no futuro","Não foi possível definir a data de expiração superior que %n dias no futuro","Não foi possível definir a data de expiração superior que %n dias no futuro"], + "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Não é possível definir a data de expiração para mais de %n dia no futuro","Não é possível definir a data de expiração para mais de %n dias no futuro","Não é possível definir a data de expiração para mais de %n dias no futuro"], "Sharing is only allowed with group members" : "O compartilhamento só é permitido com membros do grupo ", - "Sharing %s failed, because this item is already shared with the account %s" : "Falha no compartilhamento %s porque este item já está compartilhado com a conta %s", + "Sharing %s failed, because this item is already shared with the account %s" : "O compartilhamento do %s falhou, porque esse item já está compartilhado com a conta %s", "Group sharing is now allowed" : "O compartilhamento em grupo é permitido agora", "Sharing is only allowed within your own groups" : "O compartilhamento só é permitido dentro de seus próprios grupos", "Path is already shared with this group" : "O caminho já está compartilhado com este grupo", - "Link sharing is not allowed" : "O compartilhamento de link não é permitido", + "Link sharing is not allowed" : "O compartilhamento de links não é permitido", "Public upload is not allowed" : "O upload público não é permitido", - "Path contains files shared with you" : "O caminho contém arquivos compartilhados com você", + "You cannot share a folder that contains other shares" : "Você não pode compartilhar uma pasta que contém outros compartilhamentos", "Sharing is disabled" : "O compartilhamento está desativado", "Sharing is disabled for you" : "O compartilhamento está desativado para você", "Cannot share with the share owner" : "Não é possível compartilhar com o proprietário do compartilhamento", @@ -201,7 +221,7 @@ OC.L10N.register( "The requested share comes from a disabled user" : "O compartilhamento solicitado vem de um usuário desabilitado", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "O usuário não foi criado porque o limite de usuários foi atingido. Confira suas notificações para saber mais.", "Could not find category \"%s\"" : "Impossível localizar a categoria \"%s\"", - "Input text" : "Entrada de texto", + "Input text" : "Texto de entrada", "The input text" : "O texto de entrada", "Sunday" : "Domingo", "Monday" : "Segunda-feira", @@ -252,9 +272,10 @@ OC.L10N.register( "The Login is already being used" : "O Login já está sendo usado", "Could not create account" : "Não foi possível criar a conta", "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Somente os seguintes caracteres são permitidos em um Login: \"a-z\", \"A-Z\", \"0-9\", espaços e \"_.@-'\"", - "A valid Login must be provided" : "Um login válido deve ser fornecido", + "A valid Login must be provided" : "Um Login válido deve ser fornecido", "Login contains whitespace at the beginning or at the end" : "O login contém espaços em branco no início ou no final", - "Login must not consist of dots only" : "O login não deve consistir apenas em pontos", + "Login must not consist of dots only" : "O login não deve consistir apenas de pontos", + "Username is too long" : "O nome de usuário é muito longo", "Login is invalid because files already exist for this user" : "O login é inválido porque já existem arquivos para este usuário", "Account disabled" : "Conta desativada", "Login canceled by app" : "Login cancelado pelo aplicativo", @@ -265,27 +286,27 @@ OC.L10N.register( "Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.", "No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhum driver de banco de dados (sqlite, mysql ou postgresql) instalado.", "Cannot write into \"config\" directory." : "Não é possível gravar no diretório \"config\".", - "This can usually be fixed by giving the web server write access to the config directory. See %s" : "Isso geralmente pode ser corrigido dando ao servidor web acesso de gravação ao diretório de configuração. Ver %s", + "This can usually be fixed by giving the web server write access to the config directory. See %s" : "Geralmente, isso pode ser corrigido dando ao servidor web acesso de gravação ao diretório de configuração. Consulte %s", "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Ou, se você preferir manter o arquivo config.php somente para leitura, defina a opção \"config_is_read_only\" como true. Veja %s", "Cannot write into \"apps\" directory." : "Não é possível gravar no diretório \"apps\".", - "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Isso geralmente pode ser corrigido dando ao servidor web acesso de gravação ao diretório de aplicativos ou desabilitando a App Store no arquivo de configuração.", - "Cannot create \"data\" directory." : "Não é possível criar o diretório \"dados\".", - "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Isso geralmente pode ser corrigido dando ao servidor web acesso de gravação ao diretório raiz. Ver %s", - "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "As permissões geralmente podem ser corrigidas dando ao servidor web acesso de gravação ao diretório raiz. Ver %s.", + "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Geralmente, isso pode ser corrigido dando ao servidor web acesso de gravação ao diretório de aplicativos ou desabilitando a Loja de Aplicativos no arquivo de configuração.", + "Cannot create \"data\" directory." : "Não é possível criar o diretório \"data\".", + "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Geralmente, isso pode ser corrigido dando ao servidor web acesso de gravação ao diretório raiz. Consulte %s", + "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Geralmente, as permissões podem ser corrigidas dando ao servidor web acesso de gravação ao diretório raiz. Consulte %s.", "Your data directory is not writable." : "Seu diretório de dados não é gravável.", - "Setting locale to %s failed." : "Falha ao definir a localidade para %s .", - "Please install one of these locales on your system and restart your web server." : "Instale um dessas localidades em seu sistema e reinicie seu servidor web.", + "Setting locale to %s failed." : "Falha ao definir a configuração regional para %s.", + "Please install one of these locales on your system and restart your web server." : "Por favor, instale uma dessas configurações regionais em seu sistema e reinicie seu servidor web.", "PHP module %s not installed." : "Módulo PHP %s não instalado.", "Please ask your server administrator to install the module." : "Por favor, peça ao seu administrador do servidor para instalar o módulo.", "PHP setting \"%s\" is not set to \"%s\"." : "Configuração PHP \"%s\" não está configurado para \"%s\".", "Adjusting this setting in php.ini will make Nextcloud run again" : "Ajustar a configuração no php.ini fará com que o Nextcloud execute novamente", "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> está configurado para <code>%s</code> em vez do valor esperado <code>0</code>.", - "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Para corrigir este conjunto de problemas <code>mbstring.func_overload</code> para <code>0</code> no seu php.ini.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Para corrigir esse problema, defina <code>mbstring.func_overload</code> como <code>0</code> em seu php.ini.", "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP aparentemente está configurado para retirar blocos doc inline. Isso fará com que vários aplicativos do núcleo fiquem inacessíveis.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Isso provavelmente é causado por um cache/acelerador, como Zend OPcache ou eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "Módulos do PHP foram instalados, mas eles ainda estão listados como faltantes?", "Please ask your server administrator to restart the web server." : "Por favor peça ao administrador do servidor para reiniciar o servidor web.", - "The required %s config variable is not configured in the config.php file." : "A variável %s de configuração necessária não está configurada no arquivo config.php.", + "The required %s config variable is not configured in the config.php file." : "A variável de configuração %s obrigatória não está configurada no arquivo config.php.", "Please ask your server administrator to check the Nextcloud configuration." : "Peça ao administrador do servidor para verificar a configuração do Nextcloud.", "Your data directory is readable by other people." : "Seu diretório de dados pode ser lido por outras pessoas.", "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Altere as permissões para 0770 para que o diretório não possa ser listado por outras pessoas.", @@ -304,16 +325,27 @@ OC.L10N.register( "Storage connection error. %s" : "Erro na conexão de armazenamento. %s", "Storage is temporarily not available" : "Armazenamento temporariamente indisponível", "Storage connection timeout. %s" : "Atingido o tempo limite de conexão ao armazenamento. %s", - "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Para permitir que esta verificação seja executada, você deve certificar-se de que seu servidor Web pode se conectar a si mesmo. Portanto, ele deve ser capaz de resolver e conectar-se a pelo menos um de seus `trusted_domains` ou `overwrite.cli.url`. Essa falha pode ser o resultado de uma incompatibilidade de DNS no servidor ou de uma regra de firewall de saída.", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Para permitir que esta verificação seja executada, você deve certificar-se de que seu servidor web pode se conectar a si mesmo. Portanto, ele deve ser capaz de resolver e conectar a pelo menos um de seus `trusted_domains` ou `overwrite.cli.url`. Esta falha pode ser o resultado de uma incompatibilidade de DNS no servidor ou de uma regra de firewall de saída.", "Transcribe audio" : "Transcrever áudio", - "Transcribe the things said in an audio" : "Transcreva as coisas ditas em um áudio", + "Transcribe the things said in an audio" : "Transcrever o que foi dito em um áudio", "Audio input" : "Entrada de áudio", "The audio to transcribe" : "O áudio a ser transcrito", "Transcription" : "Transcrição", "The transcribed text" : "O texto transcrito", + "Chat with an agent" : "Conversar com um agente", "Chat message" : "Mensagem de bate-papo", + "A chat message to send to the agent." : "Uma mensagem de bate-papo a ser enviada ao agente", "Confirmation" : "Confirmação", - "Context write" : "Gravação de contexto", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Se deve confirmar as ações solicitadas anteriormente: 0 para negação e 1 para confirmação.", + "Conversation token" : "Token de conversação", + "A token representing the conversation." : "Um token que representa a conversa.", + "Generated response" : "Resposta gerada", + "The response from the chat model." : "A resposta do modelo de bate-papo.", + "The new conversation token" : "O novo token de conversa", + "Send this along with the next interaction." : "Envie isso junto com a próxima interação.", + "Requested actions by the agent" : "Ações solicitadas pelo agente", + "Actions that the agent would like to carry out in JSON format." : "Ações que o agente gostaria de realizar no formato JSON.", + "Context write" : "Escrita contextual", "Writes text in a given style based on the provided source material." : "Escreve texto em um determinado estilo com base no material de origem fornecido.", "Writing style" : "Estilo de escrita", "Demonstrate a writing style that you would like to immitate" : "Demonstre um estilo de escrita que você gostaria de imitar", @@ -323,23 +355,34 @@ OC.L10N.register( "The generated text with content from the source material in the given style" : "O texto gerado com conteúdo do material de origem no estilo determinado", "Emoji generator" : "Gerador de emojis", "Takes text and generates a representative emoji for it." : "Pega texto e gera um emoji representativo para ele.", - "The text to generate an emoji for" : "O texto para gerar um emoji para", + "The text to generate an emoji for" : "O texto para o qual gerar um emoji", "Generated emoji" : "Emoji gerado", "The generated emoji based on the input text" : "O emoji gerado com base no texto de entrada", "Generate image" : "Gerar imagem", "Generate an image from a text prompt" : "Gere uma imagem a partir de um prompt de texto", - "Prompt" : "Pronto", + "Prompt" : "Prompt", "Describe the image you want to generate" : "Descreva a imagem que você deseja gerar", "Number of images" : "Número de imagens", - "How many images to generate" : "Quantas imagens gerar", + "How many images to generate" : "Quantas imagens devem ser geradas", "Output images" : "Imagens de saída", "The generated images" : "As imagens geradas", - "Free text to text prompt" : "Texto livre para prompt de texto", + "Generate speech" : "Gerar fala", + "Generate speech from a transcript" : "Gerar fala a partir de uma transcrição", + "Write transcript that you want the assistant to generate speech from" : "Escreva a transcrição a partir da qual você deseja que o assistente gere a fala", + "Output speech" : "Fala de saída", + "The generated speech" : "A fala gerada", + "Free text to text prompt" : "Prompt de texto livre para texto", "Runs an arbitrary prompt through a language model that returns a reply" : "Usa um modelo de linguagem para gerar uma resposta a partir de um prompt.", "Describe a task that you want the assistant to do or ask a question" : "Descreva uma tarefa que você deseja que o assistente execute ou faça uma pergunta", "Generated reply" : "Resposta gerada", "The generated text from the assistant" : "O texto gerado do assistente", - "Chat" : "Conversa", + "Change Tone" : "Mudar o tom", + "Change the tone of a piece of text." : "Alterar o tom de um texto.", + "Write a text that you want the assistant to rewrite in another tone." : "Escreva um texto que você deseja que o assistente reescreva em outro tom.", + "Desired tone" : "Tom desejado", + "In which tone should your text be rewritten?" : "Em qual tom seu texto deve ser reescrito?", + "The rewritten text in the desired tone, written by the assistant:" : "O texto reescrito no tom desejado, escrito pelo assistente:", + "Chat" : "Bate-papo", "Chat with the assistant" : "Converse com o assistente", "System prompt" : "Prompt do sistema", "Define rules and assumptions that the assistant should follow during the conversation." : "Defina regras e suposições que o assistente deve seguir durante a conversa.", @@ -347,86 +390,69 @@ OC.L10N.register( "The history of chat messages before the current message, starting with a message by the user" : "O histórico de mensagens de bate-papo antes da mensagem atual, começando com uma mensagem do usuário", "Response message" : "Mensagem de resposta", "The generated response as part of the conversation" : "A resposta gerada como parte da conversa", + "Chat with tools" : "Conversar com ferramentas", + "Chat with the language model with tool calling support." : "Converse com o modelo de linguagem com suporte a tool calling (\"chamadas a ferramentas\").", + "Tool message" : "Mensagem da ferramenta", + "The result of tool calls in the last interaction" : "O resultado das chamadas a ferramentas na última interação", + "Available tools" : "Ferramentas disponíveis", + "The available tools in JSON format" : "As ferramentas disponíveis em formato JSON", + "The response from the chat model" : "A resposta do modelo de bate-papo", + "Tool calls" : "Chamadas a ferramentas", + "Tools call instructions from the model in JSON format" : "Instruções para chamadas a ferramentas do modelo no formato JSON", "Formalize text" : "Formalizar texto", - "Takes a text and makes it sound more formal" : "Pega um texto e faz com que ele soe mais formal", + "Takes a text and makes it sound more formal" : "Pega um texto e o faz parecer mais formal", "Write a text that you want the assistant to formalize" : "Escreva um texto que você deseja que o assistente formalize", "Formalized text" : "Texto formalizado", "The formalized text" : "O texto formalizado", "Generate a headline" : "Gere um título", - "Generates a possible headline for a text." : "Gera um título possível para um texto.", + "Generates a possible headline for a text." : "Gera um possível título para um texto.", "Original text" : "Texto original", - "The original text to generate a headline for" : "O texto original para gerar um título para", + "The original text to generate a headline for" : "O texto original para gerar um título", "The generated headline" : "O título gerado", + "Proofread" : "Revisar", + "Proofreads a text and lists corrections" : "Revisa um texto e lista as correções", + "Text" : "Texto", + "The text to proofread" : "O texto a ser revisado", + "Corrections" : "Correções", + "The corrections that should be made in your text" : "As correções que devem ser feitas em seu texto", "Reformulate text" : "Reformular texto", "Takes a text and reformulates it" : "Pega um texto e o reformula", - "Write a text that you want the assistant to reformulate" : "Escrever um texto que você deseja que o assistente reformule", + "Write a text that you want the assistant to reformulate" : "Escreva um texto que você deseja que o assistente reformule", "Reformulated text" : "Texto reformulado", - "The reformulated text, written by the assistant" : "O texto reformulado, escrito pela assistente", + "The reformulated text, written by the assistant" : "O texto reformulado, escrito pelo assistente", "Simplify text" : "Simplificar texto", - "Takes a text and simplifies it" : "Pegar um texto e simplificar ", + "Takes a text and simplifies it" : "Pega um texto e o simplifica", "Write a text that you want the assistant to simplify" : "Escreva um texto que você deseja que o assistente simplifique", "Simplified text" : "Texto simplificado", "The simplified text" : "O texto simplificado", "Summarize" : "Resumir", - "Summarizes a text" : "Resumir um texto", + "Summarizes a text" : "Resume um texto", "The original text to summarize" : "O texto original para resumir", "Summary" : "Resumo", "The generated summary" : "O resumo gerado", - "Extract topics" : "Extrair tópicos", - "Extracts topics from a text and outputs them separated by commas" : "Extrai tópicos de um texto e os exibe separados por vírgulas", - "The original text to extract topics from" : "O texto original para extrair tópicos de", - "Topics" : "Tópicos", - "The list of extracted topics" : "A lista de tópicos extraídos", + "Extract topics" : "Extrair temas", + "Extracts topics from a text and outputs them separated by commas" : "Extrai temas de um texto e os exibe separados por vírgulas", + "The original text to extract topics from" : "O texto original do qual extrair temas", + "Topics" : "Temas", + "The list of extracted topics" : "A lista de temas extraídos", "Translate" : "Traduzir", - "Translate text from one language to another" : "Traduzir o texto de um idioma para outro", + "Translate text from one language to another" : "Traduzir um texto de um idioma para outro", "Origin text" : "Texto original", "The text to translate" : "O texto a ser traduzido", "Origin language" : "Idioma original", "The language of the origin text" : "O idioma do texto original", - "Target language" : "Target language", + "Target language" : "Idioma de destino", "The desired language to translate the origin text in" : "O idioma definido para traduzir o texto original", "Result" : "Resultado", "The translated text" : "O texto traduzido", - "Free prompt" : "Solicitação gratuita", - "Runs an arbitrary prompt through the language model." : "Executa um prompt arbitrário por meio do modelo de idioma.", + "Free prompt" : "Prompt livre", + "Runs an arbitrary prompt through the language model." : "Executa um prompt arbitrário por meio do modelo de linguagem.", "Generate headline" : "Gerar título", "Summarizes text by reducing its length without losing key information." : "Resume o texto reduzindo seu comprimento sem perder informações importantes.", - "Extracts topics from a text and outputs them separated by commas." : "Extrai tópicos de um texto e os gera separados por vírgulas.", - "Education Edition" : "Edição Educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "O usuário conectado deve ser um administrador, um subadministrador ou ter direito especial para acessar esta configuração", - "Logged in user must be an admin or sub admin" : "O usuário conectado deve ser um administrador ou subadministrador", - "Logged in user must be an admin" : "O usuário conectado deve ser um administrador", - "File name is a reserved word" : "O nome do arquivo é uma palavra reservada", - "File name contains at least one invalid character" : "O nome do arquivo contém pelo menos um caracter inválido", - "File name is too long" : "O nome do arquivo é muito longo", - "Help" : "Ajuda", - "Users" : "Usuários", - "Unknown user" : "Usuário desconhecido", - "Enter the database username and name for %s" : "Digite o nome de usuário e o nome do banco de dados para %s", - "Enter the database username for %s" : "Digite o nome de usuário do banco de dados para %s", - "MySQL username and/or password not valid" : "Nome de usuário e/ou senha do MySQL inválidos", - "Oracle username and/or password not valid" : "Nome de usuário e/ou senha Oracle inválidos", - "PostgreSQL username and/or password not valid" : "Nome de usuário e/ou senha PostgreSQL inválidos", - "Set an admin username." : "Defina um nome do usuário administrador.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartilhou »%2$s« com você e quer adicionar:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartilhou »%2$s« com você e quer adicionar", - "»%s« added a note to a file shared with you" : "»%s« adicionou uma anotação num arquivo compartilhado com você", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Compartilhamento %s falhou, porque este item já está compartilhado com o usuário %s", - "%1$s shared »%2$s« with you" : "%1$s compartilhou »%2$s« com você", - "%1$s shared »%2$s« with you." : "%1$s compartilhou »%2$s« com você.", - "The username is already being used" : "Este nome de usuário já está em uso", - "Could not create user" : "Não foi possível criar o usuário", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Apenas os seguintes caracteres são permitidos em um nome de usuário: \"a-z\", \"A-Z\", \"0-9\", espaços e \"_.@-'\"", - "A valid username must be provided" : "Um nome de usuário válido deve ser fornecido", - "Username contains whitespace at the beginning or at the end" : "O nome de usuário contém espaço em branco no início ou no fim", - "Username must not consist of dots only" : "Nome do usuário não pode consistir de pontos somente", - "Username is invalid because files already exist for this user" : "O nome de usuário é inválido porque já exstem arquivos para este usuário", - "User disabled" : "Usuário desativado", + "Extracts topics from a text and outputs them separated by commas." : "Extrai temas de um texto e os exibe separados por vírgulas.", + "Organisation" : "Organização", "File is currently busy, please try again later" : "O arquivo está ocupado, tente novamente mais tarde", "Cannot download file" : "Não é possível baixar o arquivo", - "Your data directory is readable by other users." : "Seu diretório de dados pode ser lido por outros usuários.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor altere as permissões para 0770 para que o diretório não possa ser lido por outros usuários.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assegure-se que exista um arquivo chamado \".ocdata\" na raiz do diretório \"data\"." + "Login is too long" : "Login é muito longo" }, "nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/pt_BR.json b/lib/l10n/pt_BR.json index 8443e5a5650..70e525bdb12 100644 --- a/lib/l10n/pt_BR.json +++ b/lib/l10n/pt_BR.json @@ -1,28 +1,28 @@ { "translations": { "Cannot write into \"config\" directory!" : "Não é possível gravar no diretório \"config\"!", - "This can usually be fixed by giving the web server write access to the config directory." : "Isso geralmente pode ser corrigido dando ao servidor web acesso de gravação ao diretório de configuração.", + "This can usually be fixed by giving the web server write access to the config directory." : "Geralmente, isso pode ser corrigido dando ao servidor web acesso de gravação ao diretório de configuração.", "But, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it." : "Mas, se você preferir manter o arquivo config.php somente para leitura, defina a opção \"config_is_read_only\" como true nele. ", "See %s" : "Ver %s", - "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "Aplicação %1$s não está presente ou possui uma versão não compatível com este servidor. Verifique o diretório de aplicativos.", + "Application %1$s is not present or has a non-compatible version with this server. Please check the apps directory." : "O aplicativo %1$s não está presente ou tem uma versão não compatível com este servidor. Verifique o diretório de aplicativos.", "Sample configuration detected" : "Configuração de exemplo detectada", "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Foi detectado que a configuração de exemplo foi copiada. Isso pode terminar sua instalação e não é suportado. Por favor leia a documentação antes de realizar mudanças no config.php", "The page could not be found on the server." : "A página não pôde ser encontrada no servidor.", - "%s email verification" : "%s e-mail de verificação", - "Email verification" : "E-mail de verificação", - "Click the following button to confirm your email." : "Clique no botão a seguir para confirmar seu e-mail.", - "Click the following link to confirm your email." : "Clique no link a seguir para confirmar seu e-mail.", - "Confirm your email" : "Confirme seu e-mail", + "%s email verification" : "Verificação de e-mail de %s", + "Email verification" : "Verificação do endereço de e-mail", + "Click the following button to confirm your email." : "Clique no botão a seguir para confirmar seu endereço de e-mail.", + "Click the following link to confirm your email." : "Clique no link a seguir para confirmar seu endereço de e-mail.", + "Confirm your email" : "Confirmar seu e-mail", "Other activities" : "Outras atividades", "%1$s and %2$s" : "%1$s e %2$s", "%1$s, %2$s and %3$s" : "%1$s, %2$s e %3$s", "%1$s, %2$s, %3$s and %4$s" : "%1$s, %2$s, %3$s e %4$s", "%1$s, %2$s, %3$s, %4$s and %5$s" : "%1$s, %2$s, %3$s, %4$s e %5$s", - "Education bundle" : "Pacote educacional", - "Enterprise bundle" : "Pacote Enterprise", + "Education bundle" : "Pacote Educação", + "Enterprise bundle" : "Pacote Empresarial", "Groupware bundle" : "Pacote Groupware", - "Hub bundle" : "Pacote de hub", - "Public sector bundle" : "Pacote do setor público", - "Social sharing bundle" : "Pacote de compartilhamento social", + "Hub bundle" : "Pacote Hub", + "Public sector bundle" : "Pacote Setor Público", + "Social sharing bundle" : "Pacote Compartilhamento Social", "PHP %s or higher is required." : "PHP %s ou superior é necessário.", "PHP with a version lower than %s is required." : "É necessária uma versão PHP mais antiga que a %s.", "%sbit or higher PHP required." : "%sbit ou PHP maior é requerido.", @@ -35,10 +35,10 @@ "The following platforms are supported: %s" : "As seguintes plataformas são suportadas: %s", "Server version %s or higher is required." : "É requerido um servidor da versão %s ou superior.", "Server version %s or lower is required." : "É requerido um servidor da versão %s ou abaixo.", - "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "A conta conectada deve ser um administrador, um subadministrador ou ter direito especial para acessar esta configuração", - "Your current IP address doesn’t allow you to perform admin actions" : "Seu endereço IP atual não permite que você execute ações administrativas", - "Logged in account must be an admin or sub admin" : "A conta conectada deve ser de um administrador ou subadministrador", - "Logged in account must be an admin" : "A conta logada deve ser de um administrador", + "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "A conta logada deve ser um administrador, um subadministrador ou ter direito especial para acessar esta configuração", + "Your current IP address doesn't allow you to perform admin actions" : "Seu endereço IP atual não permite que você execute ações administrativas", + "Logged in account must be an admin or sub admin" : "A conta logada deve ser um administrador ou subadministrador", + "Logged in account must be an admin" : "A conta logada deve ser um administrador", "Wiping of device %s has started" : "Limpeza do dispositivo %s iniciou", "Wiping of device »%s« has started" : "A limpeza do dispositivo »%s« terminou", "»%s« started remote wipe" : "»%s« iniciou a limpeza remota", @@ -57,7 +57,12 @@ "Avatar image is not square" : "A imagem do avatar não é quadrada", "Files" : "Arquivos", "View profile" : "Visualizar perfil", - "Local time: %s" : "Hora local: %s", + "same time" : "mesmo horário", + "_%nh_::_%nh_" : ["%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm"], + "%s ahead" : "%s à frente", + "%s behind" : "%s atrás", + "Local time: %s" : "Horário local: %s", "today" : "hoje", "tomorrow" : "amanhã", "yesterday" : "ontem", @@ -66,30 +71,45 @@ "next month" : "Mês que vem", "last month" : "último mês", "_in %n month_::_in %n months_" : ["em %n mês","em %n meses","em %n meses"], - "_%n month ago_::_%n months ago_" : ["há %n mês atrás","há %n meses","há %n meses"], - "next year" : "ano que vem", + "_%n month ago_::_%n months ago_" : ["%n mês atrás","%n meses atrás","%n meses atrás"], + "next year" : "próximo ano", "last year" : "último ano", "_in %n year_::_in %n years_" : ["em %n ano","em %n anos","em %n anos"], "_%n year ago_::_%n years ago_" : ["%n ano atrás","%n anos atrás","%n anos atrás"], "_in %n hour_::_in %n hours_" : ["em %n hora","em %n horas","em %n horas"], - "_%n hour ago_::_%n hours ago_" : ["há %n hora atrás","há %n horas","há %n horas"], + "_%n hour ago_::_%n hours ago_" : ["%n hora atrás","%n horas atrás","%n horas atrás"], "_in %n minute_::_in %n minutes_" : ["em %n minuto","em %n minutos","em %n minutos"], - "_%n minute ago_::_%n minutes ago_" : ["há %n minuto atrás","há %n minutos","há %n minutos"], + "_%n minute ago_::_%n minutes ago_" : ["%n minuto atrás","%n minutos atrás","%n minutos atrás"], "in a few seconds" : "Em alguns segundos", "seconds ago" : "segundos atrás", "Empty file" : "Arquivo vazio", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "O módulo com a ID: %s não existe. Por favor, habilite-o nas configurações de seu aplicativo ou contacte o administrador.", + "No file conversion providers available" : "Não há provedores de conversão de arquivos disponíveis", + "File is too large to convert" : "O arquivo é muito grande para converter", + "Destination does not match conversion extension" : "O destino não corresponde à extensão de conversão", + "Could not convert file" : "Não foi possível converter o arquivo", + "Destination does not exist" : "Destino não existe", + "Destination is not creatable" : "Destino não pode ser criado", "Dot files are not allowed" : "Arquivos Dot não são permitidos", + "%1$s (renamed)" : "%1$s (renomeado)", + "renamed file" : "arquivo renomeado", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" é um nome de arquivo ou pasta proibido.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" é um prefixo proibido para nomes de arquivos ou pastas.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" não é permitido dentro de um nome de arquivo ou pasta.", "\"%1$s\" is a forbidden file type." : "\"%1$s\" é um tipo de arquivo proibido.", "Filenames must not end with \"%1$s\"." : "Os nomes dos arquivos não devem terminar com \"%1$s\".", - "Invalid parent path" : "Caminho mãe inválido", + "Invalid parent path" : "Caminho pai inválido", "File already exists" : "O arquivo já existe", - "Invalid path" : "Diretório inválido", - "Failed to create file from template" : "Falha ao criar arquivo do modelo ", + "Invalid path" : "Caminho inválido", + "Failed to create file from template" : "Falha ao criar arquivo a partir do modelo", "Templates" : "Modelos ", + "Storage %s cannot be moved" : "O armazenamento %s não pode ser movido", + "Moving a share (%s) into a shared folder is not allowed" : "Não é permitido mover um compartilhamento (%s) para uma pasta compartilhada", + "Moving a storage (%s) into a shared folder is not allowed" : "Não é permitido mover um armazenamento (%s) para uma pasta compartilhada", + "Moving a share (%s) into another share (%s) is not allowed" : "Não é permitido mover um compartilhamento (%s) para outro compartilhamento (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "Não é permitido mover um compartilhamento (%s) para outro armazenamento (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "Não é permitido mover um armazenamento (%s) para um compartilhamento (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Não é permitido mover um armazenamento (%s) para outro armazenamento (%s)", "Path contains invalid segments" : "O caminho contém segmentos inválidos", "Filename is a reserved word" : "Nome do arquivo é uma palavra reservada", "Filename contains at least one invalid character" : "O nome do arquivo contém pelo menos um caractere inválido ", @@ -108,35 +128,35 @@ "Log out" : "Sair", "Accounts" : "Contas", "Email" : "E-mail", - "Mail %s" : "E-Mail %s", - "Fediverse" : "Fediverse", - "View %s on the fediverse" : "Ver %s no fediverse", + "Mail %s" : "Enviar e-mail para %s", + "Fediverse" : "Fediverso", + "View %s on the fediverse" : "Ver %s no fediverso", "Phone" : "Fone", - "Call %s" : "Chamar %s", + "Call %s" : "Ligar para %s", "Twitter" : "Twitter", - "View %s on Twitter" : "Visualizar %s no Twitter", - "Website" : "Website", + "View %s on Twitter" : "Ver %s no Twitter", + "Website" : "Site", "Visit %s" : "Visitar %s", "Address" : "Endereço", "Profile picture" : "Foto do perfil", "About" : "Sobre", "Display name" : "Nome de exibição", - "Headline" : "Título ", - "Organisation" : "Organização", + "Headline" : "Título", + "Organization" : "Organização", "Role" : "Função", "Pronouns" : "Pronomes", "Unknown account" : "Conta desconhecida", "Additional settings" : "Configurações adicionais", "Enter the database Login and name for %s" : "Insira o login e o nome do banco de dados para %s", "Enter the database Login for %s" : "Insira o login do banco de dados para %s", - "Enter the database name for %s" : "Digite o nome do banco de dados para %s", + "Enter the database name for %s" : "Insira o nome do banco de dados para %s", "You cannot use dots in the database name %s" : "Você não pode usar pontos no nome do banco de dados %s", "MySQL Login and/or password not valid" : "Login e/ou senha do MySQL inválidos", "You need to enter details of an existing account." : "Você necessita entrar detalhes de uma conta existente.", "Oracle connection could not be established" : "Conexão Oracle não pôde ser estabelecida", - "Oracle Login and/or password not valid" : "Login e/ou senha Oracle inválidos", + "Oracle Login and/or password not valid" : "Login e/ou senha do Oracle inválidos", "PostgreSQL Login and/or password not valid" : "Login e/ou senha do PostgreSQL inválidos", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X não é suportado e %s não funcionará corretamente nesta plataforma. Use-o por sua conta e risco!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "O Mac OS X não é compatível e %s não funcionará corretamente nessa plataforma. Use-o por sua própria conta e risco!", "For the best results, please consider using a GNU/Linux server instead." : "Para obter melhores resultados, por favor considere o uso de um servidor GNU/Linux em seu lugar.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Aparentemente a instância %s está rodando em um ambiente PHP de 32 bits e o open_basedir foi configurado no php.ini. Isto pode gerar problemas com arquivos maiores que 4GB e é altamente não recomendável.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, remova a configuração de open_basedir de seu php.ini ou mude o PHP para 64bit.", @@ -147,41 +167,41 @@ "Sharing backend %s not found" : "Plataforma de serviço de compartilhamento %s não encontrada", "Sharing backend for %s not found" : "Plataforma de compartilhamento para %s não foi encontrada", "%1$s shared %2$s with you" : "%1$s compartilhou %2$s com você", - "Click the button below to open it." : "Clique no botão abaixo para abri-lo.", "Open %s" : "Abrir %s", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s compartilhou %2$s com você e deseja adicionar:", "%1$s shared %2$s with you and wants to add" : "%1$s compartilhou %2$s com você e deseja adicionar", "%s added a note to a file shared with you" : "%s adicionou uma nota a um arquivo compartilhado com você", - "Passwords are enforced for link and mail shares" : "As senhas são aplicadas para compartilhamentos de links e e-mails", + "Passwords are enforced for link and mail shares" : "As senhas são obrigatórias para compartilhamentos de links e e-mails", "Share recipient is not a valid user" : "O destinatário do compartilhamento não é um usuário válido", "Share recipient is not a valid group" : "O destinatário do compartilhamento não é um grupo válido", - "Share recipient should be empty" : "O destinatário do compartilhamento pode estar vazio", - "Share recipient should not be empty" : "O destinatário do compartilhamento não pode estar vazio", + "Share recipient should be empty" : "O destinatário do compartilhamento deve estar vazio", + "Share recipient should not be empty" : "O destinatário do compartilhamento não deve estar vazio", "Share recipient is not a valid circle" : "O destinatário do compartilhamento não é um círculo válido", "Unknown share type" : "Tipo de compartilhamento desconhecido", "Share initiator must be set" : "O iniciador de compartilhamento deve estar definido", "Cannot share with yourself" : "Não é possível compartilhar consigo mesmo", "Shared path must be set" : "O caminho do compartilhamento deve estar definido", - "Shared path must be either a file or a folder" : "O caminho do compartilhamento deve ser um arquivo ou uma pasta", + "Shared path must be either a file or a folder" : "O caminho do compartilhamento deve ser ou um arquivo ou uma pasta", "You cannot share your root folder" : "Você não pode compartilhar sua pasta raiz", "You are not allowed to share %s" : "Você não tem permissão para compartilhar %s", "Valid permissions are required for sharing" : "Permissões válidas são necessárias para compartilhamento", + "File shares cannot have create or delete permissions" : "Os compartilhamentos de arquivos não podem ter permissões de criação ou exclusão", "Cannot increase permissions of %s" : "Não foi possível aumentar as permissões de %s", "Shares need at least read permissions" : "Compartilhamentos precisam pelo menos permissões de leitura", "Files cannot be shared with delete permissions" : "Arquivos não podem ser compartilhados com permissões de exclusão", "Files cannot be shared with create permissions" : "Arquivos não podem ser compartilhados com permissões de criação", "Expiration date is in the past" : "Data de expiração está no passado", "Expiration date is enforced" : "A data de expiração é aplicada", - "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Não foi possível definir a data de expiração superior que %n dias no futuro","Não foi possível definir a data de expiração superior que %n dias no futuro","Não foi possível definir a data de expiração superior que %n dias no futuro"], + "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Não é possível definir a data de expiração para mais de %n dia no futuro","Não é possível definir a data de expiração para mais de %n dias no futuro","Não é possível definir a data de expiração para mais de %n dias no futuro"], "Sharing is only allowed with group members" : "O compartilhamento só é permitido com membros do grupo ", - "Sharing %s failed, because this item is already shared with the account %s" : "Falha no compartilhamento %s porque este item já está compartilhado com a conta %s", + "Sharing %s failed, because this item is already shared with the account %s" : "O compartilhamento do %s falhou, porque esse item já está compartilhado com a conta %s", "Group sharing is now allowed" : "O compartilhamento em grupo é permitido agora", "Sharing is only allowed within your own groups" : "O compartilhamento só é permitido dentro de seus próprios grupos", "Path is already shared with this group" : "O caminho já está compartilhado com este grupo", - "Link sharing is not allowed" : "O compartilhamento de link não é permitido", + "Link sharing is not allowed" : "O compartilhamento de links não é permitido", "Public upload is not allowed" : "O upload público não é permitido", - "Path contains files shared with you" : "O caminho contém arquivos compartilhados com você", + "You cannot share a folder that contains other shares" : "Você não pode compartilhar uma pasta que contém outros compartilhamentos", "Sharing is disabled" : "O compartilhamento está desativado", "Sharing is disabled for you" : "O compartilhamento está desativado para você", "Cannot share with the share owner" : "Não é possível compartilhar com o proprietário do compartilhamento", @@ -199,7 +219,7 @@ "The requested share comes from a disabled user" : "O compartilhamento solicitado vem de um usuário desabilitado", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "O usuário não foi criado porque o limite de usuários foi atingido. Confira suas notificações para saber mais.", "Could not find category \"%s\"" : "Impossível localizar a categoria \"%s\"", - "Input text" : "Entrada de texto", + "Input text" : "Texto de entrada", "The input text" : "O texto de entrada", "Sunday" : "Domingo", "Monday" : "Segunda-feira", @@ -250,9 +270,10 @@ "The Login is already being used" : "O Login já está sendo usado", "Could not create account" : "Não foi possível criar a conta", "Only the following characters are allowed in an Login: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Somente os seguintes caracteres são permitidos em um Login: \"a-z\", \"A-Z\", \"0-9\", espaços e \"_.@-'\"", - "A valid Login must be provided" : "Um login válido deve ser fornecido", + "A valid Login must be provided" : "Um Login válido deve ser fornecido", "Login contains whitespace at the beginning or at the end" : "O login contém espaços em branco no início ou no final", - "Login must not consist of dots only" : "O login não deve consistir apenas em pontos", + "Login must not consist of dots only" : "O login não deve consistir apenas de pontos", + "Username is too long" : "O nome de usuário é muito longo", "Login is invalid because files already exist for this user" : "O login é inválido porque já existem arquivos para este usuário", "Account disabled" : "Conta desativada", "Login canceled by app" : "Login cancelado pelo aplicativo", @@ -263,27 +284,27 @@ "Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.", "No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhum driver de banco de dados (sqlite, mysql ou postgresql) instalado.", "Cannot write into \"config\" directory." : "Não é possível gravar no diretório \"config\".", - "This can usually be fixed by giving the web server write access to the config directory. See %s" : "Isso geralmente pode ser corrigido dando ao servidor web acesso de gravação ao diretório de configuração. Ver %s", + "This can usually be fixed by giving the web server write access to the config directory. See %s" : "Geralmente, isso pode ser corrigido dando ao servidor web acesso de gravação ao diretório de configuração. Consulte %s", "Or, if you prefer to keep config.php file read only, set the option \"config_is_read_only\" to true in it. See %s" : "Ou, se você preferir manter o arquivo config.php somente para leitura, defina a opção \"config_is_read_only\" como true. Veja %s", "Cannot write into \"apps\" directory." : "Não é possível gravar no diretório \"apps\".", - "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Isso geralmente pode ser corrigido dando ao servidor web acesso de gravação ao diretório de aplicativos ou desabilitando a App Store no arquivo de configuração.", - "Cannot create \"data\" directory." : "Não é possível criar o diretório \"dados\".", - "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Isso geralmente pode ser corrigido dando ao servidor web acesso de gravação ao diretório raiz. Ver %s", - "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "As permissões geralmente podem ser corrigidas dando ao servidor web acesso de gravação ao diretório raiz. Ver %s.", + "This can usually be fixed by giving the web server write access to the apps directory or disabling the App Store in the config file." : "Geralmente, isso pode ser corrigido dando ao servidor web acesso de gravação ao diretório de aplicativos ou desabilitando a Loja de Aplicativos no arquivo de configuração.", + "Cannot create \"data\" directory." : "Não é possível criar o diretório \"data\".", + "This can usually be fixed by giving the web server write access to the root directory. See %s" : "Geralmente, isso pode ser corrigido dando ao servidor web acesso de gravação ao diretório raiz. Consulte %s", + "Permissions can usually be fixed by giving the web server write access to the root directory. See %s." : "Geralmente, as permissões podem ser corrigidas dando ao servidor web acesso de gravação ao diretório raiz. Consulte %s.", "Your data directory is not writable." : "Seu diretório de dados não é gravável.", - "Setting locale to %s failed." : "Falha ao definir a localidade para %s .", - "Please install one of these locales on your system and restart your web server." : "Instale um dessas localidades em seu sistema e reinicie seu servidor web.", + "Setting locale to %s failed." : "Falha ao definir a configuração regional para %s.", + "Please install one of these locales on your system and restart your web server." : "Por favor, instale uma dessas configurações regionais em seu sistema e reinicie seu servidor web.", "PHP module %s not installed." : "Módulo PHP %s não instalado.", "Please ask your server administrator to install the module." : "Por favor, peça ao seu administrador do servidor para instalar o módulo.", "PHP setting \"%s\" is not set to \"%s\"." : "Configuração PHP \"%s\" não está configurado para \"%s\".", "Adjusting this setting in php.ini will make Nextcloud run again" : "Ajustar a configuração no php.ini fará com que o Nextcloud execute novamente", "<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>." : "<code>mbstring.func_overload</code> está configurado para <code>%s</code> em vez do valor esperado <code>0</code>.", - "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Para corrigir este conjunto de problemas <code>mbstring.func_overload</code> para <code>0</code> no seu php.ini.", + "To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini." : "Para corrigir esse problema, defina <code>mbstring.func_overload</code> como <code>0</code> em seu php.ini.", "PHP is apparently set up to strip inline doc blocks. This will make several core apps inaccessible." : "PHP aparentemente está configurado para retirar blocos doc inline. Isso fará com que vários aplicativos do núcleo fiquem inacessíveis.", "This is probably caused by a cache/accelerator such as Zend OPcache or eAccelerator." : "Isso provavelmente é causado por um cache/acelerador, como Zend OPcache ou eAccelerator.", "PHP modules have been installed, but they are still listed as missing?" : "Módulos do PHP foram instalados, mas eles ainda estão listados como faltantes?", "Please ask your server administrator to restart the web server." : "Por favor peça ao administrador do servidor para reiniciar o servidor web.", - "The required %s config variable is not configured in the config.php file." : "A variável %s de configuração necessária não está configurada no arquivo config.php.", + "The required %s config variable is not configured in the config.php file." : "A variável de configuração %s obrigatória não está configurada no arquivo config.php.", "Please ask your server administrator to check the Nextcloud configuration." : "Peça ao administrador do servidor para verificar a configuração do Nextcloud.", "Your data directory is readable by other people." : "Seu diretório de dados pode ser lido por outras pessoas.", "Please change the permissions to 0770 so that the directory cannot be listed by other people." : "Altere as permissões para 0770 para que o diretório não possa ser listado por outras pessoas.", @@ -302,16 +323,27 @@ "Storage connection error. %s" : "Erro na conexão de armazenamento. %s", "Storage is temporarily not available" : "Armazenamento temporariamente indisponível", "Storage connection timeout. %s" : "Atingido o tempo limite de conexão ao armazenamento. %s", - "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Para permitir que esta verificação seja executada, você deve certificar-se de que seu servidor Web pode se conectar a si mesmo. Portanto, ele deve ser capaz de resolver e conectar-se a pelo menos um de seus `trusted_domains` ou `overwrite.cli.url`. Essa falha pode ser o resultado de uma incompatibilidade de DNS no servidor ou de uma regra de firewall de saída.", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Para permitir que esta verificação seja executada, você deve certificar-se de que seu servidor web pode se conectar a si mesmo. Portanto, ele deve ser capaz de resolver e conectar a pelo menos um de seus `trusted_domains` ou `overwrite.cli.url`. Esta falha pode ser o resultado de uma incompatibilidade de DNS no servidor ou de uma regra de firewall de saída.", "Transcribe audio" : "Transcrever áudio", - "Transcribe the things said in an audio" : "Transcreva as coisas ditas em um áudio", + "Transcribe the things said in an audio" : "Transcrever o que foi dito em um áudio", "Audio input" : "Entrada de áudio", "The audio to transcribe" : "O áudio a ser transcrito", "Transcription" : "Transcrição", "The transcribed text" : "O texto transcrito", + "Chat with an agent" : "Conversar com um agente", "Chat message" : "Mensagem de bate-papo", + "A chat message to send to the agent." : "Uma mensagem de bate-papo a ser enviada ao agente", "Confirmation" : "Confirmação", - "Context write" : "Gravação de contexto", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Se deve confirmar as ações solicitadas anteriormente: 0 para negação e 1 para confirmação.", + "Conversation token" : "Token de conversação", + "A token representing the conversation." : "Um token que representa a conversa.", + "Generated response" : "Resposta gerada", + "The response from the chat model." : "A resposta do modelo de bate-papo.", + "The new conversation token" : "O novo token de conversa", + "Send this along with the next interaction." : "Envie isso junto com a próxima interação.", + "Requested actions by the agent" : "Ações solicitadas pelo agente", + "Actions that the agent would like to carry out in JSON format." : "Ações que o agente gostaria de realizar no formato JSON.", + "Context write" : "Escrita contextual", "Writes text in a given style based on the provided source material." : "Escreve texto em um determinado estilo com base no material de origem fornecido.", "Writing style" : "Estilo de escrita", "Demonstrate a writing style that you would like to immitate" : "Demonstre um estilo de escrita que você gostaria de imitar", @@ -321,23 +353,34 @@ "The generated text with content from the source material in the given style" : "O texto gerado com conteúdo do material de origem no estilo determinado", "Emoji generator" : "Gerador de emojis", "Takes text and generates a representative emoji for it." : "Pega texto e gera um emoji representativo para ele.", - "The text to generate an emoji for" : "O texto para gerar um emoji para", + "The text to generate an emoji for" : "O texto para o qual gerar um emoji", "Generated emoji" : "Emoji gerado", "The generated emoji based on the input text" : "O emoji gerado com base no texto de entrada", "Generate image" : "Gerar imagem", "Generate an image from a text prompt" : "Gere uma imagem a partir de um prompt de texto", - "Prompt" : "Pronto", + "Prompt" : "Prompt", "Describe the image you want to generate" : "Descreva a imagem que você deseja gerar", "Number of images" : "Número de imagens", - "How many images to generate" : "Quantas imagens gerar", + "How many images to generate" : "Quantas imagens devem ser geradas", "Output images" : "Imagens de saída", "The generated images" : "As imagens geradas", - "Free text to text prompt" : "Texto livre para prompt de texto", + "Generate speech" : "Gerar fala", + "Generate speech from a transcript" : "Gerar fala a partir de uma transcrição", + "Write transcript that you want the assistant to generate speech from" : "Escreva a transcrição a partir da qual você deseja que o assistente gere a fala", + "Output speech" : "Fala de saída", + "The generated speech" : "A fala gerada", + "Free text to text prompt" : "Prompt de texto livre para texto", "Runs an arbitrary prompt through a language model that returns a reply" : "Usa um modelo de linguagem para gerar uma resposta a partir de um prompt.", "Describe a task that you want the assistant to do or ask a question" : "Descreva uma tarefa que você deseja que o assistente execute ou faça uma pergunta", "Generated reply" : "Resposta gerada", "The generated text from the assistant" : "O texto gerado do assistente", - "Chat" : "Conversa", + "Change Tone" : "Mudar o tom", + "Change the tone of a piece of text." : "Alterar o tom de um texto.", + "Write a text that you want the assistant to rewrite in another tone." : "Escreva um texto que você deseja que o assistente reescreva em outro tom.", + "Desired tone" : "Tom desejado", + "In which tone should your text be rewritten?" : "Em qual tom seu texto deve ser reescrito?", + "The rewritten text in the desired tone, written by the assistant:" : "O texto reescrito no tom desejado, escrito pelo assistente:", + "Chat" : "Bate-papo", "Chat with the assistant" : "Converse com o assistente", "System prompt" : "Prompt do sistema", "Define rules and assumptions that the assistant should follow during the conversation." : "Defina regras e suposições que o assistente deve seguir durante a conversa.", @@ -345,86 +388,69 @@ "The history of chat messages before the current message, starting with a message by the user" : "O histórico de mensagens de bate-papo antes da mensagem atual, começando com uma mensagem do usuário", "Response message" : "Mensagem de resposta", "The generated response as part of the conversation" : "A resposta gerada como parte da conversa", + "Chat with tools" : "Conversar com ferramentas", + "Chat with the language model with tool calling support." : "Converse com o modelo de linguagem com suporte a tool calling (\"chamadas a ferramentas\").", + "Tool message" : "Mensagem da ferramenta", + "The result of tool calls in the last interaction" : "O resultado das chamadas a ferramentas na última interação", + "Available tools" : "Ferramentas disponíveis", + "The available tools in JSON format" : "As ferramentas disponíveis em formato JSON", + "The response from the chat model" : "A resposta do modelo de bate-papo", + "Tool calls" : "Chamadas a ferramentas", + "Tools call instructions from the model in JSON format" : "Instruções para chamadas a ferramentas do modelo no formato JSON", "Formalize text" : "Formalizar texto", - "Takes a text and makes it sound more formal" : "Pega um texto e faz com que ele soe mais formal", + "Takes a text and makes it sound more formal" : "Pega um texto e o faz parecer mais formal", "Write a text that you want the assistant to formalize" : "Escreva um texto que você deseja que o assistente formalize", "Formalized text" : "Texto formalizado", "The formalized text" : "O texto formalizado", "Generate a headline" : "Gere um título", - "Generates a possible headline for a text." : "Gera um título possível para um texto.", + "Generates a possible headline for a text." : "Gera um possível título para um texto.", "Original text" : "Texto original", - "The original text to generate a headline for" : "O texto original para gerar um título para", + "The original text to generate a headline for" : "O texto original para gerar um título", "The generated headline" : "O título gerado", + "Proofread" : "Revisar", + "Proofreads a text and lists corrections" : "Revisa um texto e lista as correções", + "Text" : "Texto", + "The text to proofread" : "O texto a ser revisado", + "Corrections" : "Correções", + "The corrections that should be made in your text" : "As correções que devem ser feitas em seu texto", "Reformulate text" : "Reformular texto", "Takes a text and reformulates it" : "Pega um texto e o reformula", - "Write a text that you want the assistant to reformulate" : "Escrever um texto que você deseja que o assistente reformule", + "Write a text that you want the assistant to reformulate" : "Escreva um texto que você deseja que o assistente reformule", "Reformulated text" : "Texto reformulado", - "The reformulated text, written by the assistant" : "O texto reformulado, escrito pela assistente", + "The reformulated text, written by the assistant" : "O texto reformulado, escrito pelo assistente", "Simplify text" : "Simplificar texto", - "Takes a text and simplifies it" : "Pegar um texto e simplificar ", + "Takes a text and simplifies it" : "Pega um texto e o simplifica", "Write a text that you want the assistant to simplify" : "Escreva um texto que você deseja que o assistente simplifique", "Simplified text" : "Texto simplificado", "The simplified text" : "O texto simplificado", "Summarize" : "Resumir", - "Summarizes a text" : "Resumir um texto", + "Summarizes a text" : "Resume um texto", "The original text to summarize" : "O texto original para resumir", "Summary" : "Resumo", "The generated summary" : "O resumo gerado", - "Extract topics" : "Extrair tópicos", - "Extracts topics from a text and outputs them separated by commas" : "Extrai tópicos de um texto e os exibe separados por vírgulas", - "The original text to extract topics from" : "O texto original para extrair tópicos de", - "Topics" : "Tópicos", - "The list of extracted topics" : "A lista de tópicos extraídos", + "Extract topics" : "Extrair temas", + "Extracts topics from a text and outputs them separated by commas" : "Extrai temas de um texto e os exibe separados por vírgulas", + "The original text to extract topics from" : "O texto original do qual extrair temas", + "Topics" : "Temas", + "The list of extracted topics" : "A lista de temas extraídos", "Translate" : "Traduzir", - "Translate text from one language to another" : "Traduzir o texto de um idioma para outro", + "Translate text from one language to another" : "Traduzir um texto de um idioma para outro", "Origin text" : "Texto original", "The text to translate" : "O texto a ser traduzido", "Origin language" : "Idioma original", "The language of the origin text" : "O idioma do texto original", - "Target language" : "Target language", + "Target language" : "Idioma de destino", "The desired language to translate the origin text in" : "O idioma definido para traduzir o texto original", "Result" : "Resultado", "The translated text" : "O texto traduzido", - "Free prompt" : "Solicitação gratuita", - "Runs an arbitrary prompt through the language model." : "Executa um prompt arbitrário por meio do modelo de idioma.", + "Free prompt" : "Prompt livre", + "Runs an arbitrary prompt through the language model." : "Executa um prompt arbitrário por meio do modelo de linguagem.", "Generate headline" : "Gerar título", "Summarizes text by reducing its length without losing key information." : "Resume o texto reduzindo seu comprimento sem perder informações importantes.", - "Extracts topics from a text and outputs them separated by commas." : "Extrai tópicos de um texto e os gera separados por vírgulas.", - "Education Edition" : "Edição Educativa", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "O usuário conectado deve ser um administrador, um subadministrador ou ter direito especial para acessar esta configuração", - "Logged in user must be an admin or sub admin" : "O usuário conectado deve ser um administrador ou subadministrador", - "Logged in user must be an admin" : "O usuário conectado deve ser um administrador", - "File name is a reserved word" : "O nome do arquivo é uma palavra reservada", - "File name contains at least one invalid character" : "O nome do arquivo contém pelo menos um caracter inválido", - "File name is too long" : "O nome do arquivo é muito longo", - "Help" : "Ajuda", - "Users" : "Usuários", - "Unknown user" : "Usuário desconhecido", - "Enter the database username and name for %s" : "Digite o nome de usuário e o nome do banco de dados para %s", - "Enter the database username for %s" : "Digite o nome de usuário do banco de dados para %s", - "MySQL username and/or password not valid" : "Nome de usuário e/ou senha do MySQL inválidos", - "Oracle username and/or password not valid" : "Nome de usuário e/ou senha Oracle inválidos", - "PostgreSQL username and/or password not valid" : "Nome de usuário e/ou senha PostgreSQL inválidos", - "Set an admin username." : "Defina um nome do usuário administrador.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s compartilhou »%2$s« com você e quer adicionar:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s compartilhou »%2$s« com você e quer adicionar", - "»%s« added a note to a file shared with you" : "»%s« adicionou uma anotação num arquivo compartilhado com você", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Compartilhamento %s falhou, porque este item já está compartilhado com o usuário %s", - "%1$s shared »%2$s« with you" : "%1$s compartilhou »%2$s« com você", - "%1$s shared »%2$s« with you." : "%1$s compartilhou »%2$s« com você.", - "The username is already being used" : "Este nome de usuário já está em uso", - "Could not create user" : "Não foi possível criar o usuário", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Apenas os seguintes caracteres são permitidos em um nome de usuário: \"a-z\", \"A-Z\", \"0-9\", espaços e \"_.@-'\"", - "A valid username must be provided" : "Um nome de usuário válido deve ser fornecido", - "Username contains whitespace at the beginning or at the end" : "O nome de usuário contém espaço em branco no início ou no fim", - "Username must not consist of dots only" : "Nome do usuário não pode consistir de pontos somente", - "Username is invalid because files already exist for this user" : "O nome de usuário é inválido porque já exstem arquivos para este usuário", - "User disabled" : "Usuário desativado", + "Extracts topics from a text and outputs them separated by commas." : "Extrai temas de um texto e os exibe separados por vírgulas.", + "Organisation" : "Organização", "File is currently busy, please try again later" : "O arquivo está ocupado, tente novamente mais tarde", "Cannot download file" : "Não é possível baixar o arquivo", - "Your data directory is readable by other users." : "Seu diretório de dados pode ser lido por outros usuários.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor altere as permissões para 0770 para que o diretório não possa ser lido por outros usuários.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assegure-se que exista um arquivo chamado \".ocdata\" na raiz do diretório \"data\"." + "Login is too long" : "Login é muito longo" },"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/pt_PT.js b/lib/l10n/pt_PT.js index 542bdaa666d..d4e0cbc6aa9 100644 --- a/lib/l10n/pt_PT.js +++ b/lib/l10n/pt_PT.js @@ -1,10 +1,10 @@ OC.L10N.register( "lib", { - "Cannot write into \"config\" directory!" : "Não é possível gravar no directório \"config\"!", + "Cannot write into \"config\" directory!" : "Não é possível gravar no diretório \"config\"!", "See %s" : "Ver %s", "Sample configuration detected" : "Detetado exemplo de configuração", - "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Foi detectado que a configuração de amostra foi copiada. Isso pode danificar a sua instalação e não é suportado. Por favor, leia a documentação antes de realizar mudanças no config.php", + "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Foi detetado que a configuração de amostra foi copiada. Isso pode danificar a sua instalação e não é suportado. Por favor, leia a documentação antes de realizar mudanças no config.php", "The page could not be found on the server." : "Esta página não foi encontrada no servidor.", "Email verification" : "Verificação de e-mail", "Click the following button to confirm your email." : "Clique no botão a seguir para confirmar o seu e-mail.", @@ -54,13 +54,15 @@ OC.L10N.register( "in a few seconds" : "em breves segundos", "seconds ago" : "Minutos atrás", "Empty file" : "Ficheiro vazio", - "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Módulo com ID: %s não existe. Por favor active-o nas definições da aplicação ou contacte o administrador.", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Módulo com ID: %s não existe. Por favor ative-o nas definições da aplicação ou contacte o administrador.", "Dot files are not allowed" : "Ficheiros dot não são permitidos", + "%1$s (renamed)" : "%1$s (renomeado)", + "renamed file" : "ficheiro renomeado", "File already exists" : "O ficheiro já existe", "Invalid path" : "Caminho inválido!", "Failed to create file from template" : "Erro ao criar o ficheiro a partir do modelo", "Templates" : "Modelos", - "Filename contains at least one invalid character" : "Nome ficheiro contém pelo menos um caractere inválido", + "Filename contains at least one invalid character" : "Nome ficheiro contém pelo menos um carácter inválido", "Empty filename is not allowed" : "Não é permitido um ficheiro sem nome", "App \"%s\" cannot be installed because appinfo file cannot be read." : "A app \"%s\" não pode ser instalada porque o ficheiro appinfo não pode ser lido.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "A aplicação \"%s\" não pode ser instada porque não é compatível com esta versão do servidor.", @@ -69,6 +71,7 @@ OC.L10N.register( "Apps" : "Apps", "Settings" : "Definições", "Log out" : "Sair", + "Accounts" : "Contas", "Email" : "E-mail", "Mail %s" : "Mensagem para %s", "Phone" : "Telefone", @@ -82,12 +85,10 @@ OC.L10N.register( "About" : "Sobre", "Display name" : "Nome a exibir", "Headline" : "Título ", - "Organisation" : "Organização", "Role" : "Função", "Additional settings" : "Definições adicionais", "You need to enter details of an existing account." : "Precisa de introduzir detalhes de uma conta existente.", "Oracle connection could not be established" : "Não foi possível estabelecer a ligação Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Esta plataforma não suporta o sistema operativo Mac OS X e o %s poderá não funcionar correctamente. Utilize por sua conta e risco.", "For the best results, please consider using a GNU/Linux server instead." : "Para um melhor resultado, utilize antes o servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Parece que a instância %s está a ser executada num ambiente PHP de 32-bits e o open_basedir foi configurado no php.ini. Isto levará a problemas com ficheiros de tamanho superior a 4 GB e é altamente desencorajado.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, remova a definição open_basedir do seu php.ini ou altere o seu PHP para 64-bits.", @@ -95,7 +96,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Ao partilhar a interface %s deve implementar a interface OCP\\Share_Backend", "Sharing backend %s not found" : "Não foi encontrada a partilha da interface %s", "Sharing backend for %s not found" : "Não foi encontrada a partilha da interface para %s", - "Click the button below to open it." : "Clicar no botão abaixo para abrir.", "%1$s via %2$s" : "%1$s via %2$s", "Unknown share type" : "Tipo de partilha desconhecido", "You are not allowed to share %s" : "Não está autorizado a partilhar %s", @@ -151,7 +151,7 @@ OC.L10N.register( "A valid password must be provided" : "Deve ser fornecida uma palavra-passe válida", "Login canceled by app" : "Sessão cancelada pela app", "a safe home for all your data" : "Um lugar seguro para todos os seus dados", - "Application is not enabled" : "A aplicação não está activada", + "Application is not enabled" : "A aplicação não está ativada", "Authentication error" : "Erro na autenticação", "Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.", "No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhuma base de dados de drivers (sqlite, mysql, or postgresql) instaladas.", @@ -172,37 +172,13 @@ OC.L10N.register( "Storage incomplete configuration. %s" : "Configuração incompleta do armazenamento. %s", "Storage connection error. %s" : "Erro de ligação ao armazenamento. %s", "Storage is temporarily not available" : "Armazenamento temporariamente indisponível", - "Storage connection timeout. %s" : "Tempo de ligação ao armazenamento expirou. %s", + "Storage connection timeout. %s" : "A ligação ao armazenamento expirou. %s", "Chat" : "Chat", + "Text" : "Texto", "Summary" : "Resumo", "Translate" : "Traduzir", - "Education Edition" : "Edição Educação", - "Logged in user must be an admin or sub admin" : "O utilizador autenticado tem de ser um administrador ou subadministrador", - "Logged in user must be an admin" : "O utilizador autenticado tem de ser um administrador", - "File name is a reserved word" : "Nome de ficheiro é uma palavra reservada", - "File name contains at least one invalid character" : "Nome de ficheiro contém pelo menos um caráter inválido", - "File name is too long" : "Nome do ficheiro demasiado longo", - "Help" : "Ajuda", - "Users" : "Utilizadores", - "Unknown user" : "Utilizador desconhecido", - "Oracle username and/or password not valid" : "Nome de utilizador/palavra-passe do Oracle inválidos", - "PostgreSQL username and/or password not valid" : "Nome de utilizador/password do PostgreSQL inválidos", - "Set an admin username." : "Definir um nome de utilizador de administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s partilhado »%2$s« consigo e quer adicionar:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s partilhado »%2$s« consigo e quer adicionar:", - "»%s« added a note to a file shared with you" : "»%s« adicionou uma nota a um ficheiro partilhado consigo", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "A partilha de %s falhou, porque este item já está a ser partilhado com o utilizador %s", - "%1$s shared »%2$s« with you" : "%1$s partilhado »%2$s« contigo", - "%1$s shared »%2$s« with you." : "%1$s partilhado »%2$s« contigo.", - "The username is already being used" : "O nome de utilizador já está a ser usado", - "Could not create user" : "Não foi possível criar o utilizador", - "A valid username must be provided" : "Um nome de utilizador válido deve ser fornecido", - "Username contains whitespace at the beginning or at the end" : "Nome de utilizador contém espaço em branco no início ou no fim", - "Username must not consist of dots only" : "O utilizador não pode consistir de apenas pontos", - "User disabled" : "Utilizador desativado", + "Organisation" : "Organização", "File is currently busy, please try again later" : "O ficheiro está ocupado, por favor, tente mais tarde", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor altere as permissões para 0770 para que esse directório não possa ser listado por outros utilizadores.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Garanta que existe um ficheiro chamado \".occdata\" na raiz do directório de dados" + "Cannot download file" : "Não é possível transferir o ficheiro" }, "nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); diff --git a/lib/l10n/pt_PT.json b/lib/l10n/pt_PT.json index 50ed2ddc6a6..01ce60cb2c7 100644 --- a/lib/l10n/pt_PT.json +++ b/lib/l10n/pt_PT.json @@ -1,8 +1,8 @@ { "translations": { - "Cannot write into \"config\" directory!" : "Não é possível gravar no directório \"config\"!", + "Cannot write into \"config\" directory!" : "Não é possível gravar no diretório \"config\"!", "See %s" : "Ver %s", "Sample configuration detected" : "Detetado exemplo de configuração", - "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Foi detectado que a configuração de amostra foi copiada. Isso pode danificar a sua instalação e não é suportado. Por favor, leia a documentação antes de realizar mudanças no config.php", + "It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" : "Foi detetado que a configuração de amostra foi copiada. Isso pode danificar a sua instalação e não é suportado. Por favor, leia a documentação antes de realizar mudanças no config.php", "The page could not be found on the server." : "Esta página não foi encontrada no servidor.", "Email verification" : "Verificação de e-mail", "Click the following button to confirm your email." : "Clique no botão a seguir para confirmar o seu e-mail.", @@ -52,13 +52,15 @@ "in a few seconds" : "em breves segundos", "seconds ago" : "Minutos atrás", "Empty file" : "Ficheiro vazio", - "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Módulo com ID: %s não existe. Por favor active-o nas definições da aplicação ou contacte o administrador.", + "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Módulo com ID: %s não existe. Por favor ative-o nas definições da aplicação ou contacte o administrador.", "Dot files are not allowed" : "Ficheiros dot não são permitidos", + "%1$s (renamed)" : "%1$s (renomeado)", + "renamed file" : "ficheiro renomeado", "File already exists" : "O ficheiro já existe", "Invalid path" : "Caminho inválido!", "Failed to create file from template" : "Erro ao criar o ficheiro a partir do modelo", "Templates" : "Modelos", - "Filename contains at least one invalid character" : "Nome ficheiro contém pelo menos um caractere inválido", + "Filename contains at least one invalid character" : "Nome ficheiro contém pelo menos um carácter inválido", "Empty filename is not allowed" : "Não é permitido um ficheiro sem nome", "App \"%s\" cannot be installed because appinfo file cannot be read." : "A app \"%s\" não pode ser instalada porque o ficheiro appinfo não pode ser lido.", "App \"%s\" cannot be installed because it is not compatible with this version of the server." : "A aplicação \"%s\" não pode ser instada porque não é compatível com esta versão do servidor.", @@ -67,6 +69,7 @@ "Apps" : "Apps", "Settings" : "Definições", "Log out" : "Sair", + "Accounts" : "Contas", "Email" : "E-mail", "Mail %s" : "Mensagem para %s", "Phone" : "Telefone", @@ -80,12 +83,10 @@ "About" : "Sobre", "Display name" : "Nome a exibir", "Headline" : "Título ", - "Organisation" : "Organização", "Role" : "Função", "Additional settings" : "Definições adicionais", "You need to enter details of an existing account." : "Precisa de introduzir detalhes de uma conta existente.", "Oracle connection could not be established" : "Não foi possível estabelecer a ligação Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Esta plataforma não suporta o sistema operativo Mac OS X e o %s poderá não funcionar correctamente. Utilize por sua conta e risco.", "For the best results, please consider using a GNU/Linux server instead." : "Para um melhor resultado, utilize antes o servidor GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Parece que a instância %s está a ser executada num ambiente PHP de 32-bits e o open_basedir foi configurado no php.ini. Isto levará a problemas com ficheiros de tamanho superior a 4 GB e é altamente desencorajado.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Por favor, remova a definição open_basedir do seu php.ini ou altere o seu PHP para 64-bits.", @@ -93,7 +94,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Ao partilhar a interface %s deve implementar a interface OCP\\Share_Backend", "Sharing backend %s not found" : "Não foi encontrada a partilha da interface %s", "Sharing backend for %s not found" : "Não foi encontrada a partilha da interface para %s", - "Click the button below to open it." : "Clicar no botão abaixo para abrir.", "%1$s via %2$s" : "%1$s via %2$s", "Unknown share type" : "Tipo de partilha desconhecido", "You are not allowed to share %s" : "Não está autorizado a partilhar %s", @@ -149,7 +149,7 @@ "A valid password must be provided" : "Deve ser fornecida uma palavra-passe válida", "Login canceled by app" : "Sessão cancelada pela app", "a safe home for all your data" : "Um lugar seguro para todos os seus dados", - "Application is not enabled" : "A aplicação não está activada", + "Application is not enabled" : "A aplicação não está ativada", "Authentication error" : "Erro na autenticação", "Token expired. Please reload page." : "O token expirou. Por favor recarregue a página.", "No database drivers (sqlite, mysql, or postgresql) installed." : "Nenhuma base de dados de drivers (sqlite, mysql, or postgresql) instaladas.", @@ -170,37 +170,13 @@ "Storage incomplete configuration. %s" : "Configuração incompleta do armazenamento. %s", "Storage connection error. %s" : "Erro de ligação ao armazenamento. %s", "Storage is temporarily not available" : "Armazenamento temporariamente indisponível", - "Storage connection timeout. %s" : "Tempo de ligação ao armazenamento expirou. %s", + "Storage connection timeout. %s" : "A ligação ao armazenamento expirou. %s", "Chat" : "Chat", + "Text" : "Texto", "Summary" : "Resumo", "Translate" : "Traduzir", - "Education Edition" : "Edição Educação", - "Logged in user must be an admin or sub admin" : "O utilizador autenticado tem de ser um administrador ou subadministrador", - "Logged in user must be an admin" : "O utilizador autenticado tem de ser um administrador", - "File name is a reserved word" : "Nome de ficheiro é uma palavra reservada", - "File name contains at least one invalid character" : "Nome de ficheiro contém pelo menos um caráter inválido", - "File name is too long" : "Nome do ficheiro demasiado longo", - "Help" : "Ajuda", - "Users" : "Utilizadores", - "Unknown user" : "Utilizador desconhecido", - "Oracle username and/or password not valid" : "Nome de utilizador/palavra-passe do Oracle inválidos", - "PostgreSQL username and/or password not valid" : "Nome de utilizador/password do PostgreSQL inválidos", - "Set an admin username." : "Definir um nome de utilizador de administrador", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s partilhado »%2$s« consigo e quer adicionar:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s partilhado »%2$s« consigo e quer adicionar:", - "»%s« added a note to a file shared with you" : "»%s« adicionou uma nota a um ficheiro partilhado consigo", - "Open »%s«" : "Abrir »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "A partilha de %s falhou, porque este item já está a ser partilhado com o utilizador %s", - "%1$s shared »%2$s« with you" : "%1$s partilhado »%2$s« contigo", - "%1$s shared »%2$s« with you." : "%1$s partilhado »%2$s« contigo.", - "The username is already being used" : "O nome de utilizador já está a ser usado", - "Could not create user" : "Não foi possível criar o utilizador", - "A valid username must be provided" : "Um nome de utilizador válido deve ser fornecido", - "Username contains whitespace at the beginning or at the end" : "Nome de utilizador contém espaço em branco no início ou no fim", - "Username must not consist of dots only" : "O utilizador não pode consistir de apenas pontos", - "User disabled" : "Utilizador desativado", + "Organisation" : "Organização", "File is currently busy, please try again later" : "O ficheiro está ocupado, por favor, tente mais tarde", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Por favor altere as permissões para 0770 para que esse directório não possa ser listado por outros utilizadores.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Garanta que existe um ficheiro chamado \".occdata\" na raiz do directório de dados" + "Cannot download file" : "Não é possível transferir o ficheiro" },"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" }
\ No newline at end of file diff --git a/lib/l10n/ro.js b/lib/l10n/ro.js index a48d4ce711e..c66f1cf79ec 100644 --- a/lib/l10n/ro.js +++ b/lib/l10n/ro.js @@ -106,14 +106,12 @@ OC.L10N.register( "About" : "Despre", "Display name" : "Nume afișat", "Headline" : "Titlu", - "Organisation" : "Organizație", "Role" : "Rol", "Additional settings" : "Setări adiționale", "Enter the database name for %s" : "Introduceți numele bazei de date pentru %s", "You cannot use dots in the database name %s" : "Nu puteți folosi puncte în numele bazei de date %s", "You need to enter details of an existing account." : "Sunt necesare detaliile unui cont existent.", "Oracle connection could not be established" : "Conexiunea Oracle nu a putut fi stabilită", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nu este suportat și %s nu va funcționa corect pe această platformă. Continuați pe propriul risc! ", "For the best results, please consider using a GNU/Linux server instead." : "Pentru cele mai bune rezultate, ia în calcul folosirea unui server care rulează un sistem de operare GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Se pare că această instanță a %s rulează o versiune 32-bit a PHP și open_basedir a fost configurat în php.ini. Aceasta va conduce la probleme cu fișierele mai mari de 4 GB și nu este deloc recomandată.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Eliminați setarea open_basedir din php.ini utilizați versiunea 64-bit a PHP.", @@ -122,7 +120,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Backend-ul de partajare %s trebuie să implementeze interfața OCP\\Share_Backend", "Sharing backend %s not found" : "Backend-ul de partajare %s nu există", "Sharing backend for %s not found" : "Backend-ul de partajare pentru %s nu a fost găsit", - "Click the button below to open it." : "Apasă pe butonul de jos pentru a deschide.", "%1$s via %2$s" : "%1$sprin %2$s", "Unknown share type" : "Tip necunoscut de partajare", "You are not allowed to share %s" : "Nu există permisiunea de partajare %s", @@ -227,6 +224,7 @@ OC.L10N.register( "Storage is temporarily not available" : "Spațiu de stocare este indisponibil temporar", "Storage connection timeout. %s" : "Timeout la conexiunea cu spațiul de stocare. %s", "Generates a possible headline for a text." : "Generează un posibil titlu pentru text", + "Text" : "Text", "Summarize" : "Rezumă", "Summary" : "Rezumat", "Extract topics" : "Extrage subiecte", @@ -236,41 +234,8 @@ OC.L10N.register( "Generate headline" : "Generează titlu", "Summarizes text by reducing its length without losing key information." : "Rezumă textul prin reducerea lungimii acestuia, fără a pierde informațiile cheie.", "Extracts topics from a text and outputs them separated by commas." : "Extrage subiecte din text și le furnizează separate prin virgulă.", - "Education Edition" : "Ediția pentru educație", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Utilizatorul trebuie să fie administrator, sub-administrator sau să aibă permisiunea specială de a accesa această setare", - "Logged in user must be an admin or sub admin" : "Utilizatorul trebuie să fie administrator sau sub-administrator", - "Logged in user must be an admin" : "Utilizatorul trebuie să fie administrator", - "File name is a reserved word" : "Numele fișierului este un cuvânt rezervat", - "File name contains at least one invalid character" : "Numele fișierului conține cel puțin un caracter invalid", - "File name is too long" : "Numele fișierului este prea lung", - "Help" : "Ajutor", - "Users" : "Utilizatori", - "Unknown user" : "Utilizator necunoscut", - "Enter the database username and name for %s" : "Introduceți utilizatorul pentru baza de date și numele pentru %s", - "Enter the database username for %s" : "Introduceți utilizatorul pentru %s", - "MySQL username and/or password not valid" : "Utilizatorul sau/și parola MySQL invalide", - "Oracle username and/or password not valid" : "Numele de utilizator sau / și parola Oracle nu sunt valide", - "PostgreSQL username and/or password not valid" : "Nume utilizator și/sau parolă PostgreSQL greșită", - "Set an admin username." : "Setează un nume de administrator.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s a partajat »%2$s« cu tine și vrea să adauge:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s a partajat »%2$s« cu tine și vrea să adauge", - "»%s« added a note to a file shared with you" : "%s« a adaugat un comentariu la un fișier partajat cu tine", - "Open »%s«" : "Deschide »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Partajarea %s a eșuat deoarece acest element este deja partajat cu utilizatorul %s", - "%1$s shared »%2$s« with you" : "%1$s a partajat »%2$s« cu tine", - "%1$s shared »%2$s« with you." : "%1$sa partajat »%2$s« cu tine.", - "The username is already being used" : "Numele de utilizator este deja folosit", - "Could not create user" : "Nu s-a putut crea utilizatorul", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Doar următoarele caractere sunt permise în numele de utilizatori: \"a-z\", \"A-Z\", \"0-9\", spații și \"_.@-'\"", - "A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid", - "Username contains whitespace at the beginning or at the end" : "Utilizatorul contine spațiu liber la început sau la sfârșit", - "Username must not consist of dots only" : "Numele utilizatorului nu poate conține numai puncte", - "Username is invalid because files already exist for this user" : "Numele utilizatorului este invalid deoarece există deja fișiere pentru acesta", - "User disabled" : "Utilizator dezactivat", + "Organisation" : "Organizație", "File is currently busy, please try again later" : "Fișierul este blocat momentan, încercați din nou mai târziu", - "Cannot download file" : "Fișierul nu se poate descărca", - "Your data directory is readable by other users." : "Directorul de date este accesibil altor utilizatori.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Setați permisiunea 0770 astfel ca directorul să nu poată fi parcurs de alți utilizatori.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asigurați-vă că fișierul \".ocdata\" există în rădăcina directorului de date." + "Cannot download file" : "Fișierul nu se poate descărca" }, "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); diff --git a/lib/l10n/ro.json b/lib/l10n/ro.json index b08b7f7fe6a..a6a03a43075 100644 --- a/lib/l10n/ro.json +++ b/lib/l10n/ro.json @@ -104,14 +104,12 @@ "About" : "Despre", "Display name" : "Nume afișat", "Headline" : "Titlu", - "Organisation" : "Organizație", "Role" : "Rol", "Additional settings" : "Setări adiționale", "Enter the database name for %s" : "Introduceți numele bazei de date pentru %s", "You cannot use dots in the database name %s" : "Nu puteți folosi puncte în numele bazei de date %s", "You need to enter details of an existing account." : "Sunt necesare detaliile unui cont existent.", "Oracle connection could not be established" : "Conexiunea Oracle nu a putut fi stabilită", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nu este suportat și %s nu va funcționa corect pe această platformă. Continuați pe propriul risc! ", "For the best results, please consider using a GNU/Linux server instead." : "Pentru cele mai bune rezultate, ia în calcul folosirea unui server care rulează un sistem de operare GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Se pare că această instanță a %s rulează o versiune 32-bit a PHP și open_basedir a fost configurat în php.ini. Aceasta va conduce la probleme cu fișierele mai mari de 4 GB și nu este deloc recomandată.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Eliminați setarea open_basedir din php.ini utilizați versiunea 64-bit a PHP.", @@ -120,7 +118,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Backend-ul de partajare %s trebuie să implementeze interfața OCP\\Share_Backend", "Sharing backend %s not found" : "Backend-ul de partajare %s nu există", "Sharing backend for %s not found" : "Backend-ul de partajare pentru %s nu a fost găsit", - "Click the button below to open it." : "Apasă pe butonul de jos pentru a deschide.", "%1$s via %2$s" : "%1$sprin %2$s", "Unknown share type" : "Tip necunoscut de partajare", "You are not allowed to share %s" : "Nu există permisiunea de partajare %s", @@ -225,6 +222,7 @@ "Storage is temporarily not available" : "Spațiu de stocare este indisponibil temporar", "Storage connection timeout. %s" : "Timeout la conexiunea cu spațiul de stocare. %s", "Generates a possible headline for a text." : "Generează un posibil titlu pentru text", + "Text" : "Text", "Summarize" : "Rezumă", "Summary" : "Rezumat", "Extract topics" : "Extrage subiecte", @@ -234,41 +232,8 @@ "Generate headline" : "Generează titlu", "Summarizes text by reducing its length without losing key information." : "Rezumă textul prin reducerea lungimii acestuia, fără a pierde informațiile cheie.", "Extracts topics from a text and outputs them separated by commas." : "Extrage subiecte din text și le furnizează separate prin virgulă.", - "Education Edition" : "Ediția pentru educație", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Utilizatorul trebuie să fie administrator, sub-administrator sau să aibă permisiunea specială de a accesa această setare", - "Logged in user must be an admin or sub admin" : "Utilizatorul trebuie să fie administrator sau sub-administrator", - "Logged in user must be an admin" : "Utilizatorul trebuie să fie administrator", - "File name is a reserved word" : "Numele fișierului este un cuvânt rezervat", - "File name contains at least one invalid character" : "Numele fișierului conține cel puțin un caracter invalid", - "File name is too long" : "Numele fișierului este prea lung", - "Help" : "Ajutor", - "Users" : "Utilizatori", - "Unknown user" : "Utilizator necunoscut", - "Enter the database username and name for %s" : "Introduceți utilizatorul pentru baza de date și numele pentru %s", - "Enter the database username for %s" : "Introduceți utilizatorul pentru %s", - "MySQL username and/or password not valid" : "Utilizatorul sau/și parola MySQL invalide", - "Oracle username and/or password not valid" : "Numele de utilizator sau / și parola Oracle nu sunt valide", - "PostgreSQL username and/or password not valid" : "Nume utilizator și/sau parolă PostgreSQL greșită", - "Set an admin username." : "Setează un nume de administrator.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s a partajat »%2$s« cu tine și vrea să adauge:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s a partajat »%2$s« cu tine și vrea să adauge", - "»%s« added a note to a file shared with you" : "%s« a adaugat un comentariu la un fișier partajat cu tine", - "Open »%s«" : "Deschide »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Partajarea %s a eșuat deoarece acest element este deja partajat cu utilizatorul %s", - "%1$s shared »%2$s« with you" : "%1$s a partajat »%2$s« cu tine", - "%1$s shared »%2$s« with you." : "%1$sa partajat »%2$s« cu tine.", - "The username is already being used" : "Numele de utilizator este deja folosit", - "Could not create user" : "Nu s-a putut crea utilizatorul", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Doar următoarele caractere sunt permise în numele de utilizatori: \"a-z\", \"A-Z\", \"0-9\", spații și \"_.@-'\"", - "A valid username must be provided" : "Trebuie să furnizaţi un nume de utilizator valid", - "Username contains whitespace at the beginning or at the end" : "Utilizatorul contine spațiu liber la început sau la sfârșit", - "Username must not consist of dots only" : "Numele utilizatorului nu poate conține numai puncte", - "Username is invalid because files already exist for this user" : "Numele utilizatorului este invalid deoarece există deja fișiere pentru acesta", - "User disabled" : "Utilizator dezactivat", + "Organisation" : "Organizație", "File is currently busy, please try again later" : "Fișierul este blocat momentan, încercați din nou mai târziu", - "Cannot download file" : "Fișierul nu se poate descărca", - "Your data directory is readable by other users." : "Directorul de date este accesibil altor utilizatori.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Setați permisiunea 0770 astfel ca directorul să nu poată fi parcurs de alți utilizatori.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Asigurați-vă că fișierul \".ocdata\" există în rădăcina directorului de date." + "Cannot download file" : "Fișierul nu se poate descărca" },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" }
\ No newline at end of file diff --git a/lib/l10n/ru.js b/lib/l10n/ru.js index b91ed72ee3f..07ca8447c66 100644 --- a/lib/l10n/ru.js +++ b/lib/l10n/ru.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Требуется сервер версии %s или выше.", "Server version %s or lower is required." : "Требуется сервер версии %s или ниже.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Для доступа к этой настройке зарегистрированная учетная запись должна быть администратором, субадминистратором или иметь специальные права", - "Your current IP address doesn’t allow you to perform admin actions" : "Ваш текущий IP-адрес не позволяет вам выполнять административные действи", + "Your current IP address doesn't allow you to perform admin actions" : "Ваш текущий IP-адрес не позволяет вам выполнять действия администратора.", "Logged in account must be an admin or sub admin" : "Зарегистрированная учетная запись должна быть администратором или субадминистратором", "Logged in account must be an admin" : "Вошедший в систему пользователь должен быть администратором", "Wiping of device %s has started" : "Удаление данных с устройства «%s».", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Изображение аватара не квадратное", "Files" : "Файлы", "View profile" : "Открыть профиль", + "same time" : "в то же время", + "_%nh_::_%nh_" : ["%nч","%nч","%nч","%nч"], + "_%nm_::_%nm_" : ["%nм","%nм","%n м","%n м"], + "%s ahead" : "%s вперёд", + "%s behind" : "%s позади", "Local time: %s" : "Местное время: %s", "today" : "сегодня", "tomorrow" : "завтра", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "несколько секунд назад", "Empty file" : "Пустой файл", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Модуль с ID «%s» не существует. Включите его в настройках приложений или обратитесь к администратору.", + "No file conversion providers available" : "Нет доступных поставщиков услуг конвертации файлов", + "File is too large to convert" : "Файл слишком большой для преобразования", + "Destination does not match conversion extension" : "Назначение не соответствует расширению преобразования", + "Could not convert file" : "Не удалось преобразовать файл", + "Destination does not exist" : "Пункт назначения не существует", + "Destination is not creatable" : "Место назначения не может быть создано", "Dot files are not allowed" : "Файлы начинающиеся с точки не допускаются", + "%1$s (renamed)" : "%1$s (переименовано)", + "renamed file" : "переименованный файл", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" это запрещенное имя файла или папки.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" является запрещенным префиксом для имен файлов или папок.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" не допускается указывать имя файла или папки внутри него.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Некорректный путь", "Failed to create file from template" : "Не удалось создать файл на основе шаблона", "Templates" : "Шаблоны", + "Storage %s cannot be moved" : "Хранилище %s не может быть перемещено", + "Moving a share (%s) into a shared folder is not allowed" : "Перемещение общего ресурса (%s) в общую папку запрещено", + "Moving a storage (%s) into a shared folder is not allowed" : "Перемещение хранилища (%s) в общую папку запрещено", + "Moving a share (%s) into another share (%s) is not allowed" : "Перемещение общего ресурса (%s) в другой общий ресурс (%s) запрещено", + "Moving a share (%s) into another storage (%s) is not allowed" : "Перемещение общего ресурса (%s) в другое хранилище (%s) запрещено", + "Moving a storage (%s) into a share (%s) is not allowed" : "Перемещение хранилища (%s) в общий ресурс (%s) запрещено", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Перемещение хранилища (%s) в другое хранилище (%s) запрещено", "Path contains invalid segments" : "Путь содержит недопустимые сегменты", "Filename is a reserved word" : "Имя файла - это зарезервированное слово", "Filename contains at least one invalid character" : "Имя файла содержит как минимум один недопустимый символ", @@ -124,8 +144,9 @@ OC.L10N.register( "About" : "О себе", "Display name" : "Отображаемое имя", "Headline" : "Заголовок", - "Organisation" : "Организация", + "Organization" : "Организация", "Role" : "Роль", + "Pronouns" : "Местоимения", "Unknown account" : "Неизвестный аккаунт", "Additional settings" : "Дополнительные настройки", "Enter the database Login and name for %s" : "Введите логин и имя пользователя базы данных для %s", @@ -137,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Соединение с Oracle не может быть установлено", "Oracle Login and/or password not valid" : "Неверный логин и/или пароль Oracle", "PostgreSQL Login and/or password not valid" : "Неверный логин и/или пароль для PostgreSQL", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не поддерживается и %s может работать некорректно на данной платформе. Используйте на свой страх и риск!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X не поддерживается, и %s может работать некорректно на этой платформе. Используйте на свой страх и риск!", "For the best results, please consider using a GNU/Linux server instead." : "Для достижения наилучших результатов, рассмотрите вариант использования сервера на GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Кажется что экземпляр этого %s работает в 32-битной среде PHP и в php.ini был настроен open_basedir. Это приведёт к проблемам с файлами более 4 ГБ и настоятельно не рекомендуется.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Удалите директиву open_basedir из файла php.ini или смените PHP на 64-разрядную сборку.", @@ -147,14 +168,27 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Бэкенд общего доступа %s должен реализовывать интерфейс OCP\\Share_Backend", "Sharing backend %s not found" : "Механизм предоставления общего доступа %s не найден", "Sharing backend for %s not found" : "Не найден механизм предоставления общего доступа для %s ", - "Click the button below to open it." : "Нажмите расположенную ниже кнопку для перехода к полученному общему ресурсу.", + "%1$s shared %2$s with you" : "%1$s поделился(ась) %2$s с вами", "Open %s" : "Открыть %s", "%1$s via %2$s" : "%1$s через %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s поделился(ась) %2$s с вами и хочет добавить:", + "%1$s shared %2$s with you and wants to add" : "%1$s поделился(ась) %2$s с вами и хочет добавить", + "%s added a note to a file shared with you" : "%s добавил(а) заметку к файлу, которым поделился(ась) с вами", "Passwords are enforced for link and mail shares" : "Для общих ссылок и почтовых рассылок применяются пароли", + "Share recipient is not a valid user" : "Получатель общего ресурса — некорректный пользователь", + "Share recipient is not a valid group" : "Получатель общего ресурса — некорректная группа", + "Share recipient should be empty" : "Получатель общего ресурса должен быть пустым", + "Share recipient should not be empty" : "Получатель общего ресурса не должен быть пустым", + "Share recipient is not a valid circle" : "Получатель общего ресурса — некорректный круг", "Unknown share type" : "Общий доступ неизвестного типа", + "Share initiator must be set" : "Должен быть задан инициатор общего ресурса", "Cannot share with yourself" : "Не могу поделиться с самим собой", + "Shared path must be set" : "Должен быть указан путь к общему ресурсу", + "Shared path must be either a file or a folder" : "Путь должен указывать на файл или папку", "You cannot share your root folder" : "Вы не можете предоставить общий доступ к своей корневой папке", "You are not allowed to share %s" : "Вам не разрешено делиться %s", + "Valid permissions are required for sharing" : "Для общего ресурса необходимы корректные права", + "File shares cannot have create or delete permissions" : "Для файловых общих ресурсов нельзя задавать права доступа на создание или удаление", "Cannot increase permissions of %s" : "Не удалось повысить права доступа %s", "Shares need at least read permissions" : "Общим ресурсам требуются как минимум разрешения на чтение", "Files cannot be shared with delete permissions" : "Права на удаление файлов не позволяют открывать общий доступ к ним", @@ -169,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Путь уже является общим для этой группы", "Link sharing is not allowed" : "Обмен ссылками запрещен", "Public upload is not allowed" : "Публичная загрузка данных запрещена", - "Path contains files shared with you" : "Путь содержит файлы, к которым вы предоставили общий доступ", + "You cannot share a folder that contains other shares" : "Нельзя делиться папкой, содержащей другие общие ресурсы", "Sharing is disabled" : "Общий доступ отключен", "Sharing is disabled for you" : "Общий доступ для вас отключен", "Cannot share with the share owner" : "Невозможно поделиться с владельцем общего доступа", @@ -181,6 +215,7 @@ OC.L10N.register( "Cannot disable sending the password by Talk without setting a new password" : "Невозможно отключить отправку пароля по телефону без установки нового пароля", "Share provider does not support accepting" : "Поставщик общего доступа не поддерживает прием", "Cannot change target of link share" : "Невозможно изменить цель публикации ссылки", + "Invalid share recipient" : "Некорректный получатель общего ресурса", "Group \"%s\" does not exist" : "Группа \"%s\" не существует", "The requested share does not exist anymore" : "Запрошенный общий ресурс более не существует.", "The requested share comes from a disabled user" : "Запрос на общий доступ поступает от отключенного пользователя", @@ -240,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "Необходимо указать действительный логин для входа в систему", "Login contains whitespace at the beginning or at the end" : "Имя пользователя содержит пробелы в начале или в конце", "Login must not consist of dots only" : "Логин не должен состоять только из точек", + "Username is too long" : "Имя пользователя слишком длинное", "Login is invalid because files already exist for this user" : "Логин недействителен, поскольку файлы для этого пользователя уже существуют", "Account disabled" : "Учетная запись отключена", "Login canceled by app" : "Вход отменен приложением", @@ -296,8 +332,19 @@ OC.L10N.register( "The audio to transcribe" : "Аудио для расшифровки", "Transcription" : "Транскрипция", "The transcribed text" : "Расшифрованный текст", + "Chat with an agent" : "Чат с агентом", "Chat message" : "Сообщение в чате", + "A chat message to send to the agent." : "Сообщение для отправки агенту", "Confirmation" : "Подтверждение", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Подтвердить ранее запрошенные действия: 0 — отказ, 1 — подтверждение.", + "Conversation token" : "Токен беседы", + "A token representing the conversation." : "Токен, представляющий беседу.", + "Generated response" : "Сгенерированный ответ", + "The response from the chat model." : "Ответ от модели чата.", + "The new conversation token" : "Новый токен беседы", + "Send this along with the next interaction." : "Отправьте его при следующем взаимодействии.", + "Requested actions by the agent" : "Запрошенные действия от агента", + "Actions that the agent would like to carry out in JSON format." : "Действия, которые агент хотел бы выполнить в формате JSON.", "Context write" : "Контекстная запись", "Writes text in a given style based on the provided source material." : "Пишет текст в заданном стиле на основе предоставленного исходного материала.", "Writing style" : "Стиль письма", @@ -308,18 +355,33 @@ OC.L10N.register( "The generated text with content from the source material in the given style" : "Сгенерированный текст с содержимым из исходного материала в заданном стиле", "Emoji generator" : "Генератор Emoji", "Takes text and generates a representative emoji for it." : "Берет текст и генерирует для него репрезентативный смайлик.", + "The text to generate an emoji for" : "Текст для создания эмодзи", + "Generated emoji" : "Созданный эмодзи", + "The generated emoji based on the input text" : "Эмодзи, созданный на основе введённого текста", "Generate image" : "Генерировать изображение", "Generate an image from a text prompt" : "Создайте изображение из текстовой подсказки", + "Prompt" : "Подсказка", "Describe the image you want to generate" : "Опишите изображение, которое вы хотите создать", "Number of images" : "Количество изображений", "How many images to generate" : "Сколько изображений генерировать", "Output images" : "Выходные изображения", "The generated images" : "Сгенерированные изображения", + "Generate speech" : "Сгенерировать речь", + "Generate speech from a transcript" : "Сгенерировать речь из транскрипта", + "Write transcript that you want the assistant to generate speech from" : "Введите транскрипт, по которому ассистент должен сгенерировать речь", + "Output speech" : "Выходное аудио", + "The generated speech" : "Сгенерированная речь", "Free text to text prompt" : "Произвольное преобразование текста в текстовую подсказку", "Runs an arbitrary prompt through a language model that returns a reply" : "Запускает произвольный запрос с помощью языковой модели, которая возвращает ответ", "Describe a task that you want the assistant to do or ask a question" : "Опишите задачу, которую вы хотите поручить ассистенту, или задайте вопрос", "Generated reply" : "Сгенерированный ответ", "The generated text from the assistant" : "Сгенерированный текст от помощника", + "Change Tone" : "Сменить тон", + "Change the tone of a piece of text." : "Изменить тон текста", + "Write a text that you want the assistant to rewrite in another tone." : "Напишите текст, чтобы ассистент переписал его в другом тоне.", + "Desired tone" : "Желаемый тон", + "In which tone should your text be rewritten?" : "В каком тоне следует переписать ваш текст?", + "The rewritten text in the desired tone, written by the assistant:" : "Переписанный текст в нужном тоне, написанный ассистентом:", "Chat" : "Разговор", "Chat with the assistant" : "Пообщайтесь с ассистентом", "System prompt" : "Системная подсказка", @@ -328,6 +390,15 @@ OC.L10N.register( "The history of chat messages before the current message, starting with a message by the user" : "История сообщений в чате до текущего сообщения, начиная с сообщения пользователя", "Response message" : "Ответное сообщение", "The generated response as part of the conversation" : "Сгенерированный ответ в ходе беседы", + "Chat with tools" : "Чат с инструментами", + "Chat with the language model with tool calling support." : "Чат с языковой моделью с поддержкой вызова инструментов.", + "Tool message" : "Сообщение инструмента", + "The result of tool calls in the last interaction" : "Результат вызова инструментов в последнем взаимодействии", + "Available tools" : "Доступные инструменты", + "The available tools in JSON format" : "Доступные инструменты в формате JSON", + "The response from the chat model" : "Ответ от чат-модели", + "Tool calls" : "Вызовы инструментов", + "Tools call instructions from the model in JSON format" : "Инструкции по вызову инструментов от модели в формате JSON", "Formalize text" : "Формализовать текст", "Takes a text and makes it sound more formal" : "Берется текст и делает его звучание более формальным", "Write a text that you want the assistant to formalize" : "Напишите текст, который вы хотите, чтобы ассистент оформил официально", @@ -338,6 +409,12 @@ OC.L10N.register( "Original text" : "Оригинальный текст", "The original text to generate a headline for" : "Исходный текст для создания заголовка для", "The generated headline" : "Сгенерированный заголовок", + "Proofread" : "Проверка правописания", + "Proofreads a text and lists corrections" : "Проверяет текст и показывает исправления", + "Text" : "Текст", + "The text to proofread" : "Текст для проверки", + "Corrections" : "Исправления", + "The corrections that should be made in your text" : "Исправления, которые следует внести в ваш текст", "Reformulate text" : "Переформулировать текст", "Takes a text and reformulates it" : "Берет текст и переформулирует его", "Write a text that you want the assistant to reformulate" : "Напишите текст, который вы хотите, чтобы ассистент переформулировал", @@ -373,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Сгенерировать заголовок", "Summarizes text by reducing its length without losing key information." : "Обобщает текст, сокращая его длину без потери ключевой информации.", "Extracts topics from a text and outputs them separated by commas." : "Извлекает темы из текста и выводит их через запятую.", - "Education Edition" : "Набор приложений для образовательных учреждений", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Для доступа к этому параметру необходимо состоять в группе администраторов, суб-администраторов или иметь специальные права", - "Logged in user must be an admin or sub admin" : "Вошедший в систему пользователь должен обладать правами администратора или суб-администратора", - "Logged in user must be an admin" : "Вошедший в систему пользователь должен обладать правами администратора", - "File name is a reserved word" : "Имя файла является зарезервированным словом", - "File name contains at least one invalid character" : "Имя файла содержит по крайней мере один недопустимый символ", - "File name is too long" : "Имя файла слишком длинное.", - "Help" : "Помощь", - "Users" : "Пользователи", - "Unknown user" : "Неизвестный пользователь", - "Enter the database username and name for %s" : "Укажите имя пользователя и название базы данных %s", - "Enter the database username for %s" : "Укажите имя пользователя базы данных %s", - "MySQL username and/or password not valid" : "Неверное имя пользователя и/или пароль для подключения к MySQL", - "Oracle username and/or password not valid" : "Неверное имя пользователя и/или пароль Oracle", - "PostgreSQL username and/or password not valid" : "Неверное имя пользователя и/или пароль PostgreSQL", - "Set an admin username." : "Задать имя пользователя для администратора.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s предоставил(а) вам доступ к «%2$s» и хочет добавить:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s предоставил(а) вам доступ к «%2$s» и хочет добавить", - "»%s« added a note to a file shared with you" : "%s добавил(а) примечание к файлу, к которому вам открыт доступ", - "Open »%s«" : "Открыть «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "Не удалось поделиться %s, так как элемент находится в общем доступе у %s", - "%1$s shared »%2$s« with you" : "%1$s предоставил(а) вам доступ к «%2$s»", - "%1$s shared »%2$s« with you." : "%1$s предоставил(а) вам доступ к «%2$s».", - "The username is already being used" : "Имя пользователя уже используется", - "Could not create user" : "Не удалось создать пользователя", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "В имени пользователя допускаются следующие символы: «a–z», «A–Z», «0–9» и «_.@-'»", - "A valid username must be provided" : "Укажите допустимое имя пользователя", - "Username contains whitespace at the beginning or at the end" : "Имя пользователя содержит пробел в начале или в конце", - "Username must not consist of dots only" : "Имя пользователя должно состоять не только из точек", - "Username is invalid because files already exist for this user" : "Это имя не может быть использовано, файлы этого пользователя уже существуют", - "User disabled" : "Пользователь отключен", + "Organisation" : "Организация", "File is currently busy, please try again later" : "Файл в данный момент используется, повторите попытку позже.", "Cannot download file" : "Не удалось скачать файл", - "Your data directory is readable by other users." : "Каталог данных доступен для чтения другим пользователям.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Измените права доступа на 0770, чтобы другие пользователи не могли получить список файлов этого каталога.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Убедитесь, что в корне каталога данных присутствует файл «.ocdata»." + "Login is too long" : "Имя пользователя слишком длинное" }, "nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"); diff --git a/lib/l10n/ru.json b/lib/l10n/ru.json index fb503d493a9..47b6f13d325 100644 --- a/lib/l10n/ru.json +++ b/lib/l10n/ru.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Требуется сервер версии %s или выше.", "Server version %s or lower is required." : "Требуется сервер версии %s или ниже.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Для доступа к этой настройке зарегистрированная учетная запись должна быть администратором, субадминистратором или иметь специальные права", - "Your current IP address doesn’t allow you to perform admin actions" : "Ваш текущий IP-адрес не позволяет вам выполнять административные действи", + "Your current IP address doesn't allow you to perform admin actions" : "Ваш текущий IP-адрес не позволяет вам выполнять действия администратора.", "Logged in account must be an admin or sub admin" : "Зарегистрированная учетная запись должна быть администратором или субадминистратором", "Logged in account must be an admin" : "Вошедший в систему пользователь должен быть администратором", "Wiping of device %s has started" : "Удаление данных с устройства «%s».", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Изображение аватара не квадратное", "Files" : "Файлы", "View profile" : "Открыть профиль", + "same time" : "в то же время", + "_%nh_::_%nh_" : ["%nч","%nч","%nч","%nч"], + "_%nm_::_%nm_" : ["%nм","%nм","%n м","%n м"], + "%s ahead" : "%s вперёд", + "%s behind" : "%s позади", "Local time: %s" : "Местное время: %s", "today" : "сегодня", "tomorrow" : "завтра", @@ -79,7 +84,15 @@ "seconds ago" : "несколько секунд назад", "Empty file" : "Пустой файл", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Модуль с ID «%s» не существует. Включите его в настройках приложений или обратитесь к администратору.", + "No file conversion providers available" : "Нет доступных поставщиков услуг конвертации файлов", + "File is too large to convert" : "Файл слишком большой для преобразования", + "Destination does not match conversion extension" : "Назначение не соответствует расширению преобразования", + "Could not convert file" : "Не удалось преобразовать файл", + "Destination does not exist" : "Пункт назначения не существует", + "Destination is not creatable" : "Место назначения не может быть создано", "Dot files are not allowed" : "Файлы начинающиеся с точки не допускаются", + "%1$s (renamed)" : "%1$s (переименовано)", + "renamed file" : "переименованный файл", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" это запрещенное имя файла или папки.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" является запрещенным префиксом для имен файлов или папок.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" не допускается указывать имя файла или папки внутри него.", @@ -90,6 +103,13 @@ "Invalid path" : "Некорректный путь", "Failed to create file from template" : "Не удалось создать файл на основе шаблона", "Templates" : "Шаблоны", + "Storage %s cannot be moved" : "Хранилище %s не может быть перемещено", + "Moving a share (%s) into a shared folder is not allowed" : "Перемещение общего ресурса (%s) в общую папку запрещено", + "Moving a storage (%s) into a shared folder is not allowed" : "Перемещение хранилища (%s) в общую папку запрещено", + "Moving a share (%s) into another share (%s) is not allowed" : "Перемещение общего ресурса (%s) в другой общий ресурс (%s) запрещено", + "Moving a share (%s) into another storage (%s) is not allowed" : "Перемещение общего ресурса (%s) в другое хранилище (%s) запрещено", + "Moving a storage (%s) into a share (%s) is not allowed" : "Перемещение хранилища (%s) в общий ресурс (%s) запрещено", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Перемещение хранилища (%s) в другое хранилище (%s) запрещено", "Path contains invalid segments" : "Путь содержит недопустимые сегменты", "Filename is a reserved word" : "Имя файла - это зарезервированное слово", "Filename contains at least one invalid character" : "Имя файла содержит как минимум один недопустимый символ", @@ -122,8 +142,9 @@ "About" : "О себе", "Display name" : "Отображаемое имя", "Headline" : "Заголовок", - "Organisation" : "Организация", + "Organization" : "Организация", "Role" : "Роль", + "Pronouns" : "Местоимения", "Unknown account" : "Неизвестный аккаунт", "Additional settings" : "Дополнительные настройки", "Enter the database Login and name for %s" : "Введите логин и имя пользователя базы данных для %s", @@ -135,7 +156,7 @@ "Oracle connection could not be established" : "Соединение с Oracle не может быть установлено", "Oracle Login and/or password not valid" : "Неверный логин и/или пароль Oracle", "PostgreSQL Login and/or password not valid" : "Неверный логин и/или пароль для PostgreSQL", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не поддерживается и %s может работать некорректно на данной платформе. Используйте на свой страх и риск!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X не поддерживается, и %s может работать некорректно на этой платформе. Используйте на свой страх и риск!", "For the best results, please consider using a GNU/Linux server instead." : "Для достижения наилучших результатов, рассмотрите вариант использования сервера на GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Кажется что экземпляр этого %s работает в 32-битной среде PHP и в php.ini был настроен open_basedir. Это приведёт к проблемам с файлами более 4 ГБ и настоятельно не рекомендуется.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Удалите директиву open_basedir из файла php.ini или смените PHP на 64-разрядную сборку.", @@ -145,14 +166,27 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Бэкенд общего доступа %s должен реализовывать интерфейс OCP\\Share_Backend", "Sharing backend %s not found" : "Механизм предоставления общего доступа %s не найден", "Sharing backend for %s not found" : "Не найден механизм предоставления общего доступа для %s ", - "Click the button below to open it." : "Нажмите расположенную ниже кнопку для перехода к полученному общему ресурсу.", + "%1$s shared %2$s with you" : "%1$s поделился(ась) %2$s с вами", "Open %s" : "Открыть %s", "%1$s via %2$s" : "%1$s через %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s поделился(ась) %2$s с вами и хочет добавить:", + "%1$s shared %2$s with you and wants to add" : "%1$s поделился(ась) %2$s с вами и хочет добавить", + "%s added a note to a file shared with you" : "%s добавил(а) заметку к файлу, которым поделился(ась) с вами", "Passwords are enforced for link and mail shares" : "Для общих ссылок и почтовых рассылок применяются пароли", + "Share recipient is not a valid user" : "Получатель общего ресурса — некорректный пользователь", + "Share recipient is not a valid group" : "Получатель общего ресурса — некорректная группа", + "Share recipient should be empty" : "Получатель общего ресурса должен быть пустым", + "Share recipient should not be empty" : "Получатель общего ресурса не должен быть пустым", + "Share recipient is not a valid circle" : "Получатель общего ресурса — некорректный круг", "Unknown share type" : "Общий доступ неизвестного типа", + "Share initiator must be set" : "Должен быть задан инициатор общего ресурса", "Cannot share with yourself" : "Не могу поделиться с самим собой", + "Shared path must be set" : "Должен быть указан путь к общему ресурсу", + "Shared path must be either a file or a folder" : "Путь должен указывать на файл или папку", "You cannot share your root folder" : "Вы не можете предоставить общий доступ к своей корневой папке", "You are not allowed to share %s" : "Вам не разрешено делиться %s", + "Valid permissions are required for sharing" : "Для общего ресурса необходимы корректные права", + "File shares cannot have create or delete permissions" : "Для файловых общих ресурсов нельзя задавать права доступа на создание или удаление", "Cannot increase permissions of %s" : "Не удалось повысить права доступа %s", "Shares need at least read permissions" : "Общим ресурсам требуются как минимум разрешения на чтение", "Files cannot be shared with delete permissions" : "Права на удаление файлов не позволяют открывать общий доступ к ним", @@ -167,7 +201,7 @@ "Path is already shared with this group" : "Путь уже является общим для этой группы", "Link sharing is not allowed" : "Обмен ссылками запрещен", "Public upload is not allowed" : "Публичная загрузка данных запрещена", - "Path contains files shared with you" : "Путь содержит файлы, к которым вы предоставили общий доступ", + "You cannot share a folder that contains other shares" : "Нельзя делиться папкой, содержащей другие общие ресурсы", "Sharing is disabled" : "Общий доступ отключен", "Sharing is disabled for you" : "Общий доступ для вас отключен", "Cannot share with the share owner" : "Невозможно поделиться с владельцем общего доступа", @@ -179,6 +213,7 @@ "Cannot disable sending the password by Talk without setting a new password" : "Невозможно отключить отправку пароля по телефону без установки нового пароля", "Share provider does not support accepting" : "Поставщик общего доступа не поддерживает прием", "Cannot change target of link share" : "Невозможно изменить цель публикации ссылки", + "Invalid share recipient" : "Некорректный получатель общего ресурса", "Group \"%s\" does not exist" : "Группа \"%s\" не существует", "The requested share does not exist anymore" : "Запрошенный общий ресурс более не существует.", "The requested share comes from a disabled user" : "Запрос на общий доступ поступает от отключенного пользователя", @@ -238,6 +273,7 @@ "A valid Login must be provided" : "Необходимо указать действительный логин для входа в систему", "Login contains whitespace at the beginning or at the end" : "Имя пользователя содержит пробелы в начале или в конце", "Login must not consist of dots only" : "Логин не должен состоять только из точек", + "Username is too long" : "Имя пользователя слишком длинное", "Login is invalid because files already exist for this user" : "Логин недействителен, поскольку файлы для этого пользователя уже существуют", "Account disabled" : "Учетная запись отключена", "Login canceled by app" : "Вход отменен приложением", @@ -294,8 +330,19 @@ "The audio to transcribe" : "Аудио для расшифровки", "Transcription" : "Транскрипция", "The transcribed text" : "Расшифрованный текст", + "Chat with an agent" : "Чат с агентом", "Chat message" : "Сообщение в чате", + "A chat message to send to the agent." : "Сообщение для отправки агенту", "Confirmation" : "Подтверждение", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Подтвердить ранее запрошенные действия: 0 — отказ, 1 — подтверждение.", + "Conversation token" : "Токен беседы", + "A token representing the conversation." : "Токен, представляющий беседу.", + "Generated response" : "Сгенерированный ответ", + "The response from the chat model." : "Ответ от модели чата.", + "The new conversation token" : "Новый токен беседы", + "Send this along with the next interaction." : "Отправьте его при следующем взаимодействии.", + "Requested actions by the agent" : "Запрошенные действия от агента", + "Actions that the agent would like to carry out in JSON format." : "Действия, которые агент хотел бы выполнить в формате JSON.", "Context write" : "Контекстная запись", "Writes text in a given style based on the provided source material." : "Пишет текст в заданном стиле на основе предоставленного исходного материала.", "Writing style" : "Стиль письма", @@ -306,18 +353,33 @@ "The generated text with content from the source material in the given style" : "Сгенерированный текст с содержимым из исходного материала в заданном стиле", "Emoji generator" : "Генератор Emoji", "Takes text and generates a representative emoji for it." : "Берет текст и генерирует для него репрезентативный смайлик.", + "The text to generate an emoji for" : "Текст для создания эмодзи", + "Generated emoji" : "Созданный эмодзи", + "The generated emoji based on the input text" : "Эмодзи, созданный на основе введённого текста", "Generate image" : "Генерировать изображение", "Generate an image from a text prompt" : "Создайте изображение из текстовой подсказки", + "Prompt" : "Подсказка", "Describe the image you want to generate" : "Опишите изображение, которое вы хотите создать", "Number of images" : "Количество изображений", "How many images to generate" : "Сколько изображений генерировать", "Output images" : "Выходные изображения", "The generated images" : "Сгенерированные изображения", + "Generate speech" : "Сгенерировать речь", + "Generate speech from a transcript" : "Сгенерировать речь из транскрипта", + "Write transcript that you want the assistant to generate speech from" : "Введите транскрипт, по которому ассистент должен сгенерировать речь", + "Output speech" : "Выходное аудио", + "The generated speech" : "Сгенерированная речь", "Free text to text prompt" : "Произвольное преобразование текста в текстовую подсказку", "Runs an arbitrary prompt through a language model that returns a reply" : "Запускает произвольный запрос с помощью языковой модели, которая возвращает ответ", "Describe a task that you want the assistant to do or ask a question" : "Опишите задачу, которую вы хотите поручить ассистенту, или задайте вопрос", "Generated reply" : "Сгенерированный ответ", "The generated text from the assistant" : "Сгенерированный текст от помощника", + "Change Tone" : "Сменить тон", + "Change the tone of a piece of text." : "Изменить тон текста", + "Write a text that you want the assistant to rewrite in another tone." : "Напишите текст, чтобы ассистент переписал его в другом тоне.", + "Desired tone" : "Желаемый тон", + "In which tone should your text be rewritten?" : "В каком тоне следует переписать ваш текст?", + "The rewritten text in the desired tone, written by the assistant:" : "Переписанный текст в нужном тоне, написанный ассистентом:", "Chat" : "Разговор", "Chat with the assistant" : "Пообщайтесь с ассистентом", "System prompt" : "Системная подсказка", @@ -326,6 +388,15 @@ "The history of chat messages before the current message, starting with a message by the user" : "История сообщений в чате до текущего сообщения, начиная с сообщения пользователя", "Response message" : "Ответное сообщение", "The generated response as part of the conversation" : "Сгенерированный ответ в ходе беседы", + "Chat with tools" : "Чат с инструментами", + "Chat with the language model with tool calling support." : "Чат с языковой моделью с поддержкой вызова инструментов.", + "Tool message" : "Сообщение инструмента", + "The result of tool calls in the last interaction" : "Результат вызова инструментов в последнем взаимодействии", + "Available tools" : "Доступные инструменты", + "The available tools in JSON format" : "Доступные инструменты в формате JSON", + "The response from the chat model" : "Ответ от чат-модели", + "Tool calls" : "Вызовы инструментов", + "Tools call instructions from the model in JSON format" : "Инструкции по вызову инструментов от модели в формате JSON", "Formalize text" : "Формализовать текст", "Takes a text and makes it sound more formal" : "Берется текст и делает его звучание более формальным", "Write a text that you want the assistant to formalize" : "Напишите текст, который вы хотите, чтобы ассистент оформил официально", @@ -336,6 +407,12 @@ "Original text" : "Оригинальный текст", "The original text to generate a headline for" : "Исходный текст для создания заголовка для", "The generated headline" : "Сгенерированный заголовок", + "Proofread" : "Проверка правописания", + "Proofreads a text and lists corrections" : "Проверяет текст и показывает исправления", + "Text" : "Текст", + "The text to proofread" : "Текст для проверки", + "Corrections" : "Исправления", + "The corrections that should be made in your text" : "Исправления, которые следует внести в ваш текст", "Reformulate text" : "Переформулировать текст", "Takes a text and reformulates it" : "Берет текст и переформулирует его", "Write a text that you want the assistant to reformulate" : "Напишите текст, который вы хотите, чтобы ассистент переформулировал", @@ -371,41 +448,9 @@ "Generate headline" : "Сгенерировать заголовок", "Summarizes text by reducing its length without losing key information." : "Обобщает текст, сокращая его длину без потери ключевой информации.", "Extracts topics from a text and outputs them separated by commas." : "Извлекает темы из текста и выводит их через запятую.", - "Education Edition" : "Набор приложений для образовательных учреждений", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Для доступа к этому параметру необходимо состоять в группе администраторов, суб-администраторов или иметь специальные права", - "Logged in user must be an admin or sub admin" : "Вошедший в систему пользователь должен обладать правами администратора или суб-администратора", - "Logged in user must be an admin" : "Вошедший в систему пользователь должен обладать правами администратора", - "File name is a reserved word" : "Имя файла является зарезервированным словом", - "File name contains at least one invalid character" : "Имя файла содержит по крайней мере один недопустимый символ", - "File name is too long" : "Имя файла слишком длинное.", - "Help" : "Помощь", - "Users" : "Пользователи", - "Unknown user" : "Неизвестный пользователь", - "Enter the database username and name for %s" : "Укажите имя пользователя и название базы данных %s", - "Enter the database username for %s" : "Укажите имя пользователя базы данных %s", - "MySQL username and/or password not valid" : "Неверное имя пользователя и/или пароль для подключения к MySQL", - "Oracle username and/or password not valid" : "Неверное имя пользователя и/или пароль Oracle", - "PostgreSQL username and/or password not valid" : "Неверное имя пользователя и/или пароль PostgreSQL", - "Set an admin username." : "Задать имя пользователя для администратора.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s предоставил(а) вам доступ к «%2$s» и хочет добавить:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s предоставил(а) вам доступ к «%2$s» и хочет добавить", - "»%s« added a note to a file shared with you" : "%s добавил(а) примечание к файлу, к которому вам открыт доступ", - "Open »%s«" : "Открыть «%s»", - "Sharing %s failed, because this item is already shared with user %s" : "Не удалось поделиться %s, так как элемент находится в общем доступе у %s", - "%1$s shared »%2$s« with you" : "%1$s предоставил(а) вам доступ к «%2$s»", - "%1$s shared »%2$s« with you." : "%1$s предоставил(а) вам доступ к «%2$s».", - "The username is already being used" : "Имя пользователя уже используется", - "Could not create user" : "Не удалось создать пользователя", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "В имени пользователя допускаются следующие символы: «a–z», «A–Z», «0–9» и «_.@-'»", - "A valid username must be provided" : "Укажите допустимое имя пользователя", - "Username contains whitespace at the beginning or at the end" : "Имя пользователя содержит пробел в начале или в конце", - "Username must not consist of dots only" : "Имя пользователя должно состоять не только из точек", - "Username is invalid because files already exist for this user" : "Это имя не может быть использовано, файлы этого пользователя уже существуют", - "User disabled" : "Пользователь отключен", + "Organisation" : "Организация", "File is currently busy, please try again later" : "Файл в данный момент используется, повторите попытку позже.", "Cannot download file" : "Не удалось скачать файл", - "Your data directory is readable by other users." : "Каталог данных доступен для чтения другим пользователям.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Измените права доступа на 0770, чтобы другие пользователи не могли получить список файлов этого каталога.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Убедитесь, что в корне каталога данных присутствует файл «.ocdata»." + "Login is too long" : "Имя пользователя слишком длинное" },"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);" }
\ No newline at end of file diff --git a/lib/l10n/sc.js b/lib/l10n/sc.js index bf87a0b74fd..8285dd4635c 100644 --- a/lib/l10n/sc.js +++ b/lib/l10n/sc.js @@ -46,6 +46,7 @@ OC.L10N.register( "Avatar image is not square" : "S'immàgine de s'avatar no est cuadrada", "Files" : "Archìvios", "View profile" : "Ammustra su profilu", + "_%nh_::_%nh_" : ["%nh","%nh"], "today" : "oe", "tomorrow" : "cras", "yesterday" : "eris", @@ -92,12 +93,11 @@ OC.L10N.register( "About" : "In contu de", "Display name" : "Ammustra nùmene", "Headline" : "Tìtulos", - "Organisation" : "Organizatzione", + "Organization" : "Organizatzione", "Role" : "Faina", "Additional settings" : "Cunfiguratziones in agiunta", "You need to enter details of an existing account." : "Nche depes insertare is detàllios de unu contu chi b'est giai.", "Oracle connection could not be established" : "No at fatu a istabilire sa connessione Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X no est suportadu e %s no at a funtzionare in manera curreta in custa prataforma. Imprea•ddu a arriscu tuo!", "For the best results, please consider using a GNU/Linux server instead." : "Pro su mellus resurtadu, cunsidera in càmbiu de impreare unu serbidore GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Parit ca custa istàntzia %s est traballende in un'ambiente PHP a 32-bit e sa open_basedir est istada cunfigurada in php.ini. Custu at a causare problemas cun archìvios de prus de 4 GB e est iscussigiadu a forte.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Boga·nche sa cunfiguratzione open_basedir in su php.ini tuo o càmbia a su PHP a 64-bit.", @@ -106,7 +106,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Su motore de cumpartzidura %s depet cumpletare s'interfache OCP\\Share_Backend", "Sharing backend %s not found" : "Motore de cumpartzidura%s no agatadu", "Sharing backend for %s not found" : "Motore de cumpartzidura pro %s no agatadu", - "Click the button below to open it." : "Incarca su butone a suta pro dd'abèrrere.", "%1$s via %2$s" : "%1$s cun %2$s", "Unknown share type" : "Genia de cumpartzidura disconnota", "Shared path must be either a file or a folder" : "Su percursu cumpartzidu depet èssere un'archìviu o una cartella", @@ -197,39 +196,12 @@ OC.L10N.register( "Generates a possible headline for a text." : "Gènerat unu tìtulu possìbile pro unu testu.", "The original text to generate a headline for" : "Su testu originale pro su chi s'at a generare unu tìtulu", "The generated headline" : "Su tìtulu generadu", + "Text" : "Testu", "Summary" : "Resumu", "Translate" : "Borta", "Result" : "Resurtadu", "Generate headline" : "Gènera unu tìtulu", - "Education Edition" : "Editzione didàtica", - "Logged in user must be an admin or sub admin" : "S'utente devet essere de s'amministratzione o de sa suta-amministratzione ", - "Logged in user must be an admin" : "S'utente devet essere de s'amministratzione ", - "File name is a reserved word" : "Su nùmene de s'archìviu est unu faeddu riservadu", - "File name contains at least one invalid character" : "Su nùmene de s'archìviu cuntenet a su mancu unu caràtere imbàlidu", - "File name is too long" : "Su nùmene de s'archìviu est tropu longu", - "Help" : "Agiudu", - "Users" : "Utentes", - "Unknown user" : "Utèntzia disconnota", - "MySQL username and/or password not valid" : "Su nùmene utente e/o sa crae de MySQL no sunt bàlidos", - "Oracle username and/or password not valid" : "Su nùmene utente e/o sa crae de Oracle no sunt bàlidos", - "PostgreSQL username and/or password not valid" : "Su nùmene utente e/o sa crae de Postgre SQL no sunt bàlidos", - "Set an admin username." : "Cunfigura unu nùmene utente de amministratzione.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s at cumpartzidu »%2$s« cun tegus e bolet agiùnghere:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s at cumpartzidu »%2$s« cun tegus e bolet agiùnghere", - "»%s« added a note to a file shared with you" : "»%s« at agiuntu una nota a un'archìviu cumpartzidu cun tegus", - "Open »%s«" : "Aberi »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "No at fatu a cumpartzire %s, ca custu elementu est giai istadu cumpartzidu cun s'utente %s", - "%1$s shared »%2$s« with you" : "%1$s at cumpartzidu »%2$s cun tegus", - "%1$s shared »%2$s« with you." : "%1$s at cumpartzidu »%2$s cun tegus.", - "The username is already being used" : "Su nùmene utente est giai impreadu", - "Could not create user" : "No at fatu a creare s'utente", - "A valid username must be provided" : "Depes frunire unu nùmene utente bàlidu", - "Username contains whitespace at the beginning or at the end" : "Su nùmene utente cuntenet ispàtzios bòidos a su cumintzu o a sa fine", - "Username must not consist of dots only" : "Su nùmene utente no depet tènnere isceti puntos", - "Username is invalid because files already exist for this user" : "Su nùmene utente no est bàlidu, ca is archìvios bi sunt giai pro cust'utèntzia", - "User disabled" : "Utèntzia disativada", - "File is currently busy, please try again later" : "Pro immoe s'archìviu est impreadu, torra a proare a coa", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Càmbia is permissos a 0770 aici sa cartella no podet èssere in is elencos de àteras utèntzias.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assegura•ti chi in sa cartella de datos de orìgine nche siat un'archìviu cun nùmene \".ocdata\"." + "Organisation" : "Organizatzione", + "File is currently busy, please try again later" : "Pro immoe s'archìviu est impreadu, torra a proare a coa" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/sc.json b/lib/l10n/sc.json index ee247837df8..9158f9ef18a 100644 --- a/lib/l10n/sc.json +++ b/lib/l10n/sc.json @@ -44,6 +44,7 @@ "Avatar image is not square" : "S'immàgine de s'avatar no est cuadrada", "Files" : "Archìvios", "View profile" : "Ammustra su profilu", + "_%nh_::_%nh_" : ["%nh","%nh"], "today" : "oe", "tomorrow" : "cras", "yesterday" : "eris", @@ -90,12 +91,11 @@ "About" : "In contu de", "Display name" : "Ammustra nùmene", "Headline" : "Tìtulos", - "Organisation" : "Organizatzione", + "Organization" : "Organizatzione", "Role" : "Faina", "Additional settings" : "Cunfiguratziones in agiunta", "You need to enter details of an existing account." : "Nche depes insertare is detàllios de unu contu chi b'est giai.", "Oracle connection could not be established" : "No at fatu a istabilire sa connessione Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X no est suportadu e %s no at a funtzionare in manera curreta in custa prataforma. Imprea•ddu a arriscu tuo!", "For the best results, please consider using a GNU/Linux server instead." : "Pro su mellus resurtadu, cunsidera in càmbiu de impreare unu serbidore GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Parit ca custa istàntzia %s est traballende in un'ambiente PHP a 32-bit e sa open_basedir est istada cunfigurada in php.ini. Custu at a causare problemas cun archìvios de prus de 4 GB e est iscussigiadu a forte.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Boga·nche sa cunfiguratzione open_basedir in su php.ini tuo o càmbia a su PHP a 64-bit.", @@ -104,7 +104,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Su motore de cumpartzidura %s depet cumpletare s'interfache OCP\\Share_Backend", "Sharing backend %s not found" : "Motore de cumpartzidura%s no agatadu", "Sharing backend for %s not found" : "Motore de cumpartzidura pro %s no agatadu", - "Click the button below to open it." : "Incarca su butone a suta pro dd'abèrrere.", "%1$s via %2$s" : "%1$s cun %2$s", "Unknown share type" : "Genia de cumpartzidura disconnota", "Shared path must be either a file or a folder" : "Su percursu cumpartzidu depet èssere un'archìviu o una cartella", @@ -195,39 +194,12 @@ "Generates a possible headline for a text." : "Gènerat unu tìtulu possìbile pro unu testu.", "The original text to generate a headline for" : "Su testu originale pro su chi s'at a generare unu tìtulu", "The generated headline" : "Su tìtulu generadu", + "Text" : "Testu", "Summary" : "Resumu", "Translate" : "Borta", "Result" : "Resurtadu", "Generate headline" : "Gènera unu tìtulu", - "Education Edition" : "Editzione didàtica", - "Logged in user must be an admin or sub admin" : "S'utente devet essere de s'amministratzione o de sa suta-amministratzione ", - "Logged in user must be an admin" : "S'utente devet essere de s'amministratzione ", - "File name is a reserved word" : "Su nùmene de s'archìviu est unu faeddu riservadu", - "File name contains at least one invalid character" : "Su nùmene de s'archìviu cuntenet a su mancu unu caràtere imbàlidu", - "File name is too long" : "Su nùmene de s'archìviu est tropu longu", - "Help" : "Agiudu", - "Users" : "Utentes", - "Unknown user" : "Utèntzia disconnota", - "MySQL username and/or password not valid" : "Su nùmene utente e/o sa crae de MySQL no sunt bàlidos", - "Oracle username and/or password not valid" : "Su nùmene utente e/o sa crae de Oracle no sunt bàlidos", - "PostgreSQL username and/or password not valid" : "Su nùmene utente e/o sa crae de Postgre SQL no sunt bàlidos", - "Set an admin username." : "Cunfigura unu nùmene utente de amministratzione.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s at cumpartzidu »%2$s« cun tegus e bolet agiùnghere:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s at cumpartzidu »%2$s« cun tegus e bolet agiùnghere", - "»%s« added a note to a file shared with you" : "»%s« at agiuntu una nota a un'archìviu cumpartzidu cun tegus", - "Open »%s«" : "Aberi »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "No at fatu a cumpartzire %s, ca custu elementu est giai istadu cumpartzidu cun s'utente %s", - "%1$s shared »%2$s« with you" : "%1$s at cumpartzidu »%2$s cun tegus", - "%1$s shared »%2$s« with you." : "%1$s at cumpartzidu »%2$s cun tegus.", - "The username is already being used" : "Su nùmene utente est giai impreadu", - "Could not create user" : "No at fatu a creare s'utente", - "A valid username must be provided" : "Depes frunire unu nùmene utente bàlidu", - "Username contains whitespace at the beginning or at the end" : "Su nùmene utente cuntenet ispàtzios bòidos a su cumintzu o a sa fine", - "Username must not consist of dots only" : "Su nùmene utente no depet tènnere isceti puntos", - "Username is invalid because files already exist for this user" : "Su nùmene utente no est bàlidu, ca is archìvios bi sunt giai pro cust'utèntzia", - "User disabled" : "Utèntzia disativada", - "File is currently busy, please try again later" : "Pro immoe s'archìviu est impreadu, torra a proare a coa", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Càmbia is permissos a 0770 aici sa cartella no podet èssere in is elencos de àteras utèntzias.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Assegura•ti chi in sa cartella de datos de orìgine nche siat un'archìviu cun nùmene \".ocdata\"." + "Organisation" : "Organizatzione", + "File is currently busy, please try again later" : "Pro immoe s'archìviu est impreadu, torra a proare a coa" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/si.js b/lib/l10n/si.js index 6b2915d16af..4c582530b60 100644 --- a/lib/l10n/si.js +++ b/lib/l10n/si.js @@ -63,10 +63,6 @@ OC.L10N.register( "November" : "නොවැම්බර්", "December" : "දෙසැම්බර්", "Summary" : "සාරාංශය", - "Translate" : "පරිවර්තනය", - "File name is too long" : "ගොනුවේ නම දිග වැඩිය", - "Help" : "උපකාර", - "Users" : "පරිශීලකයින්", - "Unknown user" : "නොදන්නා පරිශීලකයෙකි" + "Translate" : "පරිවර්තනය" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/si.json b/lib/l10n/si.json index fd5b2f45d86..79483e78d71 100644 --- a/lib/l10n/si.json +++ b/lib/l10n/si.json @@ -61,10 +61,6 @@ "November" : "නොවැම්බර්", "December" : "දෙසැම්බර්", "Summary" : "සාරාංශය", - "Translate" : "පරිවර්තනය", - "File name is too long" : "ගොනුවේ නම දිග වැඩිය", - "Help" : "උපකාර", - "Users" : "පරිශීලකයින්", - "Unknown user" : "නොදන්නා පරිශීලකයෙකි" + "Translate" : "පරිවර්තනය" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/sk.js b/lib/l10n/sk.js index 1ca316c8118..dbb955a40d8 100644 --- a/lib/l10n/sk.js +++ b/lib/l10n/sk.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Je vyžadovaná verzia servera %s alebo vyššia.", "Server version %s or lower is required." : "Je vyžadovaná verzia servera %s alebo nižšia.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Prihlásený účet musí byť správcom, podadministrátorom alebo musí mať špeciálne právo na prístup k tomuto nastaveniu.", - "Your current IP address doesn’t allow you to perform admin actions" : "Vaša aktuálna adresa IP vám neumožňuje vykonávať akcie správcu", + "Your current IP address doesn't allow you to perform admin actions" : "Vaša aktuálna adresa IP vám neumožňuje vykonávať akcie správcu", "Logged in account must be an admin or sub admin" : "Prihlásený účet musí byť správcom alebo sub správcom.", "Logged in account must be an admin" : "Prihlásený účet musí byť správcom", "Wiping of device %s has started" : "Začalo sa mazanie zariadenia %s", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Obrázok avatara nie je štvorcový", "Files" : "Súbory", "View profile" : "Zobraziť profil", + "same time" : "rovnaký čas", + "_%nh_::_%nh_" : ["%nh","%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm","%nm"], + "%s ahead" : "%s dopredu", + "%s behind" : "%s dozadu", "Local time: %s" : "Miestny čas: %s", "today" : "dnes", "tomorrow" : "zajtra", @@ -81,6 +86,12 @@ OC.L10N.register( "seconds ago" : "pred sekundami", "Empty file" : "Prázdny súbor", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s ID: %s neexistuje. Povoľte ho prosím vo vašom nastavení aplikácií alebo kontaktujte správcu.", + "No file conversion providers available" : "Nie sú dostupný žiadny poskytovatelia konverzie", + "File is too large to convert" : "Súbor je príliš veľký pre konverziu", + "Destination does not match conversion extension" : "Cieľ nesúhlasí s príponou konverzie", + "Could not convert file" : "Nemožno skonvertovať súbor", + "Destination does not exist" : "Cieľ neexistuje", + "Destination is not creatable" : "Cieľ nie je možné vytvoriť", "Dot files are not allowed" : "Názov súboru začínajúci bodkou nie je povolený.", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" je zakázané pre súbor alebo adresár", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" je zakázaná predpona pre názov súboru alebo adresára.", @@ -92,6 +103,13 @@ OC.L10N.register( "Invalid path" : "Neplatná cesta", "Failed to create file from template" : "Nemôžem vytvoriť súbor zo šablóny", "Templates" : "Šablóny", + "Storage %s cannot be moved" : "Úložisko %s nemôže byť presunuté", + "Moving a share (%s) into a shared folder is not allowed" : "Presun zdieľania (%s) do zdieľaného adresára nie je povolený", + "Moving a storage (%s) into a shared folder is not allowed" : "Presun úložiska (%s) do zdieľaného adresára nie je povolený", + "Moving a share (%s) into another share (%s) is not allowed" : "Presun zdieľania (%s) do iného zdieľania (%s) nie je povolený", + "Moving a share (%s) into another storage (%s) is not allowed" : "Presun zdieľania (%s) do iného úložiska (%s) nie je povolený", + "Moving a storage (%s) into a share (%s) is not allowed" : "Presun úložiska (%s) do zdieľania (%s) nie je povolený", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Presun úložiska (%s) do iného úložiska (%s) nie je povolený", "Path contains invalid segments" : "Cesta obsahuje neplatné časti", "Filename is a reserved word" : "Názov súboru je rezervované slovo", "Filename contains at least one invalid character" : "Názov súboru obsahuje najmenej jeden nepovolený znak", @@ -124,7 +142,6 @@ OC.L10N.register( "About" : "O aplikácii", "Display name" : "Zobrazované meno", "Headline" : "Titul", - "Organisation" : "Organizácia", "Role" : "Rola", "Pronouns" : "Zámená", "Unknown account" : "Neznámy účet", @@ -138,7 +155,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Nie je možné pripojiť sa k Oracle", "Oracle Login and/or password not valid" : "Prihlasovacie meno a/alebo heslo pre Oracle databázu je neplatné", "PostgreSQL Login and/or password not valid" : "Prihlasovacie meno a/alebo heslo pre PostgreSQL databázu je neplatné", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nie je podporovaný a %s nebude správne fungovať na tejto platforme. Použite ho na vlastné riziko!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X nie je podporovaný a %s nebude správne fungovať na tejto platforme. Použitie na vlastné riziko!", "For the best results, please consider using a GNU/Linux server instead." : "Pre dosiahnutie najlepších výsledkov, prosím zvážte použitie GNU/Linux servera.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Zdá sa, že táto inštancia %s beží v 32-bitovom prostredí PHP a v php.ini bola nastavená voľba open_basedir. To bude zdrojom problémov so súbormi väčšími ako 4GB a dôrazne sa neodporúča.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Prosím, odstráňte nastavenie open_basedir vo vašom php.ini alebo prejdite na 64-bit PHP.", @@ -149,9 +166,11 @@ OC.L10N.register( "Sharing backend %s not found" : "Backend sprístupnenia %s nebol nájdený", "Sharing backend for %s not found" : "Backend sprístupnenia pre %s nebol nájdený", "%1$s shared %2$s with you" : "%1$s s vami zdieľal %2$s ", - "Click the button below to open it." : "Pre otvorenie klienta kliknite na tlačítko nižšie.", "Open %s" : "Otvoriť %s", "%1$s via %2$s" : "%1$s cez %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s zdieľal %2$s s vami a chce pridať:", + "%1$s shared %2$s with you and wants to add" : "%1$s zdieľal %2$s s vami a chce pridať", + "%s added a note to a file shared with you" : "%s pridal poznámku k súboru ktorý s vami zdieľa", "Passwords are enforced for link and mail shares" : "Heslo je vyžadováné pre zdieľanie odkazom alebo e-mailom", "Share recipient is not a valid user" : "Príjemca zdieľania nie je platným uživateľom", "Share recipient is not a valid group" : "Príjemca zdieľania nie je platnou skupinou", @@ -166,6 +185,7 @@ OC.L10N.register( "You cannot share your root folder" : "Nemôžete zdieľať váš koreňový adresár", "You are not allowed to share %s" : "Nemôžete sprístupniť %s", "Valid permissions are required for sharing" : "Pre zdieľanie sú potrebné korektné práva", + "File shares cannot have create or delete permissions" : "Zdieľané súbory nemôžu mať oprávnenia pre vytváranie ani odstraňovanie", "Cannot increase permissions of %s" : "Nie je možné navýšiť oprávnenia pre %s", "Shares need at least read permissions" : "Zdieľanie vyžaduje minimálne práva na čítanie", "Files cannot be shared with delete permissions" : "Súbory nie je možné sprístupňovať s oprávneniami na odstránenie", @@ -180,13 +200,17 @@ OC.L10N.register( "Path is already shared with this group" : "Cesta je už zdieľaná s touto skupinou", "Link sharing is not allowed" : "Zdieľanie odkazu nie je povolené", "Public upload is not allowed" : "Verejné nahrávanie nie je povolené", - "Path contains files shared with you" : "Cesta obsahuje súbory zdieľané s vami", "Sharing is disabled" : "Zdieľanie je zakázané", "Sharing is disabled for you" : "Zdieľanie je pre vás zakázané", "Cannot share with the share owner" : "Nie je možné zdieľať s vlastníkom", "Share does not have a full ID" : "Zdieľanie nemá plné ID", "Cannot change share type" : "Nie je možné zmeniť typ zdieľania", "Can only update recipient on user shares" : "Príjemcu je možné aktualizovať iba v užívateľských zdieľaniach", + "Cannot enable sending the password by Talk with an empty password" : "Nie je možné povoliť odosielanie hesla službou Rozhovor/Talk s prázdnym heslom", + "Cannot enable sending the password by Talk without setting a new password" : "Nie je možné povoliť odosielanie hesla službou Rozhovor/Talk bez nastavenia nového hesla", + "Cannot disable sending the password by Talk without setting a new password" : "Nie je možné zakázať odosielanie hesla službou Rozhovor/Talk bez nastavenia nového hesla", + "Share provider does not support accepting" : "Poskytovateľ zdieľania nepodporuje prijímanie", + "Cannot change target of link share" : "Nie je možné zmeniť cieľ zdieľaného odkazu", "Invalid share recipient" : "Neplatný príjemca zdieľania", "Group \"%s\" does not exist" : "Skupina \"%s\" neexistuje", "The requested share does not exist anymore" : "Požadované zdieľanie už neexistuje", @@ -284,6 +308,7 @@ OC.L10N.register( "Your data directory must be an absolute path." : "Priečinok s dátami musí byť zadaný ako absolútna cesta.", "Check the value of \"datadirectory\" in your configuration." : "Skontrolujte hodnotu \"datadirectory\" vo vašej konfigurácii.", "Your data directory is invalid." : "Priečinok pre dáta je neplatný.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Uistite sa, že v koreňovom adresári údajov je súbor s názvom \"%1$s\". Mal by mať obsah: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Akcia \"%s\" nie je podporovaná alebo implementovaná.", "Authentication failed, wrong token or provider ID given" : "Autentifikácia zlyhala, bol zadaný neplatný token alebo ID poskytovateľa", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Pre dokončenie požiadavky chýbajú parametre. Chýbajúce parametre: \"%s\"", @@ -302,8 +327,19 @@ OC.L10N.register( "The audio to transcribe" : "Zvuk pre prepísanie", "Transcription" : "Prepis", "The transcribed text" : "Prepísaný text", + "Chat with an agent" : "Čet s agentom", "Chat message" : "Správa chatu", + "A chat message to send to the agent." : "Správa četu pre poslanie agentovi.", "Confirmation" : "Potvrdenie", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Či potvrdiť predtým požadované akcie: 0 pre odmietnutie a 1 pre potvrdenie.", + "Conversation token" : "Token konverzácie", + "A token representing the conversation." : "Token reprezentujúci konverzáciu.", + "Generated response" : "Vygenerovaná odpoveď", + "The response from the chat model." : "Odpoveď z modelu četu.", + "The new conversation token" : "Nový token konverzácie", + "Send this along with the next interaction." : "Odoslať to spolu s ďalšou interakciou.", + "Requested actions by the agent" : "Vyžiadané akcie agentom", + "Actions that the agent would like to carry out in JSON format." : "Akcie, ktoré by chcel agent vykonať vo formáte JSON.", "Context write" : "Kontextový zápis", "Writes text in a given style based on the provided source material." : "Napíše text v danom štýle na základe poskytnutého zdrojového materiálu.", "Writing style" : "Štýl písania", @@ -325,13 +361,37 @@ OC.L10N.register( "How many images to generate" : "Koľko obrázkov sa bude generovať", "Output images" : "Výstupné obrázky", "The generated images" : "Vygenerované obrázky", + "Free text to text prompt" : "Výzva pre voľný text na text", + "Runs an arbitrary prompt through a language model that returns a reply" : "Spustí ľubovoľnú výzvu cez jazykový model, ktorý vráti odpoveď", + "Describe a task that you want the assistant to do or ask a question" : "Opíšte úlohu, ktorú má asistent vykonať, alebo položte otázku", "Generated reply" : "Vygenerovaná odpoveď", + "The generated text from the assistant" : "Generovaný text od asistenta", + "Change Tone" : "Zmeniť tón", + "Change the tone of a piece of text." : "Zmeniť tón časti textu", + "Write a text that you want the assistant to rewrite in another tone." : "Napíšte text pre ktorý chcete aby asistent prepísal v inom tóne.", + "Desired tone" : "Požadovaný tón", + "In which tone should your text be rewritten?" : "V akom tóne by mal byť váš text prepísaný?", + "The rewritten text in the desired tone, written by the assistant:" : "Prepísaný text v požadovanom tóne, napísaný asistentom:", "Chat" : "Chat", "Chat with the assistant" : "Chat s asistentom", "System prompt" : "Systémová výzva", + "Define rules and assumptions that the assistant should follow during the conversation." : "Definovať pravidlá a predpoklady, ktoré by mal asistent počas rozhovoru dodržiavať.", "Chat history" : "História chatu", + "The history of chat messages before the current message, starting with a message by the user" : "História četových správ pred aktuálnou správou, počnúc správou od užívateľa", "Response message" : "Správa s odpoveďou", + "The generated response as part of the conversation" : "Vygenerovaná odpoveď ako súčasť konverzácie", + "Chat with tools" : "Čet s nástrojom", + "Chat with the language model with tool calling support." : "Chatujte s jazykovým modelom s podporou volania pomocou nástroja.", + "Tool message" : "Správa nástroja", + "The result of tool calls in the last interaction" : "Výsledok volaní nástroja v poslednej interakcii", + "Available tools" : "Dostupné nástroje", + "The available tools in JSON format" : "Dostupné nástroje vo formáte JSON", + "The response from the chat model" : "Odpoveď z modelu četu", + "Tool calls" : "Žiadosti nástroja", + "Tools call instructions from the model in JSON format" : "Inštrukcie volaní nástroja z modelu v JSON formáte", "Formalize text" : "Formalizovať text", + "Takes a text and makes it sound more formal" : "Zobrať text a urobiť ho viac formálnym", + "Write a text that you want the assistant to formalize" : "Napíšte text ktorý chcete štylyzovať asistentom", "Formalized text" : "Formalizovaný text", "The formalized text" : "Formalizovaný text", "Generate a headline" : "Vygenerovať titulok", @@ -339,6 +399,12 @@ OC.L10N.register( "Original text" : "Originálny text", "The original text to generate a headline for" : "Originálny text pre ktorý sa vygeneruje titulok", "The generated headline" : "Vygenerovaný titulok", + "Proofread" : "Korektúra", + "Proofreads a text and lists corrections" : "Urobiť korektúru textu a zobraziť korekcie", + "Text" : "Text", + "The text to proofread" : "Text pre korektúru", + "Corrections" : "Opravy", + "The corrections that should be made in your text" : "Korekcie ktoré môžu byť urobené vo vašom texte", "Reformulate text" : "Preformulovať text", "Takes a text and reformulates it" : "Zoberie text a preformuluje ho", "Write a text that you want the assistant to reformulate" : "Napíšte text pre ktorý chcete aby asistent preforumuloval", @@ -374,41 +440,8 @@ OC.L10N.register( "Generate headline" : "Generovať nadpis", "Summarizes text by reducing its length without losing key information." : "Zhrňuje text tým, že znižuje jeho dĺžku bez straty kľúčových informácií.", "Extracts topics from a text and outputs them separated by commas." : "Extrahuje témy z textu a vypisuje ich oddelené čiarkami.", - "Education Edition" : "Edícia pre výuku", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Prihlásený používateľ musí byť správcom, podadministrátorom alebo musí mať špeciálne právo na prístup k tomuto nastaveniu", - "Logged in user must be an admin or sub admin" : "Prihlásený používateľ musí byť správcom alebo správcom pre čiastkovú oblasť.", - "Logged in user must be an admin" : "Prihlásený používateľ musí byť správca", - "File name is a reserved word" : "Názov súboru je rezervované slovo.", - "File name contains at least one invalid character" : "Názov súboru obsahuje nepovolené znaky.", - "File name is too long" : "Meno súboru je veľmi dlhé.", - "Help" : "Pomoc", - "Users" : "Používatelia", - "Unknown user" : "Neznámy používateľ", - "Enter the database username and name for %s" : "Zadajte užívateľské meno a názov databázy pre %s", - "Enter the database username for %s" : "Zadajte užívateľské meno databázy pre %s", - "MySQL username and/or password not valid" : "Neplatné užívateľské meno a/alebo heslo do MySQL", - "Oracle username and/or password not valid" : "Používateľské meno a/alebo heslo pre Oracle databázu je neplatné", - "PostgreSQL username and/or password not valid" : "Používateľské meno a/alebo heslo pre PostgreSQL databázu je neplatné", - "Set an admin username." : "Zadajte používateľské meno administrátora.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s vám sprístupnil »%2$s« s poznámkou:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s vám sprístupnil »%2$s« s poznámkou", - "»%s« added a note to a file shared with you" : "»%s« pridal poznámku k súboru ktorý s Vami zdieľa", - "Open »%s«" : "Otvoriť »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Zdieľanie %s zlyhalo, táto položka už je používateľovi %s zozdieľaná", - "%1$s shared »%2$s« with you" : "%1$s vám sprístupnil »%2$s«", - "%1$s shared »%2$s« with you." : "%1$s vám sprístupnil »%2$s«.", - "The username is already being used" : "Meno používateľa je už použité", - "Could not create user" : "Nepodarilo sa vytvoriť používateľa", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "V mene užívateľa je možné použiť iba nasledovné znaky: \"a-z\", \"A-Z\", \"0-9\", medzery a \"_.@-'\"", - "A valid username must be provided" : "Musíte zadať platné používateľské meno", - "Username contains whitespace at the beginning or at the end" : "Meno používateľa obsahuje na začiatku, alebo na konci medzeru", - "Username must not consist of dots only" : "Používateľské meno sa nesmie skladať len z bodiek", - "Username is invalid because files already exist for this user" : "Používateľské meno je neplatné, pretože pre tohto používateľa už existujú súbory", - "User disabled" : "Používateľ zakázaný", + "Organisation" : "Organizácia", "File is currently busy, please try again later" : "Súbor sa práve používa, skúste prosím neskôr", - "Cannot download file" : "Nemožno stiahnuť súbor", - "Your data directory is readable by other users." : "Váš priečinok s dátami je prístupný na čítanie ostatným užívateľom.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Prosím, zmeňte oprávnenia na 0770, aby tento priečinok nemohli ostatní používatelia otvoriť.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Uistite sa, že v koreňovom adresári sa nachádza súbor s názvom \".ocdata\"." + "Cannot download file" : "Nemožno stiahnuť súbor" }, "nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);"); diff --git a/lib/l10n/sk.json b/lib/l10n/sk.json index 8c624294704..04f8ab8b33b 100644 --- a/lib/l10n/sk.json +++ b/lib/l10n/sk.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Je vyžadovaná verzia servera %s alebo vyššia.", "Server version %s or lower is required." : "Je vyžadovaná verzia servera %s alebo nižšia.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Prihlásený účet musí byť správcom, podadministrátorom alebo musí mať špeciálne právo na prístup k tomuto nastaveniu.", - "Your current IP address doesn’t allow you to perform admin actions" : "Vaša aktuálna adresa IP vám neumožňuje vykonávať akcie správcu", + "Your current IP address doesn't allow you to perform admin actions" : "Vaša aktuálna adresa IP vám neumožňuje vykonávať akcie správcu", "Logged in account must be an admin or sub admin" : "Prihlásený účet musí byť správcom alebo sub správcom.", "Logged in account must be an admin" : "Prihlásený účet musí byť správcom", "Wiping of device %s has started" : "Začalo sa mazanie zariadenia %s", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Obrázok avatara nie je štvorcový", "Files" : "Súbory", "View profile" : "Zobraziť profil", + "same time" : "rovnaký čas", + "_%nh_::_%nh_" : ["%nh","%nh","%nh","%nh"], + "_%nm_::_%nm_" : ["%nm","%nm","%nm","%nm"], + "%s ahead" : "%s dopredu", + "%s behind" : "%s dozadu", "Local time: %s" : "Miestny čas: %s", "today" : "dnes", "tomorrow" : "zajtra", @@ -79,6 +84,12 @@ "seconds ago" : "pred sekundami", "Empty file" : "Prázdny súbor", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul s ID: %s neexistuje. Povoľte ho prosím vo vašom nastavení aplikácií alebo kontaktujte správcu.", + "No file conversion providers available" : "Nie sú dostupný žiadny poskytovatelia konverzie", + "File is too large to convert" : "Súbor je príliš veľký pre konverziu", + "Destination does not match conversion extension" : "Cieľ nesúhlasí s príponou konverzie", + "Could not convert file" : "Nemožno skonvertovať súbor", + "Destination does not exist" : "Cieľ neexistuje", + "Destination is not creatable" : "Cieľ nie je možné vytvoriť", "Dot files are not allowed" : "Názov súboru začínajúci bodkou nie je povolený.", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" je zakázané pre súbor alebo adresár", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" je zakázaná predpona pre názov súboru alebo adresára.", @@ -90,6 +101,13 @@ "Invalid path" : "Neplatná cesta", "Failed to create file from template" : "Nemôžem vytvoriť súbor zo šablóny", "Templates" : "Šablóny", + "Storage %s cannot be moved" : "Úložisko %s nemôže byť presunuté", + "Moving a share (%s) into a shared folder is not allowed" : "Presun zdieľania (%s) do zdieľaného adresára nie je povolený", + "Moving a storage (%s) into a shared folder is not allowed" : "Presun úložiska (%s) do zdieľaného adresára nie je povolený", + "Moving a share (%s) into another share (%s) is not allowed" : "Presun zdieľania (%s) do iného zdieľania (%s) nie je povolený", + "Moving a share (%s) into another storage (%s) is not allowed" : "Presun zdieľania (%s) do iného úložiska (%s) nie je povolený", + "Moving a storage (%s) into a share (%s) is not allowed" : "Presun úložiska (%s) do zdieľania (%s) nie je povolený", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Presun úložiska (%s) do iného úložiska (%s) nie je povolený", "Path contains invalid segments" : "Cesta obsahuje neplatné časti", "Filename is a reserved word" : "Názov súboru je rezervované slovo", "Filename contains at least one invalid character" : "Názov súboru obsahuje najmenej jeden nepovolený znak", @@ -122,7 +140,6 @@ "About" : "O aplikácii", "Display name" : "Zobrazované meno", "Headline" : "Titul", - "Organisation" : "Organizácia", "Role" : "Rola", "Pronouns" : "Zámená", "Unknown account" : "Neznámy účet", @@ -136,7 +153,7 @@ "Oracle connection could not be established" : "Nie je možné pripojiť sa k Oracle", "Oracle Login and/or password not valid" : "Prihlasovacie meno a/alebo heslo pre Oracle databázu je neplatné", "PostgreSQL Login and/or password not valid" : "Prihlasovacie meno a/alebo heslo pre PostgreSQL databázu je neplatné", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nie je podporovaný a %s nebude správne fungovať na tejto platforme. Použite ho na vlastné riziko!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X nie je podporovaný a %s nebude správne fungovať na tejto platforme. Použitie na vlastné riziko!", "For the best results, please consider using a GNU/Linux server instead." : "Pre dosiahnutie najlepších výsledkov, prosím zvážte použitie GNU/Linux servera.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Zdá sa, že táto inštancia %s beží v 32-bitovom prostredí PHP a v php.ini bola nastavená voľba open_basedir. To bude zdrojom problémov so súbormi väčšími ako 4GB a dôrazne sa neodporúča.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Prosím, odstráňte nastavenie open_basedir vo vašom php.ini alebo prejdite na 64-bit PHP.", @@ -147,9 +164,11 @@ "Sharing backend %s not found" : "Backend sprístupnenia %s nebol nájdený", "Sharing backend for %s not found" : "Backend sprístupnenia pre %s nebol nájdený", "%1$s shared %2$s with you" : "%1$s s vami zdieľal %2$s ", - "Click the button below to open it." : "Pre otvorenie klienta kliknite na tlačítko nižšie.", "Open %s" : "Otvoriť %s", "%1$s via %2$s" : "%1$s cez %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s zdieľal %2$s s vami a chce pridať:", + "%1$s shared %2$s with you and wants to add" : "%1$s zdieľal %2$s s vami a chce pridať", + "%s added a note to a file shared with you" : "%s pridal poznámku k súboru ktorý s vami zdieľa", "Passwords are enforced for link and mail shares" : "Heslo je vyžadováné pre zdieľanie odkazom alebo e-mailom", "Share recipient is not a valid user" : "Príjemca zdieľania nie je platným uživateľom", "Share recipient is not a valid group" : "Príjemca zdieľania nie je platnou skupinou", @@ -164,6 +183,7 @@ "You cannot share your root folder" : "Nemôžete zdieľať váš koreňový adresár", "You are not allowed to share %s" : "Nemôžete sprístupniť %s", "Valid permissions are required for sharing" : "Pre zdieľanie sú potrebné korektné práva", + "File shares cannot have create or delete permissions" : "Zdieľané súbory nemôžu mať oprávnenia pre vytváranie ani odstraňovanie", "Cannot increase permissions of %s" : "Nie je možné navýšiť oprávnenia pre %s", "Shares need at least read permissions" : "Zdieľanie vyžaduje minimálne práva na čítanie", "Files cannot be shared with delete permissions" : "Súbory nie je možné sprístupňovať s oprávneniami na odstránenie", @@ -178,13 +198,17 @@ "Path is already shared with this group" : "Cesta je už zdieľaná s touto skupinou", "Link sharing is not allowed" : "Zdieľanie odkazu nie je povolené", "Public upload is not allowed" : "Verejné nahrávanie nie je povolené", - "Path contains files shared with you" : "Cesta obsahuje súbory zdieľané s vami", "Sharing is disabled" : "Zdieľanie je zakázané", "Sharing is disabled for you" : "Zdieľanie je pre vás zakázané", "Cannot share with the share owner" : "Nie je možné zdieľať s vlastníkom", "Share does not have a full ID" : "Zdieľanie nemá plné ID", "Cannot change share type" : "Nie je možné zmeniť typ zdieľania", "Can only update recipient on user shares" : "Príjemcu je možné aktualizovať iba v užívateľských zdieľaniach", + "Cannot enable sending the password by Talk with an empty password" : "Nie je možné povoliť odosielanie hesla službou Rozhovor/Talk s prázdnym heslom", + "Cannot enable sending the password by Talk without setting a new password" : "Nie je možné povoliť odosielanie hesla službou Rozhovor/Talk bez nastavenia nového hesla", + "Cannot disable sending the password by Talk without setting a new password" : "Nie je možné zakázať odosielanie hesla službou Rozhovor/Talk bez nastavenia nového hesla", + "Share provider does not support accepting" : "Poskytovateľ zdieľania nepodporuje prijímanie", + "Cannot change target of link share" : "Nie je možné zmeniť cieľ zdieľaného odkazu", "Invalid share recipient" : "Neplatný príjemca zdieľania", "Group \"%s\" does not exist" : "Skupina \"%s\" neexistuje", "The requested share does not exist anymore" : "Požadované zdieľanie už neexistuje", @@ -282,6 +306,7 @@ "Your data directory must be an absolute path." : "Priečinok s dátami musí byť zadaný ako absolútna cesta.", "Check the value of \"datadirectory\" in your configuration." : "Skontrolujte hodnotu \"datadirectory\" vo vašej konfigurácii.", "Your data directory is invalid." : "Priečinok pre dáta je neplatný.", + "Ensure there is a file called \"%1$s\" in the root of the data directory. It should have the content: \"%2$s\"" : "Uistite sa, že v koreňovom adresári údajov je súbor s názvom \"%1$s\". Mal by mať obsah: \"%2$s\"", "Action \"%s\" not supported or implemented." : "Akcia \"%s\" nie je podporovaná alebo implementovaná.", "Authentication failed, wrong token or provider ID given" : "Autentifikácia zlyhala, bol zadaný neplatný token alebo ID poskytovateľa", "Parameters missing in order to complete the request. Missing Parameters: \"%s\"" : "Pre dokončenie požiadavky chýbajú parametre. Chýbajúce parametre: \"%s\"", @@ -300,8 +325,19 @@ "The audio to transcribe" : "Zvuk pre prepísanie", "Transcription" : "Prepis", "The transcribed text" : "Prepísaný text", + "Chat with an agent" : "Čet s agentom", "Chat message" : "Správa chatu", + "A chat message to send to the agent." : "Správa četu pre poslanie agentovi.", "Confirmation" : "Potvrdenie", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Či potvrdiť predtým požadované akcie: 0 pre odmietnutie a 1 pre potvrdenie.", + "Conversation token" : "Token konverzácie", + "A token representing the conversation." : "Token reprezentujúci konverzáciu.", + "Generated response" : "Vygenerovaná odpoveď", + "The response from the chat model." : "Odpoveď z modelu četu.", + "The new conversation token" : "Nový token konverzácie", + "Send this along with the next interaction." : "Odoslať to spolu s ďalšou interakciou.", + "Requested actions by the agent" : "Vyžiadané akcie agentom", + "Actions that the agent would like to carry out in JSON format." : "Akcie, ktoré by chcel agent vykonať vo formáte JSON.", "Context write" : "Kontextový zápis", "Writes text in a given style based on the provided source material." : "Napíše text v danom štýle na základe poskytnutého zdrojového materiálu.", "Writing style" : "Štýl písania", @@ -323,13 +359,37 @@ "How many images to generate" : "Koľko obrázkov sa bude generovať", "Output images" : "Výstupné obrázky", "The generated images" : "Vygenerované obrázky", + "Free text to text prompt" : "Výzva pre voľný text na text", + "Runs an arbitrary prompt through a language model that returns a reply" : "Spustí ľubovoľnú výzvu cez jazykový model, ktorý vráti odpoveď", + "Describe a task that you want the assistant to do or ask a question" : "Opíšte úlohu, ktorú má asistent vykonať, alebo položte otázku", "Generated reply" : "Vygenerovaná odpoveď", + "The generated text from the assistant" : "Generovaný text od asistenta", + "Change Tone" : "Zmeniť tón", + "Change the tone of a piece of text." : "Zmeniť tón časti textu", + "Write a text that you want the assistant to rewrite in another tone." : "Napíšte text pre ktorý chcete aby asistent prepísal v inom tóne.", + "Desired tone" : "Požadovaný tón", + "In which tone should your text be rewritten?" : "V akom tóne by mal byť váš text prepísaný?", + "The rewritten text in the desired tone, written by the assistant:" : "Prepísaný text v požadovanom tóne, napísaný asistentom:", "Chat" : "Chat", "Chat with the assistant" : "Chat s asistentom", "System prompt" : "Systémová výzva", + "Define rules and assumptions that the assistant should follow during the conversation." : "Definovať pravidlá a predpoklady, ktoré by mal asistent počas rozhovoru dodržiavať.", "Chat history" : "História chatu", + "The history of chat messages before the current message, starting with a message by the user" : "História četových správ pred aktuálnou správou, počnúc správou od užívateľa", "Response message" : "Správa s odpoveďou", + "The generated response as part of the conversation" : "Vygenerovaná odpoveď ako súčasť konverzácie", + "Chat with tools" : "Čet s nástrojom", + "Chat with the language model with tool calling support." : "Chatujte s jazykovým modelom s podporou volania pomocou nástroja.", + "Tool message" : "Správa nástroja", + "The result of tool calls in the last interaction" : "Výsledok volaní nástroja v poslednej interakcii", + "Available tools" : "Dostupné nástroje", + "The available tools in JSON format" : "Dostupné nástroje vo formáte JSON", + "The response from the chat model" : "Odpoveď z modelu četu", + "Tool calls" : "Žiadosti nástroja", + "Tools call instructions from the model in JSON format" : "Inštrukcie volaní nástroja z modelu v JSON formáte", "Formalize text" : "Formalizovať text", + "Takes a text and makes it sound more formal" : "Zobrať text a urobiť ho viac formálnym", + "Write a text that you want the assistant to formalize" : "Napíšte text ktorý chcete štylyzovať asistentom", "Formalized text" : "Formalizovaný text", "The formalized text" : "Formalizovaný text", "Generate a headline" : "Vygenerovať titulok", @@ -337,6 +397,12 @@ "Original text" : "Originálny text", "The original text to generate a headline for" : "Originálny text pre ktorý sa vygeneruje titulok", "The generated headline" : "Vygenerovaný titulok", + "Proofread" : "Korektúra", + "Proofreads a text and lists corrections" : "Urobiť korektúru textu a zobraziť korekcie", + "Text" : "Text", + "The text to proofread" : "Text pre korektúru", + "Corrections" : "Opravy", + "The corrections that should be made in your text" : "Korekcie ktoré môžu byť urobené vo vašom texte", "Reformulate text" : "Preformulovať text", "Takes a text and reformulates it" : "Zoberie text a preformuluje ho", "Write a text that you want the assistant to reformulate" : "Napíšte text pre ktorý chcete aby asistent preforumuloval", @@ -372,41 +438,8 @@ "Generate headline" : "Generovať nadpis", "Summarizes text by reducing its length without losing key information." : "Zhrňuje text tým, že znižuje jeho dĺžku bez straty kľúčových informácií.", "Extracts topics from a text and outputs them separated by commas." : "Extrahuje témy z textu a vypisuje ich oddelené čiarkami.", - "Education Edition" : "Edícia pre výuku", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Prihlásený používateľ musí byť správcom, podadministrátorom alebo musí mať špeciálne právo na prístup k tomuto nastaveniu", - "Logged in user must be an admin or sub admin" : "Prihlásený používateľ musí byť správcom alebo správcom pre čiastkovú oblasť.", - "Logged in user must be an admin" : "Prihlásený používateľ musí byť správca", - "File name is a reserved word" : "Názov súboru je rezervované slovo.", - "File name contains at least one invalid character" : "Názov súboru obsahuje nepovolené znaky.", - "File name is too long" : "Meno súboru je veľmi dlhé.", - "Help" : "Pomoc", - "Users" : "Používatelia", - "Unknown user" : "Neznámy používateľ", - "Enter the database username and name for %s" : "Zadajte užívateľské meno a názov databázy pre %s", - "Enter the database username for %s" : "Zadajte užívateľské meno databázy pre %s", - "MySQL username and/or password not valid" : "Neplatné užívateľské meno a/alebo heslo do MySQL", - "Oracle username and/or password not valid" : "Používateľské meno a/alebo heslo pre Oracle databázu je neplatné", - "PostgreSQL username and/or password not valid" : "Používateľské meno a/alebo heslo pre PostgreSQL databázu je neplatné", - "Set an admin username." : "Zadajte používateľské meno administrátora.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s vám sprístupnil »%2$s« s poznámkou:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s vám sprístupnil »%2$s« s poznámkou", - "»%s« added a note to a file shared with you" : "»%s« pridal poznámku k súboru ktorý s Vami zdieľa", - "Open »%s«" : "Otvoriť »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Zdieľanie %s zlyhalo, táto položka už je používateľovi %s zozdieľaná", - "%1$s shared »%2$s« with you" : "%1$s vám sprístupnil »%2$s«", - "%1$s shared »%2$s« with you." : "%1$s vám sprístupnil »%2$s«.", - "The username is already being used" : "Meno používateľa je už použité", - "Could not create user" : "Nepodarilo sa vytvoriť používateľa", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "V mene užívateľa je možné použiť iba nasledovné znaky: \"a-z\", \"A-Z\", \"0-9\", medzery a \"_.@-'\"", - "A valid username must be provided" : "Musíte zadať platné používateľské meno", - "Username contains whitespace at the beginning or at the end" : "Meno používateľa obsahuje na začiatku, alebo na konci medzeru", - "Username must not consist of dots only" : "Používateľské meno sa nesmie skladať len z bodiek", - "Username is invalid because files already exist for this user" : "Používateľské meno je neplatné, pretože pre tohto používateľa už existujú súbory", - "User disabled" : "Používateľ zakázaný", + "Organisation" : "Organizácia", "File is currently busy, please try again later" : "Súbor sa práve používa, skúste prosím neskôr", - "Cannot download file" : "Nemožno stiahnuť súbor", - "Your data directory is readable by other users." : "Váš priečinok s dátami je prístupný na čítanie ostatným užívateľom.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Prosím, zmeňte oprávnenia na 0770, aby tento priečinok nemohli ostatní používatelia otvoriť.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Uistite sa, že v koreňovom adresári sa nachádza súbor s názvom \".ocdata\"." + "Cannot download file" : "Nemožno stiahnuť súbor" },"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);" }
\ No newline at end of file diff --git a/lib/l10n/sl.js b/lib/l10n/sl.js index 8ce0fd59669..19151cd114c 100644 --- a/lib/l10n/sl.js +++ b/lib/l10n/sl.js @@ -51,6 +51,7 @@ OC.L10N.register( "Avatar image is not square" : "Slika podobe ni kvadratna", "Files" : "Datoteke", "View profile" : "Pokaži profil", + "_%nh_::_%nh_" : ["%nh","%nh","%nh","%nh"], "Local time: %s" : "Krajevni čas: %s", "today" : "danes", "tomorrow" : "jutri", @@ -74,6 +75,7 @@ OC.L10N.register( "Empty file" : "Prazna datoteka", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul z ID: %s ne obstaja. Omogočite ga med nastavitvami, ali pa stopite v stik s skrbnikom sistema.", "Dot files are not allowed" : "Skrite datoteke niso dovoljene", + "Filenames must not end with \"%1$s\"." : "Imena datotek se naj ne končajo s \"%1$s\".", "File already exists" : "Datoteka že obstaja", "Invalid path" : "Neveljavna pot", "Failed to create file from template" : "Ustvarjanje datoteke iz predloge je spodletelo", @@ -106,14 +108,13 @@ OC.L10N.register( "About" : "O programu", "Display name" : "Prikazno ime", "Headline" : "Naslov", - "Organisation" : "Ustanova", + "Organization" : "Organizacija", "Role" : "Vloga", "Additional settings" : "Dodatne nastavitve", "Enter the database name for %s" : "Vpis imena podatkovne zbirke za %s.", "You cannot use dots in the database name %s" : "V imenu podatkovne zbirke %s ni dovoljeno uporabljati pik.", "You need to enter details of an existing account." : "Vpisati je treba podrobnosti obstoječega računa.", "Oracle connection could not be established" : "Povezave s sistemom Oracle ni mogoče vzpostaviti.", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Sistem Mac OS X ni podprt, zato %s v tem okolju ne bo deloval zanesljivo. Program uporabljate na lastno odgovornost! ", "For the best results, please consider using a GNU/Linux server instead." : "Za najboljše rezultate je priporočljivo uporabljati strežnik GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Kaže, da je dejavna seja %s zagnana v 32-bitnem okolju PHP in, da je v datoteki php.ini nastavljen open_basedir . Tako delovanje ni priporočljivo, saj se lahko pojavijo težave z datotekami, večjimi od 4GB.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Odstraniti je treba nastavitev open_basedir v datoteki php.ini ali pa preklopiti na 64-bitno okolje PHP.", @@ -122,7 +123,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Souporaba ozadnjega programa %s mora vsebovati tudi vmesnik OCP\\Share_Backend", "Sharing backend %s not found" : "Ozadnjega programa %s za souporabo ni mogoče najti", "Sharing backend for %s not found" : "Ozadnjega programa za souporabo za %s ni mogoče najti", - "Click the button below to open it." : "Kliknite na gumb za odpiranje.", "%1$s via %2$s" : "%1$s prek %2$s", "Unknown share type" : "Neznana vrsta mesta souporabe", "You are not allowed to share %s" : "Omogočanje souporabe %s brez ustreznih dovoljenj ni mogoče.", @@ -225,44 +225,13 @@ OC.L10N.register( "Confirmation" : "Potrjevanje", "Writing style" : "Slog pisanja", "Generate image" : "Ustvari sliko", + "Text" : "Besedilo", "Summary" : "Povzetek", "Translate" : "Prevedi", "Target language" : "Ciljni jezik", "Result" : "Rezultat", - "Education Edition" : "Izobraževalna različica", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Prijavljen uporabnik mora biti določen za skrbnika, pomočnika skrbnika ali pa mora imeti dodeljene posebna dovoljenja za dostop do nastavitve.", - "Logged in user must be an admin or sub admin" : "Prijavljen uporabnik mora imeti dovoljenja skrbnika ali podpornega skrbnika", - "Logged in user must be an admin" : "Prijavljen uporabnik mora biti tudi skrbnik", - "File name is a reserved word" : "Ime datoteke je zadržana beseda", - "File name contains at least one invalid character" : "Ime datoteke vsebuje vsaj en nedovoljen znak.", - "File name is too long" : "Ime datoteke je predolgo", - "Help" : "Pomoč", - "Users" : "Uporabniki", - "Unknown user" : "Neznan uporabnik", - "Enter the database username and name for %s" : "Vpis uporabniškega imena in imena podatkovne zbirke za %s.", - "Enter the database username for %s" : "Vpis uporabniškega imena podatkovne zbirke za %s.", - "MySQL username and/or password not valid" : "Uporabniško ime ali geslo MySQL ni veljavno", - "Oracle username and/or password not valid" : "Uporabniško ime ali geslo Oracle ni veljavno", - "PostgreSQL username and/or password not valid" : "Uporabniško ime ali geslo PostgreSQL ni veljavno", - "Set an admin username." : "Nastavi uporabniško ime skrbnika.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s vam omogoča souporabo »%2$s« in želi dodati:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s vam omogoča souporabo »%2$s« in želi dodati", - "»%s« added a note to a file shared with you" : "»%s« doda opombo k datoteki v souporabi", - "Open »%s«" : "Odpri »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Nastavljanje souporabe %s je spodletelo, ker je predmet že v souporabi z uporabnikom %s.", - "%1$s shared »%2$s« with you" : "%1$s vam omogoča souporabo »%2$s«", - "%1$s shared »%2$s« with you." : "%1$s vam omogoča souporabo »%2$s«.", - "The username is already being used" : "Vpisano uporabniško ime je že v uporabi", - "Could not create user" : "Uporabnika ni mogoče ustvariti", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "V uporabniškem imenu je dovoljeno uporabiti le znake: »a–z«, »A–Z«, »0–9«, presledki in »_.@-«\".", - "A valid username must be provided" : "Navedeno mora biti veljavno uporabniško ime", - "Username contains whitespace at the beginning or at the end" : "Uporabniško ime vsebuje presledni znak na začetku ali na koncu imena.", - "Username must not consist of dots only" : "Uporabniško ime ne sme biti zgolj iz pik", - "Username is invalid because files already exist for this user" : "Uporabniško ime ni veljavno, ker za tega uporabnika že obstajajo datoteke", - "User disabled" : "Uporabnik je onemogočen", + "Organisation" : "Ustanova", "File is currently busy, please try again later" : "Datoteka je trenutno v uporabi. Poskusite znova kasneje.", - "Cannot download file" : "Datoteke ni mogoče prejeti", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Spremenite dovoljenja mape na 0770 in s tem onemogočite branje vsebine drugim uporabnikom.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Prepričajte se, da je datoteka ».ocdata« v korenu podatkovne mape." + "Cannot download file" : "Datoteke ni mogoče prejeti" }, "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"); diff --git a/lib/l10n/sl.json b/lib/l10n/sl.json index 28d7958a1e9..b818a0ae1ca 100644 --- a/lib/l10n/sl.json +++ b/lib/l10n/sl.json @@ -49,6 +49,7 @@ "Avatar image is not square" : "Slika podobe ni kvadratna", "Files" : "Datoteke", "View profile" : "Pokaži profil", + "_%nh_::_%nh_" : ["%nh","%nh","%nh","%nh"], "Local time: %s" : "Krajevni čas: %s", "today" : "danes", "tomorrow" : "jutri", @@ -72,6 +73,7 @@ "Empty file" : "Prazna datoteka", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modul z ID: %s ne obstaja. Omogočite ga med nastavitvami, ali pa stopite v stik s skrbnikom sistema.", "Dot files are not allowed" : "Skrite datoteke niso dovoljene", + "Filenames must not end with \"%1$s\"." : "Imena datotek se naj ne končajo s \"%1$s\".", "File already exists" : "Datoteka že obstaja", "Invalid path" : "Neveljavna pot", "Failed to create file from template" : "Ustvarjanje datoteke iz predloge je spodletelo", @@ -104,14 +106,13 @@ "About" : "O programu", "Display name" : "Prikazno ime", "Headline" : "Naslov", - "Organisation" : "Ustanova", + "Organization" : "Organizacija", "Role" : "Vloga", "Additional settings" : "Dodatne nastavitve", "Enter the database name for %s" : "Vpis imena podatkovne zbirke za %s.", "You cannot use dots in the database name %s" : "V imenu podatkovne zbirke %s ni dovoljeno uporabljati pik.", "You need to enter details of an existing account." : "Vpisati je treba podrobnosti obstoječega računa.", "Oracle connection could not be established" : "Povezave s sistemom Oracle ni mogoče vzpostaviti.", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Sistem Mac OS X ni podprt, zato %s v tem okolju ne bo deloval zanesljivo. Program uporabljate na lastno odgovornost! ", "For the best results, please consider using a GNU/Linux server instead." : "Za najboljše rezultate je priporočljivo uporabljati strežnik GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Kaže, da je dejavna seja %s zagnana v 32-bitnem okolju PHP in, da je v datoteki php.ini nastavljen open_basedir . Tako delovanje ni priporočljivo, saj se lahko pojavijo težave z datotekami, večjimi od 4GB.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Odstraniti je treba nastavitev open_basedir v datoteki php.ini ali pa preklopiti na 64-bitno okolje PHP.", @@ -120,7 +121,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Souporaba ozadnjega programa %s mora vsebovati tudi vmesnik OCP\\Share_Backend", "Sharing backend %s not found" : "Ozadnjega programa %s za souporabo ni mogoče najti", "Sharing backend for %s not found" : "Ozadnjega programa za souporabo za %s ni mogoče najti", - "Click the button below to open it." : "Kliknite na gumb za odpiranje.", "%1$s via %2$s" : "%1$s prek %2$s", "Unknown share type" : "Neznana vrsta mesta souporabe", "You are not allowed to share %s" : "Omogočanje souporabe %s brez ustreznih dovoljenj ni mogoče.", @@ -223,44 +223,13 @@ "Confirmation" : "Potrjevanje", "Writing style" : "Slog pisanja", "Generate image" : "Ustvari sliko", + "Text" : "Besedilo", "Summary" : "Povzetek", "Translate" : "Prevedi", "Target language" : "Ciljni jezik", "Result" : "Rezultat", - "Education Edition" : "Izobraževalna različica", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Prijavljen uporabnik mora biti določen za skrbnika, pomočnika skrbnika ali pa mora imeti dodeljene posebna dovoljenja za dostop do nastavitve.", - "Logged in user must be an admin or sub admin" : "Prijavljen uporabnik mora imeti dovoljenja skrbnika ali podpornega skrbnika", - "Logged in user must be an admin" : "Prijavljen uporabnik mora biti tudi skrbnik", - "File name is a reserved word" : "Ime datoteke je zadržana beseda", - "File name contains at least one invalid character" : "Ime datoteke vsebuje vsaj en nedovoljen znak.", - "File name is too long" : "Ime datoteke je predolgo", - "Help" : "Pomoč", - "Users" : "Uporabniki", - "Unknown user" : "Neznan uporabnik", - "Enter the database username and name for %s" : "Vpis uporabniškega imena in imena podatkovne zbirke za %s.", - "Enter the database username for %s" : "Vpis uporabniškega imena podatkovne zbirke za %s.", - "MySQL username and/or password not valid" : "Uporabniško ime ali geslo MySQL ni veljavno", - "Oracle username and/or password not valid" : "Uporabniško ime ali geslo Oracle ni veljavno", - "PostgreSQL username and/or password not valid" : "Uporabniško ime ali geslo PostgreSQL ni veljavno", - "Set an admin username." : "Nastavi uporabniško ime skrbnika.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s vam omogoča souporabo »%2$s« in želi dodati:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s vam omogoča souporabo »%2$s« in želi dodati", - "»%s« added a note to a file shared with you" : "»%s« doda opombo k datoteki v souporabi", - "Open »%s«" : "Odpri »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Nastavljanje souporabe %s je spodletelo, ker je predmet že v souporabi z uporabnikom %s.", - "%1$s shared »%2$s« with you" : "%1$s vam omogoča souporabo »%2$s«", - "%1$s shared »%2$s« with you." : "%1$s vam omogoča souporabo »%2$s«.", - "The username is already being used" : "Vpisano uporabniško ime je že v uporabi", - "Could not create user" : "Uporabnika ni mogoče ustvariti", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "V uporabniškem imenu je dovoljeno uporabiti le znake: »a–z«, »A–Z«, »0–9«, presledki in »_.@-«\".", - "A valid username must be provided" : "Navedeno mora biti veljavno uporabniško ime", - "Username contains whitespace at the beginning or at the end" : "Uporabniško ime vsebuje presledni znak na začetku ali na koncu imena.", - "Username must not consist of dots only" : "Uporabniško ime ne sme biti zgolj iz pik", - "Username is invalid because files already exist for this user" : "Uporabniško ime ni veljavno, ker za tega uporabnika že obstajajo datoteke", - "User disabled" : "Uporabnik je onemogočen", + "Organisation" : "Ustanova", "File is currently busy, please try again later" : "Datoteka je trenutno v uporabi. Poskusite znova kasneje.", - "Cannot download file" : "Datoteke ni mogoče prejeti", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Spremenite dovoljenja mape na 0770 in s tem onemogočite branje vsebine drugim uporabnikom.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Prepričajte se, da je datoteka ».ocdata« v korenu podatkovne mape." + "Cannot download file" : "Datoteke ni mogoče prejeti" },"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);" }
\ No newline at end of file diff --git a/lib/l10n/sq.js b/lib/l10n/sq.js index b9491367371..274a74b94b3 100644 --- a/lib/l10n/sq.js +++ b/lib/l10n/sq.js @@ -54,10 +54,10 @@ OC.L10N.register( "Address" : "Adresa", "Profile picture" : "Foto profili", "About" : "Rreth ", + "Organization" : "Organizate", "Additional settings" : "Konfigurime shtesë", "You need to enter details of an existing account." : "Duhet të futni detajet e një llogarie ekzistuese.", "Oracle connection could not be established" : "S’u vendos dot lidhje me Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nuk mbulohet dhe %s s’do të funksionojë si duhet në këtë platformë. Përdoreni nën përgjegjësinë tuaj! ", "For the best results, please consider using a GNU/Linux server instead." : "Për përfundimet më të mira, ju lutemi, më mirë konsideroni përdorimin e një shërbyesi GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Duket se kjo instancë %s xhiron një mjedis PHP 32-bitësh dhe open_basedir është e formësuar, te php.ini. Kjo do të shpjerë në probleme me kartela më të mëdha se 4 GB dhe këshillohet me forcë të mos ndodhë.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Ju lutemi, hiqeni rregullimin open_basedir nga php.ini juaj ose hidhuni te PHP për 64-bit.", @@ -65,7 +65,6 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Mekanizmi i shërbimit për ndarje %s duhet të sendërtojë ndërfaqen OCP\\Share_Backend", "Sharing backend %s not found" : "S’u gjet mekanizmi i shërbimit për ndarje %s", "Sharing backend for %s not found" : "S’u gjet mekanizmi i shërbimit për ndarje për %s", - "Click the button below to open it." : "Kliko butonin më poshtë për të hapur atë.", "Unknown share type" : "Lloj i panjohur ndarjesh", "You are not allowed to share %s" : "Nuk ju lejohet ta ndani %s me të tjerët", "Cannot increase permissions of %s" : "S’mund të shtohen lejet për %s", @@ -138,28 +137,10 @@ OC.L10N.register( "Storage connection error. %s" : "Gabim lidhje te depozita. %s", "Storage is temporarily not available" : "Hapsira ruajtëse nuk është në dispozicion përkohësisht", "Storage connection timeout. %s" : "Mbarim kohe lidhjeje për depozitën. %s", + "Text" : "Tekst", "Summary" : "Përmbledhje", "Translate" : "Përkthe", "Result" : "Rezultatet", - "Education Edition" : "Variant Edukativ", - "File name is a reserved word" : "Emri i kartelës është një emër i rezervuar", - "File name contains at least one invalid character" : "Emri i kartelës përmban të paktën një shenjë të pavlefshme", - "File name is too long" : "Emri i kartelës është shumë i gjatë", - "Help" : "Ndihmë", - "Users" : "Përdorues", - "Unknown user" : "Përdorues i panjohur", - "Oracle username and/or password not valid" : "Emër përdoruesi dhe/ose fjalëkalim Oracle-i i pavlefshëm", - "PostgreSQL username and/or password not valid" : "Emër përdoruesi dhe/ose fjalëkalim PostgreSQL jo të vlefshëm", - "Set an admin username." : "Caktoni një emër përdoruesi për përgjegjësin.", - "Open »%s«" : "Hap»1 %s«", - "Sharing %s failed, because this item is already shared with user %s" : "Ndarja e %s me të tjerët dështoi, ngaqë ky objekt është ndarë tashmë me përdoruesin %s", - "The username is already being used" : "Emri i përdoruesit është tashmë i përdorur", - "A valid username must be provided" : "Duhet dhënë një emër i vlefshëm përdoruesi", - "Username contains whitespace at the beginning or at the end" : "Emri i përdoruesit përmban hapësirë në fillim ose në fund", - "Username must not consist of dots only" : "Emri i përdoruesit nuk duhet të përbëhet vetëm nga pika", - "User disabled" : "Përdorues i çaktivizuar", - "File is currently busy, please try again later" : "Kartela tani është e zënë, ju lutemi, riprovoni më vonë.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Ju lutemi, kalojani lejet në 0770, që kështu atë drejtori të mos mund ta shfaqin përdorues të tjerë.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Sigurohu që ekziston një skedar i quajtur \".ocdata\" në rrënjën e direktorisë së të dhënave." + "File is currently busy, please try again later" : "Kartela tani është e zënë, ju lutemi, riprovoni më vonë." }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/sq.json b/lib/l10n/sq.json index a477d286d91..fd84a8486f3 100644 --- a/lib/l10n/sq.json +++ b/lib/l10n/sq.json @@ -52,10 +52,10 @@ "Address" : "Adresa", "Profile picture" : "Foto profili", "About" : "Rreth ", + "Organization" : "Organizate", "Additional settings" : "Konfigurime shtesë", "You need to enter details of an existing account." : "Duhet të futni detajet e një llogarie ekzistuese.", "Oracle connection could not be established" : "S’u vendos dot lidhje me Oracle", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X nuk mbulohet dhe %s s’do të funksionojë si duhet në këtë platformë. Përdoreni nën përgjegjësinë tuaj! ", "For the best results, please consider using a GNU/Linux server instead." : "Për përfundimet më të mira, ju lutemi, më mirë konsideroni përdorimin e një shërbyesi GNU/Linux.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Duket se kjo instancë %s xhiron një mjedis PHP 32-bitësh dhe open_basedir është e formësuar, te php.ini. Kjo do të shpjerë në probleme me kartela më të mëdha se 4 GB dhe këshillohet me forcë të mos ndodhë.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Ju lutemi, hiqeni rregullimin open_basedir nga php.ini juaj ose hidhuni te PHP për 64-bit.", @@ -63,7 +63,6 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Mekanizmi i shërbimit për ndarje %s duhet të sendërtojë ndërfaqen OCP\\Share_Backend", "Sharing backend %s not found" : "S’u gjet mekanizmi i shërbimit për ndarje %s", "Sharing backend for %s not found" : "S’u gjet mekanizmi i shërbimit për ndarje për %s", - "Click the button below to open it." : "Kliko butonin më poshtë për të hapur atë.", "Unknown share type" : "Lloj i panjohur ndarjesh", "You are not allowed to share %s" : "Nuk ju lejohet ta ndani %s me të tjerët", "Cannot increase permissions of %s" : "S’mund të shtohen lejet për %s", @@ -136,28 +135,10 @@ "Storage connection error. %s" : "Gabim lidhje te depozita. %s", "Storage is temporarily not available" : "Hapsira ruajtëse nuk është në dispozicion përkohësisht", "Storage connection timeout. %s" : "Mbarim kohe lidhjeje për depozitën. %s", + "Text" : "Tekst", "Summary" : "Përmbledhje", "Translate" : "Përkthe", "Result" : "Rezultatet", - "Education Edition" : "Variant Edukativ", - "File name is a reserved word" : "Emri i kartelës është një emër i rezervuar", - "File name contains at least one invalid character" : "Emri i kartelës përmban të paktën një shenjë të pavlefshme", - "File name is too long" : "Emri i kartelës është shumë i gjatë", - "Help" : "Ndihmë", - "Users" : "Përdorues", - "Unknown user" : "Përdorues i panjohur", - "Oracle username and/or password not valid" : "Emër përdoruesi dhe/ose fjalëkalim Oracle-i i pavlefshëm", - "PostgreSQL username and/or password not valid" : "Emër përdoruesi dhe/ose fjalëkalim PostgreSQL jo të vlefshëm", - "Set an admin username." : "Caktoni një emër përdoruesi për përgjegjësin.", - "Open »%s«" : "Hap»1 %s«", - "Sharing %s failed, because this item is already shared with user %s" : "Ndarja e %s me të tjerët dështoi, ngaqë ky objekt është ndarë tashmë me përdoruesin %s", - "The username is already being used" : "Emri i përdoruesit është tashmë i përdorur", - "A valid username must be provided" : "Duhet dhënë një emër i vlefshëm përdoruesi", - "Username contains whitespace at the beginning or at the end" : "Emri i përdoruesit përmban hapësirë në fillim ose në fund", - "Username must not consist of dots only" : "Emri i përdoruesit nuk duhet të përbëhet vetëm nga pika", - "User disabled" : "Përdorues i çaktivizuar", - "File is currently busy, please try again later" : "Kartela tani është e zënë, ju lutemi, riprovoni më vonë.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Ju lutemi, kalojani lejet në 0770, që kështu atë drejtori të mos mund ta shfaqin përdorues të tjerë.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Sigurohu që ekziston një skedar i quajtur \".ocdata\" në rrënjën e direktorisë së të dhënave." + "File is currently busy, please try again later" : "Kartela tani është e zënë, ju lutemi, riprovoni më vonë." },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/sr.js b/lib/l10n/sr.js index 158516dc3db..7cd0b0e025b 100644 --- a/lib/l10n/sr.js +++ b/lib/l10n/sr.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Потребна је верзија сервера %s или виша.", "Server version %s or lower is required." : "Потребна је верзија сервера %s или нижа.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Пријављени налог мора бити админ, подадмин или мора да поседује специјално право да приступи овом подешавању", - "Your current IP address doesn’t allow you to perform admin actions" : "Ваша тренутна IP адреса не дозвољава да извршавате админ радње", + "Your current IP address doesn't allow you to perform admin actions" : "Ваша тренутна IP адреса не дозвољава да извршавате админ радње", "Logged in account must be an admin or sub admin" : "Пријављени налог мора бити админ или подадмин", "Logged in account must be an admin" : "Пријављени налог мора бити админ", "Wiping of device %s has started" : "Започето брисање уређаја %s", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Слика аватара није квадратна", "Files" : "Фајлови", "View profile" : "Погледај профил", + "same time" : "исто време", + "_%nh_::_%nh_" : ["%nч","%nч","%nч"], + "_%nm_::_%nm_" : ["%nм","%nм","%nм"], + "%s ahead" : "%s испред", + "%s behind" : "%s иза", "Local time: %s" : "Локално време: %s", "today" : "данас", "tomorrow" : "сутра", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "пре неколико секунди", "Empty file" : "Празан фајл", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Модул са идентификацијом: %s не постоји. Омогућите га у подешавањима апликација или контактирајте администратора.", + "No file conversion providers available" : "Није доступан ниједан пружалац услуге конверзије фајла", + "File is too large to convert" : "Фајл је сувише велики да би могао да се конвертује", + "Destination does not match conversion extension" : "Одредиште не одговара екстензији конверзије", + "Could not convert file" : "Фајл није могао да се конвертује", + "Destination does not exist" : "Одредиште не постоји", + "Destination is not creatable" : "Одредиште не може да се креира", "Dot files are not allowed" : "Фајлови са почетном тачком нису дозвољени", + "%1$s (renamed)" : "%1$s (преименован)", + "renamed file" : "преименован фајл", "\"%1$s\" is a forbidden file or folder name." : "„%1$s” је забрањено име фајла или фолдера.", "\"%1$s\" is a forbidden prefix for file or folder names." : "„%1$s” је забрањени префикс имена фајла или фолдера.", "\"%1$s\" is not allowed inside a file or folder name." : "„%1$s” није дозвољено у имену фајла или фолдера.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Неисправна путања", "Failed to create file from template" : "Није успело креирање фајла из шаблона", "Templates" : "Шаблони", + "Storage %s cannot be moved" : "Складиште %s не може да се премести", + "Moving a share (%s) into a shared folder is not allowed" : "Није дозвољено премештање дељења (%s) у дељени фолдер", + "Moving a storage (%s) into a shared folder is not allowed" : "Није дозвољено премештање складишта (%s) у дељени фолдер", + "Moving a share (%s) into another share (%s) is not allowed" : "Није дозвољено премештање дељења (%s) у друго дељење (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "Није дозвољено премештање дељења (%s) у друго складиште (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "Није дозвољено премештање складишта (%s) у дељење (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Није дозвољено премештање складишта (%s) у друго складиште (%s)", "Path contains invalid segments" : "Путања садржи неисправне сегменте", "Filename is a reserved word" : "Име фајла је резервисана реч", "Filename contains at least one invalid character" : "Назив фајла садржи бар један недозвољен знак", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "О програму", "Display name" : "Име за приказ", "Headline" : "Наслов", - "Organisation" : "Организација", + "Organization" : "Организација", "Role" : "Улога", "Pronouns" : "Заменице", "Unknown account" : "Непознати налог", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Веза са базом података Oracle не може бити успостављена", "Oracle Login and/or password not valid" : "Oracle име за пријаву и/или лозинка нису исправни", "PostgreSQL Login and/or password not valid" : "PostgreSQL име за пријаву и/или лозинка нису исправни", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Мек ОС Икс није подржан и %s неће радити исправно на овој платформи. Користите га на сопствени ризик!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X није подржан и %s неће радити исправно на овој платформи. Користите га на сопствени ризик!", "For the best results, please consider using a GNU/Linux server instead." : "За најбоље резултате, размотрите употребу ГНУ/Линукс сервера.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Изгледа да %s ради у 32-битном PHP окружењу а open_basedir је подешен у php.ini фајлу. То може довести до проблема са фајловима већим од 4 GB, те стога није препоручљиво.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Уклоните open_basedir поставку из php.ini фајла или пређите на 64-битни PHP.", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Позадина за дељење %s није пронађена", "Sharing backend for %s not found" : "Позадина за дељење за %s није пронађена", "%1$s shared %2$s with you" : "%1$s је поделио „%2$s” са вама", - "Click the button below to open it." : "Кликните дугме испод да га отворите.", "Open %s" : "Отвори %s", "%1$s via %2$s" : "%1$s преко %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s је поделио %2$s са вама и жели да дода:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "Не можете да делите свој корени фолдер", "You are not allowed to share %s" : "Није вам дозвољено да делите %s", "Valid permissions are required for sharing" : "За дељење су неопходне исправне дозволе", + "File shares cannot have create or delete permissions" : "Фајлови не могу да се деле са дозволама за креирање или брисање", "Cannot increase permissions of %s" : "Не могу да повећам привилегије за %s", "Shares need at least read permissions" : "Дељења морају да имају барем право читања", "Files cannot be shared with delete permissions" : "Фајлови не могу да се деле са дозволама за брисање", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Путања се већ дели са овом групом", "Link sharing is not allowed" : "Није дозвољено дељење линком", "Public upload is not allowed" : "Није дозвољено јавно отпремање", - "Path contains files shared with you" : "Путања садржи фајлове који су подељени са вама", + "You cannot share a folder that contains other shares" : "Не можете да делите фолдер који садржи друга дељења", "Sharing is disabled" : "Дељење је искључено", "Sharing is disabled for you" : "Дељење је за вас искључено", "Cannot share with the share owner" : "Не може да се дели са власником дељења", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "Морате да унесете исправно име за пријаву", "Login contains whitespace at the beginning or at the end" : "Име за пријаву садржи белине на почетку или на крају", "Login must not consist of dots only" : "Име за пријаву не може да се састоји само од тачака", + "Username is too long" : "Корисничко име је сувише дугачко", "Login is invalid because files already exist for this user" : "Име за пријаву није исправно пошто већ постоје фајлови овог корисника", "Account disabled" : "Налог је искључен", "Login canceled by app" : "Пријава отказана од стране апликације", @@ -311,7 +332,6 @@ OC.L10N.register( "The audio to transcribe" : "Звук који треба да се транскрибује", "Transcription" : "Транскрипција", "The transcribed text" : "Транскрибовани текст", - "ContextAgent" : "КонтекстАгент", "Chat with an agent" : "Ћаскај са агентом", "Chat message" : "Чет порука", "A chat message to send to the agent." : "Порука која треба да се пошаље агенту.", @@ -346,6 +366,11 @@ OC.L10N.register( "How many images to generate" : "Колико слика желите да се генерише", "Output images" : "Излазне слике", "The generated images" : "Генерисане слике", + "Generate speech" : "Генериши говор", + "Generate speech from a transcript" : "Генерише говор из транскрипта", + "Write transcript that you want the assistant to generate speech from" : "Напишите транскрипт из којег желите да асистент генерише говор", + "Output speech" : "Излазни говор", + "The generated speech" : "Генерисани говор", "Free text to text prompt" : "Произвољни текст као унос", "Runs an arbitrary prompt through a language model that returns a reply" : "Извршава произвољни захтев кроз језички модел који затим враћа одговор", "Describe a task that you want the assistant to do or ask a question" : "Опишите задатак који желите да обави асистент или поставите питање", @@ -384,6 +409,12 @@ OC.L10N.register( "Original text" : "Оригинални текст", "The original text to generate a headline for" : "Оригинални текст за који се генерише наслов", "The generated headline" : "Генерисани наслов", + "Proofread" : "Лектура", + "Proofreads a text and lists corrections" : "Лекторише текст и исписује листу исправки", + "Text" : "Текст", + "The text to proofread" : "Текст који треба да се лекторише", + "Corrections" : "Исправке", + "The corrections that should be made in your text" : "Исправке које треба да се ураде над вашим текстом", "Reformulate text" : "Реформулиши текст", "Takes a text and reformulates it" : "Узима текст и реформулише га", "Write a text that you want the assistant to reformulate" : "Напишите текст који желите да асистент реформулише", @@ -419,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Генериши линију наслова", "Summarizes text by reducing its length without losing key information." : "Резимира текст тако што га скраћује без губитка кључних информација.", "Extracts topics from a text and outputs them separated by commas." : "Издваја теме из текста и исписује их раздвојене запетама.", - "Education Edition" : "Образовно издање", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Пријављени корисник мора бити админ, под админ или да поседује специјално право да приступи овом подешавању", - "Logged in user must be an admin or sub admin" : "Пријављени корисник мора бити администратор или подадминистратор", - "Logged in user must be an admin" : "Пријављени корисник мора бити администратор", - "File name is a reserved word" : "Назив фајла је резервисана реч", - "File name contains at least one invalid character" : "Назив фајла садржи бар један недозвољен знак", - "File name is too long" : "Назив фајла је предугачак", - "Help" : "Помоћ", - "Users" : "Корисници", - "Unknown user" : "Непознат корисник", - "Enter the database username and name for %s" : "Унесите корисничко име базе података и назив за %s", - "Enter the database username for %s" : "Унесите корисничко име базе података за %s", - "MySQL username and/or password not valid" : "MySQL корисничко име и/или лозинка нису исправни", - "Oracle username and/or password not valid" : "Oracle корисничко име и/или лозинка нису исправни", - "PostgreSQL username and/or password not valid" : "PostgreSQL корисничко име и/или лозинка нису исправни", - "Set an admin username." : "Поставите име за администратора.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s је поделио „%2$s“ са Вама и жели да дода:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s је поделио „%2$s“ са Вама и жели да дода", - "»%s« added a note to a file shared with you" : "\"%s\" је додао белешку на фајл који дели са Вама", - "Open »%s«" : "Отвори „%s“", - "Sharing %s failed, because this item is already shared with user %s" : "Дељење %s није успело зато што се ова ставка већ дели са корисником %s", - "%1$s shared »%2$s« with you" : "%1$s је поделио „%2$s“ са Вама", - "%1$s shared »%2$s« with you." : "%1$s је поделио „%2$s“ са Вама.", - "The username is already being used" : "Корисничко име се већ користи", - "Could not create user" : "Не могу да направим корисника", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "У корисничком имену су дозвољени само следећи карактери: „a-z”, „A-Z”, „0-9”, размаци и „_.@-'", - "A valid username must be provided" : "Морате унети исправно корисничко име", - "Username contains whitespace at the beginning or at the end" : "Корисничко име садржи белине на почетку или на крају", - "Username must not consist of dots only" : "Корисничко име не могу бити само тачке", - "Username is invalid because files already exist for this user" : "Корисничко име није исправно пошто већ постоје фајлови за овог корисника", - "User disabled" : "Корисник онемогућен", + "Organisation" : "Организација", "File is currently busy, please try again later" : "Фајл је тренутно заузет, покушајте поново касније", "Cannot download file" : "Фајл не може да се преузме", - "Your data directory is readable by other users." : "Ваш директоријум са подацима могу да читају остали корисници.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Промените дозволе у 0770 како директоријуми не би могли бити излистани од стране других корисника.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Уверите се да фајл \".ocdata\" постоји у корену директоријума са подацима." + "Login is too long" : "Име за пријаву је сувише дугачко" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/lib/l10n/sr.json b/lib/l10n/sr.json index d5af370fa19..6d25c86916c 100644 --- a/lib/l10n/sr.json +++ b/lib/l10n/sr.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Потребна је верзија сервера %s или виша.", "Server version %s or lower is required." : "Потребна је верзија сервера %s или нижа.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Пријављени налог мора бити админ, подадмин или мора да поседује специјално право да приступи овом подешавању", - "Your current IP address doesn’t allow you to perform admin actions" : "Ваша тренутна IP адреса не дозвољава да извршавате админ радње", + "Your current IP address doesn't allow you to perform admin actions" : "Ваша тренутна IP адреса не дозвољава да извршавате админ радње", "Logged in account must be an admin or sub admin" : "Пријављени налог мора бити админ или подадмин", "Logged in account must be an admin" : "Пријављени налог мора бити админ", "Wiping of device %s has started" : "Започето брисање уређаја %s", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Слика аватара није квадратна", "Files" : "Фајлови", "View profile" : "Погледај профил", + "same time" : "исто време", + "_%nh_::_%nh_" : ["%nч","%nч","%nч"], + "_%nm_::_%nm_" : ["%nм","%nм","%nм"], + "%s ahead" : "%s испред", + "%s behind" : "%s иза", "Local time: %s" : "Локално време: %s", "today" : "данас", "tomorrow" : "сутра", @@ -79,7 +84,15 @@ "seconds ago" : "пре неколико секунди", "Empty file" : "Празан фајл", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Модул са идентификацијом: %s не постоји. Омогућите га у подешавањима апликација или контактирајте администратора.", + "No file conversion providers available" : "Није доступан ниједан пружалац услуге конверзије фајла", + "File is too large to convert" : "Фајл је сувише велики да би могао да се конвертује", + "Destination does not match conversion extension" : "Одредиште не одговара екстензији конверзије", + "Could not convert file" : "Фајл није могао да се конвертује", + "Destination does not exist" : "Одредиште не постоји", + "Destination is not creatable" : "Одредиште не може да се креира", "Dot files are not allowed" : "Фајлови са почетном тачком нису дозвољени", + "%1$s (renamed)" : "%1$s (преименован)", + "renamed file" : "преименован фајл", "\"%1$s\" is a forbidden file or folder name." : "„%1$s” је забрањено име фајла или фолдера.", "\"%1$s\" is a forbidden prefix for file or folder names." : "„%1$s” је забрањени префикс имена фајла или фолдера.", "\"%1$s\" is not allowed inside a file or folder name." : "„%1$s” није дозвољено у имену фајла или фолдера.", @@ -90,6 +103,13 @@ "Invalid path" : "Неисправна путања", "Failed to create file from template" : "Није успело креирање фајла из шаблона", "Templates" : "Шаблони", + "Storage %s cannot be moved" : "Складиште %s не може да се премести", + "Moving a share (%s) into a shared folder is not allowed" : "Није дозвољено премештање дељења (%s) у дељени фолдер", + "Moving a storage (%s) into a shared folder is not allowed" : "Није дозвољено премештање складишта (%s) у дељени фолдер", + "Moving a share (%s) into another share (%s) is not allowed" : "Није дозвољено премештање дељења (%s) у друго дељење (%s)", + "Moving a share (%s) into another storage (%s) is not allowed" : "Није дозвољено премештање дељења (%s) у друго складиште (%s)", + "Moving a storage (%s) into a share (%s) is not allowed" : "Није дозвољено премештање складишта (%s) у дељење (%s)", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Није дозвољено премештање складишта (%s) у друго складиште (%s)", "Path contains invalid segments" : "Путања садржи неисправне сегменте", "Filename is a reserved word" : "Име фајла је резервисана реч", "Filename contains at least one invalid character" : "Назив фајла садржи бар један недозвољен знак", @@ -122,7 +142,7 @@ "About" : "О програму", "Display name" : "Име за приказ", "Headline" : "Наслов", - "Organisation" : "Организација", + "Organization" : "Организација", "Role" : "Улога", "Pronouns" : "Заменице", "Unknown account" : "Непознати налог", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "Веза са базом података Oracle не може бити успостављена", "Oracle Login and/or password not valid" : "Oracle име за пријаву и/или лозинка нису исправни", "PostgreSQL Login and/or password not valid" : "PostgreSQL име за пријаву и/или лозинка нису исправни", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Мек ОС Икс није подржан и %s неће радити исправно на овој платформи. Користите га на сопствени ризик!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X није подржан и %s неће радити исправно на овој платформи. Користите га на сопствени ризик!", "For the best results, please consider using a GNU/Linux server instead." : "За најбоље резултате, размотрите употребу ГНУ/Линукс сервера.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Изгледа да %s ради у 32-битном PHP окружењу а open_basedir је подешен у php.ini фајлу. То може довести до проблема са фајловима већим од 4 GB, те стога није препоручљиво.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Уклоните open_basedir поставку из php.ini фајла или пређите на 64-битни PHP.", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "Позадина за дељење %s није пронађена", "Sharing backend for %s not found" : "Позадина за дељење за %s није пронађена", "%1$s shared %2$s with you" : "%1$s је поделио „%2$s” са вама", - "Click the button below to open it." : "Кликните дугме испод да га отворите.", "Open %s" : "Отвори %s", "%1$s via %2$s" : "%1$s преко %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s је поделио %2$s са вама и жели да дода:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "Не можете да делите свој корени фолдер", "You are not allowed to share %s" : "Није вам дозвољено да делите %s", "Valid permissions are required for sharing" : "За дељење су неопходне исправне дозволе", + "File shares cannot have create or delete permissions" : "Фајлови не могу да се деле са дозволама за креирање или брисање", "Cannot increase permissions of %s" : "Не могу да повећам привилегије за %s", "Shares need at least read permissions" : "Дељења морају да имају барем право читања", "Files cannot be shared with delete permissions" : "Фајлови не могу да се деле са дозволама за брисање", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "Путања се већ дели са овом групом", "Link sharing is not allowed" : "Није дозвољено дељење линком", "Public upload is not allowed" : "Није дозвољено јавно отпремање", - "Path contains files shared with you" : "Путања садржи фајлове који су подељени са вама", + "You cannot share a folder that contains other shares" : "Не можете да делите фолдер који садржи друга дељења", "Sharing is disabled" : "Дељење је искључено", "Sharing is disabled for you" : "Дељење је за вас искључено", "Cannot share with the share owner" : "Не може да се дели са власником дељења", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "Морате да унесете исправно име за пријаву", "Login contains whitespace at the beginning or at the end" : "Име за пријаву садржи белине на почетку или на крају", "Login must not consist of dots only" : "Име за пријаву не може да се састоји само од тачака", + "Username is too long" : "Корисничко име је сувише дугачко", "Login is invalid because files already exist for this user" : "Име за пријаву није исправно пошто већ постоје фајлови овог корисника", "Account disabled" : "Налог је искључен", "Login canceled by app" : "Пријава отказана од стране апликације", @@ -309,7 +330,6 @@ "The audio to transcribe" : "Звук који треба да се транскрибује", "Transcription" : "Транскрипција", "The transcribed text" : "Транскрибовани текст", - "ContextAgent" : "КонтекстАгент", "Chat with an agent" : "Ћаскај са агентом", "Chat message" : "Чет порука", "A chat message to send to the agent." : "Порука која треба да се пошаље агенту.", @@ -344,6 +364,11 @@ "How many images to generate" : "Колико слика желите да се генерише", "Output images" : "Излазне слике", "The generated images" : "Генерисане слике", + "Generate speech" : "Генериши говор", + "Generate speech from a transcript" : "Генерише говор из транскрипта", + "Write transcript that you want the assistant to generate speech from" : "Напишите транскрипт из којег желите да асистент генерише говор", + "Output speech" : "Излазни говор", + "The generated speech" : "Генерисани говор", "Free text to text prompt" : "Произвољни текст као унос", "Runs an arbitrary prompt through a language model that returns a reply" : "Извршава произвољни захтев кроз језички модел који затим враћа одговор", "Describe a task that you want the assistant to do or ask a question" : "Опишите задатак који желите да обави асистент или поставите питање", @@ -382,6 +407,12 @@ "Original text" : "Оригинални текст", "The original text to generate a headline for" : "Оригинални текст за који се генерише наслов", "The generated headline" : "Генерисани наслов", + "Proofread" : "Лектура", + "Proofreads a text and lists corrections" : "Лекторише текст и исписује листу исправки", + "Text" : "Текст", + "The text to proofread" : "Текст који треба да се лекторише", + "Corrections" : "Исправке", + "The corrections that should be made in your text" : "Исправке које треба да се ураде над вашим текстом", "Reformulate text" : "Реформулиши текст", "Takes a text and reformulates it" : "Узима текст и реформулише га", "Write a text that you want the assistant to reformulate" : "Напишите текст који желите да асистент реформулише", @@ -417,41 +448,9 @@ "Generate headline" : "Генериши линију наслова", "Summarizes text by reducing its length without losing key information." : "Резимира текст тако што га скраћује без губитка кључних информација.", "Extracts topics from a text and outputs them separated by commas." : "Издваја теме из текста и исписује их раздвојене запетама.", - "Education Edition" : "Образовно издање", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Пријављени корисник мора бити админ, под админ или да поседује специјално право да приступи овом подешавању", - "Logged in user must be an admin or sub admin" : "Пријављени корисник мора бити администратор или подадминистратор", - "Logged in user must be an admin" : "Пријављени корисник мора бити администратор", - "File name is a reserved word" : "Назив фајла је резервисана реч", - "File name contains at least one invalid character" : "Назив фајла садржи бар један недозвољен знак", - "File name is too long" : "Назив фајла је предугачак", - "Help" : "Помоћ", - "Users" : "Корисници", - "Unknown user" : "Непознат корисник", - "Enter the database username and name for %s" : "Унесите корисничко име базе података и назив за %s", - "Enter the database username for %s" : "Унесите корисничко име базе података за %s", - "MySQL username and/or password not valid" : "MySQL корисничко име и/или лозинка нису исправни", - "Oracle username and/or password not valid" : "Oracle корисничко име и/или лозинка нису исправни", - "PostgreSQL username and/or password not valid" : "PostgreSQL корисничко име и/или лозинка нису исправни", - "Set an admin username." : "Поставите име за администратора.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s је поделио „%2$s“ са Вама и жели да дода:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s је поделио „%2$s“ са Вама и жели да дода", - "»%s« added a note to a file shared with you" : "\"%s\" је додао белешку на фајл који дели са Вама", - "Open »%s«" : "Отвори „%s“", - "Sharing %s failed, because this item is already shared with user %s" : "Дељење %s није успело зато што се ова ставка већ дели са корисником %s", - "%1$s shared »%2$s« with you" : "%1$s је поделио „%2$s“ са Вама", - "%1$s shared »%2$s« with you." : "%1$s је поделио „%2$s“ са Вама.", - "The username is already being used" : "Корисничко име се већ користи", - "Could not create user" : "Не могу да направим корисника", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "У корисничком имену су дозвољени само следећи карактери: „a-z”, „A-Z”, „0-9”, размаци и „_.@-'", - "A valid username must be provided" : "Морате унети исправно корисничко име", - "Username contains whitespace at the beginning or at the end" : "Корисничко име садржи белине на почетку или на крају", - "Username must not consist of dots only" : "Корисничко име не могу бити само тачке", - "Username is invalid because files already exist for this user" : "Корисничко име није исправно пошто већ постоје фајлови за овог корисника", - "User disabled" : "Корисник онемогућен", + "Organisation" : "Организација", "File is currently busy, please try again later" : "Фајл је тренутно заузет, покушајте поново касније", "Cannot download file" : "Фајл не може да се преузме", - "Your data directory is readable by other users." : "Ваш директоријум са подацима могу да читају остали корисници.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Промените дозволе у 0770 како директоријуми не би могли бити излистани од стране других корисника.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Уверите се да фајл \".ocdata\" постоји у корену директоријума са подацима." + "Login is too long" : "Име за пријаву је сувише дугачко" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }
\ No newline at end of file diff --git a/lib/l10n/sr@latin.js b/lib/l10n/sr@latin.js index 042f035355f..0042ab270b7 100644 --- a/lib/l10n/sr@latin.js +++ b/lib/l10n/sr@latin.js @@ -8,6 +8,7 @@ OC.L10N.register( "seconds ago" : "pre par sekundi", "Filename contains at least one invalid character" : "Naziv fajla sadrži bar jedan nedozvoljen znak", "__language_name__" : "Srpski", + "Apps" : "Aplikacije", "Settings" : "Postavke", "Log out" : "Odjava", "Email" : "email", @@ -22,7 +23,6 @@ OC.L10N.register( "Thursday" : "Četvrtak", "Friday" : "Petak", "Saturday" : "Subota", - "Translate" : "Prevedi", - "Help" : "Help" + "Translate" : "Prevedi" }, "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"); diff --git a/lib/l10n/sr@latin.json b/lib/l10n/sr@latin.json index 7ff0358bacf..857f80a066d 100644 --- a/lib/l10n/sr@latin.json +++ b/lib/l10n/sr@latin.json @@ -6,6 +6,7 @@ "seconds ago" : "pre par sekundi", "Filename contains at least one invalid character" : "Naziv fajla sadrži bar jedan nedozvoljen znak", "__language_name__" : "Srpski", + "Apps" : "Aplikacije", "Settings" : "Postavke", "Log out" : "Odjava", "Email" : "email", @@ -20,7 +21,6 @@ "Thursday" : "Četvrtak", "Friday" : "Petak", "Saturday" : "Subota", - "Translate" : "Prevedi", - "Help" : "Help" + "Translate" : "Prevedi" },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);" }
\ No newline at end of file diff --git a/lib/l10n/sv.js b/lib/l10n/sv.js index afd14966de8..2a4c2a3e440 100644 --- a/lib/l10n/sv.js +++ b/lib/l10n/sv.js @@ -38,17 +38,17 @@ OC.L10N.register( "Server version %s or higher is required." : "Serverversion %s eller nyare krävs.", "Server version %s or lower is required." : "Serverversion %s eller äldre krävs.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Inloggat konto måste vara en admin, underadministratör eller ha tilldelats speciella rättigheter för att komma åt denna inställning", - "Your current IP address doesn’t allow you to perform admin actions" : "Din nuvarande IP-adress tillåter dig inte att utföra administratörsåtgärder", + "Your current IP address doesn't allow you to perform admin actions" : "Din nuvarande IP-adress tillåter dig inte att utföra administratörsåtgärder", "Logged in account must be an admin or sub admin" : "Inloggat konto måste vara en admin eller underadministratör", "Logged in account must be an admin" : "Inloggat konto måste vara admin", "Wiping of device %s has started" : "Rensning av enhet %s har startat", - "Wiping of device »%s« has started" : "Rensning av enhet »%s« har startat", - "»%s« started remote wipe" : "»%s« startade fjärrensning", - "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "Enhet eller applikation »%s« har startat fjärrensning. Du kommer att få ett nytt mail när processen är klar", + "Wiping of device »%s« has started" : "Rensning av enhet \"%s\" har startat", + "»%s« started remote wipe" : "\"%s\" startade fjärrensning", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "Enhet eller applikation \"%s\" har startat fjärrensning. Du kommer att få ett nytt mail när processen är klar", "Wiping of device %s has finished" : "Rensning av enhet %s har slutförts", - "Wiping of device »%s« has finished" : "Rensning av enhet »%s« har slutförts", - "»%s« finished remote wipe" : "»%s« slutförde fjärrensning", - "Device or application »%s« has finished the remote wipe process." : "Enhet eller applikation »%s« har slutfört fjärrensning.", + "Wiping of device »%s« has finished" : "Rensning av enhet \"%s\" har slutförts", + "»%s« finished remote wipe" : "\"%s\" slutförde fjärrensning", + "Device or application »%s« has finished the remote wipe process." : "Enhet eller applikation \"%s\" har slutfört fjärrensning.", "Remote wipe started" : "Fjärrensning startad", "A remote wipe was started on device %s" : "Fjärrensning startades på enhet %s", "Remote wipe finished" : "Fjärrensning klar", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Profilbilden är inte fyrkantig", "Files" : "Filer", "View profile" : "Visa profil", + "same time" : "samma tid", + "_%nh_::_%nh_" : ["%nt","%nt"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s före", + "%s behind" : "%s efter", "Local time: %s" : "Lokal tid: %s", "today" : "idag", "tomorrow" : "imorgon", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "sekunder sedan", "Empty file" : "Tom fil", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulen med ID: %s finns inte. Aktivera den i appinställningar eller kontakta din administratör.", + "No file conversion providers available" : "Ingen filkonverterare tillgänglig", + "File is too large to convert" : "Filen är för stor för att konverteras", + "Destination does not match conversion extension" : "Målet matchar inte konverteringsändelsen", + "Could not convert file" : "Kunde inte konvertera filen", + "Destination does not exist" : "Destinationen finns inte", + "Destination is not creatable" : "Destinationen går inte att skapa", "Dot files are not allowed" : "Dot-filer är inte tillåtna", + "%1$s (renamed)" : "%1$s (omdöpt)", + "renamed file" : "omdöpt fil", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" är ett förbjudet fil- eller mappnamn.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" är ett förbjudet prefix för fil- eller mappnamn.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" är inte tillåtet i ett fil- eller mappnamn.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Ogiltig sökväg", "Failed to create file from template" : "Kunde skapa fil från mall", "Templates" : "Mallar", + "Storage %s cannot be moved" : "Lagring %s kan inte flyttas", + "Moving a share (%s) into a shared folder is not allowed" : "Att flytta en delning (%s) till en delad mapp är inte tillåtet", + "Moving a storage (%s) into a shared folder is not allowed" : "Att flytta en lagring (%s) till en delad mapp är inte tillåtet", + "Moving a share (%s) into another share (%s) is not allowed" : "Att flytta en delning (%s) till en annan delning (%s) är inte tillåtet", + "Moving a share (%s) into another storage (%s) is not allowed" : "Att flytta en delning (%s) till en annan lagring (%s) är inte tillåtet", + "Moving a storage (%s) into a share (%s) is not allowed" : "Att flytta en lagring (%s) till en delning (%s) är inte tillåtet", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Att flytta en lagring (%s) till en annan lagring (%s) är inte tillåtet", "Path contains invalid segments" : "Sökvägen innehåller ogiltiga segment", "Filename is a reserved word" : "Filnamnet är ett reserverat ord", "Filename contains at least one invalid character" : "Filnamnet innehåller minst ett ogiltigt tecken", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "Om", "Display name" : "Visningsnamn", "Headline" : "Rubrik", - "Organisation" : "Organisation", + "Organization" : "Organisering", "Role" : "Roll", "Pronouns" : "Pronomen", "Unknown account" : "Okänt konto", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Oracle-anslutning kunde inte etableras", "Oracle Login and/or password not valid" : "Oracle-inloggning och/eller lösenord är felaktigt", "PostgreSQL Login and/or password not valid" : "PostgreSQL-inloggning och/eller lösenord är felaktigt", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X stöds inte och %s kommer inte att fungera korrekt på denna plattform. Använd på egen risk!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X stöds inte och %s kommer inte att fungera korrekt på denna plattform. Använd på egen risk!", "For the best results, please consider using a GNU/Linux server instead." : "För bästa resultat, överväg att använda en GNU/Linux-server istället.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Det verkar som om denna %s instans körs på en 32-bitars PHP miljö och open_basedir har konfigurerats i php.ini. Detta kommer att leda till problem med filer över 4 GB och är verkligen inte rekommenderat!", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Ta bort open_basedir-inställningen i din php.ini eller växla till 64-bitars PHP.", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "Delningsgränssnittet %s hittades inte", "Sharing backend for %s not found" : "Delningsgränssnittet för %s hittades inte", "%1$s shared %2$s with you" : "%1$s delade %2$s med dig", - "Click the button below to open it." : "Klicka på knappen nedan för att öppna det.", "Open %s" : "Öppna %s", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s delade %2$s med dig och vill lägga till:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "Du kan inte dela din rotmapp", "You are not allowed to share %s" : "Du tillåts inte att dela %s", "Valid permissions are required for sharing" : "Giltiga behörigheter krävs för att dela", + "File shares cannot have create or delete permissions" : "Fildelningar kan inte ha behörighet att skapa eller radera", "Cannot increase permissions of %s" : "Kan inte höja behörigheter av %s", "Shares need at least read permissions" : "Delningar behöver åtminstone läsbehörighet", "Files cannot be shared with delete permissions" : "Filer kan inte delas med rättighet att radera", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "Sökvägen delas redan med den här gruppen", "Link sharing is not allowed" : "Länkdelning är inte tillåtet", "Public upload is not allowed" : "Offentlig uppladdning är inte tillåten", - "Path contains files shared with you" : "Sökvägen innehåller filer som delas med dig", + "You cannot share a folder that contains other shares" : "Du kan inte dela en mapp som innehåller andra delningar", "Sharing is disabled" : "Delning är inaktiverat", "Sharing is disabled for you" : "Delning är inaktiverat för dig", "Cannot share with the share owner" : "Kan inte dela med ägaren", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "En giltig inloggning måste anges", "Login contains whitespace at the beginning or at the end" : "Inloggningen innehåller blanksteg i början eller slutet", "Login must not consist of dots only" : "Inloggningen får inte innehålla enbart punkter", + "Username is too long" : "Användarnamnet är för långt", "Login is invalid because files already exist for this user" : "Inloggningen är ogiltigt eftersom det redan finns filer för den här användaren", "Account disabled" : "Konto inaktiverat", "Login canceled by app" : "Inloggningen avbruten av appen", @@ -311,8 +332,19 @@ OC.L10N.register( "The audio to transcribe" : "Ljudet att transkribera", "Transcription" : "Transkription", "The transcribed text" : "Den transkriberade texten", + "Chat with an agent" : "Chatta med en agent", "Chat message" : "Chattmeddelande", + "A chat message to send to the agent." : "Ett chattmeddelande att skicka till agenten.", "Confirmation" : "Bekräftelse", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Om tidigare begärda åtgärder ska bekräftas: 0 för avslag och 1 för bekräftelse.", + "Conversation token" : "Konversationstoken", + "A token representing the conversation." : "En token som representerar konversationen.", + "Generated response" : "Genererat svar", + "The response from the chat model." : "Svaret från chattmodellen.", + "The new conversation token" : "Den nya konversationstoken", + "Send this along with the next interaction." : "Skicka detta tillsammans med nästa interaktion.", + "Requested actions by the agent" : "Begärda åtgärder av agenten", + "Actions that the agent would like to carry out in JSON format." : "Åtgärder som agenten vill utföra i JSON-format.", "Context write" : "Kontextuell skrivning", "Writes text in a given style based on the provided source material." : "Skriver text i en given stil baserat på det tillhandahållna källmaterialet.", "Writing style" : "Skrivstil", @@ -334,11 +366,22 @@ OC.L10N.register( "How many images to generate" : "Hur många bilder som ska genereras", "Output images" : "Skapade bilder", "The generated images" : "De genererade bilderna", + "Generate speech" : "Generera tal", + "Generate speech from a transcript" : "Generera tal från en transkription", + "Write transcript that you want the assistant to generate speech from" : "Skriv den transkription som du vill att assistenten ska generera tal från", + "Output speech" : "Genererat tal", + "The generated speech" : "Det genererade talet", "Free text to text prompt" : "Fritext till text prompt", "Runs an arbitrary prompt through a language model that returns a reply" : "Kör en godtycklig prompt genom en språkmodell som returnerar ett svar", "Describe a task that you want the assistant to do or ask a question" : "Beskriv en uppgift som du vill att assistenten ska göra eller ställ en fråga", "Generated reply" : "Genererat svar", "The generated text from the assistant" : "Den genererade texten från assistenten", + "Change Tone" : "Ändra tonfall", + "Change the tone of a piece of text." : "Ändra tonfallet i ett stycke text.", + "Write a text that you want the assistant to rewrite in another tone." : "Skriv text som du vill att assistenten ska omformulera med ett annat tonfall.", + "Desired tone" : "Önskat tonfall", + "In which tone should your text be rewritten?" : "I vilken ton ska din text skrivas om?", + "The rewritten text in the desired tone, written by the assistant:" : "Den omskrivna texten i önskad ton, skriven av assistenten:", "Chat" : "Chatt", "Chat with the assistant" : "Chatta med assistenten", "System prompt" : "Systemuppmaning", @@ -347,6 +390,15 @@ OC.L10N.register( "The history of chat messages before the current message, starting with a message by the user" : "Historiken för chattmeddelanden före det aktuella meddelandet, som börjar med ett meddelande från användaren", "Response message" : "Svarsmeddelande", "The generated response as part of the conversation" : "Det genererade svaret som en del av konversationen", + "Chat with tools" : "Chatt med verktyg", + "Chat with the language model with tool calling support." : "Chatt med språkmodellen med stöd för verktygsanrop.", + "Tool message" : "Verktygsmeddelande", + "The result of tool calls in the last interaction" : "Resultatet av verktygsanropen i den senaste interaktionen", + "Available tools" : "Tillgängliga verktyg", + "The available tools in JSON format" : "Tillgängliga verktyg i JSON-format", + "The response from the chat model" : "Svaret från chattmodellen", + "Tool calls" : "Verktagsanrop", + "Tools call instructions from the model in JSON format" : "Verktygsanrop och instruktioner från modellen i JSON-format", "Formalize text" : "Formalisera text", "Takes a text and makes it sound more formal" : "Tar en text och får det att låta mer formellt", "Write a text that you want the assistant to formalize" : "Skriv en text som du vill att assistenten ska formalisera", @@ -357,6 +409,12 @@ OC.L10N.register( "Original text" : "Ursprunglig text", "The original text to generate a headline for" : "Den ursprungliga texten att skapa en rubrik för", "The generated headline" : "Den skapade rubriken", + "Proofread" : "Korrekturläs", + "Proofreads a text and lists corrections" : "Korrekturläser en text och listar korrigeringar", + "Text" : "Text", + "The text to proofread" : "Texten som ska korrekturläsas", + "Corrections" : "Korrigeringar", + "The corrections that should be made in your text" : "Korrigeringarna som bör göras i din text", "Reformulate text" : "Omformulera text", "Takes a text and reformulates it" : "Tar en text och omformulerar den", "Write a text that you want the assistant to reformulate" : "Skriv en text som du vill att assistenten ska formulera om", @@ -392,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Skapa rubrik", "Summarizes text by reducing its length without losing key information." : "Sammanfattar text genom att minska dess längd utan att förlora viktig information.", "Extracts topics from a text and outputs them separated by commas." : "Extraherar ämnen från en text och matar ut dem separerade med kommatecken.", - "Education Edition" : "Utbildningspaket", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Inloggad användare måste vara en admin, sub-admin eller ha tilldelats speciella rättigheter för att komma åt denna inställning", - "Logged in user must be an admin or sub admin" : "Inloggad användare måste vara administratör eller del-administratör", - "Logged in user must be an admin" : "Inloggad användare måste vara administratör", - "File name is a reserved word" : "Filnamnet är ett reserverat ord", - "File name contains at least one invalid character" : "Filnamnet innehåller minst ett ogiltigt tecken", - "File name is too long" : "Filnamnet är för långt", - "Help" : "Hjälp", - "Users" : "Användare", - "Unknown user" : "Okänd användare", - "Enter the database username and name for %s" : "Ange databasanvändarnamn och lösenord för %s", - "Enter the database username for %s" : "Ange databasanvändare för %s", - "MySQL username and/or password not valid" : "MySQL-användarnamn och/eller lösenord är felaktigt", - "Oracle username and/or password not valid" : "Oracle-användarnamnet och/eller lösenordet är felaktigt", - "PostgreSQL username and/or password not valid" : "PostgreSQL-användarnamnet och/eller lösenordet är felaktigt", - "Set an admin username." : "Ange ett användarnamn för administratören.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s delade »%2$s« med dig och vill lägga till:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s delade »%2$s« med dig och vill lägga till", - "»%s« added a note to a file shared with you" : "»%s« la till en kommentar till en fil delad med dig", - "Open »%s«" : "Öppna »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Delning av %s misslyckades eftersom detta redan är delat med användaren %s", - "%1$s shared »%2$s« with you" : "%1$s delade »%2$s« med dig", - "%1$s shared »%2$s« with you." : "%1$s delade »%2$s« med dig.", - "The username is already being used" : "Användarnamnet används redan", - "Could not create user" : "Kunde inte skapa användare", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Endast följande tecken är tillåtna i ett användarnamn: \"a-z\", \"A-Z\", \"0-9\", mellanslag och \"_.@-'\"", - "A valid username must be provided" : "Ett giltigt användarnamn måste anges", - "Username contains whitespace at the beginning or at the end" : "Användarnamnet består av ett mellanslag i början eller i slutet", - "Username must not consist of dots only" : "Användarnamnet får inte innehålla enbart punkter", - "Username is invalid because files already exist for this user" : "Användarnamnet är ogiltigt eftersom det redan finns filer för den här användaren", - "User disabled" : "Användare inaktiverad", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "Filen är för tillfället upptagen, försök igen senare", "Cannot download file" : "Kan inte ladda ner fil", - "Your data directory is readable by other users." : "Din datakatalog kan läsas av andra användare.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Ändra behörigheterna till 0770 så att katalogen inte kan listas av andra användare.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Säkerställ att du har filen \".ocdata\" i huvudkatalogen för din data." + "Login is too long" : "Inloggningen är för lång" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/sv.json b/lib/l10n/sv.json index 72791d58fa6..31df77b1406 100644 --- a/lib/l10n/sv.json +++ b/lib/l10n/sv.json @@ -36,17 +36,17 @@ "Server version %s or higher is required." : "Serverversion %s eller nyare krävs.", "Server version %s or lower is required." : "Serverversion %s eller äldre krävs.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Inloggat konto måste vara en admin, underadministratör eller ha tilldelats speciella rättigheter för att komma åt denna inställning", - "Your current IP address doesn’t allow you to perform admin actions" : "Din nuvarande IP-adress tillåter dig inte att utföra administratörsåtgärder", + "Your current IP address doesn't allow you to perform admin actions" : "Din nuvarande IP-adress tillåter dig inte att utföra administratörsåtgärder", "Logged in account must be an admin or sub admin" : "Inloggat konto måste vara en admin eller underadministratör", "Logged in account must be an admin" : "Inloggat konto måste vara admin", "Wiping of device %s has started" : "Rensning av enhet %s har startat", - "Wiping of device »%s« has started" : "Rensning av enhet »%s« har startat", - "»%s« started remote wipe" : "»%s« startade fjärrensning", - "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "Enhet eller applikation »%s« har startat fjärrensning. Du kommer att få ett nytt mail när processen är klar", + "Wiping of device »%s« has started" : "Rensning av enhet \"%s\" har startat", + "»%s« started remote wipe" : "\"%s\" startade fjärrensning", + "Device or application »%s« has started the remote wipe process. You will receive another email once the process has finished" : "Enhet eller applikation \"%s\" har startat fjärrensning. Du kommer att få ett nytt mail när processen är klar", "Wiping of device %s has finished" : "Rensning av enhet %s har slutförts", - "Wiping of device »%s« has finished" : "Rensning av enhet »%s« har slutförts", - "»%s« finished remote wipe" : "»%s« slutförde fjärrensning", - "Device or application »%s« has finished the remote wipe process." : "Enhet eller applikation »%s« har slutfört fjärrensning.", + "Wiping of device »%s« has finished" : "Rensning av enhet \"%s\" har slutförts", + "»%s« finished remote wipe" : "\"%s\" slutförde fjärrensning", + "Device or application »%s« has finished the remote wipe process." : "Enhet eller applikation \"%s\" har slutfört fjärrensning.", "Remote wipe started" : "Fjärrensning startad", "A remote wipe was started on device %s" : "Fjärrensning startades på enhet %s", "Remote wipe finished" : "Fjärrensning klar", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Profilbilden är inte fyrkantig", "Files" : "Filer", "View profile" : "Visa profil", + "same time" : "samma tid", + "_%nh_::_%nh_" : ["%nt","%nt"], + "_%nm_::_%nm_" : ["%nm","%nm"], + "%s ahead" : "%s före", + "%s behind" : "%s efter", "Local time: %s" : "Lokal tid: %s", "today" : "idag", "tomorrow" : "imorgon", @@ -79,7 +84,15 @@ "seconds ago" : "sekunder sedan", "Empty file" : "Tom fil", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Modulen med ID: %s finns inte. Aktivera den i appinställningar eller kontakta din administratör.", + "No file conversion providers available" : "Ingen filkonverterare tillgänglig", + "File is too large to convert" : "Filen är för stor för att konverteras", + "Destination does not match conversion extension" : "Målet matchar inte konverteringsändelsen", + "Could not convert file" : "Kunde inte konvertera filen", + "Destination does not exist" : "Destinationen finns inte", + "Destination is not creatable" : "Destinationen går inte att skapa", "Dot files are not allowed" : "Dot-filer är inte tillåtna", + "%1$s (renamed)" : "%1$s (omdöpt)", + "renamed file" : "omdöpt fil", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" är ett förbjudet fil- eller mappnamn.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" är ett förbjudet prefix för fil- eller mappnamn.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" är inte tillåtet i ett fil- eller mappnamn.", @@ -90,6 +103,13 @@ "Invalid path" : "Ogiltig sökväg", "Failed to create file from template" : "Kunde skapa fil från mall", "Templates" : "Mallar", + "Storage %s cannot be moved" : "Lagring %s kan inte flyttas", + "Moving a share (%s) into a shared folder is not allowed" : "Att flytta en delning (%s) till en delad mapp är inte tillåtet", + "Moving a storage (%s) into a shared folder is not allowed" : "Att flytta en lagring (%s) till en delad mapp är inte tillåtet", + "Moving a share (%s) into another share (%s) is not allowed" : "Att flytta en delning (%s) till en annan delning (%s) är inte tillåtet", + "Moving a share (%s) into another storage (%s) is not allowed" : "Att flytta en delning (%s) till en annan lagring (%s) är inte tillåtet", + "Moving a storage (%s) into a share (%s) is not allowed" : "Att flytta en lagring (%s) till en delning (%s) är inte tillåtet", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Att flytta en lagring (%s) till en annan lagring (%s) är inte tillåtet", "Path contains invalid segments" : "Sökvägen innehåller ogiltiga segment", "Filename is a reserved word" : "Filnamnet är ett reserverat ord", "Filename contains at least one invalid character" : "Filnamnet innehåller minst ett ogiltigt tecken", @@ -122,7 +142,7 @@ "About" : "Om", "Display name" : "Visningsnamn", "Headline" : "Rubrik", - "Organisation" : "Organisation", + "Organization" : "Organisering", "Role" : "Roll", "Pronouns" : "Pronomen", "Unknown account" : "Okänt konto", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "Oracle-anslutning kunde inte etableras", "Oracle Login and/or password not valid" : "Oracle-inloggning och/eller lösenord är felaktigt", "PostgreSQL Login and/or password not valid" : "PostgreSQL-inloggning och/eller lösenord är felaktigt", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X stöds inte och %s kommer inte att fungera korrekt på denna plattform. Använd på egen risk!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X stöds inte och %s kommer inte att fungera korrekt på denna plattform. Använd på egen risk!", "For the best results, please consider using a GNU/Linux server instead." : "För bästa resultat, överväg att använda en GNU/Linux-server istället.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Det verkar som om denna %s instans körs på en 32-bitars PHP miljö och open_basedir har konfigurerats i php.ini. Detta kommer att leda till problem med filer över 4 GB och är verkligen inte rekommenderat!", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Ta bort open_basedir-inställningen i din php.ini eller växla till 64-bitars PHP.", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "Delningsgränssnittet %s hittades inte", "Sharing backend for %s not found" : "Delningsgränssnittet för %s hittades inte", "%1$s shared %2$s with you" : "%1$s delade %2$s med dig", - "Click the button below to open it." : "Klicka på knappen nedan för att öppna det.", "Open %s" : "Öppna %s", "%1$s via %2$s" : "%1$s via %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s delade %2$s med dig och vill lägga till:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "Du kan inte dela din rotmapp", "You are not allowed to share %s" : "Du tillåts inte att dela %s", "Valid permissions are required for sharing" : "Giltiga behörigheter krävs för att dela", + "File shares cannot have create or delete permissions" : "Fildelningar kan inte ha behörighet att skapa eller radera", "Cannot increase permissions of %s" : "Kan inte höja behörigheter av %s", "Shares need at least read permissions" : "Delningar behöver åtminstone läsbehörighet", "Files cannot be shared with delete permissions" : "Filer kan inte delas med rättighet att radera", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "Sökvägen delas redan med den här gruppen", "Link sharing is not allowed" : "Länkdelning är inte tillåtet", "Public upload is not allowed" : "Offentlig uppladdning är inte tillåten", - "Path contains files shared with you" : "Sökvägen innehåller filer som delas med dig", + "You cannot share a folder that contains other shares" : "Du kan inte dela en mapp som innehåller andra delningar", "Sharing is disabled" : "Delning är inaktiverat", "Sharing is disabled for you" : "Delning är inaktiverat för dig", "Cannot share with the share owner" : "Kan inte dela med ägaren", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "En giltig inloggning måste anges", "Login contains whitespace at the beginning or at the end" : "Inloggningen innehåller blanksteg i början eller slutet", "Login must not consist of dots only" : "Inloggningen får inte innehålla enbart punkter", + "Username is too long" : "Användarnamnet är för långt", "Login is invalid because files already exist for this user" : "Inloggningen är ogiltigt eftersom det redan finns filer för den här användaren", "Account disabled" : "Konto inaktiverat", "Login canceled by app" : "Inloggningen avbruten av appen", @@ -309,8 +330,19 @@ "The audio to transcribe" : "Ljudet att transkribera", "Transcription" : "Transkription", "The transcribed text" : "Den transkriberade texten", + "Chat with an agent" : "Chatta med en agent", "Chat message" : "Chattmeddelande", + "A chat message to send to the agent." : "Ett chattmeddelande att skicka till agenten.", "Confirmation" : "Bekräftelse", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Om tidigare begärda åtgärder ska bekräftas: 0 för avslag och 1 för bekräftelse.", + "Conversation token" : "Konversationstoken", + "A token representing the conversation." : "En token som representerar konversationen.", + "Generated response" : "Genererat svar", + "The response from the chat model." : "Svaret från chattmodellen.", + "The new conversation token" : "Den nya konversationstoken", + "Send this along with the next interaction." : "Skicka detta tillsammans med nästa interaktion.", + "Requested actions by the agent" : "Begärda åtgärder av agenten", + "Actions that the agent would like to carry out in JSON format." : "Åtgärder som agenten vill utföra i JSON-format.", "Context write" : "Kontextuell skrivning", "Writes text in a given style based on the provided source material." : "Skriver text i en given stil baserat på det tillhandahållna källmaterialet.", "Writing style" : "Skrivstil", @@ -332,11 +364,22 @@ "How many images to generate" : "Hur många bilder som ska genereras", "Output images" : "Skapade bilder", "The generated images" : "De genererade bilderna", + "Generate speech" : "Generera tal", + "Generate speech from a transcript" : "Generera tal från en transkription", + "Write transcript that you want the assistant to generate speech from" : "Skriv den transkription som du vill att assistenten ska generera tal från", + "Output speech" : "Genererat tal", + "The generated speech" : "Det genererade talet", "Free text to text prompt" : "Fritext till text prompt", "Runs an arbitrary prompt through a language model that returns a reply" : "Kör en godtycklig prompt genom en språkmodell som returnerar ett svar", "Describe a task that you want the assistant to do or ask a question" : "Beskriv en uppgift som du vill att assistenten ska göra eller ställ en fråga", "Generated reply" : "Genererat svar", "The generated text from the assistant" : "Den genererade texten från assistenten", + "Change Tone" : "Ändra tonfall", + "Change the tone of a piece of text." : "Ändra tonfallet i ett stycke text.", + "Write a text that you want the assistant to rewrite in another tone." : "Skriv text som du vill att assistenten ska omformulera med ett annat tonfall.", + "Desired tone" : "Önskat tonfall", + "In which tone should your text be rewritten?" : "I vilken ton ska din text skrivas om?", + "The rewritten text in the desired tone, written by the assistant:" : "Den omskrivna texten i önskad ton, skriven av assistenten:", "Chat" : "Chatt", "Chat with the assistant" : "Chatta med assistenten", "System prompt" : "Systemuppmaning", @@ -345,6 +388,15 @@ "The history of chat messages before the current message, starting with a message by the user" : "Historiken för chattmeddelanden före det aktuella meddelandet, som börjar med ett meddelande från användaren", "Response message" : "Svarsmeddelande", "The generated response as part of the conversation" : "Det genererade svaret som en del av konversationen", + "Chat with tools" : "Chatt med verktyg", + "Chat with the language model with tool calling support." : "Chatt med språkmodellen med stöd för verktygsanrop.", + "Tool message" : "Verktygsmeddelande", + "The result of tool calls in the last interaction" : "Resultatet av verktygsanropen i den senaste interaktionen", + "Available tools" : "Tillgängliga verktyg", + "The available tools in JSON format" : "Tillgängliga verktyg i JSON-format", + "The response from the chat model" : "Svaret från chattmodellen", + "Tool calls" : "Verktagsanrop", + "Tools call instructions from the model in JSON format" : "Verktygsanrop och instruktioner från modellen i JSON-format", "Formalize text" : "Formalisera text", "Takes a text and makes it sound more formal" : "Tar en text och får det att låta mer formellt", "Write a text that you want the assistant to formalize" : "Skriv en text som du vill att assistenten ska formalisera", @@ -355,6 +407,12 @@ "Original text" : "Ursprunglig text", "The original text to generate a headline for" : "Den ursprungliga texten att skapa en rubrik för", "The generated headline" : "Den skapade rubriken", + "Proofread" : "Korrekturläs", + "Proofreads a text and lists corrections" : "Korrekturläser en text och listar korrigeringar", + "Text" : "Text", + "The text to proofread" : "Texten som ska korrekturläsas", + "Corrections" : "Korrigeringar", + "The corrections that should be made in your text" : "Korrigeringarna som bör göras i din text", "Reformulate text" : "Omformulera text", "Takes a text and reformulates it" : "Tar en text och omformulerar den", "Write a text that you want the assistant to reformulate" : "Skriv en text som du vill att assistenten ska formulera om", @@ -390,41 +448,9 @@ "Generate headline" : "Skapa rubrik", "Summarizes text by reducing its length without losing key information." : "Sammanfattar text genom att minska dess längd utan att förlora viktig information.", "Extracts topics from a text and outputs them separated by commas." : "Extraherar ämnen från en text och matar ut dem separerade med kommatecken.", - "Education Edition" : "Utbildningspaket", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Inloggad användare måste vara en admin, sub-admin eller ha tilldelats speciella rättigheter för att komma åt denna inställning", - "Logged in user must be an admin or sub admin" : "Inloggad användare måste vara administratör eller del-administratör", - "Logged in user must be an admin" : "Inloggad användare måste vara administratör", - "File name is a reserved word" : "Filnamnet är ett reserverat ord", - "File name contains at least one invalid character" : "Filnamnet innehåller minst ett ogiltigt tecken", - "File name is too long" : "Filnamnet är för långt", - "Help" : "Hjälp", - "Users" : "Användare", - "Unknown user" : "Okänd användare", - "Enter the database username and name for %s" : "Ange databasanvändarnamn och lösenord för %s", - "Enter the database username for %s" : "Ange databasanvändare för %s", - "MySQL username and/or password not valid" : "MySQL-användarnamn och/eller lösenord är felaktigt", - "Oracle username and/or password not valid" : "Oracle-användarnamnet och/eller lösenordet är felaktigt", - "PostgreSQL username and/or password not valid" : "PostgreSQL-användarnamnet och/eller lösenordet är felaktigt", - "Set an admin username." : "Ange ett användarnamn för administratören.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s delade »%2$s« med dig och vill lägga till:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s delade »%2$s« med dig och vill lägga till", - "»%s« added a note to a file shared with you" : "»%s« la till en kommentar till en fil delad med dig", - "Open »%s«" : "Öppna »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "Delning av %s misslyckades eftersom detta redan är delat med användaren %s", - "%1$s shared »%2$s« with you" : "%1$s delade »%2$s« med dig", - "%1$s shared »%2$s« with you." : "%1$s delade »%2$s« med dig.", - "The username is already being used" : "Användarnamnet används redan", - "Could not create user" : "Kunde inte skapa användare", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Endast följande tecken är tillåtna i ett användarnamn: \"a-z\", \"A-Z\", \"0-9\", mellanslag och \"_.@-'\"", - "A valid username must be provided" : "Ett giltigt användarnamn måste anges", - "Username contains whitespace at the beginning or at the end" : "Användarnamnet består av ett mellanslag i början eller i slutet", - "Username must not consist of dots only" : "Användarnamnet får inte innehålla enbart punkter", - "Username is invalid because files already exist for this user" : "Användarnamnet är ogiltigt eftersom det redan finns filer för den här användaren", - "User disabled" : "Användare inaktiverad", + "Organisation" : "Organisation", "File is currently busy, please try again later" : "Filen är för tillfället upptagen, försök igen senare", "Cannot download file" : "Kan inte ladda ner fil", - "Your data directory is readable by other users." : "Din datakatalog kan läsas av andra användare.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Ändra behörigheterna till 0770 så att katalogen inte kan listas av andra användare.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Säkerställ att du har filen \".ocdata\" i huvudkatalogen för din data." + "Login is too long" : "Inloggningen är för lång" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/sw.js b/lib/l10n/sw.js new file mode 100644 index 00000000000..60f4b19ac03 --- /dev/null +++ b/lib/l10n/sw.js @@ -0,0 +1,43 @@ +OC.L10N.register( + "lib", + { + "Authentication" : "Uthibitisho", + "Unknown filetype" : "Aina ya faili haijulikani", + "Invalid image" : "Taswira si halisi", + "Files" : "Mafaili", + "View profile" : "Angalia wasifu", + "Local time: %s" : "Muda wa kawaida: %s", + "_%n year ago_::_%n years ago_" : ["%n year ago","%n years ago"], + "seconds ago" : "sukunde zilizopita", + "%1$s (renamed)" : "%1$s (iliyopew jina jipya)", + "renamed file" : "Faili iliyopewa jina jipya", + "Filenames must not end with \"%1$s\"." : "Majina ya faili hayapaswi kuishia na \"%1$s\"", + "File already exists" : "Faili lipo tayari", + "Templates" : "Violezo", + "__language_name__" : "_lugha_jina_", + "Apps" : "Maombi", + "Settings" : "Mipangilio", + "Log out" : "Ondoka", + "Accounts" : "Akaunti", + "Email" : "Barua pepe", + "Phone" : "Simu", + "Twitter" : "Twitter", + "Website" : "Wavuti", + "Address" : "Anwani", + "About" : "Kuhusu", + "Additional settings" : "Mipangilio ya nyongeza", + "Sunday" : "Jumapili", + "Monday" : "Jumatatu", + "Tuesday" : "Jumanne", + "Wednesday" : "Jumatano", + "Thursday" : "Alhamisi", + "Friday" : "Ijumaa", + "Saturday" : "Jumamosi", + "Authentication error" : "Hitilafu ya uthibitishaji", + "Storage is temporarily not available" : "Uhifadhi haupo kwa muda", + "Confirmation" : "Uthibitisho", + "Text" : "Maandishi", + "Summary" : "Muhtasari", + "Translate" : "Tafsiri" +}, +"nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/sw.json b/lib/l10n/sw.json new file mode 100644 index 00000000000..9c261d85bf4 --- /dev/null +++ b/lib/l10n/sw.json @@ -0,0 +1,41 @@ +{ "translations": { + "Authentication" : "Uthibitisho", + "Unknown filetype" : "Aina ya faili haijulikani", + "Invalid image" : "Taswira si halisi", + "Files" : "Mafaili", + "View profile" : "Angalia wasifu", + "Local time: %s" : "Muda wa kawaida: %s", + "_%n year ago_::_%n years ago_" : ["%n year ago","%n years ago"], + "seconds ago" : "sukunde zilizopita", + "%1$s (renamed)" : "%1$s (iliyopew jina jipya)", + "renamed file" : "Faili iliyopewa jina jipya", + "Filenames must not end with \"%1$s\"." : "Majina ya faili hayapaswi kuishia na \"%1$s\"", + "File already exists" : "Faili lipo tayari", + "Templates" : "Violezo", + "__language_name__" : "_lugha_jina_", + "Apps" : "Maombi", + "Settings" : "Mipangilio", + "Log out" : "Ondoka", + "Accounts" : "Akaunti", + "Email" : "Barua pepe", + "Phone" : "Simu", + "Twitter" : "Twitter", + "Website" : "Wavuti", + "Address" : "Anwani", + "About" : "Kuhusu", + "Additional settings" : "Mipangilio ya nyongeza", + "Sunday" : "Jumapili", + "Monday" : "Jumatatu", + "Tuesday" : "Jumanne", + "Wednesday" : "Jumatano", + "Thursday" : "Alhamisi", + "Friday" : "Ijumaa", + "Saturday" : "Jumamosi", + "Authentication error" : "Hitilafu ya uthibitishaji", + "Storage is temporarily not available" : "Uhifadhi haupo kwa muda", + "Confirmation" : "Uthibitisho", + "Text" : "Maandishi", + "Summary" : "Muhtasari", + "Translate" : "Tafsiri" +},"pluralForm" :"nplurals=2; plural=(n != 1);" +}
\ No newline at end of file diff --git a/lib/l10n/ta.js b/lib/l10n/ta.js index b93c197b614..81a327ac972 100644 --- a/lib/l10n/ta.js +++ b/lib/l10n/ta.js @@ -15,6 +15,7 @@ OC.L10N.register( "Phone" : "தொலைப்பேசி", "Address" : "முகவரி", "About" : "பற்றி", + "Organization" : "நிறுவனம்", "Could not find category \"%s\"" : "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை", "Sunday" : "ஞாயிற்றுக்கிழமை", "Monday" : "திங்கட்கிழமை", @@ -57,8 +58,6 @@ OC.L10N.register( "Application is not enabled" : "செயலி இயலுமைப்படுத்தப்படவில்லை", "Authentication error" : "அத்தாட்சிப்படுத்தலில் வழு", "Token expired. Please reload page." : "அடையாளவில்லை காலாவதியாகிவிட்டது. தயவுசெய்து பக்கத்தை மீள் ஏற்றுக.", - "Translate" : "Translate", - "Help" : "உதவி", - "Users" : "பயனாளர்" + "Translate" : "Translate" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/ta.json b/lib/l10n/ta.json index 66cc40fe3f8..7b0bc63d08a 100644 --- a/lib/l10n/ta.json +++ b/lib/l10n/ta.json @@ -13,6 +13,7 @@ "Phone" : "தொலைப்பேசி", "Address" : "முகவரி", "About" : "பற்றி", + "Organization" : "நிறுவனம்", "Could not find category \"%s\"" : "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை", "Sunday" : "ஞாயிற்றுக்கிழமை", "Monday" : "திங்கட்கிழமை", @@ -55,8 +56,6 @@ "Application is not enabled" : "செயலி இயலுமைப்படுத்தப்படவில்லை", "Authentication error" : "அத்தாட்சிப்படுத்தலில் வழு", "Token expired. Please reload page." : "அடையாளவில்லை காலாவதியாகிவிட்டது. தயவுசெய்து பக்கத்தை மீள் ஏற்றுக.", - "Translate" : "Translate", - "Help" : "உதவி", - "Users" : "பயனாளர்" + "Translate" : "Translate" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/th.js b/lib/l10n/th.js index 1cd8fddc20c..234675da5d7 100644 --- a/lib/l10n/th.js +++ b/lib/l10n/th.js @@ -72,7 +72,6 @@ OC.L10N.register( "Display name" : "ชื่อที่แสดง", "Additional settings" : "การตั้งค่าเพิ่มเติม", "Oracle connection could not be established" : "ไม่สามารถสร้างการเชื่อมต่อกับ Oracle ", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "ระบบ Mac OS X ไม่ได้รับการสนับสนุน และ %s จะไม่ทำงานอย่างถูกต้องบนแพลตฟอร์มนี้ ใช้บนความเสี่ยงของคุณเอง!", "For the best results, please consider using a GNU/Linux server instead." : "เพื่อให้ได้ผลลัพธ์ที่ดีที่สุด โปรดพิจารณาใช้เซิร์ฟเวอร์ GNU/Linux แทน", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "ดูเหมือนว่าเซิร์ฟเวอร์ %s นี้ทำงานบน PHP 32 บิต และ open_basedir ได้ถูกกำหนดค่าใน php.ini ซึ่งจะมีปัญหากับไฟล์ที่มีขนาดใหญ่กว่า 4 GB และไม่แนะนำให้ใช้", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "กรุณาลบการตั้งค่า open_basedir ใน php.ini ของคุณ หรือเปลี่ยนไปใช้ PHP รุ่น 64 บิตแทน", @@ -151,23 +150,8 @@ OC.L10N.register( "Storage connection error. %s" : "ข้อผิดพลาดการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s", "Storage is temporarily not available" : "พื้นที่จัดเก็บข้อมูลไม่สามารถใช้งานได้ชั่วคราว", "Storage connection timeout. %s" : "หมดเวลาการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s", + "Text" : "ข้อความ", "Translate" : "แปลภาษา", - "File name is a reserved word" : "ชื่อแฟ้มเป็นคำสงวน", - "File name contains at least one invalid character" : "ชื่อไฟล์มีตัวอักษรที่ไม่ถูกต้องอย่างน้อย 1 ตัว", - "File name is too long" : "ชื่อไฟล์ยาวเกินไป", - "Help" : "ช่วยเหลือ", - "Users" : "ผู้ใช้งาน", - "Unknown user" : "ผู้ใช้ที่ไม่รู้จัก", - "Oracle username and/or password not valid" : "ชื่อผู้ใช้และ/หรือรหัสผ่าน Oracle ไม่ถูกต้อง", - "PostgreSQL username and/or password not valid" : "ชื่อผู้ใช้และ/หรือรหัสผ่าน PostgreSQL ไม่ถูกต้อง", - "Set an admin username." : "ตั้งค่าชื่อผู้ดูแลระบบ", - "Open »%s«" : "เปิด »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "การแชร์ %s ล้มเหลว เพราะรายการนี้ได้แชร์กับผู้ใช้ %s ไปแล้ว", - "The username is already being used" : "ชื่อผู้ใช้นี้ถูกใช้ไปแล้ว", - "A valid username must be provided" : "ต้องระบุชื่อผู้ใช้ที่ถูกต้อง", - "Username contains whitespace at the beginning or at the end" : "ชื่อผู้ใช้มีช่องว่างอยู่ด้านหน้าหรือด้านหลัง", - "User disabled" : "ผู้ใช้ถูกปิดใช้งาน", - "File is currently busy, please try again later" : "ไฟล์กำลังใช้งานอยู่ โปรดลองอีกครั้งในภายหลัง", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "กรุณาเปลี่ยนสิทธิ์การเข้าถึงเป็น 0770 เพื่อให้ไดเรกทอรีไม่สามารถแก้ไขโดยผู้ใช้อื่น" + "File is currently busy, please try again later" : "ไฟล์กำลังใช้งานอยู่ โปรดลองอีกครั้งในภายหลัง" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/th.json b/lib/l10n/th.json index 6d102cc2193..cc2c80d0e95 100644 --- a/lib/l10n/th.json +++ b/lib/l10n/th.json @@ -70,7 +70,6 @@ "Display name" : "ชื่อที่แสดง", "Additional settings" : "การตั้งค่าเพิ่มเติม", "Oracle connection could not be established" : "ไม่สามารถสร้างการเชื่อมต่อกับ Oracle ", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "ระบบ Mac OS X ไม่ได้รับการสนับสนุน และ %s จะไม่ทำงานอย่างถูกต้องบนแพลตฟอร์มนี้ ใช้บนความเสี่ยงของคุณเอง!", "For the best results, please consider using a GNU/Linux server instead." : "เพื่อให้ได้ผลลัพธ์ที่ดีที่สุด โปรดพิจารณาใช้เซิร์ฟเวอร์ GNU/Linux แทน", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "ดูเหมือนว่าเซิร์ฟเวอร์ %s นี้ทำงานบน PHP 32 บิต และ open_basedir ได้ถูกกำหนดค่าใน php.ini ซึ่งจะมีปัญหากับไฟล์ที่มีขนาดใหญ่กว่า 4 GB และไม่แนะนำให้ใช้", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "กรุณาลบการตั้งค่า open_basedir ใน php.ini ของคุณ หรือเปลี่ยนไปใช้ PHP รุ่น 64 บิตแทน", @@ -149,23 +148,8 @@ "Storage connection error. %s" : "ข้อผิดพลาดการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s", "Storage is temporarily not available" : "พื้นที่จัดเก็บข้อมูลไม่สามารถใช้งานได้ชั่วคราว", "Storage connection timeout. %s" : "หมดเวลาการเชื่อมต่อพื้นที่จัดเก็บข้อมูล %s", + "Text" : "ข้อความ", "Translate" : "แปลภาษา", - "File name is a reserved word" : "ชื่อแฟ้มเป็นคำสงวน", - "File name contains at least one invalid character" : "ชื่อไฟล์มีตัวอักษรที่ไม่ถูกต้องอย่างน้อย 1 ตัว", - "File name is too long" : "ชื่อไฟล์ยาวเกินไป", - "Help" : "ช่วยเหลือ", - "Users" : "ผู้ใช้งาน", - "Unknown user" : "ผู้ใช้ที่ไม่รู้จัก", - "Oracle username and/or password not valid" : "ชื่อผู้ใช้และ/หรือรหัสผ่าน Oracle ไม่ถูกต้อง", - "PostgreSQL username and/or password not valid" : "ชื่อผู้ใช้และ/หรือรหัสผ่าน PostgreSQL ไม่ถูกต้อง", - "Set an admin username." : "ตั้งค่าชื่อผู้ดูแลระบบ", - "Open »%s«" : "เปิด »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "การแชร์ %s ล้มเหลว เพราะรายการนี้ได้แชร์กับผู้ใช้ %s ไปแล้ว", - "The username is already being used" : "ชื่อผู้ใช้นี้ถูกใช้ไปแล้ว", - "A valid username must be provided" : "ต้องระบุชื่อผู้ใช้ที่ถูกต้อง", - "Username contains whitespace at the beginning or at the end" : "ชื่อผู้ใช้มีช่องว่างอยู่ด้านหน้าหรือด้านหลัง", - "User disabled" : "ผู้ใช้ถูกปิดใช้งาน", - "File is currently busy, please try again later" : "ไฟล์กำลังใช้งานอยู่ โปรดลองอีกครั้งในภายหลัง", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "กรุณาเปลี่ยนสิทธิ์การเข้าถึงเป็น 0770 เพื่อให้ไดเรกทอรีไม่สามารถแก้ไขโดยผู้ใช้อื่น" + "File is currently busy, please try again later" : "ไฟล์กำลังใช้งานอยู่ โปรดลองอีกครั้งในภายหลัง" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/tk.js b/lib/l10n/tk.js index 1934bafa03c..8bf4eb72e2a 100644 --- a/lib/l10n/tk.js +++ b/lib/l10n/tk.js @@ -11,7 +11,6 @@ OC.L10N.register( "Website" : "Website", "Address" : "Salgysy", "About" : "Hakynda", - "Translate" : "Terjime et", - "Help" : "Kömek" + "Translate" : "Terjime et" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/tk.json b/lib/l10n/tk.json index d1d18522cbd..fdc115784b3 100644 --- a/lib/l10n/tk.json +++ b/lib/l10n/tk.json @@ -9,7 +9,6 @@ "Website" : "Website", "Address" : "Salgysy", "About" : "Hakynda", - "Translate" : "Terjime et", - "Help" : "Kömek" + "Translate" : "Terjime et" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/tr.js b/lib/l10n/tr.js index 3ad6bc96d1d..457393b7b8d 100644 --- a/lib/l10n/tr.js +++ b/lib/l10n/tr.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Sunucu %s ya da daha sonraki bir sürüm olmalıdır.", "Server version %s or lower is required." : "Sunucu %s ya da daha önceki bir sürüm olmalıdır.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Oturum açmış hesap bir yönetici, bir alt yönetici veya bu ayara erişmek için özel izne sahip olmalıdır", - "Your current IP address doesn’t allow you to perform admin actions" : "Geçerli IP adresiniz yönetici işlemleri yapmanıza izin vermiyor", + "Your current IP address doesn't allow you to perform admin actions" : "Geçerli IP adresiniz yönetici işlemleri yapmanıza izin vermiyor", "Logged in account must be an admin or sub admin" : "Oturum açmış hesap bir yönetici ya da alt yönetici olmalıdır", "Logged in account must be an admin" : "Oturum açmış hesap bir yönetici olmalıdır", "Wiping of device %s has started" : "%s aygıtının silinmesine başlandı", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Avatar görseli kare değil", "Files" : "Dosyalar", "View profile" : "Profili görüntüle", + "same time" : "aynı zamanda", + "_%nh_::_%nh_" : ["%ns","%ns"], + "_%nm_::_%nm_" : ["%nd","%nd"], + "%s ahead" : "%s ileride", + "%s behind" : "%s geride", "Local time: %s" : "Yerel zaman: %s", "today" : "bugün", "tomorrow" : "yarın", @@ -78,10 +83,18 @@ OC.L10N.register( "_in %n minute_::_in %n minutes_" : ["%n dakika içinde","%n dakika içinde"], "_%n minute ago_::_%n minutes ago_" : ["%n dakika önce","%n dakika önce"], "in a few seconds" : "bir kaç saniye içinde", - "seconds ago" : "saniyeler önce", + "seconds ago" : "saniye önce", "Empty file" : "Dosya boş", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "%s kimlikli modül bulunamadı. Lütfen uygulamalarınız içinden modülü kullanıma alın ya da BT yöneticiniz ile görüşün.", + "No file conversion providers available" : "Kullanılabilecek bir dosya dönüştürücü hizmeti sağlayıcı yok", + "File is too large to convert" : "Dosya dönüştürülmek için çok büyük", + "Destination does not match conversion extension" : "Hedef dönüştürme eklentisiyle eşleşmiyor", + "Could not convert file" : "Dosya dönüştürülemedi", + "Destination does not exist" : "Hedef bulunamadı", + "Destination is not creatable" : "Hedef oluşturulamadı", "Dot files are not allowed" : "Nokta dosyalarına izin verilmiyor", + "%1$s (renamed)" : "%1$s (yeniden adlandırıldı)", + "renamed file" : "dosyayı yeniden adlandırdı", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" dosya ya da klasör adı olarak kullanılamaz.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" dosya ya da klasör adı ön eki olarak kullanılamaz.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" bir dosya ya da klasör adında kullanılamaz.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Yol geçersiz", "Failed to create file from template" : "Kalıptan dosya oluşturulamadı", "Templates" : "Kalıplar", + "Storage %s cannot be moved" : "%s depolama alanı taşınamadı", + "Moving a share (%s) into a shared folder is not allowed" : "Bir paylaşımın (%s) paylaşılan bir klasöre taşınmasına izin verilmiyor", + "Moving a storage (%s) into a shared folder is not allowed" : "Bir depolama alanının (%s) paylaşılan bir klasöre taşınmasına izin verilmiyor", + "Moving a share (%s) into another share (%s) is not allowed" : "Bir paylaşımın (%s) başka bir paylaşıma (%s) taşınmasına izin verilmiyor", + "Moving a share (%s) into another storage (%s) is not allowed" : "Bir paylaşımın (%s) başka bir depolama alanına (%s) taşınmasına izin verilmiyor", + "Moving a storage (%s) into a share (%s) is not allowed" : "Bir depolama alanının (%s) başka bir paylaşıma (%s) taşınmasına izin verilmiyor", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Bir depolama alanının (%s) başka bir depolama alanına (%s) taşınmasına izin verilmiyor", "Path contains invalid segments" : "Yolda geçersiz bölümler var", "Filename is a reserved word" : "Dosya adı sistem kullanımına ayrılmış bir sözcük", "Filename contains at least one invalid character" : "Dosya adında en az bir geçersiz karakter var", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "Hakkında", "Display name" : "Görüntülenecek ad", "Headline" : "Başlık", - "Organisation" : "Kuruluş", + "Organization" : "Kuruluş", "Role" : "Pozisyon", "Pronouns" : "Hitaplar", "Unknown account" : "Hesap bilinmiyor", @@ -138,24 +158,23 @@ OC.L10N.register( "Oracle connection could not be established" : "Oracle ile bağlantı kurulamadı", "Oracle Login and/or password not valid" : "Oracle kullanıcı adı ve/veya parolası geçersiz", "PostgreSQL Login and/or password not valid" : "PostgreSQL kullanıcı adı ve/veya parolası geçersiz", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X desteklenmiyor ve %s bu platformda düzgün çalışmayacak. Kullanmaktan doğacak riskler size aittir!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X desteklenmiyor ve %s bu platformda düzgün çalışmayacak. Kullanmaktan doğacak riskler size aittir!", "For the best results, please consider using a GNU/Linux server instead." : "En iyi sonucu almak için GNU/Linux sunucusu kullanın.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Bu %s kopyası 32 bit PHP ortamında çalıştırılıyor ve open_basedir seçeneği php.ini dosyasından ayarlanmış gibi görünüyor. Bu yapılandırma 4 GB boyutundan büyük dosyalarda sorun çıkarır ve kullanılması önerilmez.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Lütfen php.ini dosyasındaki open_basedir ayarını kaldırın ya da 64-bit PHP sürümüne geçin.", "Set an admin Login." : "Bir yönetici kullanıcı adı yazın.", "Set an admin password." : "Bir yönetici parolası yazın.", "Cannot create or write into the data directory %s" : "%s veri klasörü oluşturulamadı ya da içine yazılamadı", - "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Paylaşım arka ucu %s OCP\\Share_Backend arayüzünü desteklemeli", - "Sharing backend %s not found" : "%s paylaşım arka ucu bulunamadı", - "Sharing backend for %s not found" : "%s için paylaşım arka ucu bulunamadı", + "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Paylaşım arka yüzü %s OCP\\Share_Backend arayüzünü desteklemeli", + "Sharing backend %s not found" : "%s paylaşım arka yüzü bulunamadı", + "Sharing backend for %s not found" : "%s için paylaşım arka yüzü bulunamadı", "%1$s shared %2$s with you" : "%1$s, sizinle %2$s ögesini paylaştı", - "Click the button below to open it." : "Açmak için aşağıdaki düğmeye tıklayın.", - "Open %s" : "%s aç", + "Open %s" : "%s ögesini aç", "%1$s via %2$s" : "%1$s, %2$s aracılığıyla", "%1$s shared %2$s with you and wants to add:" : "%1$s sizinle %2$s ögesini paylaştı ve eklemenizi istiyor:", "%1$s shared %2$s with you and wants to add" : "%1$s sizinle %2$s ögesini paylaştı ve eklemenizi istiyor", "%s added a note to a file shared with you" : "%s sizinle paylaştığı bir dosyaya bir not ekledi", - "Passwords are enforced for link and mail shares" : "Bağlantı ve e-posta paylaşımları için parolalar zorunludur", + "Passwords are enforced for link and mail shares" : "Bağlantı ve e-posta paylaşımları için parola kullanılması zorunlu kılınmış", "Share recipient is not a valid user" : "Paylaşım alıcısı geçerli bir kullanıcı değil", "Share recipient is not a valid group" : "Paylaşım alıcısı geçerli bir grup değil", "Share recipient should be empty" : "Paylaşım alıcısı boş olmalı", @@ -169,12 +188,13 @@ OC.L10N.register( "You cannot share your root folder" : "Kök klasörünüzü paylaşamazsınız", "You are not allowed to share %s" : "%s ögesini paylaşma izniniz yok", "Valid permissions are required for sharing" : "Paylaşım için geçerli izinler olmalıdır", + "File shares cannot have create or delete permissions" : "Dosya paylaşımlarında oluşturma ya da silme izni olamaz", "Cannot increase permissions of %s" : "%s izinleri yükseltilemedi", "Shares need at least read permissions" : "Paylaşımların en azından okuma izinleri olmalıdır", "Files cannot be shared with delete permissions" : "Silme izni ile dosya paylaşılamaz", "Files cannot be shared with create permissions" : "Ekleme izni ile dosya paylaşılamaz", "Expiration date is in the past" : "Geçerlilik sonu tarihi geçmişte", - "Expiration date is enforced" : "Geçerlilik sonu tarihi dayatılıyor", + "Expiration date is enforced" : "Geçerlilik sonu tarihi zorunlu kılınmış", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Paylaşımların geçerlilik süreleri, gelecekte %n günden fazla olamaz","Paylaşımların geçerlilik süreleri, gelecekte %n günden fazla olamaz"], "Sharing is only allowed with group members" : "Paylaşım yalnızca grup üyeleri ile yapılabilir", "Sharing %s failed, because this item is already shared with the account %s" : "%s paylaşılamadı. Bu öge zaten %s hesabı ile paylaşılmış", @@ -183,16 +203,16 @@ OC.L10N.register( "Path is already shared with this group" : "Bu yol bu grup ile zaten paylaşılmış", "Link sharing is not allowed" : "Bağlantı paylaşımına izin verilmiyor", "Public upload is not allowed" : "Herkese açık yüklemeye izin verilmiyor", - "Path contains files shared with you" : "Yolda sizinle paylaşılmış dosyalar var", + "You cannot share a folder that contains other shares" : "Başka paylaşımların bulunduğu bir klasörü paylaşamazsınız", "Sharing is disabled" : "Paylaşım kullanımdan kaldırılmış", "Sharing is disabled for you" : "Paylaşım sizin için kullanımdan kaldırılmış", "Cannot share with the share owner" : "Paylaşımı sahibi ile paylaşamazsınız", "Share does not have a full ID" : "Paylaşımın tam kimliği yok", "Cannot change share type" : "Paylaşım türü değiştirilemez", "Can only update recipient on user shares" : "Yalnızca kullanıcı paylaşımlarındaki alıcıyı güncelleyebilir", - "Cannot enable sending the password by Talk with an empty password" : "Boş bir parola ile Sohbet uygulaması ile parola gönderme özelliği kullanıma alınamaz", - "Cannot enable sending the password by Talk without setting a new password" : "Yeni bir parola ayarlanmadan Sohbet uygulaması ile parola gönderme özelliği kullanıma alınamaz", - "Cannot disable sending the password by Talk without setting a new password" : "Yeni bir parola ayarlanmadan Sohbet uygulaması ile parola gönderme kullanımdan kaldırılamaz", + "Cannot enable sending the password by Talk with an empty password" : "Boş bir parola kullanarak Konuş uygulaması ile parola gönderme özelliği açılamaz", + "Cannot enable sending the password by Talk without setting a new password" : "Yeni bir parola ayarlanmadan Konuş uygulaması ile parola gönderme özelliği açılamaz", + "Cannot disable sending the password by Talk without setting a new password" : "Yeni bir parola ayarlanmadan Konuş uygulaması ile parola gönderme özelliği kapatılamaz", "Share provider does not support accepting" : "Paylaşım hizmeti sağlayıcısı kabul etmeyi desteklemiyor", "Cannot change target of link share" : "Bağlantı paylaşımının hedefi değiştirilemedi", "Invalid share recipient" : "Paylaşım alıcısı geçersiz", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "Geçerli bir kullanıcı adı yazmalısınız", "Login contains whitespace at the beginning or at the end" : "Kullanıcı adının başında ya da sonunda boşluk var", "Login must not consist of dots only" : "Kullanıcı adı yalnızca noktalardan oluşamaz", + "Username is too long" : "Kullanıcı adı çok uzun", "Login is invalid because files already exist for this user" : "Kullanıcı adı geçersiz, bu kullanıcı için zaten bazı dosyalar var", "Account disabled" : "Hesap kullanımdan kaldırılmış", "Login canceled by app" : "Oturum açma uygulama tarafından iptal edildi", @@ -311,8 +332,19 @@ OC.L10N.register( "The audio to transcribe" : "Yazıya dönüştürülecek ses", "Transcription" : "Yazıya dönüştürme", "The transcribed text" : "Dönüştürülen yazı", + "Chat with an agent" : "Bir aracı ile sohbet edin", "Chat message" : "Sohbet iletisi", + "A chat message to send to the agent." : "Aracıya gönderilecek sohbet iletisi.", "Confirmation" : "Onaylama", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Daha önce istenilen işlemlerin onaylanıp onaylanmayacağı: Reddedilmesi için 0, onaylanması için 1.", + "Conversation token" : "Görüşme kodu", + "A token representing the conversation." : "Görüşmenin kodu.", + "Generated response" : "Üretilen yanıt", + "The response from the chat model." : "Sohbet modelinin yanıtı.", + "The new conversation token" : "Yeni görüşme kodu", + "Send this along with the next interaction." : "Bunu sonraki etkileşimin yanında gönderin.", + "Requested actions by the agent" : "Aracı tarafından istenilen işlemler", + "Actions that the agent would like to carry out in JSON format." : "Aracının JSON biçiminde gerçekleştirmesi istenen işlemler.", "Context write" : "Bağlam yazma", "Writes text in a given style based on the provided source material." : "Sağlanan kaynak materyale göre belirli bir tarzda metin yazar.", "Writing style" : "Yazma tarzı", @@ -334,19 +366,39 @@ OC.L10N.register( "How many images to generate" : "Oluşturulacak görsel sayısı", "Output images" : "Çıktı görselleri", "The generated images" : "Oluşturulan görseller", + "Generate speech" : "Konuşma oluştur", + "Generate speech from a transcript" : "Bir yazıya dönüştürmeden konuşma oluştur", + "Write transcript that you want the assistant to generate speech from" : "Yardımcının konuşma oluşturmasını istediğiniz yazı dönüştürmesini yazın", + "Output speech" : "Konuşma çıktısı", + "The generated speech" : "Oluşturulan konuşma", "Free text to text prompt" : "Ücretsiz yazıdan yazıya istemi", "Runs an arbitrary prompt through a language model that returns a reply" : "Dil modeli ile bir yanıt döndüren isteğe bağlı bir bilgi istemi çalıştırır", "Describe a task that you want the assistant to do or ask a question" : "Yardımcının yapmasını istediğiniz bir görevi tanımlayın ya da bir soru sorun", "Generated reply" : "Oluşturulan yanıt", "The generated text from the assistant" : "Yardımcının oluşturduğu metin", + "Change Tone" : "Tonu değiştir", + "Change the tone of a piece of text." : "Bir metin parçasının tonunu değiştirir.", + "Write a text that you want the assistant to rewrite in another tone." : "Yardımcının başka bir tonda yeniden yazmasını istediğiniz bir metin yazın", + "Desired tone" : "İstenilen ton", + "In which tone should your text be rewritten?" : "Metin hangi tonda yeniden yazılmalı?", + "The rewritten text in the desired tone, written by the assistant:" : "Yardımcı tarafından istenilen tonda yeniden yazılan metin:", "Chat" : "Sohbet", "Chat with the assistant" : "Yardımcı ile sohbet et", "System prompt" : "Sistem istemi", - "Define rules and assumptions that the assistant should follow during the conversation." : "Sohbet sırasında yardımcının uyması gereken kuralları ve varsayımları tanımlayın.", + "Define rules and assumptions that the assistant should follow during the conversation." : "Görüşme sırasında yardımcının uyması gereken kuralları ve varsayımları tanımlayın.", "Chat history" : "Sohbet geçmişi", "The history of chat messages before the current message, starting with a message by the user" : "Kullanıcının iletisiyle başlayarak, geçerli iletiden önceki sohbet iletilerinin geçmişi", "Response message" : "Yanıt iletisi", - "The generated response as part of the conversation" : "Sohbetin parçası olarak oluşturulan yanıt", + "The generated response as part of the conversation" : "Görüşmenin parçası olarak oluşturulan yanıt", + "Chat with tools" : "Araçlar ile sohbet", + "Chat with the language model with tool calling support." : "Araç çağırma desteği ile dil modeliyle sohbet edin.", + "Tool message" : "Araç iletisi", + "The result of tool calls in the last interaction" : "Son etkileşimdeki araç çağrılarının sonucu", + "Available tools" : "Kullanılabilecek araçlar", + "The available tools in JSON format" : "JSON biçiminde kullanılabilecek araçlar", + "The response from the chat model" : "Sohbet modelinin yanıtı", + "Tool calls" : "Araç çağrıları", + "Tools call instructions from the model in JSON format" : "Araçlar, modelden JSON biçiminde komutları çağırır", "Formalize text" : "Metni resmileştir", "Takes a text and makes it sound more formal" : "Bir metni alarak daha resmi dile dönüştürür", "Write a text that you want the assistant to formalize" : "Yardımcının resmileştirmesini istediğiniz bir metin yazın", @@ -357,6 +409,12 @@ OC.L10N.register( "Original text" : "Özgün metin", "The original text to generate a headline for" : "Başlık oluşturulacak metin", "The generated headline" : "Oluşturulan başlık", + "Proofread" : "Düzelt", + "Proofreads a text and lists corrections" : "Bir metni düzeltir ve düzeltmeleri listeler", + "Text" : "Metin", + "The text to proofread" : "Düzeltilecek metin", + "Corrections" : "Düzeltmeler", + "The corrections that should be made in your text" : "Metninizde yapılması gereken düzeltmeler", "Reformulate text" : "Metni yeniden düzenle", "Takes a text and reformulates it" : "Bir metni alarak yeniden düzenler", "Write a text that you want the assistant to reformulate" : "Yardımcının yeniden düzenlemesini istediğiniz bir metin yazın", @@ -392,41 +450,9 @@ OC.L10N.register( "Generate headline" : "Başlık oluşturulsun", "Summarizes text by reducing its length without losing key information." : "Temel içeriği kaybetmeden uzunluğunu kısaltarak metni özetler.", "Extracts topics from a text and outputs them separated by commas." : "Bir metindeki konuları ayıklar ve bunları virgül ile ayırarak sıralar.", - "Education Edition" : "Eğitim sürümü", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Oturum açmış kullanıcı bir yönetici, bir alt yönetici veya bu ayara erişmek için özel izne sahip olmalıdır", - "Logged in user must be an admin or sub admin" : "Oturum açmış kullanıcı bir yönetici ya da alt yönetici olmalıdır", - "Logged in user must be an admin" : "Oturum açmış kullanıcı bir yönetici olmalıdır", - "File name is a reserved word" : "Bu dosya adı sistem kullanıma ayrılmıştır", - "File name contains at least one invalid character" : "Dosya adında en az bir geçersiz karakter var", - "File name is too long" : "Dosya adı çok uzun", - "Help" : "Yardım", - "Users" : "Kullanıcılar", - "Unknown user" : "Kullanıcı bilinmiyor", - "Enter the database username and name for %s" : "%s için veri tabanı adını ve kullanıcı adını yazın", - "Enter the database username for %s" : "%s için veri tabanı kullanıcı adını yazın", - "MySQL username and/or password not valid" : "MySQL kullanıcı adı ya da parolası geçersiz", - "Oracle username and/or password not valid" : "Oracle kullanıcı adı ya da parolası geçersiz", - "PostgreSQL username and/or password not valid" : "PostgreSQL kullanıcı adı ya da parolası geçersiz", - "Set an admin username." : "Bir yönetici kullanıcı adı yazın.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s sizinle »%2$s« ögesini paylaştı ve eklemenizi istiyor:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s sizinle »%2$s« ögesini paylaştı ve eklemenizi istiyor", - "»%s« added a note to a file shared with you" : "»%s« sizinle paylaştığı bir dosyaya bir not ekledi", - "Open »%s«" : "»%s« aç", - "Sharing %s failed, because this item is already shared with user %s" : "%s paylaşılamadı. Bu öge zaten %s kullanıcısı ile paylaşılmış", - "%1$s shared »%2$s« with you" : "%1$s, sizinle »%2$s« ögesini paylaştı", - "%1$s shared »%2$s« with you." : "%1$s, sizinle »%2$s« ögesini paylaştı.", - "The username is already being used" : "Bu kullanıcı adı zaten var", - "Could not create user" : "Kullanıcı oluşturulamadı", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kullanıcı adında yalnızca şu karakterler kullanılabilir: \"a-z\", \"A-Z\", \"0-9\", boşluk ve \"_.@-'\"", - "A valid username must be provided" : "Geçerli bir kullanıcı adı yazmalısınız", - "Username contains whitespace at the beginning or at the end" : "Kullanıcı adının başı ya da sonunda boşluk var", - "Username must not consist of dots only" : "Kullanıcı adı yalnızca noktalardan oluşamaz", - "Username is invalid because files already exist for this user" : "Kullanıcı adı geçersiz, bu kullanıcı için zaten bazı dosyalar var", - "User disabled" : "Kullanıcı kullanımdan kaldırılmış", + "Organisation" : "Kuruluş", "File is currently busy, please try again later" : "Dosya şu anda meşgul. Lütfen bir süre sonra yeniden deneyin", "Cannot download file" : "Dosya indirilemedi", - "Your data directory is readable by other users." : "Veri klasörünüz diğer kullanıcılar tarafından okunabilir.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Lütfen izinleri 0770 olarak ayarlayarak diğer kullanıcıların klasörü görebilmesini sağlayın.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Veri klasörü kökünde \".ocdata\" adında bir dosya bulunduğundan emin olun." + "Login is too long" : "Kullanıcı adı çok uzun" }, "nplurals=2; plural=(n > 1);"); diff --git a/lib/l10n/tr.json b/lib/l10n/tr.json index 5f294765dc3..97e6b913671 100644 --- a/lib/l10n/tr.json +++ b/lib/l10n/tr.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Sunucu %s ya da daha sonraki bir sürüm olmalıdır.", "Server version %s or lower is required." : "Sunucu %s ya da daha önceki bir sürüm olmalıdır.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Oturum açmış hesap bir yönetici, bir alt yönetici veya bu ayara erişmek için özel izne sahip olmalıdır", - "Your current IP address doesn’t allow you to perform admin actions" : "Geçerli IP adresiniz yönetici işlemleri yapmanıza izin vermiyor", + "Your current IP address doesn't allow you to perform admin actions" : "Geçerli IP adresiniz yönetici işlemleri yapmanıza izin vermiyor", "Logged in account must be an admin or sub admin" : "Oturum açmış hesap bir yönetici ya da alt yönetici olmalıdır", "Logged in account must be an admin" : "Oturum açmış hesap bir yönetici olmalıdır", "Wiping of device %s has started" : "%s aygıtının silinmesine başlandı", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Avatar görseli kare değil", "Files" : "Dosyalar", "View profile" : "Profili görüntüle", + "same time" : "aynı zamanda", + "_%nh_::_%nh_" : ["%ns","%ns"], + "_%nm_::_%nm_" : ["%nd","%nd"], + "%s ahead" : "%s ileride", + "%s behind" : "%s geride", "Local time: %s" : "Yerel zaman: %s", "today" : "bugün", "tomorrow" : "yarın", @@ -76,10 +81,18 @@ "_in %n minute_::_in %n minutes_" : ["%n dakika içinde","%n dakika içinde"], "_%n minute ago_::_%n minutes ago_" : ["%n dakika önce","%n dakika önce"], "in a few seconds" : "bir kaç saniye içinde", - "seconds ago" : "saniyeler önce", + "seconds ago" : "saniye önce", "Empty file" : "Dosya boş", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "%s kimlikli modül bulunamadı. Lütfen uygulamalarınız içinden modülü kullanıma alın ya da BT yöneticiniz ile görüşün.", + "No file conversion providers available" : "Kullanılabilecek bir dosya dönüştürücü hizmeti sağlayıcı yok", + "File is too large to convert" : "Dosya dönüştürülmek için çok büyük", + "Destination does not match conversion extension" : "Hedef dönüştürme eklentisiyle eşleşmiyor", + "Could not convert file" : "Dosya dönüştürülemedi", + "Destination does not exist" : "Hedef bulunamadı", + "Destination is not creatable" : "Hedef oluşturulamadı", "Dot files are not allowed" : "Nokta dosyalarına izin verilmiyor", + "%1$s (renamed)" : "%1$s (yeniden adlandırıldı)", + "renamed file" : "dosyayı yeniden adlandırdı", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" dosya ya da klasör adı olarak kullanılamaz.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" dosya ya da klasör adı ön eki olarak kullanılamaz.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" bir dosya ya da klasör adında kullanılamaz.", @@ -90,6 +103,13 @@ "Invalid path" : "Yol geçersiz", "Failed to create file from template" : "Kalıptan dosya oluşturulamadı", "Templates" : "Kalıplar", + "Storage %s cannot be moved" : "%s depolama alanı taşınamadı", + "Moving a share (%s) into a shared folder is not allowed" : "Bir paylaşımın (%s) paylaşılan bir klasöre taşınmasına izin verilmiyor", + "Moving a storage (%s) into a shared folder is not allowed" : "Bir depolama alanının (%s) paylaşılan bir klasöre taşınmasına izin verilmiyor", + "Moving a share (%s) into another share (%s) is not allowed" : "Bir paylaşımın (%s) başka bir paylaşıma (%s) taşınmasına izin verilmiyor", + "Moving a share (%s) into another storage (%s) is not allowed" : "Bir paylaşımın (%s) başka bir depolama alanına (%s) taşınmasına izin verilmiyor", + "Moving a storage (%s) into a share (%s) is not allowed" : "Bir depolama alanının (%s) başka bir paylaşıma (%s) taşınmasına izin verilmiyor", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Bir depolama alanının (%s) başka bir depolama alanına (%s) taşınmasına izin verilmiyor", "Path contains invalid segments" : "Yolda geçersiz bölümler var", "Filename is a reserved word" : "Dosya adı sistem kullanımına ayrılmış bir sözcük", "Filename contains at least one invalid character" : "Dosya adında en az bir geçersiz karakter var", @@ -122,7 +142,7 @@ "About" : "Hakkında", "Display name" : "Görüntülenecek ad", "Headline" : "Başlık", - "Organisation" : "Kuruluş", + "Organization" : "Kuruluş", "Role" : "Pozisyon", "Pronouns" : "Hitaplar", "Unknown account" : "Hesap bilinmiyor", @@ -136,24 +156,23 @@ "Oracle connection could not be established" : "Oracle ile bağlantı kurulamadı", "Oracle Login and/or password not valid" : "Oracle kullanıcı adı ve/veya parolası geçersiz", "PostgreSQL Login and/or password not valid" : "PostgreSQL kullanıcı adı ve/veya parolası geçersiz", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X desteklenmiyor ve %s bu platformda düzgün çalışmayacak. Kullanmaktan doğacak riskler size aittir!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X desteklenmiyor ve %s bu platformda düzgün çalışmayacak. Kullanmaktan doğacak riskler size aittir!", "For the best results, please consider using a GNU/Linux server instead." : "En iyi sonucu almak için GNU/Linux sunucusu kullanın.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Bu %s kopyası 32 bit PHP ortamında çalıştırılıyor ve open_basedir seçeneği php.ini dosyasından ayarlanmış gibi görünüyor. Bu yapılandırma 4 GB boyutundan büyük dosyalarda sorun çıkarır ve kullanılması önerilmez.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Lütfen php.ini dosyasındaki open_basedir ayarını kaldırın ya da 64-bit PHP sürümüne geçin.", "Set an admin Login." : "Bir yönetici kullanıcı adı yazın.", "Set an admin password." : "Bir yönetici parolası yazın.", "Cannot create or write into the data directory %s" : "%s veri klasörü oluşturulamadı ya da içine yazılamadı", - "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Paylaşım arka ucu %s OCP\\Share_Backend arayüzünü desteklemeli", - "Sharing backend %s not found" : "%s paylaşım arka ucu bulunamadı", - "Sharing backend for %s not found" : "%s için paylaşım arka ucu bulunamadı", + "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Paylaşım arka yüzü %s OCP\\Share_Backend arayüzünü desteklemeli", + "Sharing backend %s not found" : "%s paylaşım arka yüzü bulunamadı", + "Sharing backend for %s not found" : "%s için paylaşım arka yüzü bulunamadı", "%1$s shared %2$s with you" : "%1$s, sizinle %2$s ögesini paylaştı", - "Click the button below to open it." : "Açmak için aşağıdaki düğmeye tıklayın.", - "Open %s" : "%s aç", + "Open %s" : "%s ögesini aç", "%1$s via %2$s" : "%1$s, %2$s aracılığıyla", "%1$s shared %2$s with you and wants to add:" : "%1$s sizinle %2$s ögesini paylaştı ve eklemenizi istiyor:", "%1$s shared %2$s with you and wants to add" : "%1$s sizinle %2$s ögesini paylaştı ve eklemenizi istiyor", "%s added a note to a file shared with you" : "%s sizinle paylaştığı bir dosyaya bir not ekledi", - "Passwords are enforced for link and mail shares" : "Bağlantı ve e-posta paylaşımları için parolalar zorunludur", + "Passwords are enforced for link and mail shares" : "Bağlantı ve e-posta paylaşımları için parola kullanılması zorunlu kılınmış", "Share recipient is not a valid user" : "Paylaşım alıcısı geçerli bir kullanıcı değil", "Share recipient is not a valid group" : "Paylaşım alıcısı geçerli bir grup değil", "Share recipient should be empty" : "Paylaşım alıcısı boş olmalı", @@ -167,12 +186,13 @@ "You cannot share your root folder" : "Kök klasörünüzü paylaşamazsınız", "You are not allowed to share %s" : "%s ögesini paylaşma izniniz yok", "Valid permissions are required for sharing" : "Paylaşım için geçerli izinler olmalıdır", + "File shares cannot have create or delete permissions" : "Dosya paylaşımlarında oluşturma ya da silme izni olamaz", "Cannot increase permissions of %s" : "%s izinleri yükseltilemedi", "Shares need at least read permissions" : "Paylaşımların en azından okuma izinleri olmalıdır", "Files cannot be shared with delete permissions" : "Silme izni ile dosya paylaşılamaz", "Files cannot be shared with create permissions" : "Ekleme izni ile dosya paylaşılamaz", "Expiration date is in the past" : "Geçerlilik sonu tarihi geçmişte", - "Expiration date is enforced" : "Geçerlilik sonu tarihi dayatılıyor", + "Expiration date is enforced" : "Geçerlilik sonu tarihi zorunlu kılınmış", "_Cannot set expiration date more than %n day in the future_::_Cannot set expiration date more than %n days in the future_" : ["Paylaşımların geçerlilik süreleri, gelecekte %n günden fazla olamaz","Paylaşımların geçerlilik süreleri, gelecekte %n günden fazla olamaz"], "Sharing is only allowed with group members" : "Paylaşım yalnızca grup üyeleri ile yapılabilir", "Sharing %s failed, because this item is already shared with the account %s" : "%s paylaşılamadı. Bu öge zaten %s hesabı ile paylaşılmış", @@ -181,16 +201,16 @@ "Path is already shared with this group" : "Bu yol bu grup ile zaten paylaşılmış", "Link sharing is not allowed" : "Bağlantı paylaşımına izin verilmiyor", "Public upload is not allowed" : "Herkese açık yüklemeye izin verilmiyor", - "Path contains files shared with you" : "Yolda sizinle paylaşılmış dosyalar var", + "You cannot share a folder that contains other shares" : "Başka paylaşımların bulunduğu bir klasörü paylaşamazsınız", "Sharing is disabled" : "Paylaşım kullanımdan kaldırılmış", "Sharing is disabled for you" : "Paylaşım sizin için kullanımdan kaldırılmış", "Cannot share with the share owner" : "Paylaşımı sahibi ile paylaşamazsınız", "Share does not have a full ID" : "Paylaşımın tam kimliği yok", "Cannot change share type" : "Paylaşım türü değiştirilemez", "Can only update recipient on user shares" : "Yalnızca kullanıcı paylaşımlarındaki alıcıyı güncelleyebilir", - "Cannot enable sending the password by Talk with an empty password" : "Boş bir parola ile Sohbet uygulaması ile parola gönderme özelliği kullanıma alınamaz", - "Cannot enable sending the password by Talk without setting a new password" : "Yeni bir parola ayarlanmadan Sohbet uygulaması ile parola gönderme özelliği kullanıma alınamaz", - "Cannot disable sending the password by Talk without setting a new password" : "Yeni bir parola ayarlanmadan Sohbet uygulaması ile parola gönderme kullanımdan kaldırılamaz", + "Cannot enable sending the password by Talk with an empty password" : "Boş bir parola kullanarak Konuş uygulaması ile parola gönderme özelliği açılamaz", + "Cannot enable sending the password by Talk without setting a new password" : "Yeni bir parola ayarlanmadan Konuş uygulaması ile parola gönderme özelliği açılamaz", + "Cannot disable sending the password by Talk without setting a new password" : "Yeni bir parola ayarlanmadan Konuş uygulaması ile parola gönderme özelliği kapatılamaz", "Share provider does not support accepting" : "Paylaşım hizmeti sağlayıcısı kabul etmeyi desteklemiyor", "Cannot change target of link share" : "Bağlantı paylaşımının hedefi değiştirilemedi", "Invalid share recipient" : "Paylaşım alıcısı geçersiz", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "Geçerli bir kullanıcı adı yazmalısınız", "Login contains whitespace at the beginning or at the end" : "Kullanıcı adının başında ya da sonunda boşluk var", "Login must not consist of dots only" : "Kullanıcı adı yalnızca noktalardan oluşamaz", + "Username is too long" : "Kullanıcı adı çok uzun", "Login is invalid because files already exist for this user" : "Kullanıcı adı geçersiz, bu kullanıcı için zaten bazı dosyalar var", "Account disabled" : "Hesap kullanımdan kaldırılmış", "Login canceled by app" : "Oturum açma uygulama tarafından iptal edildi", @@ -309,8 +330,19 @@ "The audio to transcribe" : "Yazıya dönüştürülecek ses", "Transcription" : "Yazıya dönüştürme", "The transcribed text" : "Dönüştürülen yazı", + "Chat with an agent" : "Bir aracı ile sohbet edin", "Chat message" : "Sohbet iletisi", + "A chat message to send to the agent." : "Aracıya gönderilecek sohbet iletisi.", "Confirmation" : "Onaylama", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "Daha önce istenilen işlemlerin onaylanıp onaylanmayacağı: Reddedilmesi için 0, onaylanması için 1.", + "Conversation token" : "Görüşme kodu", + "A token representing the conversation." : "Görüşmenin kodu.", + "Generated response" : "Üretilen yanıt", + "The response from the chat model." : "Sohbet modelinin yanıtı.", + "The new conversation token" : "Yeni görüşme kodu", + "Send this along with the next interaction." : "Bunu sonraki etkileşimin yanında gönderin.", + "Requested actions by the agent" : "Aracı tarafından istenilen işlemler", + "Actions that the agent would like to carry out in JSON format." : "Aracının JSON biçiminde gerçekleştirmesi istenen işlemler.", "Context write" : "Bağlam yazma", "Writes text in a given style based on the provided source material." : "Sağlanan kaynak materyale göre belirli bir tarzda metin yazar.", "Writing style" : "Yazma tarzı", @@ -332,19 +364,39 @@ "How many images to generate" : "Oluşturulacak görsel sayısı", "Output images" : "Çıktı görselleri", "The generated images" : "Oluşturulan görseller", + "Generate speech" : "Konuşma oluştur", + "Generate speech from a transcript" : "Bir yazıya dönüştürmeden konuşma oluştur", + "Write transcript that you want the assistant to generate speech from" : "Yardımcının konuşma oluşturmasını istediğiniz yazı dönüştürmesini yazın", + "Output speech" : "Konuşma çıktısı", + "The generated speech" : "Oluşturulan konuşma", "Free text to text prompt" : "Ücretsiz yazıdan yazıya istemi", "Runs an arbitrary prompt through a language model that returns a reply" : "Dil modeli ile bir yanıt döndüren isteğe bağlı bir bilgi istemi çalıştırır", "Describe a task that you want the assistant to do or ask a question" : "Yardımcının yapmasını istediğiniz bir görevi tanımlayın ya da bir soru sorun", "Generated reply" : "Oluşturulan yanıt", "The generated text from the assistant" : "Yardımcının oluşturduğu metin", + "Change Tone" : "Tonu değiştir", + "Change the tone of a piece of text." : "Bir metin parçasının tonunu değiştirir.", + "Write a text that you want the assistant to rewrite in another tone." : "Yardımcının başka bir tonda yeniden yazmasını istediğiniz bir metin yazın", + "Desired tone" : "İstenilen ton", + "In which tone should your text be rewritten?" : "Metin hangi tonda yeniden yazılmalı?", + "The rewritten text in the desired tone, written by the assistant:" : "Yardımcı tarafından istenilen tonda yeniden yazılan metin:", "Chat" : "Sohbet", "Chat with the assistant" : "Yardımcı ile sohbet et", "System prompt" : "Sistem istemi", - "Define rules and assumptions that the assistant should follow during the conversation." : "Sohbet sırasında yardımcının uyması gereken kuralları ve varsayımları tanımlayın.", + "Define rules and assumptions that the assistant should follow during the conversation." : "Görüşme sırasında yardımcının uyması gereken kuralları ve varsayımları tanımlayın.", "Chat history" : "Sohbet geçmişi", "The history of chat messages before the current message, starting with a message by the user" : "Kullanıcının iletisiyle başlayarak, geçerli iletiden önceki sohbet iletilerinin geçmişi", "Response message" : "Yanıt iletisi", - "The generated response as part of the conversation" : "Sohbetin parçası olarak oluşturulan yanıt", + "The generated response as part of the conversation" : "Görüşmenin parçası olarak oluşturulan yanıt", + "Chat with tools" : "Araçlar ile sohbet", + "Chat with the language model with tool calling support." : "Araç çağırma desteği ile dil modeliyle sohbet edin.", + "Tool message" : "Araç iletisi", + "The result of tool calls in the last interaction" : "Son etkileşimdeki araç çağrılarının sonucu", + "Available tools" : "Kullanılabilecek araçlar", + "The available tools in JSON format" : "JSON biçiminde kullanılabilecek araçlar", + "The response from the chat model" : "Sohbet modelinin yanıtı", + "Tool calls" : "Araç çağrıları", + "Tools call instructions from the model in JSON format" : "Araçlar, modelden JSON biçiminde komutları çağırır", "Formalize text" : "Metni resmileştir", "Takes a text and makes it sound more formal" : "Bir metni alarak daha resmi dile dönüştürür", "Write a text that you want the assistant to formalize" : "Yardımcının resmileştirmesini istediğiniz bir metin yazın", @@ -355,6 +407,12 @@ "Original text" : "Özgün metin", "The original text to generate a headline for" : "Başlık oluşturulacak metin", "The generated headline" : "Oluşturulan başlık", + "Proofread" : "Düzelt", + "Proofreads a text and lists corrections" : "Bir metni düzeltir ve düzeltmeleri listeler", + "Text" : "Metin", + "The text to proofread" : "Düzeltilecek metin", + "Corrections" : "Düzeltmeler", + "The corrections that should be made in your text" : "Metninizde yapılması gereken düzeltmeler", "Reformulate text" : "Metni yeniden düzenle", "Takes a text and reformulates it" : "Bir metni alarak yeniden düzenler", "Write a text that you want the assistant to reformulate" : "Yardımcının yeniden düzenlemesini istediğiniz bir metin yazın", @@ -390,41 +448,9 @@ "Generate headline" : "Başlık oluşturulsun", "Summarizes text by reducing its length without losing key information." : "Temel içeriği kaybetmeden uzunluğunu kısaltarak metni özetler.", "Extracts topics from a text and outputs them separated by commas." : "Bir metindeki konuları ayıklar ve bunları virgül ile ayırarak sıralar.", - "Education Edition" : "Eğitim sürümü", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Oturum açmış kullanıcı bir yönetici, bir alt yönetici veya bu ayara erişmek için özel izne sahip olmalıdır", - "Logged in user must be an admin or sub admin" : "Oturum açmış kullanıcı bir yönetici ya da alt yönetici olmalıdır", - "Logged in user must be an admin" : "Oturum açmış kullanıcı bir yönetici olmalıdır", - "File name is a reserved word" : "Bu dosya adı sistem kullanıma ayrılmıştır", - "File name contains at least one invalid character" : "Dosya adında en az bir geçersiz karakter var", - "File name is too long" : "Dosya adı çok uzun", - "Help" : "Yardım", - "Users" : "Kullanıcılar", - "Unknown user" : "Kullanıcı bilinmiyor", - "Enter the database username and name for %s" : "%s için veri tabanı adını ve kullanıcı adını yazın", - "Enter the database username for %s" : "%s için veri tabanı kullanıcı adını yazın", - "MySQL username and/or password not valid" : "MySQL kullanıcı adı ya da parolası geçersiz", - "Oracle username and/or password not valid" : "Oracle kullanıcı adı ya da parolası geçersiz", - "PostgreSQL username and/or password not valid" : "PostgreSQL kullanıcı adı ya da parolası geçersiz", - "Set an admin username." : "Bir yönetici kullanıcı adı yazın.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s sizinle »%2$s« ögesini paylaştı ve eklemenizi istiyor:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s sizinle »%2$s« ögesini paylaştı ve eklemenizi istiyor", - "»%s« added a note to a file shared with you" : "»%s« sizinle paylaştığı bir dosyaya bir not ekledi", - "Open »%s«" : "»%s« aç", - "Sharing %s failed, because this item is already shared with user %s" : "%s paylaşılamadı. Bu öge zaten %s kullanıcısı ile paylaşılmış", - "%1$s shared »%2$s« with you" : "%1$s, sizinle »%2$s« ögesini paylaştı", - "%1$s shared »%2$s« with you." : "%1$s, sizinle »%2$s« ögesini paylaştı.", - "The username is already being used" : "Bu kullanıcı adı zaten var", - "Could not create user" : "Kullanıcı oluşturulamadı", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Kullanıcı adında yalnızca şu karakterler kullanılabilir: \"a-z\", \"A-Z\", \"0-9\", boşluk ve \"_.@-'\"", - "A valid username must be provided" : "Geçerli bir kullanıcı adı yazmalısınız", - "Username contains whitespace at the beginning or at the end" : "Kullanıcı adının başı ya da sonunda boşluk var", - "Username must not consist of dots only" : "Kullanıcı adı yalnızca noktalardan oluşamaz", - "Username is invalid because files already exist for this user" : "Kullanıcı adı geçersiz, bu kullanıcı için zaten bazı dosyalar var", - "User disabled" : "Kullanıcı kullanımdan kaldırılmış", + "Organisation" : "Kuruluş", "File is currently busy, please try again later" : "Dosya şu anda meşgul. Lütfen bir süre sonra yeniden deneyin", "Cannot download file" : "Dosya indirilemedi", - "Your data directory is readable by other users." : "Veri klasörünüz diğer kullanıcılar tarafından okunabilir.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Lütfen izinleri 0770 olarak ayarlayarak diğer kullanıcıların klasörü görebilmesini sağlayın.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Veri klasörü kökünde \".ocdata\" adında bir dosya bulunduğundan emin olun." + "Login is too long" : "Kullanıcı adı çok uzun" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/lib/l10n/ug.js b/lib/l10n/ug.js index bc98d033f8c..058004830e0 100644 --- a/lib/l10n/ug.js +++ b/lib/l10n/ug.js @@ -38,7 +38,6 @@ OC.L10N.register( "Server version %s or higher is required." : "مۇلازىمېتىرنىڭ% s ياكى ئۇنىڭدىن يۇقىرى نەشرى تەلەپ قىلىنىدۇ.", "Server version %s or lower is required." : "مۇلازىمېتىرنىڭ% s ياكى ئۇنىڭدىن تۆۋەن نەشرى تەلەپ قىلىنىدۇ.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "ھېساباتقا كىرگەن چوقۇم باشقۇرغۇچى ، تارماق باشقۇرغۇچى بولۇشى ياكى بۇ تەڭشەكنى زىيارەت قىلىش ھوقۇقى بولۇشى كېرەك", - "Your current IP address doesn’t allow you to perform admin actions" : "نۆۋەتتىكى IP ئادرېسىڭىز باشقۇرۇش ھەرىكىتىنى قىلىشىڭىزغا يول قويمايدۇ", "Logged in account must be an admin or sub admin" : "ھېساباتقا كىرگەن چوقۇم باشقۇرغۇچى ياكى تارماق باشقۇرغۇچى بولۇشى كېرەك", "Logged in account must be an admin" : "ھېساباتقا كىرگەن چوقۇم باشقۇرغۇچى بولۇشى كېرەك", "Wiping of device %s has started" : "ئۈسكۈنىنىڭ% s نى ئۆچۈرۈش باشلاندى", @@ -114,7 +113,6 @@ OC.L10N.register( "About" : "ھەققىدە", "Display name" : "كۆرسىتىش ئىسمى", "Headline" : "ماۋزۇ", - "Organisation" : "تەشكىلات", "Role" : "رولى", "Pronouns" : "Pronouns", "Unknown account" : "نامەلۇم ھېسابات", @@ -128,7 +126,6 @@ OC.L10N.register( "Oracle connection could not be established" : "Oracle ئۇلىنىشى قۇرۇلمىدى", "Oracle Login and/or password not valid" : "Oracle كىرىش ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", "PostgreSQL Login and/or password not valid" : "PostgreSQL كىرىش ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X نى قوللىمايدۇ ،% s بۇ سۇپىدا نورمال ئىشلىمەيدۇ. ئۇنى ئۆزىڭىزنىڭ خەتىرىگە ئاساسەن ئىشلىتىڭ! ", "For the best results, please consider using a GNU/Linux server instead." : "ئەڭ ياخشى ئۈنۈمگە ئېرىشىش ئۈچۈن ، ئۇنىڭ ئورنىغا GNU / Linux مۇلازىمېتىرىنى ئىشلىتىشنى ئويلىشىڭ.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "قارىغاندا بۇ% s مىسالى 32 بىتلىق PHP مۇھىتىدا ئىجرا بولۇۋاتقاندەك ، open_basedir php.ini دا تەڭشەلگەن. بۇ 4 GB دىن يۇقىرى ھۆججەتلەردە مەسىلە كۆرۈلىدۇ ۋە ئۈمىدسىزلىنىدۇ.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Php.ini دىكى open_basedir تەڭشىكىنى ئېلىۋېتىڭ ياكى 64 بىتلىق PHP غا ئالماشتۇرۇڭ.", @@ -139,7 +136,6 @@ OC.L10N.register( "Sharing backend %s not found" : "ئورتاقلىشىش% s تېپىلمىدى", "Sharing backend for %s not found" : "% S ئۈچۈن ئارقا زاپاسلاش تېپىلمىدى", "%1$s shared %2$s with you" : "% 1 $ s سىز بىلەن% 2 $ s ئورتاقلاشتى", - "Click the button below to open it." : "ئۇنى ئېچىش ئۈچۈن تۆۋەندىكى كۇنۇپكىنى بېسىڭ.", "Open %s" : "% S نى ئېچىڭ", "%1$s via %2$s" : "%1 $ s ئارقىلىق%2 $ s", "%1$s shared %2$s with you and wants to add:" : "% 1 $ s% 2 $ s نى سىز بىلەن ئورتاقلاشتى ۋە قوشماقچى:", @@ -172,7 +168,6 @@ OC.L10N.register( "Path is already shared with this group" : "يول ئاللىقاچان بۇ گۇرۇپپا بىلەن ئورتاقلاشتى", "Link sharing is not allowed" : "ئۇلىنىشنى ئورتاقلىشىشقا بولمايدۇ", "Public upload is not allowed" : "ئاممىۋى يوللاشقا بولمايدۇ", - "Path contains files shared with you" : "يول سىز بىلەن ئورتاقلاشقان ھۆججەتلەرنى ئۆز ئىچىگە ئالىدۇ", "Sharing is disabled" : "ئورتاقلىشىش چەكلەنگەن", "Sharing is disabled for you" : "ئورتاقلىشىش سىز ئۈچۈن چەكلەنگەن", "Cannot share with the share owner" : "پاي ئىگىسى بىلەن ئورتاقلىشالمايدۇ", @@ -346,6 +341,7 @@ OC.L10N.register( "Original text" : "ئەسلى تېكىست", "The original text to generate a headline for" : "ماۋزۇ ھاسىل قىلىدىغان ئەسلى تېكىست", "The generated headline" : "ھاسىل قىلىنغان ماۋزۇ", + "Text" : "تېكىست", "Reformulate text" : "تېكىستنى ئىسلاھ قىلىش", "Takes a text and reformulates it" : "بىر تېكىستنى ئېلىپ ئۇنى ئىسلاھ قىلىدۇ", "Write a text that you want the assistant to reformulate" : "ياردەمچى ئىسلاھ قىلماقچى بولغان تېكىستنى يېزىڭ", @@ -381,41 +377,8 @@ OC.L10N.register( "Generate headline" : "ماۋزۇ ھاسىل قىلىڭ", "Summarizes text by reducing its length without losing key information." : "ئاچقۇچلۇق ئۇچۇرلارنى يوقىتىپ قويماي ئۇزۇنلۇقىنى قىسقارتىش ئارقىلىق تېكىستنى خۇلاسىلەيدۇ.", "Extracts topics from a text and outputs them separated by commas." : "تېكىستتىن تېمىنى چىقىرىپ ، پەش ئارقىلىق ئايرىلىدۇ.", - "Education Edition" : "مائارىپ نەشرى", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "تىزىمغا كىرگەن ئىشلەتكۈچى چوقۇم باشقۇرغۇچى ، تارماق باشقۇرغۇچى بولۇشى ياكى بۇ تەڭشەكنى زىيارەت قىلىش ھوقۇقىغا ئېرىشىشى كېرەك", - "Logged in user must be an admin or sub admin" : "تىزىملاتقان ئىشلەتكۈچى چوقۇم باشقۇرغۇچى ياكى تارماق باشقۇرغۇچى بولۇشى كېرەك", - "Logged in user must be an admin" : "تىزىملاتقان ئىشلەتكۈچى چوقۇم باشقۇرغۇچى بولۇشى كېرەك", - "File name is a reserved word" : "ھۆججەت ئىسمى زاپاس سۆز", - "File name contains at least one invalid character" : "ھۆججەت ئىسمى كەم دېگەندە بىر ئىناۋەتسىز ھەرپنى ئۆز ئىچىگە ئالىدۇ", - "File name is too long" : "ھۆججەت ئىسمى بەك ئۇزۇن", - "Help" : "ياردەم", - "Users" : "ئىشلەتكۈچىلەر", - "Unknown user" : "نامەلۇم ئىشلەتكۈچى", - "Enter the database username and name for %s" : "سانداننىڭ ئىشلەتكۈچى ئىسمى ۋە% s نىڭ نامىنى كىرگۈزۈڭ", - "Enter the database username for %s" : "% S ئۈچۈن ساندان ئىشلەتكۈچى نامىنى كىرگۈزۈڭ", - "MySQL username and/or password not valid" : "MySQL ئىشلەتكۈچى ئىسمى ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", - "Oracle username and/or password not valid" : "Oracle ئىشلەتكۈچى ئىسمى ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", - "PostgreSQL username and/or password not valid" : "PostgreSQL ئىشلەتكۈچى ئىسمى ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", - "Set an admin username." : "باشقۇرغۇچى ئىشلەتكۈچى نامىنى بەلگىلەڭ.", - "%1$s shared »%2$s« with you and wants to add:" : "%1 $ s ئورتاقلاشتى »%2 $ s« سىز بىلەن قوشماقچى:", - "%1$s shared »%2$s« with you and wants to add" : "%1 $ s ئورتاقلاشتى »%2 $ s« سىز بىلەن قوشماقچى", - "»%s« added a note to a file shared with you" : "»% S« سىز بىلەن ئورتاقلاشقان ھۆججەتكە خاتىرە قوشتى", - "Open »%s«" : "ئېچىڭ »% s«", - "Sharing %s failed, because this item is already shared with user %s" : "% S نى ئورتاقلىشىش مەغلۇب بولدى ، چۈنكى بۇ تۈر ئاللىقاچان% s ئىشلەتكۈچى بىلەن ئورتاقلاشتى", - "%1$s shared »%2$s« with you" : "%1 $ s ئورتاقلاشتى »%2 $ s« سىز بىلەن", - "%1$s shared »%2$s« with you." : "%1 $ s ئورتاقلاشتى »%2 $ s« سىز بىلەن.", - "The username is already being used" : "ئىشلەتكۈچى ئىسمى ئاللىبۇرۇن ئىشلىتىلىۋاتىدۇ", - "Could not create user" : "ئىشلەتكۈچى قۇرالمىدى", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "ئىشلەتكۈچى نامىدا پەقەت تۆۋەندىكى ھەرپلەرلا رۇخسەت قىلىنىدۇ: \"a-z\", \"A-Z\", \"0-9\", بوشلۇق ۋە \"_. @ - '\"", - "A valid username must be provided" : "چوقۇم ئىناۋەتلىك ئىشلەتكۈچى ئىسمىدىن بىرنى تەمىنلەش كېرەك", - "Username contains whitespace at the beginning or at the end" : "ئىشلەتكۈچى نامىنىڭ بېشىدا ياكى ئاخىرىدا ئاق بوشلۇق بار", - "Username must not consist of dots only" : "ئىشلەتكۈچى ئىسمى پەقەت چېكىتتىن تەركىب تاپقان بولۇشى كېرەك", - "Username is invalid because files already exist for this user" : "ئىشلەتكۈچى ئىسمى ئىناۋەتسىز ، چۈنكى بۇ ئىشلەتكۈچى ئۈچۈن ھۆججەتلەر بار", - "User disabled" : "ئىشلەتكۈچى چەكلەنگەن", + "Organisation" : "تەشكىلات", "File is currently busy, please try again later" : "ھۆججەت ھازىر ئالدىراش ، كېيىن قايتا سىناڭ", - "Cannot download file" : "ھۆججەتنى چۈشۈرگىلى بولمايدۇ", - "Your data directory is readable by other users." : "سانلىق مەلۇمات مۇندەرىجىسىڭىزنى باشقا ئىشلەتكۈچىلەر ئوقۇيالايدۇ.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "ئىجازەتنى 0770 غا ئۆزگەرتىڭ ، بۇنداق بولغاندا مۇندەرىجىنى باشقا ئىشلەتكۈچىلەر تىزىپ قويمايدۇ.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "سانلىق مەلۇمات مۇندەرىجىسىنىڭ يىلتىزىدا \".ocdata\" دەپ ئاتىلىدىغان ھۆججەتنىڭ بارلىقىغا كاپالەتلىك قىلىڭ." + "Cannot download file" : "ھۆججەتنى چۈشۈرگىلى بولمايدۇ" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/ug.json b/lib/l10n/ug.json index 87f9e96009c..4099930b1cc 100644 --- a/lib/l10n/ug.json +++ b/lib/l10n/ug.json @@ -36,7 +36,6 @@ "Server version %s or higher is required." : "مۇلازىمېتىرنىڭ% s ياكى ئۇنىڭدىن يۇقىرى نەشرى تەلەپ قىلىنىدۇ.", "Server version %s or lower is required." : "مۇلازىمېتىرنىڭ% s ياكى ئۇنىڭدىن تۆۋەن نەشرى تەلەپ قىلىنىدۇ.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "ھېساباتقا كىرگەن چوقۇم باشقۇرغۇچى ، تارماق باشقۇرغۇچى بولۇشى ياكى بۇ تەڭشەكنى زىيارەت قىلىش ھوقۇقى بولۇشى كېرەك", - "Your current IP address doesn’t allow you to perform admin actions" : "نۆۋەتتىكى IP ئادرېسىڭىز باشقۇرۇش ھەرىكىتىنى قىلىشىڭىزغا يول قويمايدۇ", "Logged in account must be an admin or sub admin" : "ھېساباتقا كىرگەن چوقۇم باشقۇرغۇچى ياكى تارماق باشقۇرغۇچى بولۇشى كېرەك", "Logged in account must be an admin" : "ھېساباتقا كىرگەن چوقۇم باشقۇرغۇچى بولۇشى كېرەك", "Wiping of device %s has started" : "ئۈسكۈنىنىڭ% s نى ئۆچۈرۈش باشلاندى", @@ -112,7 +111,6 @@ "About" : "ھەققىدە", "Display name" : "كۆرسىتىش ئىسمى", "Headline" : "ماۋزۇ", - "Organisation" : "تەشكىلات", "Role" : "رولى", "Pronouns" : "Pronouns", "Unknown account" : "نامەلۇم ھېسابات", @@ -126,7 +124,6 @@ "Oracle connection could not be established" : "Oracle ئۇلىنىشى قۇرۇلمىدى", "Oracle Login and/or password not valid" : "Oracle كىرىش ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", "PostgreSQL Login and/or password not valid" : "PostgreSQL كىرىش ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X نى قوللىمايدۇ ،% s بۇ سۇپىدا نورمال ئىشلىمەيدۇ. ئۇنى ئۆزىڭىزنىڭ خەتىرىگە ئاساسەن ئىشلىتىڭ! ", "For the best results, please consider using a GNU/Linux server instead." : "ئەڭ ياخشى ئۈنۈمگە ئېرىشىش ئۈچۈن ، ئۇنىڭ ئورنىغا GNU / Linux مۇلازىمېتىرىنى ئىشلىتىشنى ئويلىشىڭ.", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "قارىغاندا بۇ% s مىسالى 32 بىتلىق PHP مۇھىتىدا ئىجرا بولۇۋاتقاندەك ، open_basedir php.ini دا تەڭشەلگەن. بۇ 4 GB دىن يۇقىرى ھۆججەتلەردە مەسىلە كۆرۈلىدۇ ۋە ئۈمىدسىزلىنىدۇ.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Php.ini دىكى open_basedir تەڭشىكىنى ئېلىۋېتىڭ ياكى 64 بىتلىق PHP غا ئالماشتۇرۇڭ.", @@ -137,7 +134,6 @@ "Sharing backend %s not found" : "ئورتاقلىشىش% s تېپىلمىدى", "Sharing backend for %s not found" : "% S ئۈچۈن ئارقا زاپاسلاش تېپىلمىدى", "%1$s shared %2$s with you" : "% 1 $ s سىز بىلەن% 2 $ s ئورتاقلاشتى", - "Click the button below to open it." : "ئۇنى ئېچىش ئۈچۈن تۆۋەندىكى كۇنۇپكىنى بېسىڭ.", "Open %s" : "% S نى ئېچىڭ", "%1$s via %2$s" : "%1 $ s ئارقىلىق%2 $ s", "%1$s shared %2$s with you and wants to add:" : "% 1 $ s% 2 $ s نى سىز بىلەن ئورتاقلاشتى ۋە قوشماقچى:", @@ -170,7 +166,6 @@ "Path is already shared with this group" : "يول ئاللىقاچان بۇ گۇرۇپپا بىلەن ئورتاقلاشتى", "Link sharing is not allowed" : "ئۇلىنىشنى ئورتاقلىشىشقا بولمايدۇ", "Public upload is not allowed" : "ئاممىۋى يوللاشقا بولمايدۇ", - "Path contains files shared with you" : "يول سىز بىلەن ئورتاقلاشقان ھۆججەتلەرنى ئۆز ئىچىگە ئالىدۇ", "Sharing is disabled" : "ئورتاقلىشىش چەكلەنگەن", "Sharing is disabled for you" : "ئورتاقلىشىش سىز ئۈچۈن چەكلەنگەن", "Cannot share with the share owner" : "پاي ئىگىسى بىلەن ئورتاقلىشالمايدۇ", @@ -344,6 +339,7 @@ "Original text" : "ئەسلى تېكىست", "The original text to generate a headline for" : "ماۋزۇ ھاسىل قىلىدىغان ئەسلى تېكىست", "The generated headline" : "ھاسىل قىلىنغان ماۋزۇ", + "Text" : "تېكىست", "Reformulate text" : "تېكىستنى ئىسلاھ قىلىش", "Takes a text and reformulates it" : "بىر تېكىستنى ئېلىپ ئۇنى ئىسلاھ قىلىدۇ", "Write a text that you want the assistant to reformulate" : "ياردەمچى ئىسلاھ قىلماقچى بولغان تېكىستنى يېزىڭ", @@ -379,41 +375,8 @@ "Generate headline" : "ماۋزۇ ھاسىل قىلىڭ", "Summarizes text by reducing its length without losing key information." : "ئاچقۇچلۇق ئۇچۇرلارنى يوقىتىپ قويماي ئۇزۇنلۇقىنى قىسقارتىش ئارقىلىق تېكىستنى خۇلاسىلەيدۇ.", "Extracts topics from a text and outputs them separated by commas." : "تېكىستتىن تېمىنى چىقىرىپ ، پەش ئارقىلىق ئايرىلىدۇ.", - "Education Edition" : "مائارىپ نەشرى", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "تىزىمغا كىرگەن ئىشلەتكۈچى چوقۇم باشقۇرغۇچى ، تارماق باشقۇرغۇچى بولۇشى ياكى بۇ تەڭشەكنى زىيارەت قىلىش ھوقۇقىغا ئېرىشىشى كېرەك", - "Logged in user must be an admin or sub admin" : "تىزىملاتقان ئىشلەتكۈچى چوقۇم باشقۇرغۇچى ياكى تارماق باشقۇرغۇچى بولۇشى كېرەك", - "Logged in user must be an admin" : "تىزىملاتقان ئىشلەتكۈچى چوقۇم باشقۇرغۇچى بولۇشى كېرەك", - "File name is a reserved word" : "ھۆججەت ئىسمى زاپاس سۆز", - "File name contains at least one invalid character" : "ھۆججەت ئىسمى كەم دېگەندە بىر ئىناۋەتسىز ھەرپنى ئۆز ئىچىگە ئالىدۇ", - "File name is too long" : "ھۆججەت ئىسمى بەك ئۇزۇن", - "Help" : "ياردەم", - "Users" : "ئىشلەتكۈچىلەر", - "Unknown user" : "نامەلۇم ئىشلەتكۈچى", - "Enter the database username and name for %s" : "سانداننىڭ ئىشلەتكۈچى ئىسمى ۋە% s نىڭ نامىنى كىرگۈزۈڭ", - "Enter the database username for %s" : "% S ئۈچۈن ساندان ئىشلەتكۈچى نامىنى كىرگۈزۈڭ", - "MySQL username and/or password not valid" : "MySQL ئىشلەتكۈچى ئىسمى ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", - "Oracle username and/or password not valid" : "Oracle ئىشلەتكۈچى ئىسمى ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", - "PostgreSQL username and/or password not valid" : "PostgreSQL ئىشلەتكۈچى ئىسمى ۋە / ياكى پارول ئىناۋەتلىك ئەمەس", - "Set an admin username." : "باشقۇرغۇچى ئىشلەتكۈچى نامىنى بەلگىلەڭ.", - "%1$s shared »%2$s« with you and wants to add:" : "%1 $ s ئورتاقلاشتى »%2 $ s« سىز بىلەن قوشماقچى:", - "%1$s shared »%2$s« with you and wants to add" : "%1 $ s ئورتاقلاشتى »%2 $ s« سىز بىلەن قوشماقچى", - "»%s« added a note to a file shared with you" : "»% S« سىز بىلەن ئورتاقلاشقان ھۆججەتكە خاتىرە قوشتى", - "Open »%s«" : "ئېچىڭ »% s«", - "Sharing %s failed, because this item is already shared with user %s" : "% S نى ئورتاقلىشىش مەغلۇب بولدى ، چۈنكى بۇ تۈر ئاللىقاچان% s ئىشلەتكۈچى بىلەن ئورتاقلاشتى", - "%1$s shared »%2$s« with you" : "%1 $ s ئورتاقلاشتى »%2 $ s« سىز بىلەن", - "%1$s shared »%2$s« with you." : "%1 $ s ئورتاقلاشتى »%2 $ s« سىز بىلەن.", - "The username is already being used" : "ئىشلەتكۈچى ئىسمى ئاللىبۇرۇن ئىشلىتىلىۋاتىدۇ", - "Could not create user" : "ئىشلەتكۈچى قۇرالمىدى", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "ئىشلەتكۈچى نامىدا پەقەت تۆۋەندىكى ھەرپلەرلا رۇخسەت قىلىنىدۇ: \"a-z\", \"A-Z\", \"0-9\", بوشلۇق ۋە \"_. @ - '\"", - "A valid username must be provided" : "چوقۇم ئىناۋەتلىك ئىشلەتكۈچى ئىسمىدىن بىرنى تەمىنلەش كېرەك", - "Username contains whitespace at the beginning or at the end" : "ئىشلەتكۈچى نامىنىڭ بېشىدا ياكى ئاخىرىدا ئاق بوشلۇق بار", - "Username must not consist of dots only" : "ئىشلەتكۈچى ئىسمى پەقەت چېكىتتىن تەركىب تاپقان بولۇشى كېرەك", - "Username is invalid because files already exist for this user" : "ئىشلەتكۈچى ئىسمى ئىناۋەتسىز ، چۈنكى بۇ ئىشلەتكۈچى ئۈچۈن ھۆججەتلەر بار", - "User disabled" : "ئىشلەتكۈچى چەكلەنگەن", + "Organisation" : "تەشكىلات", "File is currently busy, please try again later" : "ھۆججەت ھازىر ئالدىراش ، كېيىن قايتا سىناڭ", - "Cannot download file" : "ھۆججەتنى چۈشۈرگىلى بولمايدۇ", - "Your data directory is readable by other users." : "سانلىق مەلۇمات مۇندەرىجىسىڭىزنى باشقا ئىشلەتكۈچىلەر ئوقۇيالايدۇ.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "ئىجازەتنى 0770 غا ئۆزگەرتىڭ ، بۇنداق بولغاندا مۇندەرىجىنى باشقا ئىشلەتكۈچىلەر تىزىپ قويمايدۇ.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "سانلىق مەلۇمات مۇندەرىجىسىنىڭ يىلتىزىدا \".ocdata\" دەپ ئاتىلىدىغان ھۆججەتنىڭ بارلىقىغا كاپالەتلىك قىلىڭ." + "Cannot download file" : "ھۆججەتنى چۈشۈرگىلى بولمايدۇ" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/uk.js b/lib/l10n/uk.js index 5c19ee196b4..52437ee7f32 100644 --- a/lib/l10n/uk.js +++ b/lib/l10n/uk.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "Потрібна версія сервера %s або вище.", "Server version %s or lower is required." : "Потрібна версія сервера %s або нижча.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Обліковий запис для входу має бути адміністратором, заступником адміністратора або мати спеціальні права доступу до цих налаштувань.", - "Your current IP address doesn’t allow you to perform admin actions" : "Ваша поточна адреса IP не дозволяє виконувати адміністративні дії", + "Your current IP address doesn't allow you to perform admin actions" : "Ваша поточна адреса IP не дозволяє вам виконувати адміністративні дії", "Logged in account must be an admin or sub admin" : "Обліковий запис для входу має бути адміністратором, заступником адміністратора", "Logged in account must be an admin" : "Обліковий запис для входу має бути адміністратором", "Wiping of device %s has started" : "Розпочато очищення пристрою %s", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "Зображення аватара не квадратне", "Files" : "Файли", "View profile" : "Перегляд профілю", + "same time" : "той саме час", + "_%nh_::_%nh_" : ["%n год","%n год","%n год","%n год"], + "_%nm_::_%nm_" : ["%n хв","%n хв","%n хв","%n хв"], + "%s ahead" : "%s попереду", + "%s behind" : "%s позаду", "Local time: %s" : "Місцевий час: %s", "today" : "сьогодні", "tomorrow" : "завтра", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "кілька секунд тому", "Empty file" : "Порожній файл", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Модуль з ID: %s не існує. Будь ласка, увімкніть це в налаштуваннях застосунку або зверніться до адміністратора.", + "No file conversion providers available" : "Відсутні постачальники послуг з конвертування", + "File is too large to convert" : "Файл завеликий для конвертування", + "Destination does not match conversion extension" : "Призначення не відповідає розширенню конвертування", + "Could not convert file" : "Неможливо сконвертувати файл", + "Destination does not exist" : "Призначення відсутнє", + "Destination is not creatable" : "Неможливо створити призначення", "Dot files are not allowed" : "Файли які починаються з крапки не допустимі", + "%1$s (renamed)" : "%1$s (перейменовано)", + "renamed file" : "перейменовано файл", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" є недозволеним ім'ям файлів або каталогів.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" є недозволеним префіксом у іменах файлів або каталоів.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" не дозволено всередині імени файлів або каталогів.", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "Недійсний шлях", "Failed to create file from template" : "Не вдалося створити файл із шаблону", "Templates" : "Шаблони", + "Storage %s cannot be moved" : "Неможливо перемістити сховище даних %s", + "Moving a share (%s) into a shared folder is not allowed" : "Переміщення спільного ресурсу (%s) до спільного каталогу не дозволено", + "Moving a storage (%s) into a shared folder is not allowed" : "Переміщення сховища (%s) до спільного каталогу не дозволено", + "Moving a share (%s) into another share (%s) is not allowed" : "Переміщення спільного ресурсу (%s) до іншого спільного ресурсу (%s) не дозволено", + "Moving a share (%s) into another storage (%s) is not allowed" : "Переміщення спільного ресурсу (%s) до іншого сховища (%s) не дозволено", + "Moving a storage (%s) into a share (%s) is not allowed" : "Переміщення сховища (%s) до спільного ресурсу (%s) не дозволено", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Переміщення сховища (%s) до іншого сховища (%s) не дозволено", "Path contains invalid segments" : "Шлях містить недійсні елементи в назві", "Filename is a reserved word" : "Ім'я файлу є зарезервованим словом", "Filename contains at least one invalid character" : "У назві файлу міститься щонайменше один неправильний символ", @@ -120,11 +140,11 @@ OC.L10N.register( "Website" : "Вебсайт", "Visit %s" : "Відвідайте %s", "Address" : "Адреса", - "Profile picture" : "Зображення облікового запису", + "Profile picture" : "Зображення користувача", "About" : "Опис", "Display name" : "Ім'я для показу", "Headline" : "Заголовок", - "Organisation" : "Організація", + "Organization" : "Організація роботи", "Role" : "Роль", "Pronouns" : "Займенники", "Unknown account" : "Невідомий обліковий запис", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "Не можемо з'єднатися з Oracle ", "Oracle Login and/or password not valid" : "Ім'я користувача та/або пароль Oracle не дійсні", "PostgreSQL Login and/or password not valid" : "Ім'я користувача та/або пароль PostgreSQL не дійсні", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не підтримується і %s не буде коректно працювати на цій платформі. Випробовуєте на свій риск!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X не підтримується, отже %s не працюватиме належним чиним на цій платформі. Використовуйте на ваш страх і ризик.", "For the best results, please consider using a GNU/Linux server instead." : "Для кращих результатів розгляньте можливість використання GNU/Linux серверу", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Ймовірно, що сервер %s працює в 32-бітному PHP середовищі і open_basedir повинен бути налаштований в php.ini. Це призведе до проблем з файлами більше 4 ГБ і це дуже не рекомендується.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Будь ласка, вилучіть параметр open_basedir у вашому php.ini або перейдіть на 64-бітний PHP.", @@ -148,8 +168,12 @@ OC.L10N.register( "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Бекенд спільного доступу %s повинен реалізовувати інтерфейс OCP\\Share_Backend", "Sharing backend %s not found" : "Бекенд спільного доступу %s не знайдено", "Sharing backend for %s not found" : "Бекенд спільного доступу для %s не знайдено", - "Click the button below to open it." : "Щоб відкрити файл, натисніть кнопку нижче.", + "%1$s shared %2$s with you" : "%1$s поділив(ла)ся %2$s з вами", + "Open %s" : "Відкрити %s", "%1$s via %2$s" : "%1$s через %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s поділив(ла)ся %2$s з вами та бажає додати:", + "%1$s shared %2$s with you and wants to add" : "%1$s поділив(ла)ся %2$s з вами та бажає додати", + "%s added a note to a file shared with you" : "%s додав(-ла) примітку до файлу, яким поділилися з вами", "Passwords are enforced for link and mail shares" : "Для надання доступу до спільних ресурсів через посилання та ел. пошту має бути встановлено пароль на ресурс", "Share recipient is not a valid user" : "Такий отримувач спільного ресурсу відсутній", "Share recipient is not a valid group" : "Така група спільного ресурсу відсутня", @@ -164,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "Ви не можете надавати у спільний доступ кореневий каталог", "You are not allowed to share %s" : "Вам заборонено поширювати %s", "Valid permissions are required for sharing" : "Потрібний чинний дозвіл для надання у спільний доступ", + "File shares cannot have create or delete permissions" : "Відсутні дозволи сторення або вилучення для спільних файлів", "Cannot increase permissions of %s" : "Не вдалося підвищити дозволи для %s", "Shares need at least read permissions" : "Для спільних ресурсів має визначено щонайменше дозвіл на читання", "Files cannot be shared with delete permissions" : "Не можна надавати у спільний доступ файли з дозволами на вилучення", @@ -178,13 +203,16 @@ OC.L10N.register( "Path is already shared with this group" : "Шлях вже надано у спільний доступ для цієї групи", "Link sharing is not allowed" : "Спільний доступ через посилання не дозволено", "Public upload is not allowed" : "Публічні завантаження не дозволено", - "Path contains files shared with you" : "Шлях містить файли, якими поділилися з вами", + "You cannot share a folder that contains other shares" : "Неможливо надати у спільний доступ каталог, який вже містить інші спільні ресурси", "Sharing is disabled" : "Спільний доступ вимкнено", "Sharing is disabled for you" : "Ви не маєте права надавати у доступ файли або каталоги", "Cannot share with the share owner" : "Неможливо надавати у доступ власникові спільного ресурсу", "Share does not have a full ID" : "Спільний ресурс не має повного ідентифікатора", "Cannot change share type" : "Неможливо змінити тип спільного ресурсу", "Can only update recipient on user shares" : "Можна лише оновити отримувача для спільних ресурсів користувача", + "Cannot enable sending the password by Talk with an empty password" : "Не вдалося увімкнути надсилання паролю за допомогою Talk з порожнім паролем", + "Cannot enable sending the password by Talk without setting a new password" : "Не вдалося увімкнути надсилання паролю за допомогою Talk без встановлення нового паролю", + "Cannot disable sending the password by Talk without setting a new password" : "Не вдалося вимкнути надсилання паролю за допомогою Talk без встановлення нового паролю", "Share provider does not support accepting" : "Провайдер спільного доступу не підтримує прийняття", "Cannot change target of link share" : "Неможливо змінити призначення для спільного ресурсу через посилання", "Invalid share recipient" : "Недійсний отримувач спільного ресурсу", @@ -247,11 +275,12 @@ OC.L10N.register( "A valid Login must be provided" : "Зазначте дійсне ім'я користувача", "Login contains whitespace at the beginning or at the end" : "Ім'я користувача містить символ пробілу на початку або наприкінці", "Login must not consist of dots only" : "Ім'я користувача не може складатися лише з крапок", + "Username is too long" : "Ім'я користувача задовге", "Login is invalid because files already exist for this user" : "Недійсне ім'я облікового запису, оскільки файли для цього користувача вже присутні", "Account disabled" : "Обліковий запис вимкнено", "Login canceled by app" : "Вхід скасовано застосунком", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Застосунок \"%1$s\" неможливо встановити, оскільки не виконано такі залежності: %2$s", - "a safe home for all your data" : "безпечний дім для ваших даних", + "a safe home for all your data" : "безпечна домівка для ваших даних", "Application is not enabled" : "Застосунок не увімкнено", "Authentication error" : "Помилка авторизації", "Token expired. Please reload page." : "Строк дії токена скінчився. Будь ласка, перезавантажте сторінку.", @@ -297,9 +326,25 @@ OC.L10N.register( "Storage is temporarily not available" : "Сховище тимчасово недоступне", "Storage connection timeout. %s" : "Час під'єднання до сховища вичерпався. %s", "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Щоби дозволити запуск цієї перевірки, потрібно пересвідчитися, що ваш вебсервер може з'єднуватися з самим собою, що передбачає можливість резолвити та з'єднуватися з одним з `trusted_domains` або `overwrite.cli.url`. Неможливість цього може бути результатом незбігу DNS на стороні сервера або встановленими правилами брандмауера.", + "Transcribe audio" : "Транскрибувати аудіо", + "Transcribe the things said in an audio" : "Транскрибувати голос", + "Audio input" : "Аудіовхід", + "The audio to transcribe" : "Аудіо для транскрибування", + "The transcribed text" : "Транскрибований текст", "Confirmation" : "Підтвердження", + "Writing style" : "Стиль письма", + "Generated text" : "Зґенерований текст", + "Emoji generator" : "Ґенератор емоційок", + "Generated emoji" : "Зґенеровані емоційки", + "Generate image" : "Зґенерувати зображення", + "Prompt" : "Запрошення", "Chat" : "Чат", + "System prompt" : "Системний запит", + "Chat history" : "Історія чату", + "Response message" : "Відповідь", + "Available tools" : "Доступні інструменти", "Generates a possible headline for a text." : "Створює ймовірний заголовок тексту.", + "Text" : "Текст", "Summarize" : "Підсумок", "Summary" : "Загалом", "Extract topics" : "Виділити теми", @@ -311,41 +356,9 @@ OC.L10N.register( "Generate headline" : "Створити заголовок", "Summarizes text by reducing its length without losing key information." : "Викокремлює головне у тексті шляхом зменшення довжини тексту без втрати ключової інформації.", "Extracts topics from a text and outputs them separated by commas." : "Виділяє теми, які висвітлює текст, зводить їх у перелік, що розділено комами.", - "Education Edition" : "Для навчання", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Користувач, який увійшов у систему, має бути адміністратором, підадміністратором або мати спеціальні права доступу до цього налаштування", - "Logged in user must be an admin or sub admin" : "Увійшовши в систему користувач повинен бути адміністратором або підадміністратором", - "Logged in user must be an admin" : "Зареєстрований користувач має бути адміністратором", - "File name is a reserved word" : "Ім’я файлу є зарезервованим словом", - "File name contains at least one invalid character" : "Ім’я файлу містить принаймні один некоректний символ", - "File name is too long" : "Ім’я файлу занадто довге", - "Help" : "Допомога", - "Users" : "Користувачі", - "Unknown user" : "Невідомий користувач", - "Enter the database username and name for %s" : "Введіть ім’я користувача та назву бази даних %s", - "Enter the database username for %s" : "Введіть ім’я користувача бази даних для %s", - "MySQL username and/or password not valid" : "Ім'я користувача та/або пароль MySQL недійсні", - "Oracle username and/or password not valid" : "Oracle ім'я користувача та/або пароль не дійсні", - "PostgreSQL username and/or password not valid" : "PostgreSQL ім'я користувача та/або пароль не дійсні", - "Set an admin username." : "Встановіть ім'я адміністратора.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s надав(-ла) доступ до \"%2$s\" та хоче додати:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s надав(-ла) доступ до \"%2$s\" та хоче додати", - "»%s« added a note to a file shared with you" : "\"%s\" додано примітку до файлу у спільному доступі", - "Open »%s«" : "Відкрити %s", - "Sharing %s failed, because this item is already shared with user %s" : "Не вдалося поділитися %s, оскільки %s вже має до нього доступ", - "%1$s shared »%2$s« with you" : "%1$s надав(-ла) доступ до \"%2$s\"", - "%1$s shared »%2$s« with you." : "%1$s надав(-ла) доступ до \"%2$s\".", - "The username is already being used" : "Ім'я користувача вже використовується", - "Could not create user" : "Не вдалося створити користувача", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Лише такі символи дозволено у імені користувача: \"a-z\", \"A-Z\", \"0-9\", пробіл та \"_.@-'\"", - "A valid username must be provided" : "Потрібно зазначити дійсне ім'я користувача", - "Username contains whitespace at the beginning or at the end" : "Ім'я користувача містить символ пробілу в початку або в кінці", - "Username must not consist of dots only" : "Ім'я користувача не повинно складатися лише з крапок", - "Username is invalid because files already exist for this user" : "Ім'я користувача недійсне, оскільки файли для цього користувача вже існують", - "User disabled" : "Користувач виключений", + "Organisation" : "Організація", "File is currently busy, please try again later" : "Файл на разі зайнятий, будь ласка, спробуйте пізніше", "Cannot download file" : "Неможливо звантажити файл", - "Your data directory is readable by other users." : "Ваш каталог даних доступний для читання іншим користувачам.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Змініть права доступу на 0770, щоб інші користувачі не могли отримати список файлів цього каталогу.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Переконайтеся, що в корені каталогу даних є файл під назвою \".ocdata\"." + "Login is too long" : "Ім'я користувача для авторизації задовге" }, "nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);"); diff --git a/lib/l10n/uk.json b/lib/l10n/uk.json index 2932227c829..e90f18c26ae 100644 --- a/lib/l10n/uk.json +++ b/lib/l10n/uk.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "Потрібна версія сервера %s або вище.", "Server version %s or lower is required." : "Потрібна версія сервера %s або нижча.", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "Обліковий запис для входу має бути адміністратором, заступником адміністратора або мати спеціальні права доступу до цих налаштувань.", - "Your current IP address doesn’t allow you to perform admin actions" : "Ваша поточна адреса IP не дозволяє виконувати адміністративні дії", + "Your current IP address doesn't allow you to perform admin actions" : "Ваша поточна адреса IP не дозволяє вам виконувати адміністративні дії", "Logged in account must be an admin or sub admin" : "Обліковий запис для входу має бути адміністратором, заступником адміністратора", "Logged in account must be an admin" : "Обліковий запис для входу має бути адміністратором", "Wiping of device %s has started" : "Розпочато очищення пристрою %s", @@ -57,6 +57,11 @@ "Avatar image is not square" : "Зображення аватара не квадратне", "Files" : "Файли", "View profile" : "Перегляд профілю", + "same time" : "той саме час", + "_%nh_::_%nh_" : ["%n год","%n год","%n год","%n год"], + "_%nm_::_%nm_" : ["%n хв","%n хв","%n хв","%n хв"], + "%s ahead" : "%s попереду", + "%s behind" : "%s позаду", "Local time: %s" : "Місцевий час: %s", "today" : "сьогодні", "tomorrow" : "завтра", @@ -79,7 +84,15 @@ "seconds ago" : "кілька секунд тому", "Empty file" : "Порожній файл", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "Модуль з ID: %s не існує. Будь ласка, увімкніть це в налаштуваннях застосунку або зверніться до адміністратора.", + "No file conversion providers available" : "Відсутні постачальники послуг з конвертування", + "File is too large to convert" : "Файл завеликий для конвертування", + "Destination does not match conversion extension" : "Призначення не відповідає розширенню конвертування", + "Could not convert file" : "Неможливо сконвертувати файл", + "Destination does not exist" : "Призначення відсутнє", + "Destination is not creatable" : "Неможливо створити призначення", "Dot files are not allowed" : "Файли які починаються з крапки не допустимі", + "%1$s (renamed)" : "%1$s (перейменовано)", + "renamed file" : "перейменовано файл", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" є недозволеним ім'ям файлів або каталогів.", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" є недозволеним префіксом у іменах файлів або каталоів.", "\"%1$s\" is not allowed inside a file or folder name." : "\"%1$s\" не дозволено всередині імени файлів або каталогів.", @@ -90,6 +103,13 @@ "Invalid path" : "Недійсний шлях", "Failed to create file from template" : "Не вдалося створити файл із шаблону", "Templates" : "Шаблони", + "Storage %s cannot be moved" : "Неможливо перемістити сховище даних %s", + "Moving a share (%s) into a shared folder is not allowed" : "Переміщення спільного ресурсу (%s) до спільного каталогу не дозволено", + "Moving a storage (%s) into a shared folder is not allowed" : "Переміщення сховища (%s) до спільного каталогу не дозволено", + "Moving a share (%s) into another share (%s) is not allowed" : "Переміщення спільного ресурсу (%s) до іншого спільного ресурсу (%s) не дозволено", + "Moving a share (%s) into another storage (%s) is not allowed" : "Переміщення спільного ресурсу (%s) до іншого сховища (%s) не дозволено", + "Moving a storage (%s) into a share (%s) is not allowed" : "Переміщення сховища (%s) до спільного ресурсу (%s) не дозволено", + "Moving a storage (%s) into another storage (%s) is not allowed" : "Переміщення сховища (%s) до іншого сховища (%s) не дозволено", "Path contains invalid segments" : "Шлях містить недійсні елементи в назві", "Filename is a reserved word" : "Ім'я файлу є зарезервованим словом", "Filename contains at least one invalid character" : "У назві файлу міститься щонайменше один неправильний символ", @@ -118,11 +138,11 @@ "Website" : "Вебсайт", "Visit %s" : "Відвідайте %s", "Address" : "Адреса", - "Profile picture" : "Зображення облікового запису", + "Profile picture" : "Зображення користувача", "About" : "Опис", "Display name" : "Ім'я для показу", "Headline" : "Заголовок", - "Organisation" : "Організація", + "Organization" : "Організація роботи", "Role" : "Роль", "Pronouns" : "Займенники", "Unknown account" : "Невідомий обліковий запис", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "Не можемо з'єднатися з Oracle ", "Oracle Login and/or password not valid" : "Ім'я користувача та/або пароль Oracle не дійсні", "PostgreSQL Login and/or password not valid" : "Ім'я користувача та/або пароль PostgreSQL не дійсні", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X не підтримується і %s не буде коректно працювати на цій платформі. Випробовуєте на свій риск!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "Mac OS X не підтримується, отже %s не працюватиме належним чиним на цій платформі. Використовуйте на ваш страх і ризик.", "For the best results, please consider using a GNU/Linux server instead." : "Для кращих результатів розгляньте можливість використання GNU/Linux серверу", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "Ймовірно, що сервер %s працює в 32-бітному PHP середовищі і open_basedir повинен бути налаштований в php.ini. Це призведе до проблем з файлами більше 4 ГБ і це дуже не рекомендується.", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Будь ласка, вилучіть параметр open_basedir у вашому php.ini або перейдіть на 64-бітний PHP.", @@ -146,8 +166,12 @@ "Sharing backend %s must implement the interface OCP\\Share_Backend" : "Бекенд спільного доступу %s повинен реалізовувати інтерфейс OCP\\Share_Backend", "Sharing backend %s not found" : "Бекенд спільного доступу %s не знайдено", "Sharing backend for %s not found" : "Бекенд спільного доступу для %s не знайдено", - "Click the button below to open it." : "Щоб відкрити файл, натисніть кнопку нижче.", + "%1$s shared %2$s with you" : "%1$s поділив(ла)ся %2$s з вами", + "Open %s" : "Відкрити %s", "%1$s via %2$s" : "%1$s через %2$s", + "%1$s shared %2$s with you and wants to add:" : "%1$s поділив(ла)ся %2$s з вами та бажає додати:", + "%1$s shared %2$s with you and wants to add" : "%1$s поділив(ла)ся %2$s з вами та бажає додати", + "%s added a note to a file shared with you" : "%s додав(-ла) примітку до файлу, яким поділилися з вами", "Passwords are enforced for link and mail shares" : "Для надання доступу до спільних ресурсів через посилання та ел. пошту має бути встановлено пароль на ресурс", "Share recipient is not a valid user" : "Такий отримувач спільного ресурсу відсутній", "Share recipient is not a valid group" : "Така група спільного ресурсу відсутня", @@ -162,6 +186,7 @@ "You cannot share your root folder" : "Ви не можете надавати у спільний доступ кореневий каталог", "You are not allowed to share %s" : "Вам заборонено поширювати %s", "Valid permissions are required for sharing" : "Потрібний чинний дозвіл для надання у спільний доступ", + "File shares cannot have create or delete permissions" : "Відсутні дозволи сторення або вилучення для спільних файлів", "Cannot increase permissions of %s" : "Не вдалося підвищити дозволи для %s", "Shares need at least read permissions" : "Для спільних ресурсів має визначено щонайменше дозвіл на читання", "Files cannot be shared with delete permissions" : "Не можна надавати у спільний доступ файли з дозволами на вилучення", @@ -176,13 +201,16 @@ "Path is already shared with this group" : "Шлях вже надано у спільний доступ для цієї групи", "Link sharing is not allowed" : "Спільний доступ через посилання не дозволено", "Public upload is not allowed" : "Публічні завантаження не дозволено", - "Path contains files shared with you" : "Шлях містить файли, якими поділилися з вами", + "You cannot share a folder that contains other shares" : "Неможливо надати у спільний доступ каталог, який вже містить інші спільні ресурси", "Sharing is disabled" : "Спільний доступ вимкнено", "Sharing is disabled for you" : "Ви не маєте права надавати у доступ файли або каталоги", "Cannot share with the share owner" : "Неможливо надавати у доступ власникові спільного ресурсу", "Share does not have a full ID" : "Спільний ресурс не має повного ідентифікатора", "Cannot change share type" : "Неможливо змінити тип спільного ресурсу", "Can only update recipient on user shares" : "Можна лише оновити отримувача для спільних ресурсів користувача", + "Cannot enable sending the password by Talk with an empty password" : "Не вдалося увімкнути надсилання паролю за допомогою Talk з порожнім паролем", + "Cannot enable sending the password by Talk without setting a new password" : "Не вдалося увімкнути надсилання паролю за допомогою Talk без встановлення нового паролю", + "Cannot disable sending the password by Talk without setting a new password" : "Не вдалося вимкнути надсилання паролю за допомогою Talk без встановлення нового паролю", "Share provider does not support accepting" : "Провайдер спільного доступу не підтримує прийняття", "Cannot change target of link share" : "Неможливо змінити призначення для спільного ресурсу через посилання", "Invalid share recipient" : "Недійсний отримувач спільного ресурсу", @@ -245,11 +273,12 @@ "A valid Login must be provided" : "Зазначте дійсне ім'я користувача", "Login contains whitespace at the beginning or at the end" : "Ім'я користувача містить символ пробілу на початку або наприкінці", "Login must not consist of dots only" : "Ім'я користувача не може складатися лише з крапок", + "Username is too long" : "Ім'я користувача задовге", "Login is invalid because files already exist for this user" : "Недійсне ім'я облікового запису, оскільки файли для цього користувача вже присутні", "Account disabled" : "Обліковий запис вимкнено", "Login canceled by app" : "Вхід скасовано застосунком", "App \"%1$s\" cannot be installed because the following dependencies are not fulfilled: %2$s" : "Застосунок \"%1$s\" неможливо встановити, оскільки не виконано такі залежності: %2$s", - "a safe home for all your data" : "безпечний дім для ваших даних", + "a safe home for all your data" : "безпечна домівка для ваших даних", "Application is not enabled" : "Застосунок не увімкнено", "Authentication error" : "Помилка авторизації", "Token expired. Please reload page." : "Строк дії токена скінчився. Будь ласка, перезавантажте сторінку.", @@ -295,9 +324,25 @@ "Storage is temporarily not available" : "Сховище тимчасово недоступне", "Storage connection timeout. %s" : "Час під'єднання до сховища вичерпався. %s", "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "Щоби дозволити запуск цієї перевірки, потрібно пересвідчитися, що ваш вебсервер може з'єднуватися з самим собою, що передбачає можливість резолвити та з'єднуватися з одним з `trusted_domains` або `overwrite.cli.url`. Неможливість цього може бути результатом незбігу DNS на стороні сервера або встановленими правилами брандмауера.", + "Transcribe audio" : "Транскрибувати аудіо", + "Transcribe the things said in an audio" : "Транскрибувати голос", + "Audio input" : "Аудіовхід", + "The audio to transcribe" : "Аудіо для транскрибування", + "The transcribed text" : "Транскрибований текст", "Confirmation" : "Підтвердження", + "Writing style" : "Стиль письма", + "Generated text" : "Зґенерований текст", + "Emoji generator" : "Ґенератор емоційок", + "Generated emoji" : "Зґенеровані емоційки", + "Generate image" : "Зґенерувати зображення", + "Prompt" : "Запрошення", "Chat" : "Чат", + "System prompt" : "Системний запит", + "Chat history" : "Історія чату", + "Response message" : "Відповідь", + "Available tools" : "Доступні інструменти", "Generates a possible headline for a text." : "Створює ймовірний заголовок тексту.", + "Text" : "Текст", "Summarize" : "Підсумок", "Summary" : "Загалом", "Extract topics" : "Виділити теми", @@ -309,41 +354,9 @@ "Generate headline" : "Створити заголовок", "Summarizes text by reducing its length without losing key information." : "Викокремлює головне у тексті шляхом зменшення довжини тексту без втрати ключової інформації.", "Extracts topics from a text and outputs them separated by commas." : "Виділяє теми, які висвітлює текст, зводить їх у перелік, що розділено комами.", - "Education Edition" : "Для навчання", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "Користувач, який увійшов у систему, має бути адміністратором, підадміністратором або мати спеціальні права доступу до цього налаштування", - "Logged in user must be an admin or sub admin" : "Увійшовши в систему користувач повинен бути адміністратором або підадміністратором", - "Logged in user must be an admin" : "Зареєстрований користувач має бути адміністратором", - "File name is a reserved word" : "Ім’я файлу є зарезервованим словом", - "File name contains at least one invalid character" : "Ім’я файлу містить принаймні один некоректний символ", - "File name is too long" : "Ім’я файлу занадто довге", - "Help" : "Допомога", - "Users" : "Користувачі", - "Unknown user" : "Невідомий користувач", - "Enter the database username and name for %s" : "Введіть ім’я користувача та назву бази даних %s", - "Enter the database username for %s" : "Введіть ім’я користувача бази даних для %s", - "MySQL username and/or password not valid" : "Ім'я користувача та/або пароль MySQL недійсні", - "Oracle username and/or password not valid" : "Oracle ім'я користувача та/або пароль не дійсні", - "PostgreSQL username and/or password not valid" : "PostgreSQL ім'я користувача та/або пароль не дійсні", - "Set an admin username." : "Встановіть ім'я адміністратора.", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s надав(-ла) доступ до \"%2$s\" та хоче додати:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s надав(-ла) доступ до \"%2$s\" та хоче додати", - "»%s« added a note to a file shared with you" : "\"%s\" додано примітку до файлу у спільному доступі", - "Open »%s«" : "Відкрити %s", - "Sharing %s failed, because this item is already shared with user %s" : "Не вдалося поділитися %s, оскільки %s вже має до нього доступ", - "%1$s shared »%2$s« with you" : "%1$s надав(-ла) доступ до \"%2$s\"", - "%1$s shared »%2$s« with you." : "%1$s надав(-ла) доступ до \"%2$s\".", - "The username is already being used" : "Ім'я користувача вже використовується", - "Could not create user" : "Не вдалося створити користувача", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "Лише такі символи дозволено у імені користувача: \"a-z\", \"A-Z\", \"0-9\", пробіл та \"_.@-'\"", - "A valid username must be provided" : "Потрібно зазначити дійсне ім'я користувача", - "Username contains whitespace at the beginning or at the end" : "Ім'я користувача містить символ пробілу в початку або в кінці", - "Username must not consist of dots only" : "Ім'я користувача не повинно складатися лише з крапок", - "Username is invalid because files already exist for this user" : "Ім'я користувача недійсне, оскільки файли для цього користувача вже існують", - "User disabled" : "Користувач виключений", + "Organisation" : "Організація", "File is currently busy, please try again later" : "Файл на разі зайнятий, будь ласка, спробуйте пізніше", "Cannot download file" : "Неможливо звантажити файл", - "Your data directory is readable by other users." : "Ваш каталог даних доступний для читання іншим користувачам.", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "Змініть права доступу на 0770, щоб інші користувачі не могли отримати список файлів цього каталогу.", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "Переконайтеся, що в корені каталогу даних є файл під назвою \".ocdata\"." + "Login is too long" : "Ім'я користувача для авторизації задовге" },"pluralForm" :"nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);" }
\ No newline at end of file diff --git a/lib/l10n/ur_PK.js b/lib/l10n/ur_PK.js index e58134e8957..44d1c069b4d 100644 --- a/lib/l10n/ur_PK.js +++ b/lib/l10n/ur_PK.js @@ -31,8 +31,6 @@ OC.L10N.register( "September" : "ستمبر", "October" : "اکتوبر", "November" : "نومبر", - "December" : "دسمبر", - "Help" : "مدد", - "Users" : "یوزرز" + "December" : "دسمبر" }, "nplurals=2; plural=(n != 1);"); diff --git a/lib/l10n/ur_PK.json b/lib/l10n/ur_PK.json index 6054376b210..dc156aa2bf6 100644 --- a/lib/l10n/ur_PK.json +++ b/lib/l10n/ur_PK.json @@ -29,8 +29,6 @@ "September" : "ستمبر", "October" : "اکتوبر", "November" : "نومبر", - "December" : "دسمبر", - "Help" : "مدد", - "Users" : "یوزرز" + "December" : "دسمبر" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/lib/l10n/uz.js b/lib/l10n/uz.js index 17830cba76b..dbd52a84666 100644 --- a/lib/l10n/uz.js +++ b/lib/l10n/uz.js @@ -2,6 +2,7 @@ OC.L10N.register( "lib", { "Cannot write into \"config\" directory!" : "Cannot write into \"config\" directory!", + "Authentication" : "Autentifikatsiya", "Unknown filetype" : "Unknown filetype", "Invalid image" : "Invalid image", "Files" : "Files", @@ -10,16 +11,27 @@ OC.L10N.register( "seconds ago" : "seconds ago", "Apps" : "Apps", "Settings" : "Settings", + "Accounts" : "Akkaunt", + "Email" : "Email", + "Website" : "Veb-sayt", "Address" : "Address", "Profile picture" : "Profil rasmi", "About" : "About", + "Additional settings" : "Parol", "Set an admin password." : "Set an admin password.", + "Open %s" : "Ochiq %s", + "Sunday" : "Yakshanba", + "Monday" : "Dushanba", + "Tuesday" : "Seshanba", + "Wednesday" : "Chorshanba", + "Thursday" : "Payshanba", + "Friday" : "Juma", + "Saturday" : "Shanba", "January" : "January", "Authentication error" : "Authentication error", "Storage is temporarily not available" : "Storage is temporarily not available", - "File name is too long" : "File name is too long", - "Help" : "Help", - "Users" : "Users", - "Unknown user" : "Unknown user" + "Confirmation" : "Tasdiqlash", + "Text" : "Matn", + "Translate" : "Tarjima" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/uz.json b/lib/l10n/uz.json index bb313c8fa89..4ead6aa936c 100644 --- a/lib/l10n/uz.json +++ b/lib/l10n/uz.json @@ -1,5 +1,6 @@ { "translations": { "Cannot write into \"config\" directory!" : "Cannot write into \"config\" directory!", + "Authentication" : "Autentifikatsiya", "Unknown filetype" : "Unknown filetype", "Invalid image" : "Invalid image", "Files" : "Files", @@ -8,16 +9,27 @@ "seconds ago" : "seconds ago", "Apps" : "Apps", "Settings" : "Settings", + "Accounts" : "Akkaunt", + "Email" : "Email", + "Website" : "Veb-sayt", "Address" : "Address", "Profile picture" : "Profil rasmi", "About" : "About", + "Additional settings" : "Parol", "Set an admin password." : "Set an admin password.", + "Open %s" : "Ochiq %s", + "Sunday" : "Yakshanba", + "Monday" : "Dushanba", + "Tuesday" : "Seshanba", + "Wednesday" : "Chorshanba", + "Thursday" : "Payshanba", + "Friday" : "Juma", + "Saturday" : "Shanba", "January" : "January", "Authentication error" : "Authentication error", "Storage is temporarily not available" : "Storage is temporarily not available", - "File name is too long" : "File name is too long", - "Help" : "Help", - "Users" : "Users", - "Unknown user" : "Unknown user" + "Confirmation" : "Tasdiqlash", + "Text" : "Matn", + "Translate" : "Tarjima" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/vi.js b/lib/l10n/vi.js index 62191e1c7c1..23e5d87b9fc 100644 --- a/lib/l10n/vi.js +++ b/lib/l10n/vi.js @@ -49,12 +49,10 @@ OC.L10N.register( "Profile picture" : "Ảnh đại diện", "About" : "Giới thiệu", "Headline" : "Tiêu đề", - "Organisation" : "Tổ chức", "Role" : "Vai trò", "Additional settings" : "Cài đặt bổ sung", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Hãy xóa thiết lập open_basedir tại tập tin cấu hình php.ini hoặc chuyển sang dùng PHP 64-bit.", "Set an admin password." : "Thiết lập mật khẩu quản trị", - "Click the button below to open it." : "Bấm vào nút bên dưới để mở nó.", "%1$s via %2$s" : "%1$s thông qua %2$s", "Unknown share type" : "Loại chia sẻ không xác định", "Could not find category \"%s\"" : "không thể tìm thấy mục \"%s\"", @@ -102,14 +100,9 @@ OC.L10N.register( "Token expired. Please reload page." : "Mã Token đã hết hạn. Hãy tải lại trang.", "PHP module %s not installed." : "PHP mô đun %s chưa được cài đặt", "Storage is temporarily not available" : "Kho lưu trữ tạm thời không khả dụng", + "Text" : "Văn bản", "Summary" : "Tóm tắt", "Translate" : "Dịch", - "Education Edition" : "Bản Giáo dục", - "Help" : "Giúp đỡ", - "Users" : "Người dùng", - "Unknown user" : "Người dùng không tồn tại", - "Open »%s«" : "Mở »%s«", - "The username is already being used" : "Tên đăng nhập đã được sử dụng", - "User disabled" : "Vô hiệu hóa sử dụng" + "Organisation" : "Tổ chức" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/vi.json b/lib/l10n/vi.json index 4512b243e5a..67f926bf484 100644 --- a/lib/l10n/vi.json +++ b/lib/l10n/vi.json @@ -47,12 +47,10 @@ "Profile picture" : "Ảnh đại diện", "About" : "Giới thiệu", "Headline" : "Tiêu đề", - "Organisation" : "Tổ chức", "Role" : "Vai trò", "Additional settings" : "Cài đặt bổ sung", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "Hãy xóa thiết lập open_basedir tại tập tin cấu hình php.ini hoặc chuyển sang dùng PHP 64-bit.", "Set an admin password." : "Thiết lập mật khẩu quản trị", - "Click the button below to open it." : "Bấm vào nút bên dưới để mở nó.", "%1$s via %2$s" : "%1$s thông qua %2$s", "Unknown share type" : "Loại chia sẻ không xác định", "Could not find category \"%s\"" : "không thể tìm thấy mục \"%s\"", @@ -100,14 +98,9 @@ "Token expired. Please reload page." : "Mã Token đã hết hạn. Hãy tải lại trang.", "PHP module %s not installed." : "PHP mô đun %s chưa được cài đặt", "Storage is temporarily not available" : "Kho lưu trữ tạm thời không khả dụng", + "Text" : "Văn bản", "Summary" : "Tóm tắt", "Translate" : "Dịch", - "Education Edition" : "Bản Giáo dục", - "Help" : "Giúp đỡ", - "Users" : "Người dùng", - "Unknown user" : "Người dùng không tồn tại", - "Open »%s«" : "Mở »%s«", - "The username is already being used" : "Tên đăng nhập đã được sử dụng", - "User disabled" : "Vô hiệu hóa sử dụng" + "Organisation" : "Tổ chức" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/zh_CN.js b/lib/l10n/zh_CN.js index a8c6d454ab6..14f922c47e0 100644 --- a/lib/l10n/zh_CN.js +++ b/lib/l10n/zh_CN.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "需要服务器版本 %s 或更高版本。", "Server version %s or lower is required." : "需要服务器版本 %s 或更低版本。", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "登录的账号必须是管理员、副管理员或获得访问此设置的特殊权限", - "Your current IP address doesn’t allow you to perform admin actions" : "您当前的 IP 地址不允许您执行管理员操作", + "Your current IP address doesn't allow you to perform admin actions" : "您当前的 IP 地址不允许您执行管理员操作", "Logged in account must be an admin or sub admin" : "登录账号必须是管理员或副管理员", "Logged in account must be an admin" : "登录的账号必须是管理员", "Wiping of device %s has started" : "设备%s的擦除操作已开始", @@ -59,29 +59,42 @@ OC.L10N.register( "Avatar image is not square" : "头像图像不是正方形", "Files" : "文件", "View profile" : "查看个人资料", + "same time" : "同一时间", + "_%nh_::_%nh_" : ["%n 小时"], + "_%nm_::_%nm_" : ["%n分钟"], + "%s ahead" : "早 %s", + "%s behind" : "晚 %s", "Local time: %s" : "当地时间:%s", "today" : "今天", "tomorrow" : "明天", "yesterday" : "昨天", - "_in %n day_::_in %n days_" : ["%n天内"], + "_in %n day_::_in %n days_" : ["%n 天内"], "_%n day ago_::_%n days ago_" : ["%n 天前"], - "next month" : "下月", - "last month" : "上月", - "_in %n month_::_in %n months_" : ["%n月内"], + "next month" : "下个月", + "last month" : "上个月", + "_in %n month_::_in %n months_" : ["%n 月内"], "_%n month ago_::_%n months ago_" : ["%n 月前"], "next year" : "明年", "last year" : "去年", - "_in %n year_::_in %n years_" : ["%n年内"], + "_in %n year_::_in %n years_" : ["%n 年内"], "_%n year ago_::_%n years ago_" : ["%n 年前"], - "_in %n hour_::_in %n hours_" : ["%n小时内"], - "_%n hour ago_::_%n hours ago_" : ["%n小时前"], - "_in %n minute_::_in %n minutes_" : ["%n分钟内"], - "_%n minute ago_::_%n minutes ago_" : ["%n分钟前"], + "_in %n hour_::_in %n hours_" : ["%n 小时内"], + "_%n hour ago_::_%n hours ago_" : ["%n 小时前"], + "_in %n minute_::_in %n minutes_" : ["%n 分钟内"], + "_%n minute ago_::_%n minutes ago_" : ["%n 分钟前"], "in a few seconds" : "几秒钟内", "seconds ago" : "几秒前", "Empty file" : "空文件", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "模块:%s不存在。请在 App 设置中开启或联系您的管理员。", + "No file conversion providers available" : "没有可用的文件转换提供程序", + "File is too large to convert" : "文件太大,无法转换", + "Destination does not match conversion extension" : "目标与转换扩展名不匹配", + "Could not convert file" : "无法转换文件", + "Destination does not exist" : "目标不存在", + "Destination is not creatable" : "目标不可创建", "Dot files are not allowed" : "以 . 开头的文件不被允许", + "%1$s (renamed)" : "%1$s(已重命名)", + "renamed file" : "已重命名文件", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" 是禁止的文件或文件夹名称。", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" 是文件或文件夹名称的禁止前缀。", "\"%1$s\" is not allowed inside a file or folder name." : "文件或文件夹名称中不允许出现 \"%1$s\"。", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "无效的路径", "Failed to create file from template" : "从模板创建文件失败", "Templates" : "模板", + "Storage %s cannot be moved" : "无法移动存储空间 %s", + "Moving a share (%s) into a shared folder is not allowed" : "不允许将分享(%s)移动到共享文件夹中", + "Moving a storage (%s) into a shared folder is not allowed" : "不允许将储存空间(%s)移动到共享文件夹中", + "Moving a share (%s) into another share (%s) is not allowed" : "不允许将分享(%s)移动到另一个分享(%s)中", + "Moving a share (%s) into another storage (%s) is not allowed" : "不允许将分享(%s)移动到另一个储存空间(%s)中", + "Moving a storage (%s) into a share (%s) is not allowed" : "不允许将储存空间(%s)移动到分享(%s)中", + "Moving a storage (%s) into another storage (%s) is not allowed" : "不允许将储存空间(%s)移动到另一个储存空间(%s)中", "Path contains invalid segments" : "路径包含无效段", "Filename is a reserved word" : "Filename 是保留字", "Filename contains at least one invalid character" : "文件名中存在至少一个非法字符", @@ -124,7 +144,6 @@ OC.L10N.register( "About" : "关于", "Display name" : "显示用户名", "Headline" : "标题", - "Organisation" : "组织", "Role" : "角色", "Pronouns" : "称号", "Unknown account" : "未知帐户", @@ -138,7 +157,7 @@ OC.L10N.register( "Oracle connection could not be established" : "无法建立 Oracle 连接", "Oracle Login and/or password not valid" : "Oracle 用户名或密码无效", "PostgreSQL Login and/or password not valid" : "PostgreSQL 用户名或密码无效", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X 不被支持并且 %s 在这个平台上无法正常工作。请自行承担风险!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "不支持 Mac OS X,%s 在此平台上无法正常工作。请自行承担使用风险!", "For the best results, please consider using a GNU/Linux server instead." : "为了达到最好的效果,请考虑使用 GNU/Linux 服务器。", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "看起来这个 %s 实例运行在32位 PHP 环境中并且已在 php.ini 中配置open_basedir。这将在文件超过4GB时出现问题,强烈不建议这样做。", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "请删除 php.ini 中的 open_basedir 设置或切换到64位PHP。", @@ -149,7 +168,6 @@ OC.L10N.register( "Sharing backend %s not found" : "%s 的共享后端未找到", "Sharing backend for %s not found" : "%s 的共享后端未找到", "%1$s shared %2$s with you" : "%1$s 与您分享了 %2$s ", - "Click the button below to open it." : "点击下方按钮可打开它。", "Open %s" : "打开 %s", "%1$s via %2$s" : "%1$s 通过 %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s 与您分享了 %2$s 并想要添加:", @@ -169,6 +187,7 @@ OC.L10N.register( "You cannot share your root folder" : "您无法共享您的主文件夹", "You are not allowed to share %s" : "您无权共享 %s", "Valid permissions are required for sharing" : "共享需要有效的权限", + "File shares cannot have create or delete permissions" : "文件共享无法具有创建或删除权限", "Cannot increase permissions of %s" : "无法提升 %s 的权限", "Shares need at least read permissions" : "共享至少需要读取权限", "Files cannot be shared with delete permissions" : "不能带删除权限分享文件", @@ -183,7 +202,7 @@ OC.L10N.register( "Path is already shared with this group" : "路径已与此群组共享", "Link sharing is not allowed" : "不允许共享链接", "Public upload is not allowed" : "不允许公开上传", - "Path contains files shared with you" : "路径包含与你共享的文件", + "You cannot share a folder that contains other shares" : "您无法共享包含其他共享的文件夹", "Sharing is disabled" : "共享已禁用", "Sharing is disabled for you" : "已为您禁用共享", "Cannot share with the share owner" : "无法与共享所有者共享", @@ -195,10 +214,14 @@ OC.L10N.register( "Cannot disable sending the password by Talk without setting a new password" : "如果不设置新密码,则无法禁用 Talk 发送密码", "Share provider does not support accepting" : "共享提供商不支持接受", "Cannot change target of link share" : "无法更改链接共享的目标", + "Invalid share recipient" : "无效的分享接收者", + "Group \"%s\" does not exist" : "组“%s”不存在", "The requested share does not exist anymore" : "当前请求的共享已经不存在", "The requested share comes from a disabled user" : "请求的分享来自一个被禁用的用户", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "由于已达用户数量上限,用户未创建。请检查通知以了解详情。", "Could not find category \"%s\"" : "无法找到分类 \"%s\"", + "Input text" : "输入文本", + "The input text" : "输入文本", "Sunday" : "星期日", "Monday" : "星期一", "Tuesday" : "星期二", @@ -251,6 +274,7 @@ OC.L10N.register( "A valid Login must be provided" : "必须提供有效的登录名", "Login contains whitespace at the beginning or at the end" : "登录名开头或结尾包含空格", "Login must not consist of dots only" : "登录名不能仅由点组成", + "Username is too long" : "用户名太长", "Login is invalid because files already exist for this user" : "登录无效,因为此用户的文件已存在", "Account disabled" : "帐户已禁用", "Login canceled by app" : "已通过应用取消登录", @@ -300,96 +324,134 @@ OC.L10N.register( "Storage connection error. %s" : "存储连接错误。%s", "Storage is temporarily not available" : "存储暂时不可用", "Storage connection timeout. %s" : "存储连接超时。%s", - "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "要允许此检查运行,您必须确保您的 Web 服务器可以连接到自身。因此,它必须能够解析并连接到其 \"trusted_domains\" 或 \"overwrite.cli.url\" 中的至少一个。此失败可能是服务器端 DNS 不匹配或出站防火墙规则的结果。", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "要允许此检查运行,您必须确保您的 Web 服务器可以连接到自身。因此,它必须能够解析并连接到其 \"trusted_domains\" 或 \"overwrite.cli.url\" 中的至少一个。此失败可能是服务端 DNS 不匹配或出站防火墙规则的结果。", "Transcribe audio" : "转写音频", "Transcribe the things said in an audio" : "将音频中的内容转录下来", "Audio input" : "音频输入", "The audio to transcribe" : "要转录的音频", + "Transcription" : "转录", + "The transcribed text" : "已转录的文本", + "Chat with an agent" : "和 agent 对话", + "Chat message" : "聊天消息", + "A chat message to send to the agent." : "要发送给 agent 的聊天消息。", "Confirmation" : "确认", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "是否确认之前的操作:0表示拒绝,1表示确认。", + "Conversation token" : "对话令牌", + "A token representing the conversation." : "代表对话的 token。", + "Generated response" : "生成的回复", + "The response from the chat model." : "来自聊天模型的回应。", + "The new conversation token" : "新的对话 token", + "Send this along with the next interaction." : "下次交互时一起发送。", + "Requested actions by the agent" : "Agent 要求的操作", + "Actions that the agent would like to carry out in JSON format." : "代理想以 JSON 格式执行的操作。", "Context write" : "文本撰写", "Writes text in a given style based on the provided source material." : "通过给出语料的风格生成文字", "Writing style" : "撰写风格", "Demonstrate a writing style that you would like to immitate" : "展示你想模仿的写作风格", "Source material" : "来源材料", "The content that would like to be rewritten in the new writing style" : "希望以新文风重写的内容", + "Generated text" : "生成的文本", "The generated text with content from the source material in the given style" : "生成的文本内容来自给定风格的源材料", + "Emoji generator" : "表情生成器", + "Takes text and generates a representative emoji for it." : "应用文本并生成一个相应的表情。", + "The text to generate an emoji for" : "用于生成表情的文字", + "Generated emoji" : "生成的表情", "The generated emoji based on the input text" : "根据输入文本生成的表情符号", "Generate image" : "生成图片", "Generate an image from a text prompt" : "根据文本提示生成图像", "Prompt" : "提示", "Describe the image you want to generate" : "描述你想要生成的图像", + "Number of images" : "图像数量", + "How many images to generate" : "生成多少张图片", + "Output images" : "输出图像", + "The generated images" : "生成的图像", + "Generate speech" : "生成语音", + "Generate speech from a transcript" : "从转录生成语音", + "Write transcript that you want the assistant to generate speech from" : "编写您想要助手从中生成语音的转录内容", + "Output speech" : "输出语音", + "The generated speech" : "生成的语音", + "Free text to text prompt" : "免费文本转文本提示", "Runs an arbitrary prompt through a language model that returns a reply" : "通过语言模型运行任意提示并返回答复", "Describe a task that you want the assistant to do or ask a question" : "描述你希望助手执行的任务或提出问题", + "Generated reply" : "已生成回复", "The generated text from the assistant" : "助手生成的文本", + "Change Tone" : "更改语气", + "Change the tone of a piece of text." : "更改一段文本的语气。", + "Write a text that you want the assistant to rewrite in another tone." : "写一篇您想让助手用另一种语气重写的文本。", + "Desired tone" : "期望的语气", + "In which tone should your text be rewritten?" : "您的文本应该以何种语气重写?", + "The rewritten text in the desired tone, written by the assistant:" : "由助手以所需的语气重写的文本:", + "Chat" : "聊天", + "Chat with the assistant" : "与助手聊天", + "System prompt" : "系统提示", "Define rules and assumptions that the assistant should follow during the conversation." : "定义助手在对话过程中应遵循的规则和假设。", + "Chat history" : "聊天记录", "The history of chat messages before the current message, starting with a message by the user" : "当前消息之前的聊天消息历史记录,从用户发送的消息开始", + "Response message" : "应答消息", "The generated response as part of the conversation" : "作为对话的一部分生成的响应", + "Chat with tools" : "使用工具聊天", + "Chat with the language model with tool calling support." : "使用工具调用支持与语言模型聊天。", + "Tool message" : "工具消息", + "The result of tool calls in the last interaction" : "上次互动中工具调用的结果", + "Available tools" : "可用工具", + "The available tools in JSON format" : "JSON 格式的可用工具", + "The response from the chat model" : "聊天模型的应答", + "Tool calls" : "工具调用", + "Tools call instructions from the model in JSON format" : "工具以 JSON 格式从模型调用指令", + "Formalize text" : "正式化文本", "Takes a text and makes it sound more formal" : "使文本听起来更正式", "Write a text that you want the assistant to formalize" : "写下你希望助手正式化的文本", + "Formalized text" : "已正式化文本", + "The formalized text" : "正式文本", "Generate a headline" : "生成标题", "Generates a possible headline for a text." : "为一段文本生成一个可能的标题", + "Original text" : "原始文本", "The original text to generate a headline for" : "需要生成标题的原始文本", "The generated headline" : "生成的标题", + "Proofread" : "校对", + "Proofreads a text and lists corrections" : "校对文本并列出校正", + "Text" : "文本 ", + "The text to proofread" : "要校对的文本", + "Corrections" : "校正", + "The corrections that should be made in your text" : "您的文本中应该做出的校正", "Reformulate text" : "重新表述文本", "Takes a text and reformulates it" : "获取文本并将其重新表述", "Write a text that you want the assistant to reformulate" : "写下您希望云助手重新表述的文本", "Reformulated text" : "重新表述的文本", "The reformulated text, written by the assistant" : "由云助手撰写的重新表述的文本", + "Simplify text" : "简化文本", + "Takes a text and simplifies it" : "获取文本并将其简化", "Write a text that you want the assistant to simplify" : "写下您希望助手简化的文本", + "Simplified text" : "已简化文本", + "The simplified text" : "简化的文本", "Summarize" : "总结归纳", "Summarizes a text" : "总结一段文本", "The original text to summarize" : "需要总结的原始文本", - "Summary" : "概况", + "Summary" : "总结", + "The generated summary" : "生成的总结", "Extract topics" : "提取主题", "Extracts topics from a text and outputs them separated by commas" : "从文本中提取主题并输出,以逗号分隔", "The original text to extract topics from" : "需要提取主题的原始文本", + "Topics" : "主题", "The list of extracted topics" : "提取的主题列表", "Translate" : "翻译", + "Translate text from one language to another" : "将文本从一种语言翻译为另一种语言", + "Origin text" : "原始文本", "The text to translate" : "需要翻译的文本", + "Origin language" : "原始语言", "The language of the origin text" : "原始文本语言", "Target language" : "目标语言", "The desired language to translate the origin text in" : "需要翻译的目标语言", "Result" : "结果", - "Free prompt" : "自由提示", + "The translated text" : "翻译的文本", + "Free prompt" : "免费提示", "Runs an arbitrary prompt through the language model." : "向语言模型中输入任何提示词", "Generate headline" : "生成标题", "Summarizes text by reducing its length without losing key information." : "总结一段文本以减少长度而不丢失关键信息", "Extracts topics from a text and outputs them separated by commas." : "从文本中摘出主题,输出逗号分隔的结果", - "Education Edition" : "教育版", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "登录用户必须是管理员、子管理员或具有访问此设置的特殊权限", - "Logged in user must be an admin or sub admin" : "当前登录用户必须为管理员或子管理员", - "Logged in user must be an admin" : "当前登录用户必须为管理员", - "File name is a reserved word" : "文件名包含敏感字符", - "File name contains at least one invalid character" : "文件名中存在至少一个非法字符", - "File name is too long" : "文件名过长", - "Help" : "帮助", - "Users" : "用户", - "Unknown user" : "未知用户", - "Enter the database username and name for %s" : "输入 %s 的数据库用户名和名称", - "Enter the database username for %s" : "输入 %s 的数据库用户名", - "MySQL username and/or password not valid" : "MySQL 数据库用户名和/或密码无效", - "Oracle username and/or password not valid" : "Oracle 数据库用户名和/或密码无效", - "PostgreSQL username and/or password not valid" : "PostgreSQL 数据库用户名和/或密码无效", - "Set an admin username." : "请设置一个管理员用户名。", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s 与您共享了 »%2$s« 并希望添加:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s 与您共享了 »%2$s« 并希望添加", - "»%s« added a note to a file shared with you" : "»%s« 在与你共享的文件中添加了备注", - "Open »%s«" : "打开 »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "共享 %s 失败了,因为该项目已和用户 %s 进行了分享。", - "%1$s shared »%2$s« with you" : "%1$s 对您共享了 »%2$s«", - "%1$s shared »%2$s« with you." : "%1$s 对您共享了 »%2$s«。", - "The username is already being used" : "用户名已被使用", - "Could not create user" : "无法创建用户", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "在用户名中只允许使用以下字符:“a-z”、“A-Z”、“0-9”、空格和 \"_.@-'\"", - "A valid username must be provided" : "必须提供合法的用户名", - "Username contains whitespace at the beginning or at the end" : "用户名在开头或结尾处包含空格", - "Username must not consist of dots only" : "用户名不能仅由点组成", - "Username is invalid because files already exist for this user" : "用户名无效,因为该用户已经存在文件", - "User disabled" : "用户已禁用", + "Organisation" : "组织", "File is currently busy, please try again later" : "文件当前正忙,请稍后再试", "Cannot download file" : "无法下载文件", - "Your data directory is readable by other users." : "您的数据目录可被其他用户读取。", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "请更改权限为 0770 以避免其他用户查看目录。", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "请确定在根目录下有一个名为\".ocdata\"的文件。" + "Login is too long" : "登录名太长" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/zh_CN.json b/lib/l10n/zh_CN.json index f9561491eda..d8f5bcea5c3 100644 --- a/lib/l10n/zh_CN.json +++ b/lib/l10n/zh_CN.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "需要服务器版本 %s 或更高版本。", "Server version %s or lower is required." : "需要服务器版本 %s 或更低版本。", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "登录的账号必须是管理员、副管理员或获得访问此设置的特殊权限", - "Your current IP address doesn’t allow you to perform admin actions" : "您当前的 IP 地址不允许您执行管理员操作", + "Your current IP address doesn't allow you to perform admin actions" : "您当前的 IP 地址不允许您执行管理员操作", "Logged in account must be an admin or sub admin" : "登录账号必须是管理员或副管理员", "Logged in account must be an admin" : "登录的账号必须是管理员", "Wiping of device %s has started" : "设备%s的擦除操作已开始", @@ -57,29 +57,42 @@ "Avatar image is not square" : "头像图像不是正方形", "Files" : "文件", "View profile" : "查看个人资料", + "same time" : "同一时间", + "_%nh_::_%nh_" : ["%n 小时"], + "_%nm_::_%nm_" : ["%n分钟"], + "%s ahead" : "早 %s", + "%s behind" : "晚 %s", "Local time: %s" : "当地时间:%s", "today" : "今天", "tomorrow" : "明天", "yesterday" : "昨天", - "_in %n day_::_in %n days_" : ["%n天内"], + "_in %n day_::_in %n days_" : ["%n 天内"], "_%n day ago_::_%n days ago_" : ["%n 天前"], - "next month" : "下月", - "last month" : "上月", - "_in %n month_::_in %n months_" : ["%n月内"], + "next month" : "下个月", + "last month" : "上个月", + "_in %n month_::_in %n months_" : ["%n 月内"], "_%n month ago_::_%n months ago_" : ["%n 月前"], "next year" : "明年", "last year" : "去年", - "_in %n year_::_in %n years_" : ["%n年内"], + "_in %n year_::_in %n years_" : ["%n 年内"], "_%n year ago_::_%n years ago_" : ["%n 年前"], - "_in %n hour_::_in %n hours_" : ["%n小时内"], - "_%n hour ago_::_%n hours ago_" : ["%n小时前"], - "_in %n minute_::_in %n minutes_" : ["%n分钟内"], - "_%n minute ago_::_%n minutes ago_" : ["%n分钟前"], + "_in %n hour_::_in %n hours_" : ["%n 小时内"], + "_%n hour ago_::_%n hours ago_" : ["%n 小时前"], + "_in %n minute_::_in %n minutes_" : ["%n 分钟内"], + "_%n minute ago_::_%n minutes ago_" : ["%n 分钟前"], "in a few seconds" : "几秒钟内", "seconds ago" : "几秒前", "Empty file" : "空文件", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "模块:%s不存在。请在 App 设置中开启或联系您的管理员。", + "No file conversion providers available" : "没有可用的文件转换提供程序", + "File is too large to convert" : "文件太大,无法转换", + "Destination does not match conversion extension" : "目标与转换扩展名不匹配", + "Could not convert file" : "无法转换文件", + "Destination does not exist" : "目标不存在", + "Destination is not creatable" : "目标不可创建", "Dot files are not allowed" : "以 . 开头的文件不被允许", + "%1$s (renamed)" : "%1$s(已重命名)", + "renamed file" : "已重命名文件", "\"%1$s\" is a forbidden file or folder name." : "\"%1$s\" 是禁止的文件或文件夹名称。", "\"%1$s\" is a forbidden prefix for file or folder names." : "\"%1$s\" 是文件或文件夹名称的禁止前缀。", "\"%1$s\" is not allowed inside a file or folder name." : "文件或文件夹名称中不允许出现 \"%1$s\"。", @@ -90,6 +103,13 @@ "Invalid path" : "无效的路径", "Failed to create file from template" : "从模板创建文件失败", "Templates" : "模板", + "Storage %s cannot be moved" : "无法移动存储空间 %s", + "Moving a share (%s) into a shared folder is not allowed" : "不允许将分享(%s)移动到共享文件夹中", + "Moving a storage (%s) into a shared folder is not allowed" : "不允许将储存空间(%s)移动到共享文件夹中", + "Moving a share (%s) into another share (%s) is not allowed" : "不允许将分享(%s)移动到另一个分享(%s)中", + "Moving a share (%s) into another storage (%s) is not allowed" : "不允许将分享(%s)移动到另一个储存空间(%s)中", + "Moving a storage (%s) into a share (%s) is not allowed" : "不允许将储存空间(%s)移动到分享(%s)中", + "Moving a storage (%s) into another storage (%s) is not allowed" : "不允许将储存空间(%s)移动到另一个储存空间(%s)中", "Path contains invalid segments" : "路径包含无效段", "Filename is a reserved word" : "Filename 是保留字", "Filename contains at least one invalid character" : "文件名中存在至少一个非法字符", @@ -122,7 +142,6 @@ "About" : "关于", "Display name" : "显示用户名", "Headline" : "标题", - "Organisation" : "组织", "Role" : "角色", "Pronouns" : "称号", "Unknown account" : "未知帐户", @@ -136,7 +155,7 @@ "Oracle connection could not be established" : "无法建立 Oracle 连接", "Oracle Login and/or password not valid" : "Oracle 用户名或密码无效", "PostgreSQL Login and/or password not valid" : "PostgreSQL 用户名或密码无效", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "Mac OS X 不被支持并且 %s 在这个平台上无法正常工作。请自行承担风险!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "不支持 Mac OS X,%s 在此平台上无法正常工作。请自行承担使用风险!", "For the best results, please consider using a GNU/Linux server instead." : "为了达到最好的效果,请考虑使用 GNU/Linux 服务器。", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "看起来这个 %s 实例运行在32位 PHP 环境中并且已在 php.ini 中配置open_basedir。这将在文件超过4GB时出现问题,强烈不建议这样做。", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "请删除 php.ini 中的 open_basedir 设置或切换到64位PHP。", @@ -147,7 +166,6 @@ "Sharing backend %s not found" : "%s 的共享后端未找到", "Sharing backend for %s not found" : "%s 的共享后端未找到", "%1$s shared %2$s with you" : "%1$s 与您分享了 %2$s ", - "Click the button below to open it." : "点击下方按钮可打开它。", "Open %s" : "打开 %s", "%1$s via %2$s" : "%1$s 通过 %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s 与您分享了 %2$s 并想要添加:", @@ -167,6 +185,7 @@ "You cannot share your root folder" : "您无法共享您的主文件夹", "You are not allowed to share %s" : "您无权共享 %s", "Valid permissions are required for sharing" : "共享需要有效的权限", + "File shares cannot have create or delete permissions" : "文件共享无法具有创建或删除权限", "Cannot increase permissions of %s" : "无法提升 %s 的权限", "Shares need at least read permissions" : "共享至少需要读取权限", "Files cannot be shared with delete permissions" : "不能带删除权限分享文件", @@ -181,7 +200,7 @@ "Path is already shared with this group" : "路径已与此群组共享", "Link sharing is not allowed" : "不允许共享链接", "Public upload is not allowed" : "不允许公开上传", - "Path contains files shared with you" : "路径包含与你共享的文件", + "You cannot share a folder that contains other shares" : "您无法共享包含其他共享的文件夹", "Sharing is disabled" : "共享已禁用", "Sharing is disabled for you" : "已为您禁用共享", "Cannot share with the share owner" : "无法与共享所有者共享", @@ -193,10 +212,14 @@ "Cannot disable sending the password by Talk without setting a new password" : "如果不设置新密码,则无法禁用 Talk 发送密码", "Share provider does not support accepting" : "共享提供商不支持接受", "Cannot change target of link share" : "无法更改链接共享的目标", + "Invalid share recipient" : "无效的分享接收者", + "Group \"%s\" does not exist" : "组“%s”不存在", "The requested share does not exist anymore" : "当前请求的共享已经不存在", "The requested share comes from a disabled user" : "请求的分享来自一个被禁用的用户", "The user was not created because the user limit has been reached. Check your notifications to learn more." : "由于已达用户数量上限,用户未创建。请检查通知以了解详情。", "Could not find category \"%s\"" : "无法找到分类 \"%s\"", + "Input text" : "输入文本", + "The input text" : "输入文本", "Sunday" : "星期日", "Monday" : "星期一", "Tuesday" : "星期二", @@ -249,6 +272,7 @@ "A valid Login must be provided" : "必须提供有效的登录名", "Login contains whitespace at the beginning or at the end" : "登录名开头或结尾包含空格", "Login must not consist of dots only" : "登录名不能仅由点组成", + "Username is too long" : "用户名太长", "Login is invalid because files already exist for this user" : "登录无效,因为此用户的文件已存在", "Account disabled" : "帐户已禁用", "Login canceled by app" : "已通过应用取消登录", @@ -298,96 +322,134 @@ "Storage connection error. %s" : "存储连接错误。%s", "Storage is temporarily not available" : "存储暂时不可用", "Storage connection timeout. %s" : "存储连接超时。%s", - "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "要允许此检查运行,您必须确保您的 Web 服务器可以连接到自身。因此,它必须能够解析并连接到其 \"trusted_domains\" 或 \"overwrite.cli.url\" 中的至少一个。此失败可能是服务器端 DNS 不匹配或出站防火墙规则的结果。", + "To allow this check to run you have to make sure that your Web server can connect to itself. Therefore it must be able to resolve and connect to at least one of its `trusted_domains` or the `overwrite.cli.url`. This failure may be the result of a server-side DNS mismatch or outbound firewall rule." : "要允许此检查运行,您必须确保您的 Web 服务器可以连接到自身。因此,它必须能够解析并连接到其 \"trusted_domains\" 或 \"overwrite.cli.url\" 中的至少一个。此失败可能是服务端 DNS 不匹配或出站防火墙规则的结果。", "Transcribe audio" : "转写音频", "Transcribe the things said in an audio" : "将音频中的内容转录下来", "Audio input" : "音频输入", "The audio to transcribe" : "要转录的音频", + "Transcription" : "转录", + "The transcribed text" : "已转录的文本", + "Chat with an agent" : "和 agent 对话", + "Chat message" : "聊天消息", + "A chat message to send to the agent." : "要发送给 agent 的聊天消息。", "Confirmation" : "确认", + "Whether to confirm previously requested actions: 0 for denial and 1 for confirmation." : "是否确认之前的操作:0表示拒绝,1表示确认。", + "Conversation token" : "对话令牌", + "A token representing the conversation." : "代表对话的 token。", + "Generated response" : "生成的回复", + "The response from the chat model." : "来自聊天模型的回应。", + "The new conversation token" : "新的对话 token", + "Send this along with the next interaction." : "下次交互时一起发送。", + "Requested actions by the agent" : "Agent 要求的操作", + "Actions that the agent would like to carry out in JSON format." : "代理想以 JSON 格式执行的操作。", "Context write" : "文本撰写", "Writes text in a given style based on the provided source material." : "通过给出语料的风格生成文字", "Writing style" : "撰写风格", "Demonstrate a writing style that you would like to immitate" : "展示你想模仿的写作风格", "Source material" : "来源材料", "The content that would like to be rewritten in the new writing style" : "希望以新文风重写的内容", + "Generated text" : "生成的文本", "The generated text with content from the source material in the given style" : "生成的文本内容来自给定风格的源材料", + "Emoji generator" : "表情生成器", + "Takes text and generates a representative emoji for it." : "应用文本并生成一个相应的表情。", + "The text to generate an emoji for" : "用于生成表情的文字", + "Generated emoji" : "生成的表情", "The generated emoji based on the input text" : "根据输入文本生成的表情符号", "Generate image" : "生成图片", "Generate an image from a text prompt" : "根据文本提示生成图像", "Prompt" : "提示", "Describe the image you want to generate" : "描述你想要生成的图像", + "Number of images" : "图像数量", + "How many images to generate" : "生成多少张图片", + "Output images" : "输出图像", + "The generated images" : "生成的图像", + "Generate speech" : "生成语音", + "Generate speech from a transcript" : "从转录生成语音", + "Write transcript that you want the assistant to generate speech from" : "编写您想要助手从中生成语音的转录内容", + "Output speech" : "输出语音", + "The generated speech" : "生成的语音", + "Free text to text prompt" : "免费文本转文本提示", "Runs an arbitrary prompt through a language model that returns a reply" : "通过语言模型运行任意提示并返回答复", "Describe a task that you want the assistant to do or ask a question" : "描述你希望助手执行的任务或提出问题", + "Generated reply" : "已生成回复", "The generated text from the assistant" : "助手生成的文本", + "Change Tone" : "更改语气", + "Change the tone of a piece of text." : "更改一段文本的语气。", + "Write a text that you want the assistant to rewrite in another tone." : "写一篇您想让助手用另一种语气重写的文本。", + "Desired tone" : "期望的语气", + "In which tone should your text be rewritten?" : "您的文本应该以何种语气重写?", + "The rewritten text in the desired tone, written by the assistant:" : "由助手以所需的语气重写的文本:", + "Chat" : "聊天", + "Chat with the assistant" : "与助手聊天", + "System prompt" : "系统提示", "Define rules and assumptions that the assistant should follow during the conversation." : "定义助手在对话过程中应遵循的规则和假设。", + "Chat history" : "聊天记录", "The history of chat messages before the current message, starting with a message by the user" : "当前消息之前的聊天消息历史记录,从用户发送的消息开始", + "Response message" : "应答消息", "The generated response as part of the conversation" : "作为对话的一部分生成的响应", + "Chat with tools" : "使用工具聊天", + "Chat with the language model with tool calling support." : "使用工具调用支持与语言模型聊天。", + "Tool message" : "工具消息", + "The result of tool calls in the last interaction" : "上次互动中工具调用的结果", + "Available tools" : "可用工具", + "The available tools in JSON format" : "JSON 格式的可用工具", + "The response from the chat model" : "聊天模型的应答", + "Tool calls" : "工具调用", + "Tools call instructions from the model in JSON format" : "工具以 JSON 格式从模型调用指令", + "Formalize text" : "正式化文本", "Takes a text and makes it sound more formal" : "使文本听起来更正式", "Write a text that you want the assistant to formalize" : "写下你希望助手正式化的文本", + "Formalized text" : "已正式化文本", + "The formalized text" : "正式文本", "Generate a headline" : "生成标题", "Generates a possible headline for a text." : "为一段文本生成一个可能的标题", + "Original text" : "原始文本", "The original text to generate a headline for" : "需要生成标题的原始文本", "The generated headline" : "生成的标题", + "Proofread" : "校对", + "Proofreads a text and lists corrections" : "校对文本并列出校正", + "Text" : "文本 ", + "The text to proofread" : "要校对的文本", + "Corrections" : "校正", + "The corrections that should be made in your text" : "您的文本中应该做出的校正", "Reformulate text" : "重新表述文本", "Takes a text and reformulates it" : "获取文本并将其重新表述", "Write a text that you want the assistant to reformulate" : "写下您希望云助手重新表述的文本", "Reformulated text" : "重新表述的文本", "The reformulated text, written by the assistant" : "由云助手撰写的重新表述的文本", + "Simplify text" : "简化文本", + "Takes a text and simplifies it" : "获取文本并将其简化", "Write a text that you want the assistant to simplify" : "写下您希望助手简化的文本", + "Simplified text" : "已简化文本", + "The simplified text" : "简化的文本", "Summarize" : "总结归纳", "Summarizes a text" : "总结一段文本", "The original text to summarize" : "需要总结的原始文本", - "Summary" : "概况", + "Summary" : "总结", + "The generated summary" : "生成的总结", "Extract topics" : "提取主题", "Extracts topics from a text and outputs them separated by commas" : "从文本中提取主题并输出,以逗号分隔", "The original text to extract topics from" : "需要提取主题的原始文本", + "Topics" : "主题", "The list of extracted topics" : "提取的主题列表", "Translate" : "翻译", + "Translate text from one language to another" : "将文本从一种语言翻译为另一种语言", + "Origin text" : "原始文本", "The text to translate" : "需要翻译的文本", + "Origin language" : "原始语言", "The language of the origin text" : "原始文本语言", "Target language" : "目标语言", "The desired language to translate the origin text in" : "需要翻译的目标语言", "Result" : "结果", - "Free prompt" : "自由提示", + "The translated text" : "翻译的文本", + "Free prompt" : "免费提示", "Runs an arbitrary prompt through the language model." : "向语言模型中输入任何提示词", "Generate headline" : "生成标题", "Summarizes text by reducing its length without losing key information." : "总结一段文本以减少长度而不丢失关键信息", "Extracts topics from a text and outputs them separated by commas." : "从文本中摘出主题,输出逗号分隔的结果", - "Education Edition" : "教育版", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "登录用户必须是管理员、子管理员或具有访问此设置的特殊权限", - "Logged in user must be an admin or sub admin" : "当前登录用户必须为管理员或子管理员", - "Logged in user must be an admin" : "当前登录用户必须为管理员", - "File name is a reserved word" : "文件名包含敏感字符", - "File name contains at least one invalid character" : "文件名中存在至少一个非法字符", - "File name is too long" : "文件名过长", - "Help" : "帮助", - "Users" : "用户", - "Unknown user" : "未知用户", - "Enter the database username and name for %s" : "输入 %s 的数据库用户名和名称", - "Enter the database username for %s" : "输入 %s 的数据库用户名", - "MySQL username and/or password not valid" : "MySQL 数据库用户名和/或密码无效", - "Oracle username and/or password not valid" : "Oracle 数据库用户名和/或密码无效", - "PostgreSQL username and/or password not valid" : "PostgreSQL 数据库用户名和/或密码无效", - "Set an admin username." : "请设置一个管理员用户名。", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s 与您共享了 »%2$s« 并希望添加:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s 与您共享了 »%2$s« 并希望添加", - "»%s« added a note to a file shared with you" : "»%s« 在与你共享的文件中添加了备注", - "Open »%s«" : "打开 »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "共享 %s 失败了,因为该项目已和用户 %s 进行了分享。", - "%1$s shared »%2$s« with you" : "%1$s 对您共享了 »%2$s«", - "%1$s shared »%2$s« with you." : "%1$s 对您共享了 »%2$s«。", - "The username is already being used" : "用户名已被使用", - "Could not create user" : "无法创建用户", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "在用户名中只允许使用以下字符:“a-z”、“A-Z”、“0-9”、空格和 \"_.@-'\"", - "A valid username must be provided" : "必须提供合法的用户名", - "Username contains whitespace at the beginning or at the end" : "用户名在开头或结尾处包含空格", - "Username must not consist of dots only" : "用户名不能仅由点组成", - "Username is invalid because files already exist for this user" : "用户名无效,因为该用户已经存在文件", - "User disabled" : "用户已禁用", + "Organisation" : "组织", "File is currently busy, please try again later" : "文件当前正忙,请稍后再试", "Cannot download file" : "无法下载文件", - "Your data directory is readable by other users." : "您的数据目录可被其他用户读取。", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "请更改权限为 0770 以避免其他用户查看目录。", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "请确定在根目录下有一个名为\".ocdata\"的文件。" + "Login is too long" : "登录名太长" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/zh_HK.js b/lib/l10n/zh_HK.js index 76412118032..6b4fa1acbfa 100644 --- a/lib/l10n/zh_HK.js +++ b/lib/l10n/zh_HK.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "需要伺服器版本 %s 或更高", "Server version %s or lower is required." : "需要伺服器版本 %s 或更低", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "登錄帳戶必須是管理員、子管理員或具有存取此設定的特殊權限", - "Your current IP address doesn’t allow you to perform admin actions" : "您目前的 IP 位置不允許您執行管理動作", + "Your current IP address doesn't allow you to perform admin actions" : "您目前的 IP 位置不允許您執行管理動作", "Logged in account must be an admin or sub admin" : "登入的帳戶必須要是管理員或是子管理員", "Logged in account must be an admin" : "登入的帳戶必須有管理員權限", "Wiping of device %s has started" : "已開始抹除裝置 %s ", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "虛擬化身圖像不是正方形", "Files" : "檔案", "View profile" : "查看個人資料", + "same time" : "相同時間", + "_%nh_::_%nh_" : ["%n小時"], + "_%nm_::_%nm_" : ["%n分鐘"], + "%s ahead" : "提早 %s", + "%s behind" : "落後 %s", "Local time: %s" : "本地時間︰%s", "today" : "今日", "tomorrow" : "明日", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "幾秒前", "Empty file" : "空檔案", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "名為 %s 的模組不存在,請在應用程式設定中啟用,或是聯絡系統管理員", + "No file conversion providers available" : "沒有可用的檔案轉換提供者", + "File is too large to convert" : "檔案太大,無法轉換", + "Destination does not match conversion extension" : "目的地不符合轉換副檔名", + "Could not convert file" : "無法轉換檔案", + "Destination does not exist" : "目的地不存在", + "Destination is not creatable" : "無法建立目的地", "Dot files are not allowed" : "不允許小數點開頭的檔案", + "%1$s (renamed)" : "%1$s(已重新命名)", + "renamed file" : "已重新命名的檔案", "\"%1$s\" is a forbidden file or folder name." : "「%1$s」是禁止的檔案或資料夾名稱。", "\"%1$s\" is a forbidden prefix for file or folder names." : "「%1$s」是禁止的檔案或資料夾名稱前綴。", "\"%1$s\" is not allowed inside a file or folder name." : "「%1$s」不允許出現在檔案或資料夾名稱中。", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "路徑無效", "Failed to create file from template" : "無法從模板創建檔案", "Templates" : "模板", + "Storage %s cannot be moved" : "無法移動儲存空間 %s", + "Moving a share (%s) into a shared folder is not allowed" : "不允許將分享 (%s) 移動到共享資料夾中", + "Moving a storage (%s) into a shared folder is not allowed" : "不允許將儲存空間(%s) 移動到共享資料夾中", + "Moving a share (%s) into another share (%s) is not allowed" : "不允許將分享 (%s) 移動到其他分享 (%s) 中", + "Moving a share (%s) into another storage (%s) is not allowed" : "不允許將分享 (%s) 移動到其他儲存空間 (%s) 中", + "Moving a storage (%s) into a share (%s) is not allowed" : "不允許將儲存空間 (%s) 移動到分享 (%s) 中", + "Moving a storage (%s) into another storage (%s) is not allowed" : "不允許將儲存空間 (%s) 移動到其他儲存空間 (%s) 中", "Path contains invalid segments" : "路徑包含無效的部份", "Filename is a reserved word" : "檔案名稱是保留字", "Filename contains at least one invalid character" : "檔名至少要有一個有效字元", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "關於", "Display name" : "顯示名稱", "Headline" : "標題", - "Organisation" : "機構", + "Organization" : "生產力", "Role" : "角色", "Pronouns" : "代名詞", "Unknown account" : "帳戶不詳", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "無法建立 Oracle 數據庫連線", "Oracle Login and/or password not valid" : "Oracle 帳戶或密碼不正確", "PostgreSQL Login and/or password not valid" : "PostgreSQL 帳戶或密碼無效", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "不支援 Mac OS X 而且 %s 在這個平台上面無法正常運作,請自行衡量風險後使用!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "不支援 Mac OS X 而且 %s 在這個平台上面無法正常運作,請自行衡量風險後使用!", "For the best results, please consider using a GNU/Linux server instead." : "請考慮使用 GNU/Linux 伺服器以獲得最佳體驗", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "看起來 %s 是在 32 位元的 PHP 環境運行,並且 php.ini 中被設置了 open_basedir 參數,這將讓超過 4GB 的檔案操作發生問題,強烈建議您更改設定。", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "請移除 php.ini 中的 open_basedir 設定,或是改用 64 位元的 PHP", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "找不到分享後端 %s", "Sharing backend for %s not found" : "找不到 %s 的分享後端", "%1$s shared %2$s with you" : "%1$s 與您分享了 %2$s", - "Click the button below to open it." : "點下方連結開啟", "Open %s" : "打開 %s", "%1$s via %2$s" : "%1$s 由 %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s 與您分享了 %2$s,且想要新增:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "您無法分享您的根資料夾", "You are not allowed to share %s" : "你無權分享 %s", "Valid permissions are required for sharing" : "分享需要有效的權限", + "File shares cannot have create or delete permissions" : "檔案分享不能具有創建或刪除權限", "Cannot increase permissions of %s" : "無法增加 %s 的權限", "Shares need at least read permissions" : "分享需要至少讀取的權限", "Files cannot be shared with delete permissions" : "無法分享具有刪除權限的檔案", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "已與此群組分享了路徑", "Link sharing is not allowed" : "不允許連結分享", "Public upload is not allowed" : "不允許公開上傳", - "Path contains files shared with you" : "路徑包含與您分享的檔案", + "You cannot share a folder that contains other shares" : "您無法分享包含其他分享的資料夾", "Sharing is disabled" : "已停用分享", "Sharing is disabled for you" : "您已停用分享", "Cannot share with the share owner" : "無法與分享擁有者分享", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "必須提供有效帳戶", "Login contains whitespace at the beginning or at the end" : "帳戶的開頭或結尾有空白", "Login must not consist of dots only" : "帳戶不能只包含小數點", + "Username is too long" : "用戶名稱太長", "Login is invalid because files already exist for this user" : "帳戶無效,因為此用戶的檔案已經存在", "Account disabled" : "帳戶已停用", "Login canceled by app" : "登入已被應用程式取消", @@ -311,7 +332,6 @@ OC.L10N.register( "The audio to transcribe" : "要轉錄的音頻", "Transcription" : "轉錄", "The transcribed text" : "已轉錄的文字", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "與 agent 聊天", "Chat message" : "聊天訊息", "A chat message to send to the agent." : "要發送給 agent 的聊天消息。", @@ -346,6 +366,11 @@ OC.L10N.register( "How many images to generate" : "要產生多少圖像", "Output images" : "輸出圖像", "The generated images" : "產生的圖像", + "Generate speech" : "產生語音", + "Generate speech from a transcript" : "從文字稿産生語音", + "Write transcript that you want the assistant to generate speech from" : "寫下您想要小幫手產生語音的文字稿", + "Output speech" : "輸出語音", + "The generated speech" : "產生的語音", "Free text to text prompt" : "文字提示的自由文字", "Runs an arbitrary prompt through a language model that returns a reply" : "透過回傳回覆的語言模型執行任意提示", "Describe a task that you want the assistant to do or ask a question" : "描述您希望助理執行的任務或提出問題", @@ -384,6 +409,12 @@ OC.L10N.register( "Original text" : "原始文字", "The original text to generate a headline for" : "用來產生標題的原始文字", "The generated headline" : "產生的標題", + "Proofread" : "校對", + "Proofreads a text and lists corrections" : "請提供您想要校對的文本,我會幫您檢查並列出更正意見。", + "Text" : "文本 ", + "The text to proofread" : "要校對的文本", + "Corrections" : "更正", + "The corrections that should be made in your text" : "您文本中應進行的更正", "Reformulate text" : "重新表述文字", "Takes a text and reformulates it" : "取得文字並將其重新表述", "Write a text that you want the assistant to reformulate" : "寫下您希望小幫手協助您重新表述的文字", @@ -419,41 +450,9 @@ OC.L10N.register( "Generate headline" : "産生標題", "Summarizes text by reducing its length without losing key information." : "通過減少文字長度來總結而不丟失關鍵資訊。", "Extracts topics from a text and outputs them separated by commas." : "從文字中提取主題並輸出,並用逗號分隔。", - "Education Edition" : "教育版", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "登錄用戶必須是管理員、子管理員或具有存取此設定的特殊權限", - "Logged in user must be an admin or sub admin" : "登入的用戶必須要是管理員或是子管理員", - "Logged in user must be an admin" : "登入的用戶必須有管理員權限", - "File name is a reserved word" : "檔案名稱是保留字", - "File name contains at least one invalid character" : "檔案名稱含有不允許的字元", - "File name is too long" : "檔案名稱太長", - "Help" : "說明", - "Users" : "用戶", - "Unknown user" : "用戶不詳", - "Enter the database username and name for %s" : "輸入 %s 的數據庫用戶名及名稱", - "Enter the database username for %s" : "輸入 %s 的數據庫用戶名", - "MySQL username and/or password not valid" : "MySQL 用戶名稱或密碼不正確", - "Oracle username and/or password not valid" : "Oracle 用戶名和/或密碼無效", - "PostgreSQL username and/or password not valid" : "PostgreSQL 用戶名和/或密碼無效", - "Set an admin username." : "設定管理員帳號", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s 與您分享了 %2$s ,且想要加入:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s 與您分享了 %2$s ,且想要加入", - "»%s« added a note to a file shared with you" : "%s 在與您分享的檔案中加入了註解", - "Open »%s«" : "開啟 »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "分享 %s 失敗,此項目已經與用戶 %s 分享", - "%1$s shared »%2$s« with you" : "%1$s 與您分享了 %2$s", - "%1$s shared »%2$s« with you." : "%1$s 與您分享了 %2$s", - "The username is already being used" : "這個用戶名稱已經有人使用了", - "Could not create user" : "無法建立用戶", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "用戶名稱當中只能包含下列字元:\"a-z\", \"A-Z\", \"0-9\",空格 和 \"_.@-'\"", - "A valid username must be provided" : "必須提供一個有效的用戶名", - "Username contains whitespace at the beginning or at the end" : "用戶名的開頭或結尾有空白", - "Username must not consist of dots only" : "用戶名稱不能只包含小數點", - "Username is invalid because files already exist for this user" : "用戶名稱無效,因為用戶的檔案已經存在", - "User disabled" : "用戶已停用", + "Organisation" : "機構", "File is currently busy, please try again later" : "檔案目前忙碌中,請稍候再試", "Cannot download file" : "無法下載檔案", - "Your data directory is readable by other users." : "您的資料目錄可以被其他用戶讀取。", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "請將該目錄權限設定為 0770 ,以免其他用戶讀取目錄列表", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "請確保資料目錄最上層有一個 \"。ocdata\" 檔案" + "Login is too long" : "帳號太長了" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/zh_HK.json b/lib/l10n/zh_HK.json index a8e0aaceb35..12f4f473c7f 100644 --- a/lib/l10n/zh_HK.json +++ b/lib/l10n/zh_HK.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "需要伺服器版本 %s 或更高", "Server version %s or lower is required." : "需要伺服器版本 %s 或更低", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "登錄帳戶必須是管理員、子管理員或具有存取此設定的特殊權限", - "Your current IP address doesn’t allow you to perform admin actions" : "您目前的 IP 位置不允許您執行管理動作", + "Your current IP address doesn't allow you to perform admin actions" : "您目前的 IP 位置不允許您執行管理動作", "Logged in account must be an admin or sub admin" : "登入的帳戶必須要是管理員或是子管理員", "Logged in account must be an admin" : "登入的帳戶必須有管理員權限", "Wiping of device %s has started" : "已開始抹除裝置 %s ", @@ -57,6 +57,11 @@ "Avatar image is not square" : "虛擬化身圖像不是正方形", "Files" : "檔案", "View profile" : "查看個人資料", + "same time" : "相同時間", + "_%nh_::_%nh_" : ["%n小時"], + "_%nm_::_%nm_" : ["%n分鐘"], + "%s ahead" : "提早 %s", + "%s behind" : "落後 %s", "Local time: %s" : "本地時間︰%s", "today" : "今日", "tomorrow" : "明日", @@ -79,7 +84,15 @@ "seconds ago" : "幾秒前", "Empty file" : "空檔案", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "名為 %s 的模組不存在,請在應用程式設定中啟用,或是聯絡系統管理員", + "No file conversion providers available" : "沒有可用的檔案轉換提供者", + "File is too large to convert" : "檔案太大,無法轉換", + "Destination does not match conversion extension" : "目的地不符合轉換副檔名", + "Could not convert file" : "無法轉換檔案", + "Destination does not exist" : "目的地不存在", + "Destination is not creatable" : "無法建立目的地", "Dot files are not allowed" : "不允許小數點開頭的檔案", + "%1$s (renamed)" : "%1$s(已重新命名)", + "renamed file" : "已重新命名的檔案", "\"%1$s\" is a forbidden file or folder name." : "「%1$s」是禁止的檔案或資料夾名稱。", "\"%1$s\" is a forbidden prefix for file or folder names." : "「%1$s」是禁止的檔案或資料夾名稱前綴。", "\"%1$s\" is not allowed inside a file or folder name." : "「%1$s」不允許出現在檔案或資料夾名稱中。", @@ -90,6 +103,13 @@ "Invalid path" : "路徑無效", "Failed to create file from template" : "無法從模板創建檔案", "Templates" : "模板", + "Storage %s cannot be moved" : "無法移動儲存空間 %s", + "Moving a share (%s) into a shared folder is not allowed" : "不允許將分享 (%s) 移動到共享資料夾中", + "Moving a storage (%s) into a shared folder is not allowed" : "不允許將儲存空間(%s) 移動到共享資料夾中", + "Moving a share (%s) into another share (%s) is not allowed" : "不允許將分享 (%s) 移動到其他分享 (%s) 中", + "Moving a share (%s) into another storage (%s) is not allowed" : "不允許將分享 (%s) 移動到其他儲存空間 (%s) 中", + "Moving a storage (%s) into a share (%s) is not allowed" : "不允許將儲存空間 (%s) 移動到分享 (%s) 中", + "Moving a storage (%s) into another storage (%s) is not allowed" : "不允許將儲存空間 (%s) 移動到其他儲存空間 (%s) 中", "Path contains invalid segments" : "路徑包含無效的部份", "Filename is a reserved word" : "檔案名稱是保留字", "Filename contains at least one invalid character" : "檔名至少要有一個有效字元", @@ -122,7 +142,7 @@ "About" : "關於", "Display name" : "顯示名稱", "Headline" : "標題", - "Organisation" : "機構", + "Organization" : "生產力", "Role" : "角色", "Pronouns" : "代名詞", "Unknown account" : "帳戶不詳", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "無法建立 Oracle 數據庫連線", "Oracle Login and/or password not valid" : "Oracle 帳戶或密碼不正確", "PostgreSQL Login and/or password not valid" : "PostgreSQL 帳戶或密碼無效", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "不支援 Mac OS X 而且 %s 在這個平台上面無法正常運作,請自行衡量風險後使用!", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "不支援 Mac OS X 而且 %s 在這個平台上面無法正常運作,請自行衡量風險後使用!", "For the best results, please consider using a GNU/Linux server instead." : "請考慮使用 GNU/Linux 伺服器以獲得最佳體驗", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "看起來 %s 是在 32 位元的 PHP 環境運行,並且 php.ini 中被設置了 open_basedir 參數,這將讓超過 4GB 的檔案操作發生問題,強烈建議您更改設定。", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "請移除 php.ini 中的 open_basedir 設定,或是改用 64 位元的 PHP", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "找不到分享後端 %s", "Sharing backend for %s not found" : "找不到 %s 的分享後端", "%1$s shared %2$s with you" : "%1$s 與您分享了 %2$s", - "Click the button below to open it." : "點下方連結開啟", "Open %s" : "打開 %s", "%1$s via %2$s" : "%1$s 由 %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s 與您分享了 %2$s,且想要新增:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "您無法分享您的根資料夾", "You are not allowed to share %s" : "你無權分享 %s", "Valid permissions are required for sharing" : "分享需要有效的權限", + "File shares cannot have create or delete permissions" : "檔案分享不能具有創建或刪除權限", "Cannot increase permissions of %s" : "無法增加 %s 的權限", "Shares need at least read permissions" : "分享需要至少讀取的權限", "Files cannot be shared with delete permissions" : "無法分享具有刪除權限的檔案", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "已與此群組分享了路徑", "Link sharing is not allowed" : "不允許連結分享", "Public upload is not allowed" : "不允許公開上傳", - "Path contains files shared with you" : "路徑包含與您分享的檔案", + "You cannot share a folder that contains other shares" : "您無法分享包含其他分享的資料夾", "Sharing is disabled" : "已停用分享", "Sharing is disabled for you" : "您已停用分享", "Cannot share with the share owner" : "無法與分享擁有者分享", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "必須提供有效帳戶", "Login contains whitespace at the beginning or at the end" : "帳戶的開頭或結尾有空白", "Login must not consist of dots only" : "帳戶不能只包含小數點", + "Username is too long" : "用戶名稱太長", "Login is invalid because files already exist for this user" : "帳戶無效,因為此用戶的檔案已經存在", "Account disabled" : "帳戶已停用", "Login canceled by app" : "登入已被應用程式取消", @@ -309,7 +330,6 @@ "The audio to transcribe" : "要轉錄的音頻", "Transcription" : "轉錄", "The transcribed text" : "已轉錄的文字", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "與 agent 聊天", "Chat message" : "聊天訊息", "A chat message to send to the agent." : "要發送給 agent 的聊天消息。", @@ -344,6 +364,11 @@ "How many images to generate" : "要產生多少圖像", "Output images" : "輸出圖像", "The generated images" : "產生的圖像", + "Generate speech" : "產生語音", + "Generate speech from a transcript" : "從文字稿産生語音", + "Write transcript that you want the assistant to generate speech from" : "寫下您想要小幫手產生語音的文字稿", + "Output speech" : "輸出語音", + "The generated speech" : "產生的語音", "Free text to text prompt" : "文字提示的自由文字", "Runs an arbitrary prompt through a language model that returns a reply" : "透過回傳回覆的語言模型執行任意提示", "Describe a task that you want the assistant to do or ask a question" : "描述您希望助理執行的任務或提出問題", @@ -382,6 +407,12 @@ "Original text" : "原始文字", "The original text to generate a headline for" : "用來產生標題的原始文字", "The generated headline" : "產生的標題", + "Proofread" : "校對", + "Proofreads a text and lists corrections" : "請提供您想要校對的文本,我會幫您檢查並列出更正意見。", + "Text" : "文本 ", + "The text to proofread" : "要校對的文本", + "Corrections" : "更正", + "The corrections that should be made in your text" : "您文本中應進行的更正", "Reformulate text" : "重新表述文字", "Takes a text and reformulates it" : "取得文字並將其重新表述", "Write a text that you want the assistant to reformulate" : "寫下您希望小幫手協助您重新表述的文字", @@ -417,41 +448,9 @@ "Generate headline" : "産生標題", "Summarizes text by reducing its length without losing key information." : "通過減少文字長度來總結而不丟失關鍵資訊。", "Extracts topics from a text and outputs them separated by commas." : "從文字中提取主題並輸出,並用逗號分隔。", - "Education Edition" : "教育版", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "登錄用戶必須是管理員、子管理員或具有存取此設定的特殊權限", - "Logged in user must be an admin or sub admin" : "登入的用戶必須要是管理員或是子管理員", - "Logged in user must be an admin" : "登入的用戶必須有管理員權限", - "File name is a reserved word" : "檔案名稱是保留字", - "File name contains at least one invalid character" : "檔案名稱含有不允許的字元", - "File name is too long" : "檔案名稱太長", - "Help" : "說明", - "Users" : "用戶", - "Unknown user" : "用戶不詳", - "Enter the database username and name for %s" : "輸入 %s 的數據庫用戶名及名稱", - "Enter the database username for %s" : "輸入 %s 的數據庫用戶名", - "MySQL username and/or password not valid" : "MySQL 用戶名稱或密碼不正確", - "Oracle username and/or password not valid" : "Oracle 用戶名和/或密碼無效", - "PostgreSQL username and/or password not valid" : "PostgreSQL 用戶名和/或密碼無效", - "Set an admin username." : "設定管理員帳號", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s 與您分享了 %2$s ,且想要加入:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s 與您分享了 %2$s ,且想要加入", - "»%s« added a note to a file shared with you" : "%s 在與您分享的檔案中加入了註解", - "Open »%s«" : "開啟 »%s«", - "Sharing %s failed, because this item is already shared with user %s" : "分享 %s 失敗,此項目已經與用戶 %s 分享", - "%1$s shared »%2$s« with you" : "%1$s 與您分享了 %2$s", - "%1$s shared »%2$s« with you." : "%1$s 與您分享了 %2$s", - "The username is already being used" : "這個用戶名稱已經有人使用了", - "Could not create user" : "無法建立用戶", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "用戶名稱當中只能包含下列字元:\"a-z\", \"A-Z\", \"0-9\",空格 和 \"_.@-'\"", - "A valid username must be provided" : "必須提供一個有效的用戶名", - "Username contains whitespace at the beginning or at the end" : "用戶名的開頭或結尾有空白", - "Username must not consist of dots only" : "用戶名稱不能只包含小數點", - "Username is invalid because files already exist for this user" : "用戶名稱無效,因為用戶的檔案已經存在", - "User disabled" : "用戶已停用", + "Organisation" : "機構", "File is currently busy, please try again later" : "檔案目前忙碌中,請稍候再試", "Cannot download file" : "無法下載檔案", - "Your data directory is readable by other users." : "您的資料目錄可以被其他用戶讀取。", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "請將該目錄權限設定為 0770 ,以免其他用戶讀取目錄列表", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "請確保資料目錄最上層有一個 \"。ocdata\" 檔案" + "Login is too long" : "帳號太長了" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/l10n/zh_TW.js b/lib/l10n/zh_TW.js index 6ea49ab6275..148234acef5 100644 --- a/lib/l10n/zh_TW.js +++ b/lib/l10n/zh_TW.js @@ -38,7 +38,7 @@ OC.L10N.register( "Server version %s or higher is required." : "需要伺服器版本 %s 或更高。", "Server version %s or lower is required." : "需要伺服器版本 %s 或更低。", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "登入帳號必須為管理員、子管理員或有可存取此設定的特殊權限的使用者", - "Your current IP address doesn’t allow you to perform admin actions" : "您目前的 IP 位置不允許您執行管理動作", + "Your current IP address doesn't allow you to perform admin actions" : "您目前的 IP 位置不允許您執行管理動作", "Logged in account must be an admin or sub admin" : "登入的帳號必須要是管理員或是子管理員", "Logged in account must be an admin" : "登入的帳號必須有管理員權限", "Wiping of device %s has started" : "已開始抹除裝置 %s", @@ -59,6 +59,11 @@ OC.L10N.register( "Avatar image is not square" : "頭像不是正方形", "Files" : "檔案", "View profile" : "檢視個人檔案", + "same time" : "相同時間", + "_%nh_::_%nh_" : ["%n小時"], + "_%nm_::_%nm_" : ["%n分鐘"], + "%s ahead" : "提早 %s", + "%s behind" : "落後 %s", "Local time: %s" : "本機時間:%s", "today" : "今天", "tomorrow" : "明天", @@ -81,7 +86,15 @@ OC.L10N.register( "seconds ago" : "幾秒前", "Empty file" : "空白檔案", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID 為 %s 的模組不存在。請在應用程式設定中啟用,或是聯絡系統管理員。", + "No file conversion providers available" : "沒有可用的檔案轉換提供者", + "File is too large to convert" : "檔案太大,無法轉換", + "Destination does not match conversion extension" : "目的地不符合轉換副檔名", + "Could not convert file" : "無法轉換檔案", + "Destination does not exist" : "目的地不存在", + "Destination is not creatable" : "無法建立目的地", "Dot files are not allowed" : "不允許小數點開頭的檔案", + "%1$s (renamed)" : "%1$s(已重新命名)", + "renamed file" : "已重新命名檔案", "\"%1$s\" is a forbidden file or folder name." : "「%1$s」是禁止的檔案或資料夾名稱。", "\"%1$s\" is a forbidden prefix for file or folder names." : "「%1$s」是禁止的檔案或資料夾名稱前綴。", "\"%1$s\" is not allowed inside a file or folder name." : "「%1$s」不允許出現在檔案或資料夾名稱中。", @@ -92,6 +105,13 @@ OC.L10N.register( "Invalid path" : "無效的路徑", "Failed to create file from template" : "無法從範本建立檔案", "Templates" : "範本", + "Storage %s cannot be moved" : "無法移動儲存空間 %s", + "Moving a share (%s) into a shared folder is not allowed" : "不允許將分享 (%s) 移動到共享資料夾中", + "Moving a storage (%s) into a shared folder is not allowed" : "不允許將儲存空間(%s) 移動到共享資料夾中", + "Moving a share (%s) into another share (%s) is not allowed" : "不允許將分享 (%s) 移動到其他分享 (%s) 中", + "Moving a share (%s) into another storage (%s) is not allowed" : "不允許將分享 (%s) 移動到其他儲存空間 (%s) 中", + "Moving a storage (%s) into a share (%s) is not allowed" : "不允許將儲存空間 (%s) 移動到分享 (%s) 中", + "Moving a storage (%s) into another storage (%s) is not allowed" : "不允許將儲存空間 (%s) 移動到其他儲存空間 (%s) 中", "Path contains invalid segments" : "路徑包含無效的部份", "Filename is a reserved word" : "檔案名稱是保留字", "Filename contains at least one invalid character" : "檔案名稱包含了至少一個無效的字元", @@ -124,7 +144,7 @@ OC.L10N.register( "About" : "關於", "Display name" : "顯示名稱", "Headline" : "重要經歷", - "Organisation" : "組織單位", + "Organization" : "組織", "Role" : "職位", "Pronouns" : "代名詞", "Unknown account" : "未知的帳號", @@ -138,7 +158,7 @@ OC.L10N.register( "Oracle connection could not be established" : "無法建立 Oracle 資料庫連線", "Oracle Login and/or password not valid" : "Oracle 帳號或密碼不正確", "PostgreSQL Login and/or password not valid" : "PostgreSQL 帳號或密碼無效", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "不支援 Mac OS X,而且 %s 在這個平台上無法正常運作。請自行衡量風險後使用! ", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "不支援 Mac OS X,%s 在此平台上無法正常運作。請自行承擔使用風險!", "For the best results, please consider using a GNU/Linux server instead." : "請考慮改用 GNU/Linux 伺服器以獲得最佳結果。", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "%s 站台似乎是在 32 位元 PHP 環境執行,且似乎設定了 php.ini 中的 open_basedir。這將導致超過 4 GB 的檔案出現問題,因此強烈建議不要這麼做。", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "請移除 php.ini 中的 open_basedir 設定,或是改用 64 位元的 PHP。", @@ -149,7 +169,6 @@ OC.L10N.register( "Sharing backend %s not found" : "找不到分享後端 %s", "Sharing backend for %s not found" : "找不到 %s 的分享後端", "%1$s shared %2$s with you" : "%1$s 與您分享了 %2$s", - "Click the button below to open it." : "點擊下方的按鈕將其打開。", "Open %s" : "開啟 %s", "%1$s via %2$s" : "%1$s 經由 %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s 與您分享了 %2$s,且想要新增:", @@ -169,6 +188,7 @@ OC.L10N.register( "You cannot share your root folder" : "您無法分享您的根資料夾", "You are not allowed to share %s" : "您不被允許分享 %s", "Valid permissions are required for sharing" : "分享需要有效的權限", + "File shares cannot have create or delete permissions" : "檔案分享不能有建立或刪除權限", "Cannot increase permissions of %s" : "無法增加 %s 的權能", "Shares need at least read permissions" : "分享需要至少讀取的權限", "Files cannot be shared with delete permissions" : "無法分享權限允許刪除的檔案", @@ -183,7 +203,7 @@ OC.L10N.register( "Path is already shared with this group" : "路徑已與此群組分享", "Link sharing is not allowed" : "不允許連結分享", "Public upload is not allowed" : "不允許公開上傳", - "Path contains files shared with you" : "路徑包含與您分享的檔案", + "You cannot share a folder that contains other shares" : "您無法分享包含其他分享的資料夾", "Sharing is disabled" : "已停用分享", "Sharing is disabled for you" : "您已停用分享", "Cannot share with the share owner" : "無法與分享擁有者分享", @@ -255,6 +275,7 @@ OC.L10N.register( "A valid Login must be provided" : "必須提供有效帳號", "Login contains whitespace at the beginning or at the end" : "帳號的開頭或結尾有空白", "Login must not consist of dots only" : "帳號不能只包含小數點", + "Username is too long" : "使用者名稱太長了", "Login is invalid because files already exist for this user" : "帳號無效,因為使用者的檔案已經存在", "Account disabled" : "帳號已停用", "Login canceled by app" : "應用程式取消了登入", @@ -311,7 +332,6 @@ OC.L10N.register( "The audio to transcribe" : "要轉錄的音訊", "Transcription" : "轉錄", "The transcribed text" : "已轉錄的文字", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "與 agent 聊天", "Chat message" : "聊天訊息", "A chat message to send to the agent." : "要傳送給 agent 的聊天訊息。", @@ -346,6 +366,11 @@ OC.L10N.register( "How many images to generate" : "要產生多少影像", "Output images" : "輸出影像", "The generated images" : "產生的影像", + "Generate speech" : "產生語音", + "Generate speech from a transcript" : "從轉錄稿產生語音", + "Write transcript that you want the assistant to generate speech from" : "寫下您想要小幫手產生語音的來源轉錄稿", + "Output speech" : "輸出語音", + "The generated speech" : "產生的語音", "Free text to text prompt" : "文字提示的自由文字", "Runs an arbitrary prompt through a language model that returns a reply" : "透過回傳回覆的語言模型執行任意提示", "Describe a task that you want the assistant to do or ask a question" : "描述您希望助理執行的任務或提出問題", @@ -384,6 +409,12 @@ OC.L10N.register( "Original text" : "原始文字", "The original text to generate a headline for" : "用來產生標題的原始文字", "The generated headline" : "產生的標題", + "Proofread" : "校對", + "Proofreads a text and lists corrections" : "校對文字並列出修正項目", + "Text" : "文字", + "The text to proofread" : "要校對的文字", + "Corrections" : "修正", + "The corrections that should be made in your text" : "您文字中應進行的修正", "Reformulate text" : "重新表述文字", "Takes a text and reformulates it" : "取得文字並將其重新表述", "Write a text that you want the assistant to reformulate" : "寫下您希望小幫手協助您重新表述的文字", @@ -419,41 +450,9 @@ OC.L10N.register( "Generate headline" : "生成標題", "Summarizes text by reducing its length without losing key information." : "寫成摘要,減少文字長度而不丟失關鍵資訊。", "Extracts topics from a text and outputs them separated by commas." : "從文字中取出涵蓋的主題並輸出,然後用逗號分隔。", - "Education Edition" : "教育版", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "登入使用者必須為管理員、子管理員,或有可存取此設定的特定權限使用者", - "Logged in user must be an admin or sub admin" : "登入的使用者必須要是管理員或是子管理員", - "Logged in user must be an admin" : "登入的使用者必須有管理員職權", - "File name is a reserved word" : "檔案名稱是保留字", - "File name contains at least one invalid character" : "檔案名稱含有不允許的字元", - "File name is too long" : "檔案名稱太長", - "Help" : "說明", - "Users" : "使用者", - "Unknown user" : "未知的使用者", - "Enter the database username and name for %s" : "輸入 %s 的資料庫使用者名稱及其名稱", - "Enter the database username for %s" : "輸入 %s 的資料庫使用者名稱", - "MySQL username and/or password not valid" : "MySQL 使用者名稱或密碼不正確", - "Oracle username and/or password not valid" : "Oracle 使用者名稱和/或密碼無效", - "PostgreSQL username and/or password not valid" : "PostgreSQL 使用者名稱和/或密碼無效", - "Set an admin username." : "設定管理員使用者名稱。", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s 與您分享了「%2$s 」,且想要新增:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s 與您分享了「%2$s」,且想要新增", - "»%s« added a note to a file shared with you" : "「%s」在與您分享的檔案中加入了備註", - "Open »%s«" : "開啟「%s」", - "Sharing %s failed, because this item is already shared with user %s" : "分享 %s 失敗,因為此項目已與使用者 %s 分享", - "%1$s shared »%2$s« with you" : "%1$s 與您分享了「%2$s」", - "%1$s shared »%2$s« with you." : "%1$s 與您分享了「%2$s」。", - "The username is already being used" : "這個使用者名稱已有人使用", - "Could not create user" : "無法建立使用者", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "使用者名稱僅允許以下字元:「a-z」、「A-Z」、「0-9」、空格與「_.@-'」", - "A valid username must be provided" : "必須提供有效的使用者名稱", - "Username contains whitespace at the beginning or at the end" : "使用者名稱的開頭或結尾有空白", - "Username must not consist of dots only" : "使用者名稱不能只包含小數點", - "Username is invalid because files already exist for this user" : "使用者名稱無效,因為使用者的檔案已存在", - "User disabled" : "使用者已停用", + "Organisation" : "組織單位", "File is currently busy, please try again later" : "檔案目前忙碌中,請稍候再試", "Cannot download file" : "無法下載檔案", - "Your data directory is readable by other users." : "您的 data 目錄可被其他使用者讀取。", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "請將該目錄權限設定為 0770 ,以免其他使用者讀取目錄列表。", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "請確保資料目錄最上層有一個「.ocdata」檔案。" + "Login is too long" : "帳號太長了" }, "nplurals=1; plural=0;"); diff --git a/lib/l10n/zh_TW.json b/lib/l10n/zh_TW.json index 48500089377..92d12233750 100644 --- a/lib/l10n/zh_TW.json +++ b/lib/l10n/zh_TW.json @@ -36,7 +36,7 @@ "Server version %s or higher is required." : "需要伺服器版本 %s 或更高。", "Server version %s or lower is required." : "需要伺服器版本 %s 或更低。", "Logged in account must be an admin, a sub admin or gotten special right to access this setting" : "登入帳號必須為管理員、子管理員或有可存取此設定的特殊權限的使用者", - "Your current IP address doesn’t allow you to perform admin actions" : "您目前的 IP 位置不允許您執行管理動作", + "Your current IP address doesn't allow you to perform admin actions" : "您目前的 IP 位置不允許您執行管理動作", "Logged in account must be an admin or sub admin" : "登入的帳號必須要是管理員或是子管理員", "Logged in account must be an admin" : "登入的帳號必須有管理員權限", "Wiping of device %s has started" : "已開始抹除裝置 %s", @@ -57,6 +57,11 @@ "Avatar image is not square" : "頭像不是正方形", "Files" : "檔案", "View profile" : "檢視個人檔案", + "same time" : "相同時間", + "_%nh_::_%nh_" : ["%n小時"], + "_%nm_::_%nm_" : ["%n分鐘"], + "%s ahead" : "提早 %s", + "%s behind" : "落後 %s", "Local time: %s" : "本機時間:%s", "today" : "今天", "tomorrow" : "明天", @@ -79,7 +84,15 @@ "seconds ago" : "幾秒前", "Empty file" : "空白檔案", "Module with ID: %s does not exist. Please enable it in your apps settings or contact your administrator." : "ID 為 %s 的模組不存在。請在應用程式設定中啟用,或是聯絡系統管理員。", + "No file conversion providers available" : "沒有可用的檔案轉換提供者", + "File is too large to convert" : "檔案太大,無法轉換", + "Destination does not match conversion extension" : "目的地不符合轉換副檔名", + "Could not convert file" : "無法轉換檔案", + "Destination does not exist" : "目的地不存在", + "Destination is not creatable" : "無法建立目的地", "Dot files are not allowed" : "不允許小數點開頭的檔案", + "%1$s (renamed)" : "%1$s(已重新命名)", + "renamed file" : "已重新命名檔案", "\"%1$s\" is a forbidden file or folder name." : "「%1$s」是禁止的檔案或資料夾名稱。", "\"%1$s\" is a forbidden prefix for file or folder names." : "「%1$s」是禁止的檔案或資料夾名稱前綴。", "\"%1$s\" is not allowed inside a file or folder name." : "「%1$s」不允許出現在檔案或資料夾名稱中。", @@ -90,6 +103,13 @@ "Invalid path" : "無效的路徑", "Failed to create file from template" : "無法從範本建立檔案", "Templates" : "範本", + "Storage %s cannot be moved" : "無法移動儲存空間 %s", + "Moving a share (%s) into a shared folder is not allowed" : "不允許將分享 (%s) 移動到共享資料夾中", + "Moving a storage (%s) into a shared folder is not allowed" : "不允許將儲存空間(%s) 移動到共享資料夾中", + "Moving a share (%s) into another share (%s) is not allowed" : "不允許將分享 (%s) 移動到其他分享 (%s) 中", + "Moving a share (%s) into another storage (%s) is not allowed" : "不允許將分享 (%s) 移動到其他儲存空間 (%s) 中", + "Moving a storage (%s) into a share (%s) is not allowed" : "不允許將儲存空間 (%s) 移動到分享 (%s) 中", + "Moving a storage (%s) into another storage (%s) is not allowed" : "不允許將儲存空間 (%s) 移動到其他儲存空間 (%s) 中", "Path contains invalid segments" : "路徑包含無效的部份", "Filename is a reserved word" : "檔案名稱是保留字", "Filename contains at least one invalid character" : "檔案名稱包含了至少一個無效的字元", @@ -122,7 +142,7 @@ "About" : "關於", "Display name" : "顯示名稱", "Headline" : "重要經歷", - "Organisation" : "組織單位", + "Organization" : "組織", "Role" : "職位", "Pronouns" : "代名詞", "Unknown account" : "未知的帳號", @@ -136,7 +156,7 @@ "Oracle connection could not be established" : "無法建立 Oracle 資料庫連線", "Oracle Login and/or password not valid" : "Oracle 帳號或密碼不正確", "PostgreSQL Login and/or password not valid" : "PostgreSQL 帳號或密碼無效", - "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk! " : "不支援 Mac OS X,而且 %s 在這個平台上無法正常運作。請自行衡量風險後使用! ", + "Mac OS X is not supported and %s will not work properly on this platform. Use it at your own risk!" : "不支援 Mac OS X,%s 在此平台上無法正常運作。請自行承擔使用風險!", "For the best results, please consider using a GNU/Linux server instead." : "請考慮改用 GNU/Linux 伺服器以獲得最佳結果。", "It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. This will lead to problems with files over 4 GB and is highly discouraged." : "%s 站台似乎是在 32 位元 PHP 環境執行,且似乎設定了 php.ini 中的 open_basedir。這將導致超過 4 GB 的檔案出現問題,因此強烈建議不要這麼做。", "Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP." : "請移除 php.ini 中的 open_basedir 設定,或是改用 64 位元的 PHP。", @@ -147,7 +167,6 @@ "Sharing backend %s not found" : "找不到分享後端 %s", "Sharing backend for %s not found" : "找不到 %s 的分享後端", "%1$s shared %2$s with you" : "%1$s 與您分享了 %2$s", - "Click the button below to open it." : "點擊下方的按鈕將其打開。", "Open %s" : "開啟 %s", "%1$s via %2$s" : "%1$s 經由 %2$s", "%1$s shared %2$s with you and wants to add:" : "%1$s 與您分享了 %2$s,且想要新增:", @@ -167,6 +186,7 @@ "You cannot share your root folder" : "您無法分享您的根資料夾", "You are not allowed to share %s" : "您不被允許分享 %s", "Valid permissions are required for sharing" : "分享需要有效的權限", + "File shares cannot have create or delete permissions" : "檔案分享不能有建立或刪除權限", "Cannot increase permissions of %s" : "無法增加 %s 的權能", "Shares need at least read permissions" : "分享需要至少讀取的權限", "Files cannot be shared with delete permissions" : "無法分享權限允許刪除的檔案", @@ -181,7 +201,7 @@ "Path is already shared with this group" : "路徑已與此群組分享", "Link sharing is not allowed" : "不允許連結分享", "Public upload is not allowed" : "不允許公開上傳", - "Path contains files shared with you" : "路徑包含與您分享的檔案", + "You cannot share a folder that contains other shares" : "您無法分享包含其他分享的資料夾", "Sharing is disabled" : "已停用分享", "Sharing is disabled for you" : "您已停用分享", "Cannot share with the share owner" : "無法與分享擁有者分享", @@ -253,6 +273,7 @@ "A valid Login must be provided" : "必須提供有效帳號", "Login contains whitespace at the beginning or at the end" : "帳號的開頭或結尾有空白", "Login must not consist of dots only" : "帳號不能只包含小數點", + "Username is too long" : "使用者名稱太長了", "Login is invalid because files already exist for this user" : "帳號無效,因為使用者的檔案已經存在", "Account disabled" : "帳號已停用", "Login canceled by app" : "應用程式取消了登入", @@ -309,7 +330,6 @@ "The audio to transcribe" : "要轉錄的音訊", "Transcription" : "轉錄", "The transcribed text" : "已轉錄的文字", - "ContextAgent" : "ContextAgent", "Chat with an agent" : "與 agent 聊天", "Chat message" : "聊天訊息", "A chat message to send to the agent." : "要傳送給 agent 的聊天訊息。", @@ -344,6 +364,11 @@ "How many images to generate" : "要產生多少影像", "Output images" : "輸出影像", "The generated images" : "產生的影像", + "Generate speech" : "產生語音", + "Generate speech from a transcript" : "從轉錄稿產生語音", + "Write transcript that you want the assistant to generate speech from" : "寫下您想要小幫手產生語音的來源轉錄稿", + "Output speech" : "輸出語音", + "The generated speech" : "產生的語音", "Free text to text prompt" : "文字提示的自由文字", "Runs an arbitrary prompt through a language model that returns a reply" : "透過回傳回覆的語言模型執行任意提示", "Describe a task that you want the assistant to do or ask a question" : "描述您希望助理執行的任務或提出問題", @@ -382,6 +407,12 @@ "Original text" : "原始文字", "The original text to generate a headline for" : "用來產生標題的原始文字", "The generated headline" : "產生的標題", + "Proofread" : "校對", + "Proofreads a text and lists corrections" : "校對文字並列出修正項目", + "Text" : "文字", + "The text to proofread" : "要校對的文字", + "Corrections" : "修正", + "The corrections that should be made in your text" : "您文字中應進行的修正", "Reformulate text" : "重新表述文字", "Takes a text and reformulates it" : "取得文字並將其重新表述", "Write a text that you want the assistant to reformulate" : "寫下您希望小幫手協助您重新表述的文字", @@ -417,41 +448,9 @@ "Generate headline" : "生成標題", "Summarizes text by reducing its length without losing key information." : "寫成摘要,減少文字長度而不丟失關鍵資訊。", "Extracts topics from a text and outputs them separated by commas." : "從文字中取出涵蓋的主題並輸出,然後用逗號分隔。", - "Education Edition" : "教育版", - "Logged in user must be an admin, a sub admin or gotten special right to access this setting" : "登入使用者必須為管理員、子管理員,或有可存取此設定的特定權限使用者", - "Logged in user must be an admin or sub admin" : "登入的使用者必須要是管理員或是子管理員", - "Logged in user must be an admin" : "登入的使用者必須有管理員職權", - "File name is a reserved word" : "檔案名稱是保留字", - "File name contains at least one invalid character" : "檔案名稱含有不允許的字元", - "File name is too long" : "檔案名稱太長", - "Help" : "說明", - "Users" : "使用者", - "Unknown user" : "未知的使用者", - "Enter the database username and name for %s" : "輸入 %s 的資料庫使用者名稱及其名稱", - "Enter the database username for %s" : "輸入 %s 的資料庫使用者名稱", - "MySQL username and/or password not valid" : "MySQL 使用者名稱或密碼不正確", - "Oracle username and/or password not valid" : "Oracle 使用者名稱和/或密碼無效", - "PostgreSQL username and/or password not valid" : "PostgreSQL 使用者名稱和/或密碼無效", - "Set an admin username." : "設定管理員使用者名稱。", - "%1$s shared »%2$s« with you and wants to add:" : "%1$s 與您分享了「%2$s 」,且想要新增:", - "%1$s shared »%2$s« with you and wants to add" : "%1$s 與您分享了「%2$s」,且想要新增", - "»%s« added a note to a file shared with you" : "「%s」在與您分享的檔案中加入了備註", - "Open »%s«" : "開啟「%s」", - "Sharing %s failed, because this item is already shared with user %s" : "分享 %s 失敗,因為此項目已與使用者 %s 分享", - "%1$s shared »%2$s« with you" : "%1$s 與您分享了「%2$s」", - "%1$s shared »%2$s« with you." : "%1$s 與您分享了「%2$s」。", - "The username is already being used" : "這個使用者名稱已有人使用", - "Could not create user" : "無法建立使用者", - "Only the following characters are allowed in a username: \"a-z\", \"A-Z\", \"0-9\", spaces and \"_.@-'\"" : "使用者名稱僅允許以下字元:「a-z」、「A-Z」、「0-9」、空格與「_.@-'」", - "A valid username must be provided" : "必須提供有效的使用者名稱", - "Username contains whitespace at the beginning or at the end" : "使用者名稱的開頭或結尾有空白", - "Username must not consist of dots only" : "使用者名稱不能只包含小數點", - "Username is invalid because files already exist for this user" : "使用者名稱無效,因為使用者的檔案已存在", - "User disabled" : "使用者已停用", + "Organisation" : "組織單位", "File is currently busy, please try again later" : "檔案目前忙碌中,請稍候再試", "Cannot download file" : "無法下載檔案", - "Your data directory is readable by other users." : "您的 data 目錄可被其他使用者讀取。", - "Please change the permissions to 0770 so that the directory cannot be listed by other users." : "請將該目錄權限設定為 0770 ,以免其他使用者讀取目錄列表。", - "Ensure there is a file called \".ocdata\" in the root of the data directory." : "請確保資料目錄最上層有一個「.ocdata」檔案。" + "Login is too long" : "帳號太長了" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/private/Accounts/AccountManager.php b/lib/private/Accounts/AccountManager.php index 0d091786cd6..e8b67311636 100644 --- a/lib/private/Accounts/AccountManager.php +++ b/lib/private/Accounts/AccountManager.php @@ -23,6 +23,7 @@ use OCP\Cache\CappedMemoryCache; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Defaults; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Http\Client\IClientService; use OCP\IConfig; use OCP\IDBConnection; use OCP\IL10N; @@ -93,51 +94,12 @@ class AccountManager implements IAccountManager { private IURLGenerator $urlGenerator, private ICrypto $crypto, private IPhoneNumberUtil $phoneNumberUtil, + private IClientService $clientService, ) { $this->internalCache = new CappedMemoryCache(); } /** - * @return string Provided phone number in E.164 format when it was a valid number - * @throws InvalidArgumentException When the phone number was invalid or no default region is set and the number doesn't start with a country code - */ - protected function parsePhoneNumber(string $input): string { - $defaultRegion = $this->config->getSystemValueString('default_phone_region', ''); - - if ($defaultRegion === '') { - // When no default region is set, only +49… numbers are valid - if (!str_starts_with($input, '+')) { - throw new InvalidArgumentException(self::PROPERTY_PHONE); - } - - $defaultRegion = 'EN'; - } - - $phoneNumber = $this->phoneNumberUtil->convertToStandardFormat($input, $defaultRegion); - if ($phoneNumber !== null) { - return $phoneNumber; - } - - throw new InvalidArgumentException(self::PROPERTY_PHONE); - } - - /** - * @throws InvalidArgumentException When the website did not have http(s) as protocol or the host name was empty - */ - protected function parseWebsite(string $input): string { - $parts = parse_url($input); - if (!isset($parts['scheme']) || ($parts['scheme'] !== 'https' && $parts['scheme'] !== 'http')) { - throw new InvalidArgumentException(self::PROPERTY_WEBSITE); - } - - if (!isset($parts['host']) || $parts['host'] === '') { - throw new InvalidArgumentException(self::PROPERTY_WEBSITE); - } - - return $input; - } - - /** * @param IAccountProperty[] $properties */ protected function testValueLengths(array $properties, bool $throwOnData = false): void { @@ -169,45 +131,7 @@ class AccountManager implements IAccountManager { $property->setScope(self::SCOPE_LOCAL); } } else { - // migrate scope values to the new format - // invalid scopes are mapped to a default value - $property->setScope(AccountProperty::mapScopeToV2($property->getScope())); - } - } - - protected function sanitizePhoneNumberValue(IAccountProperty $property, bool $throwOnData = false): void { - if ($property->getName() !== self::PROPERTY_PHONE) { - if ($throwOnData) { - throw new InvalidArgumentException(sprintf('sanitizePhoneNumberValue can only sanitize phone numbers, %s given', $property->getName())); - } - return; - } - if ($property->getValue() === '') { - return; - } - try { - $property->setValue($this->parsePhoneNumber($property->getValue())); - } catch (InvalidArgumentException $e) { - if ($throwOnData) { - throw $e; - } - $property->setValue(''); - } - } - - protected function sanitizeWebsite(IAccountProperty $property, bool $throwOnData = false): void { - if ($property->getName() !== self::PROPERTY_WEBSITE) { - if ($throwOnData) { - throw new InvalidArgumentException(sprintf('sanitizeWebsite can only sanitize web domains, %s given', $property->getName())); - } - } - try { - $property->setValue($this->parseWebsite($property->getValue())); - } catch (InvalidArgumentException $e) { - if ($throwOnData) { - throw $e; - } - $property->setValue(''); + $property->setScope($property->getScope()); } } @@ -735,18 +659,139 @@ class AccountManager implements IAccountManager { return $account; } + /** + * Converts value (phone number) in E.164 format when it was a valid number + * @throws InvalidArgumentException When the phone number was invalid or no default region is set and the number doesn't start with a country code + */ + protected function sanitizePropertyPhoneNumber(IAccountProperty $property): void { + $defaultRegion = $this->config->getSystemValueString('default_phone_region', ''); + + if ($defaultRegion === '') { + // When no default region is set, only +49… numbers are valid + if (!str_starts_with($property->getValue(), '+')) { + throw new InvalidArgumentException(self::PROPERTY_PHONE); + } + + $defaultRegion = 'EN'; + } + + $phoneNumber = $this->phoneNumberUtil->convertToStandardFormat($property->getValue(), $defaultRegion); + if ($phoneNumber === null) { + throw new InvalidArgumentException(self::PROPERTY_PHONE); + } + $property->setValue($phoneNumber); + } + + /** + * @throws InvalidArgumentException When the website did not have http(s) as protocol or the host name was empty + */ + private function sanitizePropertyWebsite(IAccountProperty $property): void { + $parts = parse_url($property->getValue()); + if (!isset($parts['scheme']) || ($parts['scheme'] !== 'https' && $parts['scheme'] !== 'http')) { + throw new InvalidArgumentException(self::PROPERTY_WEBSITE); + } + + if (!isset($parts['host']) || $parts['host'] === '') { + throw new InvalidArgumentException(self::PROPERTY_WEBSITE); + } + } + + /** + * @throws InvalidArgumentException If the property value is not a valid user handle according to X's rules + */ + private function sanitizePropertyTwitter(IAccountProperty $property): void { + if ($property->getName() === self::PROPERTY_TWITTER) { + $matches = []; + // twitter handles only contain alpha numeric characters and the underscore and must not be longer than 15 characters + if (preg_match('/^@?([a-zA-Z0-9_]{2,15})$/', $property->getValue(), $matches) !== 1) { + throw new InvalidArgumentException(self::PROPERTY_TWITTER); + } + + // drop the leading @ if any to make it the valid handle + $property->setValue($matches[1]); + + } + } + + /** + * @throws InvalidArgumentException If the property value is not a valid fediverse handle (username@instance where instance is a valid domain) + */ + private function sanitizePropertyFediverse(IAccountProperty $property): void { + if ($property->getName() === self::PROPERTY_FEDIVERSE) { + $matches = []; + if (preg_match('/^@?([^@\s\/\\\]+)@([^\s\/\\\]+)$/', trim($property->getValue()), $matches) !== 1) { + throw new InvalidArgumentException(self::PROPERTY_FEDIVERSE); + } + + [, $username, $instance] = $matches; + $validated = filter_var($instance, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME); + if ($validated !== $instance) { + throw new InvalidArgumentException(self::PROPERTY_FEDIVERSE); + } + + if ($this->config->getSystemValueBool('has_internet_connection', true)) { + $client = $this->clientService->newClient(); + + try { + // try the public account lookup API of mastodon + $response = $client->get("https://{$instance}/api/v1/accounts/lookup?acct={$username}@{$instance}"); + // should be a json response with account information + $data = $response->getBody(); + if (is_resource($data)) { + $data = stream_get_contents($data); + } + $decoded = json_decode($data, true); + // ensure the username is the same the user passed + // in this case we can assume this is a valid fediverse server and account + if (!is_array($decoded) || ($decoded['username'] ?? '') !== $username) { + throw new InvalidArgumentException(); + } + } catch (InvalidArgumentException) { + throw new InvalidArgumentException(self::PROPERTY_FEDIVERSE); + } catch (\Exception $error) { + $this->logger->error('Could not verify fediverse account', ['exception' => $error, 'instance' => $instance]); + throw new InvalidArgumentException(self::PROPERTY_FEDIVERSE); + } + } + + $property->setValue("$username@$instance"); + } + } + public function updateAccount(IAccount $account): void { $this->testValueLengths(iterator_to_array($account->getAllProperties()), true); try { $property = $account->getProperty(self::PROPERTY_PHONE); - $this->sanitizePhoneNumberValue($property); + if ($property->getValue() !== '') { + $this->sanitizePropertyPhoneNumber($property); + } } catch (PropertyDoesNotExistException $e) { // valid case, nothing to do } try { $property = $account->getProperty(self::PROPERTY_WEBSITE); - $this->sanitizeWebsite($property); + if ($property->getValue() !== '') { + $this->sanitizePropertyWebsite($property); + } + } catch (PropertyDoesNotExistException $e) { + // valid case, nothing to do + } + + try { + $property = $account->getProperty(self::PROPERTY_TWITTER); + if ($property->getValue() !== '') { + $this->sanitizePropertyTwitter($property); + } + } catch (PropertyDoesNotExistException $e) { + // valid case, nothing to do + } + + try { + $property = $account->getProperty(self::PROPERTY_FEDIVERSE); + if ($property->getValue() !== '') { + $this->sanitizePropertyFediverse($property); + } } catch (PropertyDoesNotExistException $e) { // valid case, nothing to do } diff --git a/lib/private/Accounts/AccountProperty.php b/lib/private/Accounts/AccountProperty.php index 0c4ad568709..3a89e9bbc7a 100644 --- a/lib/private/Accounts/AccountProperty.php +++ b/lib/private/Accounts/AccountProperty.php @@ -55,16 +55,11 @@ class AccountProperty implements IAccountProperty { * @since 15.0.0 */ public function setScope(string $scope): IAccountProperty { - $newScope = $this->mapScopeToV2($scope); - if (!in_array($newScope, [ - IAccountManager::SCOPE_LOCAL, - IAccountManager::SCOPE_FEDERATED, - IAccountManager::SCOPE_PRIVATE, - IAccountManager::SCOPE_PUBLISHED - ])) { + if (!in_array($scope, IAccountManager::ALLOWED_SCOPES, )) { throw new InvalidArgumentException('Invalid scope'); } - $this->scope = $newScope; + /** @var IAccountManager::SCOPE_* $scope */ + $this->scope = $scope; return $this; } @@ -105,19 +100,6 @@ class AccountProperty implements IAccountProperty { return $this->scope; } - public static function mapScopeToV2(string $scope): string { - if (str_starts_with($scope, 'v2-')) { - return $scope; - } - - return match ($scope) { - IAccountManager::VISIBILITY_PRIVATE, '' => IAccountManager::SCOPE_LOCAL, - IAccountManager::VISIBILITY_CONTACTS_ONLY => IAccountManager::SCOPE_FEDERATED, - IAccountManager::VISIBILITY_PUBLIC => IAccountManager::SCOPE_PUBLISHED, - default => $scope, - }; - } - /** * Get the verification status of a property * diff --git a/lib/private/Accounts/Hooks.php b/lib/private/Accounts/Hooks.php index 0235879e8e7..12f2b4777f8 100644 --- a/lib/private/Accounts/Hooks.php +++ b/lib/private/Accounts/Hooks.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Activity/Event.php b/lib/private/Activity/Event.php index 810af5c0612..39cdc12b3fb 100644 --- a/lib/private/Activity/Event.php +++ b/lib/private/Activity/Event.php @@ -34,7 +34,7 @@ class Event implements IEvent { protected $subjectParsed = ''; /** @var string */ protected $subjectRich = ''; - /** @var array */ + /** @var array<string, array<string, string>> */ protected $subjectRichParameters = []; /** @var string */ protected $message = ''; @@ -44,7 +44,7 @@ class Event implements IEvent { protected $messageParsed = ''; /** @var string */ protected $messageRich = ''; - /** @var array */ + /** @var array<string, array<string, string>> */ protected $messageRichParameters = []; /** @var string */ protected $objectType = ''; @@ -415,8 +415,7 @@ class Event implements IEvent { public function isValid(): bool { return $this->isValidCommon() - && - $this->getSubject() !== '' + && $this->getSubject() !== '' ; } @@ -443,20 +442,16 @@ class Event implements IEvent { return $this->isValidCommon() - && - $this->getParsedSubject() !== '' + && $this->getParsedSubject() !== '' ; } protected function isValidCommon(): bool { return $this->getApp() !== '' - && - $this->getType() !== '' - && - $this->getAffectedUser() !== '' - && - $this->getTimestamp() !== 0 + && $this->getType() !== '' + && $this->getAffectedUser() !== '' + && $this->getTimestamp() !== 0 /** * Disabled for BC with old activities * && diff --git a/lib/private/Activity/EventMerger.php b/lib/private/Activity/EventMerger.php index 504f9088f24..0e7d318103a 100644 --- a/lib/private/Activity/EventMerger.php +++ b/lib/private/Activity/EventMerger.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Activity/Manager.php b/lib/private/Activity/Manager.php index 5c306fe6399..4e10f8a0c1a 100644 --- a/lib/private/Activity/Manager.php +++ b/lib/private/Activity/Manager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/AllConfig.php b/lib/private/AllConfig.php index 72af6c960a5..8a6bb5a4723 100644 --- a/lib/private/AllConfig.php +++ b/lib/private/AllConfig.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/App/AppManager.php b/lib/private/App/AppManager.php index fe5d3e2faeb..1911bce12bf 100644 --- a/lib/private/App/AppManager.php +++ b/lib/private/App/AppManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -8,7 +9,7 @@ namespace OC\App; use OC\AppConfig; use OC\AppFramework\Bootstrap\Coordinator; -use OC\ServerNotAvailableException; +use OC\Config\ConfigManager; use OCP\Activity\IManager as IActivityManager; use OCP\App\AppPathNotFoundException; use OCP\App\Events\AppDisableEvent; @@ -19,6 +20,7 @@ use OCP\Collaboration\AutoComplete\IManager as IAutoCompleteManager; use OCP\Collaboration\Collaborators\ISearch as ICollaboratorSearch; use OCP\Diagnostics\IEventLogger; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IAppConfig; use OCP\ICacheFactory; use OCP\IConfig; use OCP\IGroup; @@ -27,6 +29,8 @@ use OCP\INavigationManager; use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserSession; +use OCP\Server; +use OCP\ServerVersion; use OCP\Settings\IManager as ISettingsManager; use Psr\Log\LoggerInterface; @@ -44,7 +48,7 @@ class AppManager implements IAppManager { ]; /** @var string[] $appId => $enabled */ - private array $installedAppsCache = []; + private array $enabledAppsCache = []; /** @var string[]|null */ private ?array $shippedApps = null; @@ -80,12 +84,14 @@ class AppManager implements IAppManager { private ICacheFactory $memCacheFactory, private IEventDispatcher $dispatcher, private LoggerInterface $logger, + private ServerVersion $serverVersion, + private ConfigManager $configManager, ) { } private function getNavigationManager(): INavigationManager { if ($this->navigationManager === null) { - $this->navigationManager = \OCP\Server::get(INavigationManager::class); + $this->navigationManager = Server::get(INavigationManager::class); } return $this->navigationManager; } @@ -111,7 +117,7 @@ class AppManager implements IAppManager { if (!$this->config->getSystemValueBool('installed', false)) { throw new \Exception('Nextcloud is not installed yet, AppConfig is not available'); } - $this->appConfig = \OCP\Server::get(AppConfig::class); + $this->appConfig = Server::get(AppConfig::class); return $this->appConfig; } @@ -122,37 +128,49 @@ class AppManager implements IAppManager { if (!$this->config->getSystemValueBool('installed', false)) { throw new \Exception('Nextcloud is not installed yet, AppConfig is not available'); } - $this->urlGenerator = \OCP\Server::get(IURLGenerator::class); + $this->urlGenerator = Server::get(IURLGenerator::class); return $this->urlGenerator; } /** - * @return string[] $appId => $enabled + * For all enabled apps, return the value of their 'enabled' config key. + * + * @return array<string,string> appId => enabled (may be 'yes', or a json encoded list of group ids) */ - private function getInstalledAppsValues(): array { - if (!$this->installedAppsCache) { - $values = $this->getAppConfig()->getValues(false, 'enabled'); + private function getEnabledAppsValues(): array { + if (!$this->enabledAppsCache) { + /** @var array<string,string> */ + $values = $this->getAppConfig()->searchValues('enabled', false, IAppConfig::VALUE_STRING); $alwaysEnabledApps = $this->getAlwaysEnabledApps(); foreach ($alwaysEnabledApps as $appId) { $values[$appId] = 'yes'; } - $this->installedAppsCache = array_filter($values, function ($value) { + $this->enabledAppsCache = array_filter($values, function ($value) { return $value !== 'no'; }); - ksort($this->installedAppsCache); + ksort($this->enabledAppsCache); } - return $this->installedAppsCache; + return $this->enabledAppsCache; } /** - * List all installed apps + * Deprecated alias * * @return string[] */ public function getInstalledApps() { - return array_keys($this->getInstalledAppsValues()); + return $this->getEnabledApps(); + } + + /** + * List all enabled apps, either for everyone or for some groups + * + * @return list<string> + */ + public function getEnabledApps(): array { + return array_keys($this->getEnabledAppsValues()); } /** @@ -173,9 +191,9 @@ class AppManager implements IAppManager { if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { if ( - $file[0] != '.' && - is_dir($apps_dir['path'] . '/' . $file) && - is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml') + $file[0] != '.' + && is_dir($apps_dir['path'] . '/' . $file) + && is_file($apps_dir['path'] . '/' . $file . '/appinfo/info.xml') ) { $apps[] = $file; } @@ -190,10 +208,10 @@ class AppManager implements IAppManager { * List all apps enabled for a user * * @param \OCP\IUser $user - * @return string[] + * @return list<string> */ public function getEnabledAppsForUser(IUser $user) { - $apps = $this->getInstalledAppsValues(); + $apps = $this->getEnabledAppsValues(); $appsForUser = array_filter($apps, function ($enabled) use ($user) { return $this->checkAppForUser($enabled, $user); }); @@ -201,7 +219,7 @@ class AppManager implements IAppManager { } public function getEnabledAppsForGroup(IGroup $group): array { - $apps = $this->getInstalledAppsValues(); + $apps = $this->getEnabledAppsValues(); $appsForGroups = array_filter($apps, function ($enabled) use ($group) { return $this->checkAppForGroups($enabled, $group); }); @@ -238,7 +256,7 @@ class AppManager implements IAppManager { } } - // prevent app.php from printing output + // prevent app loading from printing output ob_start(); foreach ($apps as $app) { if (!$this->isAppLoaded($app) && ($types === [] || $this->isType($app, $types))) { @@ -301,7 +319,7 @@ class AppManager implements IAppManager { } public function getAppRestriction(string $appId): array { - $values = $this->getInstalledAppsValues(); + $values = $this->getEnabledAppsValues(); if (!isset($values[$appId])) { return []; @@ -327,9 +345,9 @@ class AppManager implements IAppManager { if ($user === null) { $user = $this->userSession->getUser(); } - $installedApps = $this->getInstalledAppsValues(); - if (isset($installedApps[$appId])) { - return $this->checkAppForUser($installedApps[$appId], $user); + $enabledAppsValues = $this->getEnabledAppsValues(); + if (isset($enabledAppsValues[$appId])) { + return $this->checkAppForUser($enabledAppsValues[$appId], $user); } else { return false; } @@ -393,12 +411,14 @@ class AppManager implements IAppManager { * Notice: This actually checks if the app is enabled and not only if it is installed. * * @param string $appId - * @param IGroup[]|String[] $groups - * @return bool */ - public function isInstalled($appId) { - $installedApps = $this->getInstalledAppsValues(); - return isset($installedApps[$appId]); + public function isInstalled($appId): bool { + return $this->isEnabledForAnyone($appId); + } + + public function isEnabledForAnyone(string $appId): bool { + $enabledAppsValues = $this->getEnabledAppsValues(); + return isset($enabledAppsValues[$appId]); } /** @@ -437,43 +457,13 @@ class AppManager implements IAppManager { // in case someone calls loadApp() directly \OC_App::registerAutoloading($app, $appPath); - /** @var Coordinator $coordinator */ - $coordinator = \OC::$server->get(Coordinator::class); - $isBootable = $coordinator->isBootable($app); - - $hasAppPhpFile = is_file($appPath . '/appinfo/app.php'); - - if ($isBootable && $hasAppPhpFile) { - $this->logger->error('/appinfo/app.php is not loaded when \OCP\AppFramework\Bootstrap\IBootstrap on the application class is used. Migrate everything from app.php to the Application class.', [ - 'app' => $app, - ]); - } elseif ($hasAppPhpFile) { - $eventLogger->start("bootstrap:load_app:$app:app.php", "Load legacy app.php app $app"); - $this->logger->debug('/appinfo/app.php is deprecated, use \OCP\AppFramework\Bootstrap\IBootstrap on the application class instead.', [ + if (is_file($appPath . '/appinfo/app.php')) { + $this->logger->error('/appinfo/app.php is not supported anymore, use \OCP\AppFramework\Bootstrap\IBootstrap on the application class instead.', [ 'app' => $app, ]); - try { - self::requireAppFile($appPath); - } catch (\Throwable $ex) { - if ($ex instanceof ServerNotAvailableException) { - throw $ex; - } - if (!$this->isShipped($app) && !$this->isType($app, ['authentication'])) { - $this->logger->error("App $app threw an error during app.php load and will be disabled: " . $ex->getMessage(), [ - 'exception' => $ex, - ]); - - // Only disable apps which are not shipped and that are not authentication apps - $this->disableApp($app, true); - } else { - $this->logger->error("App $app threw an error during app.php load: " . $ex->getMessage(), [ - 'exception' => $ex, - ]); - } - } - $eventLogger->end("bootstrap:load_app:$app:app.php"); } + $coordinator = Server::get(Coordinator::class); $coordinator->bootApp($app); $eventLogger->start("bootstrap:load_app:$app:info", "Load info.xml for $app and register any services defined in it"); @@ -523,8 +513,8 @@ class AppManager implements IAppManager { if (!empty($info['collaboration']['plugins'])) { // deal with one or many plugin entries - $plugins = isset($info['collaboration']['plugins']['plugin']['@value']) ? - [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin']; + $plugins = isset($info['collaboration']['plugins']['plugin']['@value']) + ? [$info['collaboration']['plugins']['plugin']] : $info['collaboration']['plugins']['plugin']; $collaboratorSearch = null; $autoCompleteManager = null; foreach ($plugins as $plugin) { @@ -545,6 +535,7 @@ class AppManager implements IAppManager { $eventLogger->end("bootstrap:load_app:$app"); } + /** * Check if an app is loaded * @param string $app app id @@ -555,38 +546,34 @@ class AppManager implements IAppManager { } /** - * Load app.php from the given app - * - * @param string $app app name - * @throws \Error - */ - private static function requireAppFile(string $app): void { - // encapsulated here to avoid variable scope conflicts - require_once $app . '/appinfo/app.php'; - } - - /** * Enable an app for every user * * @param string $appId * @param bool $forceEnable * @throws AppPathNotFoundException + * @throws \InvalidArgumentException if the application is not installed yet */ public function enableApp(string $appId, bool $forceEnable = false): void { // Check if app exists $this->getAppPath($appId); + if ($this->config->getAppValue($appId, 'installed_version', '') === '') { + throw new \InvalidArgumentException("$appId is not installed, cannot be enabled."); + } + if ($forceEnable) { $this->overwriteNextcloudRequirement($appId); } - $this->installedAppsCache[$appId] = 'yes'; + $this->enabledAppsCache[$appId] = 'yes'; $this->getAppConfig()->setValue($appId, 'enabled', 'yes'); $this->dispatcher->dispatchTyped(new AppEnableEvent($appId)); $this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE, new ManagerEvent( ManagerEvent::EVENT_APP_ENABLE, $appId )); $this->clearAppsCache(); + + $this->configManager->migrateConfigLexiconKeys($appId); } /** @@ -622,6 +609,10 @@ class AppManager implements IAppManager { throw new \InvalidArgumentException("$appId can't be enabled for groups."); } + if ($this->config->getAppValue($appId, 'installed_version', '') === '') { + throw new \InvalidArgumentException("$appId is not installed, cannot be enabled."); + } + if ($forceEnable) { $this->overwriteNextcloudRequirement($appId); } @@ -634,13 +625,15 @@ class AppManager implements IAppManager { : $group; }, $groups); - $this->installedAppsCache[$appId] = json_encode($groupIds); + $this->enabledAppsCache[$appId] = json_encode($groupIds); $this->getAppConfig()->setValue($appId, 'enabled', json_encode($groupIds)); $this->dispatcher->dispatchTyped(new AppEnableEvent($appId, $groupIds)); $this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, new ManagerEvent( ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, $appId, $groups )); $this->clearAppsCache(); + + $this->configManager->migrateConfigLexiconKeys($appId); } /** @@ -663,7 +656,7 @@ class AppManager implements IAppManager { $this->autoDisabledApps[$appId] = $previousSetting; } - unset($this->installedAppsCache[$appId]); + unset($this->enabledAppsCache[$appId]); $this->getAppConfig()->setValue($appId, 'enabled', 'no'); // run uninstall steps @@ -724,7 +717,7 @@ class AppManager implements IAppManager { */ public function getAppsNeedingUpgrade($version) { $appsToUpgrade = []; - $apps = $this->getInstalledApps(); + $apps = $this->getEnabledApps(); foreach ($apps as $appId) { $appInfo = $this->getAppInfo($appId); $appDbVersion = $this->getAppConfig()->getValue($appId, 'installed_version'); @@ -786,13 +779,26 @@ class AppManager implements IAppManager { public function getAppVersion(string $appId, bool $useCache = true): string { if (!$useCache || !isset($this->appVersions[$appId])) { - $appInfo = $this->getAppInfo($appId); - $this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0'; + if ($appId === 'core') { + $this->appVersions[$appId] = $this->serverVersion->getVersionString(); + } else { + $appInfo = $this->getAppInfo($appId); + $this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0'; + } } return $this->appVersions[$appId]; } /** + * Returns the installed versions of all apps + * + * @return array<string, string> + */ + public function getAppInstalledVersions(bool $onlyEnabled = false): array { + return $this->getAppConfig()->getAppInstalledVersions($onlyEnabled); + } + + /** * Returns a list of apps incompatible with the given version * * @param string $version Nextcloud version as array of version components @@ -802,7 +808,7 @@ class AppManager implements IAppManager { * @internal */ public function getIncompatibleApps(string $version): array { - $apps = $this->getInstalledApps(); + $apps = $this->getEnabledApps(); $incompatibleApps = []; foreach ($apps as $appId) { $info = $this->getAppInfo($appId); @@ -825,6 +831,10 @@ class AppManager implements IAppManager { } private function isAlwaysEnabled(string $appId): bool { + if ($appId === 'core') { + return true; + } + $alwaysEnabled = $this->getAlwaysEnabledApps(); return in_array($appId, $alwaysEnabled, true); } @@ -920,8 +930,23 @@ class AppManager implements IAppManager { return false; } + /** + * Clean the appId from forbidden characters + * + * @psalm-taint-escape callable + * @psalm-taint-escape cookie + * @psalm-taint-escape file + * @psalm-taint-escape has_quotes + * @psalm-taint-escape header + * @psalm-taint-escape html + * @psalm-taint-escape include + * @psalm-taint-escape ldap + * @psalm-taint-escape shell + * @psalm-taint-escape sql + * @psalm-taint-escape unserialize + */ public function cleanAppId(string $app): string { - // FIXME should list allowed characters instead - return str_replace(['<', '>', '"', "'", '\0', '/', '\\', '..'], '', $app); + /* Only lowercase alphanumeric is allowed */ + return preg_replace('/(^[0-9_]|[^a-z0-9_]+|_$)/', '', $app); } } diff --git a/lib/private/App/AppStore/AppNotFoundException.php b/lib/private/App/AppStore/AppNotFoundException.php new file mode 100644 index 00000000000..79ceebb4423 --- /dev/null +++ b/lib/private/App/AppStore/AppNotFoundException.php @@ -0,0 +1,13 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\App\AppStore; + +class AppNotFoundException extends \Exception { +} diff --git a/lib/private/App/AppStore/Bundles/Bundle.php b/lib/private/App/AppStore/Bundles/Bundle.php index 62f09b82f79..1443be81e92 100644 --- a/lib/private/App/AppStore/Bundles/Bundle.php +++ b/lib/private/App/AppStore/Bundles/Bundle.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Bundles/BundleFetcher.php b/lib/private/App/AppStore/Bundles/BundleFetcher.php index 01325699e2c..4ff53b0c70b 100644 --- a/lib/private/App/AppStore/Bundles/BundleFetcher.php +++ b/lib/private/App/AppStore/Bundles/BundleFetcher.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Bundles/EducationBundle.php b/lib/private/App/AppStore/Bundles/EducationBundle.php index 6770d4a7091..23681ec7416 100644 --- a/lib/private/App/AppStore/Bundles/EducationBundle.php +++ b/lib/private/App/AppStore/Bundles/EducationBundle.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Bundles/EnterpriseBundle.php b/lib/private/App/AppStore/Bundles/EnterpriseBundle.php index 88a9ec60a00..fc2d43e0388 100644 --- a/lib/private/App/AppStore/Bundles/EnterpriseBundle.php +++ b/lib/private/App/AppStore/Bundles/EnterpriseBundle.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Bundles/GroupwareBundle.php b/lib/private/App/AppStore/Bundles/GroupwareBundle.php index 7c7b74ff53d..93fa70268cd 100644 --- a/lib/private/App/AppStore/Bundles/GroupwareBundle.php +++ b/lib/private/App/AppStore/Bundles/GroupwareBundle.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Bundles/PublicSectorBundle.php b/lib/private/App/AppStore/Bundles/PublicSectorBundle.php index 158d525bdcc..106a6353029 100644 --- a/lib/private/App/AppStore/Bundles/PublicSectorBundle.php +++ b/lib/private/App/AppStore/Bundles/PublicSectorBundle.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Bundles/SocialSharingBundle.php b/lib/private/App/AppStore/Bundles/SocialSharingBundle.php index 7f925688ca3..40f0fb15977 100644 --- a/lib/private/App/AppStore/Bundles/SocialSharingBundle.php +++ b/lib/private/App/AppStore/Bundles/SocialSharingBundle.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Fetcher/AppDiscoverFetcher.php b/lib/private/App/AppStore/Fetcher/AppDiscoverFetcher.php index 2537d1dcec9..8389e525750 100644 --- a/lib/private/App/AppStore/Fetcher/AppDiscoverFetcher.php +++ b/lib/private/App/AppStore/Fetcher/AppDiscoverFetcher.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Fetcher/AppFetcher.php b/lib/private/App/AppStore/Fetcher/AppFetcher.php index 352646c3f5e..bbf4b00245b 100644 --- a/lib/private/App/AppStore/Fetcher/AppFetcher.php +++ b/lib/private/App/AppStore/Fetcher/AppFetcher.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -78,8 +79,8 @@ class AppFetcher extends Fetcher { $minServerVersion = $serverVersion->getMinimumVersion(); $maxServerVersion = $serverVersion->getMaximumVersion(); $minFulfilled = $this->compareVersion->isCompatible($ncVersion, $minServerVersion, '>='); - $maxFulfilled = $maxServerVersion !== '' && - $this->compareVersion->isCompatible($ncVersion, $maxServerVersion, '<='); + $maxFulfilled = $maxServerVersion !== '' + && $this->compareVersion->isCompatible($ncVersion, $maxServerVersion, '<='); $isPhpCompatible = true; if (($release['rawPhpVersionSpec'] ?? '*') !== '*') { $phpVersion = $versionParser->getVersion($release['rawPhpVersionSpec']); diff --git a/lib/private/App/AppStore/Fetcher/CategoryFetcher.php b/lib/private/App/AppStore/Fetcher/CategoryFetcher.php index d72f8fa7e24..d7857d41bee 100644 --- a/lib/private/App/AppStore/Fetcher/CategoryFetcher.php +++ b/lib/private/App/AppStore/Fetcher/CategoryFetcher.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Fetcher/Fetcher.php b/lib/private/App/AppStore/Fetcher/Fetcher.php index f998c9e2023..2e949fedb51 100644 --- a/lib/private/App/AppStore/Fetcher/Fetcher.php +++ b/lib/private/App/AppStore/Fetcher/Fetcher.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Version/Version.php b/lib/private/App/AppStore/Version/Version.php index b7e679d250a..2d169a291f1 100644 --- a/lib/private/App/AppStore/Version/Version.php +++ b/lib/private/App/AppStore/Version/Version.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/AppStore/Version/VersionParser.php b/lib/private/App/AppStore/Version/VersionParser.php index 59715c8d385..8976f28837f 100644 --- a/lib/private/App/AppStore/Version/VersionParser.php +++ b/lib/private/App/AppStore/Version/VersionParser.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/App/DependencyAnalyzer.php b/lib/private/App/DependencyAnalyzer.php index 72b38ca12c7..1e56612132b 100644 --- a/lib/private/App/DependencyAnalyzer.php +++ b/lib/private/App/DependencyAnalyzer.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/App/InfoParser.php b/lib/private/App/InfoParser.php index 6610121f446..e7a75afdf0b 100644 --- a/lib/private/App/InfoParser.php +++ b/lib/private/App/InfoParser.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/App/Platform.php b/lib/private/App/Platform.php index c2c059220c8..80e4cefed64 100644 --- a/lib/private/App/Platform.php +++ b/lib/private/App/Platform.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/App/PlatformRepository.php b/lib/private/App/PlatformRepository.php index 6d9a9cd011a..faed8b07feb 100644 --- a/lib/private/App/PlatformRepository.php +++ b/lib/private/App/PlatformRepository.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/AppConfig.php b/lib/private/AppConfig.php index dc9bac7745d..476adbb93e0 100644 --- a/lib/private/AppConfig.php +++ b/lib/private/AppConfig.php @@ -11,6 +11,11 @@ namespace OC; use InvalidArgumentException; use JsonException; +use NCU\Config\Lexicon\ConfigLexiconEntry; +use NCU\Config\Lexicon\ConfigLexiconStrictness; +use NCU\Config\Lexicon\IConfigLexicon; +use OC\AppFramework\Bootstrap\Coordinator; +use OC\Config\ConfigManager; use OCP\DB\Exception as DBException; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Exceptions\AppConfigIncorrectTypeException; @@ -20,6 +25,7 @@ use OCP\IAppConfig; use OCP\IConfig; use OCP\IDBConnection; use OCP\Security\ICrypto; +use OCP\Server; use Psr\Log\LoggerInterface; /** @@ -55,16 +61,12 @@ class AppConfig implements IAppConfig { private array $valueTypes = []; // type for all config values private bool $fastLoaded = false; private bool $lazyLoaded = false; + /** @var array<string, array{entries: array<string, ConfigLexiconEntry>, aliases: array<string, string>, strictness: ConfigLexiconStrictness}> ['app_id' => ['strictness' => ConfigLexiconStrictness, 'entries' => ['config_key' => ConfigLexiconEntry[]]] */ + private array $configLexiconDetails = []; + private bool $ignoreLexiconAliases = false; - /** - * $migrationCompleted is only needed to manage the previous structure - * of the database during the upgrading process to nc29. - * - * only when upgrading from a version prior 28.0.2 - * - * @TODO: remove this value in Nextcloud 30+ - */ - private bool $migrationCompleted = true; + /** @var ?array<string, string> */ + private ?array $appVersionsCache = null; public function __construct( protected IDBConnection $connection, @@ -118,6 +120,7 @@ class AppConfig implements IAppConfig { public function hasKey(string $app, string $key, ?bool $lazy = false): bool { $this->assertParams($app, $key); $this->loadConfig($app, $lazy); + $this->matchAndApplyLexiconDefinition($app, $key); if ($lazy === null) { $appCache = $this->getAllValues($app); @@ -143,6 +146,7 @@ class AppConfig implements IAppConfig { public function isSensitive(string $app, string $key, ?bool $lazy = false): bool { $this->assertParams($app, $key); $this->loadConfig(null, $lazy); + $this->matchAndApplyLexiconDefinition($app, $key); if (!isset($this->valueTypes[$app][$key])) { throw new AppConfigUnknownKeyException('unknown config key'); @@ -163,6 +167,9 @@ class AppConfig implements IAppConfig { * @since 29.0.0 */ public function isLazy(string $app, string $key): bool { + $this->assertParams($app, $key); + $this->matchAndApplyLexiconDefinition($app, $key); + // there is a huge probability the non-lazy config are already loaded if ($this->hasKey($app, $key, false)) { return false; @@ -285,7 +292,7 @@ class AppConfig implements IAppConfig { ): string { try { $lazy = ($lazy === null) ? $this->isLazy($app, $key) : $lazy; - } catch (AppConfigUnknownKeyException $e) { + } catch (AppConfigUnknownKeyException) { return $default; } @@ -430,6 +437,10 @@ class AppConfig implements IAppConfig { int $type, ): string { $this->assertParams($app, $key, valueType: $type); + $origKey = $key; + if (!$this->matchAndApplyLexiconDefinition($app, $key, $lazy, $type, $default)) { + return $default; // returns default if strictness of lexicon is set to WARNING (block and report) + } $this->loadConfig($app, $lazy); /** @@ -467,6 +478,14 @@ class AppConfig implements IAppConfig { $value = $this->crypto->decrypt(substr($value, self::ENCRYPTION_PREFIX_LENGTH)); } + // in case the key was modified while running matchAndApplyLexiconDefinition() we are + // interested to check options in case a modification of the value is needed + // ie inverting value from previous key when using lexicon option RENAME_INVERT_BOOLEAN + if ($origKey !== $key && $type === self::VALUE_BOOL) { + $configManager = Server::get(ConfigManager::class); + $value = ($configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0'; + } + return $value; } @@ -486,6 +505,14 @@ class AppConfig implements IAppConfig { * @see VALUE_ARRAY */ public function getValueType(string $app, string $key, ?bool $lazy = null): int { + $type = self::VALUE_MIXED; + $ignorable = $lazy ?? false; + $this->matchAndApplyLexiconDefinition($app, $key, $ignorable, $type); + if ($type !== self::VALUE_MIXED) { + // a modified $type means config key is set in Lexicon + return $type; + } + $this->assertParams($app, $key); $this->loadConfig($app, $lazy); @@ -721,6 +748,9 @@ class AppConfig implements IAppConfig { int $type, ): bool { $this->assertParams($app, $key); + if (!$this->matchAndApplyLexiconDefinition($app, $key, $lazy, $type)) { + return false; // returns false as database is not updated + } $this->loadConfig(null, $lazy); $sensitive = $this->isTyped(self::VALUE_SENSITIVE, $type); @@ -785,8 +815,8 @@ class AppConfig implements IAppConfig { * we only accept a different type from the one stored in database * if the one stored in database is not-defined (VALUE_MIXED) */ - if (!$this->isTyped(self::VALUE_MIXED, $currType) && - ($type | self::VALUE_SENSITIVE) !== ($currType | self::VALUE_SENSITIVE)) { + if (!$this->isTyped(self::VALUE_MIXED, $currType) + && ($type | self::VALUE_SENSITIVE) !== ($currType | self::VALUE_SENSITIVE)) { try { $currType = $this->convertTypeToString($currType); $type = $this->convertTypeToString($type); @@ -850,7 +880,8 @@ class AppConfig implements IAppConfig { public function updateType(string $app, string $key, int $type = self::VALUE_MIXED): bool { $this->assertParams($app, $key); $this->loadConfigAll(); - $lazy = $this->isLazy($app, $key); + $this->matchAndApplyLexiconDefinition($app, $key); + $this->isLazy($app, $key); // confirm key exists // type can only be one type if (!in_array($type, [self::VALUE_MIXED, self::VALUE_STRING, self::VALUE_INT, self::VALUE_FLOAT, self::VALUE_BOOL, self::VALUE_ARRAY])) { @@ -892,6 +923,7 @@ class AppConfig implements IAppConfig { public function updateSensitive(string $app, string $key, bool $sensitive): bool { $this->assertParams($app, $key); $this->loadConfigAll(); + $this->matchAndApplyLexiconDefinition($app, $key); try { if ($sensitive === $this->isSensitive($app, $key, null)) { @@ -951,6 +983,7 @@ class AppConfig implements IAppConfig { public function updateLazy(string $app, string $key, bool $lazy): bool { $this->assertParams($app, $key); $this->loadConfigAll(); + $this->matchAndApplyLexiconDefinition($app, $key); try { if ($lazy === $this->isLazy($app, $key)) { @@ -986,6 +1019,7 @@ class AppConfig implements IAppConfig { public function getDetails(string $app, string $key): array { $this->assertParams($app, $key); $this->loadConfigAll(); + $this->matchAndApplyLexiconDefinition($app, $key); $lazy = $this->isLazy($app, $key); if ($lazy) { @@ -1073,6 +1107,8 @@ class AppConfig implements IAppConfig { */ public function deleteKey(string $app, string $key): void { $this->assertParams($app, $key); + $this->matchAndApplyLexiconDefinition($app, $key); + $qb = $this->connection->getQueryBuilder(); $qb->delete('appconfig') ->where($qb->expr()->eq('appid', $qb->createNamedParameter($app))) @@ -1081,6 +1117,7 @@ class AppConfig implements IAppConfig { unset($this->lazyCache[$app][$key]); unset($this->fastCache[$app][$key]); + unset($this->valueTypes[$app][$key]); } /** @@ -1199,41 +1236,16 @@ class AppConfig implements IAppConfig { $qb = $this->connection->getQueryBuilder(); $qb->from('appconfig'); - /** - * The use of $this->migrationCompleted is only needed to manage the - * database during the upgrading process to nc29. - */ - if (!$this->migrationCompleted) { - $qb->select('appid', 'configkey', 'configvalue'); - } else { - // we only need value from lazy when loadConfig does not specify it - $qb->select('appid', 'configkey', 'configvalue', 'type'); - - if ($lazy !== null) { - $qb->where($qb->expr()->eq('lazy', $qb->createNamedParameter($lazy ? 1 : 0, IQueryBuilder::PARAM_INT))); - } else { - $qb->addSelect('lazy'); - } - } - - try { - $result = $qb->executeQuery(); - } catch (DBException $e) { - /** - * in case of issue with field name, it means that migration is not completed. - * Falling back to a request without select on lazy. - * This whole try/catch and the migrationCompleted variable can be removed in NC30. - */ - if ($e->getReason() !== DBException::REASON_INVALID_FIELD_NAME) { - throw $e; - } + // we only need value from lazy when loadConfig does not specify it + $qb->select('appid', 'configkey', 'configvalue', 'type'); - $this->migrationCompleted = false; - $this->loadConfig($app, $lazy); - - return; + if ($lazy !== null) { + $qb->where($qb->expr()->eq('lazy', $qb->createNamedParameter($lazy ? 1 : 0, IQueryBuilder::PARAM_INT))); + } else { + $qb->addSelect('lazy'); } + $result = $qb->executeQuery(); $rows = $result->fetchAll(); foreach ($rows as $row) { // most of the time, 'lazy' is not in the select because its value is already known @@ -1304,6 +1316,7 @@ class AppConfig implements IAppConfig { */ public function getValue($app, $key, $default = null) { $this->loadConfig($app); + $this->matchAndApplyLexiconDefinition($app, $key); return $this->fastCache[$app][$key] ?? $default; } @@ -1383,7 +1396,7 @@ class AppConfig implements IAppConfig { foreach ($values as $key => $value) { try { $type = $this->getValueType($app, $key, $lazy); - } catch (AppConfigUnknownKeyException $e) { + } catch (AppConfigUnknownKeyException) { continue; } @@ -1442,6 +1455,9 @@ class AppConfig implements IAppConfig { 'globalsiteselector' => [ '/^gss\.jwt\.key$/', ], + 'gpgmailer' => [ + '/^GpgServerKey$/', + ], 'integration_discourse' => [ '/^private_key$/', '/^public_key$/', @@ -1496,6 +1512,9 @@ class AppConfig implements IAppConfig { '/^client_secret$/', '/^oauth_instance_url$/', ], + 'maps' => [ + '/^mapboxAPIKEY$/', + ], 'notify_push' => [ '/^cookie$/', ], @@ -1533,12 +1552,12 @@ class AppConfig implements IAppConfig { '/^slogan$/', '/^url$/', ], - 'user_ldap' => [ - '/^(s..)?ldap_agent_password$/', - ], 'twofactor_gateway' => [ '/^.*token$/', ], + 'user_ldap' => [ + '/^(s..)?ldap_agent_password$/', + ], 'user_saml' => [ '/^idp-x509cert$/', ], @@ -1559,4 +1578,160 @@ class AppConfig implements IAppConfig { public function clearCachedConfig(): void { $this->clearCache(); } + + /** + * Match and apply current use of config values with defined lexicon. + * Set $lazy to NULL only if only interested into checking that $key is alias. + * + * @throws AppConfigUnknownKeyException + * @throws AppConfigTypeConflictException + * @return bool TRUE if everything is fine compared to lexicon or lexicon does not exist + */ + private function matchAndApplyLexiconDefinition( + string $app, + string &$key, + ?bool &$lazy = null, + int &$type = self::VALUE_MIXED, + string &$default = '', + ): bool { + if (in_array($key, + [ + 'enabled', + 'installed_version', + 'types', + ])) { + return true; // we don't break stuff for this list of config keys. + } + $configDetails = $this->getConfigDetailsFromLexicon($app); + if (array_key_exists($key, $configDetails['aliases']) && !$this->ignoreLexiconAliases) { + // in case '$rename' is set in ConfigLexiconEntry, we use the new config key + $key = $configDetails['aliases'][$key]; + } + + if (!array_key_exists($key, $configDetails['entries'])) { + return $this->applyLexiconStrictness($configDetails['strictness'], 'The app config key ' . $app . '/' . $key . ' is not defined in the config lexicon'); + } + + // if lazy is NULL, we ignore all check on the type/lazyness/default from Lexicon + if ($lazy === null) { + return true; + } + + /** @var ConfigLexiconEntry $configValue */ + $configValue = $configDetails['entries'][$key]; + $type &= ~self::VALUE_SENSITIVE; + + $appConfigValueType = $configValue->getValueType()->toAppConfigFlag(); + if ($type === self::VALUE_MIXED) { + $type = $appConfigValueType; // we overwrite if value was requested as mixed + } elseif ($appConfigValueType !== $type) { + throw new AppConfigTypeConflictException('The app config key ' . $app . '/' . $key . ' is typed incorrectly in relation to the config lexicon'); + } + + $lazy = $configValue->isLazy(); + $default = $configValue->getDefault() ?? $default; // default from Lexicon got priority + if ($configValue->isFlagged(self::FLAG_SENSITIVE)) { + $type |= self::VALUE_SENSITIVE; + } + if ($configValue->isDeprecated()) { + $this->logger->notice('App config key ' . $app . '/' . $key . ' is set as deprecated.'); + } + + return true; + } + + /** + * manage ConfigLexicon behavior based on strictness set in IConfigLexicon + * + * @param ConfigLexiconStrictness|null $strictness + * @param string $line + * + * @return bool TRUE if conflict can be fully ignored, FALSE if action should be not performed + * @throws AppConfigUnknownKeyException if strictness implies exception + * @see IConfigLexicon::getStrictness() + */ + private function applyLexiconStrictness( + ?ConfigLexiconStrictness $strictness, + string $line = '', + ): bool { + if ($strictness === null) { + return true; + } + + switch ($strictness) { + case ConfigLexiconStrictness::IGNORE: + return true; + case ConfigLexiconStrictness::NOTICE: + $this->logger->notice($line); + return true; + case ConfigLexiconStrictness::WARNING: + $this->logger->warning($line); + return false; + } + + throw new AppConfigUnknownKeyException($line); + } + + /** + * extract details from registered $appId's config lexicon + * + * @param string $appId + * @internal + * + * @return array{entries: array<string, ConfigLexiconEntry>, aliases: array<string, string>, strictness: ConfigLexiconStrictness} + */ + public function getConfigDetailsFromLexicon(string $appId): array { + if (!array_key_exists($appId, $this->configLexiconDetails)) { + $entries = $aliases = []; + $bootstrapCoordinator = \OCP\Server::get(Coordinator::class); + $configLexicon = $bootstrapCoordinator->getRegistrationContext()?->getConfigLexicon($appId); + foreach ($configLexicon?->getAppConfigs() ?? [] as $configEntry) { + $entries[$configEntry->getKey()] = $configEntry; + if ($configEntry->getRename() !== null) { + $aliases[$configEntry->getRename()] = $configEntry->getKey(); + } + } + + $this->configLexiconDetails[$appId] = [ + 'entries' => $entries, + 'aliases' => $aliases, + 'strictness' => $configLexicon?->getStrictness() ?? ConfigLexiconStrictness::IGNORE + ]; + } + + return $this->configLexiconDetails[$appId]; + } + + private function getLexiconEntry(string $appId, string $key): ?ConfigLexiconEntry { + return $this->getConfigDetailsFromLexicon($appId)['entries'][$key] ?? null; + } + + /** + * if set to TRUE, ignore aliases defined in Config Lexicon during the use of the methods of this class + * + * @internal + */ + public function ignoreLexiconAliases(bool $ignore): void { + $this->ignoreLexiconAliases = $ignore; + } + + /** + * Returns the installed versions of all apps + * + * @return array<string, string> + */ + public function getAppInstalledVersions(bool $onlyEnabled = false): array { + if ($this->appVersionsCache === null) { + /** @var array<string, string> */ + $this->appVersionsCache = $this->searchValues('installed_version', false, IAppConfig::VALUE_STRING); + } + if ($onlyEnabled) { + return array_filter( + $this->appVersionsCache, + fn (string $app): bool => $this->getValueString($app, 'enabled', 'no') !== 'no', + ARRAY_FILTER_USE_KEY + ); + } + return $this->appVersionsCache; + } } diff --git a/lib/private/AppFramework/Bootstrap/Coordinator.php b/lib/private/AppFramework/Bootstrap/Coordinator.php index 4e78450fa04..64e3dbfd928 100644 --- a/lib/private/AppFramework/Bootstrap/Coordinator.php +++ b/lib/private/AppFramework/Bootstrap/Coordinator.php @@ -20,6 +20,7 @@ use OCP\Dashboard\IManager; use OCP\Diagnostics\IEventLogger; use OCP\EventDispatcher\IEventDispatcher; use OCP\IServerContainer; +use Psr\Container\ContainerExceptionInterface; use Psr\Log\LoggerInterface; use Throwable; use function class_exists; @@ -30,8 +31,8 @@ class Coordinator { /** @var RegistrationContext|null */ private $registrationContext; - /** @var string[] */ - private $bootedApps = []; + /** @var array<string,true> */ + private array $bootedApps = []; public function __construct( private IServerContainer $serverContainer, @@ -69,26 +70,32 @@ class Coordinator { */ try { $path = $this->appManager->getAppPath($appId); + OC_App::registerAutoloading($appId, $path); } catch (AppPathNotFoundException) { // Ignore continue; } - OC_App::registerAutoloading($appId, $path); $this->eventLogger->end("bootstrap:register_app:$appId:autoloader"); /* * Next we check if there is an application class, and it implements * the \OCP\AppFramework\Bootstrap\IBootstrap interface */ - $appNameSpace = App::buildAppNamespace($appId); + if ($appId === 'core') { + $appNameSpace = 'OC\\Core'; + } else { + $appNameSpace = App::buildAppNamespace($appId); + } $applicationClassName = $appNameSpace . '\\AppInfo\\Application'; + try { - if (class_exists($applicationClassName) && in_array(IBootstrap::class, class_implements($applicationClassName), true)) { + if (class_exists($applicationClassName) && is_a($applicationClassName, IBootstrap::class, true)) { $this->eventLogger->start("bootstrap:register_app:$appId:application", "Load `Application` instance for $appId"); try { - /** @var IBootstrap|App $application */ - $apps[$appId] = $application = $this->serverContainer->query($applicationClassName); - } catch (QueryException $e) { + /** @var IBootstrap&App $application */ + $application = $this->serverContainer->query($applicationClassName); + $apps[$appId] = $application; + } catch (ContainerExceptionInterface $e) { // Weird, but ok $this->eventLogger->end("bootstrap:register_app:$appId"); continue; @@ -171,7 +178,7 @@ class Coordinator { public function isBootable(string $appId) { $appNameSpace = App::buildAppNamespace($appId); $applicationClassName = $appNameSpace . '\\AppInfo\\Application'; - return class_exists($applicationClassName) && - in_array(IBootstrap::class, class_implements($applicationClassName), true); + return class_exists($applicationClassName) + && in_array(IBootstrap::class, class_implements($applicationClassName), true); } } diff --git a/lib/private/AppFramework/Bootstrap/RegistrationContext.php b/lib/private/AppFramework/Bootstrap/RegistrationContext.php index d7a380f9e1d..95ad129c466 100644 --- a/lib/private/AppFramework/Bootstrap/RegistrationContext.php +++ b/lib/private/AppFramework/Bootstrap/RegistrationContext.php @@ -10,6 +10,8 @@ declare(strict_types=1); namespace OC\AppFramework\Bootstrap; use Closure; +use NCU\Config\Lexicon\IConfigLexicon; +use OC\Config\Lexicon\CoreConfigLexicon; use OC\Support\CrashReport\Registry; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IRegistrationContext; @@ -141,6 +143,9 @@ class RegistrationContext { /** @var ServiceRegistration<IDeclarativeSettingsForm>[] */ private array $declarativeSettings = []; + /** @var array<array-key, string> */ + private array $configLexiconClasses = ['core' => CoreConfigLexicon::class]; + /** @var ServiceRegistration<ITeamResourceProvider>[] */ private array $teamResourceProviders = []; @@ -149,7 +154,10 @@ class RegistrationContext { /** @var ServiceRegistration<\OCP\TaskProcessing\ITaskType>[] */ private array $taskProcessingTaskTypes = []; - + + /** @var ServiceRegistration<\OCP\Files\Conversion\IConversionProvider>[] */ + private array $fileConversionProviders = []; + /** @var ServiceRegistration<IMailProvider>[] */ private $mailProviders = []; @@ -416,12 +424,26 @@ class RegistrationContext { ); } + public function registerFileConversionProvider(string $class): void { + $this->context->registerFileConversionProvider( + $this->appId, + $class + ); + } + public function registerMailProvider(string $class): void { $this->context->registerMailProvider( $this->appId, $class ); } + + public function registerConfigLexicon(string $configLexiconClass): void { + $this->context->registerConfigLexicon( + $this->appId, + $configLexiconClass + ); + } }; } @@ -614,6 +636,14 @@ class RegistrationContext { public function registerTaskProcessingTaskType(string $appId, string $taskProcessingTaskTypeClass) { $this->taskProcessingTaskTypes[] = new ServiceRegistration($appId, $taskProcessingTaskTypeClass); } + + /** + * @psalm-param class-string<\OCP\Files\Conversion\IConversionProvider> $class + */ + public function registerFileConversionProvider(string $appId, string $class): void { + $this->fileConversionProviders[] = new ServiceRegistration($appId, $class); + } + /** * @psalm-param class-string<IMailProvider> $migratorClass */ @@ -622,6 +652,13 @@ class RegistrationContext { } /** + * @psalm-param class-string<IConfigLexicon> $configLexiconClass + */ + public function registerConfigLexicon(string $appId, string $configLexiconClass): void { + $this->configLexiconClasses[$appId] = $configLexiconClass; + } + + /** * @param App[] $apps */ public function delegateCapabilityRegistrations(array $apps): void { @@ -967,9 +1004,32 @@ class RegistrationContext { } /** + * @return ServiceRegistration<\OCP\Files\Conversion\IConversionProvider>[] + */ + public function getFileConversionProviders(): array { + return $this->fileConversionProviders; + } + + /** * @return ServiceRegistration<IMailProvider>[] */ public function getMailProviders(): array { return $this->mailProviders; } + + /** + * returns IConfigLexicon registered by the app. + * null if none registered. + * + * @param string $appId + * + * @return IConfigLexicon|null + */ + public function getConfigLexicon(string $appId): ?IConfigLexicon { + if (!array_key_exists($appId, $this->configLexiconClasses)) { + return null; + } + + return \OCP\Server::get($this->configLexiconClasses[$appId]); + } } diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 2083a0e7195..87361a9d1ea 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -10,6 +11,7 @@ use OC; use OC\AppFramework\Http; use OC\AppFramework\Http\Dispatcher; use OC\AppFramework\Http\Output; +use OC\AppFramework\Middleware\FlowV2EphemeralSessionsMiddleware; use OC\AppFramework\Middleware\MiddlewareDispatcher; use OC\AppFramework\Middleware\OCSMiddleware; use OC\AppFramework\Middleware\Security\CORSMiddleware; @@ -216,7 +218,7 @@ class DIContainer extends SimpleContainer implements IAppContainer { ) ); - + $dispatcher->registerMiddleware($c->get(FlowV2EphemeralSessionsMiddleware::class)); $securityMiddleware = new SecurityMiddleware( $c->get(IRequest::class), @@ -274,15 +276,7 @@ class DIContainer extends SimpleContainer implements IAppContainer { $c->get(LoggerInterface::class) ) ); - $dispatcher->registerMiddleware( - new RateLimitingMiddleware( - $c->get(IRequest::class), - $c->get(IUserSession::class), - $c->get(IControllerMethodReflector::class), - $c->get(OC\Security\RateLimiting\Limiter::class), - $c->get(ISession::class) - ) - ); + $dispatcher->registerMiddleware($c->get(RateLimitingMiddleware::class)); $dispatcher->registerMiddleware( new OC\AppFramework\Middleware\PublicShare\PublicShareMiddleware( $c->get(IRequest::class), @@ -447,7 +441,7 @@ class DIContainer extends SimpleContainer implements IAppContainer { return parent::query($name); } - throw new QueryException('Could not resolve ' . $name . '!' . - ' Class can not be instantiated', 1); + throw new QueryException('Could not resolve ' . $name . '!' + . ' Class can not be instantiated', 1); } } diff --git a/lib/private/AppFramework/Http.php b/lib/private/AppFramework/Http.php index 3c3e19692bf..08d6259c2a2 100644 --- a/lib/private/AppFramework/Http.php +++ b/lib/private/AppFramework/Http.php @@ -102,7 +102,7 @@ class Http extends BaseHttp { $status = self::STATUS_FOUND; } - return $this->protocolVersion . ' ' . $status . ' ' . - $this->headers[$status]; + return $this->protocolVersion . ' ' . $status . ' ' + . $this->headers[$status]; } } diff --git a/lib/private/AppFramework/Http/Dispatcher.php b/lib/private/AppFramework/Http/Dispatcher.php index d63a9108b47..d129a7d770b 100644 --- a/lib/private/AppFramework/Http/Dispatcher.php +++ b/lib/private/AppFramework/Http/Dispatcher.php @@ -90,9 +90,11 @@ class Dispatcher { * @param Controller $controller the controller which will be called * @param string $methodName the method name which will be called on * the controller - * @return array $array[0] contains a string with the http main header, - * $array[1] contains headers in the form: $key => value, $array[2] contains - * the response output + * @return array $array[0] contains the http status header as a string, + * $array[1] contains response headers as an array, + * $array[2] contains response cookies as an array, + * $array[3] contains the response output as a string, + * $array[4] contains the response object * @throws \Exception */ public function dispatch(Controller $controller, string $methodName): array { diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index d177221556c..e662cb8679a 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -45,7 +45,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { public const REGEX_LOCALHOST = '/^(127\.0\.0\.1|localhost|\[::1\])$/'; protected string $inputStream; - protected $content; + private bool $isPutStreamContentAlreadySent = false; protected array $items = []; protected array $allowedKeys = [ 'get', @@ -64,6 +64,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { protected ?CsrfTokenManager $csrfTokenManager; protected bool $contentDecoded = false; + private ?\JsonException $decodingException = null; /** * @param array $vars An associative array with the following optional values: @@ -356,13 +357,13 @@ class Request implements \ArrayAccess, \Countable, IRequest { protected function getContent() { // If the content can't be parsed into an array then return a stream resource. if ($this->isPutStreamContent()) { - if ($this->content === false) { + if ($this->isPutStreamContentAlreadySent) { throw new \LogicException( '"put" can only be accessed once if not ' . 'application/x-www-form-urlencoded or application/json.' ); } - $this->content = false; + $this->isPutStreamContentAlreadySent = true; return fopen($this->inputStream, 'rb'); } else { $this->decodeContent(); @@ -389,7 +390,14 @@ class Request implements \ArrayAccess, \Countable, IRequest { // 'application/json' and other JSON-related content types must be decoded manually. if (preg_match(self::JSON_CONTENT_TYPE_REGEX, $this->getHeader('Content-Type')) === 1) { - $params = json_decode(file_get_contents($this->inputStream), true); + $content = file_get_contents($this->inputStream); + if ($content !== '') { + try { + $params = json_decode($content, true, flags:JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + $this->decodingException = $e; + } + } if (\is_array($params) && \count($params) > 0) { $this->items['params'] = $params; if ($this->method === 'POST') { @@ -413,6 +421,12 @@ class Request implements \ArrayAccess, \Countable, IRequest { $this->contentDecoded = true; } + public function throwDecodingExceptionIfAny(): void { + if ($this->decodingException !== null) { + throw $this->decodingException; + } + } + /** * Checks if the CSRF check was correct diff --git a/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php b/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php new file mode 100644 index 00000000000..e4571dfc50e --- /dev/null +++ b/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php @@ -0,0 +1,58 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OC\AppFramework\Middleware; + +use OC\AppFramework\Utility\ControllerMethodReflector; +use OC\Core\Controller\ClientFlowLoginV2Controller; +use OC\Core\Controller\TwoFactorChallengeController; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\Attribute\PublicPage; +use OCP\AppFramework\Middleware; +use OCP\ISession; +use OCP\IUserSession; +use ReflectionMethod; + +// Will close the session if the user session is ephemeral. +// Happens when the user logs in via the login flow v2. +class FlowV2EphemeralSessionsMiddleware extends Middleware { + public function __construct( + private ISession $session, + private IUserSession $userSession, + private ControllerMethodReflector $reflector, + ) { + } + + public function beforeController(Controller $controller, string $methodName) { + if (!$this->session->get(ClientFlowLoginV2Controller::EPHEMERAL_NAME)) { + return; + } + + if ( + $controller instanceof ClientFlowLoginV2Controller + && ($methodName === 'grantPage' || $methodName === 'generateAppPassword') + ) { + return; + } + + if ($controller instanceof TwoFactorChallengeController) { + return; + } + + $reflectionMethod = new ReflectionMethod($controller, $methodName); + if (!empty($reflectionMethod->getAttributes(PublicPage::class))) { + return; + } + + if ($this->reflector->hasAnnotation('PublicPage')) { + return; + } + + $this->userSession->logout(); + $this->session->close(); + } +} diff --git a/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php b/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php index 17b423164f6..08b30092155 100644 --- a/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php +++ b/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php @@ -29,7 +29,7 @@ class NotModifiedMiddleware extends Middleware { } $modifiedSinceHeader = $this->request->getHeader('IF_MODIFIED_SINCE'); - if ($modifiedSinceHeader !== '' && $response->getLastModified() !== null && trim($modifiedSinceHeader) === $response->getLastModified()->format(\DateTimeInterface::RFC2822)) { + if ($modifiedSinceHeader !== '' && $response->getLastModified() !== null && trim($modifiedSinceHeader) === $response->getLastModified()->format(\DateTimeInterface::RFC7231)) { $response->setStatus(Http::STATUS_NOT_MODIFIED); return $response; } diff --git a/lib/private/AppFramework/Middleware/OCSMiddleware.php b/lib/private/AppFramework/Middleware/OCSMiddleware.php index 46612bf0d29..64f4b0054de 100644 --- a/lib/private/AppFramework/Middleware/OCSMiddleware.php +++ b/lib/private/AppFramework/Middleware/OCSMiddleware.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php b/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php index c80d06c90ae..5df4009b094 100644 --- a/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php +++ b/lib/private/AppFramework/Middleware/PublicShare/Exceptions/NeedAuthenticationException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php b/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php index 2b3025fccff..83e799e3d3b 100644 --- a/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php +++ b/lib/private/AppFramework/Middleware/PublicShare/PublicShareMiddleware.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -120,7 +121,7 @@ class PublicShareMiddleware extends Middleware { private function throttle($bruteforceProtectionAction, $token): void { $ip = $this->request->getRemoteAddress(); - $this->throttler->sleepDelay($ip, $bruteforceProtectionAction); + $this->throttler->sleepDelayOrThrowOnMax($ip, $bruteforceProtectionAction); $this->throttler->registerAttempt($bruteforceProtectionAction, $ip, ['token' => $token]); } } diff --git a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php index 40af67739d6..4453f5a7d4b 100644 --- a/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/CORSMiddleware.php @@ -68,8 +68,8 @@ class CORSMiddleware extends Middleware { // ensure that @CORS annotated API routes are not used in conjunction // with session authentication since this enables CSRF attack vectors - if ($this->hasAnnotationOrAttribute($reflectionMethod, 'CORS', CORS::class) && - (!$this->hasAnnotationOrAttribute($reflectionMethod, 'PublicPage', PublicPage::class) || $this->session->isLoggedIn())) { + if ($this->hasAnnotationOrAttribute($reflectionMethod, 'CORS', CORS::class) + && (!$this->hasAnnotationOrAttribute($reflectionMethod, 'PublicPage', PublicPage::class) || $this->session->isLoggedIn())) { $user = array_key_exists('PHP_AUTH_USER', $this->request->server) ? $this->request->server['PHP_AUTH_USER'] : null; $pass = array_key_exists('PHP_AUTH_PW', $this->request->server) ? $this->request->server['PHP_AUTH_PW'] : null; @@ -134,10 +134,10 @@ class CORSMiddleware extends Middleware { // allow credentials headers must not be true or CSRF is possible // otherwise foreach ($response->getHeaders() as $header => $value) { - if (strtolower($header) === 'access-control-allow-credentials' && - strtolower(trim($value)) === 'true') { - $msg = 'Access-Control-Allow-Credentials must not be ' . - 'set to true in order to prevent CSRF'; + if (strtolower($header) === 'access-control-allow-credentials' + && strtolower(trim($value)) === 'true') { + $msg = 'Access-Control-Allow-Credentials must not be ' + . 'set to true in order to prevent CSRF'; throw new SecurityException($msg); } } diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php index 646a5240bfc..53fbaaf5ed2 100644 --- a/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php +++ b/lib/private/AppFramework/Middleware/Security/Exceptions/AppNotEnabledException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php index 91f1dba874d..0380c6781aa 100644 --- a/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php +++ b/lib/private/AppFramework/Middleware/Security/Exceptions/LaxSameSiteCookieFailedException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php b/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php index 7e950f2c976..ca30f736fbc 100644 --- a/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php +++ b/lib/private/AppFramework/Middleware/Security/Exceptions/NotConfirmedException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -14,7 +15,7 @@ use OCP\AppFramework\Http; * @package OC\AppFramework\Middleware\Security\Exceptions */ class NotConfirmedException extends SecurityException { - public function __construct() { - parent::__construct('Password confirmation is required', Http::STATUS_FORBIDDEN); + public function __construct(string $message = 'Password confirmation is required') { + parent::__construct($message, Http::STATUS_FORBIDDEN); } } diff --git a/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php b/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php index 2e3ed02ed34..0facbffe504 100644 --- a/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/PasswordConfirmationMiddleware.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -79,8 +80,12 @@ class PasswordConfirmationMiddleware extends Middleware { if ($this->isPasswordConfirmationStrict($reflectionMethod)) { $authHeader = $this->request->getHeader('Authorization'); + if (!str_starts_with(strtolower($authHeader), 'basic ')) { + throw new NotConfirmedException('Required authorization header missing'); + } [, $password] = explode(':', base64_decode(substr($authHeader, 6)), 2); - $loginResult = $this->userManager->checkPassword($user->getUid(), $password); + $loginName = $this->session->get('loginname'); + $loginResult = $this->userManager->checkPassword($loginName, $password); if ($loginResult === false) { throw new NotConfirmedException(); } diff --git a/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php b/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php index f4d120ebc30..2d19be97993 100644 --- a/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/RateLimitingMiddleware.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace OC\AppFramework\Middleware\Security; use OC\AppFramework\Utility\ControllerMethodReflector; +use OC\Security\Ip\BruteforceAllowList; use OC\Security\RateLimiting\Exception\RateLimitExceededException; use OC\Security\RateLimiting\Limiter; use OC\User\Session; @@ -20,6 +21,7 @@ use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Middleware; +use OCP\IAppConfig; use OCP\IRequest; use OCP\ISession; use OCP\IUserSession; @@ -53,6 +55,8 @@ class RateLimitingMiddleware extends Middleware { protected ControllerMethodReflector $reflector, protected Limiter $limiter, protected ISession $session, + protected IAppConfig $appConfig, + protected BruteforceAllowList $bruteForceAllowList, ) { } @@ -73,6 +77,11 @@ class RateLimitingMiddleware extends Middleware { $rateLimit = $this->readLimitFromAnnotationOrAttribute($controller, $methodName, 'UserRateThrottle', UserRateLimit::class); if ($rateLimit !== null) { + if ($this->appConfig->getValueBool('bruteforcesettings', 'apply_allowlist_to_ratelimit') + && $this->bruteForceAllowList->isBypassListed($this->request->getRemoteAddress())) { + return; + } + $this->limiter->registerUserRequest( $rateLimitIdentifier, $rateLimit->getLimit(), diff --git a/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php b/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php index efe56e0b124..ed3bb232023 100644 --- a/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/SameSiteCookieMiddleware.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php index 88987290244..e3a293e0fd9 100644 --- a/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php +++ b/lib/private/AppFramework/Middleware/Security/SecurityMiddleware.php @@ -156,7 +156,7 @@ class SecurityMiddleware extends Middleware { throw new NotAdminException($this->l10n->t('Logged in account must be an admin, a sub admin or gotten special right to access this setting')); } if (!$this->remoteAddress->allowsAdminActions()) { - throw new AdminIpNotAllowedException($this->l10n->t('Your current IP address doesn’t allow you to perform admin actions')); + throw new AdminIpNotAllowedException($this->l10n->t('Your current IP address doesn\'t allow you to perform admin actions')); } } if ($this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class) @@ -173,19 +173,19 @@ class SecurityMiddleware extends Middleware { } if ($this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class) && !$this->remoteAddress->allowsAdminActions()) { - throw new AdminIpNotAllowedException($this->l10n->t('Your current IP address doesn’t allow you to perform admin actions')); + throw new AdminIpNotAllowedException($this->l10n->t('Your current IP address doesn\'t allow you to perform admin actions')); } if (!$this->hasAnnotationOrAttribute($reflectionMethod, 'SubAdminRequired', SubAdminRequired::class) && !$this->hasAnnotationOrAttribute($reflectionMethod, 'NoAdminRequired', NoAdminRequired::class) && !$this->remoteAddress->allowsAdminActions()) { - throw new AdminIpNotAllowedException($this->l10n->t('Your current IP address doesn’t allow you to perform admin actions')); + throw new AdminIpNotAllowedException($this->l10n->t('Your current IP address doesn\'t allow you to perform admin actions')); } } // Check for strict cookie requirement - if ($this->hasAnnotationOrAttribute($reflectionMethod, 'StrictCookieRequired', StrictCookiesRequired::class) || - !$this->hasAnnotationOrAttribute($reflectionMethod, 'NoCSRFRequired', NoCSRFRequired::class)) { + if ($this->hasAnnotationOrAttribute($reflectionMethod, 'StrictCookieRequired', StrictCookiesRequired::class) + || !$this->hasAnnotationOrAttribute($reflectionMethod, 'NoCSRFRequired', NoCSRFRequired::class)) { if (!$this->request->passesStrictCookieCheck()) { throw new StrictCookieMissingException(); } diff --git a/lib/private/AppFramework/OCS/BaseResponse.php b/lib/private/AppFramework/OCS/BaseResponse.php index 3b0a28fe89c..05ce133db24 100644 --- a/lib/private/AppFramework/OCS/BaseResponse.php +++ b/lib/private/AppFramework/OCS/BaseResponse.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -11,10 +12,10 @@ use OCP\AppFramework\Http\Response; /** * @psalm-import-type DataResponseType from DataResponse - * @template S of int + * @template S of Http::STATUS_* * @template-covariant T of DataResponseType * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ abstract class BaseResponse extends Response { /** @var array */ @@ -83,9 +84,9 @@ abstract class BaseResponse extends Response { */ protected function renderResult(array $meta): string { $status = $this->getStatus(); - if ($status === Http::STATUS_NO_CONTENT || - $status === Http::STATUS_NOT_MODIFIED || - ($status >= 100 && $status <= 199)) { + if ($status === Http::STATUS_NO_CONTENT + || $status === Http::STATUS_NOT_MODIFIED + || ($status >= 100 && $status <= 199)) { // Those status codes are not supposed to have a body: // https://stackoverflow.com/q/8628725 return ''; @@ -99,7 +100,7 @@ abstract class BaseResponse extends Response { ]; if ($this->format === 'json') { - return json_encode($response, JSON_HEX_TAG); + return $this->toJson($response); } $writer = new \XMLWriter(); @@ -111,6 +112,14 @@ abstract class BaseResponse extends Response { return $writer->outputMemory(true); } + /** + * @psalm-taint-escape has_quotes + * @psalm-taint-escape html + */ + protected function toJson(array $array): string { + return \json_encode($array, \JSON_HEX_TAG); + } + protected function toXML(array $array, \XMLWriter $writer): void { foreach ($array as $k => $v) { if ($k === '@attributes' && is_array($v)) { diff --git a/lib/private/AppFramework/OCS/V1Response.php b/lib/private/AppFramework/OCS/V1Response.php index c56aa9cf478..1c2c25f5cb0 100644 --- a/lib/private/AppFramework/OCS/V1Response.php +++ b/lib/private/AppFramework/OCS/V1Response.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -11,17 +12,17 @@ use OCP\AppFramework\OCSController; /** * @psalm-import-type DataResponseType from DataResponse - * @template S of int + * @template S of Http::STATUS_* * @template-covariant T of DataResponseType * @template H of array<string, mixed> - * @template-extends BaseResponse<int, DataResponseType, array<string, mixed>> + * @template-extends BaseResponse<Http::STATUS_*, DataResponseType, array<string, mixed>> */ class V1Response extends BaseResponse { /** * The V1 endpoint has very limited http status codes basically everything * is status 200 except 401 * - * @return int + * @return Http::STATUS_* */ public function getStatus() { $status = parent::getStatus(); diff --git a/lib/private/AppFramework/OCS/V2Response.php b/lib/private/AppFramework/OCS/V2Response.php index caa8302a673..efc9348eb37 100644 --- a/lib/private/AppFramework/OCS/V2Response.php +++ b/lib/private/AppFramework/OCS/V2Response.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -11,17 +12,17 @@ use OCP\AppFramework\OCSController; /** * @psalm-import-type DataResponseType from DataResponse - * @template S of int + * @template S of Http::STATUS_* * @template-covariant T of DataResponseType * @template H of array<string, mixed> - * @template-extends BaseResponse<int, DataResponseType, array<string, mixed>> + * @template-extends BaseResponse<Http::STATUS_*, DataResponseType, array<string, mixed>> */ class V2Response extends BaseResponse { /** * The V2 endpoint just passes on status codes. * Of course we have to map the OCS specific codes to proper HTTP status codes * - * @return int + * @return Http::STATUS_* */ public function getStatus() { $status = parent::getStatus(); diff --git a/lib/private/AppFramework/Routing/RouteConfig.php b/lib/private/AppFramework/Routing/RouteConfig.php deleted file mode 100644 index 2b7f21a8ba5..00000000000 --- a/lib/private/AppFramework/Routing/RouteConfig.php +++ /dev/null @@ -1,279 +0,0 @@ -<?php - -declare(strict_types=1); -/** - * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2016 ownCloud, Inc. - * SPDX-License-Identifier: AGPL-3.0-only - */ -namespace OC\AppFramework\Routing; - -use OC\AppFramework\DependencyInjection\DIContainer; -use OC\Route\Router; - -/** - * Class RouteConfig - * @package OC\AppFramework\routing - */ -class RouteConfig { - /** @var DIContainer */ - private $container; - - /** @var Router */ - private $router; - - /** @var array */ - private $routes; - - /** @var string */ - private $appName; - - /** @var string[] */ - private $controllerNameCache = []; - - protected $rootUrlApps = [ - 'cloud_federation_api', - 'core', - 'files_sharing', - 'files', - 'profile', - 'settings', - 'spreed', - ]; - - /** - * @param \OC\AppFramework\DependencyInjection\DIContainer $container - * @param \OC\Route\Router $router - * @param array $routes - * @internal param $appName - */ - public function __construct(DIContainer $container, Router $router, $routes) { - $this->routes = $routes; - $this->container = $container; - $this->router = $router; - $this->appName = $container['AppName']; - } - - /** - * The routes and resource will be registered to the \OCP\Route\IRouter - */ - public function register() { - // parse simple - $this->processIndexRoutes($this->routes); - - // parse resources - $this->processIndexResources($this->routes); - - /* - * OCS routes go into a different collection - */ - $oldCollection = $this->router->getCurrentCollection(); - $this->router->useCollection($oldCollection . '.ocs'); - - // parse ocs simple routes - $this->processOCS($this->routes); - - // parse ocs simple routes - $this->processOCSResources($this->routes); - - $this->router->useCollection($oldCollection); - } - - private function processOCS(array $routes): void { - $ocsRoutes = $routes['ocs'] ?? []; - foreach ($ocsRoutes as $ocsRoute) { - $this->processRoute($ocsRoute, 'ocs.'); - } - } - - /** - * Creates one route base on the give configuration - * @param array $routes - * @throws \UnexpectedValueException - */ - private function processIndexRoutes(array $routes): void { - $simpleRoutes = $routes['routes'] ?? []; - foreach ($simpleRoutes as $simpleRoute) { - $this->processRoute($simpleRoute); - } - } - - protected function processRoute(array $route, string $routeNamePrefix = ''): void { - $name = $route['name']; - $postfix = $route['postfix'] ?? ''; - $root = $this->buildRootPrefix($route, $routeNamePrefix); - - $url = $root . '/' . ltrim($route['url'], '/'); - $verb = strtoupper($route['verb'] ?? 'GET'); - - $split = explode('#', $name, 2); - if (count($split) !== 2) { - throw new \UnexpectedValueException('Invalid route name: use the format foo#bar to reference FooController::bar'); - } - [$controller, $action] = $split; - - $controllerName = $this->buildControllerName($controller); - $actionName = $this->buildActionName($action); - - /* - * The route name has to be lowercase, for symfony to match it correctly. - * This is required because smyfony allows mixed casing for controller names in the routes. - * To avoid breaking all the existing route names, registering and matching will only use the lowercase names. - * This is also safe on the PHP side because class and method names collide regardless of the casing. - */ - $routeName = strtolower($routeNamePrefix . $this->appName . '.' . $controller . '.' . $action . $postfix); - - $router = $this->router->create($routeName, $url) - ->method($verb); - - // optionally register requirements for route. This is used to - // tell the route parser how url parameters should be matched - if (array_key_exists('requirements', $route)) { - $router->requirements($route['requirements']); - } - - // optionally register defaults for route. This is used to - // tell the route parser how url parameters should be default valued - $defaults = []; - if (array_key_exists('defaults', $route)) { - $defaults = $route['defaults']; - } - - $defaults['caller'] = [$this->appName, $controllerName, $actionName]; - $router->defaults($defaults); - } - - /** - * For a given name and url restful OCS routes are created: - * - index - * - show - * - create - * - update - * - destroy - * - * @param array $routes - */ - private function processOCSResources(array $routes): void { - $this->processResources($routes['ocs-resources'] ?? [], 'ocs.'); - } - - /** - * For a given name and url restful routes are created: - * - index - * - show - * - create - * - update - * - destroy - * - * @param array $routes - */ - private function processIndexResources(array $routes): void { - $this->processResources($routes['resources'] ?? []); - } - - /** - * For a given name and url restful routes are created: - * - index - * - show - * - create - * - update - * - destroy - * - * @param array $resources - * @param string $routeNamePrefix - */ - protected function processResources(array $resources, string $routeNamePrefix = ''): void { - // declaration of all restful actions - $actions = [ - ['name' => 'index', 'verb' => 'GET', 'on-collection' => true], - ['name' => 'show', 'verb' => 'GET'], - ['name' => 'create', 'verb' => 'POST', 'on-collection' => true], - ['name' => 'update', 'verb' => 'PUT'], - ['name' => 'destroy', 'verb' => 'DELETE'], - ]; - - foreach ($resources as $resource => $config) { - $root = $this->buildRootPrefix($config, $routeNamePrefix); - - // the url parameter used as id to the resource - foreach ($actions as $action) { - $url = $root . '/' . ltrim($config['url'], '/'); - $method = $action['name']; - - $verb = strtoupper($action['verb'] ?? 'GET'); - $collectionAction = $action['on-collection'] ?? false; - if (!$collectionAction) { - $url .= '/{id}'; - } - if (isset($action['url-postfix'])) { - $url .= '/' . $action['url-postfix']; - } - - $controller = $resource; - - $controllerName = $this->buildControllerName($controller); - $actionName = $this->buildActionName($method); - - $routeName = $routeNamePrefix . $this->appName . '.' . strtolower($resource) . '.' . $method; - - $route = $this->router->create($routeName, $url) - ->method($verb); - - $route->defaults(['caller' => [$this->appName, $controllerName, $actionName]]); - } - } - } - - private function buildRootPrefix(array $route, string $routeNamePrefix): string { - $defaultRoot = $this->appName === 'core' ? '' : '/apps/' . $this->appName; - $root = $route['root'] ?? $defaultRoot; - - if ($routeNamePrefix !== '') { - // In OCS all apps are whitelisted - return $root; - } - - if (!\in_array($this->appName, $this->rootUrlApps, true)) { - // Only allow root URLS for some apps - return $defaultRoot; - } - - return $root; - } - - /** - * Based on a given route name the controller name is generated - * @param string $controller - * @return string - */ - private function buildControllerName(string $controller): string { - if (!isset($this->controllerNameCache[$controller])) { - $this->controllerNameCache[$controller] = $this->underScoreToCamelCase(ucfirst($controller)) . 'Controller'; - } - return $this->controllerNameCache[$controller]; - } - - /** - * Based on the action part of the route name the controller method name is generated - * @param string $action - * @return string - */ - private function buildActionName(string $action): string { - return $this->underScoreToCamelCase($action); - } - - /** - * Underscored strings are converted to camel case strings - * @param string $str - * @return string - */ - private function underScoreToCamelCase(string $str): string { - $pattern = '/_[a-z]?/'; - return preg_replace_callback( - $pattern, - function ($matches) { - return strtoupper(ltrim($matches[0], '_')); - }, - $str); - } -} diff --git a/lib/private/AppFramework/Routing/RouteParser.php b/lib/private/AppFramework/Routing/RouteParser.php index 894a74c727b..55e58234673 100644 --- a/lib/private/AppFramework/Routing/RouteParser.php +++ b/lib/private/AppFramework/Routing/RouteParser.php @@ -76,7 +76,7 @@ class RouteParser { $url = $root . '/' . ltrim($route['url'], '/'); $verb = strtoupper($route['verb'] ?? 'GET'); - $split = explode('#', $name, 2); + $split = explode('#', $name, 3); if (count($split) !== 2) { throw new \UnexpectedValueException('Invalid route name: use the format foo#bar to reference FooController::bar'); } @@ -87,7 +87,7 @@ class RouteParser { /* * The route name has to be lowercase, for symfony to match it correctly. - * This is required because smyfony allows mixed casing for controller names in the routes. + * This is required because symfony allows mixed casing for controller names in the routes. * To avoid breaking all the existing route names, registering and matching will only use the lowercase names. * This is also safe on the PHP side because class and method names collide regardless of the casing. */ diff --git a/lib/private/AppFramework/Services/AppConfig.php b/lib/private/AppFramework/Services/AppConfig.php index 423a9eb5814..04d97738483 100644 --- a/lib/private/AppFramework/Services/AppConfig.php +++ b/lib/private/AppFramework/Services/AppConfig.php @@ -337,4 +337,13 @@ class AppConfig implements IAppConfig { public function deleteUserValue(string $userId, string $key): void { $this->config->deleteUserValue($userId, $this->appName, $key); } + + /** + * Returns the installed versions of all apps + * + * @return array<string, string> + */ + public function getAppInstalledVersions(bool $onlyEnabled = false): array { + return $this->appConfig->getAppInstalledVersions($onlyEnabled); + } } diff --git a/lib/private/AppFramework/Utility/ControllerMethodReflector.php b/lib/private/AppFramework/Utility/ControllerMethodReflector.php index 2031327dfae..679e1788004 100644 --- a/lib/private/AppFramework/Utility/ControllerMethodReflector.php +++ b/lib/private/AppFramework/Utility/ControllerMethodReflector.php @@ -50,7 +50,7 @@ class ControllerMethodReflector implements IControllerMethodReflector { // extract type parameter information preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches); $this->types = array_combine($matches['var'], $matches['type']); - preg_match_all('/@psalm-param\h+(?P<type>\w+)<(?P<rangeMin>(-?\d+|min)),\h*(?P<rangeMax>(-?\d+|max))>\h+\$(?P<var>\w+)/', $docs, $matches); + preg_match_all('/@psalm-param\h+(\?)?(?P<type>\w+)<(?P<rangeMin>(-?\d+|min)),\h*(?P<rangeMax>(-?\d+|max))>(\|null)?\h+\$(?P<var>\w+)/', $docs, $matches); foreach ($matches['var'] as $index => $varName) { if ($matches['type'][$index] !== 'int') { // only int ranges are possible at the moment diff --git a/lib/private/AppFramework/Utility/SimpleContainer.php b/lib/private/AppFramework/Utility/SimpleContainer.php index 56de4a34cf6..1d77c277b02 100644 --- a/lib/private/AppFramework/Utility/SimpleContainer.php +++ b/lib/private/AppFramework/Utility/SimpleContainer.php @@ -12,6 +12,7 @@ use Closure; use OCP\AppFramework\QueryException; use OCP\IContainer; use Pimple\Container; +use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use ReflectionClass; use ReflectionException; @@ -23,8 +24,9 @@ use function class_exists; * SimpleContainer is a simple implementation of a container on basis of Pimple */ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { - /** @var Container */ - private $container; + public static bool $useLazyObjects = false; + + private Container $container; public function __construct() { $this->container = new Container(); @@ -49,16 +51,29 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { /** * @param ReflectionClass $class the class to instantiate - * @return \stdClass the created class + * @return object the created class * @suppress PhanUndeclaredClassInstanceof */ - private function buildClass(ReflectionClass $class) { + private function buildClass(ReflectionClass $class): object { $constructor = $class->getConstructor(); if ($constructor === null) { + /* No constructor, return a instance directly */ return $class->newInstance(); } + if (PHP_VERSION_ID >= 80400 && self::$useLazyObjects) { + /* For PHP>=8.4, use a lazy ghost to delay constructor and dependency resolving */ + /** @psalm-suppress UndefinedMethod */ + return $class->newLazyGhost(function (object $object) use ($constructor): void { + /** @psalm-suppress DirectConstructorCall For lazy ghosts we have to call the constructor directly */ + $object->__construct(...$this->buildClassConstructorParameters($constructor)); + }); + } else { + return $class->newInstanceArgs($this->buildClassConstructorParameters($constructor)); + } + } - return $class->newInstanceArgs(array_map(function (ReflectionParameter $parameter) { + private function buildClassConstructorParameters(\ReflectionMethod $constructor): array { + return array_map(function (ReflectionParameter $parameter) { $parameterType = $parameter->getType(); $resolveName = $parameter->getName(); @@ -69,10 +84,10 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { } try { - $builtIn = $parameter->hasType() && ($parameter->getType() instanceof ReflectionNamedType) - && $parameter->getType()->isBuiltin(); + $builtIn = $parameterType !== null && ($parameterType instanceof ReflectionNamedType) + && $parameterType->isBuiltin(); return $this->query($resolveName, !$builtIn); - } catch (QueryException $e) { + } catch (ContainerExceptionInterface $e) { // Service not found, use the default value when available if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); @@ -82,7 +97,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { $resolveName = $parameter->getName(); try { return $this->query($resolveName); - } catch (QueryException $e2) { + } catch (ContainerExceptionInterface $e2) { // Pass null if typed and nullable if ($parameter->allowsNull() && ($parameterType instanceof ReflectionNamedType)) { return null; @@ -95,7 +110,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { throw $e; } - }, $constructor->getParameters())); + }, $constructor->getParameters()); } public function resolve($name) { @@ -105,8 +120,8 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { if ($class->isInstantiable()) { return $this->buildClass($class); } else { - throw new QueryException($baseMsg . - ' Class can not be instantiated'); + throw new QueryException($baseMsg + . ' Class can not be instantiated'); } } catch (ReflectionException $e) { // Class does not exist @@ -153,13 +168,13 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { return $closure($this); }; $name = $this->sanitizeName($name); - if (isset($this[$name])) { - unset($this[$name]); + if (isset($this->container[$name])) { + unset($this->container[$name]); } if ($shared) { - $this[$name] = $wrapped; + $this->container[$name] = $wrapped; } else { - $this[$name] = $this->container->factory($wrapped); + $this->container[$name] = $this->container->factory($wrapped); } } @@ -176,7 +191,7 @@ class SimpleContainer implements ArrayAccess, ContainerInterface, IContainer { }, false); } - /* + /** * @param string $name * @return string */ diff --git a/lib/private/AppScriptDependency.php b/lib/private/AppScriptDependency.php index 380816f21ac..cc5ded0d011 100644 --- a/lib/private/AppScriptDependency.php +++ b/lib/private/AppScriptDependency.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/AppScriptSort.php b/lib/private/AppScriptSort.php index eda41e97445..134dad100dc 100644 --- a/lib/private/AppScriptSort.php +++ b/lib/private/AppScriptSort.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Authentication/Login/Chain.php b/lib/private/Authentication/Login/Chain.php index 3cba396afdd..fc90d9225a7 100644 --- a/lib/private/Authentication/Login/Chain.php +++ b/lib/private/Authentication/Login/Chain.php @@ -9,67 +9,20 @@ declare(strict_types=1); namespace OC\Authentication\Login; class Chain { - /** @var PreLoginHookCommand */ - private $preLoginHookCommand; - - /** @var UserDisabledCheckCommand */ - private $userDisabledCheckCommand; - - /** @var UidLoginCommand */ - private $uidLoginCommand; - - /** @var EmailLoginCommand */ - private $emailLoginCommand; - - /** @var LoggedInCheckCommand */ - private $loggedInCheckCommand; - - /** @var CompleteLoginCommand */ - private $completeLoginCommand; - - /** @var CreateSessionTokenCommand */ - private $createSessionTokenCommand; - - /** @var ClearLostPasswordTokensCommand */ - private $clearLostPasswordTokensCommand; - - /** @var UpdateLastPasswordConfirmCommand */ - private $updateLastPasswordConfirmCommand; - - /** @var SetUserTimezoneCommand */ - private $setUserTimezoneCommand; - - /** @var TwoFactorCommand */ - private $twoFactorCommand; - - /** @var FinishRememberedLoginCommand */ - private $finishRememberedLoginCommand; - - public function __construct(PreLoginHookCommand $preLoginHookCommand, - UserDisabledCheckCommand $userDisabledCheckCommand, - UidLoginCommand $uidLoginCommand, - EmailLoginCommand $emailLoginCommand, - LoggedInCheckCommand $loggedInCheckCommand, - CompleteLoginCommand $completeLoginCommand, - CreateSessionTokenCommand $createSessionTokenCommand, - ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand, - UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand, - SetUserTimezoneCommand $setUserTimezoneCommand, - TwoFactorCommand $twoFactorCommand, - FinishRememberedLoginCommand $finishRememberedLoginCommand, + public function __construct( + private PreLoginHookCommand $preLoginHookCommand, + private UserDisabledCheckCommand $userDisabledCheckCommand, + private UidLoginCommand $uidLoginCommand, + private LoggedInCheckCommand $loggedInCheckCommand, + private CompleteLoginCommand $completeLoginCommand, + private CreateSessionTokenCommand $createSessionTokenCommand, + private ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand, + private UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand, + private SetUserTimezoneCommand $setUserTimezoneCommand, + private TwoFactorCommand $twoFactorCommand, + private FinishRememberedLoginCommand $finishRememberedLoginCommand, + private FlowV2EphemeralSessionsCommand $flowV2EphemeralSessionsCommand, ) { - $this->preLoginHookCommand = $preLoginHookCommand; - $this->userDisabledCheckCommand = $userDisabledCheckCommand; - $this->uidLoginCommand = $uidLoginCommand; - $this->emailLoginCommand = $emailLoginCommand; - $this->loggedInCheckCommand = $loggedInCheckCommand; - $this->completeLoginCommand = $completeLoginCommand; - $this->createSessionTokenCommand = $createSessionTokenCommand; - $this->clearLostPasswordTokensCommand = $clearLostPasswordTokensCommand; - $this->updateLastPasswordConfirmCommand = $updateLastPasswordConfirmCommand; - $this->setUserTimezoneCommand = $setUserTimezoneCommand; - $this->twoFactorCommand = $twoFactorCommand; - $this->finishRememberedLoginCommand = $finishRememberedLoginCommand; } public function process(LoginData $loginData): LoginResult { @@ -77,9 +30,9 @@ class Chain { $chain ->setNext($this->userDisabledCheckCommand) ->setNext($this->uidLoginCommand) - ->setNext($this->emailLoginCommand) ->setNext($this->loggedInCheckCommand) ->setNext($this->completeLoginCommand) + ->setNext($this->flowV2EphemeralSessionsCommand) ->setNext($this->createSessionTokenCommand) ->setNext($this->clearLostPasswordTokensCommand) ->setNext($this->updateLastPasswordConfirmCommand) diff --git a/lib/private/Authentication/Login/EmailLoginCommand.php b/lib/private/Authentication/Login/EmailLoginCommand.php deleted file mode 100644 index 96cb39277fd..00000000000 --- a/lib/private/Authentication/Login/EmailLoginCommand.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -namespace OC\Authentication\Login; - -use OCP\IUserManager; - -class EmailLoginCommand extends ALoginCommand { - /** @var IUserManager */ - private $userManager; - - public function __construct(IUserManager $userManager) { - $this->userManager = $userManager; - } - - public function process(LoginData $loginData): LoginResult { - if ($loginData->getUser() === false) { - if (!filter_var($loginData->getUsername(), FILTER_VALIDATE_EMAIL)) { - return $this->processNextOrFinishSuccessfully($loginData); - } - - $users = $this->userManager->getByEmail($loginData->getUsername()); - // we only allow login by email if unique - if (count($users) === 1) { - // FIXME: This is a workaround to still stick to configured LDAP login filters - // this can be removed once the email login is properly implemented in the local user backend - // as described in https://github.com/nextcloud/server/issues/5221 - if ($users[0]->getBackendClassName() === 'LDAP') { - return $this->processNextOrFinishSuccessfully($loginData); - } - - $username = $users[0]->getUID(); - if ($username !== $loginData->getUsername()) { - $user = $this->userManager->checkPassword( - $username, - $loginData->getPassword() - ); - if ($user !== false) { - $loginData->setUser($user); - $loginData->setUsername($username); - } - } - } - } - - return $this->processNextOrFinishSuccessfully($loginData); - } -} diff --git a/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php b/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php new file mode 100644 index 00000000000..82dd829334d --- /dev/null +++ b/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Authentication\Login; + +use OC\Core\Controller\ClientFlowLoginV2Controller; +use OCP\ISession; +use OCP\IURLGenerator; + +class FlowV2EphemeralSessionsCommand extends ALoginCommand { + public function __construct( + private ISession $session, + private IURLGenerator $urlGenerator, + ) { + } + + public function process(LoginData $loginData): LoginResult { + $loginV2GrantRoute = $this->urlGenerator->linkToRoute('core.ClientFlowLoginV2.grantPage'); + if (str_starts_with($loginData->getRedirectUrl() ?? '', $loginV2GrantRoute)) { + $this->session->set(ClientFlowLoginV2Controller::EPHEMERAL_NAME, true); + } + + return $this->processNextOrFinishSuccessfully($loginData); + } +} diff --git a/lib/private/Authentication/LoginCredentials/Credentials.php b/lib/private/Authentication/LoginCredentials/Credentials.php index 2d7ed3adfd0..3414034b33c 100644 --- a/lib/private/Authentication/LoginCredentials/Credentials.php +++ b/lib/private/Authentication/LoginCredentials/Credentials.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Authentication/LoginCredentials/Store.php b/lib/private/Authentication/LoginCredentials/Store.php index b6f22ce345f..67c5712715c 100644 --- a/lib/private/Authentication/LoginCredentials/Store.php +++ b/lib/private/Authentication/LoginCredentials/Store.php @@ -50,7 +50,9 @@ class Store implements IStore { * @param array $params */ public function authenticate(array $params) { - $params['password'] = $this->crypto->encrypt((string)$params['password']); + if ($params['password'] !== null) { + $params['password'] = $this->crypto->encrypt((string)$params['password']); + } $this->session->set('login_credentials', json_encode($params)); } @@ -97,10 +99,12 @@ class Store implements IStore { if ($trySession && $this->session->exists('login_credentials')) { /** @var array $creds */ $creds = json_decode($this->session->get('login_credentials'), true); - try { - $creds['password'] = $this->crypto->decrypt($creds['password']); - } catch (Exception $e) { - //decryption failed, continue with old password as it is + if ($creds['password'] !== null) { + try { + $creds['password'] = $this->crypto->decrypt($creds['password']); + } catch (Exception $e) { + //decryption failed, continue with old password as it is + } } return new Credentials( $creds['uid'], diff --git a/lib/private/Authentication/Token/TokenCleanupJob.php b/lib/private/Authentication/Token/TokenCleanupJob.php index 041d2e8a5e2..e6d1e69e9b4 100644 --- a/lib/private/Authentication/Token/TokenCleanupJob.php +++ b/lib/private/Authentication/Token/TokenCleanupJob.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-only diff --git a/lib/private/Authentication/TwoFactorAuth/Manager.php b/lib/private/Authentication/TwoFactorAuth/Manager.php index 1b22300e317..07aa98610ed 100644 --- a/lib/private/Authentication/TwoFactorAuth/Manager.php +++ b/lib/private/Authentication/TwoFactorAuth/Manager.php @@ -308,8 +308,8 @@ class Manager { // First check if the session tells us we should do 2FA (99% case) if (!$this->session->exists(self::SESSION_UID_KEY)) { // Check if the session tells us it is 2FA authenticated already - if ($this->session->exists(self::SESSION_UID_DONE) && - $this->session->get(self::SESSION_UID_DONE) === $user->getUID()) { + if ($this->session->exists(self::SESSION_UID_DONE) + && $this->session->get(self::SESSION_UID_DONE) === $user->getUID()) { return false; } diff --git a/lib/private/Authentication/WebAuthn/Manager.php b/lib/private/Authentication/WebAuthn/Manager.php index e65002632d8..96dc0719b54 100644 --- a/lib/private/Authentication/WebAuthn/Manager.php +++ b/lib/private/Authentication/WebAuthn/Manager.php @@ -246,14 +246,6 @@ class Manager { } public function isWebAuthnAvailable(): bool { - if (!extension_loaded('bcmath')) { - return false; - } - - if (!extension_loaded('gmp')) { - return false; - } - if (!$this->config->getSystemValueBool('auth.webauthn.enabled', true)) { return false; } diff --git a/lib/private/Avatar/UserAvatar.php b/lib/private/Avatar/UserAvatar.php index 51c44b23a55..bef0a20e7b8 100644 --- a/lib/private/Avatar/UserAvatar.php +++ b/lib/private/Avatar/UserAvatar.php @@ -82,8 +82,8 @@ class UserAvatar extends Avatar { $img = new \OCP\Image(); if ( - (is_resource($data) && get_resource_type($data) === 'gd') || - (is_object($data) && get_class($data) === \GdImage::class) + (is_resource($data) && get_resource_type($data) === 'gd') + || (is_object($data) && get_class($data) === \GdImage::class) ) { $img->setResource($data); } elseif (is_resource($data)) { diff --git a/lib/private/BackgroundJob/JobList.php b/lib/private/BackgroundJob/JobList.php index 55521421711..0d88200cff7 100644 --- a/lib/private/BackgroundJob/JobList.php +++ b/lib/private/BackgroundJob/JobList.php @@ -20,6 +20,7 @@ use OCP\IDBConnection; use Psr\Log\LoggerInterface; use function get_class; use function json_encode; +use function min; use function strlen; class JobList implements IJobList { @@ -206,7 +207,27 @@ class JobList implements IJobList { $update->setParameter('jobid', $row['id']); $update->executeStatement(); - return $this->getNext($onlyTimeSensitive); + return $this->getNext($onlyTimeSensitive, $jobClasses); + } + + if ($job instanceof \OCP\BackgroundJob\TimedJob) { + $now = $this->timeFactory->getTime(); + $nextPossibleRun = $job->getLastRun() + $job->getInterval(); + if ($now < $nextPossibleRun) { + // This job is not ready for execution yet. Set timestamps to the future to avoid + // re-checking with every cron run. + // To avoid bugs that lead to jobs never executing again, the future timestamp is + // capped at two days. + $nextCheck = min($nextPossibleRun, $now + 48 * 3600); + $updateTimedJob = $this->connection->getQueryBuilder(); + $updateTimedJob->update('jobs') + ->set('last_checked', $updateTimedJob->createNamedParameter($nextCheck, IQueryBuilder::PARAM_INT)) + ->where($updateTimedJob->expr()->eq('id', $updateTimedJob->createParameter('jobid'))); + $updateTimedJob->setParameter('jobid', $row['id']); + $updateTimedJob->executeStatement(); + + return $this->getNext($onlyTimeSensitive, $jobClasses); + } } $update = $this->connection->getQueryBuilder(); diff --git a/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php b/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php index 1d0a502df6d..8faf4627251 100644 --- a/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php +++ b/lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php @@ -19,6 +19,7 @@ use OCP\Files\NotPermittedException; use OCP\FilesMetadata\AMetadataEvent; use OCP\FilesMetadata\Event\MetadataBackgroundEvent; use OCP\FilesMetadata\Event\MetadataLiveEvent; +use OCP\IPreview; use OCP\Lock\LockedException; /** @@ -27,11 +28,14 @@ use OCP\Lock\LockedException; * @template-implements IEventListener<AMetadataEvent> */ class GenerateBlurhashMetadata implements IEventListener { - private const RESIZE_BOXSIZE = 300; - private const COMPONENTS_X = 4; private const COMPONENTS_Y = 3; + public function __construct( + private IPreview $preview, + ) { + } + /** * @throws NotPermittedException * @throws GenericFileException @@ -64,42 +68,20 @@ class GenerateBlurhashMetadata implements IEventListener { return; } - $image = $this->resizedImageFromFile($file); - if (!$image) { + // Preview are disabled, so we skip generating the blurhash. + if (!$this->preview->isAvailable($file)) { return; } - $metadata->setString('blurhash', $this->generateBlurHash($image)) - ->setEtag('blurhash', $currentEtag); - } - - /** - * @param File $file - * - * @return GdImage|false - * @throws GenericFileException - * @throws NotPermittedException - * @throws LockedException - */ - private function resizedImageFromFile(File $file): GdImage|false { - $image = @imagecreatefromstring($file->getContent()); - if ($image === false) { - return false; - } - - $currX = imagesx($image); - $currY = imagesy($image); + $preview = $this->preview->getPreview($file, 64, 64, cacheResult: false); + $image = @imagecreatefromstring($preview->getContent()); - if ($currX > $currY) { - $newX = self::RESIZE_BOXSIZE; - $newY = intval($currY * $newX / $currX); - } else { - $newY = self::RESIZE_BOXSIZE; - $newX = intval($currX * $newY / $currY); + if (!$image) { + return; } - $newImage = imagescale($image, $newX, $newY); - return ($newImage !== false) ? $newImage : $image; + $metadata->setString('blurhash', $this->generateBlurHash($image)) + ->setEtag('blurhash', $currentEtag); } /** diff --git a/lib/private/Calendar/AvailabilityResult.php b/lib/private/Calendar/AvailabilityResult.php new file mode 100644 index 00000000000..8031758f64e --- /dev/null +++ b/lib/private/Calendar/AvailabilityResult.php @@ -0,0 +1,28 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Calendar; + +use OCP\Calendar\IAvailabilityResult; + +class AvailabilityResult implements IAvailabilityResult { + public function __construct( + private readonly string $attendee, + private readonly bool $available, + ) { + } + + public function getAttendeeEmail(): string { + return $this->attendee; + } + + public function isAvailable(): bool { + return $this->available; + } +} diff --git a/lib/private/Calendar/CalendarEventBuilder.php b/lib/private/Calendar/CalendarEventBuilder.php new file mode 100644 index 00000000000..1aa11c2436d --- /dev/null +++ b/lib/private/Calendar/CalendarEventBuilder.php @@ -0,0 +1,147 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Calendar; + +use DateTimeInterface; +use InvalidArgumentException; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Calendar\CalendarEventStatus; +use OCP\Calendar\ICalendarEventBuilder; +use OCP\Calendar\ICreateFromString; +use Sabre\VObject\Component\VCalendar; +use Sabre\VObject\Component\VEvent; + +class CalendarEventBuilder implements ICalendarEventBuilder { + private ?DateTimeInterface $startDate = null; + private ?DateTimeInterface $endDate = null; + private ?string $summary = null; + private ?string $description = null; + private ?string $location = null; + private ?CalendarEventStatus $status = null; + private ?array $organizer = null; + private array $attendees = []; + + public function __construct( + private readonly string $uid, + private readonly ITimeFactory $timeFactory, + ) { + } + + public function setStartDate(DateTimeInterface $start): ICalendarEventBuilder { + $this->startDate = $start; + return $this; + } + + public function setEndDate(DateTimeInterface $end): ICalendarEventBuilder { + $this->endDate = $end; + return $this; + } + + public function setSummary(string $summary): ICalendarEventBuilder { + $this->summary = $summary; + return $this; + } + + public function setDescription(string $description): ICalendarEventBuilder { + $this->description = $description; + return $this; + } + + public function setLocation(string $location): ICalendarEventBuilder { + $this->location = $location; + return $this; + } + + public function setStatus(CalendarEventStatus $status): static { + $this->status = $status; + return $this; + } + + public function setOrganizer(string $email, ?string $commonName = null): ICalendarEventBuilder { + $this->organizer = [$email, $commonName]; + return $this; + } + + public function addAttendee(string $email, ?string $commonName = null): ICalendarEventBuilder { + $this->attendees[] = [$email, $commonName]; + return $this; + } + + public function toIcs(): string { + if ($this->startDate === null) { + throw new InvalidArgumentException('Event is missing a start date'); + } + + if ($this->endDate === null) { + throw new InvalidArgumentException('Event is missing an end date'); + } + + if ($this->summary === null) { + throw new InvalidArgumentException('Event is missing a summary'); + } + + if ($this->organizer === null && $this->attendees !== []) { + throw new InvalidArgumentException('Event has attendees but is missing an organizer'); + } + + $vcalendar = new VCalendar(); + $props = [ + 'UID' => $this->uid, + 'DTSTAMP' => $this->timeFactory->now(), + 'SUMMARY' => $this->summary, + 'DTSTART' => $this->startDate, + 'DTEND' => $this->endDate, + 'STATUS' => $this->status->value, + ]; + if ($this->description !== null) { + $props['DESCRIPTION'] = $this->description; + } + if ($this->location !== null) { + $props['LOCATION'] = $this->location; + } + /** @var VEvent $vevent */ + $vevent = $vcalendar->add('VEVENT', $props); + if ($this->organizer !== null) { + self::addAttendeeToVEvent($vevent, 'ORGANIZER', $this->organizer); + } + foreach ($this->attendees as $attendee) { + self::addAttendeeToVEvent($vevent, 'ATTENDEE', $attendee); + } + return $vcalendar->serialize(); + } + + public function createInCalendar(ICreateFromString $calendar): string { + $fileName = $this->uid . '.ics'; + $calendar->createFromString($fileName, $this->toIcs()); + return $fileName; + } + + /** + * @param array{0: string, 1: ?string} $tuple A tuple of [$email, $commonName] where $commonName may be null. + */ + private static function addAttendeeToVEvent(VEvent $vevent, string $name, array $tuple): void { + [$email, $cn] = $tuple; + if (!str_starts_with($email, 'mailto:')) { + $email = "mailto:$email"; + } + $params = []; + if ($cn !== null) { + $params['CN'] = $cn; + if ($name === 'ORGANIZER') { + $params['ROLE'] = 'CHAIR'; + $params['PARTSTAT'] = 'ACCEPTED'; + } else { + $params['ROLE'] = 'REQ-PARTICIPANT'; + $params['PARTSTAT'] = 'NEEDS-ACTION'; + } + } + $vevent->add($name, $email, $params); + } +} diff --git a/lib/private/Calendar/Manager.php b/lib/private/Calendar/Manager.php index ba2124a5c23..0e2a3f5f679 100644 --- a/lib/private/Calendar/Manager.php +++ b/lib/private/Calendar/Manager.php @@ -8,10 +8,14 @@ declare(strict_types=1); */ namespace OC\Calendar; +use DateTimeInterface; use OC\AppFramework\Bootstrap\Coordinator; +use OCA\DAV\CalDAV\Auth\CustomPrincipalPlugin; +use OCA\DAV\ServerFactory; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Calendar\Exceptions\CalendarException; use OCP\Calendar\ICalendar; +use OCP\Calendar\ICalendarEventBuilder; use OCP\Calendar\ICalendarIsShared; use OCP\Calendar\ICalendarIsWritable; use OCP\Calendar\ICalendarProvider; @@ -19,10 +23,17 @@ use OCP\Calendar\ICalendarQuery; use OCP\Calendar\ICreateFromString; use OCP\Calendar\IHandleImipMessage; use OCP\Calendar\IManager; +use OCP\IUser; +use OCP\IUserManager; +use OCP\Security\ISecureRandom; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; +use Sabre\HTTP\Request; +use Sabre\HTTP\Response; use Sabre\VObject\Component\VCalendar; use Sabre\VObject\Component\VEvent; +use Sabre\VObject\Component\VFreeBusy; +use Sabre\VObject\ParseException; use Sabre\VObject\Property\VCard\DateTime; use Sabre\VObject\Reader; use Throwable; @@ -45,6 +56,9 @@ class Manager implements IManager { private ContainerInterface $container, private LoggerInterface $logger, private ITimeFactory $timeFactory, + private ISecureRandom $random, + private IUserManager $userManager, + private ServerFactory $serverFactory, ) { } @@ -216,38 +230,49 @@ class Manager implements IManager { string $recipient, string $calendarData, ): bool { - + $userCalendars = $this->getCalendarsForPrincipal($principalUri); if (empty($userCalendars)) { $this->logger->warning('iMip message could not be processed because user has no calendars'); return false; } - - /** @var VCalendar $vObject|null */ - $calendarObject = Reader::read($calendarData); - + + try { + /** @var VCalendar $vObject|null */ + $calendarObject = Reader::read($calendarData); + } catch (ParseException $e) { + $this->logger->error('iMip message could not be processed because an error occurred while parsing the iMip message', ['exception' => $e]); + return false; + } + if (!isset($calendarObject->METHOD) || $calendarObject->METHOD->getValue() !== 'REQUEST') { $this->logger->warning('iMip message contains an incorrect or invalid method'); return false; } - + if (!isset($calendarObject->VEVENT)) { $this->logger->warning('iMip message contains no event'); return false; } + /** @var VEvent|null $vEvent */ $eventObject = $calendarObject->VEVENT; if (!isset($eventObject->UID)) { $this->logger->warning('iMip message event dose not contains a UID'); return false; } - + + if (!isset($eventObject->ORGANIZER)) { + $this->logger->warning('iMip message event dose not contains an organizer'); + return false; + } + if (!isset($eventObject->ATTENDEE)) { $this->logger->warning('iMip message event dose not contains any attendees'); return false; } - + foreach ($eventObject->ATTENDEE as $entry) { $address = trim(str_replace('mailto:', '', $entry->getValue())); if ($address === $recipient) { @@ -259,17 +284,17 @@ class Manager implements IManager { $this->logger->warning('iMip message event does not contain a attendee that matches the recipient'); return false; } - + foreach ($userCalendars as $calendar) { - + if (!$calendar instanceof ICalendarIsWritable && !$calendar instanceof ICalendarIsShared) { continue; } - + if ($calendar->isDeleted() || !$calendar->isWritable() || $calendar->isShared()) { continue; } - + if (!empty($calendar->search($recipient, ['ATTENDEE'], ['uid' => $eventObject->UID->getValue()]))) { try { if ($calendar instanceof IHandleImipMessage) { @@ -282,8 +307,8 @@ class Manager implements IManager { } } } - - $this->logger->warning('iMip message event could not be processed because the no corresponding event was found in any calendar'); + + $this->logger->warning('iMip message event could not be processed because no corresponding event was found in any calendar'); return false; } @@ -296,23 +321,51 @@ class Manager implements IManager { string $recipient, string $calendarData, ): bool { - /** @var VCalendar $vObject|null */ - $vObject = Reader::read($calendarData); + + $calendars = $this->getCalendarsForPrincipal($principalUri); + if (empty($calendars)) { + $this->logger->warning('iMip message could not be processed because user has no calendars'); + return false; + } + + try { + /** @var VCalendar $vObject|null */ + $vObject = Reader::read($calendarData); + } catch (ParseException $e) { + $this->logger->error('iMip message could not be processed because an error occurred while parsing the iMip message', ['exception' => $e]); + return false; + } if ($vObject === null) { + $this->logger->warning('iMip message contains an invalid calendar object'); + return false; + } + + if (!isset($vObject->METHOD) || $vObject->METHOD->getValue() !== 'REPLY') { + $this->logger->warning('iMip message contains an incorrect or invalid method'); + return false; + } + + if (!isset($vObject->VEVENT)) { + $this->logger->warning('iMip message contains no event'); return false; } /** @var VEvent|null $vEvent */ - $vEvent = $vObject->{'VEVENT'}; + $vEvent = $vObject->VEVENT; + + if (!isset($vEvent->UID)) { + $this->logger->warning('iMip message event dose not contains a UID'); + return false; + } - if ($vEvent === null) { + if (!isset($vEvent->ORGANIZER)) { + $this->logger->warning('iMip message event dose not contains an organizer'); return false; } - // First, we check if the correct method is passed to us - if (strcasecmp('REPLY', $vObject->{'METHOD'}->getValue()) !== 0) { - $this->logger->warning('Wrong method provided for processing'); + if (!isset($vEvent->ATTENDEE)) { + $this->logger->warning('iMip message event dose not contains any attendees'); return false; } @@ -320,7 +373,7 @@ class Manager implements IManager { $organizer = substr($vEvent->{'ORGANIZER'}->getValue(), 7); if (strcasecmp($recipient, $organizer) !== 0) { - $this->logger->warning('Recipient and ORGANIZER must be identical'); + $this->logger->warning('iMip message event could not be processed because recipient and ORGANIZER must be identical'); return false; } @@ -328,13 +381,7 @@ class Manager implements IManager { /** @var DateTime $eventTime */ $eventTime = $vEvent->{'DTSTART'}; if ($eventTime->getDateTime()->getTimeStamp() < $this->timeFactory->getTime()) { // this might cause issues with recurrences - $this->logger->warning('Only events in the future are processed'); - return false; - } - - $calendars = $this->getCalendarsForPrincipal($principalUri); - if (empty($calendars)) { - $this->logger->warning('Could not find any calendars for principal ' . $principalUri); + $this->logger->warning('iMip message event could not be processed because the event is in the past'); return false; } @@ -356,14 +403,14 @@ class Manager implements IManager { } if (empty($found)) { - $this->logger->info('Event not found in any calendar for principal ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue()); + $this->logger->warning('iMip message event could not be processed because no corresponding event was found in any calendar ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue()); return false; } try { $found->handleIMipMessage($name, $calendarData); // sabre will handle the scheduling behind the scenes } catch (CalendarException $e) { - $this->logger->error('Could not update calendar for iMIP processing', ['exception' => $e]); + $this->logger->error('An error occurred while processing the iMip message event', ['exception' => $e]); return false; } return true; @@ -380,29 +427,57 @@ class Manager implements IManager { string $recipient, string $calendarData, ): bool { - /** @var VCalendar $vObject|null */ - $vObject = Reader::read($calendarData); + + $calendars = $this->getCalendarsForPrincipal($principalUri); + if (empty($calendars)) { + $this->logger->warning('iMip message could not be processed because user has no calendars'); + return false; + } + + try { + /** @var VCalendar $vObject|null */ + $vObject = Reader::read($calendarData); + } catch (ParseException $e) { + $this->logger->error('iMip message could not be processed because an error occurred while parsing the iMip message', ['exception' => $e]); + return false; + } if ($vObject === null) { + $this->logger->warning('iMip message contains an invalid calendar object'); + return false; + } + + if (!isset($vObject->METHOD) || $vObject->METHOD->getValue() !== 'CANCEL') { + $this->logger->warning('iMip message contains an incorrect or invalid method'); + return false; + } + + if (!isset($vObject->VEVENT)) { + $this->logger->warning('iMip message contains no event'); return false; } /** @var VEvent|null $vEvent */ $vEvent = $vObject->{'VEVENT'}; - if ($vEvent === null) { + if (!isset($vEvent->UID)) { + $this->logger->warning('iMip message event dose not contains a UID'); return false; } - // First, we check if the correct method is passed to us - if (strcasecmp('CANCEL', $vObject->{'METHOD'}->getValue()) !== 0) { - $this->logger->warning('Wrong method provided for processing'); + if (!isset($vEvent->ORGANIZER)) { + $this->logger->warning('iMip message event dose not contains an organizer'); + return false; + } + + if (!isset($vEvent->ATTENDEE)) { + $this->logger->warning('iMip message event dose not contains any attendees'); return false; } $attendee = substr($vEvent->{'ATTENDEE'}->getValue(), 7); if (strcasecmp($recipient, $attendee) !== 0) { - $this->logger->warning('Recipient must be an ATTENDEE of this event'); + $this->logger->warning('iMip message event could not be processed because recipient must be an ATTENDEE of this event'); return false; } @@ -413,7 +488,7 @@ class Manager implements IManager { $organizer = substr($vEvent->{'ORGANIZER'}->getValue(), 7); $isNotOrganizer = ($replyTo !== null) ? (strcasecmp($sender, $organizer) !== 0 && strcasecmp($replyTo, $organizer) !== 0) : (strcasecmp($sender, $organizer) !== 0); if ($isNotOrganizer) { - $this->logger->warning('Sender must be the ORGANIZER of this event'); + $this->logger->warning('iMip message event could not be processed because sender must be the ORGANIZER of this event'); return false; } @@ -421,14 +496,7 @@ class Manager implements IManager { /** @var DateTime $eventTime */ $eventTime = $vEvent->{'DTSTART'}; if ($eventTime->getDateTime()->getTimeStamp() < $this->timeFactory->getTime()) { // this might cause issues with recurrences - $this->logger->warning('Only events in the future are processed'); - return false; - } - - // Check if we have a calendar to work with - $calendars = $this->getCalendarsForPrincipal($principalUri); - if (empty($calendars)) { - $this->logger->warning('Could not find any calendars for principal ' . $principalUri); + $this->logger->warning('iMip message event could not be processed because the event is in the past'); return false; } @@ -450,18 +518,104 @@ class Manager implements IManager { } if (empty($found)) { - $this->logger->info('Event not found in any calendar for principal ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue()); - // this is a safe operation - // we can ignore events that have been cancelled but were not in the calendar anyway - return true; + $this->logger->warning('iMip message event could not be processed because no corresponding event was found in any calendar ' . $principalUri . 'and UID' . $vEvent->{'UID'}->getValue()); + return false; } try { $found->handleIMipMessage($name, $calendarData); // sabre will handle the scheduling behind the scenes return true; } catch (CalendarException $e) { - $this->logger->error('Could not update calendar for iMIP processing', ['exception' => $e]); + $this->logger->error('An error occurred while processing the iMip message event', ['exception' => $e]); return false; } } + + public function createEventBuilder(): ICalendarEventBuilder { + $uid = $this->random->generate(32, ISecureRandom::CHAR_ALPHANUMERIC); + return new CalendarEventBuilder($uid, $this->timeFactory); + } + + public function checkAvailability( + DateTimeInterface $start, + DateTimeInterface $end, + IUser $organizer, + array $attendees, + ): array { + $organizerMailto = 'mailto:' . $organizer->getEMailAddress(); + $request = new VCalendar(); + $request->METHOD = 'REQUEST'; + $request->add('VFREEBUSY', [ + 'DTSTART' => $start, + 'DTEND' => $end, + 'ORGANIZER' => $organizerMailto, + 'ATTENDEE' => $organizerMailto, + ]); + + $mailtoLen = strlen('mailto:'); + foreach ($attendees as $attendee) { + if (str_starts_with($attendee, 'mailto:')) { + $attendee = substr($attendee, $mailtoLen); + } + + $attendeeUsers = $this->userManager->getByEmail($attendee); + if ($attendeeUsers === []) { + continue; + } + + $request->VFREEBUSY->add('ATTENDEE', "mailto:$attendee"); + } + + $organizerUid = $organizer->getUID(); + $server = $this->serverFactory->createAttendeeAvailabilityServer(); + /** @var CustomPrincipalPlugin $plugin */ + $plugin = $server->getPlugin('auth'); + $plugin->setCurrentPrincipal("principals/users/$organizerUid"); + + $request = new Request( + 'POST', + "/calendars/$organizerUid/outbox/", + [ + 'Content-Type' => 'text/calendar', + 'Depth' => 0, + ], + $request->serialize(), + ); + $response = new Response(); + $server->invokeMethod($request, $response, false); + + $xmlService = new \Sabre\Xml\Service(); + $xmlService->elementMap = [ + '{urn:ietf:params:xml:ns:caldav}response' => 'Sabre\Xml\Deserializer\keyValue', + '{urn:ietf:params:xml:ns:caldav}recipient' => 'Sabre\Xml\Deserializer\keyValue', + ]; + $parsedResponse = $xmlService->parse($response->getBodyAsString()); + + $result = []; + foreach ($parsedResponse as $freeBusyResponse) { + $freeBusyResponse = $freeBusyResponse['value']; + if ($freeBusyResponse['{urn:ietf:params:xml:ns:caldav}request-status'] !== '2.0;Success') { + continue; + } + + $freeBusyResponseData = \Sabre\VObject\Reader::read( + $freeBusyResponse['{urn:ietf:params:xml:ns:caldav}calendar-data'] + ); + + $attendee = substr( + $freeBusyResponse['{urn:ietf:params:xml:ns:caldav}recipient']['{DAV:}href'], + $mailtoLen, + ); + + $vFreeBusy = $freeBusyResponseData->VFREEBUSY; + if (!($vFreeBusy instanceof VFreeBusy)) { + continue; + } + + // TODO: actually check values of FREEBUSY properties to find a free slot + $result[] = new AvailabilityResult($attendee, $vFreeBusy->isFree($start, $end)); + } + + return $result; + } } diff --git a/lib/private/CapabilitiesManager.php b/lib/private/CapabilitiesManager.php index d7bf25f078a..07076d9aacd 100644 --- a/lib/private/CapabilitiesManager.php +++ b/lib/private/CapabilitiesManager.php @@ -32,7 +32,7 @@ class CapabilitiesManager { } /** - * Get an array of al the capabilities that are registered at this manager + * Get an array of all the capabilities that are registered at this manager * * @param bool $public get public capabilities only * @throws \InvalidArgumentException diff --git a/lib/private/Collaboration/AutoComplete/Manager.php b/lib/private/Collaboration/AutoComplete/Manager.php index c4dd4093e69..cc5df78beea 100644 --- a/lib/private/Collaboration/AutoComplete/Manager.php +++ b/lib/private/Collaboration/AutoComplete/Manager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Collaboration/Collaborators/GroupPlugin.php b/lib/private/Collaboration/Collaborators/GroupPlugin.php index a7b84b72199..a59d5981825 100644 --- a/lib/private/Collaboration/Collaborators/GroupPlugin.php +++ b/lib/private/Collaboration/Collaborators/GroupPlugin.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Collaboration/Collaborators/LookupPlugin.php b/lib/private/Collaboration/Collaborators/LookupPlugin.php index 8b46ad5e072..fb6b9f2e0e8 100644 --- a/lib/private/Collaboration/Collaborators/LookupPlugin.php +++ b/lib/private/Collaboration/Collaborators/LookupPlugin.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -32,11 +33,13 @@ class LookupPlugin implements ISearchPlugin { public function search($search, $limit, $offset, ISearchResult $searchResult): bool { $isGlobalScaleEnabled = $this->config->getSystemValueBool('gs.enabled', false); - $isLookupServerEnabled = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes') === 'yes'; + $isLookupServerEnabled = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'no') === 'yes'; $hasInternetConnection = $this->config->getSystemValueBool('has_internet_connection', true); - // if case of Global Scale we always search the lookup server - if (!$isGlobalScaleEnabled && (!$isLookupServerEnabled || !$hasInternetConnection)) { + // If case of Global Scale we always search the lookup server + // TODO: Reconsider using the lookup server for non-global scale + // if (!$isGlobalScaleEnabled && (!$isLookupServerEnabled || !$hasInternetConnection || $disableLookupServer)) { + if (!$isGlobalScaleEnabled) { return false; } diff --git a/lib/private/Collaboration/Collaborators/MailPlugin.php b/lib/private/Collaboration/Collaborators/MailPlugin.php index 134970518bc..55e3945ace2 100644 --- a/lib/private/Collaboration/Collaborators/MailPlugin.php +++ b/lib/private/Collaboration/Collaborators/MailPlugin.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -100,6 +101,11 @@ class MailPlugin implements ISearchPlugin { $emailAddress = $emailAddressData['value']; $emailAddressType = $emailAddressData['type']; } + + if (!filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) { + continue; + } + if (isset($contact['FN'])) { $displayName = $contact['FN'] . ' (' . $emailAddress . ')'; } @@ -223,8 +229,8 @@ class MailPlugin implements ISearchPlugin { $reachedEnd = true; if ($this->shareeEnumeration) { - $reachedEnd = (count($result['wide']) < $offset + $limit) && - (count($userResults['wide']) < $offset + $limit); + $reachedEnd = (count($result['wide']) < $offset + $limit) + && (count($userResults['wide']) < $offset + $limit); $result['wide'] = array_slice($result['wide'], $offset, $limit); $userResults['wide'] = array_slice($userResults['wide'], $offset, $limit); diff --git a/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php index 89d5c4e4f79..f4c1793ea0a 100644 --- a/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php +++ b/lib/private/Collaboration/Collaborators/RemoteGroupPlugin.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Collaboration/Collaborators/RemotePlugin.php b/lib/private/Collaboration/Collaborators/RemotePlugin.php index 788ece70cb9..037c6f6cbea 100644 --- a/lib/private/Collaboration/Collaborators/RemotePlugin.php +++ b/lib/private/Collaboration/Collaborators/RemotePlugin.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Collaboration/Collaborators/Search.php b/lib/private/Collaboration/Collaborators/Search.php index 78b57b52400..32c70549a7b 100644 --- a/lib/private/Collaboration/Collaborators/Search.php +++ b/lib/private/Collaboration/Collaborators/Search.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Collaboration/Collaborators/SearchResult.php b/lib/private/Collaboration/Collaborators/SearchResult.php index 73c0fed41e0..c9c2f032f36 100644 --- a/lib/private/Collaboration/Collaborators/SearchResult.php +++ b/lib/private/Collaboration/Collaborators/SearchResult.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Collaboration/Collaborators/UserPlugin.php b/lib/private/Collaboration/Collaborators/UserPlugin.php index d196abae042..671181aea35 100644 --- a/lib/private/Collaboration/Collaborators/UserPlugin.php +++ b/lib/private/Collaboration/Collaborators/UserPlugin.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -147,11 +148,11 @@ class UserPlugin implements ISearchPlugin { if ( - $this->shareeEnumerationFullMatch && - $lowerSearch !== '' && (strtolower($uid) === $lowerSearch || - strtolower($userDisplayName) === $lowerSearch || - ($this->shareeEnumerationFullMatchIgnoreSecondDisplayName && trim(strtolower(preg_replace('/ \(.*\)$/', '', $userDisplayName))) === $lowerSearch) || - ($this->shareeEnumerationFullMatchEmail && strtolower($userEmail ?? '') === $lowerSearch)) + $this->shareeEnumerationFullMatch + && $lowerSearch !== '' && (strtolower($uid) === $lowerSearch + || strtolower($userDisplayName) === $lowerSearch + || ($this->shareeEnumerationFullMatchIgnoreSecondDisplayName && trim(strtolower(preg_replace('/ \(.*\)$/', '', $userDisplayName))) === $lowerSearch) + || ($this->shareeEnumerationFullMatchEmail && strtolower($userEmail ?? '') === $lowerSearch)) ) { if (strtolower($uid) === $lowerSearch) { $foundUserById = true; @@ -169,8 +170,8 @@ class UserPlugin implements ISearchPlugin { ]; } else { $addToWideResults = false; - if ($this->shareeEnumeration && - !($this->shareeEnumerationInGroupOnly || $this->shareeEnumerationPhone)) { + if ($this->shareeEnumeration + && !($this->shareeEnumerationInGroupOnly || $this->shareeEnumerationPhone)) { $addToWideResults = true; } diff --git a/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php b/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php index e468ad4eb4c..9c18531c8e7 100644 --- a/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php +++ b/lib/private/Collaboration/Reference/File/FileReferenceEventListener.php @@ -15,6 +15,7 @@ use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventDispatcher; use OCP\EventDispatcher\IEventListener; use OCP\Files\Events\Node\NodeDeletedEvent; +use OCP\Files\Events\Node\NodeRenamedEvent; use OCP\Share\Events\ShareCreatedEvent; use OCP\Share\Events\ShareDeletedEvent; @@ -27,6 +28,7 @@ class FileReferenceEventListener implements IEventListener { public static function register(IEventDispatcher $eventDispatcher): void { $eventDispatcher->addServiceListener(NodeDeletedEvent::class, FileReferenceEventListener::class); + $eventDispatcher->addServiceListener(NodeRenamedEvent::class, FileReferenceEventListener::class); $eventDispatcher->addServiceListener(ShareDeletedEvent::class, FileReferenceEventListener::class); $eventDispatcher->addServiceListener(ShareCreatedEvent::class, FileReferenceEventListener::class); } @@ -42,6 +44,9 @@ class FileReferenceEventListener implements IEventListener { $this->manager->invalidateCache((string)$event->getNode()->getId()); } + if ($event instanceof NodeRenamedEvent) { + $this->manager->invalidateCache((string)$event->getTarget()->getId()); + } if ($event instanceof ShareDeletedEvent) { $this->manager->invalidateCache((string)$event->getShare()->getNodeId()); } diff --git a/lib/private/Collaboration/Resources/Collection.php b/lib/private/Collaboration/Resources/Collection.php index cf5f7740ced..2481a3e9a09 100644 --- a/lib/private/Collaboration/Resources/Collection.php +++ b/lib/private/Collaboration/Resources/Collection.php @@ -164,8 +164,8 @@ class Collection implements ICollection { } protected function isSameResource(IResource $resource1, IResource $resource2): bool { - return $resource1->getType() === $resource2->getType() && - $resource1->getId() === $resource2->getId(); + return $resource1->getType() === $resource2->getType() + && $resource1->getId() === $resource2->getId(); } protected function removeCollection(): void { diff --git a/lib/private/Color.php b/lib/private/Color.php index e96d6fd23bd..d97c519e552 100644 --- a/lib/private/Color.php +++ b/lib/private/Color.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Command/CronBus.php b/lib/private/Command/CronBus.php index 1ff9bb7099a..a12520469a9 100644 --- a/lib/private/Command/CronBus.php +++ b/lib/private/Command/CronBus.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Config.php b/lib/private/Config.php index 0e8d07955af..a9eb58a1866 100644 --- a/lib/private/Config.php +++ b/lib/private/Config.php @@ -65,17 +65,37 @@ class Config { */ public function getValue($key, $default = null) { if (isset($this->envCache[$key])) { - return $this->envCache[$key]; + return self::trustSystemConfig($this->envCache[$key]); } if (isset($this->cache[$key])) { - return $this->cache[$key]; + return self::trustSystemConfig($this->cache[$key]); } return $default; } /** + * Since system config is admin controlled, we can tell psalm to ignore any taint + * + * @psalm-taint-escape callable + * @psalm-taint-escape cookie + * @psalm-taint-escape file + * @psalm-taint-escape has_quotes + * @psalm-taint-escape header + * @psalm-taint-escape html + * @psalm-taint-escape include + * @psalm-taint-escape ldap + * @psalm-taint-escape shell + * @psalm-taint-escape sql + * @psalm-taint-escape unserialize + * @psalm-pure + */ + public static function trustSystemConfig(mixed $value): mixed { + return $value; + } + + /** * Sets and deletes values and writes the config.php * * @param array $configs Associative array with `key => value` pairs @@ -246,7 +266,7 @@ class Config { * @throws HintException If the config file cannot be written to * @throws \Exception If no file lock can be acquired */ - private function writeData() { + private function writeData(): void { $this->checkReadOnly(); if (!is_file(\OC::$configDir . '/CAN_INSTALL') && !isset($this->cache['version'])) { @@ -256,7 +276,7 @@ class Config { // Create a php file ... $content = "<?php\n"; $content .= '$CONFIG = '; - $content .= var_export($this->cache, true); + $content .= var_export(self::trustSystemConfig($this->cache), true); $content .= ";\n"; touch($this->configFilePath); diff --git a/lib/private/Config/ConfigManager.php b/lib/private/Config/ConfigManager.php new file mode 100644 index 00000000000..1980269e2ca --- /dev/null +++ b/lib/private/Config/ConfigManager.php @@ -0,0 +1,250 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Config; + +use JsonException; +use NCU\Config\Exceptions\TypeConflictException; +use NCU\Config\IUserConfig; +use NCU\Config\Lexicon\ConfigLexiconEntry; +use NCU\Config\ValueType; +use OC\AppConfig; +use OCP\App\IAppManager; +use OCP\IAppConfig; +use OCP\Server; +use Psr\Log\LoggerInterface; + +/** + * tools to maintains configurations + * + * @since 32.0.0 + */ +class ConfigManager { + /** @var AppConfig|null $appConfig */ + private ?IAppConfig $appConfig = null; + /** @var UserConfig|null $userConfig */ + private ?IUserConfig $userConfig = null; + + public function __construct( + private readonly LoggerInterface $logger, + ) { + } + + /** + * Use the rename values from the list of ConfigLexiconEntry defined in each app ConfigLexicon + * to migrate config value to a new config key. + * Migration will only occur if new config key has no value in database. + * The previous value from the key set in rename will be deleted from the database when migration + * is over. + * + * This method should be mainly called during a new upgrade or when a new app is enabled. + * + * @see ConfigLexiconEntry + * @internal + * @since 32.0.0 + * @param string|null $appId when set to NULL the method will be executed for all enabled apps of the instance + */ + public function migrateConfigLexiconKeys(?string $appId = null): void { + if ($appId === null) { + $this->migrateConfigLexiconKeys('core'); + $appManager = Server::get(IAppManager::class); + foreach ($appManager->getEnabledApps() as $app) { + $this->migrateConfigLexiconKeys($app); + } + + return; + } + + $this->loadConfigServices(); + + // it is required to ignore aliases when moving config values + $this->appConfig->ignoreLexiconAliases(true); + $this->userConfig->ignoreLexiconAliases(true); + + $this->migrateAppConfigKeys($appId); + $this->migrateUserConfigKeys($appId); + + // switch back to normal behavior + $this->appConfig->ignoreLexiconAliases(false); + $this->userConfig->ignoreLexiconAliases(false); + } + + /** + * config services cannot be load at __construct() or install will fail + */ + private function loadConfigServices(): void { + if ($this->appConfig === null) { + $this->appConfig = Server::get(IAppConfig::class); + } + if ($this->userConfig === null) { + $this->userConfig = Server::get(IUserConfig::class); + } + } + + /** + * Get details from lexicon related to AppConfig and search for entries with rename to initiate + * a migration to new config key + */ + private function migrateAppConfigKeys(string $appId): void { + $lexicon = $this->appConfig->getConfigDetailsFromLexicon($appId); + foreach ($lexicon['entries'] as $entry) { + // only interested in entries with rename set + if ($entry->getRename() === null) { + continue; + } + + // only migrate if rename config key has a value and the new config key hasn't + if ($this->appConfig->hasKey($appId, $entry->getRename()) + && !$this->appConfig->hasKey($appId, $entry->getKey())) { + try { + $this->migrateAppConfigValue($appId, $entry); + } catch (TypeConflictException $e) { + $this->logger->error('could not migrate AppConfig value', ['appId' => $appId, 'entry' => $entry, 'exception' => $e]); + continue; + } + } + + // we only delete previous config value if migration went fine. + $this->appConfig->deleteKey($appId, $entry->getRename()); + } + } + + /** + * Get details from lexicon related to UserConfig and search for entries with rename to initiate + * a migration to new config key + */ + private function migrateUserConfigKeys(string $appId): void { + $lexicon = $this->userConfig->getConfigDetailsFromLexicon($appId); + foreach ($lexicon['entries'] as $entry) { + // only interested in keys with rename set + if ($entry->getRename() === null) { + continue; + } + + foreach ($this->userConfig->getValuesByUsers($appId, $entry->getRename()) as $userId => $value) { + if ($this->userConfig->hasKey($userId, $appId, $entry->getKey())) { + continue; + } + + try { + $this->migrateUserConfigValue($userId, $appId, $entry); + } catch (TypeConflictException $e) { + $this->logger->error('could not migrate UserConfig value', ['userId' => $userId, 'appId' => $appId, 'entry' => $entry, 'exception' => $e]); + continue; + } + + $this->userConfig->deleteUserConfig($userId, $appId, $entry->getRename()); + } + } + } + + + /** + * converting value from rename to the new key + * + * @throws TypeConflictException if previous value does not fit the expected type + */ + private function migrateAppConfigValue(string $appId, ConfigLexiconEntry $entry): void { + $value = $this->appConfig->getValueMixed($appId, $entry->getRename(), lazy: null); + switch ($entry->getValueType()) { + case ValueType::STRING: + $this->appConfig->setValueString($appId, $entry->getKey(), $value); + return; + + case ValueType::INT: + $this->appConfig->setValueInt($appId, $entry->getKey(), $this->convertToInt($value)); + return; + + case ValueType::FLOAT: + $this->appConfig->setValueFloat($appId, $entry->getKey(), $this->convertToFloat($value)); + return; + + case ValueType::BOOL: + $this->appConfig->setValueBool($appId, $entry->getKey(), $this->convertToBool($value, $entry)); + return; + + case ValueType::ARRAY: + $this->appConfig->setValueArray($appId, $entry->getKey(), $this->convertToArray($value)); + return; + } + } + + /** + * converting value from rename to the new key + * + * @throws TypeConflictException if previous value does not fit the expected type + */ + private function migrateUserConfigValue(string $userId, string $appId, ConfigLexiconEntry $entry): void { + $value = $this->userConfig->getValueMixed($userId, $appId, $entry->getRename(), lazy: null); + switch ($entry->getValueType()) { + case ValueType::STRING: + $this->userConfig->setValueString($userId, $appId, $entry->getKey(), $value); + return; + + case ValueType::INT: + $this->userConfig->setValueInt($userId, $appId, $entry->getKey(), $this->convertToInt($value)); + return; + + case ValueType::FLOAT: + $this->userConfig->setValueFloat($userId, $appId, $entry->getKey(), $this->convertToFloat($value)); + return; + + case ValueType::BOOL: + $this->userConfig->setValueBool($userId, $appId, $entry->getKey(), $this->convertToBool($value, $entry)); + return; + + case ValueType::ARRAY: + $this->userConfig->setValueArray($userId, $appId, $entry->getKey(), $this->convertToArray($value)); + return; + } + } + + public function convertToInt(string $value): int { + if (!is_numeric($value) || (float)$value <> (int)$value) { + throw new TypeConflictException('Value is not an integer'); + } + + return (int)$value; + } + + public function convertToFloat(string $value): float { + if (!is_numeric($value)) { + throw new TypeConflictException('Value is not a float'); + } + + return (float)$value; + } + + public function convertToBool(string $value, ?ConfigLexiconEntry $entry = null): bool { + if (in_array(strtolower($value), ['true', '1', 'on', 'yes'])) { + $valueBool = true; + } elseif (in_array(strtolower($value), ['false', '0', 'off', 'no'])) { + $valueBool = false; + } else { + throw new TypeConflictException('Value cannot be converted to boolean'); + } + if ($entry?->hasOption(ConfigLexiconEntry::RENAME_INVERT_BOOLEAN) === true) { + $valueBool = !$valueBool; + } + + return $valueBool; + } + + public function convertToArray(string $value): array { + try { + $valueArray = json_decode($value, true, flags: JSON_THROW_ON_ERROR); + } catch (JsonException) { + throw new TypeConflictException('Value is not a valid json'); + } + if (!is_array($valueArray)) { + throw new TypeConflictException('Value is not an array'); + } + + return $valueArray; + } +} diff --git a/lib/private/Config/Lexicon/CoreConfigLexicon.php b/lib/private/Config/Lexicon/CoreConfigLexicon.php new file mode 100644 index 00000000000..34a0b883c54 --- /dev/null +++ b/lib/private/Config/Lexicon/CoreConfigLexicon.php @@ -0,0 +1,43 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Config\Lexicon; + +use NCU\Config\Lexicon\ConfigLexiconEntry; +use NCU\Config\Lexicon\ConfigLexiconStrictness; +use NCU\Config\Lexicon\IConfigLexicon; +use NCU\Config\ValueType; + +/** + * ConfigLexicon for 'core' app/user configs + */ +class CoreConfigLexicon implements IConfigLexicon { + public function getStrictness(): ConfigLexiconStrictness { + return ConfigLexiconStrictness::IGNORE; + } + + /** + * @inheritDoc + * @return ConfigLexiconEntry[] + */ + public function getAppConfigs(): array { + return [ + new ConfigLexiconEntry('lastcron', ValueType::INT, 0, 'timestamp of last cron execution'), + ]; + } + + /** + * @inheritDoc + * @return ConfigLexiconEntry[] + */ + public function getUserConfigs(): array { + return [ + new ConfigLexiconEntry('lang', ValueType::STRING, null, 'language'), + ]; + } +} diff --git a/lib/private/Config/UserConfig.php b/lib/private/Config/UserConfig.php index 37e109b2121..7848f1728e3 100644 --- a/lib/private/Config/UserConfig.php +++ b/lib/private/Config/UserConfig.php @@ -15,13 +15,17 @@ use NCU\Config\Exceptions\IncorrectTypeException; use NCU\Config\Exceptions\TypeConflictException; use NCU\Config\Exceptions\UnknownKeyException; use NCU\Config\IUserConfig; +use NCU\Config\Lexicon\ConfigLexiconEntry; +use NCU\Config\Lexicon\ConfigLexiconStrictness; use NCU\Config\ValueType; +use OC\AppFramework\Bootstrap\Coordinator; use OCP\DB\Exception as DBException; use OCP\DB\IResult; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IConfig; use OCP\IDBConnection; use OCP\Security\ICrypto; +use OCP\Server; use Psr\Log\LoggerInterface; /** @@ -55,17 +59,17 @@ class UserConfig implements IUserConfig { private array $lazyCache = []; // cache for lazy config keys /** @var array<string, array<string, array<string, array<string, mixed>>>> ['user_id' => ['app_id' => ['key' => ['type' => ValueType, 'flags' => bitflag]]]] */ private array $valueDetails = []; // type for all config values - /** @var array<string, array<string, array<string, ValueType>>> ['user_id' => ['app_id' => ['key' => bitflag]]] */ - private array $valueTypes = []; // type for all config values - /** @var array<string, array<string, array<string, int>>> ['user_id' => ['app_id' => ['key' => bitflag]]] */ - private array $valueFlags = []; // type for all config values /** @var array<string, boolean> ['user_id' => bool] */ private array $fastLoaded = []; /** @var array<string, boolean> ['user_id' => bool] */ private array $lazyLoaded = []; + /** @var array<string, array{entries: array<string, ConfigLexiconEntry>, aliases: array<string, string>, strictness: ConfigLexiconStrictness}> ['app_id' => ['strictness' => ConfigLexiconStrictness, 'entries' => ['config_key' => ConfigLexiconEntry[]]] */ + private array $configLexiconDetails = []; + private bool $ignoreLexiconAliases = false; public function __construct( protected IDBConnection $connection, + protected IConfig $config, protected LoggerInterface $logger, protected ICrypto $crypto, ) { @@ -148,6 +152,7 @@ class UserConfig implements IUserConfig { public function hasKey(string $userId, string $app, string $key, ?bool $lazy = false): bool { $this->assertParams($userId, $app, $key); $this->loadConfig($userId, $lazy); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); if ($lazy === null) { $appCache = $this->getValues($userId, $app); @@ -176,6 +181,7 @@ class UserConfig implements IUserConfig { public function isSensitive(string $userId, string $app, string $key, ?bool $lazy = false): bool { $this->assertParams($userId, $app, $key); $this->loadConfig($userId, $lazy); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); if (!isset($this->valueDetails[$userId][$app][$key])) { throw new UnknownKeyException('unknown config key'); @@ -199,6 +205,7 @@ class UserConfig implements IUserConfig { public function isIndexed(string $userId, string $app, string $key, ?bool $lazy = false): bool { $this->assertParams($userId, $app, $key); $this->loadConfig($userId, $lazy); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); if (!isset($this->valueDetails[$userId][$app][$key])) { throw new UnknownKeyException('unknown config key'); @@ -220,10 +227,13 @@ class UserConfig implements IUserConfig { * @since 31.0.0 */ public function isLazy(string $userId, string $app, string $key): bool { + $this->matchAndApplyLexiconDefinition($userId, $app, $key); + // there is a huge probability the non-lazy config are already loaded // meaning that we can start by only checking if a current non-lazy key exists if ($this->hasKey($userId, $app, $key, false)) { - return false; // meaning key is not lazy. + // meaning key is not lazy. + return false; } // as key is not found as non-lazy, we load and search in the lazy config @@ -258,7 +268,8 @@ class UserConfig implements IUserConfig { $values = array_filter( $this->formatAppValues($userId, $app, ($this->fastCache[$userId][$app] ?? []) + ($this->lazyCache[$userId][$app] ?? []), $filtered), function (string $key) use ($prefix): bool { - return str_starts_with($key, $prefix); // filter values based on $prefix + // filter values based on $prefix + return str_starts_with($key, $prefix); }, ARRAY_FILTER_USE_KEY ); @@ -345,6 +356,7 @@ class UserConfig implements IUserConfig { ?array $userIds = null, ): array { $this->assertParams('', $app, $key, allowEmptyUser: true); + $this->matchAndApplyLexiconDefinition('', $app, $key); $qb = $this->connection->getQueryBuilder(); $qb->select('userid', 'configvalue', 'type') @@ -460,6 +472,7 @@ class UserConfig implements IUserConfig { */ private function searchUsersByTypedValue(string $app, string $key, string|array $value, bool $caseInsensitive = false): Generator { $this->assertParams('', $app, $key, allowEmptyUser: true); + $this->matchAndApplyLexiconDefinition('', $app, $key); $qb = $this->connection->getQueryBuilder(); $qb->from('preferences'); @@ -537,6 +550,7 @@ class UserConfig implements IUserConfig { string $default = '', ?bool $lazy = false, ): string { + $this->matchAndApplyLexiconDefinition($userId, $app, $key); try { $lazy ??= $this->isLazy($userId, $app, $key); } catch (UnknownKeyException) { @@ -706,6 +720,11 @@ class UserConfig implements IUserConfig { ValueType $type, ): string { $this->assertParams($userId, $app, $key); + $origKey = $key; + if (!$this->matchAndApplyLexiconDefinition($userId, $app, $key, $lazy, $type, default: $default)) { + // returns default if strictness of lexicon is set to WARNING (block and report) + return $default; + } $this->loadConfig($userId, $lazy); /** @@ -738,6 +757,15 @@ class UserConfig implements IUserConfig { } $this->decryptSensitiveValue($userId, $app, $key, $value); + + // in case the key was modified while running matchAndApplyLexiconDefinition() we are + // interested to check options in case a modification of the value is needed + // ie inverting value from previous key when using lexicon option RENAME_INVERT_BOOLEAN + if ($origKey !== $key && $type === ValueType::BOOL) { + $configManager = Server::get(ConfigManager::class); + $value = ($configManager->convertToBool($value, $this->getLexiconEntry($app, $key))) ? '1' : '0'; + } + return $value; } @@ -756,6 +784,7 @@ class UserConfig implements IUserConfig { public function getValueType(string $userId, string $app, string $key, ?bool $lazy = null): ValueType { $this->assertParams($userId, $app, $key); $this->loadConfig($userId, $lazy); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); if (!isset($this->valueDetails[$userId][$app][$key]['type'])) { throw new UnknownKeyException('unknown config key'); @@ -780,6 +809,7 @@ class UserConfig implements IUserConfig { public function getValueFlags(string $userId, string $app, string $key, bool $lazy = false): int { $this->assertParams($userId, $app, $key); $this->loadConfig($userId, $lazy); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); if (!isset($this->valueDetails[$userId][$app][$key])) { throw new UnknownKeyException('unknown config key'); @@ -1037,7 +1067,16 @@ class UserConfig implements IUserConfig { int $flags, ValueType $type, ): bool { + // Primary email addresses are always(!) expected to be lowercase + if ($app === 'settings' && $key === 'email') { + $value = strtolower($value); + } + $this->assertParams($userId, $app, $key); + if (!$this->matchAndApplyLexiconDefinition($userId, $app, $key, $lazy, $type, $flags)) { + // returns false as database is not updated + return false; + } $this->loadConfig($userId, $lazy); $inserted = $refreshCache = false; @@ -1045,7 +1084,7 @@ class UserConfig implements IUserConfig { $sensitive = $this->isFlagged(self::FLAG_SENSITIVE, $flags); if ($sensitive || ($this->hasKey($userId, $app, $key, $lazy) && $this->isSensitive($userId, $app, $key, $lazy))) { $value = self::ENCRYPTION_PREFIX . $this->crypto->encrypt($value); - $flags |= UserConfig::FLAG_SENSITIVE; + $flags |= self::FLAG_SENSITIVE; } // if requested, we fill the 'indexed' field with current value @@ -1089,7 +1128,8 @@ class UserConfig implements IUserConfig { $inserted = true; } catch (DBException $e) { if ($e->getReason() !== DBException::REASON_UNIQUE_CONSTRAINT_VIOLATION) { - throw $e; // TODO: throw exception or just log and returns false !? + // TODO: throw exception or just log and returns false !? + throw $e; } } } @@ -1116,8 +1156,8 @@ class UserConfig implements IUserConfig { * we only accept a different type from the one stored in database * if the one stored in database is not-defined (VALUE_MIXED) */ - if ($currType !== ValueType::MIXED && - $currType !== $type) { + if ($currType !== ValueType::MIXED + && $currType !== $type) { try { $currTypeDef = $currType->getDefinition(); $typeDef = $type->getDefinition(); @@ -1184,6 +1224,7 @@ class UserConfig implements IUserConfig { public function updateType(string $userId, string $app, string $key, ValueType $type = ValueType::MIXED): bool { $this->assertParams($userId, $app, $key); $this->loadConfigAll($userId); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); $this->isLazy($userId, $app, $key); // confirm key exists $update = $this->connection->getQueryBuilder(); @@ -1213,6 +1254,7 @@ class UserConfig implements IUserConfig { public function updateSensitive(string $userId, string $app, string $key, bool $sensitive): bool { $this->assertParams($userId, $app, $key); $this->loadConfigAll($userId); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); try { if ($sensitive === $this->isSensitive($userId, $app, $key, null)) { @@ -1268,6 +1310,8 @@ class UserConfig implements IUserConfig { */ public function updateGlobalSensitive(string $app, string $key, bool $sensitive): void { $this->assertParams('', $app, $key, allowEmptyUser: true); + $this->matchAndApplyLexiconDefinition('', $app, $key); + foreach (array_keys($this->getValuesByUsers($app, $key)) as $userId) { try { $this->updateSensitive($userId, $app, $key, $sensitive); @@ -1276,7 +1320,8 @@ class UserConfig implements IUserConfig { } } - $this->clearCacheAll(); // we clear all cache + // we clear all cache + $this->clearCacheAll(); } /** @@ -1296,6 +1341,7 @@ class UserConfig implements IUserConfig { public function updateIndexed(string $userId, string $app, string $key, bool $indexed): bool { $this->assertParams($userId, $app, $key); $this->loadConfigAll($userId); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); try { if ($indexed === $this->isIndexed($userId, $app, $key, null)) { @@ -1351,6 +1397,8 @@ class UserConfig implements IUserConfig { */ public function updateGlobalIndexed(string $app, string $key, bool $indexed): void { $this->assertParams('', $app, $key, allowEmptyUser: true); + $this->matchAndApplyLexiconDefinition('', $app, $key); + foreach (array_keys($this->getValuesByUsers($app, $key)) as $userId) { try { $this->updateIndexed($userId, $app, $key, $indexed); @@ -1359,7 +1407,8 @@ class UserConfig implements IUserConfig { } } - $this->clearCacheAll(); // we clear all cache + // we clear all cache + $this->clearCacheAll(); } /** @@ -1376,6 +1425,7 @@ class UserConfig implements IUserConfig { public function updateLazy(string $userId, string $app, string $key, bool $lazy): bool { $this->assertParams($userId, $app, $key); $this->loadConfigAll($userId); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); try { if ($lazy === $this->isLazy($userId, $app, $key)) { @@ -1410,6 +1460,7 @@ class UserConfig implements IUserConfig { */ public function updateGlobalLazy(string $app, string $key, bool $lazy): void { $this->assertParams('', $app, $key, allowEmptyUser: true); + $this->matchAndApplyLexiconDefinition('', $app, $key); $update = $this->connection->getQueryBuilder(); $update->update('preferences') @@ -1435,6 +1486,8 @@ class UserConfig implements IUserConfig { public function getDetails(string $userId, string $app, string $key): array { $this->assertParams($userId, $app, $key); $this->loadConfigAll($userId); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); + $lazy = $this->isLazy($userId, $app, $key); if ($lazy) { @@ -1482,6 +1535,8 @@ class UserConfig implements IUserConfig { */ public function deleteUserConfig(string $userId, string $app, string $key): void { $this->assertParams($userId, $app, $key); + $this->matchAndApplyLexiconDefinition($userId, $app, $key); + $qb = $this->connection->getQueryBuilder(); $qb->delete('preferences') ->where($qb->expr()->eq('userid', $qb->createNamedParameter($userId))) @@ -1491,6 +1546,7 @@ class UserConfig implements IUserConfig { unset($this->lazyCache[$userId][$app][$key]); unset($this->fastCache[$userId][$app][$key]); + unset($this->valueDetails[$userId][$app][$key]); } /** @@ -1503,6 +1559,8 @@ class UserConfig implements IUserConfig { */ public function deleteKey(string $app, string $key): void { $this->assertParams('', $app, $key, allowEmptyUser: true); + $this->matchAndApplyLexiconDefinition('', $app, $key); + $qb = $this->connection->getQueryBuilder(); $qb->delete('preferences') ->where($qb->expr()->eq('appid', $qb->createNamedParameter($app))) @@ -1521,6 +1579,7 @@ class UserConfig implements IUserConfig { */ public function deleteApp(string $app): void { $this->assertParams('', $app, allowEmptyUser: true); + $qb = $this->connection->getQueryBuilder(); $qb->delete('preferences') ->where($qb->expr()->eq('appid', $qb->createNamedParameter($app))); @@ -1782,6 +1841,14 @@ class UserConfig implements IUserConfig { } + /** + * will change referenced $value with the decrypted value in case of encrypted (sensitive value) + * + * @param string $userId + * @param string $app + * @param string $key + * @param string $value + */ private function decryptSensitiveValue(string $userId, string $app, string $key, string &$value): void { if (!$this->isFlagged(self::FLAG_SENSITIVE, $this->valueDetails[$userId][$app][$key]['flags'] ?? 0)) { return; @@ -1803,4 +1870,159 @@ class UserConfig implements IUserConfig { ]); } } + + /** + * Match and apply current use of config values with defined lexicon. + * Set $lazy to NULL only if only interested into checking that $key is alias. + * + * @throws UnknownKeyException + * @throws TypeConflictException + * @return bool FALSE if conflict with defined lexicon were observed in the process + */ + private function matchAndApplyLexiconDefinition( + string $userId, + string $app, + string &$key, + ?bool &$lazy = null, + ValueType &$type = ValueType::MIXED, + int &$flags = 0, + string &$default = '', + ): bool { + $configDetails = $this->getConfigDetailsFromLexicon($app); + if (array_key_exists($key, $configDetails['aliases']) && !$this->ignoreLexiconAliases) { + // in case '$rename' is set in ConfigLexiconEntry, we use the new config key + $key = $configDetails['aliases'][$key]; + } + + if (!array_key_exists($key, $configDetails['entries'])) { + return $this->applyLexiconStrictness($configDetails['strictness'], 'The user config key ' . $app . '/' . $key . ' is not defined in the config lexicon'); + } + + // if lazy is NULL, we ignore all check on the type/lazyness/default from Lexicon + if ($lazy === null) { + return true; + } + + /** @var ConfigLexiconEntry $configValue */ + $configValue = $configDetails['entries'][$key]; + if ($type === ValueType::MIXED) { + // we overwrite if value was requested as mixed + $type = $configValue->getValueType(); + } elseif ($configValue->getValueType() !== $type) { + throw new TypeConflictException('The user config key ' . $app . '/' . $key . ' is typed incorrectly in relation to the config lexicon'); + } + + $lazy = $configValue->isLazy(); + $flags = $configValue->getFlags(); + if ($configValue->isDeprecated()) { + $this->logger->notice('User config key ' . $app . '/' . $key . ' is set as deprecated.'); + } + + $enforcedValue = $this->config->getSystemValue('lexicon.default.userconfig.enforced', [])[$app][$key] ?? false; + if (!$enforcedValue && $this->hasKey($userId, $app, $key, $lazy)) { + // if key exists there should be no need to extract default + return true; + } + + // default from Lexicon got priority but it can still be overwritten by admin + $default = $this->getSystemDefault($app, $configValue) ?? $configValue->getDefault() ?? $default; + + // returning false will make get() returning $default and set() not changing value in database + return !$enforcedValue; + } + + /** + * get default value set in config/config.php if stored in key: + * + * 'lexicon.default.userconfig' => [ + * <appId> => [ + * <configKey> => 'my value', + * ] + * ], + * + * The entry is converted to string to fit the expected type when managing default value + */ + private function getSystemDefault(string $appId, ConfigLexiconEntry $configValue): ?string { + $default = $this->config->getSystemValue('lexicon.default.userconfig', [])[$appId][$configValue->getKey()] ?? null; + if ($default === null) { + // no system default, using default default. + return null; + } + + return $configValue->convertToString($default); + } + + /** + * manage ConfigLexicon behavior based on strictness set in IConfigLexicon + * + * @see IConfigLexicon::getStrictness() + * @param ConfigLexiconStrictness|null $strictness + * @param string $line + * + * @return bool TRUE if conflict can be fully ignored + * @throws UnknownKeyException + */ + private function applyLexiconStrictness(?ConfigLexiconStrictness $strictness, string $line = ''): bool { + if ($strictness === null) { + return true; + } + + switch ($strictness) { + case ConfigLexiconStrictness::IGNORE: + return true; + case ConfigLexiconStrictness::NOTICE: + $this->logger->notice($line); + return true; + case ConfigLexiconStrictness::WARNING: + $this->logger->warning($line); + return false; + case ConfigLexiconStrictness::EXCEPTION: + throw new UnknownKeyException($line); + } + + throw new UnknownKeyException($line); + } + + /** + * extract details from registered $appId's config lexicon + * + * @param string $appId + * @internal + * + * @return array{entries: array<string, ConfigLexiconEntry>, aliases: array<string, string>, strictness: ConfigLexiconStrictness} + */ + public function getConfigDetailsFromLexicon(string $appId): array { + if (!array_key_exists($appId, $this->configLexiconDetails)) { + $entries = $aliases = []; + $bootstrapCoordinator = \OCP\Server::get(Coordinator::class); + $configLexicon = $bootstrapCoordinator->getRegistrationContext()?->getConfigLexicon($appId); + foreach ($configLexicon?->getUserConfigs() ?? [] as $configEntry) { + $entries[$configEntry->getKey()] = $configEntry; + if ($configEntry->getRename() !== null) { + $aliases[$configEntry->getRename()] = $configEntry->getKey(); + } + } + + $this->configLexiconDetails[$appId] = [ + 'entries' => $entries, + 'aliases' => $aliases, + 'strictness' => $configLexicon?->getStrictness() ?? ConfigLexiconStrictness::IGNORE + ]; + } + + return $this->configLexiconDetails[$appId]; + } + + private function getLexiconEntry(string $appId, string $key): ?ConfigLexiconEntry { + return $this->getConfigDetailsFromLexicon($appId)['entries'][$key] ?? null; + } + + /** + * if set to TRUE, ignore aliases defined in Config Lexicon during the use of the methods of this class + * + * @internal + */ + public function ignoreLexiconAliases(bool $ignore): void { + $this->ignoreLexiconAliases = $ignore; + } } diff --git a/lib/private/Console/Application.php b/lib/private/Console/Application.php index ac30a93a186..4cf1e0da8ca 100644 --- a/lib/private/Console/Application.php +++ b/lib/private/Console/Application.php @@ -74,8 +74,8 @@ class Application { if ($this->memoryInfo->isMemoryLimitSufficient() === false) { $output->getErrorOutput()->writeln( - '<comment>The current PHP memory limit ' . - 'is below the recommended value of 512MB.</comment>' + '<comment>The current PHP memory limit ' + . 'is below the recommended value of 512MB.</comment>' ); } @@ -88,7 +88,7 @@ class Application { $this->writeMaintenanceModeInfo($input, $output); } else { $this->appManager->loadApps(); - foreach ($this->appManager->getInstalledApps() as $app) { + foreach ($this->appManager->getEnabledApps() as $app) { try { $appPath = $this->appManager->getAppPath($app); } catch (AppPathNotFoundException) { @@ -125,7 +125,7 @@ class Application { $errorOutput->writeln('Nextcloud is not installed - only a limited number of commands are available'); } } catch (NeedsUpdateException) { - if ($input->getArgument('command') !== '_completion') { + if ($input->getArgument('command') !== '_completion' && $input->getArgument('command') !== 'upgrade') { $errorOutput = $output->getErrorOutput(); $errorOutput->writeln('Nextcloud or one of the apps require upgrade - only a limited number of commands are available'); $errorOutput->writeln('You may use your browser or the occ upgrade command to do the upgrade'); diff --git a/lib/private/Contacts/ContactsMenu/ActionFactory.php b/lib/private/Contacts/ContactsMenu/ActionFactory.php index 71ebe575fdd..40037598d49 100644 --- a/lib/private/Contacts/ContactsMenu/ActionFactory.php +++ b/lib/private/Contacts/ContactsMenu/ActionFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php b/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php index 0d4cc9b9b01..cdaf9308bfc 100644 --- a/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php +++ b/lib/private/Contacts/ContactsMenu/Actions/LinkAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Contacts/ContactsMenu/Manager.php b/lib/private/Contacts/ContactsMenu/Manager.php index 65a2c4469ea..f8def45421b 100644 --- a/lib/private/Contacts/ContactsMenu/Manager.php +++ b/lib/private/Contacts/ContactsMenu/Manager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php b/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php index c852fc90b9e..266125f5ed5 100644 --- a/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php +++ b/lib/private/Contacts/ContactsMenu/Providers/EMailProvider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php b/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php index b51ade4d74d..f62e989fd64 100644 --- a/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php +++ b/lib/private/Contacts/ContactsMenu/Providers/LocalTimeProvider.php @@ -17,6 +17,7 @@ use OCP\IConfig; use OCP\IDateTimeFormatter; use OCP\IURLGenerator; use OCP\IUserManager; +use OCP\IUserSession; use OCP\L10N\IFactory as IL10NFactory; class LocalTimeProvider implements IProvider { @@ -28,6 +29,7 @@ class LocalTimeProvider implements IProvider { private ITimeFactory $timeFactory, private IDateTimeFormatter $dateTimeFormatter, private IConfig $config, + private IUserSession $currentSession, ) { } @@ -35,14 +37,51 @@ class LocalTimeProvider implements IProvider { $targetUserId = $entry->getProperty('UID'); $targetUser = $this->userManager->get($targetUserId); if (!empty($targetUser)) { - $timezone = $this->config->getUserValue($targetUser->getUID(), 'core', 'timezone') ?: $this->config->getSystemValueString('default_timezone', 'UTC'); - $dateTimeZone = new \DateTimeZone($timezone); - $localTime = $this->dateTimeFormatter->formatTime($this->timeFactory->getDateTime(), 'short', $dateTimeZone); + $timezoneStringTarget = $this->config->getUserValue($targetUser->getUID(), 'core', 'timezone') ?: $this->config->getSystemValueString('default_timezone', 'UTC'); + $timezoneTarget = new \DateTimeZone($timezoneStringTarget); + $localTimeTarget = $this->timeFactory->getDateTime('now', $timezoneTarget); + $localTimeString = $this->dateTimeFormatter->formatTime($localTimeTarget, 'short', $timezoneTarget); - $iconUrl = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/recent.svg')); $l = $this->l10nFactory->get('lib'); - $profileActionText = $l->t('Local time: %s', [$localTime]); + $currentUser = $this->currentSession->getUser(); + if ($currentUser !== null) { + $timezoneStringCurrent = $this->config->getUserValue($currentUser->getUID(), 'core', 'timezone') ?: $this->config->getSystemValueString('default_timezone', 'UTC'); + $timezoneCurrent = new \DateTimeZone($timezoneStringCurrent); + $localTimeCurrent = $this->timeFactory->getDateTime('now', $timezoneCurrent); + + // Get the timezone offsets to GMT on this very time (needed to handle daylight saving time) + $timeOffsetCurrent = $timezoneCurrent->getOffset($localTimeCurrent); + $timeOffsetTarget = $timezoneTarget->getOffset($localTimeTarget); + // Get the difference between the current users offset to GMT and then targets user to GMT + $timeOffset = $timeOffsetTarget - $timeOffsetCurrent; + if ($timeOffset === 0) { + // No offset means both users are in the same timezone + $timeOffsetString = $l->t('same time'); + } else { + // We need to cheat here as the offset could be up to 26h we can not use formatTime. + $hours = abs((int)($timeOffset / 3600)); + $minutes = abs(($timeOffset / 60) % 60); + // TRANSLATORS %n hours in a short form + $hoursString = $l->n('%nh', '%nh', $hours); + // TRANSLATORS %n minutes in a short form + $minutesString = $l->n('%nm', '%nm', $minutes); + + $timeOffsetString = ($hours > 0 ? $hoursString : '') . ($minutes > 0 ? $minutesString : ''); + if ($timeOffset > 0) { + // TRANSLATORS meaning the user is %s time ahead - like 1h30m + $timeOffsetString = $l->t('%s ahead', [$timeOffsetString]); + } else { + // TRANSLATORS meaning the user is %s time behind - like 1h30m + $timeOffsetString = $l->t('%s behind', [$timeOffsetString]); + } + } + $profileActionText = "{$localTimeString} • {$timeOffsetString}"; + } else { + $profileActionText = $l->t('Local time: %s', [$localTimeString]); + } + + $iconUrl = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/recent.svg')); $action = $this->actionFactory->newLinkAction($iconUrl, $profileActionText, '#', 'timezone'); // Order after the profile page $action->setPriority(19); diff --git a/lib/private/ContactsManager.php b/lib/private/ContactsManager.php index 7dd2bf33124..87b341ac36b 100644 --- a/lib/private/ContactsManager.php +++ b/lib/private/ContactsManager.php @@ -10,6 +10,7 @@ namespace OC; use OCP\Constants; use OCP\Contacts\IManager; use OCP\IAddressBook; +use OCP\IAddressBookEnabled; class ContactsManager implements IManager { /** @@ -34,6 +35,9 @@ class ContactsManager implements IManager { $this->loadAddressBooks(); $result = []; foreach ($this->addressBooks as $addressBook) { + if ($addressBook instanceof IAddressBookEnabled && !$addressBook->isEnabled()) { + continue; + } $searchOptions = $options; $strictSearch = array_key_exists('strict_search', $options) && $options['strict_search'] === true; diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index 1b61cc83319..88bdc377e2b 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -160,7 +160,7 @@ class Connection extends PrimaryReadReplicaConnection { $this->_config->setSQLLogger($debugStack); } - /** @var array<string, array{shards: array[], mapper: ?string}> $shardConfig */ + /** @var array<string, array{shards: array[], mapper: ?string, from_primary_key: ?int, from_shard_key: ?int}> $shardConfig */ $shardConfig = $this->params['sharding'] ?? []; $shardNames = array_keys($shardConfig); $this->shards = array_map(function (array $config, string $name) { @@ -180,7 +180,9 @@ class Connection extends PrimaryReadReplicaConnection { self::SHARD_PRESETS[$name]['shard_key'], $shardMapper, self::SHARD_PRESETS[$name]['companion_tables'], - $config['shards'] + $config['shards'], + $config['from_primary_key'] ?? 0, + $config['from_shard_key'] ?? 0, ); }, $shardConfig, $shardNames); $this->shards = array_combine($shardNames, $this->shards); @@ -199,8 +201,10 @@ class Connection extends PrimaryReadReplicaConnection { if ($this->isShardingEnabled) { foreach ($this->shards as $shardDefinition) { foreach ($shardDefinition->getAllShards() as $shard) { - /** @var ConnectionAdapter $connection */ - $connections[] = $this->shardConnectionManager->getConnection($shardDefinition, $shard); + if ($shard !== ShardDefinition::MIGRATION_SHARD) { + /** @var ConnectionAdapter $connection */ + $connections[] = $this->shardConnectionManager->getConnection($shardDefinition, $shard); + } } } } @@ -218,8 +222,6 @@ class Connection extends PrimaryReadReplicaConnection { return parent::connect(); } - $this->lastConnectionCheck[$this->getConnectionName()] = time(); - // Only trigger the event logger for the initial connect call $eventLogger = Server::get(IEventLogger::class); $eventLogger->start('connect:db', 'db connection opened'); @@ -227,6 +229,8 @@ class Connection extends PrimaryReadReplicaConnection { $status = parent::connect(); $eventLogger->end('connect:db'); + $this->lastConnectionCheck[$this->getConnectionName()] = time(); + return $status; } catch (Exception $e) { // throw a new exception to prevent leaking info from the stacktrace @@ -410,7 +414,7 @@ class Connection extends PrimaryReadReplicaConnection { $sql = $this->finishQuery($sql); $this->queriesExecuted++; - $this->logQueryToFile($sql); + $this->logQueryToFile($sql, $params); try { return parent::executeQuery($sql, $params, $types, $qcp); } catch (\Exception $e) { @@ -457,7 +461,7 @@ class Connection extends PrimaryReadReplicaConnection { } $sql = $this->finishQuery($sql); $this->queriesExecuted++; - $this->logQueryToFile($sql); + $this->logQueryToFile($sql, $params); try { return (int)parent::executeStatement($sql, $params, $types); } catch (\Exception $e) { @@ -466,14 +470,19 @@ class Connection extends PrimaryReadReplicaConnection { } } - protected function logQueryToFile(string $sql): void { + protected function logQueryToFile(string $sql, array $params): void { $logFile = $this->systemConfig->getValue('query_log_file'); if ($logFile !== '' && is_writable(dirname($logFile)) && (!file_exists($logFile) || is_writable($logFile))) { $prefix = ''; if ($this->systemConfig->getValue('query_log_file_requestid') === 'yes') { $prefix .= Server::get(IRequestId::class)->getId() . "\t"; } + $postfix = ''; + if ($this->systemConfig->getValue('query_log_file_parameters') === 'yes') { + $postfix .= '; ' . json_encode($params); + } + if ($this->systemConfig->getValue('query_log_file_backtrace') === 'yes') { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); array_pop($trace); @@ -695,6 +704,19 @@ class Connection extends PrimaryReadReplicaConnection { } /** + * Truncate a table data if it exists + * + * @param string $table table name without the prefix + * @param bool $cascade whether to truncate cascading + * + * @throws Exception + */ + public function truncateTable(string $table, bool $cascade) { + $this->executeStatement($this->getDatabasePlatform() + ->getTruncateTableSQL($this->tablePrefix . trim($table), $cascade)); + } + + /** * Check if a table exists * * @param string $table table name without the prefix @@ -872,9 +894,9 @@ class Connection extends PrimaryReadReplicaConnection { private function reconnectIfNeeded(): void { if ( - !isset($this->lastConnectionCheck[$this->getConnectionName()]) || - time() <= $this->lastConnectionCheck[$this->getConnectionName()] + 30 || - $this->isTransactionActive() + !isset($this->lastConnectionCheck[$this->getConnectionName()]) + || time() <= $this->lastConnectionCheck[$this->getConnectionName()] + 30 + || $this->isTransactionActive() ) { return; } diff --git a/lib/private/DB/ConnectionAdapter.php b/lib/private/DB/ConnectionAdapter.php index 2baeda9cfb7..78ca780f218 100644 --- a/lib/private/DB/ConnectionAdapter.php +++ b/lib/private/DB/ConnectionAdapter.php @@ -50,7 +50,7 @@ class ConnectionAdapter implements IDBConnection { $this->inner->executeQuery($sql, $params, $types) ); } catch (Exception $e) { - throw DbalException::wrap($e); + throw DbalException::wrap($e, '', $sql); } } @@ -58,7 +58,7 @@ class ConnectionAdapter implements IDBConnection { try { return $this->inner->executeUpdate($sql, $params, $types); } catch (Exception $e) { - throw DbalException::wrap($e); + throw DbalException::wrap($e, '', $sql); } } @@ -66,7 +66,7 @@ class ConnectionAdapter implements IDBConnection { try { return $this->inner->executeStatement($sql, $params, $types); } catch (Exception $e) { - throw DbalException::wrap($e); + throw DbalException::wrap($e, '', $sql); } } @@ -189,6 +189,14 @@ class ConnectionAdapter implements IDBConnection { } } + public function truncateTable(string $table, bool $cascade): void { + try { + $this->inner->truncateTable($table, $cascade); + } catch (Exception $e) { + throw DbalException::wrap($e); + } + } + public function tableExists(string $table): bool { try { return $this->inner->tableExists($table); diff --git a/lib/private/DB/ConnectionFactory.php b/lib/private/DB/ConnectionFactory.php index 8d662b0508c..4d286cb3068 100644 --- a/lib/private/DB/ConnectionFactory.php +++ b/lib/private/DB/ConnectionFactory.php @@ -108,7 +108,7 @@ class ConnectionFactory { $normalizedType = $this->normalizeType($type); $eventManager = new EventManager(); $eventManager->addEventSubscriber(new SetTransactionIsolationLevel()); - $connectionParams = $this->createConnectionParams('', $additionalConnectionParams); + $connectionParams = $this->createConnectionParams('', $additionalConnectionParams, $type); switch ($normalizedType) { case 'pgsql': // pg_connect used by Doctrine DBAL does not support URI notation (enclosed in brackets) @@ -175,12 +175,10 @@ class ConnectionFactory { /** * Create the connection parameters for the config - * - * @param string $configPrefix - * @return array */ - public function createConnectionParams(string $configPrefix = '', array $additionalConnectionParams = []) { - $type = $this->config->getValue('dbtype', 'sqlite'); + public function createConnectionParams(string $configPrefix = '', array $additionalConnectionParams = [], ?string $type = null) { + // use provided type or if null use type from config + $type = $type ?? $this->config->getValue('dbtype', 'sqlite'); $connectionParams = array_merge($this->getDefaultConnectionParams($type), [ 'user' => $this->config->getValue($configPrefix . 'dbuser', $this->config->getValue('dbuser', '')), @@ -212,7 +210,7 @@ class ConnectionFactory { 'tablePrefix' => $connectionParams['tablePrefix'] ]; - if ($this->config->getValue('mysql.utf8mb4', false)) { + if ($type === 'mysql' && $this->config->getValue('mysql.utf8mb4', false)) { $connectionParams['defaultTableOptions'] = [ 'collate' => 'utf8mb4_bin', 'charset' => 'utf8mb4', diff --git a/lib/private/DB/Exceptions/DbalException.php b/lib/private/DB/Exceptions/DbalException.php index 05ea9e22a5d..2ce6ddf80a6 100644 --- a/lib/private/DB/Exceptions/DbalException.php +++ b/lib/private/DB/Exceptions/DbalException.php @@ -35,26 +35,29 @@ use OCP\DB\Exception; class DbalException extends Exception { /** @var \Doctrine\DBAL\Exception */ private $original; + public readonly ?string $query; /** * @param \Doctrine\DBAL\Exception $original * @param int $code * @param string $message */ - private function __construct(\Doctrine\DBAL\Exception $original, int $code, string $message) { + private function __construct(\Doctrine\DBAL\Exception $original, int $code, string $message, ?string $query = null) { parent::__construct( $message, $code, $original ); $this->original = $original; + $this->query = $query; } - public static function wrap(\Doctrine\DBAL\Exception $original, string $message = ''): self { + public static function wrap(\Doctrine\DBAL\Exception $original, string $message = '', ?string $query = null): self { return new self( $original, is_int($original->getCode()) ? $original->getCode() : 0, - empty($message) ? $original->getMessage() : $message + empty($message) ? $original->getMessage() : $message, + $query, ); } diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php index 0b59509eaab..40579c7a898 100644 --- a/lib/private/DB/MigrationService.php +++ b/lib/private/DB/MigrationService.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2017 ownCloud GmbH @@ -199,9 +200,9 @@ class MigrationService { if ($versionA !== $versionB) { return ($versionA < $versionB) ? -1 : 1; } - return ($matchA[2] < $matchB[2]) ? -1 : 1; + return strnatcmp($matchA[2], $matchB[2]); } - return (basename($a) < basename($b)) ? -1 : 1; + return strnatcmp(basename($a), basename($b)); } /** @@ -250,7 +251,7 @@ class MigrationService { $toBeExecuted = []; foreach ($availableMigrations as $v) { - if ($to !== 'latest' && $v > $to) { + if ($to !== 'latest' && ($this->sortMigrations($v, $to) > 0)) { continue; } if ($this->shallBeExecuted($v, $knownMigrations)) { diff --git a/lib/private/DB/MySqlTools.php b/lib/private/DB/MySqlTools.php index cd6b812be61..3413be43417 100644 --- a/lib/private/DB/MySqlTools.php +++ b/lib/private/DB/MySqlTools.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 ownCloud GmbH * SPDX-License-Identifier: AGPL-3.0-only @@ -45,7 +46,7 @@ class MySqlTools { return false; } - return str_contains($row, 'maria') && version_compare($row, '10.3', '>=') || - !str_contains($row, 'maria') && version_compare($row, '8.0', '>='); + return str_contains($row, 'maria') && version_compare($row, '10.3', '>=') + || !str_contains($row, 'maria') && version_compare($row, '8.0', '>='); } } diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php index 559c29df208..52f82db2232 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php index 2466493c1fa..48dc1da6330 100644 --- a/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php +++ b/lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php index 6791430b1b0..8fae6275916 100644 --- a/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php +++ b/lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php index ee430a6bd71..354a2b126d7 100644 --- a/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php +++ b/lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php b/lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php index 956b2123f2c..53aa530054b 100644 --- a/lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php +++ b/lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/DB/QueryBuilder/Partitioned/PartitionedQueryBuilder.php b/lib/private/DB/QueryBuilder/Partitioned/PartitionedQueryBuilder.php index 2942eeccdf7..d748c791321 100644 --- a/lib/private/DB/QueryBuilder/Partitioned/PartitionedQueryBuilder.php +++ b/lib/private/DB/QueryBuilder/Partitioned/PartitionedQueryBuilder.php @@ -126,8 +126,8 @@ class PartitionedQueryBuilder extends ShardedQueryBuilder { $selectPartition = null; } if ( - ($select === $checkColumn || $select === '*') && - $selectPartition === $partition + ($select === $checkColumn || $select === '*') + && $selectPartition === $partition ) { return; } @@ -151,8 +151,8 @@ class PartitionedQueryBuilder extends ShardedQueryBuilder { foreach ($this->selects as $select) { foreach ($this->partitions as $partition) { if (is_string($select['select']) && ( - $select['select'] === '*' || - $partition->isColumnInPartition($select['select'])) + $select['select'] === '*' + || $partition->isColumnInPartition($select['select'])) ) { if (isset($this->splitQueries[$partition->name])) { if ($select['alias']) { @@ -444,4 +444,19 @@ class PartitionedQueryBuilder extends ShardedQueryBuilder { public function getPartitionCount(): int { return count($this->splitQueries) + 1; } + + public function hintShardKey(string $column, mixed $value, bool $overwrite = false): self { + if (str_contains($column, '.')) { + [$alias, $column] = explode('.', $column); + $partition = $this->getPartition($alias); + if ($partition) { + $this->splitQueries[$partition->name]->query->hintShardKey($column, $value, $overwrite); + } else { + parent::hintShardKey($column, $value, $overwrite); + } + } else { + parent::hintShardKey($column, $value, $overwrite); + } + return $this; + } } diff --git a/lib/private/DB/QueryBuilder/QueryBuilder.php b/lib/private/DB/QueryBuilder/QueryBuilder.php index 56c860bc42c..8b224c28dfe 100644 --- a/lib/private/DB/QueryBuilder/QueryBuilder.php +++ b/lib/private/DB/QueryBuilder/QueryBuilder.php @@ -1339,6 +1339,8 @@ class QueryBuilder implements IQueryBuilder { /** * Returns the table name with database prefix as needed by the implementation * + * Was protected until version 30. + * * @param string $table * @return string */ diff --git a/lib/private/DB/QueryBuilder/Sharded/AutoIncrementHandler.php b/lib/private/DB/QueryBuilder/Sharded/AutoIncrementHandler.php index caedaa71c97..3a230ea544d 100644 --- a/lib/private/DB/QueryBuilder/Sharded/AutoIncrementHandler.php +++ b/lib/private/DB/QueryBuilder/Sharded/AutoIncrementHandler.php @@ -108,7 +108,7 @@ class AutoIncrementHandler { } // discard the encoded initial shard - $current = $this->getMaxFromDb($shardDefinition) >> 8; + $current = $this->getMaxFromDb($shardDefinition); $next = max($current, self::MIN_VALID_KEY) + 1; if ($cache->cas($shardDefinition->table, 'empty-placeholder', $next)) { return $next; @@ -131,19 +131,22 @@ class AutoIncrementHandler { } /** - * Get the maximum primary key value from the shards + * Get the maximum primary key value from the shards, note that this has already stripped any embedded shard id */ private function getMaxFromDb(ShardDefinition $shardDefinition): int { - $max = 0; + $max = $shardDefinition->fromFileId; + $query = $this->shardConnectionManager->getConnection($shardDefinition, 0)->getQueryBuilder(); + $query->select($shardDefinition->primaryKey) + ->from($shardDefinition->table) + ->orderBy($shardDefinition->primaryKey, 'DESC') + ->setMaxResults(1); foreach ($shardDefinition->getAllShards() as $shard) { $connection = $this->shardConnectionManager->getConnection($shardDefinition, $shard); - $query = $connection->getQueryBuilder(); - $query->select($shardDefinition->primaryKey) - ->from($shardDefinition->table) - ->orderBy($shardDefinition->primaryKey, 'DESC') - ->setMaxResults(1); - $result = $query->executeQuery()->fetchOne(); + $result = $query->executeQuery($connection)->fetchOne(); if ($result) { + if ($result > $shardDefinition->fromFileId) { + $result = $result >> 8; + } $max = max($max, $result); } } diff --git a/lib/private/DB/QueryBuilder/Sharded/ShardConnectionManager.php b/lib/private/DB/QueryBuilder/Sharded/ShardConnectionManager.php index 87cac58bc57..74358e3ca96 100644 --- a/lib/private/DB/QueryBuilder/Sharded/ShardConnectionManager.php +++ b/lib/private/DB/QueryBuilder/Sharded/ShardConnectionManager.php @@ -28,8 +28,17 @@ class ShardConnectionManager { public function getConnection(ShardDefinition $shardDefinition, int $shard): IDBConnection { $connectionKey = $shardDefinition->table . '_' . $shard; - if (!isset($this->connections[$connectionKey])) { + + if (isset($this->connections[$connectionKey])) { + return $this->connections[$connectionKey]; + } + + if ($shard === ShardDefinition::MIGRATION_SHARD) { + $this->connections[$connectionKey] = \OC::$server->get(IDBConnection::class); + } elseif (isset($shardDefinition->shards[$shard])) { $this->connections[$connectionKey] = $this->createConnection($shardDefinition->shards[$shard]); + } else { + throw new \InvalidArgumentException("invalid shard key $shard only " . count($shardDefinition->shards) . ' configured'); } return $this->connections[$connectionKey]; diff --git a/lib/private/DB/QueryBuilder/Sharded/ShardDefinition.php b/lib/private/DB/QueryBuilder/Sharded/ShardDefinition.php index ebccbb639a6..4f98079d92d 100644 --- a/lib/private/DB/QueryBuilder/Sharded/ShardDefinition.php +++ b/lib/private/DB/QueryBuilder/Sharded/ShardDefinition.php @@ -15,7 +15,9 @@ use OCP\DB\QueryBuilder\Sharded\IShardMapper; */ class ShardDefinition { // we reserve the bottom byte of the primary key for the initial shard, so the total shard count is limited to what we can fit there - public const MAX_SHARDS = 256; + // additionally, shard id 255 is reserved for migration purposes + public const MAX_SHARDS = 255; + public const MIGRATION_SHARD = 255; public const PRIMARY_KEY_MASK = 0x7F_FF_FF_FF_FF_FF_FF_00; public const PRIMARY_KEY_SHARD_MASK = 0x00_00_00_00_00_00_00_FF; @@ -37,8 +39,10 @@ class ShardDefinition { public array $companionKeys, public string $shardKey, public IShardMapper $shardMapper, - public array $companionTables = [], - public array $shards = [], + public array $companionTables, + public array $shards, + public int $fromFileId, + public int $fromStorageId, ) { if (count($this->shards) >= self::MAX_SHARDS) { throw new \Exception('Only allowed maximum of ' . self::MAX_SHARDS . ' shards allowed'); @@ -53,11 +57,21 @@ class ShardDefinition { } public function getShardForKey(int $key): int { + if ($key < $this->fromStorageId) { + return self::MIGRATION_SHARD; + } return $this->shardMapper->getShardForKey($key, count($this->shards)); } + /** + * @return list<int> + */ public function getAllShards(): array { - return array_keys($this->shards); + if ($this->fromStorageId !== 0) { + return array_merge(array_keys($this->shards), [self::MIGRATION_SHARD]); + } else { + return array_keys($this->shards); + } } public function isKey(string $column): bool { diff --git a/lib/private/DB/QueryBuilder/Sharded/ShardQueryRunner.php b/lib/private/DB/QueryBuilder/Sharded/ShardQueryRunner.php index c020e72868e..25e2a3d5f2d 100644 --- a/lib/private/DB/QueryBuilder/Sharded/ShardQueryRunner.php +++ b/lib/private/DB/QueryBuilder/Sharded/ShardQueryRunner.php @@ -55,6 +55,9 @@ class ShardQueryRunner { private function getLikelyShards(array $primaryKeys): array { $shards = []; foreach ($primaryKeys as $primaryKey) { + if ($primaryKey < $this->shardDefinition->fromFileId && !in_array(ShardDefinition::MIGRATION_SHARD, $shards)) { + $shards[] = ShardDefinition::MIGRATION_SHARD; + } $encodedShard = $primaryKey & ShardDefinition::PRIMARY_KEY_SHARD_MASK; if ($encodedShard < count($this->shardDefinition->shards) && !in_array($encodedShard, $shards)) { $shards[] = $encodedShard; diff --git a/lib/private/DB/SchemaWrapper.php b/lib/private/DB/SchemaWrapper.php index 473c0009237..0d5b2040513 100644 --- a/lib/private/DB/SchemaWrapper.php +++ b/lib/private/DB/SchemaWrapper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Diagnostics/Event.php b/lib/private/Diagnostics/Event.php index cf36bf9f82a..11d6505a888 100644 --- a/lib/private/Diagnostics/Event.php +++ b/lib/private/Diagnostics/Event.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Diagnostics/EventLogger.php b/lib/private/Diagnostics/EventLogger.php index 40cbd3e9e5d..3ec35a5e9ce 100644 --- a/lib/private/Diagnostics/EventLogger.php +++ b/lib/private/Diagnostics/EventLogger.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Diagnostics/Query.php b/lib/private/Diagnostics/Query.php index 81610074709..020fc4bb512 100644 --- a/lib/private/Diagnostics/Query.php +++ b/lib/private/Diagnostics/Query.php @@ -56,7 +56,7 @@ class Query implements IQuery { public function getStart() { return $this->start; } - + /** * @return float */ diff --git a/lib/private/DirectEditing/Manager.php b/lib/private/DirectEditing/Manager.php index 4823b6b4456..154002ef340 100644 --- a/lib/private/DirectEditing/Manager.php +++ b/lib/private/DirectEditing/Manager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/DirectEditing/Token.php b/lib/private/DirectEditing/Token.php index 12ad9411216..ca01265f9df 100644 --- a/lib/private/DirectEditing/Token.php +++ b/lib/private/DirectEditing/Token.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/EmojiHelper.php b/lib/private/EmojiHelper.php index 514973b2959..52ab441e73a 100644 --- a/lib/private/EmojiHelper.php +++ b/lib/private/EmojiHelper.php @@ -19,8 +19,8 @@ class EmojiHelper implements IEmojiHelper { } public function doesPlatformSupportEmoji(): bool { - return $this->db->supports4ByteText() && - \class_exists(\IntlBreakIterator::class); + return $this->db->supports4ByteText() + && \class_exists(\IntlBreakIterator::class); } public function isValidSingleEmoji(string $emoji): bool { @@ -48,17 +48,17 @@ class EmojiHelper implements IEmojiHelper { if (strlen($emoji) >= 2) { // If the current code-point is an emoji or a modifier (like a skin-tone) // just continue and check the next character - if ($codePointType === \IntlChar::CHAR_CATEGORY_MODIFIER_SYMBOL || - $codePointType === \IntlChar::CHAR_CATEGORY_MODIFIER_LETTER || - $codePointType === \IntlChar::CHAR_CATEGORY_OTHER_SYMBOL || - $codePointType === \IntlChar::CHAR_CATEGORY_FORMAT_CHAR || // i.e. 🏴 🏴 - $codePointType === \IntlChar::CHAR_CATEGORY_OTHER_PUNCTUATION || // i.e. ‼️ ⁉️ #⃣ - $codePointType === \IntlChar::CHAR_CATEGORY_LOWERCASE_LETTER || // i.e. ℹ️ - $codePointType === \IntlChar::CHAR_CATEGORY_MATH_SYMBOL || // i.e. ↔️ ◻️ ⤴️ ⤵️ - $codePointType === \IntlChar::CHAR_CATEGORY_ENCLOSING_MARK || // i.e. 0⃣..9⃣ - $codePointType === \IntlChar::CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER || // i.e. 0⃣..9⃣ - $codePointType === \IntlChar::CHAR_CATEGORY_DASH_PUNCTUATION || // i.e. 〰️ - $codePointType === \IntlChar::CHAR_CATEGORY_GENERAL_OTHER_TYPES + if ($codePointType === \IntlChar::CHAR_CATEGORY_MODIFIER_SYMBOL + || $codePointType === \IntlChar::CHAR_CATEGORY_MODIFIER_LETTER + || $codePointType === \IntlChar::CHAR_CATEGORY_OTHER_SYMBOL + || $codePointType === \IntlChar::CHAR_CATEGORY_FORMAT_CHAR // i.e. 🏴 🏴 + || $codePointType === \IntlChar::CHAR_CATEGORY_OTHER_PUNCTUATION // i.e. ‼️ ⁉️ #⃣ + || $codePointType === \IntlChar::CHAR_CATEGORY_LOWERCASE_LETTER // i.e. ℹ️ + || $codePointType === \IntlChar::CHAR_CATEGORY_MATH_SYMBOL // i.e. ↔️ ◻️ ⤴️ ⤵️ + || $codePointType === \IntlChar::CHAR_CATEGORY_ENCLOSING_MARK // i.e. 0⃣..9⃣ + || $codePointType === \IntlChar::CHAR_CATEGORY_DECIMAL_DIGIT_NUMBER // i.e. 0⃣..9⃣ + || $codePointType === \IntlChar::CHAR_CATEGORY_DASH_PUNCTUATION // i.e. 〰️ + || $codePointType === \IntlChar::CHAR_CATEGORY_GENERAL_OTHER_TYPES ) { continue; } diff --git a/lib/private/Encryption/EncryptionEventListener.php b/lib/private/Encryption/EncryptionEventListener.php new file mode 100644 index 00000000000..d51b4b0d531 --- /dev/null +++ b/lib/private/Encryption/EncryptionEventListener.php @@ -0,0 +1,100 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace OC\Encryption; + +use OC\Files\SetupManager; +use OC\Files\View; +use OCA\Files_Trashbin\Events\NodeRestoredEvent; +use OCP\Encryption\IFile; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\EventDispatcher\IEventListener; +use OCP\Files\Events\Node\NodeRenamedEvent; +use OCP\Files\NotFoundException; +use OCP\IUser; +use OCP\IUserManager; +use OCP\IUserSession; +use OCP\Share\Events\ShareCreatedEvent; +use OCP\Share\Events\ShareDeletedEvent; +use Psr\Log\LoggerInterface; + +/** @template-implements IEventListener<NodeRenamedEvent|ShareCreatedEvent|ShareDeletedEvent|NodeRestoredEvent> */ +class EncryptionEventListener implements IEventListener { + private ?Update $updater = null; + + public function __construct( + private IUserSession $userSession, + private SetupManager $setupManager, + private Manager $encryptionManager, + private IUserManager $userManager, + ) { + } + + public static function register(IEventDispatcher $dispatcher): void { + $dispatcher->addServiceListener(NodeRenamedEvent::class, static::class); + $dispatcher->addServiceListener(ShareCreatedEvent::class, static::class); + $dispatcher->addServiceListener(ShareDeletedEvent::class, static::class); + $dispatcher->addServiceListener(NodeRestoredEvent::class, static::class); + } + + public function handle(Event $event): void { + if (!$this->encryptionManager->isEnabled()) { + return; + } + if ($event instanceof NodeRenamedEvent) { + $this->getUpdate()->postRename($event->getSource(), $event->getTarget()); + } elseif ($event instanceof ShareCreatedEvent) { + $this->getUpdate()->postShared($event->getShare()->getNode()); + } elseif ($event instanceof ShareDeletedEvent) { + try { + // In case the unsharing happens in a background job, we don't have + // a session and we load instead the user from the UserManager + $owner = $this->userManager->get($event->getShare()->getShareOwner()); + $this->getUpdate($owner)->postUnshared($event->getShare()->getNode()); + } catch (NotFoundException $e) { + /* The node was deleted already, nothing to update */ + } + } elseif ($event instanceof NodeRestoredEvent) { + $this->getUpdate()->postRestore($event->getTarget()); + } + } + + private function getUpdate(?IUser $owner = null): Update { + if (is_null($this->updater)) { + $user = $this->userSession->getUser(); + if (!$user && ($owner !== null)) { + $user = $owner; + } + if (!$user) { + throw new \Exception('Inconsistent data, File unshared, but owner not found. Should not happen'); + } + + $uid = $user->getUID(); + + if (!$this->setupManager->isSetupComplete($user)) { + $this->setupManager->setupForUser($user); + } + + $this->updater = new Update( + new Util( + new View(), + $this->userManager, + \OC::$server->getGroupManager(), + \OC::$server->getConfig()), + \OC::$server->getEncryptionManager(), + \OC::$server->get(IFile::class), + \OC::$server->get(LoggerInterface::class), + $uid + ); + } + + return $this->updater; + } +} diff --git a/lib/private/Encryption/EncryptionWrapper.php b/lib/private/Encryption/EncryptionWrapper.php index 7f355b603d6..b9db9616538 100644 --- a/lib/private/Encryption/EncryptionWrapper.php +++ b/lib/private/Encryption/EncryptionWrapper.php @@ -75,15 +75,6 @@ class EncryptionWrapper { \OC::$server->getGroupManager(), \OC::$server->getConfig() ); - $update = new Update( - new View(), - $util, - Filesystem::getMountManager(), - $this->manager, - $fileHelper, - $this->logger, - $uid - ); return new Encryption( $parameters, $this->manager, @@ -92,7 +83,6 @@ class EncryptionWrapper { $fileHelper, $uid, $keyStorage, - $update, $mountManager, $this->arrayCache ); diff --git a/lib/private/Encryption/HookManager.php b/lib/private/Encryption/HookManager.php deleted file mode 100644 index 39e7edabb95..00000000000 --- a/lib/private/Encryption/HookManager.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php - -/** - * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2016 ownCloud, Inc. - * SPDX-License-Identifier: AGPL-3.0-only - */ -namespace OC\Encryption; - -use OC\Files\Filesystem; -use OC\Files\SetupManager; -use OC\Files\View; -use OCP\Encryption\IFile; -use Psr\Log\LoggerInterface; - -class HookManager { - private static ?Update $updater = null; - - public static function postShared($params): void { - self::getUpdate()->postShared($params); - } - public static function postUnshared($params): void { - // In case the unsharing happens in a background job, we don't have - // a session and we load instead the user from the UserManager - $path = Filesystem::getPath($params['fileSource']); - $owner = Filesystem::getOwner($path); - self::getUpdate($owner)->postUnshared($params); - } - - public static function postRename($params): void { - self::getUpdate()->postRename($params); - } - - public static function postRestore($params): void { - self::getUpdate()->postRestore($params); - } - - private static function getUpdate(?string $owner = null): Update { - if (is_null(self::$updater)) { - $user = \OC::$server->getUserSession()->getUser(); - if (!$user && $owner) { - $user = \OC::$server->getUserManager()->get($owner); - } - if (!$user) { - throw new \Exception('Inconsistent data, File unshared, but owner not found. Should not happen'); - } - - $uid = ''; - if ($user) { - $uid = $user->getUID(); - } - - $setupManager = \OC::$server->get(SetupManager::class); - if (!$setupManager->isSetupComplete($user)) { - $setupManager->setupForUser($user); - } - - self::$updater = new Update( - new View(), - new Util( - new View(), - \OC::$server->getUserManager(), - \OC::$server->getGroupManager(), - \OC::$server->getConfig()), - Filesystem::getMountManager(), - \OC::$server->getEncryptionManager(), - \OC::$server->get(IFile::class), - \OC::$server->get(LoggerInterface::class), - $uid - ); - } - - return self::$updater; - } -} diff --git a/lib/private/Encryption/Keys/Storage.php b/lib/private/Encryption/Keys/Storage.php index 2c0ce9e5ef3..cce22b9138a 100644 --- a/lib/private/Encryption/Keys/Storage.php +++ b/lib/private/Encryption/Keys/Storage.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Encryption/Update.php b/lib/private/Encryption/Update.php index 0b27d63c19a..293a1ce653c 100644 --- a/lib/private/Encryption/Update.php +++ b/lib/private/Encryption/Update.php @@ -1,146 +1,85 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OC\Encryption; use InvalidArgumentException; -use OC\Files\Filesystem; -use OC\Files\Mount; use OC\Files\View; use OCP\Encryption\Exceptions\GenericEncryptionException; +use OCP\Files\File as OCPFile; +use OCP\Files\Folder; +use OCP\Files\NotFoundException; use Psr\Log\LoggerInterface; /** * update encrypted files, e.g. because a file was shared */ class Update { - /** @var View */ - protected $view; - - /** @var Util */ - protected $util; - - /** @var \OC\Files\Mount\Manager */ - protected $mountManager; - - /** @var Manager */ - protected $encryptionManager; - - /** @var string */ - protected $uid; - - /** @var File */ - protected $file; - - /** @var LoggerInterface */ - protected $logger; - - /** - * @param string $uid - */ public function __construct( - View $view, - Util $util, - Mount\Manager $mountManager, - Manager $encryptionManager, - File $file, - LoggerInterface $logger, - $uid, + protected Util $util, + protected Manager $encryptionManager, + protected File $file, + protected LoggerInterface $logger, + protected string $uid, ) { - $this->view = $view; - $this->util = $util; - $this->mountManager = $mountManager; - $this->encryptionManager = $encryptionManager; - $this->file = $file; - $this->logger = $logger; - $this->uid = $uid; } /** * hook after file was shared - * - * @param array $params */ - public function postShared($params) { - if ($this->encryptionManager->isEnabled()) { - if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') { - $path = Filesystem::getPath($params['fileSource']); - [$owner, $ownerPath] = $this->getOwnerPath($path); - $absPath = '/' . $owner . '/files/' . $ownerPath; - $this->update($absPath); - } - } + public function postShared(OCPFile|Folder $node): void { + $this->update($node); } /** * hook after file was unshared - * - * @param array $params */ - public function postUnshared($params) { - if ($this->encryptionManager->isEnabled()) { - if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') { - $path = Filesystem::getPath($params['fileSource']); - [$owner, $ownerPath] = $this->getOwnerPath($path); - $absPath = '/' . $owner . '/files/' . $ownerPath; - $this->update($absPath); - } - } + public function postUnshared(OCPFile|Folder $node): void { + $this->update($node); } /** * inform encryption module that a file was restored from the trash bin, * e.g. to update the encryption keys - * - * @param array $params */ - public function postRestore($params) { - if ($this->encryptionManager->isEnabled()) { - $path = Filesystem::normalizePath('/' . $this->uid . '/files/' . $params['filePath']); - $this->update($path); - } + public function postRestore(OCPFile|Folder $node): void { + $this->update($node); } /** * inform encryption module that a file was renamed, * e.g. to update the encryption keys - * - * @param array $params */ - public function postRename($params) { - $source = $params['oldpath']; - $target = $params['newpath']; - if ( - $this->encryptionManager->isEnabled() && - dirname($source) !== dirname($target) - ) { - [$owner, $ownerPath] = $this->getOwnerPath($target); - $absPath = '/' . $owner . '/files/' . $ownerPath; - $this->update($absPath); + public function postRename(OCPFile|Folder $source, OCPFile|Folder $target): void { + if (dirname($source->getPath()) !== dirname($target->getPath())) { + $this->update($target); } } /** - * get owner and path relative to data/<owner>/files + * get owner and path relative to data/ * - * @param string $path path to file for current user - * @return array ['owner' => $owner, 'path' => $path] * @throws \InvalidArgumentException */ - protected function getOwnerPath($path) { - $info = Filesystem::getFileInfo($path); - $owner = Filesystem::getOwner($path); + protected function getOwnerPath(OCPFile|Folder $node): string { + $owner = $node->getOwner()?->getUID(); + if ($owner === null) { + throw new InvalidArgumentException('No owner found for ' . $node->getId()); + } $view = new View('/' . $owner . '/files'); - $path = $view->getPath($info->getId()); - if ($path === null) { - throw new InvalidArgumentException('No file found for ' . $info->getId()); + try { + $path = $view->getPath($node->getId()); + } catch (NotFoundException $e) { + throw new InvalidArgumentException('No file found for ' . $node->getId(), previous:$e); } - - return [$owner, $path]; + return '/' . $owner . '/files/' . $path; } /** @@ -149,7 +88,7 @@ class Update { * @param string $path relative to data/ * @throws Exceptions\ModuleDoesNotExistsException */ - public function update($path) { + public function update(OCPFile|Folder $node): void { $encryptionModule = $this->encryptionManager->getEncryptionModule(); // if the encryption module doesn't encrypt the files on a per-user basis @@ -158,15 +97,14 @@ class Update { return; } + $path = $this->getOwnerPath($node); // if a folder was shared, get a list of all (sub-)folders - if ($this->view->is_dir($path)) { + if ($node instanceof Folder) { $allFiles = $this->util->getAllFiles($path); } else { $allFiles = [$path]; } - - foreach ($allFiles as $file) { $usersSharing = $this->file->getAccessList($file); try { diff --git a/lib/private/Encryption/Util.php b/lib/private/Encryption/Util.php index 1fb08b15696..2d7bc28129b 100644 --- a/lib/private/Encryption/Util.php +++ b/lib/private/Encryption/Util.php @@ -290,8 +290,8 @@ class Util { if (count($root) > 1) { // detect alternative key storage root $rootDir = $this->getKeyStorageRoot(); - if ($rootDir !== '' && - str_starts_with(Filesystem::normalizePath($path), Filesystem::normalizePath($rootDir)) + if ($rootDir !== '' + && str_starts_with(Filesystem::normalizePath($path), Filesystem::normalizePath($rootDir)) ) { return true; } @@ -304,7 +304,7 @@ class Util { // detect user specific folders if ($this->userManager->userExists($root[1]) - && in_array($root[2], $this->excludedPaths)) { + && in_array($root[2] ?? '', $this->excludedPaths)) { return true; } } diff --git a/lib/private/Federation/CloudFederationFactory.php b/lib/private/Federation/CloudFederationFactory.php index f5f25d14ea1..d06de0f2f58 100644 --- a/lib/private/Federation/CloudFederationFactory.php +++ b/lib/private/Federation/CloudFederationFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Federation/CloudFederationNotification.php b/lib/private/Federation/CloudFederationNotification.php index 855580843ba..6ae805df1d9 100644 --- a/lib/private/Federation/CloudFederationNotification.php +++ b/lib/private/Federation/CloudFederationNotification.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Federation/CloudFederationProviderManager.php b/lib/private/Federation/CloudFederationProviderManager.php index e9354294351..81b5d717a56 100644 --- a/lib/private/Federation/CloudFederationProviderManager.php +++ b/lib/private/Federation/CloudFederationProviderManager.php @@ -227,8 +227,8 @@ class CloudFederationProviderManager implements ICloudFederationProviderManager private function prepareOcmPayload(string $uri, string $payload): array { $payload = array_merge($this->getDefaultRequestOptions(), ['body' => $payload]); - if ($this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_SIGN_ENFORCED, lazy: true) && - $this->signatoryManager->getRemoteSignatory($this->signatureManager->extractIdentityFromUri($uri)) === null) { + if ($this->appConfig->getValueBool('core', OCMSignatoryManager::APPCONFIG_SIGN_ENFORCED, lazy: true) + && $this->signatoryManager->getRemoteSignatory($this->signatureManager->extractIdentityFromUri($uri)) === null) { return $payload; } diff --git a/lib/private/Federation/CloudFederationShare.php b/lib/private/Federation/CloudFederationShare.php index 22e36d87312..2eb06b3acea 100644 --- a/lib/private/Federation/CloudFederationShare.php +++ b/lib/private/Federation/CloudFederationShare.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -20,6 +21,8 @@ class CloudFederationShare implements ICloudFederationShare { 'ownerDisplayName' => '', 'sharedBy' => '', 'sharedByDisplayName' => '', + 'sender' => '', + 'senderDisplayName' => '', 'protocol' => [] ]; @@ -155,6 +158,7 @@ class CloudFederationShare implements ICloudFederationShare { */ public function setSharedBy($sharedBy) { $this->share['sharedBy'] = $sharedBy; + $this->share['sender'] = $sharedBy; } /** @@ -166,6 +170,7 @@ class CloudFederationShare implements ICloudFederationShare { */ public function setSharedByDisplayName($sharedByDisplayName) { $this->share['sharedByDisplayName'] = $sharedByDisplayName; + $this->share['senderDisplayName'] = $sharedByDisplayName; } /** diff --git a/lib/private/Federation/CloudId.php b/lib/private/Federation/CloudId.php index c20dbfc6418..b807c29d812 100644 --- a/lib/private/Federation/CloudId.php +++ b/lib/private/Federation/CloudId.php @@ -9,29 +9,15 @@ declare(strict_types=1); namespace OC\Federation; use OCP\Federation\ICloudId; +use OCP\Federation\ICloudIdManager; class CloudId implements ICloudId { - /** @var string */ - private $id; - /** @var string */ - private $user; - /** @var string */ - private $remote; - /** @var string|null */ - private $displayName; - - /** - * CloudId constructor. - * - * @param string $id - * @param string $user - * @param string $remote - */ - public function __construct(string $id, string $user, string $remote, ?string $displayName = null) { - $this->id = $id; - $this->user = $user; - $this->remote = $remote; - $this->displayName = $displayName; + public function __construct( + protected string $id, + protected string $user, + protected string $remote, + protected ?string $displayName = null, + ) { } /** @@ -44,12 +30,18 @@ class CloudId implements ICloudId { } public function getDisplayId(): string { + if ($this->displayName === null) { + /** @var CloudIdManager $cloudIdManager */ + $cloudIdManager = \OCP\Server::get(ICloudIdManager::class); + $this->displayName = $cloudIdManager->getDisplayNameFromContact($this->getId()); + } + + $atHost = str_replace(['http://', 'https://'], '', $this->getRemote()); + if ($this->displayName) { - $atPos = strrpos($this->getId(), '@'); - $atHost = substr($this->getId(), $atPos); - return $this->displayName . $atHost; + return $this->displayName . '@' . $atHost; } - return str_replace('https://', '', str_replace('http://', '', $this->getId())); + return $this->getUser() . '@' . $atHost; } /** diff --git a/lib/private/Federation/CloudIdManager.php b/lib/private/Federation/CloudIdManager.php index 1c808c03eda..7e7adda3d39 100644 --- a/lib/private/Federation/CloudIdManager.php +++ b/lib/private/Federation/CloudIdManager.php @@ -28,6 +28,7 @@ class CloudIdManager implements ICloudIdManager { /** @var IUserManager */ private $userManager; private ICache $memCache; + private ICache $displayNameCache; /** @var array[] */ private array $cache = []; @@ -42,6 +43,7 @@ class CloudIdManager implements ICloudIdManager { $this->urlGenerator = $urlGenerator; $this->userManager = $userManager; $this->memCache = $cacheFactory->createDistributed('cloud_id_'); + $this->displayNameCache = $cacheFactory->createDistributed('cloudid_name_'); $eventDispatcher->addListener(UserChangedEvent::class, [$this, 'handleUserEvent']); $eventDispatcher->addListener(CardUpdatedEvent::class, [$this, 'handleCardEvent']); } @@ -104,17 +106,28 @@ class CloudIdManager implements ICloudIdManager { $user = substr($id, 0, $lastValidAtPos); $remote = substr($id, $lastValidAtPos + 1); - $this->userManager->validateUserId($user); + // We accept slightly more chars when working with federationId than with a local userId. + // We remove those eventual chars from the UserId before using + // the IUserManager API to confirm its format. + $this->userManager->validateUserId(str_replace('=', '-', $user)); if (!empty($user) && !empty($remote)) { $remote = $this->ensureDefaultProtocol($remote); - return new CloudId($id, $user, $remote, $this->getDisplayNameFromContact($id)); + return new CloudId($id, $user, $remote, null); } } throw new \InvalidArgumentException('Invalid cloud id'); } - protected function getDisplayNameFromContact(string $cloudId): ?string { + public function getDisplayNameFromContact(string $cloudId): ?string { + $cachedName = $this->displayNameCache->get($cloudId); + if ($cachedName !== null) { + if ($cachedName === $cloudId) { + return null; + } + return $cachedName; + } + $addressBookEntries = $this->contactsManager->search($cloudId, ['CLOUD'], [ 'limit' => 1, 'enumeration' => false, @@ -128,14 +141,17 @@ class CloudIdManager implements ICloudIdManager { // Warning, if user decides to make their full name local only, // no FN is found on federated servers if (isset($entry['FN'])) { + $this->displayNameCache->set($cloudId, $entry['FN'], 15 * 60); return $entry['FN']; } else { - return $cloudID; + $this->displayNameCache->set($cloudId, $cloudId, 15 * 60); + return null; } } } } } + $this->displayNameCache->set($cloudId, $cloudId, 15 * 60); return null; } @@ -168,7 +184,7 @@ class CloudIdManager implements ICloudIdManager { $localUser = $this->userManager->get($user); $displayName = $localUser ? $localUser->getDisplayName() : ''; } else { - $displayName = $this->getDisplayNameFromContact($user . '@' . $host); + $displayName = null; } // For the visible cloudID we only strip away https diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index cb841755efd..329466e682d 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -109,7 +109,7 @@ class Cache implements ICache { /** * get the stored metadata of a file or folder * - * @param string | int $file either the path of a file or folder or the file id for a file or folder + * @param string|int $file either the path of a file or folder or the file id for a file or folder * @return ICacheEntry|false the cache entry as array or false if the file is not found in the cache */ public function get($file) { @@ -131,15 +131,17 @@ class Cache implements ICache { $data = $result->fetch(); $result->closeCursor(); - //merge partial data - if (!$data && is_string($file) && isset($this->partial[$file])) { - return $this->partial[$file]; - } elseif (!$data) { - return $data; - } else { + if ($data !== false) { $data['metadata'] = $metadataQuery->extractMetadata($data)->asArray(); return self::cacheEntryFromData($data, $this->mimetypeLoader); + } else { + //merge partial data + if (is_string($file) && isset($this->partial[$file])) { + return $this->partial[$file]; + } } + + return false; } /** @@ -661,13 +663,13 @@ class Cache implements ICache { $sourceData = $sourceCache->get($sourcePath); if (!$sourceData) { - throw new \Exception('Invalid source storage path: ' . $sourcePath); + throw new \Exception('Source path not found in cache: ' . $sourcePath); } $shardDefinition = $this->connection->getShardDefinition('filecache'); if ( - $shardDefinition && - $shardDefinition->getShardForKey($sourceCache->getNumericStorageId()) !== $shardDefinition->getShardForKey($this->getNumericStorageId()) + $shardDefinition + && $shardDefinition->getShardForKey($sourceCache->getNumericStorageId()) !== $shardDefinition->getShardForKey($this->getNumericStorageId()) ) { $this->moveFromStorageSharded($shardDefinition, $sourceCache, $sourceData, $targetPath); return; @@ -886,19 +888,23 @@ class Cache implements ICache { /** * Re-calculate the folder size and the size of all parent folders * - * @param string|boolean $path - * @param array $data (optional) meta data of the folder + * @param array|ICacheEntry|null $data (optional) meta data of the folder */ - public function correctFolderSize($path, $data = null, $isBackgroundScan = false) { + public function correctFolderSize(string $path, $data = null, bool $isBackgroundScan = false): void { $this->calculateFolderSize($path, $data); + if ($path !== '') { $parent = dirname($path); if ($parent === '.' || $parent === '/') { $parent = ''; } + if ($isBackgroundScan) { $parentData = $this->get($parent); - if ($parentData['size'] !== -1 && $this->getIncompleteChildrenCount($parentData['fileid']) === 0) { + if ($parentData !== false + && $parentData['size'] !== -1 + && $this->getIncompleteChildrenCount($parentData['fileid']) === 0 + ) { $this->correctFolderSize($parent, $parentData, $isBackgroundScan); } } else { @@ -920,7 +926,7 @@ class Cache implements ICache { ->from('filecache') ->whereParent($fileId) ->whereStorageId($this->getNumericStorageId()) - ->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT))); + ->andWhere($query->expr()->eq('size', $query->createNamedParameter(-1, IQueryBuilder::PARAM_INT))); $result = $query->executeQuery(); $size = (int)$result->fetchOne(); @@ -1009,8 +1015,8 @@ class Cache implements ICache { } // only set unencrypted size for a folder if any child entries have it set, or the folder is empty - $shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0 || $entry['unencrypted_size'] > 0; - if ($entry['size'] !== $totalSize || ($entry['unencrypted_size'] !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) { + $shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0 || ($entry['unencrypted_size'] ?? 0) > 0; + if ($entry['size'] !== $totalSize || (($entry['unencrypted_size'] ?? 0) !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) { if ($shouldWriteUnEncryptedSize) { // if all children have an unencrypted size of 0, just set the folder unencrypted size to 0 instead of summing the sizes if ($unencryptedMax === 0) { @@ -1061,28 +1067,19 @@ class Cache implements ICache { * @return string|false the path of the folder or false when no folder matched */ public function getIncomplete() { - // we select the fileid here first instead of directly selecting the path since this helps mariadb/mysql - // to use the correct index. - // The overhead of this should be minimal since the cost of selecting the path by id should be much lower - // than the cost of finding an item with size < 0 $query = $this->getQueryBuilder(); - $query->select('fileid') + $query->select('path') ->from('filecache') ->whereStorageId($this->getNumericStorageId()) - ->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT))) + ->andWhere($query->expr()->eq('size', $query->createNamedParameter(-1, IQueryBuilder::PARAM_INT))) ->orderBy('fileid', 'DESC') ->setMaxResults(1); $result = $query->executeQuery(); - $id = $result->fetchOne(); + $path = $result->fetchOne(); $result->closeCursor(); - if ($id === false) { - return false; - } - - $path = $this->getPathById($id); - return $path ?? false; + return $path === false ? false : (string)$path; } /** diff --git a/lib/private/Files/Cache/CacheEntry.php b/lib/private/Files/Cache/CacheEntry.php index e9417c8012a..ab5bae316f4 100644 --- a/lib/private/Files/Cache/CacheEntry.php +++ b/lib/private/Files/Cache/CacheEntry.php @@ -110,6 +110,10 @@ class CacheEntry implements ICacheEntry { return $this->data['upload_time'] ?? null; } + public function getParentId(): int { + return $this->data['parent']; + } + public function getData() { return $this->data; } diff --git a/lib/private/Files/Cache/QuerySearchHelper.php b/lib/private/Files/Cache/QuerySearchHelper.php index ff2d6766893..3ddcf1ca4e6 100644 --- a/lib/private/Files/Cache/QuerySearchHelper.php +++ b/lib/private/Files/Cache/QuerySearchHelper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index 3bd674f79e2..b067f70b8cb 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -83,7 +83,7 @@ class Scanner extends BasicEmitter implements IScanner { * * @param bool $useTransactions */ - public function setUseTransactions($useTransactions) { + public function setUseTransactions($useTransactions): void { $this->useTransactions = $useTransactions; } @@ -108,9 +108,9 @@ class Scanner extends BasicEmitter implements IScanner { * @param string $file * @param int $reuseExisting * @param int $parentId - * @param array|null|false $cacheData existing data in the cache for the file to be scanned + * @param array|CacheEntry|null|false $cacheData existing data in the cache for the file to be scanned * @param bool $lock set to false to disable getting an additional read lock during scanning - * @param null $data the metadata for the file, as returned by the storage + * @param array|null $data the metadata for the file, as returned by the storage * @return array|null an array of metadata of the scanned file * @throws \OCP\Lock\LockedException */ @@ -122,139 +122,130 @@ class Scanner extends BasicEmitter implements IScanner { return null; } } + // only proceed if $file is not a partial file, blacklist is handled by the storage - if (!self::isPartialFile($file)) { - // acquire a lock + if (self::isPartialFile($file)) { + return null; + } + + // acquire a lock + if ($lock) { + if ($this->storage->instanceOfStorage(ILockingStorage::class)) { + $this->storage->acquireLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); + } + } + + try { + $data = $data ?? $this->getData($file); + } catch (ForbiddenException $e) { if ($lock) { if ($this->storage->instanceOfStorage(ILockingStorage::class)) { - $this->storage->acquireLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); + $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); } } - try { - $data = $data ?? $this->getData($file); - } catch (ForbiddenException $e) { - if ($lock) { - if ($this->storage->instanceOfStorage(ILockingStorage::class)) { - $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); - } - } + return null; + } - return null; - } + try { + if ($data === null) { + $this->removeFromCache($file); + } else { + // pre-emit only if it was a file. By that we avoid counting/treating folders as files + if ($data['mimetype'] !== 'httpd/unix-directory') { + $this->emit('\OC\Files\Cache\Scanner', 'scanFile', [$file, $this->storageId]); + \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', ['path' => $file, 'storage' => $this->storageId]); + } - try { - if ($data) { - // pre-emit only if it was a file. By that we avoid counting/treating folders as files - if ($data['mimetype'] !== 'httpd/unix-directory') { - $this->emit('\OC\Files\Cache\Scanner', 'scanFile', [$file, $this->storageId]); - \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', ['path' => $file, 'storage' => $this->storageId]); - } + $parent = dirname($file); + if ($parent === '.' || $parent === '/') { + $parent = ''; + } + if ($parentId === -1) { + $parentId = $this->cache->getParentId($file); + } - $parent = dirname($file); - if ($parent === '.' || $parent === '/') { - $parent = ''; - } - if ($parentId === -1) { - $parentId = $this->cache->getParentId($file); + // scan the parent if it's not in the cache (id -1) and the current file is not the root folder + if ($file && $parentId === -1) { + $parentData = $this->scanFile($parent); + if ($parentData === null) { + return null; } - // scan the parent if it's not in the cache (id -1) and the current file is not the root folder - if ($file && $parentId === -1) { - $parentData = $this->scanFile($parent); - if (!$parentData) { - return null; - } - $parentId = $parentData['fileid']; - } - if ($parent) { - $data['parent'] = $parentId; - } - if (is_null($cacheData)) { - /** @var CacheEntry $cacheData */ - $cacheData = $this->cache->get($file); - } - if ($cacheData && $reuseExisting && isset($cacheData['fileid'])) { - // prevent empty etag - $etag = empty($cacheData['etag']) ? $data['etag'] : $cacheData['etag']; - $fileId = $cacheData['fileid']; - $data['fileid'] = $fileId; - // only reuse data if the file hasn't explicitly changed - $mtimeUnchanged = isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']; - // if the folder is marked as unscanned, never reuse etags - if ($mtimeUnchanged && $cacheData['size'] !== -1) { - $data['mtime'] = $cacheData['mtime']; - if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) { - $data['size'] = $cacheData['size']; - } - if ($reuseExisting & self::REUSE_ETAG && !$this->storage->instanceOfStorage(IReliableEtagStorage::class)) { - $data['etag'] = $etag; - } - } + $parentId = $parentData['fileid']; + } + if ($parent) { + $data['parent'] = $parentId; + } - // we only updated unencrypted_size if it's already set - if ($cacheData['unencrypted_size'] === 0) { - unset($data['unencrypted_size']); + $cacheData = $cacheData ?? $this->cache->get($file); + if ($reuseExisting && $cacheData !== false && isset($cacheData['fileid'])) { + // prevent empty etag + $etag = empty($cacheData['etag']) ? $data['etag'] : $cacheData['etag']; + $fileId = $cacheData['fileid']; + $data['fileid'] = $fileId; + // only reuse data if the file hasn't explicitly changed + $mtimeUnchanged = isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']; + // if the folder is marked as unscanned, never reuse etags + if ($mtimeUnchanged && $cacheData['size'] !== -1) { + $data['mtime'] = $cacheData['mtime']; + if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) { + $data['size'] = $cacheData['size']; } - - // Only update metadata that has changed - // i.e. get all the values in $data that are not present in the cache already - $newData = $this->array_diff_assoc_multi($data, $cacheData->getData()); - - // make it known to the caller that etag has been changed and needs propagation - if (isset($newData['etag'])) { - $data['etag_changed'] = true; + if ($reuseExisting & self::REUSE_ETAG && !$this->storage->instanceOfStorage(IReliableEtagStorage::class)) { + $data['etag'] = $etag; } - } else { - // we only updated unencrypted_size if it's already set - unset($data['unencrypted_size']); - $newData = $data; - $fileId = -1; } - if (!empty($newData)) { - // Reset the checksum if the data has changed - $newData['checksum'] = ''; - $newData['parent'] = $parentId; - $data['fileid'] = $this->addToCache($file, $newData, $fileId); - } - - $data['oldSize'] = ($cacheData && isset($cacheData['size'])) ? $cacheData['size'] : 0; - if ($cacheData && isset($cacheData['encrypted'])) { - $data['encrypted'] = $cacheData['encrypted']; + // we only updated unencrypted_size if it's already set + if (isset($cacheData['unencrypted_size']) && $cacheData['unencrypted_size'] === 0) { + unset($data['unencrypted_size']); } - // post-emit only if it was a file. By that we avoid counting/treating folders as files - if ($data['mimetype'] !== 'httpd/unix-directory') { - $this->emit('\OC\Files\Cache\Scanner', 'postScanFile', [$file, $this->storageId]); - \OC_Hook::emit('\OC\Files\Cache\Scanner', 'post_scan_file', ['path' => $file, 'storage' => $this->storageId]); + /** + * Only update metadata that has changed. + * i.e. get all the values in $data that are not present in the cache already + * + * We need the OC implementation for usage of "getData" method below. + * @var \OC\Files\Cache\CacheEntry $cacheData + */ + $newData = $this->array_diff_assoc_multi($data, $cacheData->getData()); + + // make it known to the caller that etag has been changed and needs propagation + if (isset($newData['etag'])) { + $data['etag_changed'] = true; } } else { - $this->removeFromCache($file); + unset($data['unencrypted_size']); + $newData = $data; + $fileId = -1; } - } catch (\Exception $e) { - if ($lock) { - if ($this->storage->instanceOfStorage(ILockingStorage::class)) { - $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); - } + if (!empty($newData)) { + // Reset the checksum if the data has changed + $newData['checksum'] = ''; + $newData['parent'] = $parentId; + $data['fileid'] = $this->addToCache($file, $newData, $fileId); } - throw $e; - } - // release the acquired lock - if ($lock) { - if ($this->storage->instanceOfStorage(ILockingStorage::class)) { - $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); + if ($cacheData !== false) { + $data['oldSize'] = $cacheData['size'] ?? 0; + $data['encrypted'] = $cacheData['encrypted'] ?? false; } - } - if ($data && !isset($data['encrypted'])) { - $data['encrypted'] = false; + // post-emit only if it was a file. By that we avoid counting/treating folders as files + if ($data['mimetype'] !== 'httpd/unix-directory') { + $this->emit('\OC\Files\Cache\Scanner', 'postScanFile', [$file, $this->storageId]); + \OC_Hook::emit('\OC\Files\Cache\Scanner', 'post_scan_file', ['path' => $file, 'storage' => $this->storageId]); + } + } + } finally { + // release the acquired lock + if ($lock && $this->storage->instanceOfStorage(ILockingStorage::class)) { + $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider); } - return $data; } - return null; + return $data; } protected function removeFromCache($path) { @@ -319,29 +310,26 @@ class Scanner extends BasicEmitter implements IScanner { if ($reuse === -1) { $reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG; } - if ($lock) { - if ($this->storage->instanceOfStorage(ILockingStorage::class)) { - $this->storage->acquireLock('scanner::' . $path, ILockingProvider::LOCK_EXCLUSIVE, $this->lockingProvider); - $this->storage->acquireLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider); - } + + if ($lock && $this->storage->instanceOfStorage(ILockingStorage::class)) { + $this->storage->acquireLock('scanner::' . $path, ILockingProvider::LOCK_EXCLUSIVE, $this->lockingProvider); + $this->storage->acquireLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider); } + try { - try { - $data = $this->scanFile($path, $reuse, -1, null, $lock); - if ($data && $data['mimetype'] === 'httpd/unix-directory') { - $size = $this->scanChildren($path, $recursive, $reuse, $data['fileid'], $lock, $data['size']); - $data['size'] = $size; - } - } catch (NotFoundException $e) { - $this->removeFromCache($path); - return null; + $data = $this->scanFile($path, $reuse, -1, lock: $lock); + + if ($data !== null && $data['mimetype'] === 'httpd/unix-directory') { + $size = $this->scanChildren($path, $recursive, $reuse, $data['fileid'], $lock, $data['size']); + $data['size'] = $size; } + } catch (NotFoundException $e) { + $this->removeFromCache($path); + return null; } finally { - if ($lock) { - if ($this->storage->instanceOfStorage(ILockingStorage::class)) { - $this->storage->releaseLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider); - $this->storage->releaseLock('scanner::' . $path, ILockingProvider::LOCK_EXCLUSIVE, $this->lockingProvider); - } + if ($lock && $this->storage->instanceOfStorage(ILockingStorage::class)) { + $this->storage->releaseLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider); + $this->storage->releaseLock('scanner::' . $path, ILockingProvider::LOCK_EXCLUSIVE, $this->lockingProvider); } } return $data; @@ -363,23 +351,23 @@ class Scanner extends BasicEmitter implements IScanner { * */ protected function array_diff_assoc_multi(array $array1, array $array2) { - + $result = []; foreach ($array1 as $key => $value) { - + // if $array2 doesn't have the same key, that's a result if (!array_key_exists($key, $array2)) { $result[$key] = $value; continue; } - + // if $array2's value for the same key is different, that's a result if ($array2[$key] !== $value && !is_array($value)) { $result[$key] = $value; continue; } - + if (is_array($value)) { $nestedDiff = $this->array_diff_assoc_multi($value, $array2[$key]); if (!empty($nestedDiff)) { @@ -395,9 +383,9 @@ class Scanner extends BasicEmitter implements IScanner { * Get the children currently in the cache * * @param int $folderId - * @return array[] + * @return array<string, \OCP\Files\Cache\ICacheEntry> */ - protected function getExistingChildren($folderId) { + protected function getExistingChildren($folderId): array { $existingChildren = []; $children = $this->cache->getFolderContentsById($folderId); foreach ($children as $child) { diff --git a/lib/private/Files/Cache/SearchBuilder.php b/lib/private/Files/Cache/SearchBuilder.php index e89b95b756f..e1d3c42a8a2 100644 --- a/lib/private/Files/Cache/SearchBuilder.php +++ b/lib/private/Files/Cache/SearchBuilder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -12,6 +13,7 @@ use OCP\Files\Search\ISearchBinaryOperator; use OCP\Files\Search\ISearchComparison; use OCP\Files\Search\ISearchOperator; use OCP\Files\Search\ISearchOrder; +use OCP\FilesMetadata\IFilesMetadataManager; use OCP\FilesMetadata\IMetadataQuery; /** @@ -80,13 +82,10 @@ class SearchBuilder { public const TAG_FAVORITE = '_$!<Favorite>!$_'; - /** @var IMimeTypeLoader */ - private $mimetypeLoader; - public function __construct( - IMimeTypeLoader $mimetypeLoader, + private IMimeTypeLoader $mimetypeLoader, + private IFilesMetadataManager $filesMetadataManager, ) { - $this->mimetypeLoader = $mimetypeLoader; } /** @@ -285,11 +284,18 @@ class SearchBuilder { private function getExtraOperatorField(ISearchComparison $operator, IMetadataQuery $metadataQuery): array { - $paramType = self::$fieldTypes[$operator->getField()]; $field = $operator->getField(); $value = $operator->getValue(); $type = $operator->getType(); + $knownMetadata = $this->filesMetadataManager->getKnownMetadata(); + $isIndex = $knownMetadata->isIndex($field); + $paramType = $knownMetadata->getType($field) === 'int' ? 'integer' : 'string'; + + if (!$isIndex) { + throw new \InvalidArgumentException('Cannot search non indexed metadata key'); + } + switch ($operator->getExtra()) { case IMetadataQuery::EXTRA: $metadataQuery->joinIndex($field); // join index table if not joined yet diff --git a/lib/private/Files/Cache/Storage.php b/lib/private/Files/Cache/Storage.php index 2b49e65f0b4..1a3bda58e6a 100644 --- a/lib/private/Files/Cache/Storage.php +++ b/lib/private/Files/Cache/Storage.php @@ -213,6 +213,7 @@ class Storage { $query = $db->getQueryBuilder(); $query->delete('filecache') ->where($query->expr()->in('storage', $query->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY))); + $query->runAcrossAllShards(); $query->executeStatement(); $query = $db->getQueryBuilder(); diff --git a/lib/private/Files/Cache/Updater.php b/lib/private/Files/Cache/Updater.php index 42812dbc882..03681036aa2 100644 --- a/lib/private/Files/Cache/Updater.php +++ b/lib/private/Files/Cache/Updater.php @@ -186,6 +186,9 @@ class Updater implements IUpdater { public function copyFromStorage(IStorage $sourceStorage, string $source, string $target): void { $this->copyOrRenameFromStorage($sourceStorage, $source, $target, function (ICache $sourceCache, ICacheEntry $sourceInfo) use ($target) { $parent = dirname($target); + if ($parent === '.') { + $parent = ''; + } $parentInCache = $this->cache->inCache($parent); if (!$parentInCache) { $parentData = $this->scanner->scan($parent, Scanner::SCAN_SHALLOW, -1, false); diff --git a/lib/private/Files/Cache/Watcher.php b/lib/private/Files/Cache/Watcher.php index 2e42b716695..f1de5d3cfb8 100644 --- a/lib/private/Files/Cache/Watcher.php +++ b/lib/private/Files/Cache/Watcher.php @@ -33,6 +33,9 @@ class Watcher implements IWatcher { */ protected $scanner; + /** @var callable[] */ + protected $onUpdate = []; + /** * @param \OC\Files\Storage\Storage $storage */ @@ -100,6 +103,9 @@ class Watcher implements IWatcher { if ($this->cache instanceof Cache) { $this->cache->correctFolderSize($path); } + foreach ($this->onUpdate as $callback) { + $callback($path); + } } /** @@ -112,7 +118,7 @@ class Watcher implements IWatcher { public function needsUpdate($path, $cachedData) { if ($this->watchPolicy === self::CHECK_ALWAYS or ($this->watchPolicy === self::CHECK_ONCE and !in_array($path, $this->checkedPaths))) { $this->checkedPaths[] = $path; - return $this->storage->hasUpdated($path, $cachedData['storage_mtime']); + return $cachedData['storage_mtime'] === null || $this->storage->hasUpdated($path, $cachedData['storage_mtime']); } return false; } @@ -130,4 +136,11 @@ class Watcher implements IWatcher { } } } + + /** + * register a callback to be called whenever the watcher triggers and update + */ + public function onUpdate(callable $callback): void { + $this->onUpdate[] = $callback; + } } diff --git a/lib/private/Files/Cache/Wrapper/CacheJail.php b/lib/private/Files/Cache/Wrapper/CacheJail.php index ea0f992114a..5bc4ee8529d 100644 --- a/lib/private/Files/Cache/Wrapper/CacheJail.php +++ b/lib/private/Files/Cache/Wrapper/CacheJail.php @@ -21,27 +21,29 @@ use OCP\Files\Search\ISearchOperator; * Jail to a subdirectory of the wrapped cache */ class CacheJail extends CacheWrapper { - /** - * @var string - */ - protected $root; - protected $unjailedRoot; + + protected string $unjailedRoot; public function __construct( ?ICache $cache, - string $root, + protected string $root, ?CacheDependencies $dependencies = null, ) { parent::__construct($cache, $dependencies); - $this->root = $root; - if ($cache instanceof CacheJail) { - $this->unjailedRoot = $cache->getSourcePath($root); - } else { - $this->unjailedRoot = $root; + $this->unjailedRoot = $root; + $parent = $cache; + while ($parent instanceof CacheWrapper) { + if ($parent instanceof CacheJail) { + $this->unjailedRoot = $parent->getSourcePath($this->unjailedRoot); + } + $parent = $parent->getCache(); } } + /** + * @return string + */ protected function getRoot() { return $this->root; } @@ -51,11 +53,14 @@ class CacheJail extends CacheWrapper { * * @return string */ - protected function getGetUnjailedRoot() { + public function getGetUnjailedRoot() { return $this->unjailedRoot; } - protected function getSourcePath($path) { + /** + * @return string + */ + protected function getSourcePath(string $path) { if ($path === '') { return $this->getRoot(); } else { @@ -95,7 +100,7 @@ class CacheJail extends CacheWrapper { /** * get the stored metadata of a file or folder * - * @param string /int $file + * @param string|int $file * @return ICacheEntry|false */ public function get($file) { @@ -206,12 +211,12 @@ class CacheJail extends CacheWrapper { /** * update the folder size and the size of all parent folders * - * @param string|boolean $path - * @param array $data (optional) meta data of the folder + * @param array|ICacheEntry|null $data (optional) meta data of the folder */ - public function correctFolderSize($path, $data = null, $isBackgroundScan = false) { - if ($this->getCache() instanceof Cache) { - $this->getCache()->correctFolderSize($this->getSourcePath($path), $data, $isBackgroundScan); + public function correctFolderSize(string $path, $data = null, bool $isBackgroundScan = false): void { + $cache = $this->getCache(); + if ($cache instanceof Cache) { + $cache->correctFolderSize($this->getSourcePath($path), $data, $isBackgroundScan); } } @@ -223,8 +228,9 @@ class CacheJail extends CacheWrapper { * @return int|float */ public function calculateFolderSize($path, $entry = null) { - if ($this->getCache() instanceof Cache) { - return $this->getCache()->calculateFolderSize($this->getSourcePath($path), $entry); + $cache = $this->getCache(); + if ($cache instanceof Cache) { + return $cache->calculateFolderSize($this->getSourcePath($path), $entry); } else { return 0; } diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php index fdaa2cf4b7a..f2f1036d6a3 100644 --- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php +++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php @@ -221,12 +221,12 @@ class CacheWrapper extends Cache { /** * update the folder size and the size of all parent folders * - * @param string|boolean $path - * @param array $data (optional) meta data of the folder + * @param array|ICacheEntry|null $data (optional) meta data of the folder */ - public function correctFolderSize($path, $data = null, $isBackgroundScan = false) { - if ($this->getCache() instanceof Cache) { - $this->getCache()->correctFolderSize($path, $data, $isBackgroundScan); + public function correctFolderSize(string $path, $data = null, bool $isBackgroundScan = false): void { + $cache = $this->getCache(); + if ($cache instanceof Cache) { + $cache->correctFolderSize($path, $data, $isBackgroundScan); } } @@ -238,8 +238,9 @@ class CacheWrapper extends Cache { * @return int|float */ public function calculateFolderSize($path, $entry = null) { - if ($this->getCache() instanceof Cache) { - return $this->getCache()->calculateFolderSize($path, $entry); + $cache = $this->getCache(); + if ($cache instanceof Cache) { + return $cache->calculateFolderSize($path, $entry); } else { return 0; } diff --git a/lib/private/Files/Cache/Wrapper/JailPropagator.php b/lib/private/Files/Cache/Wrapper/JailPropagator.php index 19ca4a13ece..d6409b7875e 100644 --- a/lib/private/Files/Cache/Wrapper/JailPropagator.php +++ b/lib/private/Files/Cache/Wrapper/JailPropagator.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Cache/Wrapper/JailWatcher.php b/lib/private/Files/Cache/Wrapper/JailWatcher.php index 9bd7da57233..b1ae516654a 100644 --- a/lib/private/Files/Cache/Wrapper/JailWatcher.php +++ b/lib/private/Files/Cache/Wrapper/JailWatcher.php @@ -55,4 +55,7 @@ class JailWatcher extends Watcher { $this->watcher->cleanFolder($this->getSourcePath($path)); } + public function onUpdate(callable $callback): void { + $this->watcher->onUpdate($callback); + } } diff --git a/lib/private/Files/Config/CachedMountFileInfo.php b/lib/private/Files/Config/CachedMountFileInfo.php index 90a6b47f9d8..69bd4e9301e 100644 --- a/lib/private/Files/Config/CachedMountFileInfo.php +++ b/lib/private/Files/Config/CachedMountFileInfo.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php index 6a5407934c8..9d63184e05f 100644 --- a/lib/private/Files/Config/MountProviderCollection.php +++ b/lib/private/Files/Config/MountProviderCollection.php @@ -24,60 +24,43 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { use EmitterTrait; /** - * @var \OCP\Files\Config\IHomeMountProvider[] + * @var list<IHomeMountProvider> */ - private $homeProviders = []; + private array $homeProviders = []; /** - * @var \OCP\Files\Config\IMountProvider[] + * @var list<IMountProvider> */ - private $providers = []; + private array $providers = []; - /** @var \OCP\Files\Config\IRootMountProvider[] */ - private $rootProviders = []; + /** @var list<IRootMountProvider> */ + private array $rootProviders = []; - /** - * @var \OCP\Files\Storage\IStorageFactory - */ - private $loader; - - /** - * @var \OCP\Files\Config\IUserMountCache - */ - private $mountCache; - - /** @var callable[] */ - private $mountFilters = []; + /** @var list<callable> */ + private array $mountFilters = []; - private IEventLogger $eventLogger; - - /** - * @param \OCP\Files\Storage\IStorageFactory $loader - * @param IUserMountCache $mountCache - */ public function __construct( - IStorageFactory $loader, - IUserMountCache $mountCache, - IEventLogger $eventLogger, + private IStorageFactory $loader, + private IUserMountCache $mountCache, + private IEventLogger $eventLogger, ) { - $this->loader = $loader; - $this->mountCache = $mountCache; - $this->eventLogger = $eventLogger; } + /** + * @return list<IMountPoint> + */ private function getMountsFromProvider(IMountProvider $provider, IUser $user, IStorageFactory $loader): array { $class = str_replace('\\', '_', get_class($provider)); $uid = $user->getUID(); $this->eventLogger->start('fs:setup:provider:' . $class, "Getting mounts from $class for $uid"); $mounts = $provider->getMountsForUser($user, $loader) ?? []; $this->eventLogger->end('fs:setup:provider:' . $class); - return $mounts; + return array_values($mounts); } /** - * @param IUser $user - * @param IMountProvider[] $providers - * @return IMountPoint[] + * @param list<IMountProvider> $providers + * @return list<IMountPoint> */ private function getUserMountsForProviders(IUser $user, array $providers): array { $loader = $this->loader; @@ -90,10 +73,16 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { return $this->filterMounts($user, $mounts); } + /** + * @return list<IMountPoint> + */ public function getMountsForUser(IUser $user): array { return $this->getUserMountsForProviders($user, $this->providers); } + /** + * @return list<IMountPoint> + */ public function getUserMountsForProviderClasses(IUser $user, array $mountProviderClasses): array { $providers = array_filter( $this->providers, @@ -102,7 +91,10 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { return $this->getUserMountsForProviders($user, $providers); } - public function addMountForUser(IUser $user, IMountManager $mountManager, ?callable $providerFilter = null) { + /** + * @return list<IMountPoint> + */ + public function addMountForUser(IUser $user, IMountManager $mountManager, ?callable $providerFilter = null): array { // shared mount provider gets to go last since it needs to know existing files // to check for name collisions $firstMounts = []; @@ -135,18 +127,15 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { array_walk($lateMounts, [$mountManager, 'addMount']); $this->eventLogger->end('fs:setup:add-mounts'); - return array_merge($lateMounts, $firstMounts); + return array_values(array_merge($lateMounts, $firstMounts)); } /** * Get the configured home mount for this user * - * @param \OCP\IUser $user - * @return \OCP\Files\Mount\IMountPoint * @since 9.1.0 */ - public function getHomeMountForUser(IUser $user) { - /** @var \OCP\Files\Config\IHomeMountProvider[] $providers */ + public function getHomeMountForUser(IUser $user): IMountPoint { $providers = array_reverse($this->homeProviders); // call the latest registered provider first to give apps an opportunity to overwrite builtin foreach ($providers as $homeProvider) { if ($mount = $homeProvider->getHomeMountForUser($user, $this->loader)) { @@ -159,34 +148,36 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { /** * Add a provider for mount points - * - * @param \OCP\Files\Config\IMountProvider $provider */ - public function registerProvider(IMountProvider $provider) { + public function registerProvider(IMountProvider $provider): void { $this->providers[] = $provider; $this->emit('\OC\Files\Config', 'registerMountProvider', [$provider]); } - public function registerMountFilter(callable $filter) { + public function registerMountFilter(callable $filter): void { $this->mountFilters[] = $filter; } - private function filterMounts(IUser $user, array $mountPoints) { - return array_filter($mountPoints, function (IMountPoint $mountPoint) use ($user) { + /** + * @param list<IMountPoint> $mountPoints + * @return list<IMountPoint> + */ + private function filterMounts(IUser $user, array $mountPoints): array { + return array_values(array_filter($mountPoints, function (IMountPoint $mountPoint) use ($user) { foreach ($this->mountFilters as $filter) { if ($filter($mountPoint, $user) === false) { return false; } } return true; - }); + })); } /** * Add a provider for home mount points * - * @param \OCP\Files\Config\IHomeMountProvider $provider + * @param IHomeMountProvider $provider * @since 9.1.0 */ public function registerHomeProvider(IHomeMountProvider $provider) { @@ -196,21 +187,19 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { /** * Get the mount cache which can be used to search for mounts without setting up the filesystem - * - * @return IUserMountCache */ - public function getMountCache() { + public function getMountCache(): IUserMountCache { return $this->mountCache; } - public function registerRootProvider(IRootMountProvider $provider) { + public function registerRootProvider(IRootMountProvider $provider): void { $this->rootProviders[] = $provider; } /** * Get all root mountpoints * - * @return \OCP\Files\Mount\IMountPoint[] + * @return list<IMountPoint> * @since 20.0.0 */ public function getRootMounts(): array { @@ -226,16 +215,33 @@ class MountProviderCollection implements IMountProviderCollection, Emitter { throw new \Exception('No root mounts provided by any provider'); } - return $mounts; + return array_values($mounts); } - public function clearProviders() { + public function clearProviders(): void { $this->providers = []; $this->homeProviders = []; $this->rootProviders = []; } + /** + * @return list<IMountProvider> + */ public function getProviders(): array { return $this->providers; } + + /** + * @return list<IHomeMountProvider> + */ + public function getHomeProviders(): array { + return $this->homeProviders; + } + + /** + * @return list<IRootMountProvider> + */ + public function getRootProviders(): array { + return $this->rootProviders; + } } diff --git a/lib/private/Files/Config/UserMountCache.php b/lib/private/Files/Config/UserMountCache.php index 7d9ecc16f76..3e53a67a044 100644 --- a/lib/private/Files/Config/UserMountCache.php +++ b/lib/private/Files/Config/UserMountCache.php @@ -11,6 +11,10 @@ use OC\User\LazyUser; use OCP\Cache\CappedMemoryCache; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\Diagnostics\IEventLogger; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\Config\Event\UserMountAddedEvent; +use OCP\Files\Config\Event\UserMountRemovedEvent; +use OCP\Files\Config\Event\UserMountUpdatedEvent; use OCP\Files\Config\ICachedMountFileInfo; use OCP\Files\Config\ICachedMountInfo; use OCP\Files\Config\IUserMountCache; @@ -46,6 +50,7 @@ class UserMountCache implements IUserMountCache { private IUserManager $userManager, private LoggerInterface $logger, private IEventLogger $eventLogger, + private IEventDispatcher $eventDispatcher, ) { $this->cacheInfoCache = new CappedMemoryCache(); $this->internalPathCache = new CappedMemoryCache(); @@ -98,24 +103,39 @@ class UserMountCache implements IUserMountCache { $userUID = $user->getUID(); try { foreach ($addedMounts as $mount) { + $this->logger->debug("Adding mount '{$mount->getKey()}' for user '$userUID'", ['app' => 'files', 'mount_provider' => $mount->getMountProvider()]); $this->addToCache($mount); /** @psalm-suppress InvalidArgument */ $this->mountsForUsers[$userUID][$mount->getKey()] = $mount; } foreach ($removedMounts as $mount) { + $this->logger->debug("Removing mount '{$mount->getKey()}' for user '$userUID'", ['app' => 'files', 'mount_provider' => $mount->getMountProvider()]); $this->removeFromCache($mount); unset($this->mountsForUsers[$userUID][$mount->getKey()]); } - foreach ($changedMounts as $mount) { - $this->updateCachedMount($mount); + foreach ($changedMounts as $mountPair) { + $newMount = $mountPair[1]; + $this->logger->debug("Updating mount '{$newMount->getKey()}' for user '$userUID'", ['app' => 'files', 'mount_provider' => $newMount->getMountProvider()]); + $this->updateCachedMount($newMount); /** @psalm-suppress InvalidArgument */ - $this->mountsForUsers[$userUID][$mount->getKey()] = $mount; + $this->mountsForUsers[$userUID][$newMount->getKey()] = $newMount; } $this->connection->commit(); } catch (\Throwable $e) { $this->connection->rollBack(); throw $e; } + + // Only fire events after all mounts have already been adjusted in the database. + foreach ($addedMounts as $mount) { + $this->eventDispatcher->dispatchTyped(new UserMountAddedEvent($mount)); + } + foreach ($removedMounts as $mount) { + $this->eventDispatcher->dispatchTyped(new UserMountRemovedEvent($mount)); + } + foreach ($changedMounts as $mountPair) { + $this->eventDispatcher->dispatchTyped(new UserMountUpdatedEvent($mountPair[0], $mountPair[1])); + } } $this->eventLogger->end('fs:setup:user:register'); } @@ -123,19 +143,19 @@ class UserMountCache implements IUserMountCache { /** * @param array<string, ICachedMountInfo> $newMounts * @param array<string, ICachedMountInfo> $cachedMounts - * @return ICachedMountInfo[] + * @return list<list{0: ICachedMountInfo, 1: ICachedMountInfo}> Pairs of old and new mounts */ - private function findChangedMounts(array $newMounts, array $cachedMounts) { + private function findChangedMounts(array $newMounts, array $cachedMounts): array { $changed = []; foreach ($cachedMounts as $key => $cachedMount) { if (isset($newMounts[$key])) { $newMount = $newMounts[$key]; if ( - $newMount->getStorageId() !== $cachedMount->getStorageId() || - $newMount->getMountId() !== $cachedMount->getMountId() || - $newMount->getMountProvider() !== $cachedMount->getMountProvider() + $newMount->getStorageId() !== $cachedMount->getStorageId() + || $newMount->getMountId() !== $cachedMount->getMountId() + || $newMount->getMountProvider() !== $cachedMount->getMountProvider() ) { - $changed[] = $newMount; + $changed[] = [$cachedMount, $newMount]; } } } diff --git a/lib/private/Files/Conversion/ConversionManager.php b/lib/private/Files/Conversion/ConversionManager.php new file mode 100644 index 00000000000..2c98a4c6404 --- /dev/null +++ b/lib/private/Files/Conversion/ConversionManager.php @@ -0,0 +1,181 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Files\Conversion; + +use OC\AppFramework\Bootstrap\Coordinator; +use OC\ForbiddenException; +use OC\SystemConfig; +use OCP\Files\Conversion\IConversionManager; +use OCP\Files\Conversion\IConversionProvider; +use OCP\Files\File; +use OCP\Files\GenericFileException; +use OCP\Files\IRootFolder; +use OCP\IL10N; +use OCP\ITempManager; +use OCP\L10N\IFactory; +use OCP\PreConditionNotMetException; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; +use Psr\Log\LoggerInterface; +use RuntimeException; +use Throwable; + +class ConversionManager implements IConversionManager { + /** @var string[] */ + private array $preferredApps = [ + 'richdocuments', + ]; + + /** @var list<IConversionProvider> */ + private array $preferredProviders = []; + + /** @var list<IConversionProvider> */ + private array $providers = []; + + private IL10N $l10n; + public function __construct( + private Coordinator $coordinator, + private ContainerInterface $serverContainer, + private IRootFolder $rootFolder, + private ITempManager $tempManager, + private LoggerInterface $logger, + private SystemConfig $config, + IFactory $l10nFactory, + ) { + $this->l10n = $l10nFactory->get('files'); + } + + public function hasProviders(): bool { + $context = $this->coordinator->getRegistrationContext(); + return !empty($context->getFileConversionProviders()); + } + + public function getProviders(): array { + $providers = []; + foreach ($this->getRegisteredProviders() as $provider) { + $providers = array_merge($providers, $provider->getSupportedMimeTypes()); + } + return $providers; + } + + public function convert(File $file, string $targetMimeType, ?string $destination = null): string { + if (!$this->hasProviders()) { + throw new PreConditionNotMetException($this->l10n->t('No file conversion providers available')); + } + + // Operate in mebibytes + $fileSize = $file->getSize() / (1024 * 1024); + $threshold = $this->config->getValue('max_file_conversion_filesize', 100); + if ($fileSize > $threshold) { + throw new GenericFileException($this->l10n->t('File is too large to convert')); + } + + $fileMimeType = $file->getMimetype(); + $validProvider = $this->getValidProvider($fileMimeType, $targetMimeType); + + if ($validProvider !== null) { + // Get the target extension given by the provider + $targetExtension = ''; + foreach ($validProvider->getSupportedMimeTypes() as $mimeProvider) { + if ($mimeProvider->getTo() === $targetMimeType) { + $targetExtension = $mimeProvider->getExtension(); + break; + } + } + // If destination not provided, we use the same path + // as the original file, but with the new extension + if ($destination === null) { + $basename = pathinfo($file->getPath(), PATHINFO_FILENAME); + $parent = $file->getParent(); + $destination = $parent->getFullPath($basename . '.' . $targetExtension); + } + + // If destination doesn't match the target extension, we throw an error + if (pathinfo($destination, PATHINFO_EXTENSION) !== $targetExtension) { + throw new GenericFileException($this->l10n->t('Destination does not match conversion extension')); + } + + // Check destination before converting + $this->checkDestination($destination); + + // Convert the file and write it to the destination + $convertedFile = $validProvider->convertFile($file, $targetMimeType); + $convertedFile = $this->writeToDestination($destination, $convertedFile); + return $convertedFile->getPath(); + } + + throw new RuntimeException($this->l10n->t('Could not convert file')); + } + + /** + * @return list<IConversionProvider> + */ + private function getRegisteredProviders(): array { + $context = $this->coordinator->getRegistrationContext(); + foreach ($context->getFileConversionProviders() as $providerRegistration) { + $class = $providerRegistration->getService(); + $appId = $providerRegistration->getAppId(); + + try { + if (in_array($appId, $this->preferredApps)) { + $this->preferredProviders[$class] = $this->serverContainer->get($class); + continue; + } + + $this->providers[$class] = $this->serverContainer->get($class); + } catch (NotFoundExceptionInterface|ContainerExceptionInterface|Throwable $e) { + $this->logger->error('Failed to load file conversion provider ' . $class, [ + 'exception' => $e, + ]); + } + } + + return array_values(array_merge([], $this->preferredProviders, $this->providers)); + } + + private function checkDestination(string $destination): void { + if (!$this->rootFolder->nodeExists(dirname($destination))) { + throw new ForbiddenException($this->l10n->t('Destination does not exist')); + } + + $folder = $this->rootFolder->get(dirname($destination)); + if (!$folder->isCreatable()) { + throw new ForbiddenException($this->l10n->t('Destination is not creatable')); + } + } + + private function writeToDestination(string $destination, mixed $content): File { + $this->checkDestination($destination); + + if ($this->rootFolder->nodeExists($destination)) { + $file = $this->rootFolder->get($destination); + $parent = $file->getParent(); + + // Folder permissions is already checked in checkDestination method + $newName = $parent->getNonExistingName(basename($destination)); + $destination = $parent->getFullPath($newName); + } + + return $this->rootFolder->newFile($destination, $content); + } + + private function getValidProvider(string $fileMimeType, string $targetMimeType): ?IConversionProvider { + foreach ($this->getRegisteredProviders() as $provider) { + foreach ($provider->getSupportedMimeTypes() as $mimeProvider) { + if ($mimeProvider->getFrom() === $fileMimeType && $mimeProvider->getTo() === $targetMimeType) { + return $provider; + } + } + } + + return null; + } +} diff --git a/lib/private/Files/FilenameValidator.php b/lib/private/Files/FilenameValidator.php index fde45068df7..a78c6d3cc3c 100644 --- a/lib/private/Files/FilenameValidator.php +++ b/lib/private/Files/FilenameValidator.php @@ -127,9 +127,6 @@ class FilenameValidator implements IFilenameValidator { if (empty($this->forbiddenCharacters)) { // Get always forbidden characters $forbiddenCharacters = str_split(\OCP\Constants::FILENAME_INVALID_CHARS); - if ($forbiddenCharacters === false) { - $forbiddenCharacters = []; - } // Get admin defined invalid characters $additionalChars = $this->config->getSystemValue('forbidden_filename_characters', []); @@ -231,7 +228,45 @@ class FilenameValidator implements IFilenameValidator { return false; } - protected function checkForbiddenName($filename): void { + public function sanitizeFilename(string $name, ?string $charReplacement = null): string { + $forbiddenCharacters = $this->getForbiddenCharacters(); + + if ($charReplacement === null) { + $charReplacement = array_diff(['_', '-', ' '], $forbiddenCharacters); + $charReplacement = reset($charReplacement) ?: ''; + } + if (mb_strlen($charReplacement) !== 1) { + throw new \InvalidArgumentException('No or invalid character replacement given'); + } + + $nameLowercase = mb_strtolower($name); + foreach ($this->getForbiddenExtensions() as $extension) { + if (str_ends_with($nameLowercase, $extension)) { + $name = substr($name, 0, strlen($name) - strlen($extension)); + } + } + + $basename = strlen($name) > 1 + ? substr($name, 0, strpos($name, '.', 1) ?: null) + : $name; + if (in_array(mb_strtolower($basename), $this->getForbiddenBasenames())) { + $name = str_replace($basename, $this->l10n->t('%1$s (renamed)', [$basename]), $name); + } + + if ($name === '') { + $name = $this->l10n->t('renamed file'); + } + + if (in_array(mb_strtolower($name), $this->getForbiddenFilenames())) { + $name = $this->l10n->t('%1$s (renamed)', [$name]); + } + + $name = str_replace($forbiddenCharacters, $charReplacement, $name); + return $name; + } + + protected function checkForbiddenName(string $filename): void { + $filename = mb_strtolower($filename); if ($this->isForbidden($filename)) { throw new ReservedWordException($this->l10n->t('"%1$s" is a forbidden file or folder name.', [$filename])); } @@ -295,6 +330,6 @@ class FilenameValidator implements IFilenameValidator { $values = $fallback; } - return array_map('mb_strtolower', $values); + return array_map(mb_strtolower(...), $values); } }; diff --git a/lib/private/Files/Mount/MountPoint.php b/lib/private/Files/Mount/MountPoint.php index 7a5a87be35b..bab2dc8e4bd 100644 --- a/lib/private/Files/Mount/MountPoint.php +++ b/lib/private/Files/Mount/MountPoint.php @@ -198,7 +198,7 @@ class MountPoint implements IMountPoint { if (is_null($storage)) { return -1; } - $this->numericStorageId = $storage->getStorageCache()->getNumericId(); + $this->numericStorageId = $storage->getCache()->getNumericStorageId(); } return $this->numericStorageId; } diff --git a/lib/private/Files/Mount/ObjectHomeMountProvider.php b/lib/private/Files/Mount/ObjectHomeMountProvider.php index 99c52108fa8..4b088f2c808 100644 --- a/lib/private/Files/Mount/ObjectHomeMountProvider.php +++ b/lib/private/Files/Mount/ObjectHomeMountProvider.php @@ -7,117 +7,39 @@ */ namespace OC\Files\Mount; +use OC\Files\ObjectStore\HomeObjectStoreStorage; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OCP\Files\Config\IHomeMountProvider; +use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage\IStorageFactory; -use OCP\IConfig; use OCP\IUser; -use Psr\Log\LoggerInterface; /** * Mount provider for object store home storages */ class ObjectHomeMountProvider implements IHomeMountProvider { - /** - * @var IConfig - */ - private $config; - - /** - * ObjectStoreHomeMountProvider constructor. - * - * @param IConfig $config - */ - public function __construct(IConfig $config) { - $this->config = $config; + public function __construct( + private PrimaryObjectStoreConfig $objectStoreConfig, + ) { } /** - * Get the cache mount for a user + * Get the home mount for a user * * @param IUser $user * @param IStorageFactory $loader - * @return \OCP\Files\Mount\IMountPoint + * @return ?IMountPoint */ - public function getHomeMountForUser(IUser $user, IStorageFactory $loader) { - $config = $this->getMultiBucketObjectStoreConfig($user); - if ($config === null) { - $config = $this->getSingleBucketObjectStoreConfig($user); - } - - if ($config === null) { + public function getHomeMountForUser(IUser $user, IStorageFactory $loader): ?IMountPoint { + $objectStoreConfig = $this->objectStoreConfig->getObjectStoreConfigForUser($user); + if ($objectStoreConfig === null) { return null; } + $arguments = array_merge($objectStoreConfig['arguments'], [ + 'objectstore' => $this->objectStoreConfig->buildObjectStore($objectStoreConfig), + 'user' => $user, + ]); - return new HomeMountPoint($user, '\OC\Files\ObjectStore\HomeObjectStoreStorage', '/' . $user->getUID(), $config['arguments'], $loader, null, null, self::class); - } - - /** - * @param IUser $user - * @return array|null - */ - private function getSingleBucketObjectStoreConfig(IUser $user) { - $config = $this->config->getSystemValue('objectstore'); - if (!is_array($config)) { - return null; - } - - // sanity checks - if (empty($config['class'])) { - \OC::$server->get(LoggerInterface::class)->error('No class given for objectstore', ['app' => 'files']); - } - if (!isset($config['arguments'])) { - $config['arguments'] = []; - } - // instantiate object store implementation - $config['arguments']['objectstore'] = new $config['class']($config['arguments']); - - $config['arguments']['user'] = $user; - - return $config; - } - - /** - * @param IUser $user - * @return array|null - */ - private function getMultiBucketObjectStoreConfig(IUser $user) { - $config = $this->config->getSystemValue('objectstore_multibucket'); - if (!is_array($config)) { - return null; - } - - // sanity checks - if (empty($config['class'])) { - \OC::$server->get(LoggerInterface::class)->error('No class given for objectstore', ['app' => 'files']); - } - if (!isset($config['arguments'])) { - $config['arguments'] = []; - } - - $bucket = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null); - - if ($bucket === null) { - /* - * Use any provided bucket argument as prefix - * and add the mapping from username => bucket - */ - if (!isset($config['arguments']['bucket'])) { - $config['arguments']['bucket'] = ''; - } - $mapper = new \OC\Files\ObjectStore\Mapper($user, $this->config); - $numBuckets = $config['arguments']['num_buckets'] ?? 64; - $config['arguments']['bucket'] .= $mapper->getBucket($numBuckets); - - $this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $config['arguments']['bucket']); - } else { - $config['arguments']['bucket'] = $bucket; - } - - // instantiate object store implementation - $config['arguments']['objectstore'] = new $config['class']($config['arguments']); - - $config['arguments']['user'] = $user; - - return $config; + return new HomeMountPoint($user, HomeObjectStoreStorage::class, '/' . $user->getUID(), $arguments, $loader, null, null, self::class); } } diff --git a/lib/private/Files/Mount/RootMountProvider.php b/lib/private/Files/Mount/RootMountProvider.php index 86f8188978f..5e0c924ad38 100644 --- a/lib/private/Files/Mount/RootMountProvider.php +++ b/lib/private/Files/Mount/RootMountProvider.php @@ -10,79 +10,41 @@ namespace OC\Files\Mount; use OC; use OC\Files\ObjectStore\ObjectStoreStorage; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OC\Files\Storage\LocalRootStorage; -use OC_App; use OCP\Files\Config\IRootMountProvider; use OCP\Files\Storage\IStorageFactory; use OCP\IConfig; -use Psr\Log\LoggerInterface; class RootMountProvider implements IRootMountProvider { + private PrimaryObjectStoreConfig $objectStoreConfig; private IConfig $config; - private LoggerInterface $logger; - public function __construct(IConfig $config, LoggerInterface $logger) { + public function __construct(PrimaryObjectStoreConfig $objectStoreConfig, IConfig $config) { + $this->objectStoreConfig = $objectStoreConfig; $this->config = $config; - $this->logger = $logger; } public function getRootMounts(IStorageFactory $loader): array { - $objectStore = $this->config->getSystemValue('objectstore', null); - $objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null); + $objectStoreConfig = $this->objectStoreConfig->getObjectStoreConfigForRoot(); - if ($objectStoreMultiBucket) { - return [$this->getMultiBucketStoreRootMount($loader, $objectStoreMultiBucket)]; - } elseif ($objectStore) { - return [$this->getObjectStoreRootMount($loader, $objectStore)]; + if ($objectStoreConfig) { + return [$this->getObjectStoreRootMount($loader, $objectStoreConfig)]; } else { return [$this->getLocalRootMount($loader)]; } } - private function validateObjectStoreConfig(array &$config) { - if (empty($config['class'])) { - $this->logger->error('No class given for objectstore', ['app' => 'files']); - } - if (!isset($config['arguments'])) { - $config['arguments'] = []; - } - - // instantiate object store implementation - $name = $config['class']; - if (str_starts_with($name, 'OCA\\') && substr_count($name, '\\') >= 2) { - $segments = explode('\\', $name); - OC_App::loadApp(strtolower($segments[1])); - } - } - private function getLocalRootMount(IStorageFactory $loader): MountPoint { $configDataDirectory = $this->config->getSystemValue('datadirectory', OC::$SERVERROOT . '/data'); return new MountPoint(LocalRootStorage::class, '/', ['datadir' => $configDataDirectory], $loader, null, null, self::class); } - private function getObjectStoreRootMount(IStorageFactory $loader, array $config): MountPoint { - $this->validateObjectStoreConfig($config); - - $config['arguments']['objectstore'] = new $config['class']($config['arguments']); - // mount with plain / root object store implementation - $config['class'] = ObjectStoreStorage::class; - - return new MountPoint($config['class'], '/', $config['arguments'], $loader, null, null, self::class); - } - - private function getMultiBucketStoreRootMount(IStorageFactory $loader, array $config): MountPoint { - $this->validateObjectStoreConfig($config); - - if (!isset($config['arguments']['bucket'])) { - $config['arguments']['bucket'] = ''; - } - // put the root FS always in first bucket for multibucket configuration - $config['arguments']['bucket'] .= '0'; - - $config['arguments']['objectstore'] = new $config['class']($config['arguments']); - // mount with plain / root object store implementation - $config['class'] = ObjectStoreStorage::class; + private function getObjectStoreRootMount(IStorageFactory $loader, array $objectStoreConfig): MountPoint { + $arguments = array_merge($objectStoreConfig['arguments'], [ + 'objectstore' => $this->objectStoreConfig->buildObjectStore($objectStoreConfig), + ]); - return new MountPoint($config['class'], '/', $config['arguments'], $loader, null, null, self::class); + return new MountPoint(ObjectStoreStorage::class, '/', $arguments, $loader, null, null, self::class); } } diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php index a894c69649a..7453b553119 100644 --- a/lib/private/Files/Node/Folder.php +++ b/lib/private/Files/Node/Folder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -126,8 +127,21 @@ class Folder extends Node implements \OCP\Files\Folder { $fullPath = $this->getFullPath($path); $nonExisting = new NonExistingFolder($this->root, $this->view, $fullPath); $this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]); - if (!$this->view->mkdir($fullPath) && !$this->view->is_dir($fullPath)) { - throw new NotPermittedException('Could not create folder "' . $fullPath . '"'); + if (!$this->view->mkdir($fullPath)) { + // maybe another concurrent process created the folder already + if (!$this->view->is_dir($fullPath)) { + throw new NotPermittedException('Could not create folder "' . $fullPath . '"'); + } else { + // we need to ensure we don't return before the concurrent request has finished updating the cache + $tries = 5; + while (!$this->view->getFileInfo($fullPath)) { + if ($tries < 1) { + throw new NotPermittedException('Could not create folder "' . $fullPath . '", folder exists but unable to get cache entry'); + } + usleep(5 * 1000); + $tries--; + } + } } $parent = dirname($fullPath) === $this->getPath() ? $this : null; $node = new Folder($this->root, $this->view, $fullPath, null, $parent); @@ -447,4 +461,12 @@ class Folder extends Node implements \OCP\Files\Folder { return $this->search($query); } + + public function verifyPath($fileName, $readonly = false): void { + $this->view->verifyPath( + $this->getPath(), + $fileName, + $readonly, + ); + } } diff --git a/lib/private/Files/Node/LazyFolder.php b/lib/private/Files/Node/LazyFolder.php index 5879748d951..37b1efa0fad 100644 --- a/lib/private/Files/Node/LazyFolder.php +++ b/lib/private/Files/Node/LazyFolder.php @@ -561,4 +561,8 @@ class LazyFolder implements Folder { public function getMetadata(): array { return $this->data['metadata'] ?? $this->__call(__FUNCTION__, func_get_args()); } + + public function verifyPath($fileName, $readonly = false): void { + $this->__call(__FUNCTION__, func_get_args()); + } } diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index 1686051131d..d82ec08f362 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -384,13 +384,17 @@ class Root extends Folder implements IRootFolder { // scope the cache by user, so we don't return nodes for different users if ($this->user) { $cachedPath = $this->pathByIdCache->get($this->user->getUID() . '::' . $id); - if ($cachedPath && str_starts_with($path, $cachedPath)) { + if ($cachedPath && str_starts_with($cachedPath, $path)) { // getting the node by path is significantly cheaper than finding it by id - $node = $this->get($cachedPath); - // by validating that the cached path still has the requested fileid we can work around the need to invalidate the cached path - // if the cached path is invalid or a different file now we fall back to the uncached logic - if ($node && $node->getId() === $id) { - return $node; + try { + $node = $this->get($cachedPath); + // by validating that the cached path still has the requested fileid we can work around the need to invalidate the cached path + // if the cached path is invalid or a different file now we fall back to the uncached logic + if ($node && $node->getId() === $id) { + return $node; + } + } catch (NotFoundException|NotPermittedException) { + // The file may be moved but the old path still in cache } } } @@ -522,9 +526,9 @@ class Root extends Folder implements IRootFolder { $isDir = $info->getType() === FileInfo::TYPE_FOLDER; $view = new View(''); if ($isDir) { - return new Folder($this, $view, $path, $info, $parent); + return new Folder($this, $view, $fullPath, $info, $parent); } else { - return new File($this, $view, $path, $info, $parent); + return new File($this, $view, $fullPath, $info, $parent); } } } diff --git a/lib/private/Files/Notify/Change.php b/lib/private/Files/Notify/Change.php index d2448e5deec..c8eccd11ae2 100644 --- a/lib/private/Files/Notify/Change.php +++ b/lib/private/Files/Notify/Change.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Notify/RenameChange.php b/lib/private/Files/Notify/RenameChange.php index 98fd7099a58..28554ceaa26 100644 --- a/lib/private/Files/Notify/RenameChange.php +++ b/lib/private/Files/Notify/RenameChange.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/ObjectStore/Azure.php b/lib/private/Files/ObjectStore/Azure.php index 575cc336ba8..2729bb3c037 100644 --- a/lib/private/Files/ObjectStore/Azure.php +++ b/lib/private/Files/ObjectStore/Azure.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/ObjectStore/ObjectStoreScanner.php b/lib/private/Files/ObjectStore/ObjectStoreScanner.php index d8a77d36dee..5c3992b8458 100644 --- a/lib/private/Files/ObjectStore/ObjectStoreScanner.php +++ b/lib/private/Files/ObjectStore/ObjectStoreScanner.php @@ -13,11 +13,11 @@ use OCP\Files\FileInfo; class ObjectStoreScanner extends Scanner { public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true, $data = null) { - return []; + return null; } public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true) { - return []; + return null; } protected function scanChildren(string $path, $recursive, int $reuse, int $folderId, bool $lock, int|float $oldSize, &$etagChanged = false) { @@ -61,7 +61,7 @@ class ObjectStoreScanner extends Scanner { $query->select('path') ->from('filecache') ->where($query->expr()->eq('storage', $query->createNamedParameter($this->cache->getNumericStorageId(), IQueryBuilder::PARAM_INT))) - ->andWhere($query->expr()->lt('size', $query->createNamedParameter(0, IQueryBuilder::PARAM_INT))) + ->andWhere($query->expr()->eq('size', $query->createNamedParameter(-1, IQueryBuilder::PARAM_INT))) ->orderBy('path', 'DESC') ->setMaxResults(1); diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php index e05de7cd91d..10ee6aec167 100644 --- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php +++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php @@ -22,6 +22,7 @@ use OCP\Files\FileInfo; use OCP\Files\GenericFileException; use OCP\Files\NotFoundException; use OCP\Files\ObjectStore\IObjectStore; +use OCP\Files\ObjectStore\IObjectStoreMetaData; use OCP\Files\ObjectStore\IObjectStoreMultiPartUpload; use OCP\Files\Storage\IChunkedFileWrite; use OCP\Files\Storage\IStorage; @@ -66,7 +67,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil $this->logger = \OCP\Server::get(LoggerInterface::class); } - public function mkdir(string $path, bool $force = false): bool { + public function mkdir(string $path, bool $force = false, array $metadata = []): bool { $path = $this->normalizePath($path); if (!$force && $this->file_exists($path)) { $this->logger->warning("Tried to create an object store folder that already exists: $path"); @@ -76,7 +77,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil $mTime = time(); $data = [ 'mimetype' => 'httpd/unix-directory', - 'size' => 0, + 'size' => $metadata['size'] ?? 0, 'mtime' => $mTime, 'storage_mtime' => $mTime, 'permissions' => \OCP\Constants::PERMISSION_ALL, @@ -412,16 +413,6 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil //create a empty file, need to have at least on char to make it // work with all object storage implementations $this->file_put_contents($path, ' '); - $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path); - $stat = [ - 'etag' => $this->getETag($path), - 'mimetype' => $mimeType, - 'size' => 0, - 'mtime' => $mtime, - 'storage_mtime' => $mtime, - 'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE, - ]; - $this->getCache()->put($path, $stat); } catch (\Exception $ex) { $this->logger->error( 'Could not create object for ' . $path, @@ -479,6 +470,11 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil $mimetypeDetector = \OC::$server->getMimeTypeDetector(); $mimetype = $mimetypeDetector->detectPath($path); + $metadata = [ + 'mimetype' => $mimetype, + 'original-storage' => $this->getId(), + 'original-path' => $path, + ]; $stat['mimetype'] = $mimetype; $stat['etag'] = $this->getETag($path); @@ -507,13 +503,21 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil ]); $size = $writtenSize; }); - $this->objectStore->writeObject($urn, $countStream, $mimetype); + if ($this->objectStore instanceof IObjectStoreMetaData) { + $this->objectStore->writeObjectWithMetaData($urn, $countStream, $metadata); + } else { + $this->objectStore->writeObject($urn, $countStream, $metadata['mimetype']); + } if (is_resource($countStream)) { fclose($countStream); } $stat['size'] = $size; } else { - $this->objectStore->writeObject($urn, $stream, $mimetype); + if ($this->objectStore instanceof IObjectStoreMetaData) { + $this->objectStore->writeObjectWithMetaData($urn, $stream, $metadata); + } else { + $this->objectStore->writeObject($urn, $stream, $metadata['mimetype']); + } if (is_resource($stream)) { fclose($stream); } @@ -592,7 +596,14 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath, ?ICacheEntry $sourceCacheEntry = null): bool { $sourceCache = $sourceStorage->getCache(); - if ($sourceStorage->instanceOfStorage(ObjectStoreStorage::class) && $sourceStorage->getObjectStore()->getStorageId() === $this->getObjectStore()->getStorageId()) { + if ( + $sourceStorage->instanceOfStorage(ObjectStoreStorage::class) + && $sourceStorage->getObjectStore()->getStorageId() === $this->getObjectStore()->getStorageId() + ) { + if ($this->getCache()->get($targetInternalPath)) { + $this->unlink($targetInternalPath); + $this->getCache()->remove($targetInternalPath); + } $this->getCache()->moveFromCache($sourceCache, $sourceInternalPath, $targetInternalPath); // Do not import any data when source and target bucket are identical. return true; @@ -615,6 +626,10 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil /** @var ObjectStoreStorage $sourceStorage */ $sourceStorage->setPreserveCacheOnDelete(false); } + if ($this->getCache()->get($targetInternalPath)) { + $this->unlink($targetInternalPath); + $this->getCache()->remove($targetInternalPath); + } $this->getCache()->moveFromCache($sourceCache, $sourceInternalPath, $targetInternalPath); return true; @@ -684,7 +699,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common implements IChunkedFil if ($cache->inCache($to)) { $cache->remove($to); } - $this->mkdir($to); + $this->mkdir($to, false, ['size' => $sourceEntry->getSize()]); foreach ($sourceCache->getFolderContentsById($sourceEntry->getId()) as $child) { $this->copyInner($sourceCache, $child, $to . '/' . $child->getName()); diff --git a/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php b/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php new file mode 100644 index 00000000000..fdfe989addc --- /dev/null +++ b/lib/private/Files/ObjectStore/PrimaryObjectStoreConfig.php @@ -0,0 +1,140 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace OC\Files\ObjectStore; + +use OCP\App\IAppManager; +use OCP\Files\ObjectStore\IObjectStore; +use OCP\IConfig; +use OCP\IUser; + +/** + * @psalm-type ObjectStoreConfig array{class: class-string<IObjectStore>, arguments: array{multibucket: bool, ...}} + */ +class PrimaryObjectStoreConfig { + public function __construct( + private readonly IConfig $config, + private readonly IAppManager $appManager, + ) { + } + + /** + * @param ObjectStoreConfig $config + */ + public function buildObjectStore(array $config): IObjectStore { + return new $config['class']($config['arguments']); + } + + /** + * @return ?ObjectStoreConfig + */ + public function getObjectStoreConfigForRoot(): ?array { + $config = $this->getObjectStoreConfig(); + + if ($config && $config['arguments']['multibucket']) { + if (!isset($config['arguments']['bucket'])) { + $config['arguments']['bucket'] = ''; + } + + // put the root FS always in first bucket for multibucket configuration + $config['arguments']['bucket'] .= '0'; + } + return $config; + } + + /** + * @return ?ObjectStoreConfig + */ + public function getObjectStoreConfigForUser(IUser $user): ?array { + $config = $this->getObjectStoreConfig(); + + if ($config && $config['arguments']['multibucket']) { + $config['arguments']['bucket'] = $this->getBucketForUser($user, $config); + } + return $config; + } + + /** + * @return ?ObjectStoreConfig + */ + private function getObjectStoreConfig(): ?array { + $objectStore = $this->config->getSystemValue('objectstore', null); + $objectStoreMultiBucket = $this->config->getSystemValue('objectstore_multibucket', null); + + // new-style multibucket config uses the same 'objectstore' key but sets `'multibucket' => true`, transparently upgrade older style config + if ($objectStoreMultiBucket) { + $objectStoreMultiBucket['arguments']['multibucket'] = true; + return $this->validateObjectStoreConfig($objectStoreMultiBucket); + } elseif ($objectStore) { + return $this->validateObjectStoreConfig($objectStore); + } else { + return null; + } + } + + /** + * @return ObjectStoreConfig + */ + private function validateObjectStoreConfig(array $config) { + if (!isset($config['class'])) { + throw new \Exception('No class configured for object store'); + } + if (!isset($config['arguments'])) { + $config['arguments'] = []; + } + $class = $config['class']; + $arguments = $config['arguments']; + if (!is_array($arguments)) { + throw new \Exception('Configured object store arguments are not an array'); + } + if (!isset($arguments['multibucket'])) { + $arguments['multibucket'] = false; + } + if (!is_bool($arguments['multibucket'])) { + throw new \Exception('arguments.multibucket must be a boolean in object store configuration'); + } + + if (!is_string($class)) { + throw new \Exception('Configured class for object store is not a string'); + } + + if (str_starts_with($class, 'OCA\\') && substr_count($class, '\\') >= 2) { + [$appId] = explode('\\', $class); + $this->appManager->loadApp(strtolower($appId)); + } + + if (!is_a($class, IObjectStore::class, true)) { + throw new \Exception('Configured class for object store is not an object store'); + } + return [ + 'class' => $class, + 'arguments' => $arguments, + ]; + } + + private function getBucketForUser(IUser $user, array $config): string { + $bucket = $this->config->getUserValue($user->getUID(), 'homeobjectstore', 'bucket', null); + + if ($bucket === null) { + /* + * Use any provided bucket argument as prefix + * and add the mapping from username => bucket + */ + if (!isset($config['arguments']['bucket'])) { + $config['arguments']['bucket'] = ''; + } + $mapper = new Mapper($user, $this->config); + $numBuckets = isset($config['arguments']['num_buckets']) ? $config['arguments']['num_buckets'] : 64; + $bucket = $config['arguments']['bucket'] . $mapper->getBucket($numBuckets); + + $this->config->setUserValue($user->getUID(), 'homeobjectstore', 'bucket', $bucket); + } + + return $bucket; + } +} diff --git a/lib/private/Files/ObjectStore/S3.php b/lib/private/Files/ObjectStore/S3.php index 41ab75caf45..72e1751e23d 100644 --- a/lib/private/Files/ObjectStore/S3.php +++ b/lib/private/Files/ObjectStore/S3.php @@ -1,16 +1,19 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + namespace OC\Files\ObjectStore; use Aws\Result; use Exception; use OCP\Files\ObjectStore\IObjectStore; +use OCP\Files\ObjectStore\IObjectStoreMetaData; use OCP\Files\ObjectStore\IObjectStoreMultiPartUpload; -class S3 implements IObjectStore, IObjectStoreMultiPartUpload { +class S3 implements IObjectStore, IObjectStoreMultiPartUpload, IObjectStoreMetaData { use S3ConnectionTrait; use S3ObjectTrait; @@ -61,7 +64,7 @@ class S3 implements IObjectStore, IObjectStoreMultiPartUpload { 'Key' => $urn, 'UploadId' => $uploadId, 'MaxParts' => 1000, - 'PartNumberMarker' => $partNumberMarker + 'PartNumberMarker' => $partNumberMarker, ] + $this->getSSECParameters()); $parts = array_merge($parts, $result->get('Parts') ?? []); $isTruncated = $result->get('IsTruncated'); @@ -89,7 +92,51 @@ class S3 implements IObjectStore, IObjectStoreMultiPartUpload { $this->getConnection()->abortMultipartUpload([ 'Bucket' => $this->bucket, 'Key' => $urn, - 'UploadId' => $uploadId + 'UploadId' => $uploadId, ]); } + + private function parseS3Metadata(array $metadata): array { + $result = []; + foreach ($metadata as $key => $value) { + if (str_starts_with($key, 'x-amz-meta-')) { + $result[substr($key, strlen('x-amz-meta-'))] = $value; + } + } + return $result; + } + + public function getObjectMetaData(string $urn): array { + $object = $this->getConnection()->headObject([ + 'Bucket' => $this->bucket, + 'Key' => $urn + ] + $this->getSSECParameters())->toArray(); + return [ + 'mtime' => $object['LastModified'], + 'etag' => trim($object['ETag'], '"'), + 'size' => (int)($object['Size'] ?? $object['ContentLength']), + ] + $this->parseS3Metadata($object['Metadata'] ?? []); + } + + public function listObjects(string $prefix = ''): \Iterator { + $results = $this->getConnection()->getPaginator('ListObjectsV2', [ + 'Bucket' => $this->bucket, + 'Prefix' => $prefix, + ] + $this->getSSECParameters()); + + foreach ($results as $result) { + if (is_array($result['Contents'])) { + foreach ($result['Contents'] as $object) { + yield [ + 'urn' => basename($object['Key']), + 'metadata' => [ + 'mtime' => $object['LastModified'], + 'etag' => trim($object['ETag'], '"'), + 'size' => (int)($object['Size'] ?? $object['ContentLength']), + ], + ]; + } + } + } + } } diff --git a/lib/private/Files/ObjectStore/S3ConfigTrait.php b/lib/private/Files/ObjectStore/S3ConfigTrait.php index 63f14ac2d00..5b086db8f77 100644 --- a/lib/private/Files/ObjectStore/S3ConfigTrait.php +++ b/lib/private/Files/ObjectStore/S3ConfigTrait.php @@ -18,6 +18,10 @@ trait S3ConfigTrait { /** Maximum number of concurrent multipart uploads */ protected int $concurrency; + /** Timeout, in seconds, for the connection to S3 server, not for the + * request. */ + protected float $connectTimeout; + protected int $timeout; protected string|false $proxy; diff --git a/lib/private/Files/ObjectStore/S3ConnectionTrait.php b/lib/private/Files/ObjectStore/S3ConnectionTrait.php index cce8752c360..67b82a44ab7 100644 --- a/lib/private/Files/ObjectStore/S3ConnectionTrait.php +++ b/lib/private/Files/ObjectStore/S3ConnectionTrait.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -39,6 +40,7 @@ trait S3ConnectionTrait { // Default to 5 like the S3 SDK does $this->concurrency = $params['concurrency'] ?? 5; $this->proxy = $params['proxy'] ?? false; + $this->connectTimeout = $params['connect_timeout'] ?? 5; $this->timeout = $params['timeout'] ?? 15; $this->storageClass = !empty($params['storageClass']) ? $params['storageClass'] : 'STANDARD'; $this->uploadPartSize = $params['uploadPartSize'] ?? 524288000; @@ -102,10 +104,13 @@ trait S3ConnectionTrait { 'use_arn_region' => false, 'http' => [ 'verify' => $this->getCertificateBundlePath(), - // Timeout for the connection to S3 server, not for the request. - 'connect_timeout' => 5 + 'connect_timeout' => $this->connectTimeout, ], 'use_aws_shared_config_files' => false, + 'retries' => [ + 'mode' => 'standard', + 'max_attempts' => 5, + ], ]; if ($this->params['s3-accelerate']) { @@ -128,7 +133,7 @@ trait S3ConnectionTrait { $logger->debug('Bucket "' . $this->bucket . '" This bucket name is not dns compatible, it may contain invalid characters.', ['app' => 'objectstore']); } - + if ($this->params['verify_bucket_exists'] && !$this->connection->doesBucketExist($this->bucket)) { try { $logger->info('Bucket "' . $this->bucket . '" does not exist - creating it.', ['app' => 'objectstore']); @@ -185,10 +190,12 @@ trait S3ConnectionTrait { return function () { $key = empty($this->params['key']) ? null : $this->params['key']; $secret = empty($this->params['secret']) ? null : $this->params['secret']; + $sessionToken = empty($this->params['session_token']) ? null : $this->params['session_token']; if ($key && $secret) { return Create::promiseFor( - new Credentials($key, $secret) + // a null sessionToken match the default signature of the constructor + new Credentials($key, $secret, $sessionToken) ); } @@ -213,7 +220,7 @@ trait S3ConnectionTrait { } protected function getSSECKey(): ?string { - if (isset($this->params['sse_c_key'])) { + if (isset($this->params['sse_c_key']) && !empty($this->params['sse_c_key'])) { return $this->params['sse_c_key']; } diff --git a/lib/private/Files/ObjectStore/S3ObjectTrait.php b/lib/private/Files/ObjectStore/S3ObjectTrait.php index 9d7cfa644e6..5e6dcf88a42 100644 --- a/lib/private/Files/ObjectStore/S3ObjectTrait.php +++ b/lib/private/Files/ObjectStore/S3ObjectTrait.php @@ -77,22 +77,32 @@ trait S3ObjectTrait { return $fh; } + private function buildS3Metadata(array $metadata): array { + $result = []; + foreach ($metadata as $key => $value) { + $result['x-amz-meta-' . $key] = $value; + } + return $result; + } /** * Single object put helper * * @param string $urn the unified resource name used to identify the object * @param StreamInterface $stream stream with the data to write - * @param string|null $mimetype the mimetype to set for the remove object @since 22.0.0 + * @param array $metaData the metadata to set for the object * @throws \Exception when something goes wrong, message will be logged */ - protected function writeSingle(string $urn, StreamInterface $stream, ?string $mimetype = null): void { + protected function writeSingle(string $urn, StreamInterface $stream, array $metaData): void { + $mimetype = $metaData['mimetype'] ?? null; + unset($metaData['mimetype']); $this->getConnection()->putObject([ 'Bucket' => $this->bucket, 'Key' => $urn, 'Body' => $stream, 'ACL' => 'private', 'ContentType' => $mimetype, + 'Metadata' => $this->buildS3Metadata($metaData), 'StorageClass' => $this->storageClass, ] + $this->getSSECParameters()); } @@ -103,43 +113,72 @@ trait S3ObjectTrait { * * @param string $urn the unified resource name used to identify the object * @param StreamInterface $stream stream with the data to write - * @param string|null $mimetype the mimetype to set for the remove object + * @param array $metaData the metadata to set for the object * @throws \Exception when something goes wrong, message will be logged */ - protected function writeMultiPart(string $urn, StreamInterface $stream, ?string $mimetype = null): void { - $uploader = new MultipartUploader($this->getConnection(), $stream, [ - 'bucket' => $this->bucket, - 'concurrency' => $this->concurrency, - 'key' => $urn, - 'part_size' => $this->uploadPartSize, - 'params' => [ - 'ContentType' => $mimetype, - 'StorageClass' => $this->storageClass, - ] + $this->getSSECParameters(), - ]); + protected function writeMultiPart(string $urn, StreamInterface $stream, array $metaData): void { + $mimetype = $metaData['mimetype'] ?? null; + unset($metaData['mimetype']); + + $attempts = 0; + $uploaded = false; + $concurrency = $this->concurrency; + $exception = null; + $state = null; + + // retry multipart upload once with concurrency at half on failure + while (!$uploaded && $attempts <= 1) { + $uploader = new MultipartUploader($this->getConnection(), $stream, [ + 'bucket' => $this->bucket, + 'concurrency' => $concurrency, + 'key' => $urn, + 'part_size' => $this->uploadPartSize, + 'state' => $state, + 'params' => [ + 'ContentType' => $mimetype, + 'Metadata' => $this->buildS3Metadata($metaData), + 'StorageClass' => $this->storageClass, + ] + $this->getSSECParameters(), + ]); + + try { + $uploader->upload(); + $uploaded = true; + } catch (S3MultipartUploadException $e) { + $exception = $e; + $attempts++; + + if ($concurrency > 1) { + $concurrency = round($concurrency / 2); + } - try { - $uploader->upload(); - } catch (S3MultipartUploadException $e) { + if ($stream->isSeekable()) { + $stream->rewind(); + } + } + } + + if (!$uploaded) { // if anything goes wrong with multipart, make sure that you don´t poison and // slow down s3 bucket with orphaned fragments - $uploadInfo = $e->getState()->getId(); - if ($e->getState()->isInitiated() && (array_key_exists('UploadId', $uploadInfo))) { + $uploadInfo = $exception->getState()->getId(); + if ($exception->getState()->isInitiated() && (array_key_exists('UploadId', $uploadInfo))) { $this->getConnection()->abortMultipartUpload($uploadInfo); } - throw new \OCA\DAV\Connector\Sabre\Exception\BadGateway('Error while uploading to S3 bucket', 0, $e); + + throw new \OCA\DAV\Connector\Sabre\Exception\BadGateway('Error while uploading to S3 bucket', 0, $exception); } } - - /** - * @param string $urn the unified resource name used to identify the object - * @param resource $stream stream with the data to write - * @param string|null $mimetype the mimetype to set for the remove object @since 22.0.0 - * @throws \Exception when something goes wrong, message will be logged - * @since 7.0.0 - */ public function writeObject($urn, $stream, ?string $mimetype = null) { + $metaData = []; + if ($mimetype) { + $metaData['mimetype'] = $mimetype; + } + $this->writeObjectWithMetaData($urn, $stream, $metaData); + } + + public function writeObjectWithMetaData(string $urn, $stream, array $metaData): void { $canSeek = fseek($stream, 0, SEEK_CUR) === 0; $psrStream = Utils::streamFor($stream); @@ -154,16 +193,16 @@ trait S3ObjectTrait { $buffer->seek(0); if ($buffer->getSize() < $this->putSizeLimit) { // buffer is fully seekable, so use it directly for the small upload - $this->writeSingle($urn, $buffer, $mimetype); + $this->writeSingle($urn, $buffer, $metaData); } else { $loadStream = new Psr7\AppendStream([$buffer, $psrStream]); - $this->writeMultiPart($urn, $loadStream, $mimetype); + $this->writeMultiPart($urn, $loadStream, $metaData); } } else { if ($size < $this->putSizeLimit) { - $this->writeSingle($urn, $psrStream, $mimetype); + $this->writeSingle($urn, $psrStream, $metaData); } else { - $this->writeMultiPart($urn, $psrStream, $mimetype); + $this->writeMultiPart($urn, $psrStream, $metaData); } } $psrStream->close(); diff --git a/lib/private/Files/ObjectStore/S3Signature.php b/lib/private/Files/ObjectStore/S3Signature.php index 994d65cc219..b80382ff67d 100644 --- a/lib/private/Files/ObjectStore/S3Signature.php +++ b/lib/private/Files/ObjectStore/S3Signature.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/ObjectStore/StorageObjectStore.php b/lib/private/Files/ObjectStore/StorageObjectStore.php index 4361795ec45..888602a62e4 100644 --- a/lib/private/Files/ObjectStore/StorageObjectStore.php +++ b/lib/private/Files/ObjectStore/StorageObjectStore.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Search/QueryOptimizer/FlattenNestedBool.php b/lib/private/Files/Search/QueryOptimizer/FlattenNestedBool.php index 2bde6f0bbdb..bb7bef2ed63 100644 --- a/lib/private/Files/Search/QueryOptimizer/FlattenNestedBool.php +++ b/lib/private/Files/Search/QueryOptimizer/FlattenNestedBool.php @@ -14,8 +14,8 @@ class FlattenNestedBool extends QueryOptimizerStep { public function processOperator(ISearchOperator &$operator) { if ( $operator instanceof SearchBinaryOperator && ( - $operator->getType() === ISearchBinaryOperator::OPERATOR_OR || - $operator->getType() === ISearchBinaryOperator::OPERATOR_AND + $operator->getType() === ISearchBinaryOperator::OPERATOR_OR + || $operator->getType() === ISearchBinaryOperator::OPERATOR_AND ) ) { $newArguments = []; diff --git a/lib/private/Files/Search/QueryOptimizer/FlattenSingleArgumentBinaryOperation.php b/lib/private/Files/Search/QueryOptimizer/FlattenSingleArgumentBinaryOperation.php index cb04351534a..7e99c04f197 100644 --- a/lib/private/Files/Search/QueryOptimizer/FlattenSingleArgumentBinaryOperation.php +++ b/lib/private/Files/Search/QueryOptimizer/FlattenSingleArgumentBinaryOperation.php @@ -16,11 +16,11 @@ class FlattenSingleArgumentBinaryOperation extends ReplacingOptimizerStep { public function processOperator(ISearchOperator &$operator): bool { parent::processOperator($operator); if ( - $operator instanceof ISearchBinaryOperator && - count($operator->getArguments()) === 1 && - ( - $operator->getType() === ISearchBinaryOperator::OPERATOR_OR || - $operator->getType() === ISearchBinaryOperator::OPERATOR_AND + $operator instanceof ISearchBinaryOperator + && count($operator->getArguments()) === 1 + && ( + $operator->getType() === ISearchBinaryOperator::OPERATOR_OR + || $operator->getType() === ISearchBinaryOperator::OPERATOR_AND ) ) { $operator = $operator->getArguments()[0]; diff --git a/lib/private/Files/Search/QueryOptimizer/OrEqualsToIn.php b/lib/private/Files/Search/QueryOptimizer/OrEqualsToIn.php index 3f2b36823ab..6df35c9c9a2 100644 --- a/lib/private/Files/Search/QueryOptimizer/OrEqualsToIn.php +++ b/lib/private/Files/Search/QueryOptimizer/OrEqualsToIn.php @@ -18,8 +18,8 @@ use OCP\Files\Search\ISearchOperator; class OrEqualsToIn extends ReplacingOptimizerStep { public function processOperator(ISearchOperator &$operator): bool { if ( - $operator instanceof ISearchBinaryOperator && - $operator->getType() === ISearchBinaryOperator::OPERATOR_OR + $operator instanceof ISearchBinaryOperator + && $operator->getType() === ISearchBinaryOperator::OPERATOR_OR ) { $groups = $this->groupEqualsComparisonsByField($operator->getArguments()); $newParts = array_map(function (array $group) { @@ -32,7 +32,7 @@ class OrEqualsToIn extends ReplacingOptimizerStep { $value = $comparison->getValue(); return $value; }, $group); - $in = new SearchComparison(ISearchComparison::COMPARE_IN, $field, $values); + $in = new SearchComparison(ISearchComparison::COMPARE_IN, $field, $values, $group[0]->getExtra()); $pathEqHash = array_reduce($group, function ($pathEqHash, ISearchComparison $comparison) { return $comparison->getQueryHint(ISearchComparison::HINT_PATH_EQ_HASH, true) && $pathEqHash; }, true); diff --git a/lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php b/lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php index 9d50746d5d1..2994a9365a7 100644 --- a/lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php +++ b/lib/private/Files/Search/QueryOptimizer/PathPrefixOptimizer.php @@ -52,9 +52,9 @@ class PathPrefixOptimizer extends QueryOptimizerStep { private function operatorPairIsPathPrefix(ISearchOperator $like, ISearchOperator $equal): bool { return ( - $like instanceof ISearchComparison && $equal instanceof ISearchComparison && - !$like->getExtra() && !$equal->getExtra() && $like->getField() === 'path' && $equal->getField() === 'path' && - $like->getType() === ISearchComparison::COMPARE_LIKE_CASE_SENSITIVE && $equal->getType() === ISearchComparison::COMPARE_EQUAL + $like instanceof ISearchComparison && $equal instanceof ISearchComparison + && !$like->getExtra() && !$equal->getExtra() && $like->getField() === 'path' && $equal->getField() === 'path' + && $like->getType() === ISearchComparison::COMPARE_LIKE_CASE_SENSITIVE && $equal->getType() === ISearchComparison::COMPARE_EQUAL && $like->getValue() === SearchComparison::escapeLikeParameter($equal->getValue()) . '/%' ); } diff --git a/lib/private/Files/Search/QueryOptimizer/SplitLargeIn.php b/lib/private/Files/Search/QueryOptimizer/SplitLargeIn.php index 5c7655b49c1..8aee1975708 100644 --- a/lib/private/Files/Search/QueryOptimizer/SplitLargeIn.php +++ b/lib/private/Files/Search/QueryOptimizer/SplitLargeIn.php @@ -18,13 +18,13 @@ use OCP\Files\Search\ISearchOperator; class SplitLargeIn extends ReplacingOptimizerStep { public function processOperator(ISearchOperator &$operator): bool { if ( - $operator instanceof ISearchComparison && - $operator->getType() === ISearchComparison::COMPARE_IN && - count($operator->getValue()) > 1000 + $operator instanceof ISearchComparison + && $operator->getType() === ISearchComparison::COMPARE_IN + && count($operator->getValue()) > 1000 ) { $chunks = array_chunk($operator->getValue(), 1000); $chunkComparisons = array_map(function (array $values) use ($operator) { - return new SearchComparison(ISearchComparison::COMPARE_IN, $operator->getField(), $values); + return new SearchComparison(ISearchComparison::COMPARE_IN, $operator->getField(), $values, $operator->getExtra()); }, $chunks); $operator = new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_OR, $chunkComparisons); diff --git a/lib/private/Files/Search/SearchBinaryOperator.php b/lib/private/Files/Search/SearchBinaryOperator.php index 59a1ba2dfaf..49f599933f4 100644 --- a/lib/private/Files/Search/SearchBinaryOperator.php +++ b/lib/private/Files/Search/SearchBinaryOperator.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Search/SearchOrder.php b/lib/private/Files/Search/SearchOrder.php index 3dcbc02bc1a..5a036653f4e 100644 --- a/lib/private/Files/Search/SearchOrder.php +++ b/lib/private/Files/Search/SearchOrder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Search/SearchQuery.php b/lib/private/Files/Search/SearchQuery.php index 1793e42d349..592749cf4a0 100644 --- a/lib/private/Files/Search/SearchQuery.php +++ b/lib/private/Files/Search/SearchQuery.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php index 2b8121a529d..d6260c38fb0 100644 --- a/lib/private/Files/SetupManager.php +++ b/lib/private/Files/SetupManager.php @@ -23,7 +23,6 @@ use OC\Share\Share; use OC\Share20\ShareDisableChecker; use OC_App; use OC_Hook; -use OC_Util; use OCA\Files_External\Config\ExternalMountPoint; use OCA\Files_Sharing\External\Mount; use OCA\Files_Sharing\ISharedMountPoint; @@ -34,6 +33,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Config\ICachedMountInfo; use OCP\Files\Config\IHomeMountProvider; use OCP\Files\Config\IMountProvider; +use OCP\Files\Config\IRootMountProvider; use OCP\Files\Config\IUserMountCache; use OCP\Files\Events\BeforeFileSystemSetupEvent; use OCP\Files\Events\InvalidateMountCacheEvent; @@ -156,7 +156,7 @@ class SetupManager { if ($mount instanceof HomeMountPoint) { $user = $mount->getUser(); return new Quota(['storage' => $storage, 'quotaCallback' => function () use ($user) { - return OC_Util::getUserQuota($user); + return $user->getQuotaBytes(); }, 'root' => 'files', 'include_external_storage' => $quotaIncludeExternal]); } @@ -171,9 +171,9 @@ class SetupManager { return new PermissionsMask([ 'storage' => $storage, 'mask' => Constants::PERMISSION_ALL & ~( - Constants::PERMISSION_UPDATE | - Constants::PERMISSION_CREATE | - Constants::PERMISSION_DELETE + Constants::PERMISSION_UPDATE + | Constants::PERMISSION_CREATE + | Constants::PERMISSION_DELETE ), ]); } @@ -280,9 +280,13 @@ class SetupManager { $mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) { return str_starts_with($mount->getMountPoint(), $userRoot); }); - $allProviders = array_map(function (IMountProvider $provider) { + $allProviders = array_map(function (IMountProvider|IHomeMountProvider|IRootMountProvider $provider) { return get_class($provider); - }, $this->mountProviderCollection->getProviders()); + }, array_merge( + $this->mountProviderCollection->getProviders(), + $this->mountProviderCollection->getHomeProviders(), + $this->mountProviderCollection->getRootProviders(), + )); $newProviders = array_diff($allProviders, $previouslySetupProviders); $mounts = array_filter($mounts, function (IMountPoint $mount) use ($previouslySetupProviders) { return !in_array($mount->getMountProvider(), $previouslySetupProviders); diff --git a/lib/private/Files/SimpleFS/SimpleFile.php b/lib/private/Files/SimpleFS/SimpleFile.php index cbb3af4db29..d9c1b47d2f1 100644 --- a/lib/private/Files/SimpleFS/SimpleFile.php +++ b/lib/private/Files/SimpleFS/SimpleFile.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -6,9 +7,11 @@ namespace OC\Files\SimpleFS; use OCP\Files\File; +use OCP\Files\GenericFileException; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; use OCP\Files\SimpleFS\ISimpleFile; +use OCP\Lock\LockedException; class SimpleFile implements ISimpleFile { private File $file; @@ -48,8 +51,10 @@ class SimpleFile implements ISimpleFile { /** * Get the content * - * @throws NotPermittedException + * @throws GenericFileException + * @throws LockedException * @throws NotFoundException + * @throws NotPermittedException */ public function getContent(): string { $result = $this->file->getContent(); @@ -65,8 +70,10 @@ class SimpleFile implements ISimpleFile { * Overwrite the file * * @param string|resource $data - * @throws NotPermittedException + * @throws GenericFileException + * @throws LockedException * @throws NotFoundException + * @throws NotPermittedException */ public function putContent($data): void { try { diff --git a/lib/private/Files/SimpleFS/SimpleFolder.php b/lib/private/Files/SimpleFS/SimpleFolder.php index 0da552e402b..62f3db25e9b 100644 --- a/lib/private/Files/SimpleFS/SimpleFolder.php +++ b/lib/private/Files/SimpleFS/SimpleFolder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Storage/Common.php b/lib/private/Files/Storage/Common.php index ca0e38774c8..2dc359169d7 100644 --- a/lib/private/Files/Storage/Common.php +++ b/lib/private/Files/Storage/Common.php @@ -19,6 +19,7 @@ use OC\Files\ObjectStore\ObjectStoreStorage; use OC\Files\Storage\Wrapper\Encryption; use OC\Files\Storage\Wrapper\Jail; use OC\Files\Storage\Wrapper\Wrapper; +use OCP\Files; use OCP\Files\Cache\ICache; use OCP\Files\Cache\IPropagator; use OCP\Files\Cache\IScanner; @@ -205,7 +206,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage, } else { $sourceStream = $this->fopen($source, 'r'); $targetStream = $this->fopen($target, 'w'); - [, $result] = \OC_Helper::streamCopy($sourceStream, $targetStream); + [, $result] = Files::streamCopy($sourceStream, $targetStream, true); if (!$result) { Server::get(LoggerInterface::class)->warning("Failed to write data while copying $source to $target"); } @@ -549,8 +550,8 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage, public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool { if ( - !$sourceStorage->instanceOfStorage(Encryption::class) && - $this->isSameStorage($sourceStorage) + !$sourceStorage->instanceOfStorage(Encryption::class) + && $this->isSameStorage($sourceStorage) ) { // resolve any jailed paths while ($sourceStorage->instanceOfStorage(Jail::class)) { @@ -734,7 +735,7 @@ abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage, throw new GenericFileException("Failed to open $path for writing"); } try { - [$count, $result] = \OC_Helper::streamCopy($stream, $target); + [$count, $result] = Files::streamCopy($stream, $target, true); if (!$result) { throw new GenericFileException('Failed to copy stream'); } diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php index 10670d6331a..afd8f87e2de 100644 --- a/lib/private/Files/Storage/DAV.php +++ b/lib/private/Files/Storage/DAV.php @@ -350,7 +350,13 @@ class DAV extends Common { } } - return $response->getBody(); + $content = $response->getBody(); + + if ($content === null || is_string($content)) { + return false; + } + + return $content; case 'w': case 'wb': case 'a': @@ -390,6 +396,8 @@ class DAV extends Common { $this->writeBack($tmpFile, $path); }); } + + return false; } public function writeBack(string $tmpFile, string $path): void { diff --git a/lib/private/Files/Storage/LocalTempFileTrait.php b/lib/private/Files/Storage/LocalTempFileTrait.php index c8e3588f2e8..fffc3e789f3 100644 --- a/lib/private/Files/Storage/LocalTempFileTrait.php +++ b/lib/private/Files/Storage/LocalTempFileTrait.php @@ -7,6 +7,8 @@ */ namespace OC\Files\Storage; +use OCP\Files; + /** * Storage backend class for providing common filesystem operation methods * which are not storage-backend specific. @@ -45,7 +47,7 @@ trait LocalTempFileTrait { } $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($extension); $target = fopen($tmpFile, 'w'); - \OC_Helper::streamCopy($source, $target); + Files::streamCopy($source, $target); fclose($target); return $tmpFile; } diff --git a/lib/private/Files/Storage/Temporary.php b/lib/private/Files/Storage/Temporary.php index ff7a816930d..ecf8a1315a9 100644 --- a/lib/private/Files/Storage/Temporary.php +++ b/lib/private/Files/Storage/Temporary.php @@ -7,16 +7,20 @@ */ namespace OC\Files\Storage; +use OCP\Files; +use OCP\ITempManager; +use OCP\Server; + /** * local storage backend in temporary folder for testing purpose */ class Temporary extends Local { public function __construct(array $parameters = []) { - parent::__construct(['datadir' => \OC::$server->getTempManager()->getTemporaryFolder()]); + parent::__construct(['datadir' => Server::get(ITempManager::class)->getTemporaryFolder()]); } public function cleanUp(): void { - \OC_Helper::rmdirr($this->datadir); + Files::rmdirr($this->datadir); } public function __destruct() { diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php index eb073d24087..58bd4dfddcf 100644 --- a/lib/private/Files/Storage/Wrapper/Encryption.php +++ b/lib/private/Files/Storage/Wrapper/Encryption.php @@ -8,7 +8,6 @@ namespace OC\Files\Storage\Wrapper; use OC\Encryption\Exceptions\ModuleDoesNotExistsException; -use OC\Encryption\Update; use OC\Encryption\Util; use OC\Files\Cache\CacheEntry; use OC\Files\Filesystem; @@ -18,10 +17,13 @@ use OC\Files\Storage\Common; use OC\Files\Storage\LocalTempFileTrait; use OC\Memcache\ArrayCache; use OCP\Cache\CappedMemoryCache; +use OCP\Encryption\Exceptions\InvalidHeaderException; use OCP\Encryption\IFile; use OCP\Encryption\IManager; use OCP\Encryption\Keys\IStorage; +use OCP\Files; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\GenericFileException; use OCP\Files\Mount\IMountPoint; use OCP\Files\Storage; use Psr\Log\LoggerInterface; @@ -49,7 +51,6 @@ class Encryption extends Wrapper { private IFile $fileHelper, private ?string $uid, private IStorage $keyStorage, - private Update $update, private Manager $mountManager, private ArrayCache $arrayCache, ) { @@ -64,7 +65,8 @@ class Encryption extends Wrapper { $info = $this->getCache()->get($path); if ($info === false) { - return false; + /* Pass call to wrapped storage, it may be a special file like a part file */ + return $this->storage->filesize($path); } if (isset($this->unencryptedSize[$fullPath])) { $size = $this->unencryptedSize[$fullPath]; @@ -184,11 +186,11 @@ class Encryption extends Wrapper { public function rename(string $source, string $target): bool { $result = $this->storage->rename($source, $target); - if ($result && + if ($result // versions always use the keys from the original file, so we can skip // this step for versions - $this->isVersion($target) === false && - $this->encryptionManager->isEnabled()) { + && $this->isVersion($target) === false + && $this->encryptionManager->isEnabled()) { $sourcePath = $this->getFullPath($source); if (!$this->util->isExcluded($sourcePath)) { $targetPath = $this->getFullPath($target); @@ -209,9 +211,9 @@ class Encryption extends Wrapper { public function rmdir(string $path): bool { $result = $this->storage->rmdir($path); $fullPath = $this->getFullPath($path); - if ($result && - $this->util->isExcluded($fullPath) === false && - $this->encryptionManager->isEnabled() + if ($result + && $this->util->isExcluded($fullPath) === false + && $this->encryptionManager->isEnabled() ) { $this->keyStorage->deleteAllFileKeys($fullPath); } @@ -224,9 +226,9 @@ class Encryption extends Wrapper { $metaData = $this->getMetaData($path); if ( - !$this->is_dir($path) && - isset($metaData['encrypted']) && - $metaData['encrypted'] === true + !$this->is_dir($path) + && isset($metaData['encrypted']) + && $metaData['encrypted'] === true ) { $fullPath = $this->getFullPath($path); $module = $this->getEncryptionModule($path); @@ -318,7 +320,7 @@ class Encryption extends Wrapper { if (!empty($encryptionModuleId)) { $encryptionModule = $this->encryptionManager->getEncryptionModule($encryptionModuleId); $shouldEncrypt = true; - } elseif (empty($encryptionModuleId) && $info['encrypted'] === true) { + } elseif ($info !== false && $info['encrypted'] === true) { // we come from a old installation. No header and/or no module defined // but the file is encrypted. In this case we need to use the // OC_DEFAULT_MODULE to read the file @@ -344,6 +346,16 @@ class Encryption extends Wrapper { if ($shouldEncrypt === true && $encryptionModule !== null) { $this->encryptedPaths->set($this->util->stripPartialFileExtension($path), true); $headerSize = $this->getHeaderSize($path); + if ($mode === 'r' && $headerSize === 0) { + $firstBlock = $this->readFirstBlock($path); + if (!$firstBlock) { + throw new InvalidHeaderException("Unable to get header block for $path"); + } elseif (!str_starts_with($firstBlock, Util::HEADER_START)) { + throw new InvalidHeaderException("Unable to get header size for $path, file doesn't start with encryption header"); + } else { + throw new InvalidHeaderException("Unable to get header size for $path, even though file does start with encryption header"); + } + } $source = $this->storage->fopen($path, $mode); if (!is_resource($source)) { return false; @@ -373,9 +385,9 @@ class Encryption extends Wrapper { $size = $this->storage->filesize($path); $result = $unencryptedSize; - if ($unencryptedSize < 0 || - ($size > 0 && $unencryptedSize === $size) || - $unencryptedSize > $size + if ($unencryptedSize < 0 + || ($size > 0 && $unencryptedSize === $size) + || $unencryptedSize > $size ) { // check if we already calculate the unencrypted size for the // given path to avoid recursions @@ -526,10 +538,22 @@ class Encryption extends Wrapper { $result = $this->copyBetweenStorage($sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime, true); if ($result) { - if ($sourceStorage->is_dir($sourceInternalPath)) { - $result = $sourceStorage->rmdir($sourceInternalPath); - } else { - $result = $sourceStorage->unlink($sourceInternalPath); + $setPreserveCacheOnDelete = $sourceStorage->instanceOfStorage(ObjectStoreStorage::class) && !$this->instanceOfStorage(ObjectStoreStorage::class); + if ($setPreserveCacheOnDelete) { + /** @var ObjectStoreStorage $sourceStorage */ + $sourceStorage->setPreserveCacheOnDelete(true); + } + try { + if ($sourceStorage->is_dir($sourceInternalPath)) { + $result = $sourceStorage->rmdir($sourceInternalPath); + } else { + $result = $sourceStorage->unlink($sourceInternalPath); + } + } finally { + if ($setPreserveCacheOnDelete) { + /** @var ObjectStoreStorage $sourceStorage */ + $sourceStorage->setPreserveCacheOnDelete(false); + } } } return $result; @@ -611,8 +635,8 @@ class Encryption extends Wrapper { ): bool { // for versions we have nothing to do, because versions should always use the // key from the original file. Just create a 1:1 copy and done - if ($this->isVersion($targetInternalPath) || - $this->isVersion($sourceInternalPath)) { + if ($this->isVersion($targetInternalPath) + || $this->isVersion($sourceInternalPath)) { // remember that we try to create a version so that we can detect it during // fopen($sourceInternalPath) and by-pass the encryption in order to // create a 1:1 copy of the file @@ -628,6 +652,7 @@ class Encryption extends Wrapper { $info->getUnencryptedSize() ); } + $this->updateEncryptedVersion($sourceStorage, $sourceInternalPath, $targetInternalPath, $isRename, true); } return $result; } @@ -653,7 +678,7 @@ class Encryption extends Wrapper { if (is_resource($dh)) { while ($result && ($file = readdir($dh)) !== false) { if (!Filesystem::isIgnoredDir($file)) { - $result &= $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file, false, $isRename); + $result = $this->copyFromStorage($sourceStorage, $sourceInternalPath . '/' . $file, $targetInternalPath . '/' . $file, $preserveMtime, $isRename); } } } @@ -661,12 +686,16 @@ class Encryption extends Wrapper { try { $source = $sourceStorage->fopen($sourceInternalPath, 'r'); $target = $this->fopen($targetInternalPath, 'w'); - [, $result] = \OC_Helper::streamCopy($source, $target); + if ($source === false || $target === false) { + $result = false; + } else { + [, $result] = Files::streamCopy($source, $target, true); + } } finally { - if (is_resource($source)) { + if (isset($source) && $source !== false) { fclose($source); } - if (is_resource($target)) { + if (isset($target) && $target !== false) { fclose($target); } } @@ -716,6 +745,9 @@ class Encryption extends Wrapper { public function hash(string $type, string $path, bool $raw = false): string|false { $fh = $this->fopen($path, 'rb'); + if ($fh === false) { + return false; + } $ctx = hash_init($type); hash_update_stream($ctx, $fh); fclose($fh); @@ -740,6 +772,9 @@ class Encryption extends Wrapper { $firstBlock = ''; if ($this->storage->is_file($path)) { $handle = $this->storage->fopen($path, 'r'); + if ($handle === false) { + return ''; + } $firstBlock = fread($handle, $this->util->getHeaderSize()); fclose($handle); } @@ -870,7 +905,10 @@ class Encryption extends Wrapper { public function writeStream(string $path, $stream, ?int $size = null): int { // always fall back to fopen $target = $this->fopen($path, 'w'); - [$count, $result] = \OC_Helper::streamCopy($stream, $target); + if ($target === false) { + throw new GenericFileException("Failed to open $path for writing"); + } + [$count, $result] = Files::streamCopy($stream, $target, true); fclose($stream); fclose($target); @@ -893,4 +931,16 @@ class Encryption extends Wrapper { public function setEnabled(bool $enabled): void { $this->enabled = $enabled; } + + /** + * Check if the on-disk data for a file has a valid encrypted header + * + * @param string $path + * @return bool + */ + public function hasValidHeader(string $path): bool { + $firstBlock = $this->readFirstBlock($path); + $header = $this->util->parseRawHeader($firstBlock); + return (count($header) > 0); + } } diff --git a/lib/private/Files/Storage/Wrapper/Jail.php b/lib/private/Files/Storage/Wrapper/Jail.php index c8db0e94e59..38b113cef88 100644 --- a/lib/private/Files/Storage/Wrapper/Jail.php +++ b/lib/private/Files/Storage/Wrapper/Jail.php @@ -11,6 +11,7 @@ use OC\Files\Cache\Wrapper\CacheJail; use OC\Files\Cache\Wrapper\JailPropagator; use OC\Files\Cache\Wrapper\JailWatcher; use OC\Files\Filesystem; +use OCP\Files; use OCP\Files\Cache\ICache; use OCP\Files\Cache\IPropagator; use OCP\Files\Cache\IWatcher; @@ -253,7 +254,7 @@ class Jail extends Wrapper { return $storage->writeStream($this->getUnjailedPath($path), $stream, $size); } else { $target = $this->fopen($path, 'w'); - [$count, $result] = \OC_Helper::streamCopy($stream, $target); + $count = Files::streamCopy($stream, $target); fclose($stream); fclose($target); return $count; diff --git a/lib/private/Files/Storage/Wrapper/Quota.php b/lib/private/Files/Storage/Wrapper/Quota.php index 3be77ba1b37..35a265f8c8e 100644 --- a/lib/private/Files/Storage/Wrapper/Quota.php +++ b/lib/private/Files/Storage/Wrapper/Quota.php @@ -21,6 +21,7 @@ class Quota extends Wrapper { protected string $sizeRoot; private SystemConfig $config; private bool $quotaIncludeExternalStorage; + private bool $enabled = true; /** * @param array $parameters @@ -46,6 +47,9 @@ class Quota extends Wrapper { } private function hasQuota(): bool { + if (!$this->enabled) { + return false; + } return $this->getQuota() !== FileInfo::SPACE_UNLIMITED; } @@ -197,4 +201,8 @@ class Quota extends Wrapper { return parent::touch($path, $mtime); } + + public function enableQuota(bool $enabled): void { + $this->enabled = $enabled; + } } diff --git a/lib/private/Files/Storage/Wrapper/Wrapper.php b/lib/private/Files/Storage/Wrapper/Wrapper.php index 6dea439fe25..7af11dd5ef7 100644 --- a/lib/private/Files/Storage/Wrapper/Wrapper.php +++ b/lib/private/Files/Storage/Wrapper/Wrapper.php @@ -9,6 +9,7 @@ namespace OC\Files\Storage\Wrapper; use OC\Files\Storage\FailedStorage; use OC\Files\Storage\Storage; +use OCP\Files; use OCP\Files\Cache\ICache; use OCP\Files\Cache\IPropagator; use OCP\Files\Cache\IScanner; @@ -322,7 +323,7 @@ class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage, IWriteStrea return $storage->writeStream($path, $stream, $size); } else { $target = $this->fopen($path, 'w'); - [$count, $result] = \OC_Helper::streamCopy($stream, $target); + $count = Files::streamCopy($stream, $target); fclose($stream); fclose($target); return $count; diff --git a/lib/private/Files/Stream/Encryption.php b/lib/private/Files/Stream/Encryption.php index 0d55385820c..ef147ec421f 100644 --- a/lib/private/Files/Stream/Encryption.php +++ b/lib/private/Files/Stream/Encryption.php @@ -312,8 +312,8 @@ class Encryption extends Wrapper { // for seekable streams the pointer is moved back to the beginning of the encrypted block // flush will start writing there when the position moves to another block - $positionInFile = (int)floor($this->position / $this->unencryptedBlockSize) * - $this->util->getBlockSize() + $this->headerSize; + $positionInFile = (int)floor($this->position / $this->unencryptedBlockSize) + * $this->util->getBlockSize() + $this->headerSize; $resultFseek = $this->parentStreamSeek($positionInFile); // only allow writes on seekable streams, or at the end of the encrypted stream @@ -336,8 +336,8 @@ class Encryption extends Wrapper { // if $data doesn't fit the current block, the fill the current block and reiterate // after the block is filled, it is flushed and $data is updatedxxx } else { - $this->cache = substr($this->cache, 0, $blockPosition) . - substr($data, 0, $this->unencryptedBlockSize - $blockPosition); + $this->cache = substr($this->cache, 0, $blockPosition) + . substr($data, 0, $this->unencryptedBlockSize - $blockPosition); $this->flush(); $this->position += ($this->unencryptedBlockSize - $blockPosition); $length += ($this->unencryptedBlockSize - $blockPosition); diff --git a/lib/private/Files/Stream/SeekableHttpStream.php b/lib/private/Files/Stream/SeekableHttpStream.php index 5ed04ed9066..6ce0a880e8d 100644 --- a/lib/private/Files/Stream/SeekableHttpStream.php +++ b/lib/private/Files/Stream/SeekableHttpStream.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Files/Template/TemplateManager.php b/lib/private/Files/Template/TemplateManager.php index 5a3f16872e6..80ef5a14786 100644 --- a/lib/private/Files/Template/TemplateManager.php +++ b/lib/private/Files/Template/TemplateManager.php @@ -19,6 +19,7 @@ use OCP\Files\IRootFolder; use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\Files\Template\BeforeGetTemplatesEvent; +use OCP\Files\Template\Field; use OCP\Files\Template\FileCreatedFromTemplateEvent; use OCP\Files\Template\ICustomTemplateProvider; use OCP\Files\Template\ITemplateManager; @@ -125,6 +126,19 @@ class TemplateManager implements ITemplateManager { }, $this->listCreators())); } + public function listTemplateFields(int $fileId): array { + foreach ($this->listCreators() as $creator) { + $fields = $this->getTemplateFields($creator, $fileId); + if (empty($fields)) { + continue; + } + + return $fields; + } + + return []; + } + /** * @param string $filePath * @param string $templateId @@ -179,7 +193,6 @@ class TemplateManager implements ITemplateManager { if ($path instanceof Folder) { return $path; } - $this->logger->warning('Template folder ' . $path . ' not found or invalid', ['app' => 'files_templates']); } throw new NotFoundException(); } @@ -188,6 +201,20 @@ class TemplateManager implements ITemplateManager { * @return list<Template> */ private function getTemplateFiles(TemplateFileCreator $type): array { + $templates = array_merge( + $this->getProviderTemplates($type), + $this->getUserTemplates($type) + ); + + $this->eventDispatcher->dispatchTyped(new BeforeGetTemplatesEvent($templates, false)); + + return $templates; + } + + /** + * @return list<Template> + */ + private function getProviderTemplates(TemplateFileCreator $type): array { $templates = []; foreach ($this->getRegisteredProviders() as $provider) { foreach ($type->getMimetypes() as $mimetype) { @@ -196,11 +223,22 @@ class TemplateManager implements ITemplateManager { } } } + + return $templates; + } + + /** + * @return list<Template> + */ + private function getUserTemplates(TemplateFileCreator $type): array { + $templates = []; + try { $userTemplateFolder = $this->getTemplateFolder(); } catch (\Exception $e) { return $templates; } + foreach ($type->getMimetypes() as $mimetype) { foreach ($userTemplateFolder->searchByMime($mimetype) as $templateFile) { $template = new Template( @@ -213,11 +251,33 @@ class TemplateManager implements ITemplateManager { } } - $this->eventDispatcher->dispatchTyped(new BeforeGetTemplatesEvent($templates)); - return $templates; } + /* + * @return list<Field> + */ + private function getTemplateFields(TemplateFileCreator $type, int $fileId): array { + $providerTemplates = $this->getProviderTemplates($type); + $userTemplates = $this->getUserTemplates($type); + + $matchedTemplates = array_filter( + array_merge($providerTemplates, $userTemplates), + function (Template $template) use ($fileId) { + return $template->jsonSerialize()['fileid'] === $fileId; + }); + + if (empty($matchedTemplates)) { + return []; + } + + $this->eventDispatcher->dispatchTyped(new BeforeGetTemplatesEvent($matchedTemplates, true)); + + return array_values(array_map(function (Template $template) { + return $template->jsonSerialize()['fields'] ?? []; + }, $matchedTemplates)); + } + /** * @param Node|File $file * @return array diff --git a/lib/private/Files/Type/Detection.php b/lib/private/Files/Type/Detection.php index b1e4c098e54..d5810a90868 100644 --- a/lib/private/Files/Type/Detection.php +++ b/lib/private/Files/Type/Detection.php @@ -9,6 +9,8 @@ declare(strict_types=1); namespace OC\Files\Type; use OCP\Files\IMimeTypeDetector; +use OCP\IBinaryFinder; +use OCP\ITempManager; use OCP\IURLGenerator; use Psr\Log\LoggerInterface; @@ -22,13 +24,17 @@ use Psr\Log\LoggerInterface; class Detection implements IMimeTypeDetector { private const CUSTOM_MIMETYPEMAPPING = 'mimetypemapping.json'; private const CUSTOM_MIMETYPEALIASES = 'mimetypealiases.json'; + private const CUSTOM_MIMETYPENAMES = 'mimetypenames.json'; - protected array $mimetypes = []; + /** @var array<list{string, string|null}> */ + protected array $mimeTypes = []; protected array $secureMimeTypes = []; - protected array $mimetypeIcons = []; + protected array $mimeTypeIcons = []; /** @var array<string,string> */ protected array $mimeTypeAlias = []; + /** @var array<string,string> */ + protected array $mimeTypesNames = []; public function __construct( private IURLGenerator $urlGenerator, @@ -39,40 +45,46 @@ class Detection implements IMimeTypeDetector { } /** - * Add an extension -> mimetype mapping + * Add an extension -> MIME type mapping * - * $mimetype is the assumed correct mime type + * $mimeType is the assumed correct mime type * The optional $secureMimeType is an alternative to send to send * to avoid potential XSS. * * @param string $extension - * @param string $mimetype + * @param string $mimeType * @param string|null $secureMimeType */ public function registerType(string $extension, - string $mimetype, + string $mimeType, ?string $secureMimeType = null): void { - $this->mimetypes[$extension] = [$mimetype, $secureMimeType]; - $this->secureMimeTypes[$mimetype] = $secureMimeType ?: $mimetype; + // Make sure the extension is a string + // https://github.com/nextcloud/server/issues/42902 + $this->mimeTypes[$extension] = [$mimeType, $secureMimeType]; + $this->secureMimeTypes[$mimeType] = $secureMimeType ?? $mimeType; } /** - * Add an array of extension -> mimetype mappings + * Add an array of extension -> MIME type mappings * - * The mimetype value is in itself an array where the first index is - * the assumed correct mimetype and the second is either a secure alternative + * The mimeType value is in itself an array where the first index is + * the assumed correct mimeType and the second is either a secure alternative * or null if the correct is considered secure. * * @param array $types */ public function registerTypeArray(array $types): void { - $this->mimetypes = array_merge($this->mimetypes, $types); + // Register the types, + foreach ($types as $extension => $mimeType) { + $this->registerType((string)$extension, $mimeType[0], $mimeType[1] ?? null); + } - // Update the alternative mimetypes to avoid having to look them up each time. - foreach ($this->mimetypes as $extension => $mimeType) { - if (str_starts_with($extension, '_comment')) { + // Update the alternative mimeTypes to avoid having to look them up each time. + foreach ($this->mimeTypes as $extension => $mimeType) { + if (str_starts_with((string)$extension, '_comment')) { continue; } + $this->secureMimeTypes[$mimeType[0]] = $mimeType[1] ?? $mimeType[0]; if (isset($mimeType[1])) { $this->secureMimeTypes[$mimeType[1]] = $mimeType[1]; @@ -93,7 +105,7 @@ class Detection implements IMimeTypeDetector { } /** - * Add the mimetype aliases if they are not yet present + * Add the MIME type aliases if they are not yet present */ private function loadAliases(): void { if (!empty($this->mimeTypeAlias)) { @@ -119,29 +131,48 @@ class Detection implements IMimeTypeDetector { } /** - * Add mimetype mappings if they are not yet present + * Add MIME type mappings if they are not yet present */ private function loadMappings(): void { - if (!empty($this->mimetypes)) { + if (!empty($this->mimeTypes)) { return; } - $mimetypeMapping = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypemapping.dist.json'), true); - $mimetypeMapping = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPEMAPPING, $mimetypeMapping); + $mimeTypeMapping = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypemapping.dist.json'), true); + $mimeTypeMapping = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPEMAPPING, $mimeTypeMapping); - $this->registerTypeArray($mimetypeMapping); + $this->registerTypeArray($mimeTypeMapping); } /** - * @return array + * @return array<list{string, string|null}> */ public function getAllMappings(): array { $this->loadMappings(); - return $this->mimetypes; + return $this->mimeTypes; + } + + private function loadNamings(): void { + if (!empty($this->mimeTypesNames)) { + return; + } + + $mimeTypeMapping = json_decode(file_get_contents($this->defaultConfigDir . '/mimetypenames.dist.json'), true); + $mimeTypeMapping = $this->loadCustomDefinitions(self::CUSTOM_MIMETYPENAMES, $mimeTypeMapping); + + $this->mimeTypesNames = $mimeTypeMapping; + } + + /** + * @return array<string,string> + */ + public function getAllNamings(): array { + $this->loadNamings(); + return $this->mimeTypesNames; } /** - * detect mimetype only based on filename, content of file is not used + * detect MIME type only based on filename, content of file is not used * * @param string $path * @return string @@ -163,8 +194,8 @@ class Detection implements IMimeTypeDetector { $extension = strrchr($fileName, '.'); if ($extension !== false) { $extension = strtolower($extension); - $extension = substr($extension, 1); //remove leading . - return $this->mimetypes[$extension][0] ?? 'application/octet-stream'; + $extension = substr($extension, 1); // remove leading . + return $this->mimeTypes[$extension][0] ?? 'application/octet-stream'; } } @@ -172,7 +203,8 @@ class Detection implements IMimeTypeDetector { } /** - * detect mimetype only based on the content of file + * Detect MIME type only based on the content of file. + * * @param string $path * @return string * @since 18.0.0 @@ -216,28 +248,30 @@ class Detection implements IMimeTypeDetector { } } - if (\OC_Helper::canExecute('file')) { + $binaryFinder = \OCP\Server::get(IBinaryFinder::class); + $program = $binaryFinder->findBinaryPath('file'); + if ($program !== false) { // it looks like we have a 'file' command, // lets see if it does have mime support $path = escapeshellarg($path); - $fp = popen("test -f $path && file -b --mime-type $path", 'r'); - $mimeType = fgets($fp); - pclose($fp); - - if ($mimeType !== false) { - //trim the newline - $mimeType = trim($mimeType); - $mimeType = $this->getSecureMimeType($mimeType); - if ($mimeType !== 'application/octet-stream') { + $fp = popen("test -f $path && $program -b --mime-type $path", 'r'); + if ($fp !== false) { + $mimeType = fgets($fp); + pclose($fp); + if ($mimeType !== false) { + //trim the newline + $mimeType = trim($mimeType); + $mimeType = $this->getSecureMimeType($mimeType); return $mimeType; } } } + return 'application/octet-stream'; } /** - * detect mimetype based on both filename and content + * Detect MIME type based on both filename and content * * @param string $path * @return string @@ -253,7 +287,7 @@ class Detection implements IMimeTypeDetector { } /** - * detect mimetype based on the content of a string + * Detect MIME type based on the content of a string * * @param string $data * @return string @@ -265,7 +299,7 @@ class Detection implements IMimeTypeDetector { return str_contains($info, ';') ? substr($info, 0, strpos($info, ';')) : $info; } - $tmpFile = \OC::$server->getTempManager()->getTemporaryFile(); + $tmpFile = \OCP\Server::get(ITempManager::class)->getTemporaryFile(); $fh = fopen($tmpFile, 'wb'); fwrite($fh, $data, 8024); fclose($fh); @@ -275,7 +309,7 @@ class Detection implements IMimeTypeDetector { } /** - * Get a secure mimetype that won't expose potential XSS. + * Get a secure MIME type that won't expose potential XSS. * * @param string $mimeType * @return string @@ -288,57 +322,56 @@ class Detection implements IMimeTypeDetector { /** * Get path to the icon of a file type - * @param string $mimetype the MIME type + * @param string $mimeType the MIME type * @return string the url */ - public function mimeTypeIcon($mimetype): string { + public function mimeTypeIcon($mimeType): string { $this->loadAliases(); - while (isset($this->mimeTypeAlias[$mimetype])) { - $mimetype = $this->mimeTypeAlias[$mimetype]; + while (isset($this->mimeTypeAlias[$mimeType])) { + $mimeType = $this->mimeTypeAlias[$mimeType]; } - if (isset($this->mimetypeIcons[$mimetype])) { - return $this->mimetypeIcons[$mimetype]; + if (isset($this->mimeTypeIcons[$mimeType])) { + return $this->mimeTypeIcons[$mimeType]; } // Replace slash and backslash with a minus - $icon = str_replace(['/', '\\'], '-', $mimetype); + $icon = str_replace(['/', '\\'], '-', $mimeType); // Is it a dir? - if ($mimetype === 'dir') { - $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder.svg'); - return $this->mimetypeIcons[$mimetype]; + if ($mimeType === 'dir') { + $this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/folder.svg'); + return $this->mimeTypeIcons[$mimeType]; } - if ($mimetype === 'dir-shared') { - $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder-shared.svg'); - return $this->mimetypeIcons[$mimetype]; + if ($mimeType === 'dir-shared') { + $this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/folder-shared.svg'); + return $this->mimeTypeIcons[$mimeType]; } - if ($mimetype === 'dir-external') { - $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/folder-external.svg'); - return $this->mimetypeIcons[$mimetype]; + if ($mimeType === 'dir-external') { + $this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/folder-external.svg'); + return $this->mimeTypeIcons[$mimeType]; } // Icon exists? try { - $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/' . $icon . '.svg'); - return $this->mimetypeIcons[$mimetype]; + $this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/' . $icon . '.svg'); + return $this->mimeTypeIcons[$mimeType]; } catch (\RuntimeException $e) { // Specified image not found } // Try only the first part of the filetype - if (strpos($icon, '-')) { $mimePart = substr($icon, 0, strpos($icon, '-')); try { - $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/' . $mimePart . '.svg'); - return $this->mimetypeIcons[$mimetype]; + $this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/' . $mimePart . '.svg'); + return $this->mimeTypeIcons[$mimeType]; } catch (\RuntimeException $e) { - // Image for the first part of the mimetype not found + // Image for the first part of the MIME type not found } } - $this->mimetypeIcons[$mimetype] = $this->urlGenerator->imagePath('core', 'filetypes/file.svg'); - return $this->mimetypeIcons[$mimetype]; + $this->mimeTypeIcons[$mimeType] = $this->urlGenerator->imagePath('core', 'filetypes/file.svg'); + return $this->mimeTypeIcons[$mimeType]; } } diff --git a/lib/private/Files/Utils/PathHelper.php b/lib/private/Files/Utils/PathHelper.php index a6ae029b957..db1294bcc10 100644 --- a/lib/private/Files/Utils/PathHelper.php +++ b/lib/private/Files/Utils/PathHelper.php @@ -37,6 +37,8 @@ class PathHelper { if ($path === '' or $path === '/') { return '/'; } + // No null bytes + $path = str_replace(chr(0), '', $path); //no windows style slashes $path = str_replace('\\', '/', $path); //add leading slash diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php index 40201d10b99..e9ed351b27b 100644 --- a/lib/private/Files/Utils/Scanner.php +++ b/lib/private/Files/Utils/Scanner.php @@ -23,11 +23,13 @@ use OCP\Files\Events\FileScannedEvent; use OCP\Files\Events\FolderScannedEvent; use OCP\Files\Events\NodeAddedToCache; use OCP\Files\Events\NodeRemovedFromCache; +use OCP\Files\Mount\IMountPoint; use OCP\Files\NotFoundException; use OCP\Files\Storage\IStorage; use OCP\Files\StorageNotAvailableException; use OCP\IDBConnection; use OCP\Lock\ILockingProvider; +use OCP\Lock\LockedException; use Psr\Log\LoggerInterface; /** @@ -85,7 +87,7 @@ class Scanner extends PublicEmitter { * get all storages for $dir * * @param string $dir - * @return \OC\Files\Mount\MountPoint[] + * @return array<string, IMountPoint> */ protected function getMounts($dir) { //TODO: move to the node based fileapi once that's done @@ -96,8 +98,9 @@ class Scanner extends PublicEmitter { $mounts = $mountManager->findIn($dir); $mounts[] = $mountManager->find($dir); $mounts = array_reverse($mounts); //start with the mount of $dir + $mountPoints = array_map(fn ($mount) => $mount->getMountPoint(), $mounts); - return $mounts; + return array_combine($mountPoints, $mounts); } /** @@ -210,6 +213,9 @@ class Scanner extends PublicEmitter { $owner = $owner['name'] ?? $ownerUid; $permissions = decoct(fileperms($fullPath)); throw new ForbiddenException("User folder $fullPath is not writable, folders is owned by $owner and has mode $permissions"); + } elseif (isset($mounts[$mount->getMountPoint() . $path . '/'])) { + // /<user>/files is overwritten by a mountpoint, so this check is irrelevant + break; } else { // if the root exists in neither the cache nor the storage the user isn't setup yet break 2; @@ -255,7 +261,15 @@ class Scanner extends PublicEmitter { try { $propagator = $storage->getPropagator(); $propagator->beginBatch(); - $scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE); + try { + $scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE); + } catch (LockedException $e) { + if (is_string($e->getReadablePath()) && str_starts_with($e->getReadablePath(), 'scanner::')) { + throw new LockedException("scanner::$dir", $e, $e->getExistingLock()); + } else { + throw $e; + } + } $cache = $storage->getCache(); if ($cache instanceof Cache) { // only re-calculate for the root folder we scanned, anything below that is taken care of by the scanner diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 66894e0c3cf..63eecf5e1d6 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -10,12 +10,14 @@ namespace OC\Files; use Icewind\Streams\CallbackWrapper; use OC\Files\Mount\MoveableMount; use OC\Files\Storage\Storage; +use OC\Files\Storage\Wrapper\Quota; use OC\Share\Share; use OC\User\LazyUser; use OC\User\Manager as UserManager; use OC\User\User; use OCA\Files_Sharing\SharedMount; use OCP\Constants; +use OCP\Files; use OCP\Files\Cache\ICacheEntry; use OCP\Files\ConnectionLostException; use OCP\Files\EmptyFileNameException; @@ -24,11 +26,13 @@ use OCP\Files\ForbiddenException; use OCP\Files\InvalidCharacterInPathException; use OCP\Files\InvalidDirectoryException; use OCP\Files\InvalidPathException; +use OCP\Files\Mount\IMountManager; use OCP\Files\Mount\IMountPoint; use OCP\Files\NotFoundException; use OCP\Files\ReservedWordException; use OCP\IUser; use OCP\IUserManager; +use OCP\L10N\IFactory; use OCP\Lock\ILockingProvider; use OCP\Lock\LockedException; use OCP\Server; @@ -605,13 +609,13 @@ class View { $this->lockFile($path, ILockingProvider::LOCK_SHARED); $exists = $this->file_exists($path); - $run = true; if ($this->shouldEmitHooks($path)) { + $run = true; $this->emit_file_hooks_pre($exists, $path, $run); - } - if (!$run) { - $this->unlockFile($path, ILockingProvider::LOCK_SHARED); - return false; + if (!$run) { + $this->unlockFile($path, ILockingProvider::LOCK_SHARED); + return false; + } } try { @@ -626,7 +630,7 @@ class View { [$storage, $internalPath] = $this->resolvePath($path); $target = $storage->fopen($internalPath, 'w'); if ($target) { - [, $result] = \OC_Helper::streamCopy($data, $target); + [, $result] = Files::streamCopy($data, $target, true); fclose($target); fclose($data); @@ -695,11 +699,14 @@ class View { * * @param string $source source path * @param string $target target path + * @param array $options * * @return bool|mixed * @throws LockedException */ - public function rename($source, $target) { + public function rename($source, $target, array $options = []) { + $checkSubMounts = $options['checkSubMounts'] ?? true; + $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($source)); $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($target)); @@ -707,6 +714,9 @@ class View { throw new ForbiddenException('Moving a folder into a child folder is forbidden', false); } + /** @var IMountManager $mountManager */ + $mountManager = \OC::$server->get(IMountManager::class); + $targetParts = explode('/', $absolutePath2); $targetUser = $targetParts[1] ?? null; $result = false; @@ -764,24 +774,28 @@ class View { try { $this->changeLock($target, ILockingProvider::LOCK_EXCLUSIVE, true); + if ($checkSubMounts) { + $movedMounts = $mountManager->findIn($this->getAbsolutePath($source)); + } else { + $movedMounts = []; + } + if ($internalPath1 === '') { - if ($mount1 instanceof MoveableMount) { - $sourceParentMount = $this->getMount(dirname($source)); - if ($sourceParentMount === $mount2 && $this->targetIsNotShared($targetUser, $absolutePath2)) { - /** - * @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1 - */ - $sourceMountPoint = $mount1->getMountPoint(); - $result = $mount1->moveMount($absolutePath2); - $manager->moveMount($sourceMountPoint, $mount1->getMountPoint()); - } else { - $result = false; - } - } else { - $result = false; - } + $sourceParentMount = $this->getMount(dirname($source)); + $movedMounts[] = $mount1; + $this->validateMountMove($movedMounts, $sourceParentMount, $mount2, !$this->targetIsNotShared($targetUser, $absolutePath2)); + /** + * @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1 + */ + $sourceMountPoint = $mount1->getMountPoint(); + $result = $mount1->moveMount($absolutePath2); + $manager->moveMount($sourceMountPoint, $mount1->getMountPoint()); + // moving a file/folder within the same mount point } elseif ($storage1 === $storage2) { + if (count($movedMounts) > 0) { + $this->validateMountMove($movedMounts, $mount1, $mount2, !$this->targetIsNotShared($targetUser, $absolutePath2)); + } if ($storage1) { $result = $storage1->rename($internalPath1, $internalPath2); } else { @@ -789,6 +803,9 @@ class View { } // moving a file/folder between storages (from $storage1 to $storage2) } else { + if (count($movedMounts) > 0) { + $this->validateMountMove($movedMounts, $mount1, $mount2, !$this->targetIsNotShared($targetUser, $absolutePath2)); + } $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2); } @@ -839,6 +856,56 @@ class View { } /** + * @throws ForbiddenException + */ + private function validateMountMove(array $mounts, IMountPoint $sourceMount, IMountPoint $targetMount, bool $targetIsShared): void { + $targetPath = $this->getRelativePath($targetMount->getMountPoint()); + if ($targetPath) { + $targetPath = trim($targetPath, '/'); + } else { + $targetPath = $targetMount->getMountPoint(); + } + + $l = \OC::$server->get(IFactory::class)->get('files'); + foreach ($mounts as $mount) { + $sourcePath = $this->getRelativePath($mount->getMountPoint()); + if ($sourcePath) { + $sourcePath = trim($sourcePath, '/'); + } else { + $sourcePath = $mount->getMountPoint(); + } + + if (!$mount instanceof MoveableMount) { + throw new ForbiddenException($l->t('Storage %s cannot be moved', [$sourcePath]), false); + } + + if ($targetIsShared) { + if ($sourceMount instanceof SharedMount) { + throw new ForbiddenException($l->t('Moving a share (%s) into a shared folder is not allowed', [$sourcePath]), false); + } else { + throw new ForbiddenException($l->t('Moving a storage (%s) into a shared folder is not allowed', [$sourcePath]), false); + } + } + + if ($sourceMount !== $targetMount) { + if ($sourceMount instanceof SharedMount) { + if ($targetMount instanceof SharedMount) { + throw new ForbiddenException($l->t('Moving a share (%s) into another share (%s) is not allowed', [$sourcePath, $targetPath]), false); + } else { + throw new ForbiddenException($l->t('Moving a share (%s) into another storage (%s) is not allowed', [$sourcePath, $targetPath]), false); + } + } else { + if ($targetMount instanceof SharedMount) { + throw new ForbiddenException($l->t('Moving a storage (%s) into a share (%s) is not allowed', [$sourcePath, $targetPath]), false); + } else { + throw new ForbiddenException($l->t('Moving a storage (%s) into another storage (%s) is not allowed', [$sourcePath, $targetPath]), false); + } + } + } + } + } + + /** * Copy a file/folder from the source path to target path * * @param string $source source path @@ -871,7 +938,7 @@ class View { try { $exists = $this->file_exists($target); - if ($this->shouldEmitHooks()) { + if ($this->shouldEmitHooks($target)) { \OC_Hook::emit( Filesystem::CLASSNAME, Filesystem::signal_copy, @@ -911,7 +978,7 @@ class View { $this->changeLock($target, ILockingProvider::LOCK_SHARED); $lockTypePath2 = ILockingProvider::LOCK_SHARED; - if ($this->shouldEmitHooks() && $result !== false) { + if ($this->shouldEmitHooks($target) && $result !== false) { \OC_Hook::emit( Filesystem::CLASSNAME, Filesystem::signal_post_copy, @@ -1401,8 +1468,7 @@ class View { public function addSubMounts(FileInfo $info, $extOnly = false): void { $mounts = Filesystem::getMountManager()->findIn($info->getPath()); $info->setSubMounts(array_filter($mounts, function (IMountPoint $mount) use ($extOnly) { - $subStorage = $mount->getStorage(); - return !($extOnly && $subStorage instanceof \OCA\Files_Sharing\SharedStorage); + return !($extOnly && $mount instanceof SharedMount); })); } @@ -1512,10 +1578,27 @@ class View { $entryName = substr($relativePath, 0, $pos); // Create parent folders if the mountpoint is inside a subfolder that doesn't exist yet - if (!isset($files[$entryName]) && $this->mkdir($path . '/' . $entryName) !== false) { - $info = $this->getFileInfo($path . '/' . $entryName); - if ($info !== false) { - $files[$entryName] = $info; + if (!isset($files[$entryName])) { + try { + [$storage, ] = $this->resolvePath($path . '/' . $entryName); + // make sure we can create the mountpoint folder, even if the user has a quota of 0 + if ($storage->instanceOfStorage(Quota::class)) { + $storage->enableQuota(false); + } + + if ($this->mkdir($path . '/' . $entryName) !== false) { + $info = $this->getFileInfo($path . '/' . $entryName); + if ($info !== false) { + $files[$entryName] = $info; + } + } + + if ($storage->instanceOfStorage(Quota::class)) { + $storage->enableQuota(true); + } + } catch (\Exception $e) { + // Creating the parent folder might not be possible, for example due to a lack of permissions. + $this->logger->debug('Failed to create non-existent parent', ['exception' => $e, 'path' => $path . '/' . $entryName]); } } @@ -1988,9 +2071,9 @@ class View { ); } } catch (LockedException $e) { - // rethrow with the a human-readable path + // rethrow with the human-readable path throw new LockedException( - $this->getPathRelativeToFiles($absolutePath), + $path, $e, $e->getExistingLock() ); @@ -2028,20 +2111,12 @@ class View { ); } } catch (LockedException $e) { - try { - // rethrow with the a human-readable path - throw new LockedException( - $this->getPathRelativeToFiles($absolutePath), - $e, - $e->getExistingLock() - ); - } catch (\InvalidArgumentException $ex) { - throw new LockedException( - $absolutePath, - $ex, - $e->getExistingLock() - ); - } + // rethrow with the a human-readable path + throw new LockedException( + $path, + $e, + $e->getExistingLock() + ); } return true; diff --git a/lib/private/FullTextSearch/FullTextSearchManager.php b/lib/private/FullTextSearch/FullTextSearchManager.php index 3ef8547ad3f..989da8d6bae 100644 --- a/lib/private/FullTextSearch/FullTextSearchManager.php +++ b/lib/private/FullTextSearch/FullTextSearchManager.php @@ -53,9 +53,9 @@ class FullTextSearchManager implements IFullTextSearchManager { * @since 16.0.0 */ public function isAvailable(): bool { - if ($this->indexService === null || - $this->providerService === null || - $this->searchService === null) { + if ($this->indexService === null + || $this->providerService === null + || $this->searchService === null) { return false; } diff --git a/lib/private/FullTextSearch/Model/IndexDocument.php b/lib/private/FullTextSearch/Model/IndexDocument.php index 8bd20bad1e0..a51447393ed 100644 --- a/lib/private/FullTextSearch/Model/IndexDocument.php +++ b/lib/private/FullTextSearch/Model/IndexDocument.php @@ -512,8 +512,8 @@ class IndexDocument implements IIndexDocument, JsonSerializable { * @since 16.0.0 */ final public function addExcerpt(string $source, string $excerpt): IIndexDocument { - $this->excerpts[] = - [ + $this->excerpts[] + = [ 'source' => $source, 'excerpt' => $this->cleanExcerpt($excerpt) ]; diff --git a/lib/private/GlobalScale/Config.php b/lib/private/GlobalScale/Config.php index 02acc1ab50a..2f729c2702e 100644 --- a/lib/private/GlobalScale/Config.php +++ b/lib/private/GlobalScale/Config.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Group/Group.php b/lib/private/Group/Group.php index 147c5baf543..6e42fad8b9f 100644 --- a/lib/private/Group/Group.php +++ b/lib/private/Group/Group.php @@ -377,7 +377,7 @@ class Group implements IGroup { */ public function hideFromCollaboration(): bool { return array_reduce($this->backends, function (bool $hide, GroupInterface $backend) { - return $hide | ($backend instanceof IHideFromCollaborationBackend && $backend->hideGroup($this->gid)); + return $hide || ($backend instanceof IHideFromCollaborationBackend && $backend->hideGroup($this->gid)); }, false); } } diff --git a/lib/private/Hooks/BasicEmitter.php b/lib/private/Hooks/BasicEmitter.php index c9444b40473..091334b71c8 100644 --- a/lib/private/Hooks/BasicEmitter.php +++ b/lib/private/Hooks/BasicEmitter.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Hooks/Emitter.php b/lib/private/Hooks/Emitter.php index 8a63ac9ed3a..86eb410860c 100644 --- a/lib/private/Hooks/Emitter.php +++ b/lib/private/Hooks/Emitter.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Hooks/EmitterTrait.php b/lib/private/Hooks/EmitterTrait.php index 8bffb6f7c3b..7b2ec4ad7fe 100644 --- a/lib/private/Hooks/EmitterTrait.php +++ b/lib/private/Hooks/EmitterTrait.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Hooks/PublicEmitter.php b/lib/private/Hooks/PublicEmitter.php index 042b616e264..77cb2bf30dd 100644 --- a/lib/private/Hooks/PublicEmitter.php +++ b/lib/private/Hooks/PublicEmitter.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Http/Client/Client.php b/lib/private/Http/Client/Client.php index c3f8f589827..553a8921a80 100644 --- a/lib/private/Http/Client/Client.php +++ b/lib/private/Http/Client/Client.php @@ -149,8 +149,8 @@ class Client implements IClient { } private function isLocalAddressAllowed(array $options) : bool { - if (($options['nextcloud']['allow_local_address'] ?? false) || - $this->config->getSystemValueBool('allow_local_remote_servers', false)) { + if (($options['nextcloud']['allow_local_address'] ?? false) + || $this->config->getSystemValueBool('allow_local_remote_servers', false)) { return true; } diff --git a/lib/private/Http/Client/Response.php b/lib/private/Http/Client/Response.php index adf83306d07..1e4cb3b8fa2 100644 --- a/lib/private/Http/Client/Response.php +++ b/lib/private/Http/Client/Response.php @@ -11,49 +11,25 @@ namespace OC\Http\Client; use OCP\Http\Client\IResponse; use Psr\Http\Message\ResponseInterface; -/** - * Class Response - * - * @package OC\Http - */ class Response implements IResponse { - /** @var ResponseInterface */ - private $response; - - /** - * @var bool - */ - private $stream; + private ResponseInterface $response; + private bool $stream; - /** - * @param ResponseInterface $response - * @param bool $stream - */ - public function __construct(ResponseInterface $response, $stream = false) { + public function __construct(ResponseInterface $response, bool $stream = false) { $this->response = $response; $this->stream = $stream; } - /** - * @return string|resource - */ public function getBody() { - return $this->stream ? - $this->response->getBody()->detach(): - $this->response->getBody()->getContents(); + return $this->stream + ? $this->response->getBody()->detach() + :$this->response->getBody()->getContents(); } - /** - * @return int - */ public function getStatusCode(): int { return $this->response->getStatusCode(); } - /** - * @param string $key - * @return string - */ public function getHeader(string $key): string { $headers = $this->response->getHeader($key); @@ -64,9 +40,6 @@ class Response implements IResponse { return $headers[0]; } - /** - * @return array - */ public function getHeaders(): array { return $this->response->getHeaders(); } diff --git a/lib/private/Image.php b/lib/private/Image.php index 3dd0bc49662..3b8cb79c853 100644 --- a/lib/private/Image.php +++ b/lib/private/Image.php @@ -56,7 +56,7 @@ class Image implements IImage { $this->appConfig = $appConfig ?? Server::get(IAppConfig::class); $this->config = $config ?? Server::get(IConfig::class); - if (\OC_Util::fileInfoLoaded()) { + if (class_exists(finfo::class)) { $this->fileInfo = new finfo(FILEINFO_MIME_TYPE); } } @@ -699,11 +699,11 @@ class Image implements IImage { fclose($fp); unset($fp); - $headerFormat = 'A4Riff/' . // get n string - 'I1Filesize/' . // get integer (file size but not actual size) - 'A4Webp/' . // get n string - 'A4Vp/' . // get n string - 'A74Chunk'; + $headerFormat = 'A4Riff/' // get n string + . 'I1Filesize/' // get integer (file size but not actual size) + . 'A4Webp/' // get n string + . 'A4Vp/' // get n string + . 'A74Chunk'; $header = unpack($headerFormat, $data); unset($data, $headerFormat); diff --git a/lib/private/Installer.php b/lib/private/Installer.php index 00fdd84c1bc..3bbef3252f4 100644 --- a/lib/private/Installer.php +++ b/lib/private/Installer.php @@ -10,20 +10,23 @@ declare(strict_types=1); namespace OC; use Doctrine\DBAL\Exception\TableExistsException; +use OC\App\AppStore\AppNotFoundException; use OC\App\AppStore\Bundles\Bundle; use OC\App\AppStore\Fetcher\AppFetcher; use OC\AppFramework\Bootstrap\Coordinator; use OC\Archive\TAR; use OC\DB\Connection; use OC\DB\MigrationService; +use OC\Files\FilenameValidator; use OC_App; -use OC_Helper; use OCP\App\IAppManager; +use OCP\Files; use OCP\HintException; use OCP\Http\Client\IClientService; use OCP\IConfig; use OCP\ITempManager; use OCP\Migration\IOutput; +use OCP\Server; use phpseclib\File\X509; use Psr\Log\LoggerInterface; @@ -172,6 +175,7 @@ class Installer { * @param string $appId * @param bool [$allowUnstable] * + * @throws AppNotFoundException If the app is not found on the appstore * @throws \Exception If the installation was not successful */ public function downloadApp(string $appId, bool $allowUnstable = false): void { @@ -241,6 +245,10 @@ class Installer { // Download the release $tempFile = $this->tempManager->getTemporaryFile('.tar.gz'); + if ($tempFile === false) { + throw new \RuntimeException('Could not create temporary file for downloading app archive.'); + } + $timeout = $this->isCLI ? 0 : 120; $client = $this->clientService->newClient(); $client->get($app['releases'][0]['download'], ['sink' => $tempFile, 'timeout' => $timeout]); @@ -252,8 +260,11 @@ class Installer { if ($verified === true) { // Seems to match, let's proceed $extractDir = $this->tempManager->getTemporaryFolder(); - $archive = new TAR($tempFile); + if ($extractDir === false) { + throw new \RuntimeException('Could not create temporary directory for unpacking app.'); + } + $archive = new TAR($tempFile); if (!$archive->extract($extractDir)) { $errorMessage = 'Could not extract app ' . $appId; @@ -324,14 +335,17 @@ class Installer { $baseDir = OC_App::getInstallPath() . '/' . $appId; // Remove old app with the ID if existent - OC_Helper::rmdirr($baseDir); + Files::rmdirr($baseDir); // Move to app folder if (@mkdir($baseDir)) { $extractDir .= '/' . $folders[0]; - OC_Helper::copyr($extractDir, $baseDir); } - OC_Helper::copyr($extractDir, $baseDir); - OC_Helper::rmdirr($extractDir); + // otherwise we just copy the outer directory + $this->copyRecursive($extractDir, $baseDir); + Files::rmdirr($extractDir); + if (function_exists('opcache_reset')) { + opcache_reset(); + } return; } // Signature does not match @@ -344,9 +358,9 @@ class Installer { } } - throw new \Exception( + throw new AppNotFoundException( sprintf( - 'Could not download app %s', + 'Could not download app %s, it was not found on the appstore', $appId ) ); @@ -450,7 +464,7 @@ class Installer { return false; } $appDir = OC_App::getInstallPath() . '/' . $appId; - OC_Helper::rmdirr($appDir); + Files::rmdirr($appDir); return true; } else { $this->logger->error('can\'t remove app ' . $appId . '. It is not installed.'); @@ -587,4 +601,33 @@ class Installer { include $script; } } + + /** + * Recursive copying of local folders. + * + * @param string $src source folder + * @param string $dest target folder + */ + private function copyRecursive(string $src, string $dest): void { + if (!file_exists($src)) { + return; + } + + if (is_dir($src)) { + if (!is_dir($dest)) { + mkdir($dest); + } + $files = scandir($src); + foreach ($files as $file) { + if ($file != '.' && $file != '..') { + $this->copyRecursive("$src/$file", "$dest/$file"); + } + } + } else { + $validator = Server::get(FilenameValidator::class); + if (!$validator->isForbidden($src)) { + copy($src, $dest); + } + } + } } diff --git a/lib/private/IntegrityCheck/Checker.php b/lib/private/IntegrityCheck/Checker.php index 3a24e8632de..2bd6e426b79 100644 --- a/lib/private/IntegrityCheck/Checker.php +++ b/lib/private/IntegrityCheck/Checker.php @@ -148,10 +148,10 @@ class Checker { } if ($filename === $this->environmentHelper->getServerRoot() . '/core/js/mimetypelist.js') { $oldMimetypeList = new GenerateMimetypeFileBuilder(); - $newFile = $oldMimetypeList->generateFile($this->mimeTypeDetector->getAllAliases()); + $newFile = $oldMimetypeList->generateFile($this->mimeTypeDetector->getAllAliases(), $this->mimeTypeDetector->getAllNamings()); $oldFile = $this->fileAccessHelper->file_get_contents($filename); if ($newFile === $oldFile) { - $hashes[$relativeFileName] = hash('sha512', $oldMimetypeList->generateFile($this->mimeTypeDetector->getOnlyDefaultAliases())); + $hashes[$relativeFileName] = hash('sha512', $oldMimetypeList->generateFile($this->mimeTypeDetector->getOnlyDefaultAliases(), $this->mimeTypeDetector->getAllNamings())); continue; } } @@ -335,8 +335,8 @@ class Checker { // Compare the list of files which are not identical $currentInstanceHashes = $this->generateHashes($this->getFolderIterator($basePath), $basePath); - $differencesA = array_diff($expectedHashes, $currentInstanceHashes); - $differencesB = array_diff($currentInstanceHashes, $expectedHashes); + $differencesA = array_diff_assoc($expectedHashes, $currentInstanceHashes); + $differencesB = array_diff_assoc($currentInstanceHashes, $expectedHashes); $differences = array_unique(array_merge($differencesA, $differencesB)); $differenceArray = []; foreach ($differences as $filename => $hash) { diff --git a/lib/private/L10N/Factory.php b/lib/private/L10N/Factory.php index eb84f264f5f..6a747744829 100644 --- a/lib/private/L10N/Factory.php +++ b/lib/private/L10N/Factory.php @@ -108,9 +108,7 @@ class Factory implements IFactory { $locale = $forceLocale; } - if ($lang === null || !$this->languageExists($app, $lang)) { - $lang = $this->findLanguage($app); - } + $lang = $this->validateLanguage($app, $lang); if ($locale === null || !$this->localeExists($locale)) { $locale = $this->findLocale($lang); @@ -131,6 +129,29 @@ class Factory implements IFactory { } /** + * Check that $lang is an existing language and not null, otherwise return the language to use instead + * + * @psalm-taint-escape callable + * @psalm-taint-escape cookie + * @psalm-taint-escape file + * @psalm-taint-escape has_quotes + * @psalm-taint-escape header + * @psalm-taint-escape html + * @psalm-taint-escape include + * @psalm-taint-escape ldap + * @psalm-taint-escape shell + * @psalm-taint-escape sql + * @psalm-taint-escape unserialize + */ + private function validateLanguage(string $app, ?string $lang): string { + if ($lang === null || !$this->languageExists($app, $lang)) { + return $this->findLanguage($app); + } else { + return $lang; + } + } + + /** * Find the best language * * @param string|null $appId App id or null for core @@ -416,8 +437,8 @@ class Factory implements IFactory { } // Use language from request - if ($this->userSession->getUser() instanceof IUser && - $user->getUID() === $this->userSession->getUser()->getUID()) { + if ($this->userSession->getUser() instanceof IUser + && $user->getUID() === $this->userSession->getUser()->getUID()) { try { return $this->getLanguageFromRequest(); } catch (LanguageNotFoundException $e) { @@ -496,10 +517,10 @@ class Factory implements IFactory { // use formal version of german ("Sie" instead of "Du") if the default // language is set to 'de_DE' if possible if ( - is_string($defaultLanguage) && - strtolower($lang) === 'de' && - strtolower($defaultLanguage) === 'de_de' && - $this->languageExists($app, 'de_DE') + is_string($defaultLanguage) + && strtolower($lang) === 'de' + && strtolower($defaultLanguage) === 'de_de' + && $this->languageExists($app, 'de_DE') ) { $result = 'de_DE'; } diff --git a/lib/private/L10N/LanguageNotFoundException.php b/lib/private/L10N/LanguageNotFoundException.php index 31b08b2ec14..087a384e00e 100644 --- a/lib/private/L10N/LanguageNotFoundException.php +++ b/lib/private/L10N/LanguageNotFoundException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/LargeFileHelper.php b/lib/private/LargeFileHelper.php index 238fb0790b8..fa4c72da756 100755 --- a/lib/private/LargeFileHelper.php +++ b/lib/private/LargeFileHelper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Lockdown/Filesystem/NullCache.php b/lib/private/Lockdown/Filesystem/NullCache.php index e84ff40e00c..5a27c5d5c6e 100644 --- a/lib/private/Lockdown/Filesystem/NullCache.php +++ b/lib/private/Lockdown/Filesystem/NullCache.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -21,20 +22,23 @@ class NullCache implements ICache { } public function get($file) { - return $file !== '' ? null : - new CacheEntry([ - 'fileid' => -1, - 'parent' => -1, - 'name' => '', - 'path' => '', - 'size' => '0', - 'mtime' => time(), - 'storage_mtime' => time(), - 'etag' => '', - 'mimetype' => FileInfo::MIMETYPE_FOLDER, - 'mimepart' => 'httpd', - 'permissions' => Constants::PERMISSION_READ - ]); + if ($file !== '') { + return false; + } + + return new CacheEntry([ + 'fileid' => -1, + 'parent' => -1, + 'name' => '', + 'path' => '', + 'size' => '0', + 'mtime' => time(), + 'storage_mtime' => time(), + 'etag' => '', + 'mimetype' => FileInfo::MIMETYPE_FOLDER, + 'mimepart' => 'httpd', + 'permissions' => Constants::PERMISSION_READ + ]); } public function getFolderContents($folder) { diff --git a/lib/private/Lockdown/Filesystem/NullStorage.php b/lib/private/Lockdown/Filesystem/NullStorage.php index 967f8b5108e..71a40d8da1e 100644 --- a/lib/private/Lockdown/Filesystem/NullStorage.php +++ b/lib/private/Lockdown/Filesystem/NullStorage.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Lockdown/LockdownManager.php b/lib/private/Lockdown/LockdownManager.php index 3b45709d5c9..4f351812bad 100644 --- a/lib/private/Lockdown/LockdownManager.php +++ b/lib/private/Lockdown/LockdownManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Log.php b/lib/private/Log.php index 98de9bfa858..301a25d12c1 100644 --- a/lib/private/Log.php +++ b/lib/private/Log.php @@ -37,6 +37,7 @@ use function strtr; class Log implements ILogger, IDataLogger { private ?bool $logConditionSatisfied = null; private ?IEventDispatcher $eventDispatcher = null; + private int $nestingLevel = 0; public function __construct( private IWriter $logger, @@ -192,6 +193,11 @@ class Log implements ILogger, IDataLogger { } public function getLogLevel(array $context, string $message): int { + if ($this->nestingLevel > 1) { + return ILogger::WARN; + } + + $this->nestingLevel++; /** * @psalm-var array{ * shared_secret?: string, @@ -242,6 +248,7 @@ class Log implements ILogger, IDataLogger { // if log condition is satisfied change the required log level to DEBUG if ($this->logConditionSatisfied) { + $this->nestingLevel--; return ILogger::DEBUG; } @@ -256,6 +263,7 @@ class Log implements ILogger, IDataLogger { * once this is met -> change the required log level to debug */ if (in_array($context['app'], $logCondition['apps'] ?? [], true)) { + $this->nestingLevel--; return ILogger::DEBUG; } } @@ -263,11 +271,13 @@ class Log implements ILogger, IDataLogger { if (!isset($logCondition['matches'])) { $configLogLevel = $this->config->getValue('loglevel', ILogger::WARN); if (is_numeric($configLogLevel)) { + $this->nestingLevel--; return min((int)$configLogLevel, ILogger::FATAL); } // Invalid configuration, warn the user and fall back to default level of WARN error_log('Nextcloud configuration: "loglevel" is not a valid integer'); + $this->nestingLevel--; return ILogger::WARN; } @@ -281,21 +291,24 @@ class Log implements ILogger, IDataLogger { if (!isset($option['apps']) && !isset($option['loglevel']) && !isset($option['message'])) { /* Only user and/or secret are listed as conditions, we can cache the result for the rest of the request */ $this->logConditionSatisfied = true; + $this->nestingLevel--; return ILogger::DEBUG; } + $this->nestingLevel--; return $option['loglevel'] ?? ILogger::DEBUG; } } + $this->nestingLevel--; return ILogger::WARN; } protected function checkLogSecret(string $conditionSecret): bool { $request = \OCP\Server::get(IRequest::class); - if ($request->getMethod() === 'PUT' && - !str_contains($request->getHeader('Content-Type'), 'application/x-www-form-urlencoded') && - !str_contains($request->getHeader('Content-Type'), 'application/json')) { + if ($request->getMethod() === 'PUT' + && !str_contains($request->getHeader('Content-Type'), 'application/x-www-form-urlencoded') + && !str_contains($request->getHeader('Content-Type'), 'application/json')) { return hash_equals($conditionSecret, ''); } diff --git a/lib/private/Log/ErrorHandler.php b/lib/private/Log/ErrorHandler.php index e1faf336118..6597274a868 100644 --- a/lib/private/Log/ErrorHandler.php +++ b/lib/private/Log/ErrorHandler.php @@ -72,9 +72,9 @@ class ErrorHandler { private static function errnoToLogLevel(int $errno): int { return match ($errno) { - E_USER_WARNING => ILogger::WARN, + E_WARNING, E_USER_WARNING => ILogger::WARN, E_DEPRECATED, E_USER_DEPRECATED => ILogger::DEBUG, - E_USER_NOTICE => ILogger::INFO, + E_NOTICE, E_USER_NOTICE => ILogger::INFO, default => ILogger::ERROR, }; } diff --git a/lib/private/Log/ExceptionSerializer.php b/lib/private/Log/ExceptionSerializer.php index 6d94bf51f45..af7c9e48435 100644 --- a/lib/private/Log/ExceptionSerializer.php +++ b/lib/private/Log/ExceptionSerializer.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Log/LogDetails.php b/lib/private/Log/LogDetails.php index bd18eb983db..6063b25cef9 100644 --- a/lib/private/Log/LogDetails.php +++ b/lib/private/Log/LogDetails.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -37,7 +38,7 @@ abstract class LogDetails { $url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--'; $method = is_string($request->getMethod()) ? $request->getMethod() : '--'; if ($this->config->getValue('installed', false)) { - $user = \OC_User::getUser() ?? '--'; + $user = \OC_User::getUser() ?: '--'; } else { $user = '--'; } @@ -59,6 +60,10 @@ abstract class LogDetails { 'userAgent', 'version' ); + $clientReqId = $request->getHeader('X-Request-Id'); + if ($clientReqId !== '') { + $entry['clientReqId'] = $clientReqId; + } if (is_array($message)) { // Exception messages are extracted and the exception is put into a separate field diff --git a/lib/private/Log/LogFactory.php b/lib/private/Log/LogFactory.php index bbe77de198c..ee6054b81f8 100644 --- a/lib/private/Log/LogFactory.php +++ b/lib/private/Log/LogFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Log/Rotate.php b/lib/private/Log/Rotate.php index 839c40726b7..ee1593b87ac 100644 --- a/lib/private/Log/Rotate.php +++ b/lib/private/Log/Rotate.php @@ -7,6 +7,8 @@ */ namespace OC\Log; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\BackgroundJob\TimedJob; use OCP\IConfig; use OCP\Log\RotationTrait; use Psr\Log\LoggerInterface; @@ -17,9 +19,15 @@ use Psr\Log\LoggerInterface; * For more professional log management set the 'logfile' config to a different * location and manage that with your own tools. */ -class Rotate extends \OCP\BackgroundJob\Job { +class Rotate extends TimedJob { use RotationTrait; + public function __construct(ITimeFactory $time) { + parent::__construct($time); + + $this->setInterval(3600); + } + public function run($argument): void { $config = \OCP\Server::get(IConfig::class); $this->filePath = $config->getSystemValueString('logfile', $config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log'); diff --git a/lib/private/Log/Syslog.php b/lib/private/Log/Syslog.php index bd2c39509b1..46214599eb8 100644 --- a/lib/private/Log/Syslog.php +++ b/lib/private/Log/Syslog.php @@ -20,15 +20,18 @@ class Syslog extends LogDetails implements IWriter { ILogger::FATAL => LOG_CRIT, ]; + private string $tag; + public function __construct( SystemConfig $config, ?string $tag = null, ) { parent::__construct($config); if ($tag === null) { - $tag = $config->getValue('syslog_tag', 'Nextcloud'); + $this->tag = $config->getValue('syslog_tag', 'Nextcloud'); + } else { + $this->tag = $tag; } - openlog($tag, LOG_PID | LOG_CONS, LOG_USER); } public function __destruct() { @@ -41,6 +44,7 @@ class Syslog extends LogDetails implements IWriter { */ public function write(string $app, $message, int $level): void { $syslog_level = $this->levels[$level]; + openlog($this->tag, LOG_PID | LOG_CONS, LOG_USER); syslog($syslog_level, $this->logDetailsAsJSON($app, $message, $level)); } } diff --git a/lib/private/Log/Systemdlog.php b/lib/private/Log/Systemdlog.php index 46de0f7db97..ffea0511732 100644 --- a/lib/private/Log/Systemdlog.php +++ b/lib/private/Log/Systemdlog.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Mail/EMailTemplate.php b/lib/private/Mail/EMailTemplate.php index 2cb222fd137..1d19f00b0a1 100644 --- a/lib/private/Mail/EMailTemplate.php +++ b/lib/private/Mail/EMailTemplate.php @@ -523,7 +523,7 @@ EOF; $this->ensureBodyListClosed(); $color = $this->themingDefaults->getDefaultColorPrimary(); - $textColor = $this->themingDefaults->getTextColorPrimary(); + $textColor = $this->themingDefaults->getDefaultTextColorPrimary(); $this->htmlBody .= vsprintf($this->buttonGroup, [$color, $color, $urlLeft, $color, $textColor, $textColor, $textLeft, $urlRight, $textRight]); $this->plainBody .= PHP_EOL . $plainTextLeft . ': ' . $urlLeft . PHP_EOL; @@ -554,7 +554,7 @@ EOF; } $color = $this->themingDefaults->getDefaultColorPrimary(); - $textColor = $this->themingDefaults->getTextColorPrimary(); + $textColor = $this->themingDefaults->getDefaultTextColorPrimary(); $this->htmlBody .= vsprintf($this->button, [$color, $color, $url, $color, $textColor, $textColor, $text]); if ($plainText !== false) { diff --git a/lib/private/Mail/Mailer.php b/lib/private/Mail/Mailer.php index 18636e183d0..bdc4d6760e0 100644 --- a/lib/private/Mail/Mailer.php +++ b/lib/private/Mail/Mailer.php @@ -232,9 +232,6 @@ class Mailer implements IMailer { } /** - * @deprecated 26.0.0 Implicit validation is done in \OC\Mail\Message::setRecipients - * via \Symfony\Component\Mime\Address::__construct - * * @param string $email Email address to be validated * @return bool True if the mail address is valid, false otherwise */ diff --git a/lib/private/Mail/Message.php b/lib/private/Mail/Message.php index faeba469e20..523a4836760 100644 --- a/lib/private/Mail/Message.php +++ b/lib/private/Mail/Message.php @@ -316,7 +316,7 @@ class Message implements IMessage { public function getAutoSubmitted(): string { $headers = $this->symfonyEmail->getHeaders(); - return $headers->has(AutoSubmitted::HEADER) ? - $headers->get(AutoSubmitted::HEADER)->getBodyAsString() : AutoSubmitted::VALUE_NO; + return $headers->has(AutoSubmitted::HEADER) + ? $headers->get(AutoSubmitted::HEADER)->getBodyAsString() : AutoSubmitted::VALUE_NO; } } diff --git a/lib/private/Mail/Provider/Manager.php b/lib/private/Mail/Provider/Manager.php index 61791620198..f162d30b834 100644 --- a/lib/private/Mail/Provider/Manager.php +++ b/lib/private/Mail/Provider/Manager.php @@ -17,7 +17,7 @@ use Psr\Log\LoggerInterface; use Throwable; class Manager implements IManager { - + protected ?array $providersCollection = null; public function __construct( @@ -63,7 +63,7 @@ class Manager implements IManager { * @return array<string,string> collection of provider id and label ['jmap' => 'JMap Connector'] */ public function types(): array { - + // construct types collection $types = []; // extract id and name from providers collection @@ -72,7 +72,7 @@ class Manager implements IManager { } // return types collection return $types; - + } /** @@ -131,7 +131,7 @@ class Manager implements IManager { if (!is_array($this->providersCollection)) { $this->providers(); } - + if (isset($this->providersCollection[$providerId])) { return $this->providersCollection[$providerId]; } @@ -150,7 +150,7 @@ class Manager implements IManager { * @return array<string,array<string,IService>> collection of provider id, service id and object ['jmap' => ['Service1' => IServiceObject]] */ public function services(string $userId): array { - + // initilize collection $services = []; // retrieve and iterate through mail providers @@ -164,7 +164,7 @@ class Manager implements IManager { } // return collection return $services; - + } /** @@ -179,7 +179,7 @@ class Manager implements IManager { * @return IService|null returns service object or null if none found */ public function findServiceById(string $userId, string $serviceId, ?string $providerId = null): ?IService { - + // evaluate if provider id was specified if ($providerId !== null) { // find provider @@ -204,7 +204,7 @@ class Manager implements IManager { } } } - + // return null if no match was found return null; @@ -223,7 +223,7 @@ class Manager implements IManager { * @return IService|null returns service object or null if none found */ public function findServiceByAddress(string $userId, string $address, ?string $providerId = null): ?IService { - + // evaluate if provider id was specified if ($providerId !== null) { // find provider diff --git a/lib/private/Memcache/APCu.php b/lib/private/Memcache/APCu.php index 024462d227b..937f8a863ab 100644 --- a/lib/private/Memcache/APCu.php +++ b/lib/private/Memcache/APCu.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Memcache/ArrayCache.php b/lib/private/Memcache/ArrayCache.php index 4cac60c272c..9b3540b771f 100644 --- a/lib/private/Memcache/ArrayCache.php +++ b/lib/private/Memcache/ArrayCache.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Memcache/CADTrait.php b/lib/private/Memcache/CADTrait.php index 3bf94246338..d0f6611c4f3 100644 --- a/lib/private/Memcache/CADTrait.php +++ b/lib/private/Memcache/CADTrait.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Memcache/CASTrait.php b/lib/private/Memcache/CASTrait.php index 945f1539f99..8c2d2a46b19 100644 --- a/lib/private/Memcache/CASTrait.php +++ b/lib/private/Memcache/CASTrait.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Memcache/Cache.php b/lib/private/Memcache/Cache.php index 2a2a6e2a23f..774769b25fe 100644 --- a/lib/private/Memcache/Cache.php +++ b/lib/private/Memcache/Cache.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Memcache/Factory.php b/lib/private/Memcache/Factory.php index a44f0127651..b54189937fc 100644 --- a/lib/private/Memcache/Factory.php +++ b/lib/private/Memcache/Factory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -134,8 +135,8 @@ class Factory implements ICacheFactory { $this->profiler->add($cache); } - if ($this->lockingCacheClass === Redis::class && - $this->logFile !== '' && is_writable(dirname($this->logFile)) && (!file_exists($this->logFile) || is_writable($this->logFile))) { + if ($this->lockingCacheClass === Redis::class + && $this->logFile !== '' && is_writable(dirname($this->logFile)) && (!file_exists($this->logFile) || is_writable($this->logFile))) { $cache = new LoggerWrapperCache($cache, $this->logFile); } return $cache; diff --git a/lib/private/Memcache/Memcached.php b/lib/private/Memcache/Memcached.php index 620013feda6..d8b624a978a 100644 --- a/lib/private/Memcache/Memcached.php +++ b/lib/private/Memcache/Memcached.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -48,8 +49,8 @@ class Memcached extends Cache implements IMemcache { * @psalm-suppress TypeDoesNotContainType */ if (\Memcached::HAVE_IGBINARY) { - $defaultOptions[\Memcached::OPT_SERIALIZER] = - \Memcached::SERIALIZER_IGBINARY; + $defaultOptions[\Memcached::OPT_SERIALIZER] + = \Memcached::SERIALIZER_IGBINARY; } $options = \OC::$server->getConfig()->getSystemValue('memcached_options', []); if (is_array($options)) { diff --git a/lib/private/Memcache/NullCache.php b/lib/private/Memcache/NullCache.php index b667869bf0d..eac1e6ddadc 100644 --- a/lib/private/Memcache/NullCache.php +++ b/lib/private/Memcache/NullCache.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Memcache/Redis.php b/lib/private/Memcache/Redis.php index 711531e0ac2..f8c51570c4f 100644 --- a/lib/private/Memcache/Redis.php +++ b/lib/private/Memcache/Redis.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Migration/BackgroundRepair.php b/lib/private/Migration/BackgroundRepair.php index cbc21e4fe12..d542b82d5e1 100644 --- a/lib/private/Migration/BackgroundRepair.php +++ b/lib/private/Migration/BackgroundRepair.php @@ -7,9 +7,8 @@ */ namespace OC\Migration; -use OC\NeedsUpdateException; use OC\Repair; -use OC_App; +use OCP\App\IAppManager; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; use OCP\BackgroundJob\TimedJob; @@ -26,6 +25,7 @@ class BackgroundRepair extends TimedJob { ITimeFactory $time, private LoggerInterface $logger, private IJobList $jobList, + private IAppManager $appManager, ) { parent::__construct($time); $this->setInterval(15 * 60); @@ -34,7 +34,6 @@ class BackgroundRepair extends TimedJob { /** * @param array $argument * @throws \Exception - * @throws \OC\NeedsUpdateException */ protected function run($argument): void { if (!isset($argument['app']) || !isset($argument['step'])) { @@ -44,13 +43,7 @@ class BackgroundRepair extends TimedJob { } $app = $argument['app']; - try { - $this->loadApp($app); - } catch (NeedsUpdateException $ex) { - // as long as the app is not yet done with it's offline migration - // we better not start with the live migration - return; - } + $this->appManager->loadApp($app); $step = $argument['step']; $this->repair->setRepairSteps([]); @@ -73,13 +66,4 @@ class BackgroundRepair extends TimedJob { // remove the job once executed successfully $this->jobList->remove($this, $this->argument); } - - /** - * @codeCoverageIgnore - * @param $app - * @throws NeedsUpdateException - */ - protected function loadApp($app): void { - OC_App::loadApp($app); - } } diff --git a/lib/private/Migration/ConsoleOutput.php b/lib/private/Migration/ConsoleOutput.php index 7ccc4e7825a..31412bf4ff0 100644 --- a/lib/private/Migration/ConsoleOutput.php +++ b/lib/private/Migration/ConsoleOutput.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2015 ownCloud GmbH diff --git a/lib/private/Migration/MetadataManager.php b/lib/private/Migration/MetadataManager.php index fac9127a123..f4cb95342b4 100644 --- a/lib/private/Migration/MetadataManager.php +++ b/lib/private/Migration/MetadataManager.php @@ -73,7 +73,7 @@ class MetadataManager { ): array { $appsAttributes = []; foreach (array_keys($metadata['apps']) as $appId) { - if ($filterKnownMigrations && !$this->appManager->isInstalled($appId)) { + if ($filterKnownMigrations && !$this->appManager->isEnabledForAnyone($appId)) { continue; // if not interested and app is not installed } @@ -97,7 +97,7 @@ class MetadataManager { * @since 30.0.0 */ public function getUnsupportedApps(array $metadata): array { - return array_values(array_diff($this->appManager->getInstalledApps(), array_keys($metadata['apps']))); + return array_values(array_diff($this->appManager->getEnabledApps(), array_keys($metadata['apps']))); } /** diff --git a/lib/private/Migration/NullOutput.php b/lib/private/Migration/NullOutput.php index 3f4cc38dba8..8db7b950af8 100644 --- a/lib/private/Migration/NullOutput.php +++ b/lib/private/Migration/NullOutput.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-only diff --git a/lib/private/Migration/SimpleOutput.php b/lib/private/Migration/SimpleOutput.php index 31420d49932..b7a07cc6ff2 100644 --- a/lib/private/Migration/SimpleOutput.php +++ b/lib/private/Migration/SimpleOutput.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2015 ownCloud GmbH diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php index f341c6d3094..fb0795376bb 100644 --- a/lib/private/NavigationManager.php +++ b/lib/private/NavigationManager.php @@ -11,6 +11,7 @@ use InvalidArgumentException; use OC\App\AppManager; use OC\Group\Manager; use OCP\App\IAppManager; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IConfig; use OCP\IGroupManager; use OCP\INavigationManager; @@ -18,6 +19,7 @@ use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserSession; use OCP\L10N\IFactory; +use OCP\Navigation\Events\LoadAdditionalEntriesEvent; use Psr\Log\LoggerInterface; /** @@ -56,6 +58,7 @@ class NavigationManager implements INavigationManager { IGroupManager $groupManager, IConfig $config, LoggerInterface $logger, + protected IEventDispatcher $eventDispatcher, ) { $this->appManager = $appManager; $this->urlGenerator = $urlGenerator; @@ -74,7 +77,7 @@ class NavigationManager implements INavigationManager { $this->closureEntries[] = $entry; return; } - $this->init(); + $this->init(false); $id = $entry['id']; @@ -107,9 +110,10 @@ class NavigationManager implements INavigationManager { } private function updateDefaultEntries() { + $defaultEntryId = $this->getDefaultEntryIdForUser($this->userSession->getUser(), false); foreach ($this->entries as $id => $entry) { if ($entry['type'] === 'link') { - $this->entries[$id]['default'] = $id === $this->getDefaultEntryIdForUser($this->userSession->getUser(), false); + $this->entries[$id]['default'] = $id === $defaultEntryId; } } } @@ -119,10 +123,6 @@ class NavigationManager implements INavigationManager { */ public function getAll(string $type = 'link'): array { $this->init(); - foreach ($this->closureEntries as $c) { - $this->add($c()); - } - $this->closureEntries = []; $result = $this->entries; if ($type !== 'all') { @@ -208,7 +208,13 @@ class NavigationManager implements INavigationManager { return $this->activeEntry; } - private function init() { + private function init(bool $resolveClosures = true): void { + if ($resolveClosures) { + while ($c = array_pop($this->closureEntries)) { + $this->add($c()); + } + } + if ($this->init) { return; } @@ -318,13 +324,14 @@ class NavigationManager implements INavigationManager { ]); } } + $this->eventDispatcher->dispatchTyped(new LoadAdditionalEntriesEvent()); if ($this->userSession->isLoggedIn()) { $user = $this->userSession->getUser(); $apps = $this->appManager->getEnabledAppsForUser($user); $this->customAppOrder = json_decode($this->config->getUserValue($user->getUID(), 'core', 'apporder', '[]'), true, flags:JSON_THROW_ON_ERROR); } else { - $apps = $this->appManager->getInstalledApps(); + $apps = $this->appManager->getEnabledApps(); $this->customAppOrder = []; } @@ -415,11 +422,6 @@ class NavigationManager implements INavigationManager { public function get(string $id): ?array { $this->init(); - foreach ($this->closureEntries as $c) { - $this->add($c()); - } - $this->closureEntries = []; - return $this->entries[$id]; } diff --git a/lib/private/Notification/Manager.php b/lib/private/Notification/Manager.php index ac287e97048..8c457db8beb 100644 --- a/lib/private/Notification/Manager.php +++ b/lib/private/Notification/Manager.php @@ -74,7 +74,15 @@ class Manager implements IManager { * @since 17.0.0 */ public function registerApp(string $appClass): void { - $this->appClasses[] = $appClass; + // other apps may want to rely on the 'main' notification app so make it deterministic that + // the 'main' notification app adds it's notifications first and removes it's notifications last + if ($appClass === \OCA\Notifications\App::class) { + // add 'main' notifications app to start of internal list of apps + array_unshift($this->appClasses, $appClass); + } else { + // add app to end of internal list of apps + $this->appClasses[] = $appClass; + } } /** @@ -209,7 +217,9 @@ class Manager implements IManager { * @since 8.2.0 */ public function hasNotifiers(): bool { - return !empty($this->notifiers) || !empty($this->notifierClasses); + return !empty($this->notifiers) + || !empty($this->notifierClasses) + || (!$this->parsedRegistrationContext && !empty($this->coordinator->getRegistrationContext()->getNotifierServices())); } /** @@ -237,7 +247,7 @@ class Manager implements IManager { $alreadyDeferring = $this->deferPushing; $this->deferPushing = true; - $apps = $this->getApps(); + $apps = array_reverse($this->getApps()); foreach ($apps as $app) { if ($app instanceof IDeferrableApp) { @@ -252,7 +262,7 @@ class Manager implements IManager { * @since 20.0.0 */ public function flush(): void { - $apps = $this->getApps(); + $apps = array_reverse($this->getApps()); foreach ($apps as $app) { if (!$app instanceof IDeferrableApp) { @@ -384,7 +394,7 @@ class Manager implements IManager { * @param INotification $notification */ public function markProcessed(INotification $notification): void { - $apps = $this->getApps(); + $apps = array_reverse($this->getApps()); foreach ($apps as $app) { $app->markProcessed($notification); @@ -396,7 +406,7 @@ class Manager implements IManager { * @return int */ public function getCount(INotification $notification): int { - $apps = $this->getApps(); + $apps = array_reverse($this->getApps()); $count = 0; foreach ($apps as $app) { diff --git a/lib/private/Notification/Notification.php b/lib/private/Notification/Notification.php index f8f1e247854..fcce7fd0020 100644 --- a/lib/private/Notification/Notification.php +++ b/lib/private/Notification/Notification.php @@ -429,8 +429,7 @@ class Notification implements INotification { public function isValid(): bool { return $this->isValidCommon() - && - $this->getSubject() !== '' + && $this->getSubject() !== '' ; } @@ -456,8 +455,7 @@ class Notification implements INotification { return $this->isValidCommon() - && - $this->getParsedSubject() !== '' + && $this->getParsedSubject() !== '' ; } @@ -468,14 +466,10 @@ class Notification implements INotification { return $this->getApp() !== '' - && - $this->getUser() !== '' - && - $this->getDateTime()->getTimestamp() !== 0 - && - $this->getObjectType() !== '' - && - $this->getObjectId() !== '' + && $this->getUser() !== '' + && $this->getDateTime()->getTimestamp() !== 0 + && $this->getObjectType() !== '' + && $this->getObjectId() !== '' ; } } diff --git a/lib/private/OCM/Model/OCMProvider.php b/lib/private/OCM/Model/OCMProvider.php index 99a3770faef..be13d65a40f 100644 --- a/lib/private/OCM/Model/OCMProvider.php +++ b/lib/private/OCM/Model/OCMProvider.php @@ -11,18 +11,22 @@ namespace OC\OCM\Model; use NCU\Security\Signature\Model\Signatory; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; use OCP\OCM\Events\ResourceTypeRegisterEvent; use OCP\OCM\Exceptions\OCMArgumentException; use OCP\OCM\Exceptions\OCMProviderException; -use OCP\OCM\IOCMProvider; +use OCP\OCM\ICapabilityAwareOCMProvider; use OCP\OCM\IOCMResource; /** * @since 28.0.0 */ -class OCMProvider implements IOCMProvider { +class OCMProvider implements ICapabilityAwareOCMProvider { + private string $provider; private bool $enabled = false; private string $apiVersion = ''; + private string $inviteAcceptDialog = ''; + private array $capabilities = []; private string $endPoint = ''; /** @var IOCMResource[] */ private array $resourceTypes = []; @@ -31,7 +35,9 @@ class OCMProvider implements IOCMProvider { public function __construct( protected IEventDispatcher $dispatcher, + protected IConfig $config, ) { + $this->provider = 'Nextcloud ' . $config->getSystemValue('version'); } /** @@ -71,6 +77,30 @@ class OCMProvider implements IOCMProvider { } /** + * returns the invite accept dialog + * + * @return string + * @since 32.0.0 + */ + public function getInviteAcceptDialog(): string { + return $this->inviteAcceptDialog; + } + + /** + * set the invite accept dialog + * + * @param string $inviteAcceptDialog + * + * @return $this + * @since 32.0.0 + */ + public function setInviteAcceptDialog(string $inviteAcceptDialog): static { + $this->inviteAcceptDialog = $inviteAcceptDialog; + + return $this; + } + + /** * @param string $endPoint * * @return $this @@ -89,6 +119,34 @@ class OCMProvider implements IOCMProvider { } /** + * @return string + */ + public function getProvider(): string { + return $this->provider; + } + + /** + * @param array $capabilities + * + * @return $this + */ + public function setCapabilities(array $capabilities): static { + foreach ($capabilities as $value) { + if (!in_array($value, $this->capabilities)) { + array_push($this->capabilities, $value); + } + } + + return $this; + } + + /** + * @return array + */ + public function getCapabilities(): array { + return $this->capabilities; + } + /** * create a new resource to later add it with {@see IOCMProvider::addResourceType()} * @return IOCMResource */ @@ -166,9 +224,8 @@ class OCMProvider implements IOCMProvider { * * @param array $data * - * @return $this + * @return OCMProvider&static * @throws OCMProviderException in case a descent provider cannot be generated from data - * @see self::jsonSerialize() */ public function import(array $data): static { $this->setEnabled(is_bool($data['enabled'] ?? '') ? $data['enabled'] : false) @@ -209,21 +266,7 @@ class OCMProvider implements IOCMProvider { } /** - * @return array{ - * enabled: bool, - * apiVersion: '1.0-proposal1', - * endPoint: string, - * publicKey: array{ - * keyId: string, - * publicKeyPem: string - * }, - * resourceTypes: list<array{ - * name: string, - * shareTypes: list<string>, - * protocols: array<string, string> - * }>, - * version: string - * } + * @since 28.0.0 */ public function jsonSerialize(): array { $resourceTypes = []; @@ -231,13 +274,24 @@ class OCMProvider implements IOCMProvider { $resourceTypes[] = $res->jsonSerialize(); } - return [ + $response = [ 'enabled' => $this->isEnabled(), 'apiVersion' => '1.0-proposal1', // deprecated, but keep it to stay compatible with old version 'version' => $this->getApiVersion(), // informative but real version 'endPoint' => $this->getEndPoint(), - 'publicKey' => $this->getSignatory()->jsonSerialize(), + 'publicKey' => $this->getSignatory()?->jsonSerialize(), 'resourceTypes' => $resourceTypes ]; + + $capabilities = $this->getCapabilities(); + $inviteAcceptDialog = $this->getInviteAcceptDialog(); + if ($capabilities) { + $response['capabilities'] = $capabilities; + } + if ($inviteAcceptDialog) { + $response['inviteAcceptDialog'] = $inviteAcceptDialog; + } + return $response; + } } diff --git a/lib/private/OCM/OCMDiscoveryService.php b/lib/private/OCM/OCMDiscoveryService.php index af612416372..a151bbc753c 100644 --- a/lib/private/OCM/OCMDiscoveryService.php +++ b/lib/private/OCM/OCMDiscoveryService.php @@ -17,8 +17,8 @@ use OCP\ICache; use OCP\ICacheFactory; use OCP\IConfig; use OCP\OCM\Exceptions\OCMProviderException; +use OCP\OCM\ICapabilityAwareOCMProvider; use OCP\OCM\IOCMDiscoveryService; -use OCP\OCM\IOCMProvider; use Psr\Log\LoggerInterface; /** @@ -31,7 +31,7 @@ class OCMDiscoveryService implements IOCMDiscoveryService { ICacheFactory $cacheFactory, private IClientService $clientService, private IConfig $config, - private IOCMProvider $provider, + private ICapabilityAwareOCMProvider $provider, private LoggerInterface $logger, ) { $this->cache = $cacheFactory->createDistributed('ocm-discovery'); @@ -42,10 +42,10 @@ class OCMDiscoveryService implements IOCMDiscoveryService { * @param string $remote * @param bool $skipCache * - * @return IOCMProvider + * @return ICapabilityAwareOCMProvider * @throws OCMProviderException */ - public function discover(string $remote, bool $skipCache = false): IOCMProvider { + public function discover(string $remote, bool $skipCache = false): ICapabilityAwareOCMProvider { $remote = rtrim($remote, '/'); if (!str_starts_with($remote, 'http://') && !str_starts_with($remote, 'https://')) { // if scheme not specified, we test both; diff --git a/lib/private/Preview/BackgroundCleanupJob.php b/lib/private/Preview/BackgroundCleanupJob.php index e816ae22743..3138abb1bf9 100644 --- a/lib/private/Preview/BackgroundCleanupJob.php +++ b/lib/private/Preview/BackgroundCleanupJob.php @@ -63,13 +63,13 @@ class BackgroundCleanupJob extends TimedJob { $qb->expr()->castColumn('a.name', IQueryBuilder::PARAM_INT), 'b.fileid' )) ->where( - $qb->expr()->isNull('b.fileid') - )->andWhere( - $qb->expr()->eq('a.storage', $qb->createNamedParameter($this->previewFolder->getStorageId())) - )->andWhere( - $qb->expr()->eq('a.parent', $qb->createNamedParameter($this->previewFolder->getId())) - )->andWhere( - $qb->expr()->like('a.name', $qb->createNamedParameter('__%')) + $qb->expr()->andX( + $qb->expr()->isNull('b.fileid'), + $qb->expr()->eq('a.storage', $qb->createNamedParameter($this->previewFolder->getStorageId())), + $qb->expr()->eq('a.parent', $qb->createNamedParameter($this->previewFolder->getId())), + $qb->expr()->like('a.name', $qb->createNamedParameter('__%')), + $qb->expr()->eq('a.mimetype', $qb->createNamedParameter($this->mimeTypeLoader->getId('httpd/unix-directory'))) + ) ); if (!$this->isCLI) { diff --git a/lib/private/Preview/Bundled.php b/lib/private/Preview/Bundled.php index 836dc4bd357..6100e8262a4 100644 --- a/lib/private/Preview/Bundled.php +++ b/lib/private/Preview/Bundled.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php index ef68c17b896..4a7341896ef 100644 --- a/lib/private/Preview/Generator.php +++ b/lib/private/Preview/Generator.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -11,6 +12,7 @@ use OCP\Files\IAppData; use OCP\Files\InvalidPathException; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\Files\SimpleFS\InMemoryFile; use OCP\Files\SimpleFS\ISimpleFile; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IConfig; @@ -20,34 +22,20 @@ use OCP\IStreamImage; use OCP\Preview\BeforePreviewFetchedEvent; use OCP\Preview\IProviderV2; use OCP\Preview\IVersionedPreviewFile; +use Psr\Log\LoggerInterface; class Generator { public const SEMAPHORE_ID_ALL = 0x0a11; public const SEMAPHORE_ID_NEW = 0x07ea; - /** @var IPreview */ - private $previewManager; - /** @var IConfig */ - private $config; - /** @var IAppData */ - private $appData; - /** @var GeneratorHelper */ - private $helper; - /** @var IEventDispatcher */ - private $eventDispatcher; - public function __construct( - IConfig $config, - IPreview $previewManager, - IAppData $appData, - GeneratorHelper $helper, - IEventDispatcher $eventDispatcher, + private IConfig $config, + private IPreview $previewManager, + private IAppData $appData, + private GeneratorHelper $helper, + private IEventDispatcher $eventDispatcher, + private LoggerInterface $logger, ) { - $this->config = $config; - $this->previewManager = $previewManager; - $this->appData = $appData; - $this->helper = $helper; - $this->eventDispatcher = $eventDispatcher; } /** @@ -56,17 +44,19 @@ class Generator { * The cache is searched first and if nothing usable was found then a preview is * generated by one of the providers * - * @param File $file - * @param int $width - * @param int $height - * @param bool $crop - * @param string $mode - * @param string|null $mimeType * @return ISimpleFile * @throws NotFoundException * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) */ - public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) { + public function getPreview( + File $file, + int $width = -1, + int $height = -1, + bool $crop = false, + string $mode = IPreview::MODE_FILL, + ?string $mimeType = null, + bool $cacheResult = true, + ): ISimpleFile { $specification = [ 'width' => $width, 'height' => $height, @@ -83,23 +73,30 @@ class Generator { $mimeType, )); + $this->logger->debug('Requesting preview for {path} with width={width}, height={height}, crop={crop}, mode={mode}, mimeType={mimeType}', [ + 'path' => $file->getPath(), + 'width' => $width, + 'height' => $height, + 'crop' => $crop, + 'mode' => $mode, + 'mimeType' => $mimeType, + ]); + + // since we only ask for one preview, and the generate method return the last one it created, it returns the one we want - return $this->generatePreviews($file, [$specification], $mimeType); + return $this->generatePreviews($file, [$specification], $mimeType, $cacheResult); } /** * Generates previews of a file * - * @param File $file - * @param non-empty-array $specifications - * @param string $mimeType - * @return ISimpleFile the last preview that was generated * @throws NotFoundException * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) */ - public function generatePreviews(File $file, array $specifications, $mimeType = null) { + public function generatePreviews(File $file, array $specifications, ?string $mimeType = null, bool $cacheResult = true): ISimpleFile { //Make sure that we can read the file if (!$file->isReadable()) { + $this->logger->warning('Cannot read file: {path}, skipping preview generation.', ['path' => $file->getPath()]); throw new NotFoundException('Cannot read file'); } @@ -121,6 +118,7 @@ class Generator { $maxPreviewImage = null; // only load the image when we need it if ($maxPreview->getSize() === 0) { $maxPreview->delete(); + $this->logger->error('Max preview generated for file {path} has size 0, deleting and throwing exception.', ['path' => $file->getPath()]); throw new NotFoundException('Max preview size 0, invalid!'); } @@ -167,7 +165,8 @@ class Generator { $maxPreviewImage = $this->helper->getImage($maxPreview); } - $preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion); + $this->logger->debug('Cached preview not found for file {path}, generating a new preview.', ['path' => $file->getPath()]); + $preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion, $cacheResult); // New file, augment our array $previewFiles[] = $preview; } @@ -335,6 +334,11 @@ class Generator { $previewConcurrency = $this->getNumConcurrentPreviews('preview_concurrency_new'); $sem = self::guardWithSemaphore(self::SEMAPHORE_ID_NEW, $previewConcurrency); try { + $this->logger->debug('Calling preview provider for {mimeType} with width={width}, height={height}', [ + 'mimeType' => $mimeType, + 'width' => $width, + 'height' => $height, + ]); $preview = $this->helper->getThumbnail($provider, $file, $width, $height); } finally { self::unguardWithSemaphore($sem); @@ -346,11 +350,10 @@ class Generator { $path = $this->generatePath($preview->width(), $preview->height(), $crop, $max, $preview->dataMimeType(), $prefix); try { - $file = $previewFolder->newFile($path); if ($preview instanceof IStreamImage) { - $file->putContent($preview->resource()); + return $previewFolder->newFile($path, $preview->resource()); } else { - $file->putContent($preview->data()); + return $previewFolder->newFile($path, $preview->data()); } } catch (NotPermittedException $e) { throw new NotFoundException(); @@ -485,19 +488,20 @@ class Generator { } /** - * @param ISimpleFolder $previewFolder - * @param ISimpleFile $maxPreview - * @param int $width - * @param int $height - * @param bool $crop - * @param int $maxWidth - * @param int $maxHeight - * @param string $prefix - * @return ISimpleFile * @throws NotFoundException * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) */ - private function generatePreview(ISimpleFolder $previewFolder, IImage $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $prefix) { + private function generatePreview( + ISimpleFolder $previewFolder, + IImage $maxPreview, + int $width, + int $height, + bool $crop, + int $maxWidth, + int $maxHeight, + string $prefix, + bool $cacheResult, + ): ISimpleFile { $preview = $maxPreview; if (!$preview->valid()) { throw new \InvalidArgumentException('Failed to generate preview, failed to load image'); @@ -534,12 +538,14 @@ class Generator { $path = $this->generatePath($width, $height, $crop, false, $preview->dataMimeType(), $prefix); try { - $file = $previewFolder->newFile($path); - $file->putContent($preview->data()); + if ($cacheResult) { + return $previewFolder->newFile($path, $preview->data()); + } else { + return new InMemoryFile($path, $preview->data()); + } } catch (NotPermittedException $e) { throw new NotFoundException(); } - return $file; } @@ -558,6 +564,7 @@ class Generator { $path = $this->generatePath($width, $height, $crop, false, $mimeType, $prefix); foreach ($files as $file) { if ($file->getName() === $path) { + $this->logger->debug('Found cached preview: {path}', ['path' => $path]); return $file; } } diff --git a/lib/private/Preview/GeneratorHelper.php b/lib/private/Preview/GeneratorHelper.php index 5f43c94b624..e914dcc2002 100644 --- a/lib/private/Preview/GeneratorHelper.php +++ b/lib/private/Preview/GeneratorHelper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/HEIC.php b/lib/private/Preview/HEIC.php index e5d73c943a4..64eb48e58df 100644 --- a/lib/private/Preview/HEIC.php +++ b/lib/private/Preview/HEIC.php @@ -12,6 +12,7 @@ namespace OC\Preview; use OCP\Files\File; use OCP\Files\FileInfo; use OCP\IImage; +use OCP\Server; use Psr\Log\LoggerInterface; /** @@ -44,8 +45,8 @@ class HEIC extends ProviderV2 { $tmpPath = $this->getLocalFile($file); if ($tmpPath === false) { - \OC::$server->get(LoggerInterface::class)->error( - 'Failed to get thumbnail for: ' . $file->getPath(), + Server::get(LoggerInterface::class)->error( + 'Failed to get local file to generate thumbnail for: ' . $file->getPath(), ['app' => 'core'] ); return null; diff --git a/lib/private/Preview/Image.php b/lib/private/Preview/Image.php index 69841f07929..78a402c636a 100644 --- a/lib/private/Preview/Image.php +++ b/lib/private/Preview/Image.php @@ -9,6 +9,8 @@ namespace OC\Preview; use OCP\Files\File; use OCP\IImage; +use OCP\Server; +use Psr\Log\LoggerInterface; abstract class Image extends ProviderV2 { /** @@ -25,6 +27,13 @@ abstract class Image extends ProviderV2 { $image = new \OCP\Image(); $fileName = $this->getLocalFile($file); + if ($fileName === false) { + Server::get(LoggerInterface::class)->error( + 'Failed to get local file to generate thumbnail for: ' . $file->getPath(), + ['app' => 'core'] + ); + return null; + } $image->loadFromFile($fileName); $image->fixOrientation(); diff --git a/lib/private/Preview/Imaginary.php b/lib/private/Preview/Imaginary.php index baa883f4bd9..d421da74ac8 100644 --- a/lib/private/Preview/Imaginary.php +++ b/lib/private/Preview/Imaginary.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/Krita.php b/lib/private/Preview/Krita.php index 2e77c7befd2..e96fac993aa 100644 --- a/lib/private/Preview/Krita.php +++ b/lib/private/Preview/Krita.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/MP3.php b/lib/private/Preview/MP3.php index 105b182b415..add0028738e 100644 --- a/lib/private/Preview/MP3.php +++ b/lib/private/Preview/MP3.php @@ -9,6 +9,8 @@ namespace OC\Preview; use OCP\Files\File; use OCP\IImage; +use OCP\Server; +use Psr\Log\LoggerInterface; use wapmorgan\Mp3Info\Mp3Info; use function OCP\Log\logger; @@ -25,6 +27,13 @@ class MP3 extends ProviderV2 { */ public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage { $tmpPath = $this->getLocalFile($file); + if ($tmpPath === false) { + Server::get(LoggerInterface::class)->error( + 'Failed to get local file to generate thumbnail for: ' . $file->getPath(), + ['app' => 'core'] + ); + return null; + } try { $audio = new Mp3Info($tmpPath, true); diff --git a/lib/private/Preview/MimeIconProvider.php b/lib/private/Preview/MimeIconProvider.php index 80545bd4063..d1963fe882b 100644 --- a/lib/private/Preview/MimeIconProvider.php +++ b/lib/private/Preview/MimeIconProvider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -54,7 +55,7 @@ class MimeIconProvider implements IMimeIconProvider { return null; } - + private function searchfileName(string $fileName): ?string { // If the file exists in the current enabled legacy // custom theme, let's return it @@ -65,7 +66,7 @@ class MimeIconProvider implements IMimeIconProvider { return $this->urlGenerator->getAbsoluteURL($path); } } - + // Previously, we used to pass this through Theming // But it was only used to colour icons containing // 0082c9. Since with vue we moved to inline svg icons, diff --git a/lib/private/Preview/Movie.php b/lib/private/Preview/Movie.php index 4a6104930d6..47895f999d8 100644 --- a/lib/private/Preview/Movie.php +++ b/lib/private/Preview/Movie.php @@ -5,32 +5,27 @@ * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OC\Preview; use OCP\Files\File; use OCP\Files\FileInfo; +use OCP\IConfig; use OCP\IImage; +use OCP\ITempManager; +use OCP\Server; use Psr\Log\LoggerInterface; class Movie extends ProviderV2 { - /** - * @deprecated 23.0.0 pass option to \OCP\Preview\ProviderV2 - * @var string - */ - public static $avconvBinary; + private IConfig $config; - /** - * @deprecated 23.0.0 pass option to \OCP\Preview\ProviderV2 - * @var string - */ - public static $ffmpegBinary; + private ?string $binary = null; - /** @var string */ - private $binary; + public function __construct(array $options = []) { + parent::__construct($options); + $this->config = Server::get(IConfig::class); + } - /** - * {@inheritDoc} - */ public function getMimeType(): string { return '/video\/.*/'; } @@ -39,14 +34,9 @@ class Movie extends ProviderV2 { * {@inheritDoc} */ public function isAvailable(FileInfo $file): bool { - // TODO: remove when avconv is dropped if (is_null($this->binary)) { if (isset($this->options['movieBinary'])) { $this->binary = $this->options['movieBinary']; - } elseif (is_string(self::$avconvBinary)) { - $this->binary = self::$avconvBinary; - } elseif (is_string(self::$ffmpegBinary)) { - $this->binary = self::$ffmpegBinary; } } return is_string($this->binary); @@ -64,10 +54,15 @@ class Movie extends ProviderV2 { $result = null; if ($this->useTempFile($file)) { - // try downloading 5 MB first as it's likely that the first frames are present there - // in some cases this doesn't work for example when the moov atom is at the - // end of the file, so if it fails we fall back to getting the full file - $sizeAttempts = [5242880, null]; + // Try downloading 5 MB first, as it's likely that the first frames are present there. + // In some cases this doesn't work, for example when the moov atom is at the + // end of the file, so if it fails we fall back to getting the full file. + // Unless the file is not local (e.g. S3) as we do not want to download the whole (e.g. 37Gb) file + if ($file->getStorage()->isLocal()) { + $sizeAttempts = [5242880, null]; + } else { + $sizeAttempts = [5242880]; + } } else { // size is irrelevant, only attempt once $sizeAttempts = [null]; @@ -75,15 +70,19 @@ class Movie extends ProviderV2 { foreach ($sizeAttempts as $size) { $absPath = $this->getLocalFile($file, $size); + if ($absPath === false) { + Server::get(LoggerInterface::class)->error( + 'Failed to get local file to generate thumbnail for: ' . $file->getPath(), + ['app' => 'core'] + ); + return null; + } - $result = null; - if (is_string($absPath)) { - $result = $this->generateThumbNail($maxX, $maxY, $absPath, 5); + $result = $this->generateThumbNail($maxX, $maxY, $absPath, 5); + if ($result === null) { + $result = $this->generateThumbNail($maxX, $maxY, $absPath, 1); if ($result === null) { - $result = $this->generateThumbNail($maxX, $maxY, $absPath, 1); - if ($result === null) { - $result = $this->generateThumbNail($maxX, $maxY, $absPath, 0); - } + $result = $this->generateThumbNail($maxX, $maxY, $absPath, 0); } } @@ -97,8 +96,42 @@ class Movie extends ProviderV2 { return $result; } + private function useHdr(string $absPath): bool { + // load ffprobe path from configuration, otherwise generate binary path using ffmpeg binary path + $ffprobe_binary = $this->config->getSystemValue('preview_ffprobe_path', null) ?? (pathinfo($this->binary, PATHINFO_DIRNAME) . '/ffprobe'); + // run ffprobe on the video file to get value of "color_transfer" + $test_hdr_cmd = [$ffprobe_binary,'-select_streams', 'v:0', + '-show_entries', 'stream=color_transfer', + '-of', 'default=noprint_wrappers=1:nokey=1', + $absPath]; + $test_hdr_proc = proc_open($test_hdr_cmd, [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $test_hdr_pipes); + if ($test_hdr_proc === false) { + return false; + } + $test_hdr_stdout = trim(stream_get_contents($test_hdr_pipes[1])); + $test_hdr_stderr = trim(stream_get_contents($test_hdr_pipes[2])); + proc_close($test_hdr_proc); + // search build options for libzimg (provides zscale filter) + $ffmpeg_libzimg_installed = strpos($test_hdr_stderr, '--enable-libzimg'); + // Only values of "smpte2084" and "arib-std-b67" indicate an HDR video. + // Only return true if video is detected as HDR and libzimg is installed. + if (($test_hdr_stdout === 'smpte2084' || $test_hdr_stdout === 'arib-std-b67') && $ffmpeg_libzimg_installed !== false) { + return true; + } else { + return false; + } + } + private function generateThumbNail(int $maxX, int $maxY, string $absPath, int $second): ?IImage { - $tmpPath = \OC::$server->getTempManager()->getTemporaryFile(); + $tmpPath = Server::get(ITempManager::class)->getTemporaryFile(); + + if ($tmpPath === false) { + Server::get(LoggerInterface::class)->error( + 'Failed to get local file to generate thumbnail for: ' . $absPath, + ['app' => 'core'] + ); + return null; + } $binaryType = substr(strrchr($this->binary, '/'), 1); @@ -108,10 +141,21 @@ class Movie extends ProviderV2 { '-an', '-f', 'mjpeg', '-vframes', '1', '-vsync', '1', $tmpPath]; } elseif ($binaryType === 'ffmpeg') { - $cmd = [$this->binary, '-y', '-ss', (string)$second, - '-i', $absPath, - '-f', 'mjpeg', '-vframes', '1', - $tmpPath]; + if ($this->useHdr($absPath)) { + // Force colorspace to '2020_ncl' because some videos are + // tagged incorrectly as 'reserved' resulting in fail if not forced. + $cmd = [$this->binary, '-y', '-ss', (string)$second, + '-i', $absPath, + '-f', 'mjpeg', '-vframes', '1', + '-vf', 'zscale=min=2020_ncl:t=linear:npl=100,format=gbrpf32le,zscale=p=bt709,tonemap=tonemap=hable:desat=0,zscale=t=bt709:m=bt709:r=tv,format=yuv420p', + $tmpPath]; + } else { + // always default to generating preview using non-HDR command + $cmd = [$this->binary, '-y', '-ss', (string)$second, + '-i', $absPath, + '-f', 'mjpeg', '-vframes', '1', + $tmpPath]; + } } else { // Not supported unlink($tmpPath); @@ -122,8 +166,8 @@ class Movie extends ProviderV2 { $returnCode = -1; $output = ''; if (is_resource($proc)) { - $stdout = trim(stream_get_contents($pipes[1])); $stderr = trim(stream_get_contents($pipes[2])); + $stdout = trim(stream_get_contents($pipes[1])); $returnCode = proc_close($proc); $output = $stdout . $stderr; } @@ -140,7 +184,7 @@ class Movie extends ProviderV2 { } if ($second === 0) { - $logger = \OC::$server->get(LoggerInterface::class); + $logger = Server::get(LoggerInterface::class); $logger->info('Movie preview generation failed Output: {output}', ['app' => 'core', 'output' => $output]); } diff --git a/lib/private/Preview/Office.php b/lib/private/Preview/Office.php index 20fbef6eb23..ffba0211de2 100644 --- a/lib/private/Preview/Office.php +++ b/lib/private/Preview/Office.php @@ -12,6 +12,7 @@ use OCP\Files\FileInfo; use OCP\IImage; use OCP\ITempManager; use OCP\Server; +use Psr\Log\LoggerInterface; abstract class Office extends ProviderV2 { /** @@ -33,6 +34,13 @@ abstract class Office extends ProviderV2 { // The file to generate the preview for. $absPath = $this->getLocalFile($file); + if ($absPath === false) { + Server::get(LoggerInterface::class)->error( + 'Failed to get local file to generate thumbnail for: ' . $file->getPath(), + ['app' => 'core'] + ); + return null; + } // The destination for the LibreOffice user profile. // LibreOffice can rune once per user profile and therefore instance id and file id are included. diff --git a/lib/private/Preview/ProviderV2.php b/lib/private/Preview/ProviderV2.php index 7251dd70d17..556d1099d2d 100644 --- a/lib/private/Preview/ProviderV2.php +++ b/lib/private/Preview/ProviderV2.php @@ -6,27 +6,23 @@ declare(strict_types=1); * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + namespace OC\Preview; use OCP\Files\File; use OCP\Files\FileInfo; use OCP\IImage; +use OCP\ITempManager; use OCP\Preview\IProviderV2; +use OCP\Server; +use Psr\Log\LoggerInterface; abstract class ProviderV2 implements IProviderV2 { - /** @var array */ - protected $options; - - /** @var array */ - protected $tmpFiles = []; + protected array $tmpFiles = []; - /** - * Constructor - * - * @param array $options - */ - public function __construct(array $options = []) { - $this->options = $options; + public function __construct( + protected array $options = [], + ) { } /** @@ -50,7 +46,7 @@ abstract class ProviderV2 implements IProviderV2 { * @param File $file * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image - * @return null|\OCP\IImage false if no preview was generated + * @return null|\OCP\IImage null if no preview was generated * @since 17.0.0 */ abstract public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage; @@ -63,12 +59,19 @@ abstract class ProviderV2 implements IProviderV2 { * Get a path to either the local file or temporary file * * @param File $file - * @param int $maxSize maximum size for temporary files - * @return string|false + * @param ?int $maxSize maximum size for temporary files */ - protected function getLocalFile(File $file, ?int $maxSize = null) { + protected function getLocalFile(File $file, ?int $maxSize = null): string|false { if ($this->useTempFile($file)) { - $absPath = \OC::$server->getTempManager()->getTemporaryFile(); + $absPath = Server::get(ITempManager::class)->getTemporaryFile(); + + if ($absPath === false) { + Server::get(LoggerInterface::class)->error( + 'Failed to get local file to generate thumbnail for: ' . $file->getPath(), + ['app' => 'core'] + ); + return false; + } $content = $file->fopen('r'); if ($content === false) { diff --git a/lib/private/Preview/SGI.php b/lib/private/Preview/SGI.php index 06ea9c0c69a..78b1ea5828a 100644 --- a/lib/private/Preview/SGI.php +++ b/lib/private/Preview/SGI.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/TGA.php b/lib/private/Preview/TGA.php index 62e5aadc2af..675907b4e49 100644 --- a/lib/private/Preview/TGA.php +++ b/lib/private/Preview/TGA.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/Watcher.php b/lib/private/Preview/Watcher.php index abddd7b5acb..21f040d8342 100644 --- a/lib/private/Preview/Watcher.php +++ b/lib/private/Preview/Watcher.php @@ -8,6 +8,7 @@ declare(strict_types=1); */ namespace OC\Preview; +use OCP\Files\FileInfo; use OCP\Files\Folder; use OCP\Files\IAppData; use OCP\Files\Node; @@ -37,7 +38,7 @@ class Watcher { $this->deleteNode($node); } - protected function deleteNode(Node $node) { + protected function deleteNode(FileInfo $node) { // We only handle files if ($node instanceof Folder) { return; diff --git a/lib/private/Preview/WatcherConnector.php b/lib/private/Preview/WatcherConnector.php index ae2a136ca78..c34dd1dde4d 100644 --- a/lib/private/Preview/WatcherConnector.php +++ b/lib/private/Preview/WatcherConnector.php @@ -9,43 +9,33 @@ declare(strict_types=1); namespace OC\Preview; use OC\SystemConfig; +use OCA\Files_Versions\Events\VersionRestoredEvent; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IRootFolder; use OCP\Files\Node; class WatcherConnector { - /** @var IRootFolder */ - private $root; - - /** @var SystemConfig */ - private $config; - - /** - * WatcherConnector constructor. - * - * @param IRootFolder $root - * @param SystemConfig $config - */ - public function __construct(IRootFolder $root, - SystemConfig $config) { - $this->root = $root; - $this->config = $config; + public function __construct( + private IRootFolder $root, + private SystemConfig $config, + private IEventDispatcher $dispatcher, + ) { } - /** - * @return Watcher - */ private function getWatcher(): Watcher { return \OCP\Server::get(Watcher::class); } - public function connectWatcher() { + public function connectWatcher(): void { // Do not connect if we are not setup yet! if ($this->config->getValue('instanceid', null) !== null) { $this->root->listen('\OC\Files', 'postWrite', function (Node $node) { $this->getWatcher()->postWrite($node); }); - \OC_Hook::connect('\OCP\Versions', 'rollback', $this->getWatcher(), 'versionRollback'); + $this->dispatcher->addListener(VersionRestoredEvent::class, function (VersionRestoredEvent $event) { + $this->getWatcher()->versionRollback(['node' => $event->getVersion()->getSourceFile()]); + }); } } } diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php index c8ef2fac8f3..0bb0280406c 100644 --- a/lib/private/PreviewManager.php +++ b/lib/private/PreviewManager.php @@ -21,8 +21,10 @@ use OCP\Files\SimpleFS\ISimpleFile; use OCP\IBinaryFinder; use OCP\IConfig; use OCP\IPreview; -use OCP\IServerContainer; use OCP\Preview\IProviderV2; +use Psr\Container\ContainerInterface; +use Psr\Log\LoggerInterface; + use function array_key_exists; class PreviewManager implements IPreview { @@ -47,7 +49,7 @@ class PreviewManager implements IPreview { * @psalm-var array<string, null> */ private array $loadedBootstrapProviders = []; - private IServerContainer $container; + private ContainerInterface $container; private IBinaryFinder $binaryFinder; private IMagickSupport $imagickSupport; private bool $enablePreviews; @@ -60,7 +62,7 @@ class PreviewManager implements IPreview { GeneratorHelper $helper, ?string $userId, Coordinator $bootstrapCoordinator, - IServerContainer $container, + ContainerInterface $container, IBinaryFinder $binaryFinder, IMagickSupport $imagickSupport, ) { @@ -136,35 +138,27 @@ class PreviewManager implements IPreview { $this->rootFolder, $this->config ), - $this->eventDispatcher + $this->eventDispatcher, + $this->container->get(LoggerInterface::class), ); } return $this->generator; } - /** - * Returns a preview of a file - * - * The cache is searched first and if nothing usable was found then a preview is - * generated by one of the providers - * - * @param File $file - * @param int $width - * @param int $height - * @param bool $crop - * @param string $mode - * @param string $mimeType - * @return ISimpleFile - * @throws NotFoundException - * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) - * @since 11.0.0 - \InvalidArgumentException was added in 12.0.0 - */ - public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) { - $this->throwIfPreviewsDisabled(); + public function getPreview( + File $file, + $width = -1, + $height = -1, + $crop = false, + $mode = IPreview::MODE_FILL, + $mimeType = null, + bool $cacheResult = true, + ): ISimpleFile { + $this->throwIfPreviewsDisabled($file, $mimeType); $previewConcurrency = $this->getGenerator()->getNumConcurrentPreviews('preview_concurrency_all'); $sem = Generator::guardWithSemaphore(Generator::SEMAPHORE_ID_ALL, $previewConcurrency); try { - $preview = $this->getGenerator()->getPreview($file, $width, $height, $crop, $mode, $mimeType); + $preview = $this->getGenerator()->getPreview($file, $width, $height, $crop, $mode, $mimeType, $cacheResult); } finally { Generator::unguardWithSemaphore($sem); } @@ -184,7 +178,7 @@ class PreviewManager implements IPreview { * @since 19.0.0 */ public function generatePreviews(File $file, array $specifications, $mimeType = null) { - $this->throwIfPreviewsDisabled(); + $this->throwIfPreviewsDisabled($file, $mimeType); return $this->getGenerator()->generatePreviews($file, $specifications, $mimeType); } @@ -219,13 +213,15 @@ class PreviewManager implements IPreview { /** * Check if a preview can be generated for a file */ - public function isAvailable(\OCP\Files\FileInfo $file): bool { + public function isAvailable(\OCP\Files\FileInfo $file, ?string $mimeType = null): bool { if (!$this->enablePreviews) { return false; } + $fileMimeType = $mimeType ?? $file->getMimeType(); + $this->registerCoreProviders(); - if (!$this->isMimeSupported($file->getMimetype())) { + if (!$this->isMimeSupported($fileMimeType)) { return false; } @@ -235,7 +231,7 @@ class PreviewManager implements IPreview { } foreach ($this->providers as $supportedMimeType => $providers) { - if (preg_match($supportedMimeType, $file->getMimetype())) { + if (preg_match($supportedMimeType, $fileMimeType)) { foreach ($providers as $providerClosure) { $provider = $this->helper->getProvider($providerClosure); if (!($provider instanceof IProviderV2)) { @@ -343,7 +339,7 @@ class PreviewManager implements IPreview { $this->registerCoreProvider(Preview\XBitmap::class, '/image\/x-xbitmap/'); $this->registerCoreProvider(Preview\WebP::class, '/image\/webp/'); $this->registerCoreProvider(Preview\Krita::class, '/application\/x-krita/'); - $this->registerCoreProvider(Preview\MP3::class, '/audio\/mpeg/'); + $this->registerCoreProvider(Preview\MP3::class, '/audio\/mpeg$/'); $this->registerCoreProvider(Preview\OpenDocument::class, '/application\/vnd.oasis.opendocument.*/'); $this->registerCoreProvider(Preview\Imaginary::class, Preview\Imaginary::supportedMimeTypes()); $this->registerCoreProvider(Preview\ImaginaryPDF::class, Preview\ImaginaryPDF::supportedMimeTypes()); @@ -461,8 +457,8 @@ class PreviewManager implements IPreview { /** * @throws NotFoundException if preview generation is disabled */ - private function throwIfPreviewsDisabled(): void { - if (!$this->enablePreviews) { + private function throwIfPreviewsDisabled(File $file, ?string $mimeType = null): void { + if (!$this->isAvailable($file, $mimeType)) { throw new NotFoundException('Previews disabled'); } } diff --git a/lib/private/PreviewNotAvailableException.php b/lib/private/PreviewNotAvailableException.php index b1fec912769..582f337acd1 100644 --- a/lib/private/PreviewNotAvailableException.php +++ b/lib/private/PreviewNotAvailableException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Profile/Actions/FediverseAction.php b/lib/private/Profile/Actions/FediverseAction.php index 1076027629d..b48f1db5c50 100644 --- a/lib/private/Profile/Actions/FediverseAction.php +++ b/lib/private/Profile/Actions/FediverseAction.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace OC\Profile\Actions; use OCP\Accounts\IAccountManager; +use OCP\Accounts\PropertyDoesNotExistException; use OCP\IURLGenerator; use OCP\IUser; use OCP\L10N\IFactory; @@ -27,8 +28,13 @@ class FediverseAction implements ILinkAction { } public function preload(IUser $targetUser): void { - $account = $this->accountManager->getAccount($targetUser); - $this->value = $account->getProperty(IAccountManager::PROPERTY_FEDIVERSE)->getValue(); + try { + $account = $this->accountManager->getAccount($targetUser); + $this->value = $account->getProperty(IAccountManager::PROPERTY_FEDIVERSE)->getValue(); + } catch (PropertyDoesNotExistException) { + // `getTarget` will return null to skip this action + $this->value = ''; + } } public function getAppId(): string { @@ -57,11 +63,18 @@ class FediverseAction implements ILinkAction { } public function getTarget(): ?string { - if (empty($this->value)) { + if ($this->value === '') { + return null; + } + + $handle = $this->value[0] === '@' ? substr($this->value, 1) : $this->value; + [$username, $instance] = [...explode('@', $handle, 2), '']; + + if (($username === '') || ($instance === '')) { + return null; + } elseif (str_contains($username, '/') || str_contains($instance, '/')) { return null; } - $username = $this->value[0] === '@' ? substr($this->value, 1) : $this->value; - [$username, $instance] = explode('@', $username); return 'https://' . $instance . '/@' . $username; } } diff --git a/lib/private/Profile/ProfileManager.php b/lib/private/Profile/ProfileManager.php index 9d3d94fab21..1ade208fbcf 100644 --- a/lib/private/Profile/ProfileManager.php +++ b/lib/private/Profile/ProfileManager.php @@ -12,6 +12,7 @@ namespace OC\Profile; use OC\AppFramework\Bootstrap\Coordinator; use OC\Core\Db\ProfileConfig; use OC\Core\Db\ProfileConfigMapper; +use OC\Core\ResponseDefinitions; use OC\KnownUser\KnownUserService; use OC\Profile\Actions\EmailAction; use OC\Profile\Actions\FediverseAction; @@ -33,6 +34,9 @@ use Psr\Log\LoggerInterface; use function array_flip; use function usort; +/** + * @psalm-import-type CoreProfileFields from ResponseDefinitions + */ class ProfileManager implements IProfileManager { /** @var ILinkAction[] */ private array $actions = []; @@ -223,7 +227,7 @@ class ProfileManager implements IProfileManager { /** * Return the profile parameters of the target user that are visible to the visiting user * in an associative array - * @return array{userId: string, address?: string|null, biography?: string|null, displayname?: string|null, headline?: string|null, isUserAvatarVisible?: bool, organisation?: string|null, pronouns?: string|null, role?: string|null, actions: list<array{id: string, icon: string, title: string, target: ?string}>} + * @psalm-return CoreProfileFields */ public function getProfileFields(IUser $targetUser, ?IUser $visitingUser): array { $account = $this->accountManager->getAccount($targetUser); @@ -243,8 +247,8 @@ class ProfileManager implements IProfileManager { case IAccountManager::PROPERTY_ORGANISATION: case IAccountManager::PROPERTY_ROLE: case IAccountManager::PROPERTY_PRONOUNS: - $profileParameters[$property] = - $this->isProfileFieldVisible($property, $targetUser, $visitingUser) + $profileParameters[$property] + = $this->isProfileFieldVisible($property, $targetUser, $visitingUser) // Explicitly set to null when value is empty string ? ($account->getProperty($property)->getValue() ?: null) : null; @@ -346,7 +350,7 @@ class ProfileManager implements IProfileManager { } /** - * Return the profile config of the target user with additional medatata, + * Return the profile config of the target user with additional metadata, * if a config does not already exist a default config is created and returned */ public function getProfileConfigWithMetadata(IUser $targetUser, ?IUser $visitingUser): array { @@ -395,7 +399,7 @@ class ProfileManager implements IProfileManager { ], IAccountManager::PROPERTY_ORGANISATION => [ 'appId' => self::CORE_APP_ID, - 'displayId' => $this->l10nFactory->get('lib')->t('Organisation'), + 'displayId' => $this->l10nFactory->get('lib')->t('Organization'), ], IAccountManager::PROPERTY_ROLE => [ 'appId' => self::CORE_APP_ID, diff --git a/lib/private/Profiler/BuiltInProfiler.php b/lib/private/Profiler/BuiltInProfiler.php new file mode 100644 index 00000000000..0a62365e901 --- /dev/null +++ b/lib/private/Profiler/BuiltInProfiler.php @@ -0,0 +1,95 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace OC\Profiler; + +use DateTime; +use OCP\IConfig; +use OCP\IRequest; + +class BuiltInProfiler { + private \ExcimerProfiler $excimer; + + public function __construct( + private IConfig $config, + private IRequest $request, + ) { + } + + public function start(): void { + if (!extension_loaded('excimer')) { + return; + } + + $shouldProfileSingleRequest = $this->shouldProfileSingleRequest(); + $shouldSample = $this->config->getSystemValueBool('profiling.sample') && !$shouldProfileSingleRequest; + + + if (!$shouldProfileSingleRequest && !$shouldSample) { + return; + } + + $requestRate = $this->config->getSystemValue('profiling.request.rate', 0.001); + $sampleRate = $this->config->getSystemValue('profiling.sample.rate', 1.0); + $eventType = $this->config->getSystemValue('profiling.event_type', EXCIMER_REAL); + + + $this->excimer = new \ExcimerProfiler(); + $this->excimer->setPeriod($shouldProfileSingleRequest ? $requestRate : $sampleRate); + $this->excimer->setEventType($eventType); + $this->excimer->setMaxDepth(250); + + if ($shouldSample) { + $this->excimer->setFlushCallback([$this, 'handleSampleFlush'], 1); + } + + $this->excimer->start(); + register_shutdown_function([$this, 'handleShutdown']); + } + + public function handleSampleFlush(\ExcimerLog $log): void { + file_put_contents($this->getSampleFilename(), $log->formatCollapsed(), FILE_APPEND); + } + + public function handleShutdown(): void { + $this->excimer->stop(); + + if (!$this->shouldProfileSingleRequest()) { + $this->excimer->flush(); + return; + } + + $request = \OCP\Server::get(IRequest::class); + $data = $this->excimer->getLog()->getSpeedscopeData(); + + $data['profiles'][0]['name'] = $request->getMethod() . ' ' . $request->getRequestUri() . ' ' . $request->getId(); + + file_put_contents($this->getProfileFilename(), json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); + } + + private function shouldProfileSingleRequest(): bool { + $shouldProfileSingleRequest = $this->config->getSystemValueBool('profiling.request', false); + $profileSecret = $this->config->getSystemValueString('profiling.secret', ''); + $secretParam = $this->request->getParam('profile_secret') ?? null; + return $shouldProfileSingleRequest || (!empty($profileSecret) && $profileSecret === $secretParam); + } + + private function getSampleFilename(): string { + $profilePath = $this->config->getSystemValueString('profiling.path', '/tmp'); + $sampleRotation = $this->config->getSystemValueInt('profiling.sample.rotation', 60); + $timestamp = floor(time() / ($sampleRotation * 60)) * ($sampleRotation * 60); + $sampleName = date('Y-m-d_Hi', (int)$timestamp); + return $profilePath . '/sample-' . $sampleName . '.log'; + } + + private function getProfileFilename(): string { + $profilePath = $this->config->getSystemValueString('profiling.path', '/tmp'); + $requestId = $this->request->getId(); + return $profilePath . '/profile-' . (new DateTime)->format('Y-m-d_His_v') . '-' . $requestId . '.json'; + } +} diff --git a/lib/private/RedisFactory.php b/lib/private/RedisFactory.php index dcb56cee9ef..f13f9299c1c 100644 --- a/lib/private/RedisFactory.php +++ b/lib/private/RedisFactory.php @@ -152,8 +152,8 @@ class RedisFactory { } public function isAvailable(): bool { - return \extension_loaded('redis') && - \version_compare(\phpversion('redis'), self::REDIS_MINIMAL_VERSION, '>='); + return \extension_loaded('redis') + && \version_compare(\phpversion('redis'), self::REDIS_MINIMAL_VERSION, '>='); } /** @@ -163,7 +163,7 @@ class RedisFactory { * @return boolean */ private function isConnectionParametersSupported(): bool { - return \extension_loaded('redis') && - \version_compare(\phpversion('redis'), self::REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION, '>='); + return \extension_loaded('redis') + && \version_compare(\phpversion('redis'), self::REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION, '>='); } } diff --git a/lib/private/Remote/Api/ApiBase.php b/lib/private/Remote/Api/ApiBase.php index dff3edb51b9..b2f96fb3c24 100644 --- a/lib/private/Remote/Api/ApiBase.php +++ b/lib/private/Remote/Api/ApiBase.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Remote/Api/ApiCollection.php b/lib/private/Remote/Api/ApiCollection.php index 65039f4b5aa..f154cd21926 100644 --- a/lib/private/Remote/Api/ApiCollection.php +++ b/lib/private/Remote/Api/ApiCollection.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Remote/Api/ApiFactory.php b/lib/private/Remote/Api/ApiFactory.php index 7daddd16011..795584e566a 100644 --- a/lib/private/Remote/Api/ApiFactory.php +++ b/lib/private/Remote/Api/ApiFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Remote/Api/NotFoundException.php b/lib/private/Remote/Api/NotFoundException.php index 5251313f5f0..361d03d24ed 100644 --- a/lib/private/Remote/Api/NotFoundException.php +++ b/lib/private/Remote/Api/NotFoundException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Remote/Api/OCS.php b/lib/private/Remote/Api/OCS.php index de07eb8bc56..36bc22751a5 100644 --- a/lib/private/Remote/Api/OCS.php +++ b/lib/private/Remote/Api/OCS.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Remote/Credentials.php b/lib/private/Remote/Credentials.php index fb0f03ae148..7f1ffaa727c 100644 --- a/lib/private/Remote/Credentials.php +++ b/lib/private/Remote/Credentials.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Remote/Instance.php b/lib/private/Remote/Instance.php index ac3233b93c9..10403af4ec7 100644 --- a/lib/private/Remote/Instance.php +++ b/lib/private/Remote/Instance.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -123,7 +124,13 @@ class Instance implements IInstance { private function downloadStatus($url) { try { $request = $this->clientService->newClient()->get($url); - return $request->getBody(); + $content = $request->getBody(); + + // IResponse.getBody responds with null|resource if returning a stream response was requested. + // As that's not the case here, we can just ignore the psalm warning by adding an assertion. + assert(is_string($content)); + + return $content; } catch (\Exception $e) { return false; } diff --git a/lib/private/Remote/InstanceFactory.php b/lib/private/Remote/InstanceFactory.php index f3047b851b2..f1b7a1de4ba 100644 --- a/lib/private/Remote/InstanceFactory.php +++ b/lib/private/Remote/InstanceFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Remote/User.php b/lib/private/Remote/User.php index 5c8e9d3ca4e..ae1032cdc1c 100644 --- a/lib/private/Remote/User.php +++ b/lib/private/Remote/User.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair.php b/lib/private/Repair.php index 5b6daa36a03..7fbf776d9a1 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -7,7 +7,6 @@ */ namespace OC; -use OC\DB\Connection; use OC\DB\ConnectionAdapter; use OC\Repair\AddAppConfigLazyMigration; use OC\Repair\AddBruteForceCleanupJob; @@ -38,10 +37,10 @@ use OC\Repair\NC20\EncryptionLegacyCipher; use OC\Repair\NC20\EncryptionMigration; use OC\Repair\NC20\ShippedDashboardEnable; use OC\Repair\NC21\AddCheckForUserCertificatesJob; -use OC\Repair\NC21\ValidatePhoneNumber; use OC\Repair\NC22\LookupServerSendCheck; use OC\Repair\NC24\AddTokenCleanupJob; use OC\Repair\NC25\AddMissingSecretJob; +use OC\Repair\NC29\SanitizeAccountProperties; use OC\Repair\NC30\RemoveLegacyDatadirFile; use OC\Repair\OldGroupMembershipShares; use OC\Repair\Owncloud\CleanPreviews; @@ -62,6 +61,7 @@ use OCP\AppFramework\QueryException; use OCP\AppFramework\Utility\ITimeFactory; use OCP\Collaboration\Resources\IManager; use OCP\EventDispatcher\IEventDispatcher; +use OCP\Files\AppData\IAppDataFactory; use OCP\IAppConfig; use OCP\IConfig; use OCP\IDBConnection; @@ -167,14 +167,14 @@ class Repair implements IOutput { \OC::$server->getUserManager(), \OC::$server->getConfig() ), - new MigrateOauthTables(\OC::$server->get(Connection::class)), + \OC::$server->get(MigrateOauthTables::class), new UpdateLanguageCodes(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig()), new AddLogRotateJob(\OC::$server->getJobList()), new ClearFrontendCaches(\OC::$server->getMemCacheFactory(), \OCP\Server::get(JSCombiner::class)), \OCP\Server::get(ClearGeneratedAvatarCache::class), new AddPreviewBackgroundCleanupJob(\OC::$server->getJobList()), new AddCleanupUpdaterBackupsJob(\OC::$server->getJobList()), - new CleanupCardDAVPhotoCache(\OC::$server->getConfig(), \OC::$server->getAppDataDir('dav-photocache'), \OC::$server->get(LoggerInterface::class)), + new CleanupCardDAVPhotoCache(\OC::$server->getConfig(), \OCP\Server::get(IAppDataFactory::class), \OC::$server->get(LoggerInterface::class)), new AddClenupLoginFlowV2BackgroundJob(\OC::$server->getJobList()), new RemoveLinkShares(\OC::$server->getDatabaseConnection(), \OC::$server->getConfig(), \OC::$server->getGroupManager(), \OC::$server->get(INotificationManager::class), \OCP\Server::get(ITimeFactory::class)), new ClearCollectionsAccessCache(\OC::$server->getConfig(), \OCP\Server::get(IManager::class)), @@ -195,6 +195,7 @@ class Repair implements IOutput { \OCP\Server::get(RepairLogoDimension::class), \OCP\Server::get(RemoveLegacyDatadirFile::class), \OCP\Server::get(AddCleanupDeletedUsersBackgroundJob::class), + \OCP\Server::get(SanitizeAccountProperties::class), ]; } @@ -213,8 +214,7 @@ class Repair implements IOutput { \OCP\Server::get(IAppConfig::class), \OCP\Server::get(IDBConnection::class) ), - \OC::$server->get(ValidatePhoneNumber::class), - \OC::$server->get(DeleteSchedulingObjects::class), + \OCP\Server::get(DeleteSchedulingObjects::class), ]; } diff --git a/lib/private/Repair/AddCleanupUpdaterBackupsJob.php b/lib/private/Repair/AddCleanupUpdaterBackupsJob.php index 8bd938b7e3a..e631a3303f1 100644 --- a/lib/private/Repair/AddCleanupUpdaterBackupsJob.php +++ b/lib/private/Repair/AddCleanupUpdaterBackupsJob.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/AddMetadataGenerationJob.php b/lib/private/Repair/AddMetadataGenerationJob.php index 4535fb0c9e0..76c60f303a7 100644 --- a/lib/private/Repair/AddMetadataGenerationJob.php +++ b/lib/private/Repair/AddMetadataGenerationJob.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/ClearFrontendCaches.php b/lib/private/Repair/ClearFrontendCaches.php index 77a3df5598a..5c57a63379d 100644 --- a/lib/private/Repair/ClearFrontendCaches.php +++ b/lib/private/Repair/ClearFrontendCaches.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/ClearGeneratedAvatarCache.php b/lib/private/Repair/ClearGeneratedAvatarCache.php index 2dea4bd2d61..0f743afbb4c 100644 --- a/lib/private/Repair/ClearGeneratedAvatarCache.php +++ b/lib/private/Repair/ClearGeneratedAvatarCache.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/ClearGeneratedAvatarCacheJob.php b/lib/private/Repair/ClearGeneratedAvatarCacheJob.php index 38cf03b731a..524a470e62a 100644 --- a/lib/private/Repair/ClearGeneratedAvatarCacheJob.php +++ b/lib/private/Repair/ClearGeneratedAvatarCacheJob.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/Collation.php b/lib/private/Repair/Collation.php index 5a309892bf0..43229792217 100644 --- a/lib/private/Repair/Collation.php +++ b/lib/private/Repair/Collation.php @@ -97,11 +97,11 @@ class Collation implements IRepairStep { // fetch tables by columns $statement = $connection->executeQuery( - 'SELECT DISTINCT(TABLE_NAME) AS `table`' . - ' FROM INFORMATION_SCHEMA . COLUMNS' . - ' WHERE TABLE_SCHEMA = ?' . - " AND (COLLATION_NAME <> '" . $characterSet . "_bin' OR CHARACTER_SET_NAME <> '" . $characterSet . "')" . - " AND TABLE_NAME LIKE '*PREFIX*%'", + 'SELECT DISTINCT(TABLE_NAME) AS `table`' + . ' FROM INFORMATION_SCHEMA . COLUMNS' + . ' WHERE TABLE_SCHEMA = ?' + . " AND (COLLATION_NAME <> '" . $characterSet . "_bin' OR CHARACTER_SET_NAME <> '" . $characterSet . "')" + . " AND TABLE_NAME LIKE '*PREFIX*%'", [$dbName] ); $rows = $statement->fetchAll(); @@ -112,11 +112,11 @@ class Collation implements IRepairStep { // fetch tables by collation $statement = $connection->executeQuery( - 'SELECT DISTINCT(TABLE_NAME) AS `table`' . - ' FROM INFORMATION_SCHEMA . TABLES' . - ' WHERE TABLE_SCHEMA = ?' . - " AND TABLE_COLLATION <> '" . $characterSet . "_bin'" . - " AND TABLE_NAME LIKE '*PREFIX*%'", + 'SELECT DISTINCT(TABLE_NAME) AS `table`' + . ' FROM INFORMATION_SCHEMA . TABLES' + . ' WHERE TABLE_SCHEMA = ?' + . " AND TABLE_COLLATION <> '" . $characterSet . "_bin'" + . " AND TABLE_NAME LIKE '*PREFIX*%'", [$dbName] ); $rows = $statement->fetchAll(); diff --git a/lib/private/Repair/ConfigKeyMigration.php b/lib/private/Repair/ConfigKeyMigration.php new file mode 100644 index 00000000000..da4aa153dc5 --- /dev/null +++ b/lib/private/Repair/ConfigKeyMigration.php @@ -0,0 +1,29 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Repair; + +use OC\Config\ConfigManager; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class ConfigKeyMigration implements IRepairStep { + public function __construct( + private ConfigManager $configManager, + ) { + } + + public function getName(): string { + return 'Migrate config keys'; + } + + public function run(IOutput $output) { + $this->configManager->migrateConfigLexiconKeys(); + } +} diff --git a/lib/private/Repair/MoveUpdaterStepFile.php b/lib/private/Repair/MoveUpdaterStepFile.php index c9b51b308c4..bb8f9d3acfc 100644 --- a/lib/private/Repair/MoveUpdaterStepFile.php +++ b/lib/private/Repair/MoveUpdaterStepFile.php @@ -1,10 +1,12 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OC\Repair; +use OCP\Files; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; @@ -40,7 +42,7 @@ class MoveUpdaterStepFile implements IRepairStep { // cleanup if (file_exists($previousStepFile)) { - if (\OC_Helper::rmdirr($previousStepFile)) { + if (Files::rmdirr($previousStepFile)) { $output->info('.step-previous-update removed'); } else { $output->info('.step-previous-update can\'t be removed - abort move of .step file'); diff --git a/lib/private/Repair/NC13/AddLogRotateJob.php b/lib/private/Repair/NC13/AddLogRotateJob.php index 8fe68a42819..bd6c510785f 100644 --- a/lib/private/Repair/NC13/AddLogRotateJob.php +++ b/lib/private/Repair/NC13/AddLogRotateJob.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php b/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php index a9cbbb4cbbf..646dd2c5e83 100644 --- a/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php +++ b/lib/private/Repair/NC16/CleanupCardDAVPhotoCache.php @@ -6,9 +6,10 @@ declare(strict_types=1); * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + namespace OC\Repair\NC16; -use OCP\Files\IAppData; +use OCP\Files\AppData\IAppDataFactory; use OCP\Files\NotFoundException; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IConfig; @@ -27,18 +28,11 @@ use RuntimeException; * photo could be returned for this vcard. These invalid files are removed by this migration step. */ class CleanupCardDAVPhotoCache implements IRepairStep { - /** @var IConfig */ - private $config; - - /** @var IAppData */ - private $appData; - - private LoggerInterface $logger; - - public function __construct(IConfig $config, IAppData $appData, LoggerInterface $logger) { - $this->config = $config; - $this->appData = $appData; - $this->logger = $logger; + public function __construct( + private IConfig $config, + private IAppDataFactory $appDataFactory, + private LoggerInterface $logger, + ) { } public function getName(): string { @@ -46,8 +40,10 @@ class CleanupCardDAVPhotoCache implements IRepairStep { } private function repair(IOutput $output): void { + $photoCacheAppData = $this->appDataFactory->get('dav-photocache'); + try { - $folders = $this->appData->getDirectoryListing(); + $folders = $photoCacheAppData->getDirectoryListing(); } catch (NotFoundException $e) { return; } catch (RuntimeException $e) { diff --git a/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php b/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php index 4f80b3809e8..5cee33b381c 100644 --- a/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php +++ b/lib/private/Repair/NC21/AddCheckForUserCertificatesJob.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/NC21/ValidatePhoneNumber.php b/lib/private/Repair/NC21/ValidatePhoneNumber.php deleted file mode 100644 index 3a6ace37bd2..00000000000 --- a/lib/private/Repair/NC21/ValidatePhoneNumber.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -namespace OC\Repair\NC21; - -use OCP\Accounts\IAccountManager; -use OCP\IConfig; -use OCP\IUser; -use OCP\IUserManager; -use OCP\Migration\IOutput; -use OCP\Migration\IRepairStep; - -class ValidatePhoneNumber implements IRepairStep { - /** @var IConfig */ - protected $config; - /** @var IUserManager */ - protected $userManager; - /** @var IAccountManager */ - private $accountManager; - - public function __construct(IUserManager $userManager, - IAccountManager $accountManager, - IConfig $config) { - $this->config = $config; - $this->userManager = $userManager; - $this->accountManager = $accountManager; - } - - public function getName(): string { - return 'Validate the phone number and store it in a known format for search'; - } - - public function run(IOutput $output): void { - if ($this->config->getSystemValueString('default_phone_region', '') === '') { - $output->warning('Can not validate phone numbers without `default_phone_region` being set in the config file'); - return; - } - - $numUpdated = 0; - $numRemoved = 0; - - $this->userManager->callForSeenUsers(function (IUser $user) use (&$numUpdated, &$numRemoved) { - $account = $this->accountManager->getAccount($user); - $property = $account->getProperty(IAccountManager::PROPERTY_PHONE); - - if ($property->getValue() !== '') { - $this->accountManager->updateAccount($account); - $updatedAccount = $this->accountManager->getAccount($user); - $updatedProperty = $updatedAccount->getProperty(IAccountManager::PROPERTY_PHONE); - - if ($property->getValue() !== $updatedProperty->getValue()) { - if ($updatedProperty->getValue() === '') { - $numRemoved++; - } else { - $numUpdated++; - } - } - } - }); - - if ($numRemoved > 0 || $numUpdated > 0) { - $output->info('Updated ' . $numUpdated . ' entries and cleaned ' . $numRemoved . ' invalid phone numbers'); - } - } -} diff --git a/lib/private/Repair/NC29/SanitizeAccountProperties.php b/lib/private/Repair/NC29/SanitizeAccountProperties.php new file mode 100644 index 00000000000..412570ba71d --- /dev/null +++ b/lib/private/Repair/NC29/SanitizeAccountProperties.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Repair\NC29; + +use OCP\BackgroundJob\IJobList; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class SanitizeAccountProperties implements IRepairStep { + + public function __construct( + private IJobList $jobList, + ) { + } + + public function getName(): string { + return 'Validate account properties and store phone numbers in a known format for search'; + } + + public function run(IOutput $output): void { + $this->jobList->add(SanitizeAccountPropertiesJob::class, null); + $output->info('Queued background to validate account properties.'); + } +} diff --git a/lib/private/Repair/NC29/SanitizeAccountPropertiesJob.php b/lib/private/Repair/NC29/SanitizeAccountPropertiesJob.php new file mode 100644 index 00000000000..55ec445e9da --- /dev/null +++ b/lib/private/Repair/NC29/SanitizeAccountPropertiesJob.php @@ -0,0 +1,75 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Repair\NC29; + +use InvalidArgumentException; +use OCP\Accounts\IAccountManager; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\BackgroundJob\QueuedJob; +use OCP\IUser; +use OCP\IUserManager; +use Psr\Log\LoggerInterface; + +class SanitizeAccountPropertiesJob extends QueuedJob { + + private const PROPERTIES_TO_CHECK = [ + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + IAccountManager::PROPERTY_FEDIVERSE, + ]; + + public function __construct( + ITimeFactory $timeFactory, + private IUserManager $userManager, + private IAccountManager $accountManager, + private LoggerInterface $logger, + ) { + parent::__construct($timeFactory); + $this->setAllowParallelRuns(false); + } + + protected function run(mixed $argument): void { + $numRemoved = 0; + + $this->userManager->callForSeenUsers(function (IUser $user) use (&$numRemoved) { + $account = $this->accountManager->getAccount($user); + $properties = array_keys($account->jsonSerialize()); + + // Check if there are some properties we can sanitize - reduces number of db queries + if (empty(array_intersect($properties, self::PROPERTIES_TO_CHECK))) { + return; + } + + // Limit the loop to the properties we check to ensure there are no infinite loops + // we add one additional loop (+ 1) as we need 1 loop for checking + 1 for update. + $iteration = count(self::PROPERTIES_TO_CHECK) + 1; + while ($iteration-- > 0) { + try { + $this->accountManager->updateAccount($account); + return; + } catch (InvalidArgumentException $e) { + if (in_array($e->getMessage(), IAccountManager::ALLOWED_PROPERTIES)) { + $numRemoved++; + $property = $account->getProperty($e->getMessage()); + $account->setProperty($property->getName(), '', $property->getScope(), IAccountManager::NOT_VERIFIED); + } else { + $this->logger->error('Error while sanitizing account property', ['exception' => $e, 'user' => $user->getUID()]); + return; + } + } + } + $this->logger->error('Iteration limit exceeded while cleaning account properties', ['user' => $user->getUID()]); + }); + + if ($numRemoved > 0) { + $this->logger->info('Cleaned ' . $numRemoved . ' invalid account property entries'); + } + } +} diff --git a/lib/private/Repair/Owncloud/CleanPreviews.php b/lib/private/Repair/Owncloud/CleanPreviews.php index 86e173cf402..50ee965e087 100644 --- a/lib/private/Repair/Owncloud/CleanPreviews.php +++ b/lib/private/Repair/Owncloud/CleanPreviews.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/Owncloud/DropAccountTermsTable.php b/lib/private/Repair/Owncloud/DropAccountTermsTable.php index 18f169c9b49..534825c146a 100644 --- a/lib/private/Repair/Owncloud/DropAccountTermsTable.php +++ b/lib/private/Repair/Owncloud/DropAccountTermsTable.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/Owncloud/MigrateOauthTables.php b/lib/private/Repair/Owncloud/MigrateOauthTables.php index 02f89db6c24..de26a907e02 100644 --- a/lib/private/Repair/Owncloud/MigrateOauthTables.php +++ b/lib/private/Repair/Owncloud/MigrateOauthTables.php @@ -1,25 +1,37 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + namespace OC\Repair\Owncloud; +use OC\Authentication\Token\IProvider as ITokenProvider; use OC\DB\Connection; use OC\DB\SchemaWrapper; +use OCA\OAuth2\Db\AccessToken; +use OCA\OAuth2\Db\AccessTokenMapper; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\Authentication\Token\IToken; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\IConfig; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; +use OCP\Security\ICrypto; +use OCP\Security\ISecureRandom; class MigrateOauthTables implements IRepairStep { - /** @var Connection */ - protected $db; - /** - * @param Connection $db - */ - public function __construct(Connection $db) { - $this->db = $db; + public function __construct( + protected Connection $db, + private AccessTokenMapper $accessTokenMapper, + private ITokenProvider $tokenProvider, + private ISecureRandom $random, + private ITimeFactory $timeFactory, + private ICrypto $crypto, + private IConfig $config, + ) { } /** @@ -36,14 +48,23 @@ class MigrateOauthTables implements IRepairStep { return; } - $output->info('Update the oauth2_access_tokens table schema.'); + // Create column and then migrate before handling unique index. + // So that we can distinguish between legacy (from oc) and new rows (from nc). $table = $schema->getTable('oauth2_access_tokens'); if (!$table->hasColumn('hashed_code')) { + $output->info('Prepare the oauth2_access_tokens table schema.'); $table->addColumn('hashed_code', 'string', [ 'notnull' => true, 'length' => 128, ]); + + // Regenerate schema after migrating to it + $this->db->migrateToSchema($schema->getWrappedSchema()); + $schema = new SchemaWrapper($this->db); } + + $output->info('Update the oauth2_access_tokens table schema.'); + $table = $schema->getTable('oauth2_access_tokens'); if (!$table->hasColumn('encrypted_token')) { $table->addColumn('encrypted_token', 'string', [ 'notnull' => true, @@ -51,11 +72,31 @@ class MigrateOauthTables implements IRepairStep { ]); } if (!$table->hasIndex('oauth2_access_hash_idx')) { + // Drop legacy access codes first to prevent integrity constraint violations + $qb = $this->db->getQueryBuilder(); + $qb->delete('oauth2_access_tokens') + ->where($qb->expr()->eq('hashed_code', $qb->createNamedParameter(''))); + $qb->executeStatement(); + $table->addUniqueIndex(['hashed_code'], 'oauth2_access_hash_idx'); } if (!$table->hasIndex('oauth2_access_client_id_idx')) { $table->addIndex(['client_id'], 'oauth2_access_client_id_idx'); } + if (!$table->hasColumn('token_id')) { + $table->addColumn('token_id', 'integer', [ + 'notnull' => true, + ]); + } + if ($table->hasColumn('expires')) { + $table->dropColumn('expires'); + } + if ($table->hasColumn('user_id')) { + $table->dropColumn('user_id'); + } + if ($table->hasColumn('token')) { + $table->dropColumn('token'); + } $output->info('Update the oauth2_clients table schema.'); $table = $schema->getTable('oauth2_clients'); @@ -99,10 +140,10 @@ class MigrateOauthTables implements IRepairStep { $table->addIndex(['client_identifier'], 'oauth2_client_id_idx'); } - $this->db->migrateToSchema($schema->getWrappedSchema()); - // Regenerate schema after migrating to it + $this->db->migrateToSchema($schema->getWrappedSchema()); $schema = new SchemaWrapper($this->db); + if ($schema->getTable('oauth2_clients')->hasColumn('identifier')) { $output->info("Move identifier column's data to the new client_identifier column."); // 1. Fetch all [id, identifier] couple. @@ -124,10 +165,18 @@ class MigrateOauthTables implements IRepairStep { $output->info('Drop the identifier column.'); $table = $schema->getTable('oauth2_clients'); $table->dropColumn('identifier'); + + // Regenerate schema after migrating to it $this->db->migrateToSchema($schema->getWrappedSchema()); + $schema = new SchemaWrapper($this->db); } - $output->info('Delete clients (and their related access tokens) with the redirect_uri starting with oc:// or ending with *'); + $enableOcClients = $this->config->getSystemValueBool('oauth2.enable_oc_clients', false); + if ($enableOcClients) { + $output->info('Delete clients (and their related access tokens) with the redirect_uri starting with oc://'); + } else { + $output->info('Delete clients (and their related access tokens) with the redirect_uri starting with oc:// or ending with *'); + } // delete the access tokens $qbDeleteAccessTokens = $this->db->getQueryBuilder(); @@ -136,10 +185,12 @@ class MigrateOauthTables implements IRepairStep { ->from('oauth2_clients') ->where( $qbSelectClientId->expr()->iLike('redirect_uri', $qbDeleteAccessTokens->createNamedParameter('oc://%', IQueryBuilder::PARAM_STR)) - ) - ->orWhere( + ); + if (!$enableOcClients) { + $qbSelectClientId->orWhere( $qbSelectClientId->expr()->iLike('redirect_uri', $qbDeleteAccessTokens->createNamedParameter('%*', IQueryBuilder::PARAM_STR)) ); + } $qbDeleteAccessTokens->delete('oauth2_access_tokens') ->where( @@ -152,10 +203,57 @@ class MigrateOauthTables implements IRepairStep { $qbDeleteClients->delete('oauth2_clients') ->where( $qbDeleteClients->expr()->iLike('redirect_uri', $qbDeleteClients->createNamedParameter('oc://%', IQueryBuilder::PARAM_STR)) - ) - ->orWhere( + ); + if (!$enableOcClients) { + $qbDeleteClients->orWhere( $qbDeleteClients->expr()->iLike('redirect_uri', $qbDeleteClients->createNamedParameter('%*', IQueryBuilder::PARAM_STR)) ); + } $qbDeleteClients->executeStatement(); + + // Migrate legacy refresh tokens from oc + if ($schema->hasTable('oauth2_refresh_tokens')) { + $output->info('Migrate legacy oauth2 refresh tokens.'); + + $qbSelect = $this->db->getQueryBuilder(); + $qbSelect->select('*') + ->from('oauth2_refresh_tokens'); + $result = $qbSelect->executeQuery(); + $now = $this->timeFactory->now()->getTimestamp(); + $index = 0; + while ($row = $result->fetch()) { + $clientId = $row['client_id']; + $refreshToken = $row['token']; + + // Insert expired token so that it can be rotated on the next refresh + $accessToken = $this->random->generate(72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS); + $authToken = $this->tokenProvider->generateToken( + $accessToken, + $row['user_id'], + $row['user_id'], + null, + "oc_migrated_client{$clientId}_t{$now}_i$index", + IToken::PERMANENT_TOKEN, + IToken::DO_NOT_REMEMBER, + ); + $authToken->setExpires($now - 3600); + $this->tokenProvider->updateToken($authToken); + + $accessTokenEntity = new AccessToken(); + $accessTokenEntity->setTokenId($authToken->getId()); + $accessTokenEntity->setClientId($clientId); + $accessTokenEntity->setHashedCode(hash('sha512', $refreshToken)); + $accessTokenEntity->setEncryptedToken($this->crypto->encrypt($accessToken, $refreshToken)); + $accessTokenEntity->setCodeCreatedAt($now); + $accessTokenEntity->setTokenCount(1); + $this->accessTokenMapper->insert($accessTokenEntity); + + $index++; + } + $result->closeCursor(); + + $schema->dropTable('oauth2_refresh_tokens'); + $schema->performDropTableCalls(); + } } } diff --git a/lib/private/Repair/Owncloud/MoveAvatars.php b/lib/private/Repair/Owncloud/MoveAvatars.php index 7fdabae7a66..9e3f4b89b13 100644 --- a/lib/private/Repair/Owncloud/MoveAvatars.php +++ b/lib/private/Repair/Owncloud/MoveAvatars.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/Owncloud/SaveAccountsTableData.php b/lib/private/Repair/Owncloud/SaveAccountsTableData.php index 08665687b29..ab1560ddb8d 100644 --- a/lib/private/Repair/Owncloud/SaveAccountsTableData.php +++ b/lib/private/Repair/Owncloud/SaveAccountsTableData.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/Owncloud/UpdateLanguageCodes.php b/lib/private/Repair/Owncloud/UpdateLanguageCodes.php index e27ab06b2f3..8d9046ad49f 100644 --- a/lib/private/Repair/Owncloud/UpdateLanguageCodes.php +++ b/lib/private/Repair/Owncloud/UpdateLanguageCodes.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Repair/RepairMimeTypes.php b/lib/private/Repair/RepairMimeTypes.php index 715f7623440..3c9720b9e91 100644 --- a/lib/private/Repair/RepairMimeTypes.php +++ b/lib/private/Repair/RepairMimeTypes.php @@ -338,6 +338,21 @@ class RepairMimeTypes implements IRepairStep { } /** + * @throws Exception + * @since 32.0.0 + */ + private function introduceMusicxmlType(): IResult|int|null { + $updatedMimetypes = [ + 'mxl' => 'application/vnd.recordare.musicxml', + 'musicxml' => 'application/vnd.recordare.musicxml+xml', + ]; + + return $this->updateMimetypes($updatedMimetypes); + } + + + + /** * Check if there are any migrations available * * @throws Exception @@ -447,6 +462,10 @@ class RepairMimeTypes implements IRepairStep { $out->info('Fixed zst mime type'); } + if (version_compare($mimeTypeVersion, '32.0.0.0', '<') && $this->introduceMusicxmlType()) { + $out->info('Fixed musicxml mime type'); + } + if (!$this->dryRun) { $this->appConfig->setValueString('files', 'mimetype_version', $serverVersion); } diff --git a/lib/private/RichObjectStrings/Validator.php b/lib/private/RichObjectStrings/Validator.php index f3d2ffd5723..adc4a8710f7 100644 --- a/lib/private/RichObjectStrings/Validator.php +++ b/lib/private/RichObjectStrings/Validator.php @@ -56,7 +56,7 @@ class Validator implements IValidator { throw new InvalidObjectExeption('Parameter is malformed'); } - $this->validateParameter($parameter); + $this->validateParameter($placeholder, $parameter); } } @@ -64,7 +64,7 @@ class Validator implements IValidator { * @param array $parameter * @throws InvalidObjectExeption */ - protected function validateParameter(array $parameter): void { + protected function validateParameter(string $placeholder, array $parameter): void { if (!isset($parameter['type'])) { throw new InvalidObjectExeption('Object type is undefined'); } @@ -74,15 +74,15 @@ class Validator implements IValidator { $missingKeys = array_diff($requiredParameters, array_keys($parameter)); if (!empty($missingKeys)) { - throw new InvalidObjectExeption('Object is invalid, missing keys:' . json_encode($missingKeys)); + throw new InvalidObjectExeption('Object for placeholder ' . $placeholder . ' is invalid, missing keys:' . json_encode($missingKeys)); } foreach ($parameter as $key => $value) { if (!is_string($key)) { - throw new InvalidObjectExeption('Object is invalid, key ' . $key . ' is not a string'); + throw new InvalidObjectExeption('Object for placeholder ' . $placeholder . ' is invalid, key ' . $key . ' is not a string'); } if (!is_string($value)) { - throw new InvalidObjectExeption('Object is invalid, value ' . $value . ' is not a string'); + throw new InvalidObjectExeption('Object for placeholder ' . $placeholder . ' is invalid, value ' . $value . ' for key ' . $key . ' is not a string'); } } } diff --git a/lib/private/Route/CachingRouter.php b/lib/private/Route/CachingRouter.php index 7dd26827d3c..becdb807f73 100644 --- a/lib/private/Route/CachingRouter.php +++ b/lib/private/Route/CachingRouter.php @@ -15,10 +15,16 @@ use OCP\IConfig; use OCP\IRequest; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\RouteCollection; class CachingRouter extends Router { protected ICache $cache; + protected array $legacyCreatedRoutes = []; + public function __construct( ICacheFactory $cacheFactory, LoggerInterface $logger, @@ -54,4 +60,98 @@ class CachingRouter extends Router { return $url; } } + + private function serializeRouteCollection(RouteCollection $collection): array { + $dumper = new CompiledUrlMatcherDumper($collection); + return $dumper->getCompiledRoutes(); + } + + /** + * Find the route matching $url + * + * @param string $url The url to find + * @throws \Exception + * @return array + */ + public function findMatchingRoute(string $url): array { + $this->eventLogger->start('cacheroute:match', 'Match route'); + $key = $this->context->getHost() . '#' . $this->context->getBaseUrl() . '#rootCollection'; + $cachedRoutes = $this->cache->get($key); + if (!$cachedRoutes) { + parent::loadRoutes(); + $cachedRoutes = $this->serializeRouteCollection($this->root); + $this->cache->set($key, $cachedRoutes, ($this->config->getSystemValueBool('debug') ? 3 : 3600)); + } + $matcher = new CompiledUrlMatcher($cachedRoutes, $this->context); + $this->eventLogger->start('cacheroute:url:match', 'Symfony URL match call'); + try { + $parameters = $matcher->match($url); + } catch (ResourceNotFoundException $e) { + if (!str_ends_with($url, '/')) { + // We allow links to apps/files? for backwards compatibility reasons + // However, since Symfony does not allow empty route names, the route + // we need to match is '/', so we need to append the '/' here. + try { + $parameters = $matcher->match($url . '/'); + } catch (ResourceNotFoundException $newException) { + // If we still didn't match a route, we throw the original exception + throw $e; + } + } else { + throw $e; + } + } + $this->eventLogger->end('cacheroute:url:match'); + + $this->eventLogger->end('cacheroute:match'); + return $parameters; + } + + /** + * @param array{action:mixed, ...} $parameters + */ + protected function callLegacyActionRoute(array $parameters): void { + /* + * Closures cannot be serialized to cache, so for legacy routes calling an action we have to include the routes.php file again + */ + $app = $parameters['app']; + $this->useCollection($app); + parent::requireRouteFile($parameters['route-file'], $app); + $collection = $this->getCollection($app); + $parameters['action'] = $collection->get($parameters['_route'])?->getDefault('action'); + parent::callLegacyActionRoute($parameters); + } + + /** + * Create a \OC\Route\Route. + * Deprecated + * + * @param string $name Name of the route to create. + * @param string $pattern The pattern to match + * @param array $defaults An array of default parameter values + * @param array $requirements An array of requirements for parameters (regexes) + */ + public function create($name, $pattern, array $defaults = [], array $requirements = []): Route { + $this->legacyCreatedRoutes[] = $name; + return parent::create($name, $pattern, $defaults, $requirements); + } + + /** + * Require a routes.php file + */ + protected function requireRouteFile(string $file, string $appName): void { + $this->legacyCreatedRoutes = []; + parent::requireRouteFile($file, $appName); + foreach ($this->legacyCreatedRoutes as $routeName) { + $route = $this->collection?->get($routeName); + if ($route === null) { + /* Should never happen */ + throw new \Exception("Could not find route $routeName"); + } + if ($route->hasDefault('action')) { + $route->setDefault('route-file', $file); + $route->setDefault('app', $appName); + } + } + } } diff --git a/lib/private/Route/Route.php b/lib/private/Route/Route.php index ab5a1f6b59a..08231649e76 100644 --- a/lib/private/Route/Route.php +++ b/lib/private/Route/Route.php @@ -124,15 +124,9 @@ class Route extends SymfonyRoute implements IRoute { * The action to execute when this route matches, includes a file like * it is called directly * @param string $file - * @return void */ public function actionInclude($file) { - $function = function ($param) use ($file) { - unset($param['_route']); - $_GET = array_merge($_GET, $param); - unset($param); - require_once "$file"; - } ; - $this->action($function); + $this->setDefault('file', $file); + return $this; } } diff --git a/lib/private/Route/Router.php b/lib/private/Route/Router.php index 886e70c9a35..90225212e9a 100644 --- a/lib/private/Route/Router.php +++ b/lib/private/Route/Router.php @@ -53,10 +53,10 @@ class Router implements IRouter { public function __construct( protected LoggerInterface $logger, IRequest $request, - private IConfig $config, - private IEventLogger $eventLogger, + protected IConfig $config, + protected IEventLogger $eventLogger, private ContainerInterface $container, - private IAppManager $appManager, + protected IAppManager $appManager, ) { $baseUrl = \OC::$WEBROOT; if (!($config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true')) { @@ -74,6 +74,14 @@ class Router implements IRouter { $this->root = $this->getCollection('root'); } + public function setContext(RequestContext $context): void { + $this->context = $context; + } + + public function getRouteCollection() { + return $this->root; + } + /** * Get the files to load the routes from * @@ -82,7 +90,7 @@ class Router implements IRouter { public function getRoutingFiles() { if ($this->routingFiles === null) { $this->routingFiles = []; - foreach (\OC_APP::getEnabledApps() as $app) { + foreach ($this->appManager->getEnabledApps() as $app) { try { $appPath = $this->appManager->getAppPath($app); $file = $appPath . '/appinfo/routes.php'; @@ -102,7 +110,7 @@ class Router implements IRouter { * * @param null|string $app */ - public function loadRoutes($app = null) { + public function loadRoutes(?string $app = null, bool $skipLoadingCore = false): void { if (is_string($app)) { $app = $this->appManager->cleanAppId($app); } @@ -116,9 +124,11 @@ class Router implements IRouter { $this->loaded = true; $routingFiles = $this->getRoutingFiles(); - foreach (\OC_App::getEnabledApps() as $enabledApp) { + $this->eventLogger->start('route:load:attributes', 'Loading Routes from attributes'); + foreach ($this->appManager->getEnabledApps() as $enabledApp) { $this->loadAttributeRoutes($enabledApp); } + $this->eventLogger->end('route:load:attributes'); } else { if (isset($this->loadedApps[$app])) { return; @@ -140,9 +150,10 @@ class Router implements IRouter { } } + $this->eventLogger->start('route:load:files', 'Loading Routes from files'); foreach ($routingFiles as $app => $file) { if (!isset($this->loadedApps[$app])) { - if (!\OC_App::isAppLoaded($app)) { + if (!$this->appManager->isAppLoaded($app)) { // app MUST be loaded before app routes // try again next time loadRoutes() is called $this->loaded = false; @@ -160,11 +171,13 @@ class Router implements IRouter { $this->root->addCollection($collection); } } - if (!isset($this->loadedApps['core'])) { + $this->eventLogger->end('route:load:files'); + + if (!$skipLoadingCore && !isset($this->loadedApps['core'])) { $this->loadedApps['core'] = true; $this->useCollection('root'); $this->setupRoutes($this->getAttributeRoutes('core'), 'core'); - require_once __DIR__ . '/../../../core/routes.php'; + $this->requireRouteFile(__DIR__ . '/../../../core/routes.php', 'core'); // Also add the OCS collection $collection = $this->getCollection('root.ocs'); @@ -256,14 +269,15 @@ class Router implements IRouter { $this->loadRoutes('settings'); } elseif (str_starts_with($url, '/core/')) { \OC::$REQUESTEDAPP = $url; - if (!$this->config->getSystemValueBool('maintenance') && !Util::needUpgrade()) { - \OC_App::loadApps(); + if ($this->config->getSystemValueBool('installed', false) && !Util::needUpgrade()) { + $this->appManager->loadApps(); } $this->loadRoutes('core'); } else { $this->loadRoutes(); } + $this->eventLogger->start('route:url:match', 'Symfony url matcher call'); $matcher = new UrlMatcher($this->root, $this->context); try { $parameters = $matcher->match($url); @@ -282,6 +296,7 @@ class Router implements IRouter { throw $e; } } + $this->eventLogger->end('route:url:match'); $this->eventLogger->end('route:match'); return $parameters; @@ -305,17 +320,11 @@ class Router implements IRouter { $application = $this->getApplicationClass($caller[0]); \OC\AppFramework\App::main($caller[1], $caller[2], $application->getContainer(), $parameters); } elseif (isset($parameters['action'])) { - $action = $parameters['action']; - if (!is_callable($action)) { - throw new \Exception('not a callable action'); - } - unset($parameters['action']); - unset($parameters['caller']); - $this->eventLogger->start('route:run:call', 'Run callable route'); - call_user_func($action, $parameters); - $this->eventLogger->end('route:run:call'); + $this->logger->warning('Deprecated action route used', ['parameters' => $parameters]); + $this->callLegacyActionRoute($parameters); } elseif (isset($parameters['file'])) { - include $parameters['file']; + $this->logger->debug('Deprecated file route used', ['parameters' => $parameters]); + $this->includeLegacyFileRoute($parameters); } else { throw new \Exception('no action available'); } @@ -323,6 +332,32 @@ class Router implements IRouter { } /** + * @param array{file:mixed, ...} $parameters + */ + protected function includeLegacyFileRoute(array $parameters): void { + $param = $parameters; + unset($param['_route']); + $_GET = array_merge($_GET, $param); + unset($param); + require_once $parameters['file']; + } + + /** + * @param array{action:mixed, ...} $parameters + */ + protected function callLegacyActionRoute(array $parameters): void { + $action = $parameters['action']; + if (!is_callable($action)) { + throw new \Exception('not a callable action'); + } + unset($parameters['action']); + unset($parameters['caller']); + $this->eventLogger->start('route:run:call', 'Run callable route'); + call_user_func($action, $parameters); + $this->eventLogger->end('route:run:call'); + } + + /** * Get the url generator * * @return \Symfony\Component\Routing\Generator\UrlGenerator @@ -485,8 +520,8 @@ class Router implements IRouter { * @param string $file the route file location to include * @param string $appName */ - private function requireRouteFile($file, $appName) { - $this->setupRoutes(include_once $file, $appName); + protected function requireRouteFile(string $file, string $appName): void { + $this->setupRoutes(include $file, $appName); } diff --git a/lib/private/Security/Bruteforce/Throttler.php b/lib/private/Security/Bruteforce/Throttler.php index 924ae3685f3..574f6c80c3f 100644 --- a/lib/private/Security/Bruteforce/Throttler.php +++ b/lib/private/Security/Bruteforce/Throttler.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace OC\Security\Bruteforce; use OC\Security\Bruteforce\Backend\IBackend; +use OC\Security\Ip\BruteforceAllowList; use OC\Security\Normalizer\IpAddress; use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; @@ -32,14 +33,13 @@ use Psr\Log\LoggerInterface; class Throttler implements IThrottler { /** @var bool[] */ private array $hasAttemptsDeleted = []; - /** @var bool[] */ - private array $ipIsWhitelisted = []; public function __construct( private ITimeFactory $timeFactory, private LoggerInterface $logger, private IConfig $config, private IBackend $backend, + private BruteforceAllowList $allowList, ) { } @@ -83,70 +83,7 @@ class Throttler implements IThrottler { * Check if the IP is whitelisted */ public function isBypassListed(string $ip): bool { - if (isset($this->ipIsWhitelisted[$ip])) { - return $this->ipIsWhitelisted[$ip]; - } - - if (!$this->config->getSystemValueBool('auth.bruteforce.protection.enabled', true)) { - $this->ipIsWhitelisted[$ip] = true; - return true; - } - - $keys = $this->config->getAppKeys('bruteForce'); - $keys = array_filter($keys, function ($key) { - return str_starts_with($key, 'whitelist_'); - }); - - if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { - $type = 4; - } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { - $type = 6; - } else { - $this->ipIsWhitelisted[$ip] = false; - return false; - } - - $ip = inet_pton($ip); - - foreach ($keys as $key) { - $cidr = $this->config->getAppValue('bruteForce', $key, null); - - $cx = explode('/', $cidr); - $addr = $cx[0]; - $mask = (int)$cx[1]; - - // Do not compare ipv4 to ipv6 - if (($type === 4 && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) || - ($type === 6 && !filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))) { - continue; - } - - $addr = inet_pton($addr); - - $valid = true; - for ($i = 0; $i < $mask; $i++) { - $part = ord($addr[(int)($i / 8)]); - $orig = ord($ip[(int)($i / 8)]); - - $bitmask = 1 << (7 - ($i % 8)); - - $part = $part & $bitmask; - $orig = $orig & $bitmask; - - if ($part !== $orig) { - $valid = false; - break; - } - } - - if ($valid === true) { - $this->ipIsWhitelisted[$ip] = true; - return true; - } - } - - $this->ipIsWhitelisted[$ip] = false; - return false; + return $this->allowList->isBypassListed($ip); } /** @@ -190,6 +127,13 @@ class Throttler implements IThrottler { */ public function getDelay(string $ip, string $action = ''): int { $attempts = $this->getAttempts($ip, $action); + return $this->calculateDelay($attempts); + } + + /** + * {@inheritDoc} + */ + public function calculateDelay(int $attempts): int { if ($attempts === 0) { return 0; } @@ -262,25 +206,31 @@ class Throttler implements IThrottler { * {@inheritDoc} */ public function sleepDelayOrThrowOnMax(string $ip, string $action = ''): int { - $delay = $this->getDelay($ip, $action); - if (($delay === self::MAX_DELAY_MS) && $this->getAttempts($ip, $action, 0.5) > $this->config->getSystemValueInt('auth.bruteforce.max-attempts', self::MAX_ATTEMPTS)) { - $this->logger->info('IP address blocked because it reached the maximum failed attempts in the last 30 minutes [action: {action}, ip: {ip}]', [ - 'action' => $action, - 'ip' => $ip, - ]); - // If the ip made too many attempts within the last 30 mins we don't execute anymore - throw new MaxDelayReached('Reached maximum delay'); - } - if ($delay > 100) { - $this->logger->info('IP address throttled because it reached the attempts limit in the last 30 minutes [action: {action}, delay: {delay}, ip: {ip}]', [ + $maxAttempts = $this->config->getSystemValueInt('auth.bruteforce.max-attempts', self::MAX_ATTEMPTS); + $attempts = $this->getAttempts($ip, $action); + if ($attempts > $maxAttempts) { + $attempts30mins = $this->getAttempts($ip, $action, 0.5); + if ($attempts30mins > $maxAttempts) { + $this->logger->info('IP address blocked because it reached the maximum failed attempts in the last 30 minutes [action: {action}, attempts: {attempts}, ip: {ip}]', [ + 'action' => $action, + 'ip' => $ip, + 'attempts' => $attempts30mins, + ]); + // If the ip made too many attempts within the last 30 mins we don't execute anymore + throw new MaxDelayReached('Reached maximum delay'); + } + + $this->logger->info('IP address throttled because it reached the attempts limit in the last 12 hours [action: {action}, attempts: {attempts}, ip: {ip}]', [ 'action' => $action, 'ip' => $ip, - 'delay' => $delay, + 'attempts' => $attempts, ]); } - if (!$this->config->getSystemValueBool('auth.bruteforce.protection.testing')) { - usleep($delay * 1000); + + if ($attempts > 0) { + return $this->calculateDelay($attempts); } - return $delay; + + return 0; } } diff --git a/lib/private/Security/Hasher.php b/lib/private/Security/Hasher.php index ba661f5a356..722fdab902f 100644 --- a/lib/private/Security/Hasher.php +++ b/lib/private/Security/Hasher.php @@ -106,8 +106,8 @@ class Hasher implements IHasher { // Verify whether it matches a legacy PHPass or SHA1 string $hashLength = \strlen($hash); - if (($hashLength === 60 && password_verify($message . $this->legacySalt, $hash)) || - ($hashLength === 40 && hash_equals($hash, sha1($message)))) { + if (($hashLength === 60 && password_verify($message . $this->legacySalt, $hash)) + || ($hashLength === 40 && hash_equals($hash, sha1($message)))) { $newHash = $this->hash($message); return true; } @@ -115,8 +115,8 @@ class Hasher implements IHasher { // Verify whether it matches a legacy PHPass or SHA1 string // Retry with empty passwordsalt for cases where it was not set $hashLength = \strlen($hash); - if (($hashLength === 60 && password_verify($message, $hash)) || - ($hashLength === 40 && hash_equals($hash, sha1($message)))) { + if (($hashLength === 60 && password_verify($message, $hash)) + || ($hashLength === 40 && hash_equals($hash, sha1($message)))) { $newHash = $this->hash($message); return true; } diff --git a/lib/private/Security/Ip/BruteforceAllowList.php b/lib/private/Security/Ip/BruteforceAllowList.php new file mode 100644 index 00000000000..cc4f0ceebe5 --- /dev/null +++ b/lib/private/Security/Ip/BruteforceAllowList.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Security\Ip; + +use OCP\IAppConfig; +use OCP\Security\Ip\IFactory; + +class BruteforceAllowList { + /** @var array<string, bool> */ + protected array $ipIsAllowListed = []; + + public function __construct( + private readonly IAppConfig $appConfig, + private readonly IFactory $factory, + ) { + } + + /** + * Check if the IP is allowed to bypass bruteforce protection + */ + public function isBypassListed(string $ip): bool { + if (isset($this->ipIsAllowListed[$ip])) { + return $this->ipIsAllowListed[$ip]; + } + + try { + $address = $this->factory->addressFromString($ip); + } catch (\InvalidArgumentException) { + $this->ipIsAllowListed[$ip] = false; + return false; + } + + $keys = $this->appConfig->getKeys('bruteForce'); + $keys = array_filter($keys, static fn ($key): bool => str_starts_with($key, 'whitelist_')); + + foreach ($keys as $key) { + $rangeString = $this->appConfig->getValueString('bruteForce', $key); + try { + $range = $this->factory->rangeFromString($rangeString); + } catch (\InvalidArgumentException) { + continue; + } + + $allowed = $range->contains($address); + if ($allowed) { + $this->ipIsAllowListed[$ip] = true; + return true; + } + } + + $this->ipIsAllowListed[$ip] = false; + return false; + } +} diff --git a/lib/private/Security/Normalizer/IpAddress.php b/lib/private/Security/Normalizer/IpAddress.php index e9232c5fe9f..4d33a7bd632 100644 --- a/lib/private/Security/Normalizer/IpAddress.php +++ b/lib/private/Security/Normalizer/IpAddress.php @@ -8,6 +8,8 @@ declare(strict_types=1); */ namespace OC\Security\Normalizer; +use OCP\IConfig; + /** * Class IpAddress is used for normalizing IPv4 and IPv6 addresses in security * relevant contexts in Nextcloud. @@ -24,7 +26,8 @@ class IpAddress { } /** - * Return the given subnet for an IPv6 address (64 first bits) + * Return the given subnet for an IPv6 address + * Rely on security.ipv6_normalized_subnet_size, defaults to 56 */ private function getIPv6Subnet(string $ip): string { if ($ip[0] === '[' && $ip[-1] === ']') { // If IP is with brackets, for example [::1] @@ -35,10 +38,25 @@ class IpAddress { $ip = substr($ip, 0, $pos - 1); } - $binary = \inet_pton($ip); - $mask = inet_pton('FFFF:FFFF:FFFF:FFFF::'); + $config = \OCP\Server::get(IConfig::class); + $maskSize = min(64, $config->getSystemValueInt('security.ipv6_normalized_subnet_size', 56)); + $maskSize = max(32, $maskSize); + if (PHP_INT_SIZE === 4) { + if ($maskSize === 64) { + $value = -1; + } elseif ($maskSize === 63) { + $value = PHP_INT_MAX; + } else { + $value = (1 << $maskSize - 32) - 1; + } + // as long as we support 32bit PHP we cannot use the `P` pack formatter (and not overflow 32bit integer) + $mask = pack('VVVV', -1, $value, 0, 0); + } else { + $mask = pack('VVP', (1 << 32) - 1, (1 << $maskSize - 32) - 1, 0); + } - return inet_ntop($binary & $mask) . '/64'; + $binary = \inet_pton($ip); + return inet_ntop($binary & $mask) . '/' . $maskSize; } /** @@ -63,7 +81,7 @@ class IpAddress { /** - * Gets either the /32 (IPv4) or the /64 (IPv6) subnet of an IP address + * Gets either the /32 (IPv4) or the /56 (default for IPv6) subnet of an IP address */ public function getSubnet(): string { if (filter_var($this->ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { diff --git a/lib/private/Security/RateLimiting/Limiter.php b/lib/private/Security/RateLimiting/Limiter.php index b7ac26d9132..316becfa009 100644 --- a/lib/private/Security/RateLimiting/Limiter.php +++ b/lib/private/Security/RateLimiting/Limiter.php @@ -13,10 +13,12 @@ use OC\Security\RateLimiting\Backend\IBackend; use OC\Security\RateLimiting\Exception\RateLimitExceededException; use OCP\IUser; use OCP\Security\RateLimiting\ILimiter; +use Psr\Log\LoggerInterface; class Limiter implements ILimiter { public function __construct( private IBackend $backend, + private LoggerInterface $logger, ) { } @@ -32,6 +34,11 @@ class Limiter implements ILimiter { ): void { $existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier); if ($existingAttempts >= $limit) { + $this->logger->info('Request blocked because it exceeds the rate limit [method: {method}, limit: {limit}, period: {period}]', [ + 'method' => $methodIdentifier, + 'limit' => $limit, + 'period' => $period, + ]); throw new RateLimitExceededException(); } diff --git a/lib/private/Security/Signature/Model/SignedRequest.php b/lib/private/Security/Signature/Model/SignedRequest.php index f30935e83b1..12a43f32bcc 100644 --- a/lib/private/Security/Signature/Model/SignedRequest.php +++ b/lib/private/Security/Signature/Model/SignedRequest.php @@ -74,8 +74,8 @@ class SignedRequest implements ISignedRequest, JsonSerializable { */ public function getDigest(): string { if ($this->digest === '') { - $this->digest = $this->digestAlgorithm->value . '=' . - base64_encode(hash($this->digestAlgorithm->getHashingAlgorithm(), $this->body, true)); + $this->digest = $this->digestAlgorithm->value . '=' + . base64_encode(hash($this->digestAlgorithm->getHashingAlgorithm(), $this->body, true)); } return $this->digest; } diff --git a/lib/private/Security/VerificationToken/VerificationToken.php b/lib/private/Security/VerificationToken/VerificationToken.php index 1995b482597..89f45180359 100644 --- a/lib/private/Security/VerificationToken/VerificationToken.php +++ b/lib/private/Security/VerificationToken/VerificationToken.php @@ -85,9 +85,9 @@ class VerificationToken implements IVerificationToken { ): string { $token = $this->secureRandom->generate( 21, - ISecureRandom::CHAR_DIGITS . - ISecureRandom::CHAR_LOWER . - ISecureRandom::CHAR_UPPER + ISecureRandom::CHAR_DIGITS + . ISecureRandom::CHAR_LOWER + . ISecureRandom::CHAR_UPPER ); $tokenValue = $this->timeFactory->getTime() . ':' . $token; $encryptedValue = $this->crypto->encrypt($tokenValue, $passwordPrefix . $this->config->getSystemValueString('secret')); diff --git a/lib/private/Server.php b/lib/private/Server.php index a20c37732a7..c78decd90cb 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -45,6 +46,7 @@ use OC\Files\Cache\FileAccess; use OC\Files\Config\MountProviderCollection; use OC\Files\Config\UserMountCache; use OC\Files\Config\UserMountCacheListener; +use OC\Files\Conversion\ConversionManager; use OC\Files\Lock\LockManager; use OC\Files\Mount\CacheMountProvider; use OC\Files\Mount\LocalHomeMountProvider; @@ -54,6 +56,7 @@ use OC\Files\Mount\RootMountProvider; use OC\Files\Node\HookConnector; use OC\Files\Node\LazyRoot; use OC\Files\Node\Root; +use OC\Files\ObjectStore\PrimaryObjectStoreConfig; use OC\Files\SetupManager; use OC\Files\Storage\StorageFactory; use OC\Files\Template\TemplateManager; @@ -123,10 +126,6 @@ use OC\User\DisplayNameCache; use OC\User\Listeners\BeforeUserDeletedListener; use OC\User\Listeners\UserChangedListener; use OC\User\Session; -use OCA\Files_External\Service\BackendService; -use OCA\Files_External\Service\GlobalStoragesService; -use OCA\Files_External\Service\UserGlobalStoragesService; -use OCA\Files_External\Service\UserStoragesService; use OCA\Theming\ImageManager; use OCA\Theming\Service\BackgroundService; use OCA\Theming\ThemingDefaults; @@ -137,7 +136,6 @@ use OCP\AppFramework\Utility\ITimeFactory; use OCP\Authentication\LoginCredentials\IStore; use OCP\Authentication\Token\IProvider as OCPIProvider; use OCP\BackgroundJob\IJobList; -use OCP\Collaboration\AutoComplete\IManager; use OCP\Collaboration\Reference\IReferenceManager; use OCP\Command\IBus; use OCP\Comments\ICommentsManager; @@ -155,6 +153,7 @@ use OCP\Federation\ICloudIdManager; use OCP\Files\Cache\IFileAccess; use OCP\Files\Config\IMountProviderCollection; use OCP\Files\Config\IUserMountCache; +use OCP\Files\Conversion\IConversionManager; use OCP\Files\IMimeTypeDetector; use OCP\Files\IMimeTypeLoader; use OCP\Files\IRootFolder; @@ -187,7 +186,6 @@ use OCP\IRequest; use OCP\IRequestId; use OCP\IServerContainer; use OCP\ISession; -use OCP\ITagManager; use OCP\ITempManager; use OCP\IURLGenerator; use OCP\IUserManager; @@ -199,6 +197,7 @@ use OCP\Lock\ILockingProvider; use OCP\Lockdown\ILockdownManager; use OCP\Log\ILogFactory; use OCP\Mail\IMailer; +use OCP\OCM\ICapabilityAwareOCMProvider; use OCP\OCM\IOCMDiscoveryService; use OCP\OCM\IOCMProvider; use OCP\Preview\IMimeIconProvider; @@ -210,7 +209,6 @@ use OCP\RichObjectStrings\IRichTextFormatter; use OCP\RichObjectStrings\IValidator; use OCP\Route\IRouter; use OCP\Security\Bruteforce\IThrottler; -use OCP\Security\IContentSecurityPolicyManager; use OCP\Security\ICredentialsManager; use OCP\Security\ICrypto; use OCP\Security\IHasher; @@ -284,6 +282,7 @@ class Server extends ServerContainer implements IServerContainer { $this->registerAlias(\OCP\DirectEditing\IManager::class, \OC\DirectEditing\Manager::class); $this->registerAlias(ITemplateManager::class, TemplateManager::class); + $this->registerAlias(\OCP\Template\ITemplateManager::class, \OC\Template\TemplateManager::class); $this->registerAlias(IActionFactory::class, ActionFactory::class); @@ -323,7 +322,7 @@ class Server extends ServerContainer implements IServerContainer { return new Profiler($c->get(SystemConfig::class)); }); - $this->registerService(\OCP\Encryption\IManager::class, function (Server $c): Encryption\Manager { + $this->registerService(Encryption\Manager::class, function (Server $c): Encryption\Manager { $view = new View(); $util = new Encryption\Util( $view, @@ -340,6 +339,7 @@ class Server extends ServerContainer implements IServerContainer { new ArrayCache() ); }); + $this->registerAlias(\OCP\Encryption\IManager::class, Encryption\Manager::class); $this->registerService(IFile::class, function (ContainerInterface $c) { $util = new Encryption\Util( @@ -408,7 +408,8 @@ class Server extends ServerContainer implements IServerContainer { $previewConnector = new \OC\Preview\WatcherConnector( $root, - $c->get(SystemConfig::class) + $c->get(SystemConfig::class), + $this->get(IEventDispatcher::class) ); $previewConnector->connectWatcher(); @@ -571,6 +572,7 @@ class Server extends ServerContainer implements IServerContainer { $this->registerAlias(IAppConfig::class, \OC\AppConfig::class); $this->registerAlias(IUserConfig::class, \OC\Config\UserConfig::class); + $this->registerAlias(IAppManager::class, AppManager::class); $this->registerService(IFactory::class, function (Server $c) { return new \OC\L10N\Factory( @@ -604,10 +606,10 @@ class Server extends ServerContainer implements IServerContainer { if ($config->getValue('installed', false) && !(defined('PHPUNIT_RUN') && PHPUNIT_RUN)) { $logQuery = $config->getValue('log_query'); - $prefixClosure = function () use ($logQuery, $serverVersion) { + $prefixClosure = function () use ($logQuery, $serverVersion): ?string { if (!$logQuery) { try { - $v = \OC_App::getAppVersions(); + $v = \OCP\Server::get(IAppConfig::class)->getAppInstalledVersions(true); } catch (\Doctrine\DBAL\Exception $e) { // Database service probably unavailable // Probably related to https://github.com/nextcloud/server/issues/37424 @@ -622,7 +624,7 @@ class Server extends ServerContainer implements IServerContainer { ]; } $v['core'] = implode(',', $serverVersion->getVersion()); - $version = implode(',', $v); + $version = implode(',', array_keys($v)) . implode(',', $v); $instanceId = \OC_Util::getInstanceId(); $path = \OC::$SERVERROOT; return md5($instanceId . '-' . $version . '-' . $path); @@ -779,20 +781,6 @@ class Server extends ServerContainer implements IServerContainer { }); $this->registerAlias(ITempManager::class, TempManager::class); - - $this->registerService(AppManager::class, function (ContainerInterface $c) { - // TODO: use auto-wiring - return new \OC\App\AppManager( - $c->get(IUserSession::class), - $c->get(\OCP\IConfig::class), - $c->get(IGroupManager::class), - $c->get(ICacheFactory::class), - $c->get(IEventDispatcher::class), - $c->get(LoggerInterface::class), - ); - }); - $this->registerAlias(IAppManager::class, AppManager::class); - $this->registerAlias(IDateTimeZone::class, DateTimeZone::class); $this->registerService(IDateTimeFormatter::class, function (Server $c) { @@ -821,10 +809,11 @@ class Server extends ServerContainer implements IServerContainer { $config = $c->get(\OCP\IConfig::class); $logger = $c->get(LoggerInterface::class); + $objectStoreConfig = $c->get(PrimaryObjectStoreConfig::class); $manager->registerProvider(new CacheMountProvider($config)); $manager->registerHomeProvider(new LocalHomeMountProvider()); - $manager->registerHomeProvider(new ObjectHomeMountProvider($config)); - $manager->registerRootProvider(new RootMountProvider($config, $c->get(LoggerInterface::class))); + $manager->registerHomeProvider(new ObjectHomeMountProvider($objectStoreConfig)); + $manager->registerRootProvider(new RootMountProvider($objectStoreConfig, $config)); $manager->registerRootProvider(new ObjectStorePreviewCacheMountProvider($logger, $config)); return $manager; @@ -834,8 +823,8 @@ class Server extends ServerContainer implements IServerContainer { $busClass = $c->get(\OCP\IConfig::class)->getSystemValueString('commandbus'); if ($busClass) { [$app, $class] = explode('::', $busClass, 2); - if ($c->get(IAppManager::class)->isInstalled($app)) { - \OC_App::loadApp($app); + if ($c->get(IAppManager::class)->isEnabledForUser($app)) { + $c->get(IAppManager::class)->loadApp($app); return $c->get($class); } else { throw new ServiceUnavailableException("The app providing the command bus ($app) is not enabled"); @@ -863,15 +852,15 @@ class Server extends ServerContainer implements IServerContainer { $this->registerDeprecatedAlias('IntegrityCodeChecker', Checker::class); $this->registerService(Checker::class, function (ContainerInterface $c) { - // IConfig and IAppManager requires a working database. This code - // might however be called when ownCloud is not yet setup. + // IConfig requires a working database. This code + // might however be called when Nextcloud is not yet setup. if (\OC::$server->get(SystemConfig::class)->getValue('installed', false)) { $config = $c->get(\OCP\IConfig::class); $appConfig = $c->get(\OCP\IAppConfig::class); } else { - $config = $appConfig = $appManager = null; + $config = null; + $appConfig = null; } - $appManager = $c->get(IAppManager::class); return new Checker( $c->get(ServerVersion::class), @@ -881,7 +870,7 @@ class Server extends ServerContainer implements IServerContainer { $config, $appConfig, $c->get(ICacheFactory::class), - $appManager, + $c->get(IAppManager::class), $c->get(IMimeTypeDetector::class) ); }); @@ -1043,7 +1032,7 @@ class Server extends ServerContainer implements IServerContainer { $classExists = false; } - if ($classExists && $c->get(\OCP\IConfig::class)->getSystemValueBool('installed', false) && $c->get(IAppManager::class)->isInstalled('theming') && $c->get(TrustedDomainHelper::class)->isTrustedDomain($c->getRequest()->getInsecureServerHost())) { + if ($classExists && $c->get(\OCP\IConfig::class)->getSystemValueBool('installed', false) && $c->get(IAppManager::class)->isEnabledForAnyone('theming') && $c->get(TrustedDomainHelper::class)->isTrustedDomain($c->getRequest()->getInsecureServerHost())) { $backgroundService = new BackgroundService( $c->get(IRootFolder::class), $c->getAppDataDir('theming'), @@ -1106,7 +1095,6 @@ class Server extends ServerContainer implements IServerContainer { ); return new CryptoWrapper( - $c->get(\OCP\IConfig::class), $c->get(ICrypto::class), $c->get(ISecureRandom::class), $request @@ -1121,7 +1109,7 @@ class Server extends ServerContainer implements IServerContainer { $config = $c->get(\OCP\IConfig::class); $factoryClass = $config->getSystemValue('sharing.managerFactory', ProviderFactory::class); /** @var \OCP\Share\IProviderFactory $factory */ - return new $factoryClass($this); + return $c->get($factoryClass); }); $this->registerAlias(\OCP\Share\IManager::class, \OC\Share20\Manager::class); @@ -1258,6 +1246,8 @@ class Server extends ServerContainer implements IServerContainer { $this->registerAlias(ITranslationManager::class, TranslationManager::class); + $this->registerAlias(IConversionManager::class, ConversionManager::class); + $this->registerAlias(ISpeechToTextManager::class, SpeechToTextManager::class); $this->registerAlias(IEventSourceFactory::class, EventSourceFactory::class); @@ -1270,7 +1260,8 @@ class Server extends ServerContainer implements IServerContainer { $this->registerAlias(IPhoneNumberUtil::class, PhoneNumberUtil::class); - $this->registerAlias(IOCMProvider::class, OCMProvider::class); + $this->registerAlias(ICapabilityAwareOCMProvider::class, OCMProvider::class); + $this->registerDeprecatedAlias(IOCMProvider::class, OCMProvider::class); $this->registerAlias(ISetupCheckManager::class, SetupCheckManager::class); @@ -1299,30 +1290,6 @@ class Server extends ServerContainer implements IServerContainer { $hookConnector->viewToNode(); } - /** - * @return \OCP\Calendar\IManager - * @deprecated 20.0.0 - */ - public function getCalendarManager() { - return $this->get(\OC\Calendar\Manager::class); - } - - /** - * @return \OCP\Calendar\Resource\IManager - * @deprecated 20.0.0 - */ - public function getCalendarResourceBackendManager() { - return $this->get(\OC\Calendar\Resource\Manager::class); - } - - /** - * @return \OCP\Calendar\Room\IManager - * @deprecated 20.0.0 - */ - public function getCalendarRoomBackendManager() { - return $this->get(\OC\Calendar\Room\Manager::class); - } - private function connectDispatcher(): void { /** @var IEventDispatcher $eventDispatcher */ $eventDispatcher = $this->get(IEventDispatcher::class); @@ -1360,14 +1327,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return \OCP\Encryption\Keys\IStorage - * @deprecated 20.0.0 - */ - public function getEncryptionKeyStorage() { - return $this->get(IStorage::class); - } - - /** * The current request object holding all information about the request * currently being processed is returned from this method. * In case the current execution was not initiated by a web request null is returned @@ -1380,61 +1339,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * Returns the preview manager which can create preview images for a given file - * - * @return IPreview - * @deprecated 20.0.0 - */ - public function getPreviewManager() { - return $this->get(IPreview::class); - } - - /** - * Returns the tag manager which can get and set tags for different object types - * - * @see \OCP\ITagManager::load() - * @return ITagManager - * @deprecated 20.0.0 - */ - public function getTagManager() { - return $this->get(ITagManager::class); - } - - /** - * Returns the system-tag manager - * - * @return ISystemTagManager - * - * @since 9.0.0 - * @deprecated 20.0.0 - */ - public function getSystemTagManager() { - return $this->get(ISystemTagManager::class); - } - - /** - * Returns the system-tag object mapper - * - * @return ISystemTagObjectMapper - * - * @since 9.0.0 - * @deprecated 20.0.0 - */ - public function getSystemTagObjectMapper() { - return $this->get(ISystemTagObjectMapper::class); - } - - /** - * Returns the avatar manager, used for avatar functionality - * - * @return IAvatarManager - * @deprecated 20.0.0 - */ - public function getAvatarManager() { - return $this->get(IAvatarManager::class); - } - - /** * Returns the root folder of ownCloud's data directory * * @return IRootFolder @@ -1518,22 +1422,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return \OC\Authentication\TwoFactorAuth\Manager - * @deprecated 20.0.0 - */ - public function getTwoFactorAuthManager() { - return $this->get(\OC\Authentication\TwoFactorAuth\Manager::class); - } - - /** - * @return \OC\NavigationManager - * @deprecated 20.0.0 - */ - public function getNavigationManager() { - return $this->get(INavigationManager::class); - } - - /** * @return \OCP\IConfig * @deprecated 20.0.0 */ @@ -1550,16 +1438,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * Returns the app config manager - * - * @return IAppConfig - * @deprecated 20.0.0 - */ - public function getAppConfig() { - return $this->get(IAppConfig::class); - } - - /** * @return IFactory * @deprecated 20.0.0 */ @@ -1588,14 +1466,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return AppFetcher - * @deprecated 20.0.0 - */ - public function getAppFetcher() { - return $this->get(AppFetcher::class); - } - - /** * Returns an ICache instance. Since 8.1.0 it returns a fake cache. Use * getMemCacheFactory() instead. * @@ -1617,17 +1487,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * Returns an \OC\RedisFactory instance - * - * @return \OC\RedisFactory - * @deprecated 20.0.0 - */ - public function getGetRedisFactory() { - return $this->get('RedisFactory'); - } - - - /** * Returns the current session * * @return \OCP\IDBConnection @@ -1658,25 +1517,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return ILogFactory - * @throws \OCP\AppFramework\QueryException - * @deprecated 20.0.0 - */ - public function getLogFactory() { - return $this->get(ILogFactory::class); - } - - /** - * Returns a router for generating and matching urls - * - * @return IRouter - * @deprecated 20.0.0 - */ - public function getRouter() { - return $this->get(IRouter::class); - } - - /** * Returns a SecureRandom instance * * @return \OCP\Security\ISecureRandom @@ -1707,16 +1547,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * Returns a CredentialsManager instance - * - * @return ICredentialsManager - * @deprecated 20.0.0 - */ - public function getCredentialsManager() { - return $this->get(ICredentialsManager::class); - } - - /** * Get the certificate manager * * @return \OCP\ICertificateManager @@ -1726,40 +1556,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * Returns an instance of the HTTP client service - * - * @return IClientService - * @deprecated 20.0.0 - */ - public function getHTTPClientService() { - return $this->get(IClientService::class); - } - - /** - * Get the active event logger - * - * The returned logger only logs data when debug mode is enabled - * - * @return IEventLogger - * @deprecated 20.0.0 - */ - public function getEventLogger() { - return $this->get(IEventLogger::class); - } - - /** - * Get the active query logger - * - * The returned logger only logs data when debug mode is enabled - * - * @return IQueryLogger - * @deprecated 20.0.0 - */ - public function getQueryLogger() { - return $this->get(IQueryLogger::class); - } - - /** * Get the manager for temporary files and folders * * @return \OCP\ITempManager @@ -1800,66 +1596,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return \OC\OCSClient - * @deprecated 20.0.0 - */ - public function getOcsClient() { - return $this->get('OcsClient'); - } - - /** - * @return IDateTimeZone - * @deprecated 20.0.0 - */ - public function getDateTimeZone() { - return $this->get(IDateTimeZone::class); - } - - /** - * @return IDateTimeFormatter - * @deprecated 20.0.0 - */ - public function getDateTimeFormatter() { - return $this->get(IDateTimeFormatter::class); - } - - /** - * @return IMountProviderCollection - * @deprecated 20.0.0 - */ - public function getMountProviderCollection() { - return $this->get(IMountProviderCollection::class); - } - - /** - * Get the IniWrapper - * - * @return IniGetWrapper - * @deprecated 20.0.0 - */ - public function getIniWrapper() { - return $this->get(IniGetWrapper::class); - } - - /** - * @return \OCP\Command\IBus - * @deprecated 20.0.0 - */ - public function getCommandBus() { - return $this->get(IBus::class); - } - - /** - * Get the trusted domain helper - * - * @return TrustedDomainHelper - * @deprecated 20.0.0 - */ - public function getTrustedDomainHelper() { - return $this->get(TrustedDomainHelper::class); - } - - /** * Get the locking provider * * @return ILockingProvider @@ -1871,22 +1607,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return IMountManager - * @deprecated 20.0.0 - **/ - public function getMountManager() { - return $this->get(IMountManager::class); - } - - /** - * @return IUserMountCache - * @deprecated 20.0.0 - */ - public function getUserMountCache() { - return $this->get(IUserMountCache::class); - } - - /** * Get the MimeTypeDetector * * @return IMimeTypeDetector @@ -1907,16 +1627,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * Get the manager of all the capabilities - * - * @return CapabilitiesManager - * @deprecated 20.0.0 - */ - public function getCapabilitiesManager() { - return $this->get(CapabilitiesManager::class); - } - - /** * Get the Notification Manager * * @return \OCP\Notification\IManager @@ -1928,14 +1638,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return ICommentsManager - * @deprecated 20.0.0 - */ - public function getCommentsManager() { - return $this->get(ICommentsManager::class); - } - - /** * @return \OCA\Theming\ThemingDefaults * @deprecated 20.0.0 */ @@ -1952,14 +1654,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return \OC\Session\CryptoWrapper - * @deprecated 20.0.0 - */ - public function getSessionCryptoWrapper() { - return $this->get('CryptoWrapper'); - } - - /** * @return CsrfTokenManager * @deprecated 20.0.0 */ @@ -1968,22 +1662,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return IThrottler - * @deprecated 20.0.0 - */ - public function getBruteForceThrottler() { - return $this->get(Throttler::class); - } - - /** - * @return IContentSecurityPolicyManager - * @deprecated 20.0.0 - */ - public function getContentSecurityPolicyManager() { - return $this->get(ContentSecurityPolicyManager::class); - } - - /** * @return ContentSecurityPolicyNonceManager * @deprecated 20.0.0 */ @@ -1992,80 +1670,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * Not a public API as of 8.2, wait for 9.0 - * - * @return \OCA\Files_External\Service\BackendService - * @deprecated 20.0.0 - */ - public function getStoragesBackendService() { - return $this->get(BackendService::class); - } - - /** - * Not a public API as of 8.2, wait for 9.0 - * - * @return \OCA\Files_External\Service\GlobalStoragesService - * @deprecated 20.0.0 - */ - public function getGlobalStoragesService() { - return $this->get(GlobalStoragesService::class); - } - - /** - * Not a public API as of 8.2, wait for 9.0 - * - * @return \OCA\Files_External\Service\UserGlobalStoragesService - * @deprecated 20.0.0 - */ - public function getUserGlobalStoragesService() { - return $this->get(UserGlobalStoragesService::class); - } - - /** - * Not a public API as of 8.2, wait for 9.0 - * - * @return \OCA\Files_External\Service\UserStoragesService - * @deprecated 20.0.0 - */ - public function getUserStoragesService() { - return $this->get(UserStoragesService::class); - } - - /** - * @return \OCP\Share\IManager - * @deprecated 20.0.0 - */ - public function getShareManager() { - return $this->get(\OCP\Share\IManager::class); - } - - /** - * @return \OCP\Collaboration\Collaborators\ISearch - * @deprecated 20.0.0 - */ - public function getCollaboratorSearch() { - return $this->get(\OCP\Collaboration\Collaborators\ISearch::class); - } - - /** - * @return \OCP\Collaboration\AutoComplete\IManager - * @deprecated 20.0.0 - */ - public function getAutoCompleteManager() { - return $this->get(IManager::class); - } - - /** - * Returns the LDAP Provider - * - * @return \OCP\LDAP\ILDAPProvider - * @deprecated 20.0.0 - */ - public function getLDAPProvider() { - return $this->get('LDAPProvider'); - } - - /** * @return \OCP\Settings\IManager * @deprecated 20.0.0 */ @@ -2084,14 +1688,6 @@ class Server extends ServerContainer implements IServerContainer { } /** - * @return \OCP\Lockdown\ILockdownManager - * @deprecated 20.0.0 - */ - public function getLockdownManager() { - return $this->get('LockdownManager'); - } - - /** * @return \OCP\Federation\ICloudIdManager * @deprecated 20.0.0 */ @@ -2099,65 +1695,6 @@ class Server extends ServerContainer implements IServerContainer { return $this->get(ICloudIdManager::class); } - /** - * @return \OCP\GlobalScale\IConfig - * @deprecated 20.0.0 - */ - public function getGlobalScaleConfig() { - return $this->get(IConfig::class); - } - - /** - * @return \OCP\Federation\ICloudFederationProviderManager - * @deprecated 20.0.0 - */ - public function getCloudFederationProviderManager() { - return $this->get(ICloudFederationProviderManager::class); - } - - /** - * @return \OCP\Remote\Api\IApiFactory - * @deprecated 20.0.0 - */ - public function getRemoteApiFactory() { - return $this->get(IApiFactory::class); - } - - /** - * @return \OCP\Federation\ICloudFederationFactory - * @deprecated 20.0.0 - */ - public function getCloudFederationFactory() { - return $this->get(ICloudFederationFactory::class); - } - - /** - * @return \OCP\Remote\IInstanceFactory - * @deprecated 20.0.0 - */ - public function getRemoteInstanceFactory() { - return $this->get(IInstanceFactory::class); - } - - /** - * @return IStorageFactory - * @deprecated 20.0.0 - */ - public function getStorageFactory() { - return $this->get(IStorageFactory::class); - } - - /** - * Get the Preview GeneratorHelper - * - * @return GeneratorHelper - * @since 17.0.0 - * @deprecated 20.0.0 - */ - public function getGeneratorHelper() { - return $this->get(\OC\Preview\GeneratorHelper::class); - } - private function registerDeprecatedAlias(string $alias, string $target) { $this->registerService($alias, function (ContainerInterface $container) use ($target, $alias) { try { diff --git a/lib/private/ServerContainer.php b/lib/private/ServerContainer.php index 9f887b2d48a..b5bcbdaeb6f 100644 --- a/lib/private/ServerContainer.php +++ b/lib/private/ServerContainer.php @@ -128,18 +128,17 @@ class ServerContainer extends SimpleContainer { } catch (QueryException $e) { // Continue with general autoloading then } - } - - // In case the service starts with OCA\ we try to find the service in - // the apps container first. - if (($appContainer = $this->getAppContainerForService($name)) !== null) { - try { - return $appContainer->queryNoFallback($name); - } catch (QueryException $e) { - // Didn't find the service or the respective app container - // In this case the service won't be part of the core container, - // so we can throw directly - throw $e; + // In case the service starts with OCA\ we try to find the service in + // the apps container first. + if (($appContainer = $this->getAppContainerForService($name)) !== null) { + try { + return $appContainer->queryNoFallback($name); + } catch (QueryException $e) { + // Didn't find the service or the respective app container + // In this case the service won't be part of the core container, + // so we can throw directly + throw $e; + } } } elseif (str_starts_with($name, 'OC\\Settings\\') && substr_count($name, '\\') >= 3) { $segments = explode('\\', $name); diff --git a/lib/private/Session/CryptoWrapper.php b/lib/private/Session/CryptoWrapper.php index aceb387ea74..40c2ba6adf3 100644 --- a/lib/private/Session/CryptoWrapper.php +++ b/lib/private/Session/CryptoWrapper.php @@ -1,13 +1,15 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OC\Session; -use OCP\IConfig; use OCP\IRequest; use OCP\ISession; use OCP\Security\ICrypto; @@ -30,37 +32,19 @@ use OCP\Security\ISecureRandom; * @package OC\Session */ class CryptoWrapper { + /** @var string */ public const COOKIE_NAME = 'oc_sessionPassphrase'; - /** @var IConfig */ - protected $config; - /** @var ISession */ - protected $session; - /** @var ICrypto */ - protected $crypto; - /** @var ISecureRandom */ - protected $random; - /** @var string */ - protected $passphrase; + protected string $passphrase; - /** - * @param IConfig $config - * @param ICrypto $crypto - * @param ISecureRandom $random - * @param IRequest $request - */ - public function __construct(IConfig $config, - ICrypto $crypto, + public function __construct( + protected ICrypto $crypto, ISecureRandom $random, - IRequest $request) { - $this->crypto = $crypto; - $this->config = $config; - $this->random = $random; - - if (!is_null($request->getCookie(self::COOKIE_NAME))) { - $this->passphrase = $request->getCookie(self::COOKIE_NAME); - } else { - $this->passphrase = $this->random->generate(128); + IRequest $request, + ) { + $passphrase = $request->getCookie(self::COOKIE_NAME); + if ($passphrase === null) { + $passphrase = $random->generate(128); $secureCookie = $request->getServerProtocol() === 'https'; // FIXME: Required for CI if (!defined('PHPUNIT_RUN')) { @@ -71,11 +55,11 @@ class CryptoWrapper { setcookie( self::COOKIE_NAME, - $this->passphrase, + $passphrase, [ 'expires' => 0, 'path' => $webRoot, - 'domain' => '', + 'domain' => \OCP\Server::get(\OCP\IConfig::class)->getSystemValueString('cookie_domain'), 'secure' => $secureCookie, 'httponly' => true, 'samesite' => 'Lax', @@ -83,13 +67,10 @@ class CryptoWrapper { ); } } + $this->passphrase = $passphrase; } - /** - * @param ISession $session - * @return ISession - */ - public function wrapSession(ISession $session) { + public function wrapSession(ISession $session): ISession { if (!($session instanceof CryptoSessionData)) { return new CryptoSessionData($session, $this->crypto, $this->passphrase); } diff --git a/lib/private/Settings/DeclarativeManager.php b/lib/private/Settings/DeclarativeManager.php index dea0c678f20..534b4b19984 100644 --- a/lib/private/Settings/DeclarativeManager.php +++ b/lib/private/Settings/DeclarativeManager.php @@ -15,6 +15,7 @@ use OCP\IAppConfig; use OCP\IConfig; use OCP\IGroupManager; use OCP\IUser; +use OCP\Security\ICrypto; use OCP\Server; use OCP\Settings\DeclarativeSettingsTypes; use OCP\Settings\Events\DeclarativeSettingsGetValueEvent; @@ -49,6 +50,7 @@ class DeclarativeManager implements IDeclarativeManager { private IConfig $config, private IAppConfig $appConfig, private LoggerInterface $logger, + private ICrypto $crypto, ) { } @@ -266,7 +268,7 @@ class DeclarativeManager implements IDeclarativeManager { $this->eventDispatcher->dispatchTyped(new DeclarativeSettingsSetValueEvent($user, $app, $formId, $fieldId, $value)); break; case DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL: - $this->saveInternalValue($user, $app, $fieldId, $value); + $this->saveInternalValue($user, $app, $formId, $fieldId, $value); break; default: throw new Exception('Unknown storage type "' . $storageType . '"'); @@ -290,18 +292,52 @@ class DeclarativeManager implements IDeclarativeManager { private function getInternalValue(IUser $user, string $app, string $formId, string $fieldId): mixed { $sectionType = $this->getSectionType($app, $fieldId); $defaultValue = $this->getDefaultValue($app, $formId, $fieldId); + + $field = $this->getSchemaField($app, $formId, $fieldId); + $isSensitive = $field !== null && isset($field['sensitive']) && $field['sensitive'] === true; + switch ($sectionType) { case DeclarativeSettingsTypes::SECTION_TYPE_ADMIN: - return $this->config->getAppValue($app, $fieldId, $defaultValue); + $value = $this->config->getAppValue($app, $fieldId, $defaultValue); + break; case DeclarativeSettingsTypes::SECTION_TYPE_PERSONAL: - return $this->config->getUserValue($user->getUID(), $app, $fieldId, $defaultValue); + $value = $this->config->getUserValue($user->getUID(), $app, $fieldId, $defaultValue); + break; default: throw new Exception('Unknown section type "' . $sectionType . '"'); } + if ($isSensitive && $value !== '') { + try { + $value = $this->crypto->decrypt($value); + } catch (Exception $e) { + $this->logger->warning('Failed to decrypt sensitive value for field {field} in app {app}: {message}', [ + 'field' => $fieldId, + 'app' => $app, + 'message' => $e->getMessage(), + ]); + $value = $defaultValue; + } + } + return $value; } - private function saveInternalValue(IUser $user, string $app, string $fieldId, mixed $value): void { + private function saveInternalValue(IUser $user, string $app, string $formId, string $fieldId, mixed $value): void { $sectionType = $this->getSectionType($app, $fieldId); + + $field = $this->getSchemaField($app, $formId, $fieldId); + if ($field !== null && isset($field['sensitive']) && $field['sensitive'] === true && $value !== '' && $value !== 'dummySecret') { + try { + $value = $this->crypto->encrypt($value); + } catch (Exception $e) { + $this->logger->warning('Failed to decrypt sensitive value for field {field} in app {app}: {message}', [ + 'field' => $fieldId, + 'app' => $app, + 'message' => $e->getMessage()] + ); + throw new Exception('Failed to encrypt sensitive value'); + } + } + switch ($sectionType) { case DeclarativeSettingsTypes::SECTION_TYPE_ADMIN: $this->appConfig->setValueString($app, $fieldId, $value); @@ -314,6 +350,27 @@ class DeclarativeManager implements IDeclarativeManager { } } + private function getSchemaField(string $app, string $formId, string $fieldId): ?array { + $form = $this->getForm($app, $formId); + if ($form !== null) { + foreach ($form->getSchema()['fields'] as $field) { + if ($field['id'] === $fieldId) { + return $field; + } + } + } + foreach ($this->appSchemas[$app] ?? [] as $schema) { + if ($schema['id'] === $formId) { + foreach ($schema['fields'] as $field) { + if ($field['id'] === $fieldId) { + return $field; + } + } + } + } + return null; + } + private function getDefaultValue(string $app, string $formId, string $fieldId): mixed { foreach ($this->appSchemas[$app] as $schema) { if ($schema['id'] === $formId) { @@ -391,6 +448,12 @@ class DeclarativeManager implements IDeclarativeManager { ]); return false; } + if (isset($field['sensitive']) && $field['sensitive'] === true && !in_array($field['type'], [DeclarativeSettingsTypes::TEXT, DeclarativeSettingsTypes::PASSWORD])) { + $this->logger->warning('Declarative settings: sensitive field type is supported only for TEXT and PASSWORD types ({app}, {form_id}, {field_id})', [ + 'app' => $appId, 'form_id' => $formId, 'field_id' => $fieldId, + ]); + return false; + } if (!$this->validateField($appId, $formId, $field)) { return false; } diff --git a/lib/private/Settings/Manager.php b/lib/private/Settings/Manager.php index c96c04f34ff..78dc64c3c3f 100644 --- a/lib/private/Settings/Manager.php +++ b/lib/private/Settings/Manager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Settings/Section.php b/lib/private/Settings/Section.php index 9cc6523b9ae..6cd8885d2df 100644 --- a/lib/private/Settings/Section.php +++ b/lib/private/Settings/Section.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Setup.php b/lib/private/Setup.php index f286c3698cf..4082cd5df50 100644 --- a/lib/private/Setup.php +++ b/lib/private/Setup.php @@ -14,6 +14,7 @@ use Exception; use InvalidArgumentException; use OC\Authentication\Token\PublicKeyTokenProvider; use OC\Authentication\Token\TokenCleanupJob; +use OC\Core\BackgroundJobs\GenerateMetadataJob; use OC\Log\Rotate; use OC\Preview\BackgroundCleanupJob; use OC\TextProcessing\RemoveOldTasksBackgroundJob; @@ -21,12 +22,14 @@ use OC\User\BackgroundJobs\CleanupDeletedUsers; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; use OCP\Defaults; +use OCP\Http\Client\IClientService; use OCP\IAppConfig; use OCP\IConfig; use OCP\IGroup; use OCP\IGroupManager; use OCP\IL10N; use OCP\IRequest; +use OCP\IURLGenerator; use OCP\IUserManager; use OCP\IUserSession; use OCP\L10N\IFactory as IL10NFactory; @@ -170,8 +173,7 @@ class Setup { self::protectDataDirectory(); try { - $util = new \OC_Util(); - $htAccessWorking = $util->isHtaccessWorking(Server::get(IConfig::class)); + $htAccessWorking = $this->isHtaccessWorking($dataDir); } catch (\OCP\HintException $e) { $errors[] = [ 'error' => $e->getMessage(), @@ -185,8 +187,8 @@ class Setup { if (\OC_Util::runningOnMac()) { $errors[] = [ 'error' => $this->l10n->t( - 'Mac OS X is not supported and %s will not work properly on this platform. ' . - 'Use it at your own risk! ', + 'Mac OS X is not supported and %s will not work properly on this platform. ' + . 'Use it at your own risk!', [$this->defaults->getProductName()] ), 'hint' => $this->l10n->t('For the best results, please consider using a GNU/Linux server instead.'), @@ -196,8 +198,8 @@ class Setup { if ($this->iniWrapper->getString('open_basedir') !== '' && PHP_INT_SIZE === 4) { $errors[] = [ 'error' => $this->l10n->t( - 'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' . - 'This will lead to problems with files over 4 GB and is highly discouraged.', + 'It seems that this %s instance is running on a 32-bit PHP environment and the open_basedir has been configured in php.ini. ' + . 'This will lead to problems with files over 4 GB and is highly discouraged.', [$this->defaults->getProductName()] ), 'hint' => $this->l10n->t('Please remove the open_basedir setting within your php.ini or switch to 64-bit PHP.'), @@ -205,10 +207,6 @@ class Setup { } return [ - 'hasSQLite' => isset($databases['sqlite']), - 'hasMySQL' => isset($databases['mysql']), - 'hasPostgreSQL' => isset($databases['pgsql']), - 'hasOracle' => isset($databases['oci']), 'databases' => $databases, 'directory' => $dataDir, 'htaccessWorking' => $htAccessWorking, @@ -216,6 +214,87 @@ class Setup { ]; } + public function createHtaccessTestFile(string $dataDir): string|false { + // php dev server does not support htaccess + if (php_sapi_name() === 'cli-server') { + return false; + } + + // testdata + $fileName = '/htaccesstest.txt'; + $testContent = 'This is used for testing whether htaccess is properly enabled to disallow access from the outside. This file can be safely removed.'; + + // creating a test file + $testFile = $dataDir . '/' . $fileName; + + if (file_exists($testFile)) {// already running this test, possible recursive call + return false; + } + + $fp = @fopen($testFile, 'w'); + if (!$fp) { + throw new \OCP\HintException('Can\'t create test file to check for working .htaccess file.', + 'Make sure it is possible for the web server to write to ' . $testFile); + } + fwrite($fp, $testContent); + fclose($fp); + + return $testContent; + } + + /** + * Check if the .htaccess file is working + * + * @param \OCP\IConfig $config + * @return bool + * @throws Exception + * @throws \OCP\HintException If the test file can't get written. + */ + public function isHtaccessWorking(string $dataDir) { + $config = Server::get(IConfig::class); + + if (\OC::$CLI || !$config->getSystemValueBool('check_for_working_htaccess', true)) { + return true; + } + + $testContent = $this->createHtaccessTestFile($dataDir); + if ($testContent === false) { + return false; + } + + $fileName = '/htaccesstest.txt'; + $testFile = $dataDir . '/' . $fileName; + + // accessing the file via http + $url = Server::get(IURLGenerator::class)->getAbsoluteURL(\OC::$WEBROOT . '/data' . $fileName); + try { + $content = Server::get(IClientService::class)->newClient()->get($url)->getBody(); + } catch (\Exception $e) { + $content = false; + } + + if (str_starts_with($url, 'https:')) { + $url = 'http:' . substr($url, 6); + } else { + $url = 'https:' . substr($url, 5); + } + + try { + $fallbackContent = Server::get(IClientService::class)->newClient()->get($url)->getBody(); + } catch (\Exception $e) { + $fallbackContent = false; + } + + // cleanup + @unlink($testFile); + + /* + * If the content is not equal to test content our .htaccess + * is working as required + */ + return $content !== $testContent && $fallbackContent !== $testContent; + } + /** * @return array<string|array> errors */ @@ -225,11 +304,15 @@ class Setup { $error = []; $dbType = $options['dbtype']; - if (empty($options['adminlogin'])) { - $error[] = $l->t('Set an admin Login.'); - } - if (empty($options['adminpass'])) { - $error[] = $l->t('Set an admin password.'); + $disableAdminUser = (bool)($options['admindisable'] ?? false); + + if (!$disableAdminUser) { + if (empty($options['adminlogin'])) { + $error[] = $l->t('Set an admin Login.'); + } + if (empty($options['adminpass'])) { + $error[] = $l->t('Set an admin password.'); + } } if (empty($options['directory'])) { $options['directory'] = \OC::$SERVERROOT . '/data'; @@ -239,8 +322,6 @@ class Setup { $dbType = 'sqlite'; } - $username = htmlspecialchars_decode($options['adminlogin']); - $password = htmlspecialchars_decode($options['adminpass']); $dataDir = htmlspecialchars_decode($options['directory']); $class = self::$dbSetupClasses[$dbType]; @@ -296,7 +377,7 @@ class Setup { $this->outputDebug($output, 'Configuring database'); $dbSetup->initialize($options); try { - $dbSetup->setupDatabase($username); + $dbSetup->setupDatabase(); } catch (\OC\DatabaseSetupException $e) { $error[] = [ 'error' => $e->getMessage(), @@ -326,19 +407,22 @@ class Setup { return $error; } - $this->outputDebug($output, 'Create admin account'); - - // create the admin account and group $user = null; - try { - $user = Server::get(IUserManager::class)->createUser($username, $password); - if (!$user) { - $error[] = "Account <$username> could not be created."; + if (!$disableAdminUser) { + $username = htmlspecialchars_decode($options['adminlogin']); + $password = htmlspecialchars_decode($options['adminpass']); + $this->outputDebug($output, 'Create admin account'); + + try { + $user = Server::get(IUserManager::class)->createUser($username, $password); + if (!$user) { + $error[] = "Account <$username> could not be created."; + return $error; + } + } catch (Exception $exception) { + $error[] = $exception->getMessage(); return $error; } - } catch (Exception $exception) { - $error[] = $exception->getMessage(); - return $error; } $config = Server::get(IConfig::class); @@ -353,7 +437,7 @@ class Setup { } $group = Server::get(IGroupManager::class)->createGroup('admin'); - if ($group instanceof IGroup) { + if ($user !== null && $group instanceof IGroup) { $group->addUser($user); } @@ -385,26 +469,28 @@ class Setup { $bootstrapCoordinator = Server::get(\OC\AppFramework\Bootstrap\Coordinator::class); $bootstrapCoordinator->runInitialRegistration(); - // Create a session token for the newly created user - // The token provider requires a working db, so it's not injected on setup - /** @var \OC\User\Session $userSession */ - $userSession = Server::get(IUserSession::class); - $provider = Server::get(PublicKeyTokenProvider::class); - $userSession->setTokenProvider($provider); - $userSession->login($username, $password); - $user = $userSession->getUser(); - if (!$user) { - $error[] = 'No account found in session.'; - return $error; - } - $userSession->createSessionToken($request, $user->getUID(), $username, $password); + if (!$disableAdminUser) { + // Create a session token for the newly created user + // The token provider requires a working db, so it's not injected on setup + /** @var \OC\User\Session $userSession */ + $userSession = Server::get(IUserSession::class); + $provider = Server::get(PublicKeyTokenProvider::class); + $userSession->setTokenProvider($provider); + $userSession->login($username, $password); + $user = $userSession->getUser(); + if (!$user) { + $error[] = 'No account found in session.'; + return $error; + } + $userSession->createSessionToken($request, $user->getUID(), $username, $password); - $session = $userSession->getSession(); - $session->set('last-password-confirm', Server::get(ITimeFactory::class)->getTime()); + $session = $userSession->getSession(); + $session->set('last-password-confirm', Server::get(ITimeFactory::class)->getTime()); - // Set email for admin - if (!empty($options['adminemail'])) { - $user->setSystemEMailAddress($options['adminemail']); + // Set email for admin + if (!empty($options['adminemail'])) { + $user->setSystemEMailAddress($options['adminemail']); + } } return $error; @@ -417,6 +503,7 @@ class Setup { $jobList->add(BackgroundCleanupJob::class); $jobList->add(RemoveOldTasksBackgroundJob::class); $jobList->add(CleanupDeletedUsers::class); + $jobList->add(GenerateMetadataJob::class); } /** diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index dbbb587206b..ec4ce040090 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -127,10 +127,7 @@ abstract class AbstractDatabase { return $connection; } - /** - * @param string $username - */ - abstract public function setupDatabase($username); + abstract public function setupDatabase(); public function runMigrations(?IOutput $output = null) { if (!is_dir(\OC::$SERVERROOT . '/core/Migrations')) { diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php index 2708ada31c1..1e2dda4c609 100644 --- a/lib/private/Setup/MySQL.php +++ b/lib/private/Setup/MySQL.php @@ -16,7 +16,7 @@ use OCP\Security\ISecureRandom; class MySQL extends AbstractDatabase { public $dbprettyname = 'MySQL/MariaDB'; - public function setupDatabase($username) { + public function setupDatabase() { //check if the database user has admin right $connection = $this->connect(['dbname' => null]); @@ -28,7 +28,7 @@ class MySQL extends AbstractDatabase { } if ($this->tryCreateDbUser) { - $this->createSpecificUser($username, new ConnectionAdapter($connection)); + $this->createSpecificUser('oc_admin', new ConnectionAdapter($connection)); } $this->config->setValues([ @@ -59,7 +59,7 @@ class MySQL extends AbstractDatabase { /** * @param \OC\DB\Connection $connection */ - private function createDatabase($connection) { + private function createDatabase($connection): void { try { $name = $this->dbName; $user = $this->dbUser; @@ -91,7 +91,7 @@ class MySQL extends AbstractDatabase { * @param IDBConnection $connection * @throws \OC\DatabaseSetupException */ - private function createDBUser($connection) { + private function createDBUser($connection): void { try { $name = $this->dbUser; $password = $this->dbPassword; @@ -99,15 +99,15 @@ class MySQL extends AbstractDatabase { // the anonymous user would take precedence when there is one. if ($connection->getDatabasePlatform() instanceof Mysql80Platform) { - $query = "CREATE USER '$name'@'localhost' IDENTIFIED WITH mysql_native_password BY '$password'"; - $connection->executeUpdate($query); - $query = "CREATE USER '$name'@'%' IDENTIFIED WITH mysql_native_password BY '$password'"; - $connection->executeUpdate($query); + $query = "CREATE USER ?@'localhost' IDENTIFIED WITH mysql_native_password BY ?"; + $connection->executeUpdate($query, [$name,$password]); + $query = "CREATE USER ?@'%' IDENTIFIED WITH mysql_native_password BY ?"; + $connection->executeUpdate($query, [$name,$password]); } else { - $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'"; - $connection->executeUpdate($query); - $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'"; - $connection->executeUpdate($query); + $query = "CREATE USER ?@'localhost' IDENTIFIED BY ?"; + $connection->executeUpdate($query, [$name,$password]); + $query = "CREATE USER ?@'%' IDENTIFIED BY ?"; + $connection->executeUpdate($query, [$name,$password]); } } catch (\Exception $ex) { $this->logger->error('Database user creation failed.', [ @@ -119,7 +119,7 @@ class MySQL extends AbstractDatabase { } /** - * @param $username + * @param string $username * @param IDBConnection $connection */ private function createSpecificUser($username, $connection): void { diff --git a/lib/private/Setup/OCI.php b/lib/private/Setup/OCI.php index 47e5e5436a5..61c7f968787 100644 --- a/lib/private/Setup/OCI.php +++ b/lib/private/Setup/OCI.php @@ -40,7 +40,7 @@ class OCI extends AbstractDatabase { return $errors; } - public function setupDatabase($username) { + public function setupDatabase() { try { $this->connect(); } catch (\Exception $e) { diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php index b1cf031e876..9a686db2e54 100644 --- a/lib/private/Setup/PostgreSQL.php +++ b/lib/private/Setup/PostgreSQL.php @@ -16,10 +16,9 @@ class PostgreSQL extends AbstractDatabase { public $dbprettyname = 'PostgreSQL'; /** - * @param string $username * @throws \OC\DatabaseSetupException */ - public function setupDatabase($username) { + public function setupDatabase() { try { $connection = $this->connect([ 'dbname' => 'postgres' @@ -46,7 +45,7 @@ class PostgreSQL extends AbstractDatabase { //use the admin login data for the new database user //add prefix to the postgresql user name to prevent collisions - $this->dbUser = 'oc_' . strtolower($username); + $this->dbUser = 'oc_admin'; //create a new password so we don't need to store the admin config in the config file $this->dbPassword = \OC::$server->get(ISecureRandom::class)->generate(30, ISecureRandom::CHAR_ALPHANUMERIC); diff --git a/lib/private/Setup/Sqlite.php b/lib/private/Setup/Sqlite.php index 1b90ebd5a5e..b34b1e32ede 100644 --- a/lib/private/Setup/Sqlite.php +++ b/lib/private/Setup/Sqlite.php @@ -45,7 +45,7 @@ class Sqlite extends AbstractDatabase { } } - public function setupDatabase($username) { + public function setupDatabase() { $datadir = $this->config->getValue( 'datadirectory', \OC::$SERVERROOT . '/data' diff --git a/lib/private/Share/Share.php b/lib/private/Share/Share.php index 56a4c6410c5..1121d71e45f 100644 --- a/lib/private/Share/Share.php +++ b/lib/private/Share/Share.php @@ -133,8 +133,8 @@ class Share extends Constants { // for file/folder shares we need to compare file_source, otherwise we compare item_source // only group shares if they already point to the same target, otherwise the file where shared // before grouping of shares was added. In this case we don't group them to avoid confusions - if (($fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) || - (!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) { + if (($fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) + || (!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) { // add the first item to the list of grouped shares if (!isset($result[$key]['grouped'])) { $result[$key]['grouped'][] = $result[$key]; diff --git a/lib/private/Share20/DefaultShareProvider.php b/lib/private/Share20/DefaultShareProvider.php index ca3c33d6dbb..e1eebe1e450 100644 --- a/lib/private/Share20/DefaultShareProvider.php +++ b/lib/private/Share20/DefaultShareProvider.php @@ -5,6 +5,7 @@ * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OC\Share20; use OC\Files\Cache\Cache; @@ -31,6 +32,7 @@ use OCP\Share\IAttributes; use OCP\Share\IManager; use OCP\Share\IShare; use OCP\Share\IShareProviderSupportsAccept; +use OCP\Share\IShareProviderSupportsAllSharesInFolder; use OCP\Share\IShareProviderWithNotification; use Psr\Log\LoggerInterface; use function str_starts_with; @@ -40,7 +42,7 @@ use function str_starts_with; * * @package OC\Share20 */ -class DefaultShareProvider implements IShareProviderWithNotification, IShareProviderSupportsAccept { +class DefaultShareProvider implements IShareProviderWithNotification, IShareProviderSupportsAccept, IShareProviderSupportsAllSharesInFolder { // Special share type for user modified group shares public const SHARE_TYPE_USERGROUP = 2; @@ -322,10 +324,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))) ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))) ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId()))) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )) + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))) ->executeQuery(); $data = $stmt->fetch(); @@ -383,10 +382,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv ], IQueryBuilder::PARAM_INT_ARRAY) ) ) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )) + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))) ->orderBy('id'); $cursor = $qb->executeQuery(); @@ -449,10 +445,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))) ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))) ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId()))) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )) + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))) ->executeQuery(); $data = $stmt->fetch(); @@ -565,10 +558,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))) ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))) ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId()))) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )) + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))) ->setMaxResults(1) ->executeQuery(); @@ -615,35 +605,41 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv throw new \Exception('non-shallow getSharesInFolder is no longer supported'); } + return $this->getSharesInFolderInternal($userId, $node, $reshares); + } + + public function getAllSharesInFolder(Folder $node): array { + return $this->getSharesInFolderInternal(null, $node, null); + } + + /** + * @return array<int, list<IShare>> + */ + private function getSharesInFolderInternal(?string $userId, Folder $node, ?bool $reshares): array { $qb = $this->dbConn->getQueryBuilder(); $qb->select('s.*', 'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash', 'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime', 'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum') ->from('share', 's') - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )); + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))); - $qb->andWhere($qb->expr()->orX( - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)) - )); + $qb->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK], IQueryBuilder::PARAM_INT_ARRAY))); - /** - * Reshares for this user are shares where they are the owner. - */ - if ($reshares === false) { - $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))); - } else { - $qb->andWhere( - $qb->expr()->orX( - $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), - $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) - ) - ); + if ($userId !== null) { + /** + * Reshares for this user are shares where they are the owner. + */ + if ($reshares !== true) { + $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))); + } else { + $qb->andWhere( + $qb->expr()->orX( + $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)), + $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)) + ) + ); + } } // todo? maybe get these from the oc_mounts table @@ -675,7 +671,6 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv foreach ($chunks as $chunk) { $qb->setParameter('chunk', $chunk, IQueryBuilder::PARAM_INT_ARRAY); - $a = $qb->getSQL(); $cursor = $qb->executeQuery(); while ($data = $cursor->fetch()) { $shares[$data['fileid']][] = $this->createShare($data); @@ -693,10 +688,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv $qb = $this->dbConn->getQueryBuilder(); $qb->select('*') ->from('share') - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )); + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))); $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType))); @@ -756,10 +748,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv ], IQueryBuilder::PARAM_INT_ARRAY) ) ) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )); + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))); $cursor = $qb->executeQuery(); $data = $cursor->fetch(); @@ -795,17 +784,8 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv $cursor = $qb->select('*') ->from('share') ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId()))) - ->andWhere( - $qb->expr()->orX( - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)), - ) - ) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )) + ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK], IQueryBuilder::PARAM_INT_ARRAY))) + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))) ->orderBy('id', 'ASC') ->executeQuery(); @@ -874,10 +854,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER))) ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId))) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )); + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))); // Filter by node if provided if ($node !== null) { @@ -942,10 +919,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv $groups, IQueryBuilder::PARAM_STR_ARRAY ))) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )); + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))); $cursor = $qb->executeQuery(); while ($data = $cursor->fetch()) { @@ -988,10 +962,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv ->from('share') ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))) ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token))) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )) + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))) ->executeQuery(); $data = $cursor->fetch(); @@ -1090,7 +1061,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv ->from('share') ->where($qb->expr()->eq('share_with', $qb->createNamedParameter($userId))) ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))) - ->andWhere($qb->expr()->in('item_type', [$qb->createNamedParameter('file'), $qb->createNamedParameter('folder')])); + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))); // this is called with either all group shares or one group share. // for all shares it's easier to just only search by share_with, @@ -1147,10 +1118,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv */ $qb->where( $qb->expr()->andX( - $qb->expr()->orX( - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)) - ), + $qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_GROUP, IShare::TYPE_USERGROUP], IQueryBuilder::PARAM_INT_ARRAY)), $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)) ) ); @@ -1323,26 +1291,31 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv $qb = $this->dbConn->getQueryBuilder(); - $or = $qb->expr()->orX( - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)) - ); + $shareTypes = [IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK]; if ($currentAccess) { - $or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))); + $shareTypes[] = IShare::TYPE_USERGROUP; } $qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions') ->from('share') ->where( - $or + $qb->expr()->in('share_type', $qb->createNamedParameter($shareTypes, IQueryBuilder::PARAM_INT_ARRAY)) ) ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY))) - ->andWhere($qb->expr()->orX( - $qb->expr()->eq('item_type', $qb->createNamedParameter('file')), - $qb->expr()->eq('item_type', $qb->createNamedParameter('folder')) - )); + ->andWhere($qb->expr()->in('item_type', $qb->createNamedParameter(['file', 'folder'], IQueryBuilder::PARAM_STR_ARRAY))); + + // Ensure accepted is true for user and usergroup type + $qb->andWhere( + $qb->expr()->orX( + $qb->expr()->andX( + $qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)), + $qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)), + ), + $qb->expr()->eq('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED, IQueryBuilder::PARAM_INT)), + ), + ); + $cursor = $qb->executeQuery(); $users = []; @@ -1647,13 +1620,7 @@ class DefaultShareProvider implements IShareProviderWithNotification, IShareProv $qb->select('*') ->from('share') - ->where( - $qb->expr()->orX( - $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)), - $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK)) - ) - ); + ->where($qb->expr()->in('share_type', $qb->createNamedParameter([IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK], IQueryBuilder::PARAM_INT_ARRAY))); $cursor = $qb->executeQuery(); while ($data = $cursor->fetch()) { diff --git a/lib/private/Share20/Exception/BackendError.php b/lib/private/Share20/Exception/BackendError.php index 60f7dcc1a17..b2585367727 100644 --- a/lib/private/Share20/Exception/BackendError.php +++ b/lib/private/Share20/Exception/BackendError.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Share20/Exception/InvalidShare.php b/lib/private/Share20/Exception/InvalidShare.php index 755efdfd2cc..8756455f9d2 100644 --- a/lib/private/Share20/Exception/InvalidShare.php +++ b/lib/private/Share20/Exception/InvalidShare.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/private/Share20/GroupDeletedListener.php b/lib/private/Share20/GroupDeletedListener.php new file mode 100644 index 00000000000..7e1ad71c465 --- /dev/null +++ b/lib/private/Share20/GroupDeletedListener.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Share20; + +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; +use OCP\Group\Events\GroupDeletedEvent; +use OCP\Share\IManager; + +/** + * @template-implements IEventListener<GroupDeletedEvent> + */ +class GroupDeletedListener implements IEventListener { + public function __construct( + protected IManager $shareManager, + ) { + } + + public function handle(Event $event): void { + if (!$event instanceof GroupDeletedEvent) { + return; + } + + $this->shareManager->groupDeleted($event->getGroup()->getGID()); + } +} diff --git a/lib/private/Share20/Hooks.php b/lib/private/Share20/Hooks.php deleted file mode 100644 index 809b50791e5..00000000000 --- a/lib/private/Share20/Hooks.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/** - * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2016 ownCloud, Inc. - * SPDX-License-Identifier: AGPL-3.0-only - */ -namespace OC\Share20; - -use OCP\Share\IManager as IShareManager; - -class Hooks { - public static function post_deleteUser($arguments) { - \OC::$server->get(IShareManager::class)->userDeleted($arguments['uid']); - } - - public static function post_deleteGroup($arguments) { - \OC::$server->get(IShareManager::class)->groupDeleted($arguments['gid']); - } -} diff --git a/lib/private/Share20/LegacyHooks.php b/lib/private/Share20/LegacyHooks.php index 99c2b0a9a87..3bce0b9560a 100644 --- a/lib/private/Share20/LegacyHooks.php +++ b/lib/private/Share20/LegacyHooks.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -69,9 +70,9 @@ class LegacyHooks { // Prepare hook $shareType = $share->getShareType(); $sharedWith = ''; - if ($shareType === IShare::TYPE_USER || - $shareType === IShare::TYPE_GROUP || - $shareType === IShare::TYPE_REMOTE) { + if ($shareType === IShare::TYPE_USER + || $shareType === IShare::TYPE_GROUP + || $shareType === IShare::TYPE_REMOTE) { $sharedWith = $share->getSharedWith(); } diff --git a/lib/private/Share20/Manager.php b/lib/private/Share20/Manager.php index 219f3d86380..01664c6a0a3 100644 --- a/lib/private/Share20/Manager.php +++ b/lib/private/Share20/Manager.php @@ -21,6 +21,7 @@ use OCP\Files\Mount\IShareOwnerlessMount; use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\HintException; +use OCP\IAppConfig; use OCP\IConfig; use OCP\IDateTimeZone; use OCP\IGroupManager; @@ -34,6 +35,7 @@ use OCP\Mail\IMailer; use OCP\Security\Events\ValidatePasswordPolicyEvent; use OCP\Security\IHasher; use OCP\Security\ISecureRandom; +use OCP\Security\PasswordContext; use OCP\Share; use OCP\Share\Events\BeforeShareDeletedEvent; use OCP\Share\Events\ShareAcceptedEvent; @@ -43,11 +45,13 @@ use OCP\Share\Events\ShareDeletedFromSelfEvent; use OCP\Share\Exceptions\AlreadySharedException; use OCP\Share\Exceptions\GenericShareException; use OCP\Share\Exceptions\ShareNotFound; +use OCP\Share\Exceptions\ShareTokenException; use OCP\Share\IManager; use OCP\Share\IProviderFactory; use OCP\Share\IShare; use OCP\Share\IShareProvider; use OCP\Share\IShareProviderSupportsAccept; +use OCP\Share\IShareProviderSupportsAllSharesInFolder; use OCP\Share\IShareProviderWithNotification; use Psr\Log\LoggerInterface; @@ -78,6 +82,7 @@ class Manager implements IManager { private KnownUserService $knownUserService, private ShareDisableChecker $shareDisableChecker, private IDateTimeZone $dateTimeZone, + private IAppConfig $appConfig, ) { $this->l = $this->l10nFactory->get('lib'); // The constructor of LegacyHooks registers the listeners of share events @@ -113,7 +118,8 @@ class Manager implements IManager { // Let others verify the password try { - $this->dispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); + $event = new ValidatePasswordPolicyEvent($password, PasswordContext::SHARING); + $this->dispatcher->dispatchTyped($event); } catch (HintException $e) { /* Wrap in a 400 bad request error */ throw new HintException($e->getMessage(), $e->getHint(), 400, $e); @@ -176,8 +182,8 @@ class Manager implements IManager { } // Cannot share with yourself - if ($share->getShareType() === IShare::TYPE_USER && - $share->getSharedWith() === $share->getSharedBy()) { + if ($share->getShareType() === IShare::TYPE_USER + && $share->getSharedWith() === $share->getSharedBy()) { throw new \InvalidArgumentException($this->l->t('Cannot share with yourself')); } @@ -187,8 +193,8 @@ class Manager implements IManager { } // And it should be a file or a folder - if (!($share->getNode() instanceof \OCP\Files\File) && - !($share->getNode() instanceof \OCP\Files\Folder)) { + if (!($share->getNode() instanceof \OCP\Files\File) + && !($share->getNode() instanceof \OCP\Files\Folder)) { throw new \InvalidArgumentException($this->l->t('Shared path must be either a file or a folder')); } @@ -212,6 +218,17 @@ class Manager implements IManager { throw new \InvalidArgumentException($this->l->t('Valid permissions are required for sharing')); } + // Permissions must be valid + if ($share->getPermissions() < 0 || $share->getPermissions() > \OCP\Constants::PERMISSION_ALL) { + throw new \InvalidArgumentException($this->l->t('Valid permissions are required for sharing')); + } + + // Single file shares should never have delete or create permissions + if (($share->getNode() instanceof File) + && (($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE)) !== 0)) { + throw new \InvalidArgumentException($this->l->t('File shares cannot have create or delete permissions')); + } + $permissions = 0; $nodesForUser = $userFolder->getById($share->getNodeId()); foreach ($nodesForUser as $node) { @@ -234,8 +251,8 @@ class Manager implements IManager { // Link shares are allowed to have no read permissions to allow upload to hidden folders $noReadPermissionRequired = $share->getShareType() === IShare::TYPE_LINK || $share->getShareType() === IShare::TYPE_EMAIL; - if (!$noReadPermissionRequired && - ($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) { + if (!$noReadPermissionRequired + && ($share->getPermissions() & \OCP\Constants::PERMISSION_READ) === 0) { throw new \InvalidArgumentException($this->l->t('Shares need at least read permissions')); } @@ -544,8 +561,8 @@ class Manager implements IManager { } // Check if public upload is allowed - if ($share->getNodeType() === 'folder' && !$this->shareApiLinkAllowPublicUpload() && - ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) { + if ($share->getNodeType() === 'folder' && !$this->shareApiLinkAllowPublicUpload() + && ($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE | \OCP\Constants::PERMISSION_DELETE))) { throw new \InvalidArgumentException($this->l->t('Public upload is not allowed')); } } @@ -581,7 +598,11 @@ class Manager implements IManager { $mounts = $this->mountManager->findIn($path->getPath()); foreach ($mounts as $mount) { if ($mount->getStorage()->instanceOfStorage('\OCA\Files_Sharing\ISharedStorage')) { - throw new \InvalidArgumentException($this->l->t('Path contains files shared with you')); + // Using a flat sharing model ensures the file owner can always see who has access. + // Allowing parent folder sharing would require tracking inherited access, which adds complexity + // and hurts performance/scalability. + // So we forbid sharing a parent folder of a share you received. + throw new \InvalidArgumentException($this->l->t('You cannot share a folder that contains other shares')); } } } @@ -659,41 +680,7 @@ class Manager implements IManager { $this->linkCreateChecks($share); $this->setLinkParent($share); - // Initial token length - $tokenLength = \OC\Share\Helper::getTokenLength(); - - do { - $tokenExists = false; - - for ($i = 0; $i <= 2; $i++) { - // Generate a new token - $token = $this->secureRandom->generate( - $tokenLength, - \OCP\Security\ISecureRandom::CHAR_HUMAN_READABLE - ); - - try { - // Try to fetch a share with the generated token - $this->getShareByToken($token); - $tokenExists = true; // Token exists, we need to try again - } catch (\OCP\Share\Exceptions\ShareNotFound $e) { - // Token is unique, exit the loop - $tokenExists = false; - break; - } - } - - // If we've reached the maximum attempts and the token still exists, increase the token length - if ($tokenExists) { - $tokenLength++; - - // Check if the token length exceeds the maximum allowed length - if ($tokenLength > \OC\Share\Constants::MAX_TOKEN_LENGTH) { - throw new \Exception('Unable to generate a unique share token. Maximum token length exceeded.'); - } - } - } while ($tokenExists); - + $token = $this->generateToken(); // Set the unique token $share->setToken($token); @@ -711,8 +698,8 @@ class Manager implements IManager { } // Cannot share with the owner - if ($share->getShareType() === IShare::TYPE_USER && - $share->getSharedWith() === $share->getShareOwner()) { + if ($share->getShareType() === IShare::TYPE_USER + && $share->getSharedWith() === $share->getShareOwner()) { throw new \InvalidArgumentException($this->l->t('Cannot share with the share owner')); } @@ -804,14 +791,14 @@ class Manager implements IManager { } // We can only change the recipient on user shares - if ($share->getSharedWith() !== $originalShare->getSharedWith() && - $share->getShareType() !== IShare::TYPE_USER) { + if ($share->getSharedWith() !== $originalShare->getSharedWith() + && $share->getShareType() !== IShare::TYPE_USER) { throw new \InvalidArgumentException($this->l->t('Can only update recipient on user shares')); } // Cannot share with the owner - if ($share->getShareType() === IShare::TYPE_USER && - $share->getSharedWith() === $share->getShareOwner()) { + if ($share->getShareType() === IShare::TYPE_USER + && $share->getSharedWith() === $share->getShareOwner()) { throw new \InvalidArgumentException($this->l->t('Cannot share with the share owner')); } @@ -962,11 +949,11 @@ class Manager implements IManager { * @return boolean whether the password was updated or not. */ private function updateSharePasswordIfNeeded(IShare $share, IShare $originalShare) { - $passwordsAreDifferent = ($share->getPassword() !== $originalShare->getPassword()) && - (($share->getPassword() !== null && $originalShare->getPassword() === null) || - ($share->getPassword() === null && $originalShare->getPassword() !== null) || - ($share->getPassword() !== null && $originalShare->getPassword() !== null && - !$this->hasher->verify($share->getPassword(), $originalShare->getPassword()))); + $passwordsAreDifferent = ($share->getPassword() !== $originalShare->getPassword()) + && (($share->getPassword() !== null && $originalShare->getPassword() === null) + || ($share->getPassword() === null && $originalShare->getPassword() !== null) + || ($share->getPassword() !== null && $originalShare->getPassword() !== null + && !$this->hasher->verify($share->getPassword(), $originalShare->getPassword()))); // Password updated. if ($passwordsAreDifferent) { @@ -1083,7 +1070,12 @@ class Manager implements IManager { foreach ($userIds as $userId) { foreach ($shareTypes as $shareType) { - $provider = $this->factory->getProviderForType($shareType); + try { + $provider = $this->factory->getProviderForType($shareType); + } catch (ProviderException $e) { + continue; + } + if ($node instanceof Folder) { /* We need to get all shares by this user to get subshares */ $shares = $provider->getSharesBy($userId, $shareType, null, false, -1, 0); @@ -1222,11 +1214,13 @@ class Manager implements IManager { $shares = []; foreach ($providers as $provider) { if ($isOwnerless) { - foreach ($node->getDirectoryListing() as $childNode) { - $data = $provider->getSharesByPath($childNode); - $fid = $childNode->getId(); - $shares[$fid] ??= []; - $shares[$fid] = array_merge($shares[$fid], $data); + // If the provider does not implement the additional interface, + // we lack a performant way of querying all shares and therefore ignore the provider. + if ($provider instanceof IShareProviderSupportsAllSharesInFolder) { + foreach ($provider->getAllSharesInFolder($node) as $fid => $data) { + $shares[$fid] ??= []; + $shares[$fid] = array_merge($shares[$fid], $data); + } } } else { foreach ($provider->getSharesInFolder($userId, $node, $reshares) as $fid => $data) { @@ -1243,9 +1237,9 @@ class Manager implements IManager { * @inheritdoc */ public function getSharesBy($userId, $shareType, $path = null, $reshares = false, $limit = 50, $offset = 0, bool $onlyValid = true) { - if ($path !== null && - !($path instanceof \OCP\Files\File) && - !($path instanceof \OCP\Files\Folder)) { + if ($path !== null + && !($path instanceof \OCP\Files\File) + && !($path instanceof \OCP\Files\Folder)) { throw new \InvalidArgumentException($this->l->t('Invalid path')); } @@ -1493,15 +1487,6 @@ class Manager implements IManager { $this->deleteShare($share); throw new ShareNotFound($this->l->t('The requested share does not exist anymore')); } - - try { - $share->getNode(); - // Ignore share, file is still accessible - } catch (NotFoundException) { - // Access lost, but maybe only temporarily, so don't delete the share right away - throw new ShareNotFound($this->l->t('The requested share does not exist anymore')); - } - if ($this->config->getAppValue('files_sharing', 'hide_disabled_user_shares', 'no') === 'yes') { $uids = array_unique([$share->getShareOwner(),$share->getSharedBy()]); foreach ($uids as $uid) { @@ -1567,8 +1552,14 @@ class Manager implements IManager { * @inheritdoc */ public function groupDeleted($gid) { - $provider = $this->factory->getProviderForType(IShare::TYPE_GROUP); - $provider->groupDeleted($gid); + foreach ([IShare::TYPE_GROUP, IShare::TYPE_REMOTE_GROUP] as $type) { + try { + $provider = $this->factory->getProviderForType($type); + } catch (ProviderException $e) { + continue; + } + $provider->groupDeleted($gid); + } $excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', ''); if ($excludedGroups === '') { @@ -1588,8 +1579,14 @@ class Manager implements IManager { * @inheritdoc */ public function userDeletedFromGroup($uid, $gid) { - $provider = $this->factory->getProviderForType(IShare::TYPE_GROUP); - $provider->userDeletedFromGroup($uid, $gid); + foreach ([IShare::TYPE_GROUP, IShare::TYPE_REMOTE_GROUP] as $type) { + try { + $provider = $this->factory->getProviderForType($type); + } catch (ProviderException $e) { + continue; + } + $provider->userDeletedFromGroup($uid, $gid); + } } /** @@ -1801,8 +1798,8 @@ class Manager implements IManager { * @return bool */ public function shareApiLinkDefaultExpireDateEnforced() { - return $this->shareApiLinkDefaultExpireDate() && - $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes'; + return $this->shareApiLinkDefaultExpireDate() + && $this->config->getAppValue('core', 'shareapi_enforce_expire_date', 'no') === 'yes'; } @@ -1839,8 +1836,8 @@ class Manager implements IManager { * @return bool */ public function shareApiInternalDefaultExpireDateEnforced(): bool { - return $this->shareApiInternalDefaultExpireDate() && - $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes'; + return $this->shareApiInternalDefaultExpireDate() + && $this->config->getAppValue('core', 'shareapi_enforce_internal_expire_date', 'no') === 'yes'; } /** @@ -1849,8 +1846,8 @@ class Manager implements IManager { * @return bool */ public function shareApiRemoteDefaultExpireDateEnforced(): bool { - return $this->shareApiRemoteDefaultExpireDate() && - $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes'; + return $this->shareApiRemoteDefaultExpireDate() + && $this->config->getAppValue('core', 'shareapi_enforce_remote_expire_date', 'no') === 'yes'; } /** @@ -1918,13 +1915,13 @@ class Manager implements IManager { } public function limitEnumerationToGroups(): bool { - return $this->allowEnumeration() && - $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes'; + return $this->allowEnumeration() + && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_group', 'no') === 'yes'; } public function limitEnumerationToPhone(): bool { - return $this->allowEnumeration() && - $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes'; + return $this->allowEnumeration() + && $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_to_phone', 'no') === 'yes'; } public function allowEnumerationFullMatch(): bool { @@ -1939,6 +1936,14 @@ class Manager implements IManager { return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match_ignore_second_dn', 'no') === 'yes'; } + public function allowCustomTokens(): bool { + return $this->appConfig->getValueBool('core', 'shareapi_allow_custom_tokens', false); + } + + public function allowViewWithoutDownload(): bool { + return $this->appConfig->getValueBool('core', 'shareapi_allow_view_without_download', true); + } + public function currentUserCanEnumerateTargetUser(?IUser $currentUser, IUser $targetUser): bool { if ($this->allowEnumerationFullMatch()) { return true; @@ -1976,14 +1981,9 @@ class Manager implements IManager { } /** - * Copied from \OC_Util::isSharingDisabledForUser - * - * TODO: Deprecate function from OC_Util - * - * @param string $userId - * @return bool + * Check if sharing is disabled for the current user */ - public function sharingDisabledForUser($userId) { + public function sharingDisabledForUser(?string $userId): bool { return $this->shareDisableChecker->sharingDisabledForUser($userId); } @@ -2025,4 +2025,43 @@ class Manager implements IManager { yield from $provider->getAllShares(); } } + + public function generateToken(): string { + // Initial token length + $tokenLength = \OC\Share\Helper::getTokenLength(); + + do { + $tokenExists = false; + + for ($i = 0; $i <= 2; $i++) { + // Generate a new token + $token = $this->secureRandom->generate( + $tokenLength, + ISecureRandom::CHAR_HUMAN_READABLE, + ); + + try { + // Try to fetch a share with the generated token + $this->getShareByToken($token); + $tokenExists = true; // Token exists, we need to try again + } catch (ShareNotFound $e) { + // Token is unique, exit the loop + $tokenExists = false; + break; + } + } + + // If we've reached the maximum attempts and the token still exists, increase the token length + if ($tokenExists) { + $tokenLength++; + + // Check if the token length exceeds the maximum allowed length + if ($tokenLength > \OC\Share\Constants::MAX_TOKEN_LENGTH) { + throw new ShareTokenException('Unable to generate a unique share token. Maximum token length exceeded.'); + } + } + } while ($tokenExists); + + return $token; + } } diff --git a/lib/private/Share20/ProviderFactory.php b/lib/private/Share20/ProviderFactory.php index 7335c863df0..d920edfd90e 100644 --- a/lib/private/Share20/ProviderFactory.php +++ b/lib/private/Share20/ProviderFactory.php @@ -1,32 +1,21 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OC\Share20; use OC\Share20\Exception\ProviderException; -use OCA\FederatedFileSharing\AddressHandler; use OCA\FederatedFileSharing\FederatedShareProvider; -use OCA\FederatedFileSharing\Notifications; -use OCA\FederatedFileSharing\TokenHandler; -use OCA\ShareByMail\Settings\SettingsManager; use OCA\ShareByMail\ShareByMailProvider; use OCA\Talk\Share\RoomShareProvider; -use OCP\AppFramework\Utility\ITimeFactory; -use OCP\Defaults; -use OCP\EventDispatcher\IEventDispatcher; -use OCP\Federation\ICloudFederationFactory; -use OCP\Files\IRootFolder; -use OCP\Http\Client\IClientService; -use OCP\IServerContainer; -use OCP\L10N\IFactory; -use OCP\Mail\IMailer; -use OCP\Security\IHasher; -use OCP\Security\ISecureRandom; -use OCP\Share\IManager; +use OCP\App\IAppManager; +use OCP\Server; use OCP\Share\IProviderFactory; use OCP\Share\IShare; use OCP\Share\IShareProvider; @@ -38,30 +27,22 @@ use Psr\Log\LoggerInterface; * @package OC\Share20 */ class ProviderFactory implements IProviderFactory { - /** @var DefaultShareProvider */ - private $defaultProvider = null; - /** @var FederatedShareProvider */ - private $federatedProvider = null; - /** @var ShareByMailProvider */ - private $shareByMailProvider; - /** @var \OCA\Circles\ShareByCircleProvider */ - private $shareByCircleProvider = null; - /** @var bool */ - private $circlesAreNotAvailable = false; - /** @var \OCA\Talk\Share\RoomShareProvider */ + private ?DefaultShareProvider $defaultProvider = null; + private ?FederatedShareProvider $federatedProvider = null; + private ?ShareByMailProvider $shareByMailProvider = null; + /** + * @psalm-suppress UndefinedDocblockClass + * @var ?RoomShareProvider + */ private $roomShareProvider = null; - private $registeredShareProviders = []; + private array $registeredShareProviders = []; - private $shareProviders = []; + private array $shareProviders = []; - /** - * IProviderFactory constructor. - * - * @param IServerContainer $serverContainer - */ public function __construct( - private IServerContainer $serverContainer, + protected IAppManager $appManager, + protected LoggerInterface $logger, ) { } @@ -71,81 +52,24 @@ class ProviderFactory implements IProviderFactory { /** * Create the default share provider. - * - * @return DefaultShareProvider */ - protected function defaultShareProvider() { - if ($this->defaultProvider === null) { - $this->defaultProvider = new DefaultShareProvider( - $this->serverContainer->getDatabaseConnection(), - $this->serverContainer->getUserManager(), - $this->serverContainer->getGroupManager(), - $this->serverContainer->get(IRootFolder::class), - $this->serverContainer->get(IMailer::class), - $this->serverContainer->get(Defaults::class), - $this->serverContainer->get(IFactory::class), - $this->serverContainer->getURLGenerator(), - $this->serverContainer->get(ITimeFactory::class), - $this->serverContainer->get(LoggerInterface::class), - $this->serverContainer->get(IManager::class), - ); - } - - return $this->defaultProvider; + protected function defaultShareProvider(): DefaultShareProvider { + return Server::get(DefaultShareProvider::class); } /** * Create the federated share provider - * - * @return FederatedShareProvider */ - protected function federatedShareProvider() { + protected function federatedShareProvider(): ?FederatedShareProvider { if ($this->federatedProvider === null) { /* * Check if the app is enabled */ - $appManager = $this->serverContainer->getAppManager(); - if (!$appManager->isEnabledForUser('federatedfilesharing')) { + if (!$this->appManager->isEnabledForUser('federatedfilesharing')) { return null; } - /* - * TODO: add factory to federated sharing app - */ - $l = $this->serverContainer->getL10N('federatedfilesharing'); - $addressHandler = new AddressHandler( - $this->serverContainer->getURLGenerator(), - $l, - $this->serverContainer->getCloudIdManager() - ); - $notifications = new Notifications( - $addressHandler, - $this->serverContainer->get(IClientService::class), - $this->serverContainer->get(\OCP\OCS\IDiscoveryService::class), - $this->serverContainer->getJobList(), - \OC::$server->getCloudFederationProviderManager(), - \OC::$server->get(ICloudFederationFactory::class), - $this->serverContainer->get(IEventDispatcher::class), - $this->serverContainer->get(LoggerInterface::class), - ); - $tokenHandler = new TokenHandler( - $this->serverContainer->get(ISecureRandom::class) - ); - - $this->federatedProvider = new FederatedShareProvider( - $this->serverContainer->getDatabaseConnection(), - $addressHandler, - $notifications, - $tokenHandler, - $l, - $this->serverContainer->get(IRootFolder::class), - $this->serverContainer->getConfig(), - $this->serverContainer->getUserManager(), - $this->serverContainer->getCloudIdManager(), - $this->serverContainer->getGlobalScaleConfig(), - $this->serverContainer->getCloudFederationProviderManager(), - $this->serverContainer->get(LoggerInterface::class), - ); + $this->federatedProvider = Server::get(FederatedShareProvider::class); } return $this->federatedProvider; @@ -153,90 +77,34 @@ class ProviderFactory implements IProviderFactory { /** * Create the federated share provider - * - * @return ShareByMailProvider */ - protected function getShareByMailProvider() { + protected function getShareByMailProvider(): ?ShareByMailProvider { if ($this->shareByMailProvider === null) { /* * Check if the app is enabled */ - $appManager = $this->serverContainer->getAppManager(); - if (!$appManager->isEnabledForUser('sharebymail')) { + if (!$this->appManager->isEnabledForUser('sharebymail')) { return null; } - $settingsManager = new SettingsManager($this->serverContainer->getConfig()); - - $this->shareByMailProvider = new ShareByMailProvider( - $this->serverContainer->getConfig(), - $this->serverContainer->getDatabaseConnection(), - $this->serverContainer->get(ISecureRandom::class), - $this->serverContainer->getUserManager(), - $this->serverContainer->get(IRootFolder::class), - $this->serverContainer->getL10N('sharebymail'), - $this->serverContainer->get(LoggerInterface::class), - $this->serverContainer->get(IMailer::class), - $this->serverContainer->getURLGenerator(), - $this->serverContainer->getActivityManager(), - $settingsManager, - $this->serverContainer->get(Defaults::class), - $this->serverContainer->get(IHasher::class), - $this->serverContainer->get(IEventDispatcher::class), - $this->serverContainer->get(IManager::class) - ); + $this->shareByMailProvider = Server::get(ShareByMailProvider::class); } return $this->shareByMailProvider; } - - /** - * Create the circle share provider - * - * @return FederatedShareProvider - * - * @suppress PhanUndeclaredClassMethod - */ - protected function getShareByCircleProvider() { - if ($this->circlesAreNotAvailable) { - return null; - } - - if (!$this->serverContainer->getAppManager()->isEnabledForUser('circles') || - !class_exists('\OCA\Circles\ShareByCircleProvider') - ) { - $this->circlesAreNotAvailable = true; - return null; - } - - if ($this->shareByCircleProvider === null) { - $this->shareByCircleProvider = new \OCA\Circles\ShareByCircleProvider( - $this->serverContainer->getDatabaseConnection(), - $this->serverContainer->get(ISecureRandom::class), - $this->serverContainer->getUserManager(), - $this->serverContainer->get(IRootFolder::class), - $this->serverContainer->getL10N('circles'), - $this->serverContainer->get(LoggerInterface::class), - $this->serverContainer->getURLGenerator() - ); - } - - return $this->shareByCircleProvider; - } - /** * Create the room share provider * - * @return RoomShareProvider + * @psalm-suppress UndefinedDocblockClass + * @return ?RoomShareProvider */ protected function getRoomShareProvider() { if ($this->roomShareProvider === null) { /* * Check if the app is enabled */ - $appManager = $this->serverContainer->getAppManager(); - if (!$appManager->isEnabledForUser('spreed')) { + if (!$this->appManager->isEnabledForUser('spreed')) { return null; } @@ -244,9 +112,9 @@ class ProviderFactory implements IProviderFactory { /** * @psalm-suppress UndefinedClass */ - $this->roomShareProvider = $this->serverContainer->get(RoomShareProvider::class); + $this->roomShareProvider = Server::get(RoomShareProvider::class); } catch (\Throwable $e) { - $this->serverContainer->get(LoggerInterface::class)->error( + $this->logger->error( $e->getMessage(), ['exception' => $e] ); @@ -272,8 +140,6 @@ class ProviderFactory implements IProviderFactory { $provider = $this->federatedShareProvider(); } elseif ($id === 'ocMailShare') { $provider = $this->getShareByMailProvider(); - } elseif ($id === 'ocCircleShare') { - $provider = $this->getShareByCircleProvider(); } elseif ($id === 'ocRoomShare') { $provider = $this->getRoomShareProvider(); } @@ -281,10 +147,10 @@ class ProviderFactory implements IProviderFactory { foreach ($this->registeredShareProviders as $shareProvider) { try { /** @var IShareProvider $instance */ - $instance = $this->serverContainer->get($shareProvider); + $instance = Server::get($shareProvider); $this->shareProviders[$instance->identifier()] = $instance; } catch (\Throwable $e) { - $this->serverContainer->get(LoggerInterface::class)->error( + $this->logger->error( $e->getMessage(), ['exception' => $e] ); @@ -308,9 +174,9 @@ class ProviderFactory implements IProviderFactory { public function getProviderForType($shareType) { $provider = null; - if ($shareType === IShare::TYPE_USER || - $shareType === IShare::TYPE_GROUP || - $shareType === IShare::TYPE_LINK + if ($shareType === IShare::TYPE_USER + || $shareType === IShare::TYPE_GROUP + || $shareType === IShare::TYPE_LINK ) { $provider = $this->defaultShareProvider(); } elseif ($shareType === IShare::TYPE_REMOTE || $shareType === IShare::TYPE_REMOTE_GROUP) { @@ -318,7 +184,7 @@ class ProviderFactory implements IProviderFactory { } elseif ($shareType === IShare::TYPE_EMAIL) { $provider = $this->getShareByMailProvider(); } elseif ($shareType === IShare::TYPE_CIRCLE) { - $provider = $this->getShareByCircleProvider(); + $provider = $this->getProvider('ocCircleShare'); } elseif ($shareType === IShare::TYPE_ROOM) { $provider = $this->getRoomShareProvider(); } elseif ($shareType === IShare::TYPE_DECK) { @@ -341,10 +207,6 @@ class ProviderFactory implements IProviderFactory { if ($shareByMail !== null) { $shares[] = $shareByMail; } - $shareByCircle = $this->getShareByCircleProvider(); - if ($shareByCircle !== null) { - $shares[] = $shareByCircle; - } $roomShare = $this->getRoomShareProvider(); if ($roomShare !== null) { $shares[] = $roomShare; @@ -353,9 +215,9 @@ class ProviderFactory implements IProviderFactory { foreach ($this->registeredShareProviders as $shareProvider) { try { /** @var IShareProvider $instance */ - $instance = $this->serverContainer->get($shareProvider); + $instance = Server::get($shareProvider); } catch (\Throwable $e) { - $this->serverContainer->get(LoggerInterface::class)->error( + $this->logger->error( $e->getMessage(), ['exception' => $e] ); diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php index c1c13c77fa4..8caabb0898a 100644 --- a/lib/private/Share20/Share.php +++ b/lib/private/Share20/Share.php @@ -14,8 +14,10 @@ use OCP\Files\IRootFolder; use OCP\Files\Node; use OCP\Files\NotFoundException; use OCP\IUserManager; +use OCP\Server; use OCP\Share\Exceptions\IllegalIDChangeException; use OCP\Share\IAttributes; +use OCP\Share\IManager; use OCP\Share\IShare; class Share implements IShare { @@ -66,14 +68,13 @@ class Share implements IShare { private $shareTime; /** @var bool */ private $mailSend; - /** @var string */ - private $label = ''; /** @var ICacheEntry|null */ private $nodeCacheEntry; /** @var bool */ private $hideDownload = false; private bool $reminderSent = false; + private string $label = ''; private bool $noExpirationDate = false; public function __construct( @@ -419,8 +420,8 @@ class Share implements IShare { * @inheritdoc */ public function isExpired() { - return $this->getExpirationDate() !== null && - $this->getExpirationDate() <= new \DateTime(); + return $this->getExpirationDate() !== null + && $this->getExpirationDate() <= new \DateTime(); } /** @@ -623,4 +624,23 @@ class Share implements IShare { public function getReminderSent(): bool { return $this->reminderSent; } + + public function canSeeContent(): bool { + $shareManager = Server::get(IManager::class); + + $allowViewWithoutDownload = $shareManager->allowViewWithoutDownload(); + // If the share manager allows viewing without download, we can always see the content. + if ($allowViewWithoutDownload) { + return true; + } + + // No "allow preview" header set, so we must check if + // the share has not explicitly disabled download permissions + $attributes = $this->getAttributes(); + if ($attributes?->getAttribute('permissions', 'download') === false) { + return false; + } + + return true; + } } diff --git a/lib/private/Share20/ShareAttributes.php b/lib/private/Share20/ShareAttributes.php index 96da1e336e3..f90fbd9c6cd 100644 --- a/lib/private/Share20/ShareAttributes.php +++ b/lib/private/Share20/ShareAttributes.php @@ -32,8 +32,8 @@ class ShareAttributes implements IAttributes { * @inheritdoc */ public function getAttribute(string $scope, string $key): mixed { - if (\array_key_exists($scope, $this->attributes) && - \array_key_exists($key, $this->attributes[$scope])) { + if (\array_key_exists($scope, $this->attributes) + && \array_key_exists($key, $this->attributes[$scope])) { return $this->attributes[$scope][$key]; } return null; diff --git a/lib/private/Share20/ShareDisableChecker.php b/lib/private/Share20/ShareDisableChecker.php index 9b8bc01558c..8cf523b8b31 100644 --- a/lib/private/Share20/ShareDisableChecker.php +++ b/lib/private/Share20/ShareDisableChecker.php @@ -25,12 +25,7 @@ class ShareDisableChecker { $this->sharingDisabledForUsersCache = new CappedMemoryCache(); } - - /** - * @param ?string $userId - * @return bool - */ - public function sharingDisabledForUser(?string $userId) { + public function sharingDisabledForUser(?string $userId): bool { if ($userId === null) { return false; } diff --git a/lib/private/Share20/ShareHelper.php b/lib/private/Share20/ShareHelper.php index d4a54f1d687..3f6bab98a7f 100644 --- a/lib/private/Share20/ShareHelper.php +++ b/lib/private/Share20/ShareHelper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Share20/UserDeletedListener.php b/lib/private/Share20/UserDeletedListener.php new file mode 100644 index 00000000000..e0e091454b0 --- /dev/null +++ b/lib/private/Share20/UserDeletedListener.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OC\Share20; + +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; +use OCP\Share\IManager; +use OCP\User\Events\UserDeletedEvent; + +/** + * @template-implements IEventListener<UserDeletedEvent> + */ +class UserDeletedListener implements IEventListener { + public function __construct( + protected IManager $shareManager, + ) { + } + + public function handle(Event $event): void { + if (!$event instanceof UserDeletedEvent) { + return; + } + + $this->shareManager->userDeleted($event->getUser()->getUID()); + } +} diff --git a/lib/private/Support/CrashReport/Registry.php b/lib/private/Support/CrashReport/Registry.php index 93969a81265..77dd8163174 100644 --- a/lib/private/Support/CrashReport/Registry.php +++ b/lib/private/Support/CrashReport/Registry.php @@ -110,6 +110,7 @@ class Registry implements IRegistry { \OC::$server->get(LoggerInterface::class)->critical('Could not load lazy crash reporter: ' . $e->getMessage(), [ 'exception' => $e, ]); + return; } /** * Try to register the loaded reporter. Theoretically it could be of a wrong diff --git a/lib/private/Support/Subscription/Registry.php b/lib/private/Support/Subscription/Registry.php index 3d3daa97abb..34f24d1d026 100644 --- a/lib/private/Support/Subscription/Registry.php +++ b/lib/private/Support/Subscription/Registry.php @@ -8,7 +8,6 @@ declare(strict_types=1); */ namespace OC\Support\Subscription; -use OC\User\Backend; use OCP\AppFramework\QueryException; use OCP\IConfig; use OCP\IGroupManager; @@ -19,8 +18,6 @@ use OCP\Support\Subscription\Exception\AlreadyRegisteredException; use OCP\Support\Subscription\IRegistry; use OCP\Support\Subscription\ISubscription; use OCP\Support\Subscription\ISupportedApps; -use OCP\User\Backend\ICountMappedUsersBackend; -use OCP\User\Backend\ICountUsersBackend; use Psr\Log\LoggerInterface; class Registry implements IRegistry { @@ -141,8 +138,8 @@ class Registry implements IRegistry { */ public function delegateIsHardUserLimitReached(?IManager $notificationManager = null): bool { $subscription = $this->getSubscription(); - if ($subscription instanceof ISubscription && - $subscription->hasValidSubscription()) { + if ($subscription instanceof ISubscription + && $subscription->hasValidSubscription()) { $userLimitReached = $subscription->isHardUserLimitReached(); if ($userLimitReached && $notificationManager instanceof IManager) { $this->notifyAboutReachedUserLimit($notificationManager); @@ -167,22 +164,8 @@ class Registry implements IRegistry { } private function getUserCount(): int { - $userCount = 0; - $backends = $this->userManager->getBackends(); - foreach ($backends as $backend) { - if ($backend instanceof ICountMappedUsersBackend) { - $userCount += $backend->countMappedUsers(); - } elseif ($backend->implementsActions(Backend::COUNT_USERS)) { - /** @var ICountUsersBackend $backend */ - $backendUsers = $backend->countUsers(); - if ($backendUsers !== false) { - $userCount += $backendUsers; - } else { - // TODO what if the user count can't be determined? - $this->logger->warning('Can not determine user count for ' . get_class($backend), ['app' => 'lib']); - } - } - } + /* We cannot limit because we substract disabled users afterward. But we limit to mapped users so should be not too expensive. */ + $userCount = (int)$this->userManager->countUsersTotal(0, true); $disabledUsers = $this->config->getUsersForUserValue('core', 'enabled', 'false'); $disabledUsersCount = count($disabledUsers); diff --git a/lib/private/SystemConfig.php b/lib/private/SystemConfig.php index 5818f78f962..57777b06ed6 100644 --- a/lib/private/SystemConfig.php +++ b/lib/private/SystemConfig.php @@ -73,6 +73,7 @@ class SystemConfig { // S3 'key' => true, 'secret' => true, + 'sse_c_key' => true, // Swift v2 'username' => true, 'password' => true, @@ -116,24 +117,6 @@ class SystemConfig { } /** - * Since system config is admin controlled, we can tell psalm to ignore any taint - * - * @psalm-taint-escape sql - * @psalm-taint-escape html - * @psalm-taint-escape ldap - * @psalm-taint-escape callable - * @psalm-taint-escape file - * @psalm-taint-escape ssrf - * @psalm-taint-escape cookie - * @psalm-taint-escape header - * @psalm-taint-escape has_quotes - * @psalm-pure - */ - public static function trustSystemConfig(mixed $value): mixed { - return $value; - } - - /** * Lists all available config keys * @return array an array of key names */ @@ -169,7 +152,7 @@ class SystemConfig { * @return mixed the value or $default */ public function getValue($key, $default = '') { - return $this->trustSystemConfig($this->config->getValue($key, $default)); + return $this->config->getValue($key, $default); } /** diff --git a/lib/private/SystemTag/ManagerFactory.php b/lib/private/SystemTag/ManagerFactory.php index 0fd2ca5fd36..4d3a1396529 100644 --- a/lib/private/SystemTag/ManagerFactory.php +++ b/lib/private/SystemTag/ManagerFactory.php @@ -9,7 +9,11 @@ declare(strict_types=1); namespace OC\SystemTag; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IAppConfig; +use OCP\IDBConnection; +use OCP\IGroupManager; use OCP\IServerContainer; +use OCP\IUserSession; use OCP\SystemTag\ISystemTagManager; use OCP\SystemTag\ISystemTagManagerFactory; use OCP\SystemTag\ISystemTagObjectMapper; @@ -36,9 +40,11 @@ class ManagerFactory implements ISystemTagManagerFactory { */ public function getManager(): ISystemTagManager { return new SystemTagManager( - $this->serverContainer->getDatabaseConnection(), - $this->serverContainer->getGroupManager(), + $this->serverContainer->get(IDBConnection::class), + $this->serverContainer->get(IGroupManager::class), $this->serverContainer->get(IEventDispatcher::class), + $this->serverContainer->get(IUserSession::class), + $this->serverContainer->get(IAppConfig::class), ); } @@ -50,7 +56,7 @@ class ManagerFactory implements ISystemTagManagerFactory { */ public function getObjectMapper(): ISystemTagObjectMapper { return new SystemTagObjectMapper( - $this->serverContainer->getDatabaseConnection(), + $this->serverContainer->get(IDBConnection::class), $this->getManager(), $this->serverContainer->get(IEventDispatcher::class), ); diff --git a/lib/private/SystemTag/SystemTagManager.php b/lib/private/SystemTag/SystemTagManager.php index 4f05d40c34c..e889ceff54e 100644 --- a/lib/private/SystemTag/SystemTagManager.php +++ b/lib/private/SystemTag/SystemTagManager.php @@ -11,14 +11,18 @@ namespace OC\SystemTag; use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IAppConfig; use OCP\IDBConnection; use OCP\IGroupManager; use OCP\IUser; +use OCP\IUserSession; use OCP\SystemTag\ISystemTag; use OCP\SystemTag\ISystemTagManager; use OCP\SystemTag\ManagerEvent; use OCP\SystemTag\TagAlreadyExistsException; +use OCP\SystemTag\TagCreationForbiddenException; use OCP\SystemTag\TagNotFoundException; +use OCP\SystemTag\TagUpdateForbiddenException; /** * Manager class for system tags @@ -36,6 +40,8 @@ class SystemTagManager implements ISystemTagManager { protected IDBConnection $connection, protected IGroupManager $groupManager, protected IEventDispatcher $dispatcher, + private IUserSession $userSession, + private IAppConfig $appConfig, ) { $query = $this->connection->getQueryBuilder(); $this->selectTagQuery = $query->select('*') @@ -145,6 +151,11 @@ class SystemTagManager implements ISystemTagManager { } public function createTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag { + $user = $this->userSession->getUser(); + if (!$this->canUserCreateTag($user)) { + throw new TagCreationForbiddenException(); + } + // Length of name column is 64 $truncatedTagName = substr($tagName, 0, 64); $query = $this->connection->getQueryBuilder(); @@ -197,8 +208,14 @@ class SystemTagManager implements ISystemTagManager { ); } + $user = $this->userSession->getUser(); + if (!$this->canUserUpdateTag($user)) { + throw new TagUpdateForbiddenException(); + } + $beforeUpdate = array_shift($tags); // Length of name column is 64 + $newName = trim($newName); $truncatedNewName = substr($newName, 0, 64); $afterUpdate = new SystemTag( $tagId, @@ -319,6 +336,24 @@ class SystemTagManager implements ISystemTagManager { return false; } + public function canUserCreateTag(?IUser $user): bool { + if ($user === null) { + // If no user given, allows only calls from CLI + return \OC::$CLI; + } + + if ($this->appConfig->getValueBool('systemtags', 'restrict_creation_to_admin', false) === false) { + return true; + } + + return $this->groupManager->isAdmin($user->getUID()); + } + + public function canUserUpdateTag(?IUser $user): bool { + // We currently have no different permissions for updating tags than for creating them + return $this->canUserCreateTag($user); + } + public function canUserSeeTag(ISystemTag $tag, ?IUser $user): bool { // If no user, then we only show public tags if (!$user && $tag->getAccessLevel() === ISystemTag::ACCESS_LEVEL_PUBLIC) { diff --git a/lib/private/SystemTag/SystemTagObjectMapper.php b/lib/private/SystemTag/SystemTagObjectMapper.php index 09a7ce1a6ed..1fa5975dafb 100644 --- a/lib/private/SystemTag/SystemTagObjectMapper.php +++ b/lib/private/SystemTag/SystemTagObjectMapper.php @@ -284,6 +284,10 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { * {@inheritdoc} */ public function setObjectIdsForTag(string $tagId, string $objectType, array $objectIds): void { + $currentObjectIds = $this->getObjectIdsForTags($tagId, $objectType); + $removedObjectIds = array_diff($currentObjectIds, $objectIds); + $addedObjectIds = array_diff($objectIds, $currentObjectIds); + $this->connection->beginTransaction(); $query = $this->connection->getQueryBuilder(); $query->delete(self::RELATION_TABLE) @@ -292,6 +296,15 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { ->executeStatement(); $this->connection->commit(); + foreach ($removedObjectIds as $objectId) { + $this->dispatcher->dispatch(MapperEvent::EVENT_UNASSIGN, new MapperEvent( + MapperEvent::EVENT_UNASSIGN, + $objectType, + (string)$objectId, + [(int)$tagId] + )); + } + if (empty($objectIds)) { return; } @@ -312,6 +325,26 @@ class SystemTagObjectMapper implements ISystemTagObjectMapper { $this->updateEtagForTags([$tagId]); $this->connection->commit(); + + // Dispatch assign events for new object ids + foreach ($addedObjectIds as $objectId) { + $this->dispatcher->dispatch(MapperEvent::EVENT_ASSIGN, new MapperEvent( + MapperEvent::EVENT_ASSIGN, + $objectType, + (string)$objectId, + [(int)$tagId] + )); + } + + // Dispatch unassign events for removed object ids + foreach ($removedObjectIds as $objectId) { + $this->dispatcher->dispatch(MapperEvent::EVENT_UNASSIGN, new MapperEvent( + MapperEvent::EVENT_UNASSIGN, + $objectType, + (string)$objectId, + [(int)$tagId] + )); + } } /** diff --git a/lib/private/TaskProcessing/Manager.php b/lib/private/TaskProcessing/Manager.php index ffa39912a01..0ffd141543f 100644 --- a/lib/private/TaskProcessing/Manager.php +++ b/lib/private/TaskProcessing/Manager.php @@ -31,14 +31,19 @@ use OCP\Files\Node; use OCP\Files\NotPermittedException; use OCP\Files\SimpleFS\ISimpleFile; use OCP\Http\Client\IClientService; +use OCP\ICache; +use OCP\ICacheFactory; use OCP\IConfig; use OCP\IL10N; use OCP\IServerContainer; +use OCP\IUserManager; +use OCP\IUserSession; use OCP\L10N\IFactory; use OCP\Lock\LockedException; use OCP\SpeechToText\ISpeechToTextProvider; use OCP\SpeechToText\ISpeechToTextProviderWithId; use OCP\TaskProcessing\EShapeType; +use OCP\TaskProcessing\Events\GetTaskProcessingProvidersEvent; use OCP\TaskProcessing\Events\TaskFailedEvent; use OCP\TaskProcessing\Events\TaskSuccessfulEvent; use OCP\TaskProcessing\Exception\NotFoundException; @@ -77,6 +82,15 @@ class Manager implements IManager { private ?array $availableTaskTypes = null; private IAppData $appData; + private ?array $preferences = null; + private ?array $providersById = null; + + /** @var ITaskType[]|null */ + private ?array $taskTypes = null; + private ICache $distributedCache; + + private ?GetTaskProcessingProvidersEvent $eventResult = null; + public function __construct( private IConfig $config, private Coordinator $coordinator, @@ -91,8 +105,12 @@ class Manager implements IManager { private IUserMountCache $userMountCache, private IClientService $clientService, private IAppManager $appManager, + private IUserManager $userManager, + private IUserSession $userSession, + ICacheFactory $cacheFactory, ) { $this->appData = $appDataFactory->get('core'); + $this->distributedCache = $cacheFactory->createDistributed('task_processing::'); } @@ -481,6 +499,20 @@ class Manager implements IManager { } /** + * Dispatches the event to collect external providers and task types. + * Caches the result within the request. + */ + private function dispatchGetProvidersEvent(): GetTaskProcessingProvidersEvent { + if ($this->eventResult !== null) { + return $this->eventResult; + } + + $this->eventResult = new GetTaskProcessingProvidersEvent(); + $this->dispatcher->dispatchTyped($this->eventResult); + return $this->eventResult ; + } + + /** * @return IProvider[] */ private function _getProviders(): array { @@ -508,6 +540,16 @@ class Manager implements IManager { } } + $event = $this->dispatchGetProvidersEvent(); + $externalProviders = $event->getProviders(); + foreach ($externalProviders as $provider) { + if (!isset($providers[$provider->getId()])) { + $providers[$provider->getId()] = $provider; + } else { + $this->logger->info('Skipping external task processing provider with ID ' . $provider->getId() . ' because a local provider with the same ID already exists.'); + } + } + $providers += $this->_getTextProcessingProviders() + $this->_getTextToImageProviders() + $this->_getSpeechToTextProviders(); return $providers; @@ -523,6 +565,10 @@ class Manager implements IManager { return []; } + if ($this->taskTypes !== null) { + return $this->taskTypes; + } + // Default task types $taskTypes = [ \OCP\TaskProcessing\TaskTypes\TextToText::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToText::class), @@ -541,6 +587,8 @@ class Manager implements IManager { \OCP\TaskProcessing\TaskTypes\TextToTextChangeTone::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToTextChangeTone::class), \OCP\TaskProcessing\TaskTypes\TextToTextChatWithTools::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToTextChatWithTools::class), \OCP\TaskProcessing\TaskTypes\ContextAgentInteraction::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\ContextAgentInteraction::class), + \OCP\TaskProcessing\TaskTypes\TextToTextProofread::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToTextProofread::class), + \OCP\TaskProcessing\TaskTypes\TextToSpeech::ID => \OCP\Server::get(\OCP\TaskProcessing\TaskTypes\TextToSpeech::class), ]; foreach ($context->getTaskProcessingTaskTypes() as $providerServiceRegistration) { @@ -559,9 +607,42 @@ class Manager implements IManager { } } + $event = $this->dispatchGetProvidersEvent(); + $externalTaskTypes = $event->getTaskTypes(); + foreach ($externalTaskTypes as $taskType) { + if (isset($taskTypes[$taskType->getId()])) { + $this->logger->warning('External task processing task type is using ID ' . $taskType->getId() . ' which is already used by a locally registered task type (' . get_class($taskTypes[$taskType->getId()]) . ')'); + } + $taskTypes[$taskType->getId()] = $taskType; + } + $taskTypes += $this->_getTextProcessingTaskTypes(); - return $taskTypes; + $this->taskTypes = $taskTypes; + return $this->taskTypes; + } + + /** + * @return array + */ + private function _getTaskTypeSettings(): array { + try { + $json = $this->config->getAppValue('core', 'ai.taskprocessing_type_preferences', ''); + if ($json === '') { + return []; + } + return json_decode($json, true, flags: JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + $this->logger->error('Failed to get settings. JSON Error in ai.taskprocessing_type_preferences', ['exception' => $e]); + $taskTypeSettings = []; + $taskTypes = $this->_getTaskTypes(); + foreach ($taskTypes as $taskType) { + $taskTypeSettings[$taskType->getId()] = false; + }; + + return $taskTypeSettings; + } + } /** @@ -701,12 +782,23 @@ class Manager implements IManager { public function getPreferredProvider(string $taskTypeId) { try { - $preferences = json_decode($this->config->getAppValue('core', 'ai.taskprocessing_provider_preferences', 'null'), associative: true, flags: JSON_THROW_ON_ERROR); + if ($this->preferences === null) { + $this->preferences = $this->distributedCache->get('ai.taskprocessing_provider_preferences'); + if ($this->preferences === null) { + $this->preferences = json_decode($this->config->getAppValue('core', 'ai.taskprocessing_provider_preferences', 'null'), associative: true, flags: JSON_THROW_ON_ERROR); + $this->distributedCache->set('ai.taskprocessing_provider_preferences', $this->preferences, 60 * 3); + } + } + $providers = $this->getProviders(); - if (isset($preferences[$taskTypeId])) { - $provider = current(array_values(array_filter($providers, fn ($provider) => $provider->getId() === $preferences[$taskTypeId]))); - if ($provider !== false) { - return $provider; + if (isset($this->preferences[$taskTypeId])) { + $providersById = $this->providersById ?? array_reduce($providers, static function (array $carry, IProvider $provider) { + $carry[$provider->getId()] = $provider; + return $carry; + }, []); + $this->providersById = $providersById; + if (isset($providersById[$this->preferences[$taskTypeId]])) { + return $providersById[$this->preferences[$taskTypeId]]; } } // By default, use the first available provider @@ -721,12 +813,27 @@ class Manager implements IManager { throw new \OCP\TaskProcessing\Exception\Exception('No matching provider found'); } - public function getAvailableTaskTypes(): array { + public function getAvailableTaskTypes(bool $showDisabled = false, ?string $userId = null): array { + // userId will be obtained from the session if left to null + if (!$this->checkGuestAccess($userId)) { + return []; + } if ($this->availableTaskTypes === null) { + $cachedValue = $this->distributedCache->get('available_task_types_v2'); + if ($cachedValue !== null) { + $this->availableTaskTypes = unserialize($cachedValue); + } + } + // Either we have no cache or showDisabled is turned on, which we don't want to cache, ever. + if ($this->availableTaskTypes === null || $showDisabled) { $taskTypes = $this->_getTaskTypes(); + $taskTypeSettings = $this->_getTaskTypeSettings(); $availableTaskTypes = []; foreach ($taskTypes as $taskType) { + if ((!$showDisabled) && isset($taskTypeSettings[$taskType->getId()]) && !$taskTypeSettings[$taskType->getId()]) { + continue; + } try { $provider = $this->getPreferredProvider($taskType->getId()); } catch (\OCP\TaskProcessing\Exception\Exception $e) { @@ -752,9 +859,16 @@ class Manager implements IManager { } } + if ($showDisabled) { + // Do not cache showDisabled, ever. + return $availableTaskTypes; + } + $this->availableTaskTypes = $availableTaskTypes; + $this->distributedCache->set('available_task_types_v2', serialize($this->availableTaskTypes), 60); } + return $this->availableTaskTypes; } @@ -762,7 +876,27 @@ class Manager implements IManager { return isset($this->getAvailableTaskTypes()[$task->getTaskTypeId()]); } + private function checkGuestAccess(?string $userId = null): bool { + if ($userId === null && !$this->userSession->isLoggedIn()) { + return true; + } + if ($userId === null) { + $user = $this->userSession->getUser(); + } else { + $user = $this->userManager->get($userId); + } + + $guestsAllowed = $this->config->getAppValue('core', 'ai.taskprocessing_guests', 'false'); + if ($guestsAllowed == 'true' || !class_exists(\OCA\Guests\UserBackend::class) || !($user->getBackend() instanceof \OCA\Guests\UserBackend)) { + return true; + } + return false; + } + public function scheduleTask(Task $task): void { + if (!$this->checkGuestAccess($task->getUserId())) { + throw new \OCP\TaskProcessing\Exception\PreConditionNotMetException('Access to this resource is forbidden for guests.'); + } if (!$this->canHandleTask($task)) { throw new \OCP\TaskProcessing\Exception\PreConditionNotMetException('No task processing provider is installed that can handle this task type: ' . $task->getTaskTypeId()); } @@ -777,6 +911,9 @@ class Manager implements IManager { } public function runTask(Task $task): Task { + if (!$this->checkGuestAccess($task->getUserId())) { + throw new \OCP\TaskProcessing\Exception\PreConditionNotMetException('Access to this resource is forbidden for guests.'); + } if (!$this->canHandleTask($task)) { throw new \OCP\TaskProcessing\Exception\PreConditionNotMetException('No task processing provider is installed that can handle this task type: ' . $task->getTaskTypeId()); } @@ -938,7 +1075,7 @@ class Manager implements IManager { $task->setEndedAt(time()); $error = 'The task was processed successfully but the provider\'s output doesn\'t pass validation against the task type\'s outputShape spec and/or the provider\'s own optionalOutputShape spec'; $task->setErrorMessage($error); - $this->logger->error($error, ['exception' => $e]); + $this->logger->error($error, ['exception' => $e, 'output' => $result]); } catch (NotPermittedException $e) { $task->setProgress(1); $task->setStatus(Task::STATUS_FAILED); @@ -955,7 +1092,11 @@ class Manager implements IManager { $this->logger->error($error, ['exception' => $e]); } } - $taskEntity = \OC\TaskProcessing\Db\Task::fromPublicTask($task); + try { + $taskEntity = \OC\TaskProcessing\Db\Task::fromPublicTask($task); + } catch (\JsonException $e) { + throw new \OCP\TaskProcessing\Exception\Exception('The task was processed successfully but the provider\'s output could not be encoded as JSON for the database.', 0, $e); + } try { $this->taskMapper->update($taskEntity); $this->runWebhook($task); @@ -1331,7 +1472,7 @@ class Manager implements IManager { $this->logger->warning('Task processing AppAPI webhook failed for task ' . $task->getId() . '. Invalid method: ' . $method); } [, $exAppId, $httpMethod] = $parsedMethod; - if (!$this->appManager->isInstalled('app_api')) { + if (!$this->appManager->isEnabledForAnyone('app_api')) { $this->logger->warning('Task processing AppAPI webhook failed for task ' . $task->getId() . '. AppAPI is disabled or not installed.'); return; } diff --git a/lib/private/TaskProcessing/RemoveOldTasksBackgroundJob.php b/lib/private/TaskProcessing/RemoveOldTasksBackgroundJob.php index c6f26e3aa8b..42d073a024d 100644 --- a/lib/private/TaskProcessing/RemoveOldTasksBackgroundJob.php +++ b/lib/private/TaskProcessing/RemoveOldTasksBackgroundJob.php @@ -16,7 +16,7 @@ use OCP\Files\SimpleFS\ISimpleFolder; use Psr\Log\LoggerInterface; class RemoveOldTasksBackgroundJob extends TimedJob { - public const MAX_TASK_AGE_SECONDS = 60 * 60 * 24 * 7 * 4; // 4 weeks + public const MAX_TASK_AGE_SECONDS = 60 * 60 * 24 * 30 * 4; // 4 months private \OCP\Files\IAppData $appData; public function __construct( diff --git a/lib/private/TaskProcessing/SynchronousBackgroundJob.php b/lib/private/TaskProcessing/SynchronousBackgroundJob.php index de3b424176c..19c53d59932 100644 --- a/lib/private/TaskProcessing/SynchronousBackgroundJob.php +++ b/lib/private/TaskProcessing/SynchronousBackgroundJob.php @@ -59,8 +59,8 @@ class SynchronousBackgroundJob extends QueuedJob { // check if this job needs to be scheduled again: // if there is at least one preferred synchronous provider that has a scheduled task - $synchronousProviders = array_filter($providers, fn ($provider) => - $provider instanceof ISynchronousProvider); + $synchronousProviders = array_filter($providers, fn ($provider) + => $provider instanceof ISynchronousProvider); $synchronousPreferredProviders = array_filter($synchronousProviders, function ($provider) { $taskTypeId = $provider->getTaskTypeId(); $preferredProvider = $this->taskProcessingManager->getPreferredProvider($taskTypeId); diff --git a/lib/private/Teams/TeamManager.php b/lib/private/Teams/TeamManager.php index d75b0209c71..13d6cc459a9 100644 --- a/lib/private/Teams/TeamManager.php +++ b/lib/private/Teams/TeamManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/TempManager.php b/lib/private/TempManager.php index f55d722d9d9..4c0ffcf43d7 100644 --- a/lib/private/TempManager.php +++ b/lib/private/TempManager.php @@ -8,8 +8,10 @@ namespace OC; use bantu\IniGetWrapper\IniGetWrapper; +use OCP\Files; use OCP\IConfig; use OCP\ITempManager; +use OCP\Security\ISecureRandom; use Psr\Log\LoggerInterface; class TempManager implements ITempManager { @@ -34,51 +36,25 @@ class TempManager implements ITempManager { $this->tmpBaseDir = $this->getTempBaseDir(); } - /** - * Builds the filename with suffix and removes potential dangerous characters - * such as directory separators. - * - * @param string $absolutePath Absolute path to the file / folder - * @param string $postFix Postfix appended to the temporary file name, may be user controlled - * @return string - */ - private function buildFileNameWithSuffix($absolutePath, $postFix = '') { + private function generateTemporaryPath(string $postFix): string { + $secureRandom = \OCP\Server::get(ISecureRandom::class); + $absolutePath = $this->tmpBaseDir . '/' . self::TMP_PREFIX . $secureRandom->generate(32, ISecureRandom::CHAR_ALPHANUMERIC); + if ($postFix !== '') { $postFix = '.' . ltrim($postFix, '.'); $postFix = str_replace(['\\', '/'], '', $postFix); - $absolutePath .= '-'; } return $absolutePath . $postFix; } - /** - * Create a temporary file and return the path - * - * @param string $postFix Postfix appended to the temporary file name - * @return string - */ - public function getTemporaryFile($postFix = '') { - if (is_writable($this->tmpBaseDir)) { - // To create an unique file and prevent the risk of race conditions - // or duplicated temporary files by other means such as collisions - // we need to create the file using `tempnam` and append a possible - // postfix to it later - $file = tempnam($this->tmpBaseDir, self::TMP_PREFIX); - $this->current[] = $file; + public function getTemporaryFile($postFix = ''): string|false { + $path = $this->generateTemporaryPath($postFix); - // If a postfix got specified sanitize it and create a postfixed - // temporary file - if ($postFix !== '') { - $fileNameWithPostfix = $this->buildFileNameWithSuffix($file, $postFix); - touch($fileNameWithPostfix); - chmod($fileNameWithPostfix, 0600); - $this->current[] = $fileNameWithPostfix; - return $fileNameWithPostfix; - } - - return $file; - } else { + $old_umask = umask(0077); + $fp = fopen($path, 'x'); + umask($old_umask); + if ($fp === false) { $this->log->warning( 'Can not create a temporary file in directory {dir}. Check it exists and has correct permissions', [ @@ -87,30 +63,16 @@ class TempManager implements ITempManager { ); return false; } - } - /** - * Create a temporary folder and return the path - * - * @param string $postFix Postfix appended to the temporary folder name - * @return string - */ - public function getTemporaryFolder($postFix = '') { - if (is_writable($this->tmpBaseDir)) { - // To create an unique directory and prevent the risk of race conditions - // or duplicated temporary files by other means such as collisions - // we need to create the file using `tempnam` and append a possible - // postfix to it later - $uniqueFileName = tempnam($this->tmpBaseDir, self::TMP_PREFIX); - $this->current[] = $uniqueFileName; + fclose($fp); + $this->current[] = $path; + return $path; + } - // Build a name without postfix - $path = $this->buildFileNameWithSuffix($uniqueFileName . '-folder', $postFix); - mkdir($path, 0700); - $this->current[] = $path; + public function getTemporaryFolder($postFix = ''): string|false { + $path = $this->generateTemporaryPath($postFix) . '/'; - return $path . '/'; - } else { + if (mkdir($path, 0700) === false) { $this->log->warning( 'Can not create a temporary folder in directory {dir}. Check it exists and has correct permissions', [ @@ -119,6 +81,9 @@ class TempManager implements ITempManager { ); return false; } + + $this->current[] = $path; + return $path; } /** @@ -135,7 +100,7 @@ class TempManager implements ITempManager { foreach ($files as $file) { if (file_exists($file)) { try { - \OC_Helper::rmdirr($file); + Files::rmdirr($file); } catch (\UnexpectedValueException $ex) { $this->log->warning( 'Error deleting temporary file/folder: {file} - Reason: {error}', diff --git a/lib/private/Template/Base.php b/lib/private/Template/Base.php index 602c8e6257e..a13e6703960 100644 --- a/lib/private/Template/Base.php +++ b/lib/private/Template/Base.php @@ -8,11 +8,10 @@ namespace OC\Template; use OCP\Defaults; -use Throwable; class Base { private $template; // The template - private $vars; // Vars + private array $vars = []; /** @var \OCP\IL10N */ private $l10n; @@ -59,11 +58,9 @@ class Base { } /** - * @param string $serverRoot - * @param string $theme * @return string[] */ - protected function getCoreTemplateDirs($theme, $serverRoot) { + protected function getCoreTemplateDirs(string $theme, string $serverRoot): array { return [ $serverRoot . '/themes/' . $theme . '/core/templates/', $serverRoot . '/core/templates/', @@ -72,30 +69,24 @@ class Base { /** * Assign variables - * @param string $key key - * @param float|array|bool|integer|string|Throwable $value value - * @return bool * * This function assigns a variable. It can be accessed via $_[$key] in * the template. * * If the key existed before, it will be overwritten */ - public function assign($key, $value) { + public function assign(string $key, mixed $value): void { $this->vars[$key] = $value; - return true; } /** * Appends a variable - * @param string $key key - * @param mixed $value value * * This function assigns a variable in an array context. If the key already * exists, the value will be appended. It can be accessed via * $_[$key][$position] in the template. */ - public function append($key, $value) { + public function append(string $key, mixed $value): void { if (array_key_exists($key, $this->vars)) { $this->vars[$key][] = $value; } else { @@ -105,42 +96,29 @@ class Base { /** * Prints the proceeded template - * @return bool * * This function proceeds the template and prints its output. */ - public function printPage() { + public function printPage(): void { $data = $this->fetchPage(); - if ($data === false) { - return false; - } else { - print $data; - return true; - } + print $data; } /** * Process the template * - * @param array|null $additionalParams - * @return string This function processes the template. - * * This function processes the template. */ - public function fetchPage($additionalParams = null) { + public function fetchPage(?array $additionalParams = null): string { return $this->load($this->template, $additionalParams); } /** * doing the actual work * - * @param string $file - * @param array|null $additionalParams - * @return string content - * * Includes the template file, fetches its output */ - protected function load($file, $additionalParams = null) { + protected function load(string $file, ?array $additionalParams = null): string { // Register the variables $_ = $this->vars; $l = $this->l10n; @@ -158,6 +136,7 @@ class Base { // Include ob_start(); try { + require_once __DIR__ . '/functions.php'; include $file; $data = ob_get_contents(); } catch (\Exception $e) { diff --git a/lib/private/Template/JSCombiner.php b/lib/private/Template/JSCombiner.php index 5fce3effb3f..a94f822a448 100644 --- a/lib/private/Template/JSCombiner.php +++ b/lib/private/Template/JSCombiner.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Template/JSConfigHelper.php b/lib/private/Template/JSConfigHelper.php index e6d3c6af87e..de9df04ae4b 100644 --- a/lib/private/Template/JSConfigHelper.php +++ b/lib/private/Template/JSConfigHelper.php @@ -12,7 +12,7 @@ use OC\Authentication\Token\IProvider; use OC\CapabilitiesManager; use OC\Files\FilenameValidator; use OC\Share\Share; -use OCA\Provisioning_API\Controller\AUserData; +use OCA\Provisioning_API\Controller\AUserDataOCSController; use OCP\App\AppPathNotFoundException; use OCP\App\IAppManager; use OCP\Authentication\Exceptions\ExpiredTokenException; @@ -30,6 +30,7 @@ use OCP\ILogger; use OCP\ISession; use OCP\IURLGenerator; use OCP\IUser; +use OCP\Server; use OCP\ServerVersion; use OCP\Session\Exceptions\SessionNotAvailableException; use OCP\Share\IManager as IShareManager; @@ -66,7 +67,7 @@ class JSConfigHelper { $backend = $this->currentUser->getBackend(); if ($backend instanceof IPasswordConfirmationBackend) { - $userBackendAllowsPasswordConfirmation = $backend->canConfirmPassword($uid); + $userBackendAllowsPasswordConfirmation = $backend->canConfirmPassword($uid) && $this->canUserValidatePassword(); } elseif (isset($this->excludedUserBackEnds[$this->currentUser->getBackendClassName()])) { $userBackendAllowsPasswordConfirmation = false; } @@ -78,7 +79,7 @@ class JSConfigHelper { $apps_paths = []; if ($this->currentUser === null) { - $apps = $this->appManager->getInstalledApps(); + $apps = $this->appManager->getEnabledApps(); } else { $apps = $this->appManager->getEnabledAppsForUser($this->currentUser); } @@ -136,7 +137,7 @@ class JSConfigHelper { $capabilities = $this->capabilitiesManager->getCapabilities(false, true); - $userFirstDay = $this->config->getUserValue($uid, 'core', AUserData::USER_FIELD_FIRST_DAY_OF_WEEK, null); + $userFirstDay = $this->config->getUserValue($uid, 'core', AUserDataOCSController::USER_FIELD_FIRST_DAY_OF_WEEK, null); $firstDay = (int)($userFirstDay ?? $this->l->l('firstday', null)); $config = [ @@ -161,6 +162,8 @@ class JSConfigHelper { 'enable_non-accessible_features' => $this->config->getSystemValueBool('enable_non-accessible_features', true), ]; + $shareManager = Server::get(IShareManager::class); + $array = [ '_oc_debug' => $this->config->getSystemValue('debug', false) ? 'true' : 'false', '_oc_isadmin' => $uid !== null && $this->groupManager->isAdmin($uid) ? 'true' : 'false', @@ -235,11 +238,11 @@ class JSConfigHelper { 'defaultExpireDateEnforced' => $enforceDefaultExpireDate, 'enforcePasswordForPublicLink' => Util::isPublicLinkPasswordRequired(), 'enableLinkPasswordByDefault' => $enableLinkPasswordByDefault, - 'sharingDisabledForUser' => Util::isSharingDisabledForUser(), + 'sharingDisabledForUser' => $shareManager->sharingDisabledForUser($uid), 'resharingAllowed' => Share::isResharingAllowed(), 'remoteShareAllowed' => $outgoingServer2serverShareEnabled, 'federatedCloudShareDoc' => $this->urlGenerator->linkToDocs('user-sharing-federated'), - 'allowGroupSharing' => \OC::$server->get(IShareManager::class)->allowGroupSharing(), + 'allowGroupSharing' => $shareManager->allowGroupSharing(), 'defaultInternalExpireDateEnabled' => $defaultInternalExpireDateEnabled, 'defaultInternalExpireDate' => $defaultInternalExpireDate, 'defaultInternalExpireDateEnforced' => $defaultInternalExpireDateEnforced, diff --git a/lib/private/Template/JSResourceLocator.php b/lib/private/Template/JSResourceLocator.php index aad999f939a..a6d2d13a2ad 100644 --- a/lib/private/Template/JSResourceLocator.php +++ b/lib/private/Template/JSResourceLocator.php @@ -69,7 +69,7 @@ class JSResourceLocator extends ResourceLocator { || $this->appendScriptIfExist($this->serverroot, "dist/$app-$scriptName") || $this->appendScriptIfExist($appRoot, $script, $appWebRoot) || $this->cacheAndAppendCombineJsonIfExist($this->serverroot, $script . '.json') - || $this->cacheAndAppendCombineJsonIfExist($appRoot, $script . '.json', $appWebRoot) + || $this->cacheAndAppendCombineJsonIfExist($appRoot, $script . '.json', $app) || $this->appendScriptIfExist($this->serverroot, $theme_dir . 'core/' . $script) || $this->appendScriptIfExist($this->serverroot, 'core/' . $script) || (strpos($scriptName, '/') === -1 && ($this->appendScriptIfExist($this->serverroot, $theme_dir . "dist/core-$scriptName") diff --git a/lib/private/Template/Template.php b/lib/private/Template/Template.php new file mode 100644 index 00000000000..ee85562091f --- /dev/null +++ b/lib/private/Template/Template.php @@ -0,0 +1,159 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace OC\Template; + +use OC\Security\CSP\ContentSecurityPolicyNonceManager; +use OC\TemplateLayout; +use OCP\App\AppPathNotFoundException; +use OCP\App\IAppManager; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\Defaults; +use OCP\Server; +use OCP\Template\ITemplate; +use OCP\Template\TemplateNotFoundException; +use OCP\Util; + +class Template extends Base implements ITemplate { + private string $path; + private array $headers = []; + + /** + * @param string $app app providing the template + * @param string $name of the template file (without suffix) + * @param TemplateResponse::RENDER_AS_* $renderAs If $renderAs is set, will try to + * produce a full page in the according layout. + * @throws TemplateNotFoundException + */ + public function __construct( + protected string $app, + string $name, + private string $renderAs = TemplateResponse::RENDER_AS_BLANK, + bool $registerCall = true, + ) { + $theme = \OC_Util::getTheme(); + + $requestToken = ($registerCall ? Util::callRegister() : ''); + $cspNonce = Server::get(ContentSecurityPolicyNonceManager::class)->getNonce(); + + // fix translation when app is something like core/lostpassword + $parts = explode('/', $app); + $l10n = Util::getL10N($parts[0]); + + [$path, $template] = $this->findTemplate($theme, $app, $name); + + $this->path = $path; + + parent::__construct( + $template, + $requestToken, + $l10n, + Server::get(Defaults::class), + $cspNonce, + ); + } + + + /** + * find the template with the given name + * + * Will select the template file for the selected theme. + * Checking all the possible locations. + * + * @param string $name of the template file (without suffix) + * @return array{string,string} Directory path and filename + * @throws TemplateNotFoundException + */ + protected function findTemplate(string $theme, string $app, string $name): array { + // Check if it is a app template or not. + if ($app !== '') { + try { + $appDir = Server::get(IAppManager::class)->getAppPath($app); + } catch (AppPathNotFoundException) { + $appDir = false; + } + $dirs = $this->getAppTemplateDirs($theme, $app, \OC::$SERVERROOT, $appDir); + } else { + $dirs = $this->getCoreTemplateDirs($theme, \OC::$SERVERROOT); + } + $locator = new TemplateFileLocator($dirs); + return $locator->find($name); + } + + /** + * Add a custom element to the header + * @param string $tag tag name of the element + * @param array $attributes array of attributes for the element + * @param string $text the text content for the element. If $text is null then the + * element will be written as empty element. So use "" to get a closing tag. + */ + public function addHeader(string $tag, array $attributes, ?string $text = null): void { + $this->headers[] = [ + 'tag' => $tag, + 'attributes' => $attributes, + 'text' => $text + ]; + } + + /** + * Process the template + * + * This function process the template. If $this->renderAs is set, it + * will produce a full page. + */ + public function fetchPage(?array $additionalParams = null): string { + $data = parent::fetchPage($additionalParams); + + if ($this->renderAs) { + $page = Server::get(TemplateLayout::class)->getPageTemplate($this->renderAs, $this->app); + + if (is_array($additionalParams)) { + foreach ($additionalParams as $key => $value) { + $page->assign($key, $value); + } + } + + // Add custom headers + $headers = ''; + foreach (\OC_Util::$headers as $header) { + $headers .= '<' . Util::sanitizeHTML($header['tag']); + if (strcasecmp($header['tag'], 'script') === 0 && in_array('src', array_map('strtolower', array_keys($header['attributes'])))) { + $headers .= ' defer'; + } + foreach ($header['attributes'] as $name => $value) { + $headers .= ' ' . Util::sanitizeHTML($name) . '="' . Util::sanitizeHTML($value) . '"'; + } + if ($header['text'] !== null) { + $headers .= '>' . Util::sanitizeHTML($header['text']) . '</' . Util::sanitizeHTML($header['tag']) . '>'; + } else { + $headers .= '/>'; + } + } + + $page->assign('headers', $headers); + $page->assign('content', $data); + return $page->fetchPage($additionalParams); + } + + return $data; + } + + /** + * Include template + * + * @return string returns content of included template + * + * Includes another template. use <?php echo $this->inc('template'); ?> to + * do this. + */ + public function inc(string $file, ?array $additionalParams = null): string { + return $this->load($this->path . $file . '.php', $additionalParams); + } +} diff --git a/lib/private/Template/TemplateFileLocator.php b/lib/private/Template/TemplateFileLocator.php index 38583d158a3..11a568b5b21 100644 --- a/lib/private/Template/TemplateFileLocator.php +++ b/lib/private/Template/TemplateFileLocator.php @@ -1,29 +1,31 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OC\Template; -class TemplateFileLocator { - protected $dirs; - private $path; +use OCP\Template\TemplateNotFoundException; +class TemplateFileLocator { /** * @param string[] $dirs */ - public function __construct($dirs) { - $this->dirs = $dirs; + public function __construct( + private array $dirs, + ) { } /** - * @param string $template - * @return string - * @throws \Exception + * @return array{string,string} Directory path and filename + * @throws TemplateNotFoundException */ - public function find($template) { + public function find(string $template): array { if ($template === '') { throw new \InvalidArgumentException('Empty template name'); } @@ -31,14 +33,9 @@ class TemplateFileLocator { foreach ($this->dirs as $dir) { $file = $dir . $template . '.php'; if (is_file($file)) { - $this->path = $dir; - return $file; + return [$dir,$file]; } } - throw new \Exception('template file not found: template:' . $template); - } - - public function getPath() { - return $this->path; + throw new TemplateNotFoundException('template file not found: template:' . $template); } } diff --git a/lib/private/Template/TemplateManager.php b/lib/private/Template/TemplateManager.php new file mode 100644 index 00000000000..34da4deac72 --- /dev/null +++ b/lib/private/Template/TemplateManager.php @@ -0,0 +1,169 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OC\Template; + +use OCP\App\IAppManager; +use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; +use OCP\AppFramework\Http\TemplateResponse; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\IRequest; +use OCP\Server; +use OCP\Template\ITemplate; +use OCP\Template\ITemplateManager; +use OCP\Template\TemplateNotFoundException; +use Psr\Log\LoggerInterface; + +class TemplateManager implements ITemplateManager { + public function __construct( + private IAppManager $appManager, + private IEventDispatcher $eventDispatcher, + ) { + } + + /** + * @param TemplateResponse::RENDER_AS_* $renderAs + * @throws TemplateNotFoundException if the template cannot be found + */ + public function getTemplate(string $app, string $name, string $renderAs = TemplateResponse::RENDER_AS_BLANK, bool $registerCall = true): ITemplate { + return new Template($app, $name, $renderAs, $registerCall); + } + + /** + * Shortcut to print a simple page for guests + * @param string $application The application we render the template for + * @param string $name Name of the template + * @param array $parameters Parameters for the template + */ + public function printGuestPage(string $application, string $name, array $parameters = []): void { + $content = $this->getTemplate($application, $name, $name === 'error' ? $name : 'guest'); + foreach ($parameters as $key => $value) { + $content->assign($key, $value); + } + $content->printPage(); + } + + /** + * Print a fatal error page and terminates the script + * @param string $error_msg The error message to show + * @param string $hint An optional hint message - needs to be properly escape + */ + public function printErrorPage(string $error_msg, string $hint = '', int $statusCode = 500): never { + if ($this->appManager->isEnabledForUser('theming') && !$this->appManager->isAppLoaded('theming')) { + $this->appManager->loadApp('theming'); + } + + if ($error_msg === $hint) { + // If the hint is the same as the message there is no need to display it twice. + $hint = ''; + } + $errors = [['error' => $error_msg, 'hint' => $hint]]; + + http_response_code($statusCode); + try { + // Try rendering themed html error page + $response = new TemplateResponse( + '', + 'error', + ['errors' => $errors], + TemplateResponse::RENDER_AS_ERROR, + $statusCode, + ); + $event = new BeforeTemplateRenderedEvent(false, $response); + $this->eventDispatcher->dispatchTyped($event); + print($response->render()); + } catch (\Throwable $e1) { + $logger = \OCP\Server::get(LoggerInterface::class); + $logger->error('Rendering themed error page failed. Falling back to un-themed error page.', [ + 'app' => 'core', + 'exception' => $e1, + ]); + + try { + // Try rendering unthemed html error page + $content = $this->getTemplate('', 'error', 'error', false); + $content->assign('errors', $errors); + $content->printPage(); + } catch (\Exception $e2) { + // If nothing else works, fall back to plain text error page + $logger->error("$error_msg $hint", ['app' => 'core']); + $logger->error('Rendering un-themed error page failed. Falling back to plain text error page.', [ + 'app' => 'core', + 'exception' => $e2, + ]); + + header('Content-Type: text/plain; charset=utf-8'); + print("$error_msg $hint"); + } + } + die(); + } + + /** + * print error page using Exception details + */ + public function printExceptionErrorPage(\Throwable $exception, int $statusCode = 503): never { + $debug = false; + http_response_code($statusCode); + try { + $debug = (bool)Server::get(\OC\SystemConfig::class)->getValue('debug', false); + $serverLogsDocumentation = Server::get(\OC\SystemConfig::class)->getValue('documentation_url.server_logs', ''); + $request = Server::get(IRequest::class); + $content = $this->getTemplate('', 'exception', 'error', false); + $content->assign('errorClass', get_class($exception)); + $content->assign('errorMsg', $exception->getMessage()); + $content->assign('errorCode', $exception->getCode()); + $content->assign('file', $exception->getFile()); + $content->assign('line', $exception->getLine()); + $content->assign('exception', $exception); + $content->assign('debugMode', $debug); + $content->assign('serverLogsDocumentation', $serverLogsDocumentation); + $content->assign('remoteAddr', $request->getRemoteAddress()); + $content->assign('requestID', $request->getId()); + $content->printPage(); + } catch (\Exception $e) { + try { + $logger = Server::get(LoggerInterface::class); + $logger->error($exception->getMessage(), ['app' => 'core', 'exception' => $exception]); + $logger->error($e->getMessage(), ['app' => 'core', 'exception' => $e]); + } catch (\Throwable $e) { + // no way to log it properly - but to avoid a white page of death we send some output + $this->printPlainErrorPage($e, $debug); + + // and then throw it again to log it at least to the web server error log + throw $e; + } + + $this->printPlainErrorPage($e, $debug); + } + die(); + } + + /** + * @psalm-taint-escape has_quotes + * @psalm-taint-escape html + */ + private function fakeEscapeForPlainText(string $str): string { + return $str; + } + + private function printPlainErrorPage(\Throwable $exception, bool $debug = false): void { + header('Content-Type: text/plain; charset=utf-8'); + print("Internal Server Error\n\n"); + print("The server encountered an internal error and was unable to complete your request.\n"); + print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n"); + print("More details can be found in the server log.\n"); + + if ($debug) { + print("\n"); + print($exception->getMessage() . ' ' . $exception->getFile() . ' at ' . $exception->getLine() . "\n"); + print($this->fakeEscapeForPlainText($exception->getTraceAsString())); + } + } +} diff --git a/lib/private/legacy/template/functions.php b/lib/private/Template/functions.php index 37df801c3c4..402a7491e03 100644 --- a/lib/private/legacy/template/functions.php +++ b/lib/private/Template/functions.php @@ -6,20 +6,26 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +use OC\Security\CSP\ContentSecurityPolicyNonceManager; +use OCP\Files\IMimeTypeDetector; use OCP\IDateTimeFormatter; +use OCP\IURLGenerator; +use OCP\Server; use OCP\Util; -function p($string) { - print(\OCP\Util::sanitizeHTML($string)); +/** + * @param string $string + */ +function p($string): void { + print(Util::sanitizeHTML($string)); } - /** * Prints a <link> tag for loading css * @param string $href the source URL, ignored when empty * @param string $opts, additional optional options */ -function emit_css_tag($href, $opts = '') { +function emit_css_tag($href, $opts = ''): void { $s = '<link rel="stylesheet"'; if (!empty($href)) { $s .= ' href="' . $href . '"'; @@ -34,7 +40,7 @@ function emit_css_tag($href, $opts = '') { * Prints all tags for CSS loading * @param array $obj all the script information from template */ -function emit_css_loading_tags($obj) { +function emit_css_loading_tags($obj): void { foreach ($obj['cssfiles'] as $css) { emit_css_tag($css); } @@ -49,8 +55,8 @@ function emit_css_loading_tags($obj) { * @param string $script_content the inline script content, ignored when empty * @param string $content_type the type of the source (e.g. 'module') */ -function emit_script_tag(string $src, string $script_content = '', string $content_type = '') { - $nonceManager = \OC::$server->get(\OC\Security\CSP\ContentSecurityPolicyNonceManager::class); +function emit_script_tag(string $src, string $script_content = '', string $content_type = ''): void { + $nonceManager = Server::get(ContentSecurityPolicyNonceManager::class); $defer_str = ' defer'; $type = $content_type !== '' ? ' type="' . $content_type . '"' : ''; @@ -74,7 +80,7 @@ function emit_script_tag(string $src, string $script_content = '', string $conte * Print all <script> tags for loading JS * @param array $obj all the script information from template */ -function emit_script_loading_tags($obj) { +function emit_script_loading_tags($obj): void { foreach ($obj['jsfiles'] as $jsfile) { $fileName = explode('?', $jsfile, 2)[0]; $type = str_ends_with($fileName, '.mjs') ? 'module' : ''; @@ -88,9 +94,9 @@ function emit_script_loading_tags($obj) { /** * Prints an unsanitized string - usage of this function may result into XSS. * Consider using p() instead. - * @param string|array $string the string which will be printed as it is + * @param string $string the string which will be printed as it is */ -function print_unescaped($string) { +function print_unescaped($string): void { print($string); } @@ -106,7 +112,7 @@ function print_unescaped($string) { * @param string|string[] $file the filename, * if an array is given it will add all scripts */ -function script($app, $file = null) { +function script($app, $file = null): void { if (is_array($file)) { foreach ($file as $script) { Util::addScript($app, $script, 'core'); @@ -117,34 +123,18 @@ function script($app, $file = null) { } /** - * Shortcut for adding vendor scripts to a page - * @param string $app the appname - * @param string|string[] $file the filename, - * if an array is given it will add all scripts - */ -function vendor_script($app, $file = null) { - if (is_array($file)) { - foreach ($file as $f) { - OC_Util::addVendorScript($app, $f); - } - } else { - OC_Util::addVendorScript($app, $file); - } -} - -/** * Shortcut for adding styles to a page * @param string $app the appname * @param string|string[] $file the filename, * if an array is given it will add all styles */ -function style($app, $file = null) { +function style($app, $file = null): void { if (is_array($file)) { foreach ($file as $f) { - OC_Util::addStyle($app, $f); + Util::addStyle($app, $f); } } else { - OC_Util::addStyle($app, $file); + Util::addStyle($app, $file); } } @@ -153,8 +143,9 @@ function style($app, $file = null) { * @param string $app the appname * @param string|string[] $file the filename, * if an array is given it will add all styles + * @deprecated 32.0.0 */ -function vendor_style($app, $file = null) { +function vendor_style($app, $file = null): void { if (is_array($file)) { foreach ($file as $f) { OC_Util::addVendorStyle($app, $f); @@ -169,26 +160,8 @@ function vendor_style($app, $file = null) { * @param string $app the appname * if an array is given it will add all styles */ -function translation($app) { - OC_Util::addTranslations($app); -} - -/** - * Shortcut for HTML imports - * @param string $app the appname - * @param string|string[] $file the path relative to the app's component folder, - * if an array is given it will add all components - */ -function component($app, $file) { - if (is_array($file)) { - foreach ($file as $f) { - $url = link_to($app, 'component/' . $f . '.html'); - OC_Util::addHeader('link', ['rel' => 'import', 'href' => $url]); - } - } else { - $url = link_to($app, 'component/' . $file . '.html'); - OC_Util::addHeader('link', ['rel' => 'import', 'href' => $url]); - } +function translation($app): void { + Util::addTranslations($app); } /** @@ -201,15 +174,15 @@ function component($app, $file) { * For further information have a look at \OCP\IURLGenerator::linkTo */ function link_to($app, $file, $args = []) { - return \OC::$server->getURLGenerator()->linkTo($app, $file, $args); + return Server::get(IURLGenerator::class)->linkTo($app, $file, $args); } /** - * @param $key + * @param string $key * @return string url to the online documentation */ function link_to_docs($key) { - return \OC::$server->getURLGenerator()->linkToDocs($key); + return Server::get(IURLGenerator::class)->linkToDocs($key); } /** @@ -221,16 +194,16 @@ function link_to_docs($key) { * For further information have a look at \OCP\IURLGenerator::imagePath */ function image_path($app, $image) { - return \OC::$server->getURLGenerator()->imagePath($app, $image); + return Server::get(IURLGenerator::class)->imagePath($app, $image); } /** - * make OC_Helper::mimetypeIcon available as a simple function + * make mimetypeIcon available as a simple function * @param string $mimetype mimetype * @return string link to the image */ function mimetype_icon($mimetype) { - return \OC::$server->getMimeTypeDetector()->mimeTypeIcon($mimetype); + return Server::get(IMimeTypeDetector::class)->mimeTypeIcon($mimetype); } /** @@ -240,7 +213,7 @@ function mimetype_icon($mimetype) { * @return string link to the preview */ function preview_icon($path) { - return \OC::$server->getURLGenerator()->linkToRoute('core.Preview.getPreview', ['x' => 32, 'y' => 32, 'file' => $path]); + return Server::get(IURLGenerator::class)->linkToRoute('core.Preview.getPreview', ['x' => 32, 'y' => 32, 'file' => $path]); } /** @@ -249,18 +222,19 @@ function preview_icon($path) { * @return string */ function publicPreview_icon($path, $token) { - return \OC::$server->getURLGenerator()->linkToRoute('files_sharing.PublicPreview.getPreview', ['x' => 32, 'y' => 32, 'file' => $path, 'token' => $token]); + return Server::get(IURLGenerator::class)->linkToRoute('files_sharing.PublicPreview.getPreview', ['x' => 32, 'y' => 32, 'file' => $path, 'token' => $token]); } /** - * make OC_Helper::humanFileSize available as a simple function + * make Util::humanFileSize available as a simple function * @param int $bytes size in bytes * @return string size as string + * @deprecated use Util::humanFileSize instead * - * For further information have a look at OC_Helper::humanFileSize + * For further information have a look at Util::humanFileSize */ function human_file_size($bytes) { - return OC_Helper::humanFileSize($bytes); + return Util::humanFileSize($bytes); } /** @@ -283,7 +257,7 @@ function strip_time($timestamp) { * @return string timestamp */ function relative_modified_date($timestamp, $fromTime = null, $dateOnly = false): string { - $formatter = \OCP\Server::get(IDateTimeFormatter::class); + $formatter = Server::get(IDateTimeFormatter::class); if ($dateOnly) { return $formatter->formatDateSpan($timestamp, $fromTime); @@ -291,7 +265,12 @@ function relative_modified_date($timestamp, $fromTime = null, $dateOnly = false) return $formatter->formatTimeSpan($timestamp, $fromTime); } -function html_select_options($options, $selected, $params = []) { +/** + * @param array $options + * @param string[]|string $selected + * @param array $params + */ +function html_select_options($options, $selected, $params = []): string { if (!is_array($selected)) { $selected = [$selected]; } @@ -314,7 +293,7 @@ function html_select_options($options, $selected, $params = []) { $label = $label[$label_name]; } $select = in_array($value, $selected) ? ' selected="selected"' : ''; - $html .= '<option value="' . \OCP\Util::sanitizeHTML($value) . '"' . $select . '>' . \OCP\Util::sanitizeHTML($label) . '</option>' . "\n"; + $html .= '<option value="' . Util::sanitizeHTML($value) . '"' . $select . '>' . Util::sanitizeHTML($label) . '</option>' . "\n"; } return $html; } diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php index 2bc9ff5a2af..cfc387d2164 100644 --- a/lib/private/TemplateLayout.php +++ b/lib/private/TemplateLayout.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -25,36 +27,32 @@ use OCP\IRequest; use OCP\IURLGenerator; use OCP\IUserSession; use OCP\L10N\IFactory; +use OCP\Server; use OCP\ServerVersion; use OCP\Support\Subscription\IRegistry; +use OCP\Template\ITemplate; +use OCP\Template\ITemplateManager; use OCP\Util; -class TemplateLayout extends \OC_Template { - private static $versionHash = ''; +class TemplateLayout { + private static string $versionHash = ''; /** @var string[] */ - private static $cacheBusterCache = []; - - /** @var CSSResourceLocator|null */ - public static $cssLocator = null; - - /** @var JSResourceLocator|null */ - public static $jsLocator = null; - - private IConfig $config; - private IAppManager $appManager; - private InitialStateService $initialState; - private INavigationManager $navigationManager; - - /** - * @param string $renderAs - * @param string $appId application id - */ - public function __construct($renderAs, $appId = '') { - $this->config = \OCP\Server::get(IConfig::class); - $this->appManager = \OCP\Server::get(IAppManager::class); - $this->initialState = \OCP\Server::get(InitialStateService::class); - $this->navigationManager = \OCP\Server::get(INavigationManager::class); + private static array $cacheBusterCache = []; + + public static ?CSSResourceLocator $cssLocator = null; + public static ?JSResourceLocator $jsLocator = null; + + public function __construct( + private IConfig $config, + private IAppManager $appManager, + private InitialStateService $initialState, + private INavigationManager $navigationManager, + private ITemplateManager $templateManager, + private ServerVersion $serverVersion, + ) { + } + public function getPageTemplate(string $renderAs, string $appId): ITemplate { // Add fallback theming variables if not rendered as user if ($renderAs !== TemplateResponse::RENDER_AS_USER) { // TODO cache generated default theme if enabled for fallback if server is erroring ? @@ -62,143 +60,149 @@ class TemplateLayout extends \OC_Template { } // Decide which page we show - if ($renderAs === TemplateResponse::RENDER_AS_USER) { - parent::__construct('core', 'layout.user'); - if (in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) { - $this->assign('bodyid', 'body-settings'); - } else { - $this->assign('bodyid', 'body-user'); - } - - $this->initialState->provideInitialState('core', 'active-app', $this->navigationManager->getActiveEntry()); - $this->initialState->provideInitialState('core', 'apps', array_values($this->navigationManager->getAll())); + switch ($renderAs) { + case TemplateResponse::RENDER_AS_USER: + $page = $this->templateManager->getTemplate('core', 'layout.user'); + if (in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) { + $page->assign('bodyid', 'body-settings'); + } else { + $page->assign('bodyid', 'body-user'); + } - if ($this->config->getSystemValueBool('unified_search.enabled', false) || !$this->config->getSystemValueBool('enable_non-accessible_features', true)) { - $this->initialState->provideInitialState('unified-search', 'limit-default', (int)$this->config->getAppValue('core', 'unified-search.limit-default', (string)SearchQuery::LIMIT_DEFAULT)); - $this->initialState->provideInitialState('unified-search', 'min-search-length', (int)$this->config->getAppValue('core', 'unified-search.min-search-length', (string)1)); - $this->initialState->provideInitialState('unified-search', 'live-search', $this->config->getAppValue('core', 'unified-search.live-search', 'yes') === 'yes'); - Util::addScript('core', 'legacy-unified-search', 'core'); - } else { - Util::addScript('core', 'unified-search', 'core'); - } - // Set body data-theme - $this->assign('enabledThemes', []); - if ($this->appManager->isEnabledForUser('theming') && class_exists('\OCA\Theming\Service\ThemesService')) { - /** @var \OCA\Theming\Service\ThemesService */ - $themesService = \OC::$server->get(\OCA\Theming\Service\ThemesService::class); - $this->assign('enabledThemes', $themesService->getEnabledThemes()); - } + $this->initialState->provideInitialState('core', 'active-app', $this->navigationManager->getActiveEntry()); + $this->initialState->provideInitialState('core', 'apps', array_values($this->navigationManager->getAll())); - // Set logo link target - $logoUrl = $this->config->getSystemValueString('logo_url', ''); - $this->assign('logoUrl', $logoUrl); + if ($this->config->getSystemValueBool('unified_search.enabled', false) || !$this->config->getSystemValueBool('enable_non-accessible_features', true)) { + $this->initialState->provideInitialState('unified-search', 'limit-default', (int)$this->config->getAppValue('core', 'unified-search.limit-default', (string)SearchQuery::LIMIT_DEFAULT)); + $this->initialState->provideInitialState('unified-search', 'min-search-length', (int)$this->config->getAppValue('core', 'unified-search.min-search-length', (string)1)); + $this->initialState->provideInitialState('unified-search', 'live-search', $this->config->getAppValue('core', 'unified-search.live-search', 'yes') === 'yes'); + Util::addScript('core', 'legacy-unified-search', 'core'); + } else { + Util::addScript('core', 'unified-search', 'core'); + } - // Set default entry name - $defaultEntryId = $this->navigationManager->getDefaultEntryIdForUser(); - $defaultEntry = $this->navigationManager->get($defaultEntryId); - $this->assign('defaultAppName', $defaultEntry['name']); + // Set logo link target + $logoUrl = $this->config->getSystemValueString('logo_url', ''); + $page->assign('logoUrl', $logoUrl); + + // Set default entry name + $defaultEntryId = $this->navigationManager->getDefaultEntryIdForUser(); + $defaultEntry = $this->navigationManager->get($defaultEntryId); + $page->assign('defaultAppName', $defaultEntry['name'] ?? ''); + + // Add navigation entry + $page->assign('application', ''); + $page->assign('appid', $appId); + + $navigation = $this->navigationManager->getAll(); + $page->assign('navigation', $navigation); + $settingsNavigation = $this->navigationManager->getAll('settings'); + $this->initialState->provideInitialState('core', 'settingsNavEntries', $settingsNavigation); + + foreach ($navigation as $entry) { + if ($entry['active']) { + $page->assign('application', $entry['name']); + break; + } + } - // Add navigation entry - $this->assign('application', ''); - $this->assign('appid', $appId); + foreach ($settingsNavigation as $entry) { + if ($entry['active']) { + $page->assign('application', $entry['name']); + break; + } + } - $navigation = $this->navigationManager->getAll(); - $this->assign('navigation', $navigation); - $settingsNavigation = $this->navigationManager->getAll('settings'); - $this->initialState->provideInitialState('core', 'settingsNavEntries', $settingsNavigation); + $user = Server::get(IUserSession::class)->getUser(); - foreach ($navigation as $entry) { - if ($entry['active']) { - $this->assign('application', $entry['name']); - break; + if ($user === null) { + $page->assign('user_uid', false); + $page->assign('user_displayname', false); + $page->assign('userAvatarSet', false); + $page->assign('userStatus', false); + } else { + $page->assign('user_uid', $user->getUID()); + $page->assign('user_displayname', $user->getDisplayName()); + $page->assign('userAvatarSet', true); + $page->assign('userAvatarVersion', $this->config->getUserValue($user->getUID(), 'avatar', 'version', 0)); } - } - - foreach ($settingsNavigation as $entry) { - if ($entry['active']) { - $this->assign('application', $entry['name']); - break; + break; + case TemplateResponse::RENDER_AS_ERROR: + $page = $this->templateManager->getTemplate('core', 'layout.guest', '', false); + $page->assign('bodyid', 'body-login'); + $page->assign('user_displayname', ''); + $page->assign('user_uid', ''); + break; + case TemplateResponse::RENDER_AS_GUEST: + $page = $this->templateManager->getTemplate('core', 'layout.guest'); + Util::addStyle('guest'); + $page->assign('bodyid', 'body-login'); + + $userDisplayName = false; + $user = Server::get(IUserSession::class)->getUser(); + if ($user) { + $userDisplayName = $user->getDisplayName(); } - } - $userDisplayName = false; - $user = \OC::$server->get(IUserSession::class)->getUser(); - if ($user) { - $userDisplayName = $user->getDisplayName(); - } - $this->assign('user_displayname', $userDisplayName); - $this->assign('user_uid', \OC_User::getUser()); - - if ($user === null) { - $this->assign('userAvatarSet', false); - $this->assign('userStatus', false); - } else { - $this->assign('userAvatarSet', true); - $this->assign('userAvatarVersion', $this->config->getUserValue(\OC_User::getUser(), 'avatar', 'version', 0)); - } - } elseif ($renderAs === TemplateResponse::RENDER_AS_ERROR) { - parent::__construct('core', 'layout.guest', '', false); - $this->assign('bodyid', 'body-login'); - $this->assign('user_displayname', ''); - $this->assign('user_uid', ''); - } elseif ($renderAs === TemplateResponse::RENDER_AS_GUEST) { - parent::__construct('core', 'layout.guest'); - \OC_Util::addStyle('guest'); - $this->assign('bodyid', 'body-login'); - - $userDisplayName = false; - $user = \OC::$server->get(IUserSession::class)->getUser(); - if ($user) { - $userDisplayName = $user->getDisplayName(); - } - $this->assign('user_displayname', $userDisplayName); - $this->assign('user_uid', \OC_User::getUser()); - } elseif ($renderAs === TemplateResponse::RENDER_AS_PUBLIC) { - parent::__construct('core', 'layout.public'); - $this->assign('appid', $appId); - $this->assign('bodyid', 'body-public'); - - // Set logo link target - $logoUrl = $this->config->getSystemValueString('logo_url', ''); - $this->assign('logoUrl', $logoUrl); - - /** @var IRegistry $subscription */ - $subscription = \OCP\Server::get(IRegistry::class); - $showSimpleSignup = $this->config->getSystemValueBool('simpleSignUpLink.shown', true); - if ($showSimpleSignup && $subscription->delegateHasValidSubscription()) { - $showSimpleSignup = false; - } + $page->assign('user_displayname', $userDisplayName); + $page->assign('user_uid', \OC_User::getUser()); + break; + case TemplateResponse::RENDER_AS_PUBLIC: + $page = $this->templateManager->getTemplate('core', 'layout.public'); + $page->assign('appid', $appId); + $page->assign('bodyid', 'body-public'); + + // Set logo link target + $logoUrl = $this->config->getSystemValueString('logo_url', ''); + $page->assign('logoUrl', $logoUrl); + + $subscription = Server::get(IRegistry::class); + $showSimpleSignup = $this->config->getSystemValueBool('simpleSignUpLink.shown', true); + if ($showSimpleSignup && $subscription->delegateHasValidSubscription()) { + $showSimpleSignup = false; + } - $defaultSignUpLink = 'https://nextcloud.com/signup/'; - $signUpLink = $this->config->getSystemValueString('registration_link', $defaultSignUpLink); - if ($signUpLink !== $defaultSignUpLink) { - $showSimpleSignup = true; - } + $defaultSignUpLink = 'https://nextcloud.com/signup/'; + $signUpLink = $this->config->getSystemValueString('registration_link', $defaultSignUpLink); + if ($signUpLink !== $defaultSignUpLink) { + $showSimpleSignup = true; + } - if ($this->appManager->isEnabledForUser('registration')) { - $urlGenerator = \OCP\Server::get(IURLGenerator::class); - $signUpLink = $urlGenerator->getAbsoluteURL('/index.php/apps/registration/'); - } + if ($this->appManager->isEnabledForUser('registration')) { + $urlGenerator = Server::get(IURLGenerator::class); + $signUpLink = $urlGenerator->getAbsoluteURL('/index.php/apps/registration/'); + } - $this->assign('showSimpleSignUpLink', $showSimpleSignup); - $this->assign('signUpLink', $signUpLink); - } else { - parent::__construct('core', 'layout.base'); + $page->assign('showSimpleSignUpLink', $showSimpleSignup); + $page->assign('signUpLink', $signUpLink); + break; + default: + $page = $this->templateManager->getTemplate('core', 'layout.base'); + break; } // Send the language, locale, and direction to our layouts - $lang = \OC::$server->get(IFactory::class)->findLanguage(); - $locale = \OC::$server->get(IFactory::class)->findLocale($lang); - $direction = \OC::$server->getL10NFactory()->getLanguageDirection($lang); + $l10nFactory = Server::get(IFactory::class); + $lang = $l10nFactory->findLanguage(); + $locale = $l10nFactory->findLocale($lang); + $direction = $l10nFactory->getLanguageDirection($lang); $lang = str_replace('_', '-', $lang); - $this->assign('language', $lang); - $this->assign('locale', $locale); - $this->assign('direction', $direction); + $page->assign('language', $lang); + $page->assign('locale', $locale); + $page->assign('direction', $direction); + + // Set body data-theme + try { + $themesService = Server::get(\OCA\Theming\Service\ThemesService::class); + } catch (\Exception) { + $themesService = null; + } + $page->assign('enabledThemes', $themesService?->getEnabledThemes() ?? []); if ($this->config->getSystemValueBool('installed', false)) { if (empty(self::$versionHash)) { - $v = \OC_App::getAppVersions(); - $v['core'] = implode('.', \OCP\Util::getVersion()); + $v = $this->appManager->getAppInstalledVersions(true); + $v['core'] = implode('.', $this->serverVersion->getVersion()); self::$versionHash = substr(md5(implode(',', $v)), 0, 8); } } else { @@ -206,14 +210,13 @@ class TemplateLayout extends \OC_Template { } // Add the js files - // TODO: remove deprecated OC_Util injection - $jsFiles = self::findJavascriptFiles(array_merge(\OC_Util::$scripts, Util::getScripts())); - $this->assign('jsfiles', []); + $jsFiles = self::findJavascriptFiles(Util::getScripts()); + $page->assign('jsfiles', []); if ($this->config->getSystemValueBool('installed', false) && $renderAs != TemplateResponse::RENDER_AS_ERROR) { // this is on purpose outside of the if statement below so that the initial state is prefilled (done in the getConfig() call) // see https://github.com/nextcloud/server/pull/22636 for details $jsConfigHelper = new JSConfigHelper( - \OCP\Server::get(ServerVersion::class), + $this->serverVersion, \OCP\Util::getL10N('lib'), \OCP\Server::get(Defaults::class), $this->appManager, @@ -230,26 +233,28 @@ class TemplateLayout extends \OC_Template { ); $config = $jsConfigHelper->getConfig(); if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) { - $this->assign('inline_ocjs', $config); + $page->assign('inline_ocjs', $config); } else { - $this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash])); + $page->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash])); } } foreach ($jsFiles as $info) { $web = $info[1]; $file = $info[2]; - $this->append('jsfiles', $web . '/' . $file . $this->getVersionHashSuffix()); + $page->append('jsfiles', $web . '/' . $file . $this->getVersionHashSuffix()); } + $request = \OCP\Server::get(IRequest::class); + try { - $pathInfo = \OC::$server->getRequest()->getPathInfo(); + $pathInfo = $request->getPathInfo(); } catch (\Exception $e) { $pathInfo = ''; } // Do not initialise scss appdata until we have a fully installed instance // Do not load scss for update, errors, installation or login page - if (\OC::$server->getSystemConfig()->getValue('installed', false) + if ($this->config->getSystemValueBool('installed', false) && !\OCP\Util::needUpgrade() && $pathInfo !== '' && !preg_match('/^\/login/', $pathInfo) @@ -259,49 +264,45 @@ class TemplateLayout extends \OC_Template { } else { // If we ignore the scss compiler, // we need to load the guest css fallback - \OC_Util::addStyle('guest'); - $cssFiles = self::findStylesheetFiles(\OC_Util::$styles, false); + Util::addStyle('guest'); + $cssFiles = self::findStylesheetFiles(\OC_Util::$styles); } - $this->assign('cssfiles', []); - $this->assign('printcssfiles', []); + $page->assign('cssfiles', []); + $page->assign('printcssfiles', []); $this->initialState->provideInitialState('core', 'versionHash', self::$versionHash); foreach ($cssFiles as $info) { $web = $info[1]; $file = $info[2]; if (str_ends_with($file, 'print.css')) { - $this->append('printcssfiles', $web . '/' . $file . $this->getVersionHashSuffix()); + $page->append('printcssfiles', $web . '/' . $file . $this->getVersionHashSuffix()); } else { $suffix = $this->getVersionHashSuffix($web, $file); if (!str_contains($file, '?v=')) { - $this->append('cssfiles', $web . '/' . $file . $suffix); + $page->append('cssfiles', $web . '/' . $file . $suffix); } else { - $this->append('cssfiles', $web . '/' . $file . '-' . substr($suffix, 3)); + $page->append('cssfiles', $web . '/' . $file . '-' . substr($suffix, 3)); } } } - $request = \OCP\Server::get(IRequest::class); if ($request->isUserAgent([Request::USER_AGENT_CLIENT_IOS, Request::USER_AGENT_SAFARI, Request::USER_AGENT_SAFARI_MOBILE])) { // Prevent auto zoom with iOS but still allow user zoom // On chrome (and others) this does not work (will also disable user zoom) - $this->assign('viewport_maximum_scale', '1.0'); + $page->assign('viewport_maximum_scale', '1.0'); } - $this->assign('initialStates', $this->initialState->getInitialStates()); + $page->assign('initialStates', $this->initialState->getInitialStates()); + + $page->assign('id-app-content', $renderAs === TemplateResponse::RENDER_AS_USER ? '#app-content' : '#content'); + $page->assign('id-app-navigation', $renderAs === TemplateResponse::RENDER_AS_USER ? '#app-navigation' : null); - $this->assign('id-app-content', $renderAs === TemplateResponse::RENDER_AS_USER ? '#app-content' : '#content'); - $this->assign('id-app-navigation', $renderAs === TemplateResponse::RENDER_AS_USER ? '#app-navigation' : null); + return $page; } - /** - * @param string $path - * @param string $file - * @return string - */ - protected function getVersionHashSuffix($path = false, $file = false) { + protected function getVersionHashSuffix(string $path = '', string $file = ''): string { if ($this->config->getSystemValueBool('debug', false)) { // allows chrome workspace mapping in debug mode return ''; @@ -314,11 +315,11 @@ class TemplateLayout extends \OC_Template { $hash = false; // Try the web-root first - if (is_string($path) && $path !== '') { + if ($path !== '') { $hash = $this->getVersionHashByPath($path); } // If not found try the file - if ($hash === false && is_string($file) && $file !== '') { + if ($hash === false && $file !== '') { $hash = $this->getVersionHashByPath($file); } // As a last resort we use the server version hash @@ -336,29 +337,30 @@ class TemplateLayout extends \OC_Template { if (array_key_exists($path, self::$cacheBusterCache) === false) { // Not yet cached, so lets find the cache buster string $appId = $this->getAppNamefromPath($path); - if ($appId === false || $appId === null) { + if ($appId === false) { // No app Id could be guessed return false; } - $appVersion = $this->appManager->getAppVersion($appId); - // For shipped apps the app version is not a single source of truth, we rather also need to consider the Nextcloud version - if ($this->appManager->isShipped($appId)) { - $appVersion .= '-' . self::$versionHash; - } + if ($appId === 'core') { + // core is not a real app but the server itself + $hash = self::$versionHash; + } else { + $appVersion = $this->appManager->getAppVersion($appId); + // For shipped apps the app version is not a single source of truth, we rather also need to consider the Nextcloud version + if ($this->appManager->isShipped($appId)) { + $appVersion .= '-' . self::$versionHash; + } - $hash = substr(md5($appVersion), 0, 8); + $hash = substr(md5($appVersion), 0, 8); + } self::$cacheBusterCache[$path] = $hash; } return self::$cacheBusterCache[$path]; } - /** - * @param array $styles - * @return array - */ - public static function findStylesheetFiles($styles, $compileScss = true) { + public static function findStylesheetFiles(array $styles): array { if (!self::$cssLocator) { self::$cssLocator = \OCP\Server::get(CSSResourceLocator::class); } @@ -366,27 +368,21 @@ class TemplateLayout extends \OC_Template { return self::$cssLocator->getResources(); } - /** - * @param string $path - * @return string|boolean - */ - public function getAppNamefromPath($path) { - if ($path !== '' && is_string($path)) { + public function getAppNamefromPath(string $path): string|false { + if ($path !== '') { $pathParts = explode('/', $path); if ($pathParts[0] === 'css') { // This is a scss request return $pathParts[1]; + } elseif ($pathParts[0] === 'core') { + return 'core'; } return end($pathParts); } return false; } - /** - * @param array $scripts - * @return array - */ - public static function findJavascriptFiles($scripts) { + public static function findJavascriptFiles(array $scripts): array { if (!self::$jsLocator) { self::$jsLocator = \OCP\Server::get(JSResourceLocator::class); } @@ -400,7 +396,7 @@ class TemplateLayout extends \OC_Template { * @return string Relative path * @throws \Exception If $filePath is not under \OC::$SERVERROOT */ - public static function convertToRelativePath($filePath) { + public static function convertToRelativePath(string $filePath) { $relativePath = explode(\OC::$SERVERROOT, $filePath); if (count($relativePath) !== 2) { throw new \Exception('$filePath is not under the \OC::$SERVERROOT'); diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php index ad12fae5144..1a2978b84d7 100644 --- a/lib/private/URLGenerator.php +++ b/lib/private/URLGenerator.php @@ -189,14 +189,14 @@ class URLGenerator implements IURLGenerator { $basename = substr(basename($file), 0, -4); try { - $appPath = $this->getAppManager()->getAppPath($appName); - } catch (AppPathNotFoundException $e) { if ($appName === 'core' || $appName === '') { $appName = 'core'; $appPath = false; } else { - throw new RuntimeException('image not found: image: ' . $file . ' webroot: ' . \OC::$WEBROOT . ' serverroot: ' . \OC::$SERVERROOT); + $appPath = $this->getAppManager()->getAppPath($appName); } + } catch (AppPathNotFoundException $e) { + throw new RuntimeException('image not found: image: ' . $file . ' webroot: ' . \OC::$WEBROOT . ' serverroot: ' . \OC::$SERVERROOT); } // Check if the app is in the app folder @@ -304,6 +304,11 @@ class URLGenerator implements IURLGenerator { if ($href === '') { throw new \InvalidArgumentException('Default navigation entry is missing href: ' . $entryId); } + + if (str_starts_with($href, $this->getBaseUrl())) { + return $href; + } + if (str_starts_with($href, '/index.php/') && ($this->config->getSystemValueBool('htaccess.IgnoreFrontController', false) || getenv('front_controller_active') === 'true')) { $href = substr($href, 10); } diff --git a/lib/private/Updater.php b/lib/private/Updater.php index c4631f2c7d3..6495bad2da2 100644 --- a/lib/private/Updater.php +++ b/lib/private/Updater.php @@ -167,8 +167,8 @@ class Updater extends BasicEmitter { // Vendor was not set correctly on install, so we have to white-list known versions if ($currentVendor === '' && ( - isset($allowedPreviousVersions['owncloud'][$oldVersion]) || - isset($allowedPreviousVersions['owncloud'][$majorMinor]) + isset($allowedPreviousVersions['owncloud'][$oldVersion]) + || isset($allowedPreviousVersions['owncloud'][$majorMinor]) )) { $currentVendor = 'owncloud'; $this->config->setAppValue('core', 'vendor', $currentVendor); @@ -176,13 +176,13 @@ class Updater extends BasicEmitter { if ($currentVendor === 'nextcloud') { return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) - && (version_compare($oldVersion, $newVersion, '<=') || - $this->config->getSystemValueBool('debug', false)); + && (version_compare($oldVersion, $newVersion, '<=') + || $this->config->getSystemValueBool('debug', false)); } // Check if the instance can be migrated - return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) || - isset($allowedPreviousVersions[$currentVendor][$oldVersion]); + return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) + || isset($allowedPreviousVersions[$currentVendor][$oldVersion]); } /** @@ -242,7 +242,7 @@ class Updater extends BasicEmitter { $appManager = \OC::$server->getAppManager(); // upgrade appstore apps - $this->upgradeAppStoreApps($appManager->getInstalledApps()); + $this->upgradeAppStoreApps($appManager->getEnabledApps()); $autoDisabledApps = $appManager->getAutoDisabledApps(); if (!empty($autoDisabledApps)) { $this->upgradeAppStoreApps(array_keys($autoDisabledApps), $autoDisabledApps); diff --git a/lib/private/Updater/VersionCheck.php b/lib/private/Updater/VersionCheck.php index 53bfc0d5d5f..be410b06c3e 100644 --- a/lib/private/Updater/VersionCheck.php +++ b/lib/private/Updater/VersionCheck.php @@ -105,17 +105,20 @@ class VersionCheck { } /** - * @codeCoverageIgnore - * @param string $url - * @return resource|string * @throws \Exception */ - protected function getUrlContent($url) { - $client = $this->clientService->newClient(); - $response = $client->get($url, [ + protected function getUrlContent(string $url): string { + $response = $this->clientService->newClient()->get($url, [ 'timeout' => 5, ]); - return $response->getBody(); + + $content = $response->getBody(); + + // IResponse.getBody responds with null|resource if returning a stream response was requested. + // As that's not the case here, we can just ignore the psalm warning by adding an assertion. + assert(is_string($content)); + + return $content; } private function computeCategory(): int { diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php index d2ec835a25d..31488247939 100644 --- a/lib/private/User/Database.php +++ b/lib/private/User/Database.php @@ -12,16 +12,18 @@ use InvalidArgumentException; use OCP\AppFramework\Db\TTransactional; use OCP\Cache\CappedMemoryCache; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IConfig; use OCP\IDBConnection; +use OCP\IUserManager; use OCP\Security\Events\ValidatePasswordPolicyEvent; use OCP\Security\IHasher; use OCP\User\Backend\ABackend; use OCP\User\Backend\ICheckPasswordBackend; -use OCP\User\Backend\ICountUsersBackend; use OCP\User\Backend\ICreateUserBackend; use OCP\User\Backend\IGetDisplayNameBackend; use OCP\User\Backend\IGetHomeBackend; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\ILimitAwareCountUsersBackend; use OCP\User\Backend\IPasswordHashBackend; use OCP\User\Backend\ISearchKnownUsersBackend; use OCP\User\Backend\ISetDisplayNameBackend; @@ -37,21 +39,16 @@ class Database extends ABackend implements IGetDisplayNameBackend, ICheckPasswordBackend, IGetHomeBackend, - ICountUsersBackend, + ILimitAwareCountUsersBackend, ISearchKnownUsersBackend, IGetRealUIDBackend, IPasswordHashBackend { - /** @var CappedMemoryCache */ - private $cache; - /** @var IEventDispatcher */ - private $eventDispatcher; - - /** @var IDBConnection */ - private $dbConn; - - /** @var string */ - private $table; + private CappedMemoryCache $cache; + private IConfig $config; + private ?IDBConnection $dbConnection; + private IEventDispatcher $eventDispatcher; + private string $table; use TTransactional; @@ -65,15 +62,18 @@ class Database extends ABackend implements $this->cache = new CappedMemoryCache(); $this->table = $table; $this->eventDispatcher = $eventDispatcher ?? \OCP\Server::get(IEventDispatcher::class); + $this->config = \OCP\Server::get(IConfig::class); + $this->dbConnection = null; } /** * FIXME: This function should not be required! */ - private function fixDI() { - if ($this->dbConn === null) { - $this->dbConn = \OC::$server->getDatabaseConnection(); + private function getDbConnection() { + if ($this->dbConnection === null) { + $this->dbConnection = \OCP\Server::get(IDBConnection::class); } + return $this->dbConnection; } /** @@ -87,52 +87,54 @@ class Database extends ABackend implements * itself, not in its subclasses. */ public function createUser(string $uid, string $password): bool { - $this->fixDI(); - - if (!$this->userExists($uid)) { - $this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); - - return $this->atomic(function () use ($uid, $password) { - $qb = $this->dbConn->getQueryBuilder(); - $qb->insert($this->table) - ->values([ - 'uid' => $qb->createNamedParameter($uid), - 'password' => $qb->createNamedParameter(\OCP\Server::get(IHasher::class)->hash($password)), - 'uid_lower' => $qb->createNamedParameter(mb_strtolower($uid)), - ]); - - $result = $qb->executeStatement(); - - // Clear cache - unset($this->cache[$uid]); - // Repopulate the cache - $this->loadUser($uid); - - return (bool)$result; - }, $this->dbConn); + if ($this->userExists($uid)) { + return false; } - return false; + $this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); + + $dbConn = $this->getDbConnection(); + return $this->atomic(function () use ($uid, $password, $dbConn) { + $qb = $dbConn->getQueryBuilder(); + $qb->insert($this->table) + ->values([ + 'uid' => $qb->createNamedParameter($uid), + 'password' => $qb->createNamedParameter(\OCP\Server::get(IHasher::class)->hash($password)), + 'uid_lower' => $qb->createNamedParameter(mb_strtolower($uid)), + ]); + + $result = $qb->executeStatement(); + + // Clear cache + unset($this->cache[$uid]); + // Repopulate the cache + $this->loadUser($uid); + + return (bool)$result; + }, $dbConn); } /** - * delete a user + * Deletes a user * * @param string $uid The username of the user to delete * @return bool - * - * Deletes a user */ public function deleteUser($uid) { - $this->fixDI(); - // Delete user-group-relation - $query = $this->dbConn->getQueryBuilder(); + $dbConn = $this->getDbConnection(); + $query = $dbConn->getQueryBuilder(); $query->delete($this->table) ->where($query->expr()->eq('uid_lower', $query->createNamedParameter(mb_strtolower($uid)))); $result = $query->executeStatement(); if (isset($this->cache[$uid])) { + // If the user logged in through email there is a second cache entry, also unset that. + $email = $this->cache[$uid]['email'] ?? null; + if ($email !== null) { + unset($this->cache[$email]); + } + // Unset the cache entry unset($this->cache[$uid]); } @@ -140,7 +142,8 @@ class Database extends ABackend implements } private function updatePassword(string $uid, string $passwordHash): bool { - $query = $this->dbConn->getQueryBuilder(); + $dbConn = $this->getDbConnection(); + $query = $dbConn->getQueryBuilder(); $query->update($this->table) ->set('password', $query->createNamedParameter($passwordHash)) ->where($query->expr()->eq('uid_lower', $query->createNamedParameter(mb_strtolower($uid)))); @@ -159,35 +162,34 @@ class Database extends ABackend implements * Change the password of a user */ public function setPassword(string $uid, string $password): bool { - $this->fixDI(); - - if ($this->userExists($uid)) { - $this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); + if (!$this->userExists($uid)) { + return false; + } - $hasher = \OCP\Server::get(IHasher::class); - $hashedPassword = $hasher->hash($password); + $this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); - $return = $this->updatePassword($uid, $hashedPassword); + $hasher = \OCP\Server::get(IHasher::class); + $hashedPassword = $hasher->hash($password); - if ($return) { - $this->cache[$uid]['password'] = $hashedPassword; - } + $return = $this->updatePassword($uid, $hashedPassword); - return $return; + if ($return) { + $this->cache[$uid]['password'] = $hashedPassword; } - return false; + return $return; } public function getPasswordHash(string $userId): ?string { - $this->fixDI(); if (!$this->userExists($userId)) { return null; } if (!empty($this->cache[$userId]['password'])) { return $this->cache[$userId]['password']; } - $qb = $this->dbConn->getQueryBuilder(); + + $dbConn = $this->getDbConnection(); + $qb = $dbConn->getQueryBuilder(); $qb->select('password') ->from($this->table) ->where($qb->expr()->eq('uid_lower', $qb->createNamedParameter(mb_strtolower($userId)))); @@ -196,6 +198,7 @@ class Database extends ABackend implements if ($hash === false) { return null; } + $this->cache[$userId]['password'] = $hash; return $hash; } @@ -204,11 +207,12 @@ class Database extends ABackend implements if (!\OCP\Server::get(IHasher::class)->validate($passwordHash)) { throw new InvalidArgumentException(); } - $this->fixDI(); + $result = $this->updatePassword($userId, $passwordHash); if (!$result) { return false; } + $this->cache[$userId]['password'] = $passwordHash; return true; } @@ -229,21 +233,20 @@ class Database extends ABackend implements throw new \InvalidArgumentException('Invalid displayname'); } - $this->fixDI(); - - if ($this->userExists($uid)) { - $query = $this->dbConn->getQueryBuilder(); - $query->update($this->table) - ->set('displayname', $query->createNamedParameter($displayName)) - ->where($query->expr()->eq('uid_lower', $query->createNamedParameter(mb_strtolower($uid)))); - $query->executeStatement(); + if (!$this->userExists($uid)) { + return false; + } - $this->cache[$uid]['displayname'] = $displayName; + $dbConn = $this->getDbConnection(); + $query = $dbConn->getQueryBuilder(); + $query->update($this->table) + ->set('displayname', $query->createNamedParameter($displayName)) + ->where($query->expr()->eq('uid_lower', $query->createNamedParameter(mb_strtolower($uid)))); + $query->executeStatement(); - return true; - } + $this->cache[$uid]['displayname'] = $displayName; - return false; + return true; } /** @@ -269,9 +272,8 @@ class Database extends ABackend implements public function getDisplayNames($search = '', $limit = null, $offset = null) { $limit = $this->fixLimit($limit); - $this->fixDI(); - - $query = $this->dbConn->getQueryBuilder(); + $dbConn = $this->getDbConnection(); + $query = $dbConn->getQueryBuilder(); $query->select('uid', 'displayname') ->from($this->table, 'u') @@ -281,9 +283,9 @@ class Database extends ABackend implements $query->expr()->eq('configkey', $query->expr()->literal('email'))) ) // sqlite doesn't like re-using a single named parameter here - ->where($query->expr()->iLike('uid', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%'))) - ->orWhere($query->expr()->iLike('displayname', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%'))) - ->orWhere($query->expr()->iLike('configvalue', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%'))) + ->where($query->expr()->iLike('uid', $query->createPositionalParameter('%' . $dbConn->escapeLikeParameter($search) . '%'))) + ->orWhere($query->expr()->iLike('displayname', $query->createPositionalParameter('%' . $dbConn->escapeLikeParameter($search) . '%'))) + ->orWhere($query->expr()->iLike('configvalue', $query->createPositionalParameter('%' . $dbConn->escapeLikeParameter($search) . '%'))) ->orderBy($query->func()->lower('displayname'), 'ASC') ->addOrderBy('uid_lower', 'ASC') ->setMaxResults($limit) @@ -309,9 +311,8 @@ class Database extends ABackend implements public function searchKnownUsersByDisplayName(string $searcher, string $pattern, ?int $limit = null, ?int $offset = null): array { $limit = $this->fixLimit($limit); - $this->fixDI(); - - $query = $this->dbConn->getQueryBuilder(); + $dbConn = $this->getDbConnection(); + $query = $dbConn->getQueryBuilder(); $query->select('u.uid', 'u.displayname') ->from($this->table, 'u') @@ -321,8 +322,8 @@ class Database extends ABackend implements )) ->where($query->expr()->eq('k.known_to', $query->createNamedParameter($searcher))) ->andWhere($query->expr()->orX( - $query->expr()->iLike('u.uid', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($pattern) . '%')), - $query->expr()->iLike('u.displayname', $query->createNamedParameter('%' . $this->dbConn->escapeLikeParameter($pattern) . '%')) + $query->expr()->iLike('u.uid', $query->createNamedParameter('%' . $dbConn->escapeLikeParameter($pattern) . '%')), + $query->expr()->iLike('u.displayname', $query->createNamedParameter('%' . $dbConn->escapeLikeParameter($pattern) . '%')) )) ->orderBy('u.displayname', 'ASC') ->addOrderBy('u.uid_lower', 'ASC') @@ -341,7 +342,7 @@ class Database extends ABackend implements /** * Check if the password is correct * - * @param string $loginName The loginname + * @param string $loginName The login name * @param string $password The password * @return string * @@ -368,46 +369,64 @@ class Database extends ABackend implements /** * Load an user in the cache * - * @param string $uid the username + * @param string $loginName the username or email * @return boolean true if user was found, false otherwise */ - private function loadUser($uid) { - $this->fixDI(); + private function loadUser(string $loginName, bool $tryEmail = true): bool { + if (isset($this->cache[$loginName])) { + return $this->cache[$loginName] !== false; + } - $uid = (string)$uid; - if (!isset($this->cache[$uid])) { - //guests $uid could be NULL or '' - if ($uid === '') { - $this->cache[$uid] = false; - return true; - } + //guests $uid could be NULL or '' + if ($loginName === '') { + $this->cache[$loginName] = false; + return false; + } + + $dbConn = $this->getDbConnection(); + $qb = $dbConn->getQueryBuilder(); + $qb->select('uid', 'displayname', 'password') + ->from($this->table) + ->where( + $qb->expr()->eq( + 'uid_lower', $qb->createNamedParameter(mb_strtolower($loginName)) + ) + ); + $result = $qb->executeQuery(); + $row = $result->fetch(); + $result->closeCursor(); + + // "uid" is primary key, so there can only be a single result + if ($row !== false) { + $this->cache[$loginName] = [ + 'uid' => (string)$row['uid'], + 'displayname' => (string)$row['displayname'], + 'password' => (string)$row['password'], + ]; + return true; + } - $qb = $this->dbConn->getQueryBuilder(); - $qb->select('uid', 'displayname', 'password') - ->from($this->table) - ->where( - $qb->expr()->eq( - 'uid_lower', $qb->createNamedParameter(mb_strtolower($uid)) - ) - ); - $result = $qb->executeQuery(); - $row = $result->fetch(); - $result->closeCursor(); - - // "uid" is primary key, so there can only be a single result - if ($row !== false) { - $this->cache[$uid] = [ - 'uid' => (string)$row['uid'], - 'displayname' => (string)$row['displayname'], - 'password' => (string)$row['password'], - ]; - } else { - $this->cache[$uid] = false; - return false; + // Not found by UID so we try also for email, load uid for email. + if ($tryEmail) { + /** @var string|null $uid Psalm does not get the type correct here */ + [$uid] = [...$this->config->getUsersForUserValue('settings', 'email', mb_strtolower($loginName)), null]; + + // If found, try loading it + if ($uid !== null && $uid !== $loginName) { + $result = $this->loadUser($uid, false); + if ($result) { + // Also add cache result for the email + $this->cache[$loginName] = $this->cache[$uid]; + // Set a reference to the uid cache entry for also delete email entry on user delete + $this->cache[$uid]['email'] = $loginName; + return true; + } } } - return true; + // Not found by uid nor email, so cache as not existing + $this->cache[$loginName] = false; + return false; } /** @@ -436,8 +455,7 @@ class Database extends ABackend implements * @return boolean */ public function userExists($uid) { - $this->loadUser($uid); - return $this->cache[$uid] !== false; + return $this->loadUser($uid); } /** @@ -448,7 +466,7 @@ class Database extends ABackend implements */ public function getHome(string $uid) { if ($this->userExists($uid)) { - return \OC::$server->getConfig()->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $uid; + return $this->config->getSystemValueString('datadirectory', \OC::$SERVERROOT . '/data') . '/' . $uid; } return false; @@ -463,18 +481,18 @@ class Database extends ABackend implements /** * counts the users in the database - * - * @return int|false */ - public function countUsers() { - $this->fixDI(); - - $query = $this->dbConn->getQueryBuilder(); + public function countUsers(int $limit = 0): int|false { + $dbConn = $this->getDbConnection(); + $query = $dbConn->getQueryBuilder(); $query->select($query->func()->count('uid')) ->from($this->table); - $result = $query->executeQuery(); + $result = $query->executeQuery()->fetchOne(); + if ($result === false) { + return false; + } - return $result->fetchOne(); + return (int)$result; } /** @@ -505,7 +523,7 @@ class Database extends ABackend implements throw new \Exception('key uid is expected to be set in $param'); } - $backends = \OC::$server->getUserManager()->getBackends(); + $backends = \OCP\Server::get(IUserManager::class)->getBackends(); foreach ($backends as $backend) { if ($backend instanceof Database) { /** @var \OC\User\Database $backend */ diff --git a/lib/private/User/DisplayNameCache.php b/lib/private/User/DisplayNameCache.php index 34db783de68..40e1c752589 100644 --- a/lib/private/User/DisplayNameCache.php +++ b/lib/private/User/DisplayNameCache.php @@ -11,6 +11,7 @@ use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\ICache; use OCP\ICacheFactory; +use OCP\IUser; use OCP\IUserManager; use OCP\User\Events\UserChangedEvent; use OCP\User\Events\UserDeletedEvent; @@ -37,6 +38,11 @@ class DisplayNameCache implements IEventListener { if (isset($this->cache[$userId])) { return $this->cache[$userId]; } + + if (strlen($userId) > IUser::MAX_USERID_LENGTH) { + return null; + } + $displayName = $this->memCache->get($userId); if ($displayName) { $this->cache[$userId] = $displayName; diff --git a/lib/private/User/LazyUser.php b/lib/private/User/LazyUser.php index 92a0c735215..501169019d4 100644 --- a/lib/private/User/LazyUser.php +++ b/lib/private/User/LazyUser.php @@ -60,11 +60,15 @@ class LazyUser implements IUser { return $this->getUser()->setDisplayName($displayName); } - public function getLastLogin() { + public function getLastLogin(): int { return $this->getUser()->getLastLogin(); } - public function updateLastLoginTimestamp() { + public function getFirstLogin(): int { + return $this->getUser()->getFirstLogin(); + } + + public function updateLastLoginTimestamp(): bool { return $this->getUser()->updateLastLoginTimestamp(); } @@ -108,6 +112,10 @@ class LazyUser implements IUser { return $this->getUser()->canChangeDisplayName(); } + public function canChangeEmail(): bool { + return $this->getUser()->canChangeEmail(); + } + public function isEnabled() { return $this->getUser()->isEnabled(); } @@ -152,6 +160,10 @@ class LazyUser implements IUser { return $this->getUser()->getQuota(); } + public function getQuotaBytes(): int|float { + return $this->getUser()->getQuotaBytes(); + } + public function setQuota($quota) { $this->getUser()->setQuota($quota); } diff --git a/lib/private/User/Listeners/UserChangedListener.php b/lib/private/User/Listeners/UserChangedListener.php index 983a4e81233..8f618950255 100644 --- a/lib/private/User/Listeners/UserChangedListener.php +++ b/lib/private/User/Listeners/UserChangedListener.php @@ -28,7 +28,7 @@ class UserChangedListener implements IEventListener { if (!($event instanceof UserChangedEvent)) { return; } - + $user = $event->getUser(); $feature = $event->getFeature(); $oldValue = $event->getOldValue(); diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php index 7f5b06cc5f6..097fd9a0dc8 100644 --- a/lib/private/User/Manager.php +++ b/lib/private/User/Manager.php @@ -24,8 +24,10 @@ use OCP\L10N\IFactory; use OCP\Server; use OCP\Support\Subscription\IAssertion; use OCP\User\Backend\ICheckPasswordBackend; +use OCP\User\Backend\ICountMappedUsersBackend; use OCP\User\Backend\ICountUsersBackend; use OCP\User\Backend\IGetRealUIDBackend; +use OCP\User\Backend\ILimitAwareCountUsersBackend; use OCP\User\Backend\IProvideEnabledStateBackend; use OCP\User\Backend\ISearchKnownUsersBackend; use OCP\User\Events\BeforeUserCreatedEvent; @@ -52,7 +54,7 @@ use Psr\Log\LoggerInterface; */ class Manager extends PublicEmitter implements IUserManager { /** - * @var \OCP\UserInterface[] $backends + * @var UserInterface[] $backends */ private array $backends = []; @@ -80,37 +82,24 @@ class Manager extends PublicEmitter implements IUserManager { /** * Get the active backends - * @return \OCP\UserInterface[] + * @return UserInterface[] */ - public function getBackends() { + public function getBackends(): array { return $this->backends; } - /** - * register a user backend - * - * @param \OCP\UserInterface $backend - */ - public function registerBackend($backend) { + public function registerBackend(UserInterface $backend): void { $this->backends[] = $backend; } - /** - * remove a user backend - * - * @param \OCP\UserInterface $backend - */ - public function removeBackend($backend) { + public function removeBackend(UserInterface $backend): void { $this->cachedUsers = []; if (($i = array_search($backend, $this->backends)) !== false) { unset($this->backends[$i]); } } - /** - * remove all user backends - */ - public function clearBackends() { + public function clearBackends(): void { $this->cachedUsers = []; $this->backends = []; } @@ -129,6 +118,10 @@ class Manager extends PublicEmitter implements IUserManager { return $this->cachedUsers[$uid]; } + if (strlen($uid) > IUser::MAX_USERID_LENGTH) { + return null; + } + $cachedBackend = $this->cache->get(sha1($uid)); if ($cachedBackend !== null && isset($this->backends[$cachedBackend])) { // Cache has the info of the user backend already, so ask that one directly @@ -188,6 +181,10 @@ class Manager extends PublicEmitter implements IUserManager { * @return bool */ public function userExists($uid) { + if (strlen($uid) > IUser::MAX_USERID_LENGTH) { + return false; + } + $user = $this->get($uid); return ($user !== null); } @@ -323,9 +320,9 @@ class Manager extends PublicEmitter implements IUserManager { $users, function (IUser $user) use ($search): bool { try { - return mb_stripos($user->getUID(), $search) !== false || - mb_stripos($user->getDisplayName(), $search) !== false || - mb_stripos($user->getEMailAddress() ?? '', $search) !== false; + return mb_stripos($user->getUID(), $search) !== false + || mb_stripos($user->getDisplayName(), $search) !== false + || mb_stripos($user->getEMailAddress() ?? '', $search) !== false; } catch (NoUserException $ex) { $this->logger->error('Error while filtering disabled users', ['exception' => $ex, 'userUID' => $user->getUID()]); return false; @@ -488,22 +485,58 @@ class Manager extends PublicEmitter implements IUserManager { return $userCountStatistics; } + public function countUsersTotal(int $limit = 0, bool $onlyMappedUsers = false): int|false { + $userCount = false; + + foreach ($this->backends as $backend) { + if ($onlyMappedUsers && $backend instanceof ICountMappedUsersBackend) { + $backendUsers = $backend->countMappedUsers(); + } elseif ($backend instanceof ILimitAwareCountUsersBackend) { + $backendUsers = $backend->countUsers($limit); + } elseif ($backend instanceof ICountUsersBackend || $backend->implementsActions(Backend::COUNT_USERS)) { + /** @var ICountUsersBackend $backend */ + $backendUsers = $backend->countUsers(); + } else { + $this->logger->debug('Skip backend for user count: ' . get_class($backend)); + continue; + } + if ($backendUsers !== false) { + $userCount = (int)$userCount + $backendUsers; + if ($limit > 0) { + if ($userCount >= $limit) { + break; + } + $limit -= $userCount; + } + } else { + $this->logger->warning('Can not determine user count for ' . get_class($backend)); + } + } + return $userCount; + } + /** * returns how many users per backend exist in the requested groups (if supported by backend) * - * @param IGroup[] $groups an array of gid to search in - * @return array|int an array of backend class as key and count number as value - * if $hasLoggedIn is true only an int is returned + * @param IGroup[] $groups an array of groups to search in + * @param int $limit limit to stop counting + * @return array{int,int} total number of users, and number of disabled users in the given groups, below $limit. If limit is reached, -1 is returned for number of disabled users */ - public function countUsersOfGroups(array $groups) { + public function countUsersAndDisabledUsersOfGroups(array $groups, int $limit): array { $users = []; + $disabled = []; foreach ($groups as $group) { - $usersIds = array_map(function ($user) { - return $user->getUID(); - }, $group->getUsers()); - $users = array_merge($users, $usersIds); + foreach ($group->getUsers() as $user) { + $users[$user->getUID()] = 1; + if (!$user->isEnabled()) { + $disabled[$user->getUID()] = 1; + } + if (count($users) >= $limit) { + return [count($users),-1]; + } + } } - return count(array_unique($users)); + return [count($users),count($disabled)]; } /** @@ -570,36 +603,6 @@ class Manager extends PublicEmitter implements IUserManager { } /** - * returns how many users are disabled in the requested groups - * - * @param array $groups groupids to search - * @return int - * @since 14.0.0 - */ - public function countDisabledUsersOfGroups(array $groups): int { - $queryBuilder = \OC::$server->getDatabaseConnection()->getQueryBuilder(); - $queryBuilder->select($queryBuilder->createFunction('COUNT(DISTINCT ' . $queryBuilder->getColumnName('uid') . ')')) - ->from('preferences', 'p') - ->innerJoin('p', 'group_user', 'g', $queryBuilder->expr()->eq('p.userid', 'g.uid')) - ->where($queryBuilder->expr()->eq('appid', $queryBuilder->createNamedParameter('core'))) - ->andWhere($queryBuilder->expr()->eq('configkey', $queryBuilder->createNamedParameter('enabled'))) - ->andWhere($queryBuilder->expr()->eq('configvalue', $queryBuilder->createNamedParameter('false'), IQueryBuilder::PARAM_STR)) - ->andWhere($queryBuilder->expr()->in('gid', $queryBuilder->createNamedParameter($groups, IQueryBuilder::PARAM_STR_ARRAY))); - - $result = $queryBuilder->execute(); - $count = $result->fetchOne(); - $result->closeCursor(); - - if ($count !== false) { - $count = (int)$count; - } else { - $count = 0; - } - - return $count; - } - - /** * returns how many users have logged in once * * @return int @@ -620,30 +623,14 @@ class Manager extends PublicEmitter implements IUserManager { return $result; } - /** - * @param \Closure $callback - * @psalm-param \Closure(\OCP\IUser):?bool $callback - * @since 11.0.0 - */ public function callForSeenUsers(\Closure $callback) { - $limit = 1000; - $offset = 0; - do { - $userIds = $this->getSeenUserIds($limit, $offset); - $offset += $limit; - foreach ($userIds as $userId) { - foreach ($this->backends as $backend) { - if ($backend->userExists($userId)) { - $user = $this->getUserObject($userId, $backend, false); - $return = $callback($user); - if ($return === false) { - return; - } - break; - } - } + $users = $this->getSeenUsers(); + foreach ($users as $user) { + $return = $callback($user); + if ($return === false) { + return; } - } while (count($userIds) >= $limit); + } } /** @@ -713,14 +700,14 @@ class Manager extends PublicEmitter implements IUserManager { public function validateUserId(string $uid, bool $checkDataDirectory = false): void { $l = Server::get(IFactory::class)->get('lib'); - // Check the name for bad characters + // Check the ID for bad characters // Allowed are: "a-z", "A-Z", "0-9", spaces and "_.@-'" if (preg_match('/[^a-zA-Z0-9 _.@\-\']/', $uid)) { throw new \InvalidArgumentException($l->t('Only the following characters are allowed in an Login:' . ' "a-z", "A-Z", "0-9", spaces and "_.@-\'"')); } - // No empty username + // No empty user ID if (trim($uid) === '') { throw new \InvalidArgumentException($l->t('A valid Login must be provided')); } @@ -730,11 +717,17 @@ class Manager extends PublicEmitter implements IUserManager { throw new \InvalidArgumentException($l->t('Login contains whitespace at the beginning or at the end')); } - // Username only consists of 1 or 2 dots (directory traversal) + // User ID only consists of 1 or 2 dots (directory traversal) if ($uid === '.' || $uid === '..') { throw new \InvalidArgumentException($l->t('Login must not consist of dots only')); } + // User ID is too long + if (strlen($uid) > IUser::MAX_USERID_LENGTH) { + // TRANSLATORS User ID is too long + throw new \InvalidArgumentException($l->t('Username is too long')); + } + if (!$this->verifyUid($uid, $checkDataDirectory)) { throw new \InvalidArgumentException($l->t('Login is invalid because files already exist for this user')); } @@ -819,4 +812,30 @@ class Manager extends PublicEmitter implements IUserManager { public function getDisplayNameCache(): DisplayNameCache { return $this->displayNameCache; } + + /** + * Gets the list of users sorted by lastLogin, from most recent to least recent + * + * @param int $offset from which offset to fetch + * @return \Iterator<IUser> list of user IDs + * @since 30.0.0 + */ + public function getSeenUsers(int $offset = 0): \Iterator { + $limit = 1000; + + do { + $userIds = $this->getSeenUserIds($limit, $offset); + $offset += $limit; + + foreach ($userIds as $userId) { + foreach ($this->backends as $backend) { + if ($backend->userExists($userId)) { + $user = $this->getUserObject($userId, $backend, false); + yield $user; + break; + } + } + } + } while (count($userIds) === $limit); + } } diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index 408ebffb390..95e4b6e4a87 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -780,7 +781,7 @@ class Session implements IUserSession, Emitter { * Check if login names match */ private function validateTokenLoginName(?string $loginName, IToken $token): bool { - if ($token->getLoginName() !== $loginName) { + if (mb_strtolower($token->getLoginName()) !== mb_strtolower($loginName ?? '')) { // TODO: this makes it impossible to use different login names on browser and client // e.g. login by e-mail 'user@example.com' on browser for generating the token will not // allow to use the client token with the login name 'user'. @@ -834,9 +835,8 @@ class Session implements IUserSession, Emitter { return true; } - // Remember me tokens are not app_passwords - if ($dbToken->getRemember() === IToken::DO_NOT_REMEMBER) { - // Set the session variable so we know this is an app password + // Set the session variable so we know this is an app password + if ($dbToken instanceof PublicKeyToken && $dbToken->getType() === IToken::PERMANENT_TOKEN) { $this->session->set('app_password', $token); } @@ -968,6 +968,7 @@ class Session implements IUserSession, Emitter { if ($webRoot === '') { $webRoot = '/'; } + $domain = $this->config->getSystemValueString('cookie_domain'); $maxAge = $this->config->getSystemValueInt('remember_login_cookie_lifetime', 60 * 60 * 24 * 15); \OC\Http\CookieHelper::setCookie( @@ -975,7 +976,7 @@ class Session implements IUserSession, Emitter { $username, $maxAge, $webRoot, - '', + $domain, $secureCookie, true, \OC\Http\CookieHelper::SAMESITE_LAX @@ -985,7 +986,7 @@ class Session implements IUserSession, Emitter { $token, $maxAge, $webRoot, - '', + $domain, $secureCookie, true, \OC\Http\CookieHelper::SAMESITE_LAX @@ -996,7 +997,7 @@ class Session implements IUserSession, Emitter { $this->session->getId(), $maxAge, $webRoot, - '', + $domain, $secureCookie, true, \OC\Http\CookieHelper::SAMESITE_LAX @@ -1012,18 +1013,19 @@ class Session implements IUserSession, Emitter { public function unsetMagicInCookie() { //TODO: DI for cookies and IRequest $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https'; + $domain = $this->config->getSystemValueString('cookie_domain'); unset($_COOKIE['nc_username']); //TODO: DI unset($_COOKIE['nc_token']); unset($_COOKIE['nc_session_id']); - setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true); - setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true); - setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true); + setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, $domain, $secureCookie, true); + setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, $domain, $secureCookie, true); + setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, $domain, $secureCookie, true); // old cookies might be stored under /webroot/ instead of /webroot // and Firefox doesn't like it! - setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); - setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); - setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true); + setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', $domain, $secureCookie, true); + setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', $domain, $secureCookie, true); + setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', $domain, $secureCookie, true); } /** diff --git a/lib/private/User/User.php b/lib/private/User/User.php index 4b1ec4366d0..88ed0d44387 100644 --- a/lib/private/User/User.php +++ b/lib/private/User/User.php @@ -11,7 +11,6 @@ use InvalidArgumentException; use OC\Accounts\AccountManager; use OC\Avatar\AvatarManager; use OC\Hooks\Emitter; -use OC_Helper; use OCP\Accounts\IAccountManager; use OCP\Comments\ICommentsManager; use OCP\EventDispatcher\IEventDispatcher; @@ -65,8 +64,8 @@ class User implements IUser { /** @var string */ private $home; - /** @var int|null */ - private $lastLogin; + private ?int $lastLogin = null; + private ?int $firstLogin = null; /** @var IAvatarManager */ private $avatarManager; @@ -202,28 +201,47 @@ class User implements IUser { /** * returns the timestamp of the user's last login or 0 if the user did never * login - * - * @return int */ - public function getLastLogin() { + public function getLastLogin(): int { if ($this->lastLogin === null) { $this->lastLogin = (int)$this->config->getUserValue($this->uid, 'login', 'lastLogin', 0); } - return (int)$this->lastLogin; + return $this->lastLogin; + } + + /** + * returns the timestamp of the user's last login or 0 if the user did never + * login + */ + public function getFirstLogin(): int { + if ($this->firstLogin === null) { + $this->firstLogin = (int)$this->config->getUserValue($this->uid, 'login', 'firstLogin', 0); + } + return $this->firstLogin; } /** * updates the timestamp of the most recent login of this user */ - public function updateLastLoginTimestamp() { + public function updateLastLoginTimestamp(): bool { $previousLogin = $this->getLastLogin(); + $firstLogin = $this->getFirstLogin(); $now = time(); $firstTimeLogin = $previousLogin === 0; if ($now - $previousLogin > 60) { - $this->lastLogin = time(); - $this->config->setUserValue( - $this->uid, 'login', 'lastLogin', (string)$this->lastLogin); + $this->lastLogin = $now; + $this->config->setUserValue($this->uid, 'login', 'lastLogin', (string)$this->lastLogin); + } + + if ($firstLogin === 0) { + if ($firstTimeLogin) { + $this->firstLogin = $now; + } else { + /* Unknown first login, most likely was before upgrade to Nextcloud 31 */ + $this->firstLogin = -1; + } + $this->config->setUserValue($this->uid, 'login', 'firstLogin', (string)$this->firstLogin); } return $firstTimeLogin; @@ -428,6 +446,11 @@ class User implements IUser { return $this->backend->implementsActions(Backend::SET_DISPLAYNAME); } + public function canChangeEmail(): bool { + // Fallback to display name value to avoid changing behavior with the new option. + return $this->config->getSystemValueBool('allow_user_to_change_email', $this->config->getSystemValueBool('allow_user_to_change_display_name', true)); + } + /** * check if the user is enabled * @@ -535,6 +558,19 @@ class User implements IUser { return $quota; } + public function getQuotaBytes(): int|float { + $quota = $this->getQuota(); + if ($quota === 'none') { + return \OCP\Files\FileInfo::SPACE_UNLIMITED; + } + + $bytes = \OCP\Util::computerFileSize($quota); + if ($bytes === false) { + return \OCP\Files\FileInfo::SPACE_UNKNOWN; + } + return $bytes; + } + /** * set the users' quota * @@ -546,11 +582,11 @@ class User implements IUser { public function setQuota($quota) { $oldQuota = $this->config->getUserValue($this->uid, 'files', 'quota', ''); if ($quota !== 'none' and $quota !== 'default') { - $bytesQuota = OC_Helper::computerFileSize($quota); + $bytesQuota = \OCP\Util::computerFileSize($quota); if ($bytesQuota === false) { throw new InvalidArgumentException('Failed to set quota to invalid value ' . $quota); } - $quota = OC_Helper::humanFileSize($bytesQuota); + $quota = \OCP\Util::humanFileSize($bytesQuota); } if ($quota !== $oldQuota) { $this->config->setUserValue($this->uid, 'files', 'quota', $quota); diff --git a/lib/private/legacy/OC_App.php b/lib/private/legacy/OC_App.php index 544938b6ff9..24982ab9e80 100644 --- a/lib/private/legacy/OC_App.php +++ b/lib/private/legacy/OC_App.php @@ -9,6 +9,7 @@ declare(strict_types=1); use OC\App\DependencyAnalyzer; use OC\App\Platform; use OC\AppFramework\Bootstrap\Coordinator; +use OC\Config\ConfigManager; use OC\DB\MigrationService; use OC\Installer; use OC\Repair; @@ -185,7 +186,7 @@ class OC_App { } if (is_null($user)) { - $apps = $appManager->getInstalledApps(); + $apps = $appManager->getEnabledApps(); } else { $apps = $appManager->getEnabledAppsForUser($user); } @@ -211,7 +212,7 @@ class OC_App { array $groups = []) { // Check if app is already downloaded /** @var Installer $installer */ - $installer = \OCP\Server::get(Installer::class); + $installer = Server::get(Installer::class); $isDownloaded = $installer->isDownloaded($appId); if (!$isDownloaded) { @@ -246,7 +247,7 @@ class OC_App { } } - \OCP\Server::get(LoggerInterface::class)->error('No application directories are marked as writable.', ['app' => 'core']); + Server::get(LoggerInterface::class)->error('No application directories are marked as writable.', ['app' => 'core']); return null; } @@ -310,12 +311,14 @@ class OC_App { * @param string $appId * @param bool $refreshAppPath should be set to true only during install/upgrade * @return string|false - * @deprecated 11.0.0 use \OCP\Server::get(IAppManager)->getAppPath() + * @deprecated 11.0.0 use Server::get(IAppManager)->getAppPath() */ public static function getAppPath(string $appId, bool $refreshAppPath = false) { $appId = self::cleanAppId($appId); if ($appId === '') { return false; + } elseif ($appId === 'core') { + return __DIR__ . '/../../../core'; } if (($dir = self::findAppInDirectories($appId, $refreshAppPath)) != false) { @@ -347,7 +350,7 @@ class OC_App { */ public static function getAppVersionByPath(string $path): string { $infoFile = $path . '/appinfo/info.xml'; - $appData = \OCP\Server::get(IAppManager::class)->getAppInfoByPath($infoFile); + $appData = Server::get(IAppManager::class)->getAppInfoByPath($infoFile); return $appData['version'] ?? ''; } @@ -389,7 +392,7 @@ class OC_App { * @deprecated 20.0.0 Please register your alternative login option using the registerAlternativeLogin() on the RegistrationContext in your Application class implementing the OCP\Authentication\IAlternativeLogin interface */ public static function registerLogIn(array $entry) { - \OCP\Server::get(LoggerInterface::class)->debug('OC_App::registerLogIn() is deprecated, please register your alternative login option using the registerAlternativeLogin() on the RegistrationContext in your Application class implementing the OCP\Authentication\IAlternativeLogin interface'); + Server::get(LoggerInterface::class)->debug('OC_App::registerLogIn() is deprecated, please register your alternative login option using the registerAlternativeLogin() on the RegistrationContext in your Application class implementing the OCP\Authentication\IAlternativeLogin interface'); self::$altLogin[] = $entry; } @@ -398,11 +401,11 @@ class OC_App { */ public static function getAlternativeLogIns(): array { /** @var Coordinator $bootstrapCoordinator */ - $bootstrapCoordinator = \OCP\Server::get(Coordinator::class); + $bootstrapCoordinator = Server::get(Coordinator::class); foreach ($bootstrapCoordinator->getRegistrationContext()->getAlternativeLogins() as $registration) { if (!in_array(IAlternativeLogin::class, class_implements($registration->getService()), true)) { - \OCP\Server::get(LoggerInterface::class)->error('Alternative login option {option} does not implement {interface} and is therefore ignored.', [ + Server::get(LoggerInterface::class)->error('Alternative login option {option} does not implement {interface} and is therefore ignored.', [ 'option' => $registration->getService(), 'interface' => IAlternativeLogin::class, 'app' => $registration->getAppId(), @@ -412,9 +415,9 @@ class OC_App { try { /** @var IAlternativeLogin $provider */ - $provider = \OCP\Server::get($registration->getService()); + $provider = Server::get($registration->getService()); } catch (ContainerExceptionInterface $e) { - \OCP\Server::get(LoggerInterface::class)->error('Alternative login option {option} can not be initialized.', + Server::get(LoggerInterface::class)->error('Alternative login option {option} can not be initialized.', [ 'exception' => $e, 'option' => $registration->getService(), @@ -431,7 +434,7 @@ class OC_App { 'class' => $provider->getClass(), ]; } catch (Throwable $e) { - \OCP\Server::get(LoggerInterface::class)->error('Alternative login option {option} had an error while loading.', + Server::get(LoggerInterface::class)->error('Alternative login option {option} had an error while loading.', [ 'exception' => $e, 'option' => $registration->getService(), @@ -450,17 +453,16 @@ class OC_App { * @deprecated 31.0.0 Use IAppManager::getAllAppsInAppsFolders instead */ public static function getAllApps(): array { - return \OCP\Server::get(IAppManager::class)->getAllAppsInAppsFolders(); + return Server::get(IAppManager::class)->getAllAppsInAppsFolders(); } /** * List all supported apps * - * @return array + * @deprecated 32.0.0 Use \OCP\Support\Subscription\IRegistry::delegateGetSupportedApps instead */ public function getSupportedApps(): array { - /** @var \OCP\Support\Subscription\IRegistry $subscriptionRegistry */ - $subscriptionRegistry = \OCP\Server::get(\OCP\Support\Subscription\IRegistry::class); + $subscriptionRegistry = Server::get(\OCP\Support\Subscription\IRegistry::class); $supportedApps = $subscriptionRegistry->delegateGetSupportedApps(); return $supportedApps; } @@ -485,12 +487,12 @@ class OC_App { if (!in_array($app, $blacklist)) { $info = $appManager->getAppInfo($app, false, $langCode); if (!is_array($info)) { - \OCP\Server::get(LoggerInterface::class)->error('Could not read app info file for app "' . $app . '"', ['app' => 'core']); + Server::get(LoggerInterface::class)->error('Could not read app info file for app "' . $app . '"', ['app' => 'core']); continue; } if (!isset($info['name'])) { - \OCP\Server::get(LoggerInterface::class)->error('App id "' . $app . '" has no name in appinfo', ['app' => 'core']); + Server::get(LoggerInterface::class)->error('App id "' . $app . '" has no name in appinfo', ['app' => 'core']); continue; } @@ -557,7 +559,7 @@ class OC_App { public static function shouldUpgrade(string $app): bool { $versions = self::getAppVersions(); - $currentVersion = \OCP\Server::get(\OCP\App\IAppManager::class)->getAppVersion($app); + $currentVersion = Server::get(\OCP\App\IAppManager::class)->getAppVersion($app); if ($currentVersion && isset($versions[$app])) { $installedVersion = $versions[$app]; if (!version_compare($currentVersion, $installedVersion, '=')) { @@ -643,16 +645,10 @@ class OC_App { /** * get the installed version of all apps + * @deprecated 32.0.0 Use IAppManager::getAppInstalledVersions or IAppConfig::getAppInstalledVersions instead */ - public static function getAppVersions() { - static $versions; - - if (!$versions) { - /** @var IAppConfig $appConfig */ - $appConfig = \OCP\Server::get(IAppConfig::class); - $versions = $appConfig->searchValues('installed_version'); - } - return $versions; + public static function getAppVersions(): array { + return Server::get(IAppConfig::class)->getAppInstalledVersions(); } /** @@ -670,13 +666,13 @@ class OC_App { } if (is_file($appPath . '/appinfo/database.xml')) { - \OCP\Server::get(LoggerInterface::class)->error('The appinfo/database.xml file is not longer supported. Used in ' . $appId); + Server::get(LoggerInterface::class)->error('The appinfo/database.xml file is not longer supported. Used in ' . $appId); return false; } \OC::$server->getAppManager()->clearAppsCache(); $l = \OC::$server->getL10N('core'); - $appData = \OCP\Server::get(\OCP\App\IAppManager::class)->getAppInfo($appId, false, $l->getLanguageCode()); + $appData = Server::get(\OCP\App\IAppManager::class)->getAppInfo($appId, false, $l->getLanguageCode()); $ignoreMaxApps = \OC::$server->getConfig()->getSystemValue('app_install_overwrite', []); $ignoreMax = in_array($appId, $ignoreMaxApps, true); @@ -716,9 +712,13 @@ class OC_App { self::setAppTypes($appId); - $version = \OCP\Server::get(\OCP\App\IAppManager::class)->getAppVersion($appId); + $version = Server::get(\OCP\App\IAppManager::class)->getAppVersion($appId); \OC::$server->getConfig()->setAppValue($appId, 'installed_version', $version); + // migrate eventual new config keys in the process + /** @psalm-suppress InternalMethod */ + Server::get(ConfigManager::class)->migrateConfigLexiconKeys($appId); + \OC::$server->get(IEventDispatcher::class)->dispatchTyped(new AppUpdateEvent($appId)); \OC::$server->get(IEventDispatcher::class)->dispatch(ManagerEvent::EVENT_APP_UPDATE, new ManagerEvent( ManagerEvent::EVENT_APP_UPDATE, $appId @@ -775,28 +775,6 @@ class OC_App { } } - /** - * @param string $appId - * @return \OC\Files\View|false - */ - public static function getStorage(string $appId) { - if (\OC::$server->getAppManager()->isEnabledForUser($appId)) { //sanity check - if (\OC::$server->getUserSession()->isLoggedIn()) { - $view = new \OC\Files\View('/' . OC_User::getUser()); - if (!$view->file_exists($appId)) { - $view->mkdir($appId); - } - return new \OC\Files\View('/' . OC_User::getUser() . '/' . $appId); - } else { - \OCP\Server::get(LoggerInterface::class)->error('Can\'t get app storage, app ' . $appId . ', user not logged in', ['app' => 'core']); - return false; - } - } else { - \OCP\Server::get(LoggerInterface::class)->error('Can\'t get app storage, app ' . $appId . ' not enabled', ['app' => 'core']); - return false; - } - } - protected static function findBestL10NOption(array $options, string $lang): string { // only a single option if (isset($options['@value'])) { diff --git a/lib/private/legacy/OC_Defaults.php b/lib/private/legacy/OC_Defaults.php index f7015a1863a..0d460ff966d 100644 --- a/lib/private/legacy/OC_Defaults.php +++ b/lib/private/legacy/OC_Defaults.php @@ -228,9 +228,9 @@ class OC_Defaults { if ($this->themeExist('getShortFooter')) { $footer = $this->theme->getShortFooter(); } else { - $footer = '<a href="' . $this->getBaseUrl() . '" target="_blank"' . - ' rel="noreferrer noopener">' . $this->getEntity() . '</a>' . - ' – ' . $this->getSlogan(); + $footer = '<a href="' . $this->getBaseUrl() . '" target="_blank"' + . ' rel="noreferrer noopener">' . $this->getEntity() . '</a>' + . ' – ' . $this->getSlogan(); } return $footer; diff --git a/lib/private/legacy/OC_Helper.php b/lib/private/legacy/OC_Helper.php index 087ea3ef88b..4388f775623 100644 --- a/lib/private/legacy/OC_Helper.php +++ b/lib/private/legacy/OC_Helper.php @@ -12,6 +12,7 @@ use OCP\Files\Mount\IMountPoint; use OCP\IBinaryFinder; use OCP\ICacheFactory; use OCP\IUser; +use OCP\Server; use OCP\Util; use Psr\Log\LoggerInterface; @@ -36,85 +37,11 @@ class OC_Helper { private static ?bool $quotaIncludeExternalStorage = null; /** - * Make a human file size - * @param int|float $bytes file size in bytes - * @return string a human readable file size - * - * Makes 2048 to 2 kB. - */ - public static function humanFileSize(int|float $bytes): string { - if ($bytes < 0) { - return '?'; - } - if ($bytes < 1024) { - return "$bytes B"; - } - $bytes = round($bytes / 1024, 0); - if ($bytes < 1024) { - return "$bytes KB"; - } - $bytes = round($bytes / 1024, 1); - if ($bytes < 1024) { - return "$bytes MB"; - } - $bytes = round($bytes / 1024, 1); - if ($bytes < 1024) { - return "$bytes GB"; - } - $bytes = round($bytes / 1024, 1); - if ($bytes < 1024) { - return "$bytes TB"; - } - - $bytes = round($bytes / 1024, 1); - return "$bytes PB"; - } - - /** - * Make a computer file size - * @param string $str file size in human readable format - * @return false|int|float a file size in bytes - * - * Makes 2kB to 2048. - * - * Inspired by: https://www.php.net/manual/en/function.filesize.php#92418 - */ - public static function computerFileSize(string $str): false|int|float { - $str = strtolower($str); - if (is_numeric($str)) { - return Util::numericToNumber($str); - } - - $bytes_array = [ - 'b' => 1, - 'k' => 1024, - 'kb' => 1024, - 'mb' => 1024 * 1024, - 'm' => 1024 * 1024, - 'gb' => 1024 * 1024 * 1024, - 'g' => 1024 * 1024 * 1024, - 'tb' => 1024 * 1024 * 1024 * 1024, - 't' => 1024 * 1024 * 1024 * 1024, - 'pb' => 1024 * 1024 * 1024 * 1024 * 1024, - 'p' => 1024 * 1024 * 1024 * 1024 * 1024, - ]; - - $bytes = (float)$str; - - if (preg_match('#([kmgtp]?b?)$#si', $str, $matches) && isset($bytes_array[$matches[1]])) { - $bytes *= $bytes_array[$matches[1]]; - } else { - return false; - } - - return Util::numericToNumber(round($bytes)); - } - - /** * Recursive copying of folders * @param string $src source folder * @param string $dest target folder * @return void + * @deprecated 32.0.0 - use \OCP\Files\Folder::copy */ public static function copyr($src, $dest) { if (!file_exists($src)) { @@ -140,44 +67,6 @@ class OC_Helper { } /** - * Recursive deletion of folders - * @param string $dir path to the folder - * @param bool $deleteSelf if set to false only the content of the folder will be deleted - * @return bool - */ - public static function rmdirr($dir, $deleteSelf = true) { - if (is_dir($dir)) { - $files = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS), - RecursiveIteratorIterator::CHILD_FIRST - ); - - foreach ($files as $fileInfo) { - /** @var SplFileInfo $fileInfo */ - if ($fileInfo->isLink()) { - unlink($fileInfo->getPathname()); - } elseif ($fileInfo->isDir()) { - rmdir($fileInfo->getRealPath()); - } else { - unlink($fileInfo->getRealPath()); - } - } - if ($deleteSelf) { - rmdir($dir); - } - } elseif (file_exists($dir)) { - if ($deleteSelf) { - unlink($dir); - } - } - if (!$deleteSelf) { - return true; - } - - return !file_exists($dir); - } - - /** * @deprecated 18.0.0 * @return \OC\Files\Type\TemplateManager */ @@ -196,6 +85,7 @@ class OC_Helper { * @internal param string $program name * @internal param string $optional search path, defaults to $PATH * @return bool true if executable program found in path + * @deprecated 32.0.0 use the \OCP\IBinaryFinder */ public static function canExecute($name, $path = false) { // path defaults to PATH from environment if not set @@ -206,7 +96,7 @@ class OC_Helper { $exts = ['']; $check_fn = 'is_executable'; // Default check will be done with $path directories : - $dirs = explode(PATH_SEPARATOR, $path); + $dirs = explode(PATH_SEPARATOR, (string)$path); // WARNING : We have to check if open_basedir is enabled : $obd = OC::$server->get(IniGetWrapper::class)->getString('open_basedir'); if ($obd != 'none') { @@ -233,31 +123,10 @@ class OC_Helper { * @param resource $source * @param resource $target * @return array the number of bytes copied and result + * @deprecated 5.0.0 - Use \OCP\Files::streamCopy */ public static function streamCopy($source, $target) { - if (!$source or !$target) { - return [0, false]; - } - $bufSize = 8192; - $result = true; - $count = 0; - while (!feof($source)) { - $buf = fread($source, $bufSize); - $bytesWritten = fwrite($target, $buf); - if ($bytesWritten !== false) { - $count += $bytesWritten; - } - // note: strlen is expensive so only use it when necessary, - // on the last block - if ($bytesWritten === false - || ($bytesWritten < $bufSize && $bytesWritten < strlen($buf)) - ) { - // write error, could be disk full ? - $result = false; - break; - } - } - return [$count, $result]; + return \OCP\Files::streamCopy($source, $target, true); } /** @@ -320,115 +189,20 @@ class OC_Helper { } /** - * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. - * - * @param array $input The array to work on - * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default) - * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 - * @return array - * - * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. - * based on https://www.php.net/manual/en/function.array-change-key-case.php#107715 - * - */ - public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') { - $case = ($case != MB_CASE_UPPER) ? MB_CASE_LOWER : MB_CASE_UPPER; - $ret = []; - foreach ($input as $k => $v) { - $ret[mb_convert_case($k, $case, $encoding)] = $v; - } - return $ret; - } - - /** - * performs a search in a nested array - * @param array $haystack the array to be searched - * @param string $needle the search string - * @param mixed $index optional, only search this key name - * @return mixed the key of the matching field, otherwise false - * - * performs a search in a nested array - * - * taken from https://www.php.net/manual/en/function.array-search.php#97645 - */ - public static function recursiveArraySearch($haystack, $needle, $index = null) { - $aIt = new RecursiveArrayIterator($haystack); - $it = new RecursiveIteratorIterator($aIt); - - while ($it->valid()) { - if (((isset($index) and ($it->key() == $index)) or !isset($index)) and ($it->current() == $needle)) { - return $aIt->key(); - } - - $it->next(); - } - - return false; - } - - /** - * calculates the maximum upload size respecting system settings, free space and user quota - * - * @param string $dir the current folder where the user currently operates - * @param int|float $freeSpace the number of bytes free on the storage holding $dir, if not set this will be received from the storage directly - * @return int|float number of bytes representing - */ - public static function maxUploadFilesize($dir, $freeSpace = null) { - if (is_null($freeSpace) || $freeSpace < 0) { - $freeSpace = self::freeSpace($dir); - } - return min($freeSpace, self::uploadLimit()); - } - - /** - * Calculate free space left within user quota - * - * @param string $dir the current folder where the user currently operates - * @return int|float number of bytes representing - */ - public static function freeSpace($dir) { - $freeSpace = \OC\Files\Filesystem::free_space($dir); - if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) { - $freeSpace = max($freeSpace, 0); - return $freeSpace; - } else { - return (INF > 0)? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188 - } - } - - /** - * Calculate PHP upload limit - * - * @return int|float PHP upload file size limit - */ - public static function uploadLimit() { - $ini = \OC::$server->get(IniGetWrapper::class); - $upload_max_filesize = Util::computerFileSize($ini->get('upload_max_filesize')) ?: 0; - $post_max_size = Util::computerFileSize($ini->get('post_max_size')) ?: 0; - if ($upload_max_filesize === 0 && $post_max_size === 0) { - return INF; - } elseif ($upload_max_filesize === 0 || $post_max_size === 0) { - return max($upload_max_filesize, $post_max_size); //only the non 0 value counts - } else { - return min($upload_max_filesize, $post_max_size); - } - } - - /** * Checks if a function is available * * @deprecated 25.0.0 use \OCP\Util::isFunctionEnabled instead */ public static function is_function_enabled(string $function_name): bool { - return \OCP\Util::isFunctionEnabled($function_name); + return Util::isFunctionEnabled($function_name); } /** * Try to find a program - * @deprecated 25.0.0 Use \OC\BinaryFinder directly + * @deprecated 25.0.0 Use \OCP\IBinaryFinder directly */ public static function findBinaryPath(string $program): ?string { - $result = \OCP\Server::get(IBinaryFinder::class)->findBinaryPath($program); + $result = Server::get(IBinaryFinder::class)->findBinaryPath($program); return $result !== false ? $result : null; } @@ -448,7 +222,7 @@ class OC_Helper { */ public static function getStorageInfo($path, $rootInfo = null, $includeMountPoints = true, $useCache = true) { if (!self::$cacheFactory) { - self::$cacheFactory = \OC::$server->get(ICacheFactory::class); + self::$cacheFactory = Server::get(ICacheFactory::class); } $memcache = self::$cacheFactory->createLocal('storage_info'); @@ -498,7 +272,7 @@ class OC_Helper { } else { $user = \OC::$server->getUserSession()->getUser(); } - $quota = OC_Util::getUserQuota($user); + $quota = $user?->getQuotaBytes() ?? \OCP\Files\FileInfo::SPACE_UNKNOWN; if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) { // always get free space / total space from root + mount points return self::getGlobalStorageInfo($quota, $user, $mount); @@ -541,9 +315,16 @@ class OC_Helper { $relative = 0; } + /* + * \OCA\Files_Sharing\External\Storage returns the cloud ID as the owner for the storage. + * It is unnecessary to query the user manager for the display name, as it won't have this information. + */ + $isRemoteShare = $storage->instanceOfStorage(\OCA\Files_Sharing\External\Storage::class); + $ownerId = $storage->getOwner($path); $ownerDisplayName = ''; - if ($ownerId !== false) { + + if ($isRemoteShare === false && $ownerId !== false) { $ownerDisplayName = \OC::$server->getUserManager()->getDisplayName($ownerId) ?? ''; } @@ -565,7 +346,7 @@ class OC_Helper { 'mountPoint' => trim($mountPoint, '/'), ]; - if ($ownerId && $path === '/') { + if ($isRemoteShare === false && $ownerId !== false && $path === '/') { // If path is root, store this as last known quota usage for this user \OCP\Server::get(\OCP\IConfig::class)->setUserValue($ownerId, 'files', 'lastSeenQuotaUsage', (string)$relative); } @@ -634,6 +415,7 @@ class OC_Helper { /** * Returns whether the config file is set manually to read-only * @return bool + * @deprecated 32.0.0 use the `config_is_read_only` system config directly */ public static function isReadOnlyConfigEnabled() { return \OC::$server->getConfig()->getSystemValueBool('config_is_read_only', false); diff --git a/lib/private/legacy/OC_JSON.php b/lib/private/legacy/OC_JSON.php index d2b85951123..6daef18dd61 100644 --- a/lib/private/legacy/OC_JSON.php +++ b/lib/private/legacy/OC_JSON.php @@ -74,7 +74,6 @@ class OC_JSON { * Send json error msg * @deprecated 12.0.0 Use a AppFramework JSONResponse instead * @suppress PhanDeprecatedFunction - * @psalm-taint-escape html */ public static function error($data = []) { $data['status'] = 'error'; @@ -86,7 +85,6 @@ class OC_JSON { * Send json success msg * @deprecated 12.0.0 Use a AppFramework JSONResponse instead * @suppress PhanDeprecatedFunction - * @psalm-taint-escape html */ public static function success($data = []) { $data['status'] = 'success'; @@ -97,6 +95,9 @@ class OC_JSON { /** * Encode JSON * @deprecated 12.0.0 Use a AppFramework JSONResponse instead + * + * @psalm-taint-escape has_quotes + * @psalm-taint-escape html */ private static function encode($data) { return json_encode($data, JSON_HEX_TAG); diff --git a/lib/private/legacy/OC_Response.php b/lib/private/legacy/OC_Response.php index 86274f5fcb7..c45852b4b1d 100644 --- a/lib/private/legacy/OC_Response.php +++ b/lib/private/legacy/OC_Response.php @@ -78,7 +78,6 @@ class OC_Response { header('X-Frame-Options: SAMEORIGIN'); // Disallow iFraming from other domains header('X-Permitted-Cross-Domain-Policies: none'); // https://www.adobe.com/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html header('X-Robots-Tag: noindex, nofollow'); // https://developers.google.com/webmasters/control-crawl-index/docs/robots_meta_tag - header('X-XSS-Protection: 1; mode=block'); // Enforce browser based XSS filters } } } diff --git a/lib/private/legacy/OC_Template.php b/lib/private/legacy/OC_Template.php index 1026e536b97..bccf99af65e 100644 --- a/lib/private/legacy/OC_Template.php +++ b/lib/private/legacy/OC_Template.php @@ -5,209 +5,25 @@ * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ -use OC\TemplateLayout; -use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; -use OCP\AppFramework\Http\TemplateResponse; -use OCP\EventDispatcher\IEventDispatcher; -use Psr\Log\LoggerInterface; - -require_once __DIR__ . '/template/functions.php'; +use OCP\Server; +use OCP\Template\ITemplateManager; /** * This class provides the templates for ownCloud. + * @deprecated 32.0.0 Use \OCP\Template\ITemplateManager instead */ -class OC_Template extends \OC\Template\Base { - /** @var string */ - private $renderAs; // Create a full page? - - /** @var string */ - private $path; // The path to the template - - /** @var array */ - private $headers = []; //custom headers - - /** @var string */ - protected $app; // app id - - /** - * Constructor - * - * @param string $app app providing the template - * @param string $name of the template file (without suffix) - * @param string $renderAs If $renderAs is set, OC_Template will try to - * produce a full page in the according layout. For - * now, $renderAs can be set to "guest", "user" or - * "admin". - * @param bool $registerCall = true - */ - public function __construct($app, $name, $renderAs = TemplateResponse::RENDER_AS_BLANK, $registerCall = true) { - $theme = OC_Util::getTheme(); - - $requestToken = (OC::$server->getSession() && $registerCall) ? \OCP\Util::callRegister() : ''; - $cspNonce = \OCP\Server::get(\OC\Security\CSP\ContentSecurityPolicyNonceManager::class)->getNonce(); - - $parts = explode('/', $app); // fix translation when app is something like core/lostpassword - $l10n = \OC::$server->getL10N($parts[0]); - /** @var \OCP\Defaults $themeDefaults */ - $themeDefaults = \OCP\Server::get(\OCP\Defaults::class); - - [$path, $template] = $this->findTemplate($theme, $app, $name); - - // Set the private data - $this->renderAs = $renderAs; - $this->path = $path; - $this->app = $app; - - parent::__construct( - $template, - $requestToken, - $l10n, - $themeDefaults, - $cspNonce, - ); - } - - - /** - * find the template with the given name - * @param string $name of the template file (without suffix) - * - * Will select the template file for the selected theme. - * Checking all the possible locations. - * @param string $theme - * @param string $app - * @return string[] - */ - protected function findTemplate($theme, $app, $name) { - // Check if it is a app template or not. - if ($app !== '') { - $dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app)); - } else { - $dirs = $this->getCoreTemplateDirs($theme, OC::$SERVERROOT); - } - $locator = new \OC\Template\TemplateFileLocator($dirs); - $template = $locator->find($name); - $path = $locator->getPath(); - return [$path, $template]; - } - - /** - * Add a custom element to the header - * @param string $tag tag name of the element - * @param array $attributes array of attributes for the element - * @param string $text the text content for the element. If $text is null then the - * element will be written as empty element. So use "" to get a closing tag. - */ - public function addHeader($tag, $attributes, $text = null) { - $this->headers[] = [ - 'tag' => $tag, - 'attributes' => $attributes, - 'text' => $text - ]; - } - - /** - * Process the template - * @return string - * - * This function process the template. If $this->renderAs is set, it - * will produce a full page. - */ - public function fetchPage($additionalParams = null) { - $data = parent::fetchPage($additionalParams); - - if ($this->renderAs) { - $page = new TemplateLayout($this->renderAs, $this->app); - - if (is_array($additionalParams)) { - foreach ($additionalParams as $key => $value) { - $page->assign($key, $value); - } - } - - // Add custom headers - $headers = ''; - foreach (OC_Util::$headers as $header) { - $headers .= '<' . \OCP\Util::sanitizeHTML($header['tag']); - if (strcasecmp($header['tag'], 'script') === 0 && in_array('src', array_map('strtolower', array_keys($header['attributes'])))) { - $headers .= ' defer'; - } - foreach ($header['attributes'] as $name => $value) { - $headers .= ' ' . \OCP\Util::sanitizeHTML($name) . '="' . \OCP\Util::sanitizeHTML($value) . '"'; - } - if ($header['text'] !== null) { - $headers .= '>' . \OCP\Util::sanitizeHTML($header['text']) . '</' . \OCP\Util::sanitizeHTML($header['tag']) . '>'; - } else { - $headers .= '/>'; - } - } - - $page->assign('headers', $headers); - - $page->assign('content', $data); - return $page->fetchPage($additionalParams); - } - - return $data; - } - - /** - * Include template - * - * @param string $file - * @param array|null $additionalParams - * @return string returns content of included template - * - * Includes another template. use <?php echo $this->inc('template'); ?> to - * do this. - */ - public function inc($file, $additionalParams = null) { - return $this->load($this->path . $file . '.php', $additionalParams); - } - - /** - * Shortcut to print a simple page for users - * @param string $application The application we render the template for - * @param string $name Name of the template - * @param array $parameters Parameters for the template - * @return boolean|null - */ - public static function printUserPage($application, $name, $parameters = []) { - $content = new OC_Template($application, $name, 'user'); - foreach ($parameters as $key => $value) { - $content->assign($key, $value); - } - print $content->printPage(); - } - - /** - * Shortcut to print a simple page for admins - * @param string $application The application we render the template for - * @param string $name Name of the template - * @param array $parameters Parameters for the template - * @return bool - */ - public static function printAdminPage($application, $name, $parameters = []) { - $content = new OC_Template($application, $name, 'admin'); - foreach ($parameters as $key => $value) { - $content->assign($key, $value); - } - return $content->printPage(); - } - +class OC_Template extends \OC\Template\Template { /** * Shortcut to print a simple page for guests * @param string $application The application we render the template for * @param string $name Name of the template - * @param array|string $parameters Parameters for the template + * @param array $parameters Parameters for the template * @return bool + * @deprecated 32.0.0 Use \OCP\Template\ITemplateManager instead */ public static function printGuestPage($application, $name, $parameters = []) { - $content = new OC_Template($application, $name, $name === 'error' ? $name : 'guest'); - foreach ($parameters as $key => $value) { - $content->assign($key, $value); - } - return $content->printPage(); + Server::get(ITemplateManager::class)->printGuestPage($application, $name, $parameters); + return true; } /** @@ -215,115 +31,21 @@ class OC_Template extends \OC\Template\Base { * @param string $error_msg The error message to show * @param string $hint An optional hint message - needs to be properly escape * @param int $statusCode - * @suppress PhanAccessMethodInternal + * @return never + * @deprecated 32.0.0 Use \OCP\Template\ITemplateManager instead */ public static function printErrorPage($error_msg, $hint = '', $statusCode = 500) { - if (\OC::$server->getAppManager()->isEnabledForUser('theming') && !\OC_App::isAppLoaded('theming')) { - \OC_App::loadApp('theming'); - } - - - if ($error_msg === $hint) { - // If the hint is the same as the message there is no need to display it twice. - $hint = ''; - } - $errors = [['error' => $error_msg, 'hint' => $hint]]; - - http_response_code($statusCode); - try { - // Try rendering themed html error page - $response = new TemplateResponse( - '', - 'error', - ['errors' => $errors], - TemplateResponse::RENDER_AS_ERROR, - $statusCode, - ); - $event = new BeforeTemplateRenderedEvent(false, $response); - \OC::$server->get(IEventDispatcher::class)->dispatchTyped($event); - print($response->render()); - } catch (\Throwable $e1) { - $logger = \OCP\Server::get(LoggerInterface::class); - $logger->error('Rendering themed error page failed. Falling back to un-themed error page.', [ - 'app' => 'core', - 'exception' => $e1, - ]); - - try { - // Try rendering unthemed html error page - $content = new \OC_Template('', 'error', 'error', false); - $content->assign('errors', $errors); - $content->printPage(); - } catch (\Exception $e2) { - // If nothing else works, fall back to plain text error page - $logger->error("$error_msg $hint", ['app' => 'core']); - $logger->error('Rendering un-themed error page failed. Falling back to plain text error page.', [ - 'app' => 'core', - 'exception' => $e2, - ]); - - header('Content-Type: text/plain; charset=utf-8'); - print("$error_msg $hint"); - } - } - die(); + Server::get(ITemplateManager::class)->printErrorPage($error_msg, $hint, $statusCode); } /** * print error page using Exception details * @param Exception|Throwable $exception * @param int $statusCode - * @return bool|string - * @suppress PhanAccessMethodInternal + * @return never + * @deprecated 32.0.0 Use \OCP\Template\ITemplateManager instead */ public static function printExceptionErrorPage($exception, $statusCode = 503) { - $debug = false; - http_response_code($statusCode); - try { - $debug = \OC::$server->getSystemConfig()->getValue('debug', false); - $serverLogsDocumentation = \OC::$server->getSystemConfig()->getValue('documentation_url.server_logs', ''); - $request = \OC::$server->getRequest(); - $content = new \OC_Template('', 'exception', 'error', false); - $content->assign('errorClass', get_class($exception)); - $content->assign('errorMsg', $exception->getMessage()); - $content->assign('errorCode', $exception->getCode()); - $content->assign('file', $exception->getFile()); - $content->assign('line', $exception->getLine()); - $content->assign('exception', $exception); - $content->assign('debugMode', $debug); - $content->assign('serverLogsDocumentation', $serverLogsDocumentation); - $content->assign('remoteAddr', $request->getRemoteAddress()); - $content->assign('requestID', $request->getId()); - $content->printPage(); - } catch (\Exception $e) { - try { - $logger = \OCP\Server::get(LoggerInterface::class); - $logger->error($exception->getMessage(), ['app' => 'core', 'exception' => $exception]); - $logger->error($e->getMessage(), ['app' => 'core', 'exception' => $e]); - } catch (Throwable $e) { - // no way to log it properly - but to avoid a white page of death we send some output - self::printPlainErrorPage($e, $debug); - - // and then throw it again to log it at least to the web server error log - throw $e; - } - - self::printPlainErrorPage($e, $debug); - } - die(); - } - - private static function printPlainErrorPage(\Throwable $exception, bool $debug = false) { - header('Content-Type: text/plain; charset=utf-8'); - print("Internal Server Error\n\n"); - print("The server encountered an internal error and was unable to complete your request.\n"); - print("Please contact the server administrator if this error reappears multiple times, please include the technical details below in your report.\n"); - print("More details can be found in the server log.\n"); - - if ($debug) { - print("\n"); - print($exception->getMessage() . ' ' . $exception->getFile() . ' at ' . $exception->getLine() . "\n"); - print($exception->getTraceAsString()); - } + Server::get(ITemplateManager::class)->printExceptionErrorPage($exception, $statusCode); } } diff --git a/lib/private/legacy/OC_User.php b/lib/private/legacy/OC_User.php index 4cc102d6672..115c1ccd03a 100644 --- a/lib/private/legacy/OC_User.php +++ b/lib/private/legacy/OC_User.php @@ -40,8 +40,6 @@ use Psr\Log\LoggerInterface; * logout() */ class OC_User { - private static $_usedBackends = []; - private static $_setupedBackends = []; // bool, stores if a user want to access a resource anonymously, e.g if they open a public link @@ -52,14 +50,13 @@ class OC_User { * * @param string|\OCP\UserInterface $backend default: database The backend to use for user management * @return bool + * @deprecated 32.0.0 Use IUserManager::registerBackend instead * * Set the User Authentication Module - * @suppress PhanDeprecatedFunction */ public static function useBackend($backend = 'database') { if ($backend instanceof \OCP\UserInterface) { - self::$_usedBackends[get_class($backend)] = $backend; - \OC::$server->getUserManager()->registerBackend($backend); + Server::get(IUserManager::class)->registerBackend($backend); } else { // You'll never know what happens if ($backend === null or !is_string($backend)) { @@ -72,18 +69,15 @@ class OC_User { case 'mysql': case 'sqlite': Server::get(LoggerInterface::class)->debug('Adding user backend ' . $backend . '.', ['app' => 'core']); - self::$_usedBackends[$backend] = new \OC\User\Database(); - \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]); + Server::get(IUserManager::class)->registerBackend(new \OC\User\Database()); break; case 'dummy': - self::$_usedBackends[$backend] = new \Test\Util\User\Dummy(); - \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]); + Server::get(IUserManager::class)->registerBackend(new \Test\Util\User\Dummy()); break; default: Server::get(LoggerInterface::class)->debug('Adding default user backend ' . $backend . '.', ['app' => 'core']); $className = 'OC_USER_' . strtoupper($backend); - self::$_usedBackends[$backend] = new $className(); - \OC::$server->getUserManager()->registerBackend(self::$_usedBackends[$backend]); + Server::get(IUserManager::class)->registerBackend(new $className()); break; } } @@ -92,10 +86,10 @@ class OC_User { /** * remove all used backends + * @deprecated 32.0.0 Use IUserManager::clearBackends instead */ public static function clearBackends() { - self::$_usedBackends = []; - \OC::$server->getUserManager()->clearBackends(); + Server::get(IUserManager::class)->clearBackends(); } /** @@ -248,7 +242,7 @@ class OC_User { */ public static function setUserId($uid) { $userSession = \OC::$server->getUserSession(); - $userManager = \OC::$server->getUserManager(); + $userManager = Server::get(IUserManager::class); if ($user = $userManager->get($uid)) { $userSession->setUser($user); } else { @@ -348,7 +342,7 @@ class OC_User { * Change the password of a user */ public static function setPassword($uid, $password, $recoveryPassword = null) { - $user = \OC::$server->getUserManager()->get($uid); + $user = Server::get(IUserManager::class)->get($uid); if ($user) { return $user->setPassword($password, $recoveryPassword); } else { @@ -364,7 +358,7 @@ class OC_User { * @deprecated 12.0.0 Use \OC::$server->getUserManager->getHome() */ public static function getHome($uid) { - $user = \OC::$server->getUserManager()->get($uid); + $user = Server::get(IUserManager::class)->get($uid); if ($user) { return $user->getHome(); } else { @@ -385,7 +379,7 @@ class OC_User { */ public static function getDisplayNames($search = '', $limit = null, $offset = null) { $displayNames = []; - $users = \OC::$server->getUserManager()->searchDisplayName($search, $limit, $offset); + $users = Server::get(IUserManager::class)->searchDisplayName($search, $limit, $offset); foreach ($users as $user) { $displayNames[$user->getUID()] = $user->getDisplayName(); } @@ -398,7 +392,7 @@ class OC_User { * @return OCP\Authentication\IApacheBackend|null if no backend active, otherwise OCP\Authentication\IApacheBackend */ private static function findFirstActiveUsedBackend() { - foreach (self::$_usedBackends as $backend) { + foreach (Server::get(IUserManager::class)->getBackends() as $backend) { if ($backend instanceof OCP\Authentication\IApacheBackend) { if ($backend->isSessionActive()) { return $backend; diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php index f82082d3d12..948dfcf7926 100644 --- a/lib/private/legacy/OC_Util.php +++ b/lib/private/legacy/OC_Util.php @@ -9,7 +9,6 @@ use bantu\IniGetWrapper\IniGetWrapper; use OC\Authentication\TwoFactorAuth\Manager as TwoFactorAuthManager; use OC\Files\SetupManager; use OCP\Files\Template\ITemplateManager; -use OCP\Http\Client\IClientService; use OCP\IConfig; use OCP\IGroupManager; use OCP\IURLGenerator; @@ -19,18 +18,13 @@ use OCP\Security\ISecureRandom; use OCP\Share\IManager; use Psr\Log\LoggerInterface; +/** + * @deprecated 32.0.0 Use \OCP\Util or any appropriate official API instead + */ class OC_Util { - public static $scripts = []; public static $styles = []; public static $headers = []; - /** @var array Local cache of version.php */ - private static $versionCache = null; - - protected static function getAppManager() { - return \OC::$server->getAppManager(); - } - /** * Setup the file system * @@ -63,8 +57,8 @@ class OC_Util { * Check if a password is required for each public link * * @param bool $checkGroupMembership Check group membership exclusion - * @return boolean - * @suppress PhanDeprecatedFunction + * @return bool + * @deprecated 32.0.0 use OCP\Share\IManager's shareApiLinkEnforcePassword directly */ public static function isPublicLinkPasswordRequired(bool $checkGroupMembership = true) { /** @var IManager $shareManager */ @@ -78,6 +72,7 @@ class OC_Util { * @param IGroupManager $groupManager * @param IUser|null $user * @return bool + * @deprecated 32.0.0 use OCP\Share\IManager's sharingDisabledForUser directly */ public static function isSharingDisabledForUser(IConfig $config, IGroupManager $groupManager, $user) { /** @var IManager $shareManager */ @@ -90,7 +85,7 @@ class OC_Util { * check if share API enforces a default expire date * * @return bool - * @suppress PhanDeprecatedFunction + * @deprecated 32.0.0 use OCP\Share\IManager's shareApiLinkDefaultExpireDateEnforced directly */ public static function isDefaultExpireDateEnforced() { /** @var IManager $shareManager */ @@ -103,6 +98,7 @@ class OC_Util { * * @param IUser|null $user * @return int|\OCP\Files\FileInfo::SPACE_UNLIMITED|false|float Quota bytes + * @deprecated 9.0.0 - Use \OCP\IUser::getQuota or \OCP\IUser::getQuotaBytes */ public static function getUserQuota(?IUser $user) { if (is_null($user)) { @@ -112,7 +108,7 @@ class OC_Util { if ($userQuota === 'none') { return \OCP\Files\FileInfo::SPACE_UNLIMITED; } - return OC_Helper::computerFileSize($userQuota); + return \OCP\Util::computerFileSize($userQuota); } /** @@ -191,14 +187,13 @@ class OC_Util { $child = $target->newFolder($file); self::copyr($source . '/' . $file, $child); } else { - $child = $target->newFile($file); $sourceStream = fopen($source . '/' . $file, 'r'); if ($sourceStream === false) { $logger->error(sprintf('Could not fopen "%s"', $source . '/' . $file), ['app' => 'core']); closedir($dir); return; } - $child->putContent($sourceStream); + $target->newFile($file, $sourceStream); } } } @@ -206,12 +201,10 @@ class OC_Util { } /** - * @return void - * @suppress PhanUndeclaredMethod + * @deprecated 32.0.0 Call tearDown directly on SetupManager */ - public static function tearDownFS() { - /** @var SetupManager $setupManager */ - $setupManager = \OC::$server->get(SetupManager::class); + public static function tearDownFS(): void { + $setupManager = \OCP\Server::get(SetupManager::class); $setupManager->tearDown(); } @@ -220,10 +213,9 @@ class OC_Util { * * @param string $application application to get the files from * @param string $directory directory within this application (css, js, vendor, etc) - * @param string $file the file inside of the above folder - * @return string the path + * @param ?string $file the file inside of the above folder */ - private static function generatePath($application, $directory, $file) { + private static function generatePath($application, $directory, $file): string { if (is_null($file)) { $file = $application; $application = ''; @@ -236,68 +228,14 @@ class OC_Util { } /** - * add a javascript file - * - * @deprecated 24.0.0 - Use \OCP\Util::addScript - * - * @param string $application application id - * @param string|null $file filename - * @param bool $prepend prepend the Script to the beginning of the list - * @return void - */ - public static function addScript($application, $file = null, $prepend = false) { - $path = OC_Util::generatePath($application, 'js', $file); - - // core js files need separate handling - if ($application !== 'core' && $file !== null) { - self::addTranslations($application); - } - self::addExternalResource($application, $prepend, $path, 'script'); - } - - /** - * add a javascript file from the vendor sub folder - * - * @param string $application application id - * @param string|null $file filename - * @param bool $prepend prepend the Script to the beginning of the list - * @return void - */ - public static function addVendorScript($application, $file = null, $prepend = false) { - $path = OC_Util::generatePath($application, 'vendor', $file); - self::addExternalResource($application, $prepend, $path, 'script'); - } - - /** - * add a translation JS file - * - * @deprecated 24.0.0 - * - * @param string $application application id - * @param string|null $languageCode language code, defaults to the current language - * @param bool|null $prepend prepend the Script to the beginning of the list - */ - public static function addTranslations($application, $languageCode = null, $prepend = false) { - if (is_null($languageCode)) { - $languageCode = \OC::$server->get(IFactory::class)->findLanguage($application); - } - if (!empty($application)) { - $path = "$application/l10n/$languageCode"; - } else { - $path = "l10n/$languageCode"; - } - self::addExternalResource($application, $prepend, $path, 'script'); - } - - /** * add a css file * * @param string $application application id * @param string|null $file filename * @param bool $prepend prepend the Style to the beginning of the list - * @return void + * @deprecated 32.0.0 Use \OCP\Util::addStyle */ - public static function addStyle($application, $file = null, $prepend = false) { + public static function addStyle($application, $file = null, $prepend = false): void { $path = OC_Util::generatePath($application, 'css', $file); self::addExternalResource($application, $prepend, $path, 'style'); } @@ -308,9 +246,9 @@ class OC_Util { * @param string $application application id * @param string|null $file filename * @param bool $prepend prepend the Style to the beginning of the list - * @return void + * @deprecated 32.0.0 */ - public static function addVendorStyle($application, $file = null, $prepend = false) { + public static function addVendorStyle($application, $file = null, $prepend = false): void { $path = OC_Util::generatePath($application, 'vendor', $file); self::addExternalResource($application, $prepend, $path, 'style'); } @@ -322,9 +260,8 @@ class OC_Util { * @param bool $prepend prepend the file to the beginning of the list * @param string $path * @param string $type (script or style) - * @return void */ - private static function addExternalResource($application, $prepend, $path, $type = 'script') { + private static function addExternalResource($application, $prepend, $path, $type = 'script'): void { if ($type === 'style') { if (!in_array($path, self::$styles)) { if ($prepend === true) { @@ -333,14 +270,6 @@ class OC_Util { self::$styles[] = $path; } } - } elseif ($type === 'script') { - if (!in_array($path, self::$scripts)) { - if ($prepend === true) { - array_unshift(self::$scripts, $path); - } else { - self::$scripts [] = $path; - } - } } } @@ -352,8 +281,9 @@ class OC_Util { * @param array $attributes array of attributes for the element * @param string $text the text content for the element * @param bool $prepend prepend the header to the beginning of the list + * @deprecated 32.0.0 Use \OCP\Util::addHeader instead */ - public static function addHeader($tag, $attributes, $text = null, $prepend = false) { + public static function addHeader($tag, $attributes, $text = null, $prepend = false): void { $header = [ 'tag' => $tag, 'attributes' => $attributes, @@ -369,7 +299,6 @@ class OC_Util { /** * check if the current server configuration is suitable for ownCloud * - * @param \OC\SystemConfig $config * @return array arrays with error messages and hints */ public static function checkServer(\OC\SystemConfig $config) { @@ -402,7 +331,7 @@ class OC_Util { } // Check if config folder is writable. - if (!OC_Helper::isReadOnlyConfigEnabled()) { + if (!(bool)$config->getValue('config_is_read_only', false)) { if (!is_writable(OC::$configDir) or !is_readable(OC::$configDir)) { $errors[] = [ 'error' => $l->t('Cannot write into "config" directory.'), @@ -550,8 +479,8 @@ class OC_Util { * TODO: Should probably be implemented in the above generic dependency * check somehow in the long-term. */ - if ($iniWrapper->getBool('mbstring.func_overload') !== null && - $iniWrapper->getBool('mbstring.func_overload') === true) { + if ($iniWrapper->getBool('mbstring.func_overload') !== null + && $iniWrapper->getBool('mbstring.func_overload') === true) { $errors[] = [ 'error' => $l->t('<code>mbstring.func_overload</code> is set to <code>%s</code> instead of the expected value <code>0</code>.', [$iniWrapper->getString('mbstring.func_overload')]), 'hint' => $l->t('To fix this issue set <code>mbstring.func_overload</code> to <code>0</code> in your php.ini.') @@ -592,6 +521,7 @@ class OC_Util { * * @param string $dataDirectory * @return array arrays with error messages and hints + * @internal */ public static function checkDataDirectoryPermissions($dataDirectory) { if (!\OC::$server->getConfig()->getSystemValueBool('check_data_directory_permissions', true)) { @@ -620,6 +550,7 @@ class OC_Util { * * @param string $dataDirectory data directory path * @return array errors found + * @internal */ public static function checkDataDirectoryValidity($dataDirectory) { $l = \OC::$server->getL10N('lib'); @@ -644,9 +575,9 @@ class OC_Util { * Check if the user is logged in, redirects to home if not. With * redirect URL parameter to the request URI. * - * @return void + * @deprecated 32.0.0 */ - public static function checkLoggedIn() { + public static function checkLoggedIn(): void { // Check if we are a user if (!\OC::$server->getUserSession()->isLoggedIn()) { header('Location: ' . \OC::$server->getURLGenerator()->linkToRoute( @@ -668,10 +599,10 @@ class OC_Util { /** * Check if the user is a admin, redirects to home if not * - * @return void + * @deprecated 32.0.0 */ - public static function checkAdminUser() { - OC_Util::checkLoggedIn(); + public static function checkAdminUser(): void { + self::checkLoggedIn(); if (!OC_User::isAdminUser(OC_User::getUser())) { header('Location: ' . \OCP\Util::linkToAbsolute('', 'index.php')); exit(); @@ -684,7 +615,7 @@ class OC_Util { * the apps visible for the current user * * @return string URL - * @suppress PhanDeprecatedFunction + * @deprecated 32.0.0 use IURLGenerator's linkToDefaultPageUrl directly */ public static function getDefaultPageUrl() { /** @var IURLGenerator $urlGenerator */ @@ -695,9 +626,9 @@ class OC_Util { /** * Redirect to the user default page * - * @return void + * @deprecated 32.0.0 */ - public static function redirectToDefaultPage() { + public static function redirectToDefaultPage(): void { $location = self::getDefaultPageUrl(); header('Location: ' . $location); exit(); @@ -708,7 +639,7 @@ class OC_Util { * * @return string */ - public static function getInstanceId() { + public static function getInstanceId(): string { $id = \OC::$server->getSystemConfig()->getValue('instanceid', null); if (is_null($id)) { // We need to guarantee at least one letter in instanceid so it can be used as the session_name @@ -725,11 +656,11 @@ class OC_Util { * string or array of strings before displaying it on a web page. * * @param string|string[] $value - * @return string|string[] an array of sanitized strings or a single sanitized string, depends on the input parameter. + * @return ($value is array ? string[] : string) + * @deprecated 32.0.0 use \OCP\Util::sanitizeHTML instead */ public static function sanitizeHTML($value) { if (is_array($value)) { - /** @var string[] $value */ $value = array_map(function ($value) { return self::sanitizeHTML($value); }, $value); @@ -749,6 +680,7 @@ class OC_Util { * * @param string $component part of URI to encode * @return string + * @deprecated 32.0.0 use \OCP\Util::encodePath instead */ public static function encodePath($component) { $encoded = rawurlencode($component); @@ -756,86 +688,6 @@ class OC_Util { return $encoded; } - - public function createHtaccessTestFile(\OCP\IConfig $config) { - // php dev server does not support htaccess - if (php_sapi_name() === 'cli-server') { - return false; - } - - // testdata - $fileName = '/htaccesstest.txt'; - $testContent = 'This is used for testing whether htaccess is properly enabled to disallow access from the outside. This file can be safely removed.'; - - // creating a test file - $testFile = $config->getSystemValueString('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName; - - if (file_exists($testFile)) {// already running this test, possible recursive call - return false; - } - - $fp = @fopen($testFile, 'w'); - if (!$fp) { - throw new \OCP\HintException('Can\'t create test file to check for working .htaccess file.', - 'Make sure it is possible for the web server to write to ' . $testFile); - } - fwrite($fp, $testContent); - fclose($fp); - - return $testContent; - } - - /** - * Check if the .htaccess file is working - * - * @param \OCP\IConfig $config - * @return bool - * @throws Exception - * @throws \OCP\HintException If the test file can't get written. - */ - public function isHtaccessWorking(\OCP\IConfig $config) { - if (\OC::$CLI || !$config->getSystemValueBool('check_for_working_htaccess', true)) { - return true; - } - - $testContent = $this->createHtaccessTestFile($config); - if ($testContent === false) { - return false; - } - - $fileName = '/htaccesstest.txt'; - $testFile = $config->getSystemValueString('datadirectory', OC::$SERVERROOT . '/data') . '/' . $fileName; - - // accessing the file via http - $url = \OC::$server->getURLGenerator()->getAbsoluteURL(OC::$WEBROOT . '/data' . $fileName); - try { - $content = \OC::$server->get(IClientService::class)->newClient()->get($url)->getBody(); - } catch (\Exception $e) { - $content = false; - } - - if (str_starts_with($url, 'https:')) { - $url = 'http:' . substr($url, 6); - } else { - $url = 'https:' . substr($url, 5); - } - - try { - $fallbackContent = \OC::$server->get(IClientService::class)->newClient()->get($url)->getBody(); - } catch (\Exception $e) { - $fallbackContent = false; - } - - // cleanup - @unlink($testFile); - - /* - * If the content is not equal to test content our .htaccess - * is working as required - */ - return $content !== $testContent && $fallbackContent !== $testContent; - } - /** * Check if current locale is non-UTF8 * @@ -855,9 +707,9 @@ class OC_Util { * Check if the setlocale call does not work. This can happen if the right * local packages are not available on the server. * - * @return bool + * @internal */ - public static function isSetLocaleWorking() { + public static function isSetLocaleWorking(): bool { if (self::isNonUTF8Locale()) { // Borrowed from \Patchwork\Utf8\Bootup::initLocale setlocale(LC_ALL, 'C.UTF-8', 'C'); @@ -875,9 +727,9 @@ class OC_Util { /** * Check if it's possible to get the inline annotations * - * @return bool + * @internal */ - public static function isAnnotationsWorking() { + public static function isAnnotationsWorking(): bool { if (PHP_VERSION_ID >= 80300) { /** @psalm-suppress UndefinedMethod */ $reflection = \ReflectionMethod::createFromMethodName(__METHOD__); @@ -892,9 +744,9 @@ class OC_Util { /** * Check if the PHP module fileinfo is loaded. * - * @return bool + * @internal */ - public static function fileInfoLoaded() { + public static function fileInfoLoaded(): bool { return function_exists('finfo_open'); } @@ -940,15 +792,15 @@ class OC_Util { * Normalize a unicode string * * @param string $value a not normalized string - * @return bool|string + * @return string The normalized string or the input if the normalization failed */ - public static function normalizeUnicode($value) { + public static function normalizeUnicode(string $value): string { if (Normalizer::isNormalized($value)) { return $value; } $normalizedValue = Normalizer::normalize($value); - if ($normalizedValue === null || $normalizedValue === false) { + if ($normalizedValue === false) { \OCP\Server::get(LoggerInterface::class)->warning('normalizing failed for "' . $value . '"', ['app' => 'core']); return $value; } @@ -964,6 +816,7 @@ class OC_Util { * @param \OC\SystemConfig $config * @return bool whether the core or any app needs an upgrade * @throws \OCP\HintException When the upgrade from the given version is not allowed + * @deprecated 32.0.0 Use \OCP\Util::needUpgrade instead */ public static function needUpgrade(\OC\SystemConfig $config) { if ($config->getValue('installed', false)) { diff --git a/lib/public/Accounts/IAccountManager.php b/lib/public/Accounts/IAccountManager.php index a15651eb5e6..92fc0002674 100644 --- a/lib/public/Accounts/IAccountManager.php +++ b/lib/public/Accounts/IAccountManager.php @@ -48,30 +48,6 @@ interface IAccountManager { public const SCOPE_PUBLISHED = 'v2-published'; /** - * Contact details only visible locally - * - * @since 15.0.0 - * @deprecated 21.0.1 - */ - public const VISIBILITY_PRIVATE = 'private'; - - /** - * Contact details visible on trusted federated servers. - * - * @since 15.0.0 - * @deprecated 21.0.1 - */ - public const VISIBILITY_CONTACTS_ONLY = 'contacts'; - - /** - * Contact details visible on trusted federated servers and in the public lookup server. - * - * @since 15.0.0 - * @deprecated 21.0.1 - */ - public const VISIBILITY_PUBLIC = 'public'; - - /** * The list of allowed scopes * * @since 25.0.0 @@ -81,9 +57,6 @@ interface IAccountManager { self::SCOPE_LOCAL, self::SCOPE_FEDERATED, self::SCOPE_PUBLISHED, - self::VISIBILITY_PRIVATE, - self::VISIBILITY_CONTACTS_ONLY, - self::VISIBILITY_PUBLIC, ]; /** @@ -98,6 +71,7 @@ interface IAccountManager { /** * @since 27.0.0 + * @deprecated 27.0.0 only added for backwards compatibility with provisioning_api UsersController::getCurrentUser */ public const PROPERTY_DISPLAYNAME_LEGACY = 'display-name'; diff --git a/lib/public/Accounts/PropertyDoesNotExistException.php b/lib/public/Accounts/PropertyDoesNotExistException.php index d0f10cdf12f..1d27ef1df30 100644 --- a/lib/public/Accounts/PropertyDoesNotExistException.php +++ b/lib/public/Accounts/PropertyDoesNotExistException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Activity/IEventMerger.php b/lib/public/Activity/IEventMerger.php index e9355c88004..5d0f691f2d4 100644 --- a/lib/public/Activity/IEventMerger.php +++ b/lib/public/Activity/IEventMerger.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Activity/IFilter.php b/lib/public/Activity/IFilter.php index 75d53650127..008de6f5bca 100644 --- a/lib/public/Activity/IFilter.php +++ b/lib/public/Activity/IFilter.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Activity/IProvider.php b/lib/public/Activity/IProvider.php index 17fffbb26e2..dec4e7ade64 100644 --- a/lib/public/Activity/IProvider.php +++ b/lib/public/Activity/IProvider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Activity/ISetting.php b/lib/public/Activity/ISetting.php index c5c5c523477..1304ab8c658 100644 --- a/lib/public/Activity/ISetting.php +++ b/lib/public/Activity/ISetting.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/App/AppPathNotFoundException.php b/lib/public/App/AppPathNotFoundException.php index 5e3ea7a9919..56d6571ea68 100644 --- a/lib/public/App/AppPathNotFoundException.php +++ b/lib/public/App/AppPathNotFoundException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/App/Events/AppUpdateEvent.php b/lib/public/App/Events/AppUpdateEvent.php index 344e7def080..2cf59ff7949 100644 --- a/lib/public/App/Events/AppUpdateEvent.php +++ b/lib/public/App/Events/AppUpdateEvent.php @@ -16,15 +16,13 @@ use OCP\EventDispatcher\Event; * @since 27.0.0 */ class AppUpdateEvent extends Event { - private string $appId; - /** * @since 27.0.0 */ - public function __construct(string $appId) { + public function __construct( + private readonly string $appId, + ) { parent::__construct(); - - $this->appId = $appId; } /** diff --git a/lib/public/App/IAppManager.php b/lib/public/App/IAppManager.php index 110bcacf396..20019ce1ffd 100644 --- a/lib/public/App/IAppManager.php +++ b/lib/public/App/IAppManager.php @@ -52,6 +52,14 @@ interface IAppManager { public function getAppVersion(string $appId, bool $useCache = true): string; /** + * Returns the installed version of all apps + * + * @return array<string, string> + * @since 32.0.0 + */ + public function getAppInstalledVersions(bool $onlyEnabled = false): array; + + /** * Returns the app icon or null if none is found * * @param string $appId @@ -79,10 +87,18 @@ interface IAppManager { * @param string $appId * @return bool * @since 8.0.0 + * @deprecated 32.0.0 Use either {@see self::isEnabledForUser} or {@see self::isEnabledForAnyone} */ public function isInstalled($appId); /** + * Check if an app is enabled in the instance, either for everyone or for specific groups + * + * @since 32.0.0 + */ + public function isEnabledForAnyone(string $appId): bool; + + /** * Check if an app should be enabled by default * * Notice: This actually checks if the app should be enabled by default @@ -168,7 +184,7 @@ interface IAppManager { * List all apps enabled for a user * * @param \OCP\IUser $user - * @return string[] + * @return list<string> * @since 8.1.0 */ public function getEnabledAppsForUser(IUser $user); @@ -178,10 +194,19 @@ interface IAppManager { * * @return string[] * @since 8.1.0 + * @deprecated 32.0.0 Use either {@see self::getEnabledApps} or {@see self::getEnabledAppsForUser} */ public function getInstalledApps(); /** + * List all apps enabled, either for everyone or for specific groups only + * + * @return list<string> + * @since 32.0.0 + */ + public function getEnabledApps(): array; + + /** * Clear the cached list of apps when enabling/disabling an app * @since 8.1.0 */ @@ -292,10 +317,17 @@ interface IAppManager { /** * Clean the appId from forbidden characters * + * @psalm-taint-escape callable + * @psalm-taint-escape cookie * @psalm-taint-escape file - * @psalm-taint-escape include - * @psalm-taint-escape html * @psalm-taint-escape has_quotes + * @psalm-taint-escape header + * @psalm-taint-escape html + * @psalm-taint-escape include + * @psalm-taint-escape ldap + * @psalm-taint-escape shell + * @psalm-taint-escape sql + * @psalm-taint-escape unserialize * * @since 31.0.0 */ diff --git a/lib/public/AppFramework/ApiController.php b/lib/public/AppFramework/ApiController.php index dae80456e26..729582c8505 100644 --- a/lib/public/AppFramework/ApiController.php +++ b/lib/public/AppFramework/ApiController.php @@ -58,9 +58,8 @@ abstract class ApiController extends Controller { #[PublicPage] #[NoAdminRequired] public function preflightedCors() { - if (isset($this->request->server['HTTP_ORIGIN'])) { - $origin = $this->request->server['HTTP_ORIGIN']; - } else { + $origin = $this->request->getHeader('origin'); + if ($origin === '') { $origin = '*'; } diff --git a/lib/public/AppFramework/App.php b/lib/public/AppFramework/App.php index 06404baea70..c00fde47418 100644 --- a/lib/public/AppFramework/App.php +++ b/lib/public/AppFramework/App.php @@ -9,10 +9,10 @@ declare(strict_types=1); */ namespace OCP\AppFramework; -use OC\AppFramework\Routing\RouteConfig; -use OC\Route\Router; +use OC\AppFramework\Utility\SimpleContainer; use OC\ServerContainer; -use OCP\Route\IRouter; +use OCP\IConfig; +use OCP\Server; use Psr\Log\LoggerInterface; /** @@ -47,7 +47,7 @@ class App { * @since 6.0.0 */ public function __construct(string $appName, array $urlParams = []) { - $runIsSetupDirectly = \OC::$server->getConfig()->getSystemValueBool('debug') + $runIsSetupDirectly = Server::get(IConfig::class)->getSystemValueBool('debug') && !ini_get('zend.exception_ignore_args'); if ($runIsSetupDirectly) { @@ -58,23 +58,30 @@ class App { $classNameParts = explode('\\', trim($applicationClassName, '\\')); foreach ($e->getTrace() as $step) { - if (isset($step['class'], $step['function'], $step['args'][0]) && - $step['class'] === ServerContainer::class && - $step['function'] === 'query' && - $step['args'][0] === $applicationClassName) { + if (isset($step['class'], $step['function'], $step['args'][0]) + && $step['class'] === ServerContainer::class + && $step['function'] === 'query' + && $step['args'][0] === $applicationClassName) { $setUpViaQuery = true; break; - } elseif (isset($step['class'], $step['function'], $step['args'][0]) && - $step['class'] === ServerContainer::class && - $step['function'] === 'getAppContainer' && - $step['args'][1] === $classNameParts[1]) { + } elseif (isset($step['class'], $step['function'], $step['args'][0]) + && $step['class'] === ServerContainer::class + && $step['function'] === 'getAppContainer' + && $step['args'][1] === $classNameParts[1]) { + $setUpViaQuery = true; + break; + } elseif (isset($step['class'], $step['function'], $step['args'][0]) + && $step['class'] === SimpleContainer::class + && preg_match('/{closure:OC\\\\AppFramework\\\\Utility\\\\SimpleContainer::buildClass\\(\\):\\d+}/', $step['function']) + && $step['args'][0] === $this) { + /* We are setup through a lazy ghost, fine */ $setUpViaQuery = true; break; } } if (!$setUpViaQuery && $applicationClassName !== \OCP\AppFramework\App::class) { - \OCP\Server::get(LoggerInterface::class)->error($e->getMessage(), [ + Server::get(LoggerInterface::class)->error($e->getMessage(), [ 'app' => $appName, 'exception' => $e, ]); @@ -97,35 +104,6 @@ class App { } /** - * This function is to be called to create single routes and restful routes based on the given $routes array. - * - * Example code in routes.php of tasks app (it will register two restful resources): - * $routes = array( - * 'resources' => array( - * 'lists' => array('url' => '/tasklists'), - * 'tasks' => array('url' => '/tasklists/{listId}/tasks') - * ) - * ); - * - * $a = new TasksApp(); - * $a->registerRoutes($this, $routes); - * - * @param \OCP\Route\IRouter $router - * @param array $routes - * @since 6.0.0 - * @suppress PhanAccessMethodInternal - * @deprecated 20.0.0 Just return an array from your routes.php - */ - public function registerRoutes(IRouter $router, array $routes) { - if (!($router instanceof Router)) { - throw new \RuntimeException('Can only setup routes with real router'); - } - - $routeConfig = new RouteConfig($this->container, $router, $routes); - $routeConfig->register(); - } - - /** * This function is called by the routing component to fire up the frameworks dispatch mechanism. * * Example code in routes.php of the task app: diff --git a/lib/public/AppFramework/Bootstrap/IBootstrap.php b/lib/public/AppFramework/Bootstrap/IBootstrap.php index 81c34524191..7260d2b77a1 100644 --- a/lib/public/AppFramework/Bootstrap/IBootstrap.php +++ b/lib/public/AppFramework/Bootstrap/IBootstrap.php @@ -25,8 +25,6 @@ interface IBootstrap { * At this stage you can assume that all services are registered and the DI * container(s) are ready to be queried. * - * This is also the state where an optional `appinfo/app.php` was loaded. - * * @param IBootContext $context * * @since 20.0.0 diff --git a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php index b9e5413e5c2..011d1520414 100644 --- a/lib/public/AppFramework/Bootstrap/IRegistrationContext.php +++ b/lib/public/AppFramework/Bootstrap/IRegistrationContext.php @@ -415,6 +415,19 @@ interface IRegistrationContext { public function registerTaskProcessingTaskType(string $taskProcessingTaskTypeClass): void; /** + * Register an implementation of \OCP\Files\Conversion\IConversionProvider + * that will handle the conversion of files from one MIME type to another + * + * @param string $class + * @psalm-param class-string<\OCP\Files\Conversion\IConversionProvider> $class + * + * @return void + * + * @since 31.0.0 + */ + public function registerFileConversionProvider(string $class): void; + + /** * Register a mail provider * * @param string $class @@ -423,4 +436,15 @@ interface IRegistrationContext { */ public function registerMailProvider(string $class): void; + + /** + * Register an implementation of \OCP\Config\Lexicon\IConfigLexicon that + * will handle the config lexicon + * + * @param string $configLexiconClass + * + * @psalm-param class-string<\NCU\Config\Lexicon\IConfigLexicon> $configLexiconClass + * @since 31.0.0 + */ + public function registerConfigLexicon(string $configLexiconClass): void; } diff --git a/lib/public/AppFramework/Controller.php b/lib/public/AppFramework/Controller.php index 7c25b3382e7..cdeaac99366 100644 --- a/lib/public/AppFramework/Controller.php +++ b/lib/public/AppFramework/Controller.php @@ -135,7 +135,7 @@ abstract class Controller { return $responder($response); } - throw new \DomainException('No responder registered for format ' . - $format . '!'); + throw new \DomainException('No responder registered for format ' + . $format . '!'); } } diff --git a/lib/public/AppFramework/Db/Entity.php b/lib/public/AppFramework/Db/Entity.php index d90d3ed4837..3094070af5f 100644 --- a/lib/public/AppFramework/Db/Entity.php +++ b/lib/public/AppFramework/Db/Entity.php @@ -159,8 +159,8 @@ abstract class Entity { if (property_exists($this, $name)) { return $this->$name; } else { - throw new \BadFunctionCallException($name . - ' is not a valid attribute'); + throw new \BadFunctionCallException($name + . ' is not a valid attribute'); } } @@ -180,8 +180,8 @@ abstract class Entity { } elseif ($this->isGetterForBoolProperty($methodName)) { return $this->getter(lcfirst(substr($methodName, 2))); } else { - throw new \BadFunctionCallException($methodName . - ' does not exist'); + throw new \BadFunctionCallException($methodName + . ' does not exist'); } } @@ -215,7 +215,7 @@ abstract class Entity { * @return string the property name * @since 7.0.0 */ - public function columnToProperty(string $columnName): string { + public function columnToProperty(string $columnName) { $parts = explode('_', $columnName); $property = ''; diff --git a/lib/public/AppFramework/Db/QBMapper.php b/lib/public/AppFramework/Db/QBMapper.php index 4071a4a47a4..7fb5b2a9afd 100644 --- a/lib/public/AppFramework/Db/QBMapper.php +++ b/lib/public/AppFramework/Db/QBMapper.php @@ -296,8 +296,8 @@ abstract class QBMapper { * @since 14.0.0 */ private function buildDebugMessage(string $msg, IQueryBuilder $sql): string { - return $msg . - ': query "' . $sql->getSQL() . '"; '; + return $msg + . ': query "' . $sql->getSQL() . '"; '; } diff --git a/lib/public/AppFramework/Http/Attribute/CORS.php b/lib/public/AppFramework/Http/Attribute/CORS.php index 2c3eac362cf..ff639635635 100644 --- a/lib/public/AppFramework/Http/Attribute/CORS.php +++ b/lib/public/AppFramework/Http/Attribute/CORS.php @@ -12,7 +12,9 @@ namespace OCP\AppFramework\Http\Attribute; use Attribute; /** - * Attribute for controller methods that can also be accessed by not logged-in user + * Attribute for controller methods that can also be accessed by other websites. + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS for an explanation of the functionality and the security implications. + * See https://docs.nextcloud.com/server/latest/developer_manual/digging_deeper/rest_apis.html on how to implement it in your controller. * * @since 27.0.0 */ diff --git a/lib/public/AppFramework/Http/Attribute/RequestHeader.php b/lib/public/AppFramework/Http/Attribute/RequestHeader.php new file mode 100644 index 00000000000..1d0fbbfa0c3 --- /dev/null +++ b/lib/public/AppFramework/Http/Attribute/RequestHeader.php @@ -0,0 +1,34 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\AppFramework\Http\Attribute; + +use Attribute; + +/** + * This attribute allows documenting request headers and is primarily intended for OpenAPI documentation. + * It should be added whenever you use a request header in a controller method, in order to properly describe the header and its functionality. + * There are no checks that ensure the header is set, so you will still need to do this yourself in the controller method. + * + * @since 32.0.0 + */ +#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] +class RequestHeader { + /** + * @param lowercase-string $name The name of the request header + * @param non-empty-string $description The description of the request header + * @param bool $indirect Allow indirect usage of the header for example in a middleware. Enabling this turns off the check which ensures that the header must be referenced in the controller method. + */ + public function __construct( + protected string $name, + protected string $description, + protected bool $indirect = false, + ) { + } +} diff --git a/lib/public/AppFramework/Http/DataDisplayResponse.php b/lib/public/AppFramework/Http/DataDisplayResponse.php index 889c57a7901..e1ded910328 100644 --- a/lib/public/AppFramework/Http/DataDisplayResponse.php +++ b/lib/public/AppFramework/Http/DataDisplayResponse.php @@ -13,9 +13,9 @@ use OCP\AppFramework\Http; * Class DataDisplayResponse * * @since 8.1.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class DataDisplayResponse extends Response { /** diff --git a/lib/public/AppFramework/Http/DataDownloadResponse.php b/lib/public/AppFramework/Http/DataDownloadResponse.php index 80100137c48..ee6bcf0d0c5 100644 --- a/lib/public/AppFramework/Http/DataDownloadResponse.php +++ b/lib/public/AppFramework/Http/DataDownloadResponse.php @@ -13,10 +13,10 @@ use OCP\AppFramework\Http; * Class DataDownloadResponse * * @since 8.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template C of string * @template H of array<string, mixed> - * @template-extends DownloadResponse<int, string, array<string, mixed>> + * @template-extends DownloadResponse<Http::STATUS_*, string, array<string, mixed>> */ class DataDownloadResponse extends DownloadResponse { /** diff --git a/lib/public/AppFramework/Http/DataResponse.php b/lib/public/AppFramework/Http/DataResponse.php index 2ebb66f9e73..2b54ce848ef 100644 --- a/lib/public/AppFramework/Http/DataResponse.php +++ b/lib/public/AppFramework/Http/DataResponse.php @@ -14,10 +14,10 @@ use OCP\AppFramework\Http; * for responders to transform * @since 8.0.0 * @psalm-type DataResponseType = array|int|float|string|bool|object|null|\stdClass|\JsonSerializable - * @template S of int + * @template S of Http::STATUS_* * @template-covariant T of DataResponseType * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class DataResponse extends Response { /** diff --git a/lib/public/AppFramework/Http/DownloadResponse.php b/lib/public/AppFramework/Http/DownloadResponse.php index 058b3070297..190de022d36 100644 --- a/lib/public/AppFramework/Http/DownloadResponse.php +++ b/lib/public/AppFramework/Http/DownloadResponse.php @@ -12,10 +12,10 @@ use OCP\AppFramework\Http; /** * Prompts the user to download the a file * @since 7.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template C of string * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class DownloadResponse extends Response { /** diff --git a/lib/public/AppFramework/Http/FileDisplayResponse.php b/lib/public/AppFramework/Http/FileDisplayResponse.php index 0cc51f7c59f..c18404b7d91 100644 --- a/lib/public/AppFramework/Http/FileDisplayResponse.php +++ b/lib/public/AppFramework/Http/FileDisplayResponse.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -13,9 +14,9 @@ use OCP\Files\SimpleFS\ISimpleFile; * Class FileDisplayResponse * * @since 11.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class FileDisplayResponse extends Response implements ICallbackResponse { /** @var File|ISimpleFile */ diff --git a/lib/public/AppFramework/Http/JSONResponse.php b/lib/public/AppFramework/Http/JSONResponse.php index afe36c4a8c3..a226e29a1b5 100644 --- a/lib/public/AppFramework/Http/JSONResponse.php +++ b/lib/public/AppFramework/Http/JSONResponse.php @@ -12,10 +12,10 @@ use OCP\AppFramework\Http; /** * A renderer for JSON calls * @since 6.0.0 - * @template S of int - * @template-covariant T of array|object|\stdClass|\JsonSerializable + * @template S of Http::STATUS_* + * @template-covariant T of null|string|int|float|bool|array|\stdClass|\JsonSerializable * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class JSONResponse extends Response { /** @@ -58,6 +58,9 @@ class JSONResponse extends Response { * @return string the rendered json * @since 6.0.0 * @throws \Exception If data could not get encoded + * + * @psalm-taint-escape has_quotes + * @psalm-taint-escape html */ public function render() { return json_encode($this->data, JSON_HEX_TAG | JSON_THROW_ON_ERROR | $this->encodeFlags, 2048); diff --git a/lib/public/AppFramework/Http/NotFoundResponse.php b/lib/public/AppFramework/Http/NotFoundResponse.php index 9ebefe69be1..137d1a26655 100644 --- a/lib/public/AppFramework/Http/NotFoundResponse.php +++ b/lib/public/AppFramework/Http/NotFoundResponse.php @@ -12,9 +12,9 @@ use OCP\AppFramework\Http; /** * A generic 404 response showing an 404 error page as well to the end-user * @since 8.1.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends TemplateResponse<int, array<string, mixed>> + * @template-extends TemplateResponse<Http::STATUS_*, array<string, mixed>> */ class NotFoundResponse extends TemplateResponse { /** diff --git a/lib/public/AppFramework/Http/RedirectResponse.php b/lib/public/AppFramework/Http/RedirectResponse.php index 41fc4d83856..74847205976 100644 --- a/lib/public/AppFramework/Http/RedirectResponse.php +++ b/lib/public/AppFramework/Http/RedirectResponse.php @@ -12,9 +12,9 @@ use OCP\AppFramework\Http; /** * Redirects to a different URL * @since 7.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class RedirectResponse extends Response { private $redirectURL; diff --git a/lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php b/lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php index 3e2fcf6f6c7..0a0c04f671d 100644 --- a/lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php +++ b/lib/public/AppFramework/Http/RedirectToDefaultAppResponse.php @@ -16,9 +16,9 @@ use OCP\IURLGenerator; * * @since 16.0.0 * @deprecated 23.0.0 Use RedirectResponse() with IURLGenerator::linkToDefaultPageUrl() instead - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends RedirectResponse<int, array<string, mixed>> + * @template-extends RedirectResponse<Http::STATUS_*, array<string, mixed>> */ class RedirectToDefaultAppResponse extends RedirectResponse { /** @@ -30,8 +30,7 @@ class RedirectToDefaultAppResponse extends RedirectResponse { * @deprecated 23.0.0 Use RedirectResponse() with IURLGenerator::linkToDefaultPageUrl() instead */ public function __construct(int $status = Http::STATUS_SEE_OTHER, array $headers = []) { - /** @var IURLGenerator $urlGenerator */ - $urlGenerator = \OC::$server->get(IURLGenerator::class); + $urlGenerator = \OCP\Server::get(IURLGenerator::class); parent::__construct($urlGenerator->linkToDefaultPageUrl(), $status, $headers); } } diff --git a/lib/public/AppFramework/Http/Response.php b/lib/public/AppFramework/Http/Response.php index d1860402359..bdebb12c00d 100644 --- a/lib/public/AppFramework/Http/Response.php +++ b/lib/public/AppFramework/Http/Response.php @@ -18,7 +18,7 @@ use Psr\Log\LoggerInterface; * * It handles headers, HTTP status code, last modified and ETag. * @since 6.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> */ class Response { @@ -93,11 +93,10 @@ class Response { // Set expires header $expires = new \DateTime(); - /** @var ITimeFactory $time */ $time = \OCP\Server::get(ITimeFactory::class); $expires->setTimestamp($time->getTime()); $expires->add(new \DateInterval('PT' . $cacheSeconds . 'S')); - $this->addHeader('Expires', $expires->format(\DateTimeInterface::RFC2822)); + $this->addHeader('Expires', $expires->format(\DateTimeInterface::RFC7231)); } else { $this->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); unset($this->headers['Expires']); @@ -184,10 +183,10 @@ class Response { if ($this->status === Http::STATUS_NOT_MODIFIED && stripos($name, 'x-') === 0) { /** @var IConfig $config */ - $config = \OC::$server->get(IConfig::class); + $config = \OCP\Server::get(IConfig::class); if ($config->getSystemValueBool('debug', false)) { - \OC::$server->get(LoggerInterface::class)->error('Setting custom header on a 304 is not supported (Header: {header})', [ + \OCP\Server::get(LoggerInterface::class)->error('Setting custom header on a 304 is not supported (Header: {header})', [ 'header' => $name, ]); } @@ -229,7 +228,7 @@ class Response { /** * @psalm-suppress UndefinedClass */ - $request = \OC::$server->get(IRequest::class); + $request = \OCP\Server::get(IRequest::class); $mergeWith = [ 'X-Request-Id' => $request->getId(), 'Cache-Control' => 'no-cache, no-store, must-revalidate', @@ -239,7 +238,7 @@ class Response { ]; if ($this->lastModified) { - $mergeWith['Last-Modified'] = $this->lastModified->format(\DateTimeInterface::RFC2822); + $mergeWith['Last-Modified'] = $this->lastModified->format(\DateTimeInterface::RFC7231); } if ($this->ETag) { diff --git a/lib/public/AppFramework/Http/StandaloneTemplateResponse.php b/lib/public/AppFramework/Http/StandaloneTemplateResponse.php index f729bd772fb..244a6b80f9f 100644 --- a/lib/public/AppFramework/Http/StandaloneTemplateResponse.php +++ b/lib/public/AppFramework/Http/StandaloneTemplateResponse.php @@ -7,6 +7,8 @@ declare(strict_types=1); */ namespace OCP\AppFramework\Http; +use OCP\AppFramework\Http; + /** * A template response that does not emit the loadAdditionalScripts events. * @@ -14,9 +16,9 @@ namespace OCP\AppFramework\Http; * full nextcloud UI. Like the 2FA page, or the grant page in the login flow. * * @since 16.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends TemplateResponse<int, array<string, mixed>> + * @template-extends TemplateResponse<Http::STATUS_*, array<string, mixed>> */ class StandaloneTemplateResponse extends TemplateResponse { } diff --git a/lib/public/AppFramework/Http/StreamResponse.php b/lib/public/AppFramework/Http/StreamResponse.php index 1039e20e5c5..d0e6e3e148a 100644 --- a/lib/public/AppFramework/Http/StreamResponse.php +++ b/lib/public/AppFramework/Http/StreamResponse.php @@ -13,9 +13,9 @@ use OCP\AppFramework\Http; * Class StreamResponse * * @since 8.1.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class StreamResponse extends Response implements ICallbackResponse { /** @var string */ diff --git a/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php b/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php index 4f958a2620c..281bb559a10 100644 --- a/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php +++ b/lib/public/AppFramework/Http/Template/ExternalShareMenuAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/Http/Template/IMenuAction.php b/lib/public/AppFramework/Http/Template/IMenuAction.php index 50b346add86..124e95fe019 100644 --- a/lib/public/AppFramework/Http/Template/IMenuAction.php +++ b/lib/public/AppFramework/Http/Template/IMenuAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/Http/Template/LinkMenuAction.php b/lib/public/AppFramework/Http/Template/LinkMenuAction.php index 6ae1fcdf13b..391802a1dce 100644 --- a/lib/public/AppFramework/Http/Template/LinkMenuAction.php +++ b/lib/public/AppFramework/Http/Template/LinkMenuAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php b/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php index 1000f4db549..4c156cdecea 100644 --- a/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php +++ b/lib/public/AppFramework/Http/Template/PublicTemplateResponse.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -15,8 +16,8 @@ use OCP\IInitialStateService; * * @since 14.0.0 * @template H of array<string, mixed> - * @template S of int - * @template-extends TemplateResponse<int, array<string, mixed>> + * @template S of Http::STATUS_* + * @template-extends TemplateResponse<Http::STATUS_*, array<string, mixed>> */ class PublicTemplateResponse extends TemplateResponse { private $headerTitle = ''; @@ -44,6 +45,7 @@ class PublicTemplateResponse extends TemplateResponse { ) { parent::__construct($appName, $templateName, $params, 'public', $status, $headers); \OCP\Util::addScript('core', 'public-page-menu'); + \OCP\Util::addScript('core', 'public-page-user-menu'); $state = \OCP\Server::get(IInitialStateService::class); $state->provideLazyInitialState('core', 'public-page-menu', function () { diff --git a/lib/public/AppFramework/Http/Template/SimpleMenuAction.php b/lib/public/AppFramework/Http/Template/SimpleMenuAction.php index 4cbbd5302d7..03cb9b4c7ea 100644 --- a/lib/public/AppFramework/Http/Template/SimpleMenuAction.php +++ b/lib/public/AppFramework/Http/Template/SimpleMenuAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/Http/TemplateResponse.php b/lib/public/AppFramework/Http/TemplateResponse.php index 2c7567c080b..af37a1a2313 100644 --- a/lib/public/AppFramework/Http/TemplateResponse.php +++ b/lib/public/AppFramework/Http/TemplateResponse.php @@ -1,21 +1,27 @@ <?php +declare(strict_types=1); + + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ + namespace OCP\AppFramework\Http; use OCP\AppFramework\Http; +use OCP\Server; +use OCP\Template\ITemplateManager; /** * Response for a normal template * @since 6.0.0 * - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class TemplateResponse extends Response { /** @@ -180,7 +186,7 @@ class TemplateResponse extends Response { $renderAs = $this->renderAs; } - $template = new \OCP\Template($this->appName, $this->templateName, $renderAs); + $template = Server::get(ITemplateManager::class)->getTemplate($this->appName, $this->templateName, $renderAs); foreach ($this->params as $key => $value) { $template->assign($key, $value); diff --git a/lib/public/AppFramework/Http/TextPlainResponse.php b/lib/public/AppFramework/Http/TextPlainResponse.php index e7c728c37ab..9dfa2c5544d 100644 --- a/lib/public/AppFramework/Http/TextPlainResponse.php +++ b/lib/public/AppFramework/Http/TextPlainResponse.php @@ -12,9 +12,9 @@ use OCP\AppFramework\Http; /** * A renderer for text responses * @since 22.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class TextPlainResponse extends Response { /** @var string */ diff --git a/lib/public/AppFramework/Http/TooManyRequestsResponse.php b/lib/public/AppFramework/Http/TooManyRequestsResponse.php index b7b0a98c9e1..f7084ec768d 100644 --- a/lib/public/AppFramework/Http/TooManyRequestsResponse.php +++ b/lib/public/AppFramework/Http/TooManyRequestsResponse.php @@ -8,14 +8,15 @@ declare(strict_types=1); namespace OCP\AppFramework\Http; use OCP\AppFramework\Http; -use OCP\Template; +use OCP\Server; +use OCP\Template\ITemplateManager; /** * A generic 429 response showing an 404 error page as well to the end-user * @since 19.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class TooManyRequestsResponse extends Response { /** @@ -34,7 +35,7 @@ class TooManyRequestsResponse extends Response { * @since 19.0.0 */ public function render() { - $template = new Template('core', '429', 'blank'); + $template = Server::get(ITemplateManager::class)->getTemplate('core', '429', TemplateResponse::RENDER_AS_BLANK); return $template->fetchPage(); } } diff --git a/lib/public/AppFramework/Http/ZipResponse.php b/lib/public/AppFramework/Http/ZipResponse.php index 3b9e251d332..a552eb1294f 100644 --- a/lib/public/AppFramework/Http/ZipResponse.php +++ b/lib/public/AppFramework/Http/ZipResponse.php @@ -15,9 +15,9 @@ use OCP\IRequest; * Public library to send several files in one zip archive. * * @since 15.0.0 - * @template S of int + * @template S of Http::STATUS_* * @template H of array<string, mixed> - * @template-extends Response<int, array<string, mixed>> + * @template-extends Response<Http::STATUS_*, array<string, mixed>> */ class ZipResponse extends Response implements ICallbackResponse { /** @var array{internalName: string, resource: resource, size: int, time: int}[] Files to be added to the zip response */ diff --git a/lib/public/AppFramework/OCS/OCSBadRequestException.php b/lib/public/AppFramework/OCS/OCSBadRequestException.php index c229468fb0d..77b8ec6c86d 100644 --- a/lib/public/AppFramework/OCS/OCSBadRequestException.php +++ b/lib/public/AppFramework/OCS/OCSBadRequestException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/OCS/OCSException.php b/lib/public/AppFramework/OCS/OCSException.php index 962bad830e7..02901992f8d 100644 --- a/lib/public/AppFramework/OCS/OCSException.php +++ b/lib/public/AppFramework/OCS/OCSException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/OCS/OCSForbiddenException.php b/lib/public/AppFramework/OCS/OCSForbiddenException.php index 03b1db6104f..0d001377043 100644 --- a/lib/public/AppFramework/OCS/OCSForbiddenException.php +++ b/lib/public/AppFramework/OCS/OCSForbiddenException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/OCS/OCSNotFoundException.php b/lib/public/AppFramework/OCS/OCSNotFoundException.php index 997b0c390f9..67cea9ed759 100644 --- a/lib/public/AppFramework/OCS/OCSNotFoundException.php +++ b/lib/public/AppFramework/OCS/OCSNotFoundException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/OCS/OCSPreconditionFailedException.php b/lib/public/AppFramework/OCS/OCSPreconditionFailedException.php index 2e67263bcb9..4fc2820eaec 100644 --- a/lib/public/AppFramework/OCS/OCSPreconditionFailedException.php +++ b/lib/public/AppFramework/OCS/OCSPreconditionFailedException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/AppFramework/PublicShareController.php b/lib/public/AppFramework/PublicShareController.php index 458606455d1..999b3827565 100644 --- a/lib/public/AppFramework/PublicShareController.php +++ b/lib/public/AppFramework/PublicShareController.php @@ -98,8 +98,8 @@ abstract class PublicShareController extends Controller { } // If we are authenticated properly - if ($this->session->get('public_link_authenticated_token') === $this->getToken() && - $this->session->get('public_link_authenticated_password_hash') === $this->getPasswordHash()) { + if ($this->session->get('public_link_authenticated_token') === $this->getToken() + && $this->session->get('public_link_authenticated_password_hash') === $this->getPasswordHash()) { return true; } diff --git a/lib/public/AppFramework/Services/IInitialState.php b/lib/public/AppFramework/Services/IInitialState.php index 24698108d68..ac58bcad3cc 100644 --- a/lib/public/AppFramework/Services/IInitialState.php +++ b/lib/public/AppFramework/Services/IInitialState.php @@ -37,7 +37,7 @@ interface IInitialState { * * @param string $key * @param Closure $closure returns a primitive or an object that implements JsonSerializable - * @psalm-param Closure():bool|Closure():int|Closure():float|Closure():string|Closure():\JsonSerializable $closure + * @psalm-param Closure():bool|Closure():int|Closure():float|Closure():string|Closure():array|Closure():\JsonSerializable $closure */ public function provideLazyInitialState(string $key, Closure $closure): void; } diff --git a/lib/public/Authentication/Events/AnyLoginFailedEvent.php b/lib/public/Authentication/Events/AnyLoginFailedEvent.php index fce12e04b8d..e39a39372cb 100644 --- a/lib/public/Authentication/Events/AnyLoginFailedEvent.php +++ b/lib/public/Authentication/Events/AnyLoginFailedEvent.php @@ -31,12 +31,20 @@ class AnyLoginFailedEvent extends Event { /** * @since 26.0.0 + * @deprecated 31.0.0 Use getLoginName() instead */ public function geLoginName(): string { return $this->loginName; } /** + * @since 31.0.0 + */ + public function getLoginName(): string { + return $this->loginName; + } + + /** * @since 26.0.0 */ public function getPassword(): ?string { diff --git a/lib/public/Authentication/Exceptions/CredentialsUnavailableException.php b/lib/public/Authentication/Exceptions/CredentialsUnavailableException.php index 835fd1eac9d..6ca8e68ed95 100644 --- a/lib/public/Authentication/Exceptions/CredentialsUnavailableException.php +++ b/lib/public/Authentication/Exceptions/CredentialsUnavailableException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Authentication/Exceptions/PasswordUnavailableException.php b/lib/public/Authentication/Exceptions/PasswordUnavailableException.php index 6a425f4ddd9..89e254e8ba1 100644 --- a/lib/public/Authentication/Exceptions/PasswordUnavailableException.php +++ b/lib/public/Authentication/Exceptions/PasswordUnavailableException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Authentication/IProvideUserSecretBackend.php b/lib/public/Authentication/IProvideUserSecretBackend.php index c005f6c9d59..dfab35c5f48 100644 --- a/lib/public/Authentication/IProvideUserSecretBackend.php +++ b/lib/public/Authentication/IProvideUserSecretBackend.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-only diff --git a/lib/public/Authentication/LoginCredentials/ICredentials.php b/lib/public/Authentication/LoginCredentials/ICredentials.php index a1c802f73b0..9848bbbe821 100644 --- a/lib/public/Authentication/LoginCredentials/ICredentials.php +++ b/lib/public/Authentication/LoginCredentials/ICredentials.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Authentication/TwoFactorAuth/ILoginSetupProvider.php b/lib/public/Authentication/TwoFactorAuth/ILoginSetupProvider.php index 84b0a9066f2..32ede4f385c 100644 --- a/lib/public/Authentication/TwoFactorAuth/ILoginSetupProvider.php +++ b/lib/public/Authentication/TwoFactorAuth/ILoginSetupProvider.php @@ -8,16 +8,15 @@ declare(strict_types=1); */ namespace OCP\Authentication\TwoFactorAuth; -use OCP\Template; +use OCP\Template\ITemplate; /** * @since 17.0.0 */ interface ILoginSetupProvider { /** - * @return Template - * * @since 17.0.0 + * @since 32.0.0 Broader return type ITemplate instead of \OCP\Template */ - public function getBody(): Template; + public function getBody(): ITemplate; } diff --git a/lib/public/Authentication/TwoFactorAuth/IPersonalProviderSettings.php b/lib/public/Authentication/TwoFactorAuth/IPersonalProviderSettings.php index 610f299c526..3cf7946272e 100644 --- a/lib/public/Authentication/TwoFactorAuth/IPersonalProviderSettings.php +++ b/lib/public/Authentication/TwoFactorAuth/IPersonalProviderSettings.php @@ -6,9 +6,10 @@ declare(strict_types=1); * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + namespace OCP\Authentication\TwoFactorAuth; -use OCP\Template; +use OCP\Template\ITemplate; /** * Interface IPersonalProviderSettings @@ -17,9 +18,8 @@ use OCP\Template; */ interface IPersonalProviderSettings { /** - * @return Template - * * @since 15.0.0 + * @since 32.0.0 Broader return type ITemplate instead of \OCP\Template */ - public function getBody(): Template; + public function getBody(): ITemplate; } diff --git a/lib/public/Authentication/TwoFactorAuth/IProvider.php b/lib/public/Authentication/TwoFactorAuth/IProvider.php index f1dd24ff0a2..27c4121f4ac 100644 --- a/lib/public/Authentication/TwoFactorAuth/IProvider.php +++ b/lib/public/Authentication/TwoFactorAuth/IProvider.php @@ -9,7 +9,7 @@ declare(strict_types=1); namespace OCP\Authentication\TwoFactorAuth; use OCP\IUser; -use OCP\Template; +use OCP\Template\ITemplate; /** * @since 9.1.0 @@ -50,11 +50,9 @@ interface IProvider { * Get the template for rending the 2FA provider view * * @since 9.1.0 - * - * @param IUser $user - * @return Template + * @since 32.0.0 Broader return type ITemplate instead of \OCP\Template. */ - public function getTemplate(IUser $user): Template; + public function getTemplate(IUser $user): ITemplate; /** * Verify the given challenge diff --git a/lib/public/BackgroundJob/TimedJob.php b/lib/public/BackgroundJob/TimedJob.php index 85ca34665b4..486c03c5fda 100644 --- a/lib/public/BackgroundJob/TimedJob.php +++ b/lib/public/BackgroundJob/TimedJob.php @@ -33,6 +33,15 @@ abstract class TimedJob extends Job { } /** + * Get the interval [seconds] for the job + * + * @since 32.0.0 + */ + public function getInterval(): int { + return $this->interval; + } + + /** * Whether the background job is time sensitive and needs to run soon after * the scheduled interval, of if it is okay to be delayed until a later time. * @@ -54,8 +63,8 @@ abstract class TimedJob extends Job { * @since 24.0.0 */ public function setTimeSensitivity(int $sensitivity): void { - if ($sensitivity !== self::TIME_SENSITIVE && - $sensitivity !== self::TIME_INSENSITIVE) { + if ($sensitivity !== self::TIME_SENSITIVE + && $sensitivity !== self::TIME_INSENSITIVE) { throw new \InvalidArgumentException('Invalid sensitivity'); } diff --git a/lib/public/BeforeSabrePubliclyLoadedEvent.php b/lib/public/BeforeSabrePubliclyLoadedEvent.php index c69cf867a43..33f9f8bc378 100644 --- a/lib/public/BeforeSabrePubliclyLoadedEvent.php +++ b/lib/public/BeforeSabrePubliclyLoadedEvent.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Calendar/BackendTemporarilyUnavailableException.php b/lib/public/Calendar/BackendTemporarilyUnavailableException.php index e02ef1a84fd..c2bbb1417ee 100644 --- a/lib/public/Calendar/BackendTemporarilyUnavailableException.php +++ b/lib/public/Calendar/BackendTemporarilyUnavailableException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Calendar/CalendarEventStatus.php b/lib/public/Calendar/CalendarEventStatus.php new file mode 100644 index 00000000000..5e070545758 --- /dev/null +++ b/lib/public/Calendar/CalendarEventStatus.php @@ -0,0 +1,19 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar; + +/** + * The status of a calendar event. + * + * @since 32.0.0 + */ +enum CalendarEventStatus: string { + case TENTATIVE = 'TENTATIVE'; + case CONFIRMED = 'CONFIRMED'; + case CANCELLED = 'CANCELLED'; +}; diff --git a/lib/public/Calendar/CalendarExportOptions.php b/lib/public/Calendar/CalendarExportOptions.php new file mode 100644 index 00000000000..bf21dd85ae4 --- /dev/null +++ b/lib/public/Calendar/CalendarExportOptions.php @@ -0,0 +1,68 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar; + +/** + * Calendar Export Options + * + * @since 32.0.0 + */ +final class CalendarExportOptions { + + /** @var 'ical'|'jcal'|'xcal' */ + private string $format = 'ical'; + private ?string $rangeStart = null; + private ?int $rangeCount = null; + + /** + * Gets the export format + * + * @return 'ical'|'jcal'|'xcal' (defaults to ical) + */ + public function getFormat(): string { + return $this->format; + } + + /** + * Sets the export format + * + * @param 'ical'|'jcal'|'xcal' $format + */ + public function setFormat(string $format): void { + $this->format = $format; + } + + /** + * Gets the start of the range to export + */ + public function getRangeStart(): ?string { + return $this->rangeStart; + } + + /** + * Sets the start of the range to export + */ + public function setRangeStart(?string $rangeStart): void { + $this->rangeStart = $rangeStart; + } + + /** + * Gets the number of objects to export + */ + public function getRangeCount(): ?int { + return $this->rangeCount; + } + + /** + * Sets the number of objects to export + */ + public function setRangeCount(?int $rangeCount): void { + $this->rangeCount = $rangeCount; + } +} diff --git a/lib/public/Calendar/Events/AbstractCalendarObjectEvent.php b/lib/public/Calendar/Events/AbstractCalendarObjectEvent.php new file mode 100644 index 00000000000..111ed096f78 --- /dev/null +++ b/lib/public/Calendar/Events/AbstractCalendarObjectEvent.php @@ -0,0 +1,79 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar\Events; + +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IWebhookCompatibleEvent; + +/** + * @since 32.0.0 + */ +abstract class AbstractCalendarObjectEvent extends Event implements IWebhookCompatibleEvent { + + /** + * @param int $calendarId + * @param array $calendarData + * @param array $shares + * @param array $objectData + * @since 32.0.0 + */ + public function __construct( + private int $calendarId, + private array $calendarData, + private array $shares, + private array $objectData, + ) { + parent::__construct(); + } + + /** + * @return int + * @since 32.0.0 + */ + public function getCalendarId(): int { + return $this->calendarId; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getCalendarData(): array { + return $this->calendarData; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getShares(): array { + return $this->shares; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getObjectData(): array { + return $this->objectData; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getWebhookSerializable(): array { + return [ + 'calendarId' => $this->getCalendarId(), + 'calendarData' => $this->getCalendarData(), + 'shares' => $this->getShares(), + 'objectData' => $this->getObjectData(), + ]; + } +} diff --git a/lib/public/Calendar/Events/CalendarObjectCreatedEvent.php b/lib/public/Calendar/Events/CalendarObjectCreatedEvent.php new file mode 100644 index 00000000000..a4d0f40ec55 --- /dev/null +++ b/lib/public/Calendar/Events/CalendarObjectCreatedEvent.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar\Events; + +/** + * @since 32.0.0 + */ +class CalendarObjectCreatedEvent extends AbstractCalendarObjectEvent { +} diff --git a/lib/public/Calendar/Events/CalendarObjectDeletedEvent.php b/lib/public/Calendar/Events/CalendarObjectDeletedEvent.php new file mode 100644 index 00000000000..5466213584e --- /dev/null +++ b/lib/public/Calendar/Events/CalendarObjectDeletedEvent.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar\Events; + +/** + * @since 32.0.0 + */ +class CalendarObjectDeletedEvent extends AbstractCalendarObjectEvent { +} diff --git a/lib/public/Calendar/Events/CalendarObjectMovedEvent.php b/lib/public/Calendar/Events/CalendarObjectMovedEvent.php new file mode 100644 index 00000000000..1c7df0e1ed5 --- /dev/null +++ b/lib/public/Calendar/Events/CalendarObjectMovedEvent.php @@ -0,0 +1,104 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar\Events; + +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IWebhookCompatibleEvent; + +/** + * @since 32.0.0 + */ +class CalendarObjectMovedEvent extends Event implements IWebhookCompatibleEvent { + /** + * @since 32.0.0 + */ + public function __construct( + private int $sourceCalendarId, + private array $sourceCalendarData, + private int $targetCalendarId, + private array $targetCalendarData, + private array $sourceShares, + private array $targetShares, + private array $objectData, + ) { + parent::__construct(); + } + + /** + * @return int + * @since 32.0.0 + */ + public function getSourceCalendarId(): int { + return $this->sourceCalendarId; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getSourceCalendarData(): array { + return $this->sourceCalendarData; + } + + /** + * @return int + * @since 32.0.0 + */ + public function getTargetCalendarId(): int { + return $this->targetCalendarId; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getTargetCalendarData(): array { + return $this->targetCalendarData; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getSourceShares(): array { + return $this->sourceShares; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getTargetShares(): array { + return $this->targetShares; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getObjectData(): array { + return $this->objectData; + } + + /** + * @return array + * @since 32.0.0 + */ + public function getWebhookSerializable(): array { + return [ + 'sourceCalendarId' => $this->getSourceCalendarId(), + 'sourceCalendarData' => $this->getSourceCalendarData(), + 'targetCalendarId' => $this->getTargetCalendarId(), + 'targetCalendarData' => $this->getTargetCalendarData(), + 'sourceShares' => $this->getSourceShares(), + 'targetShares' => $this->getTargetShares(), + 'objectData' => $this->getObjectData(), + ]; + } +} diff --git a/lib/public/Calendar/Events/CalendarObjectMovedToTrashEvent.php b/lib/public/Calendar/Events/CalendarObjectMovedToTrashEvent.php new file mode 100644 index 00000000000..ffbd7b0375a --- /dev/null +++ b/lib/public/Calendar/Events/CalendarObjectMovedToTrashEvent.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar\Events; + +/** + * @since 32.0.0 + */ +class CalendarObjectMovedToTrashEvent extends AbstractCalendarObjectEvent { +} diff --git a/lib/public/Calendar/Events/CalendarObjectRestoredEvent.php b/lib/public/Calendar/Events/CalendarObjectRestoredEvent.php new file mode 100644 index 00000000000..7890e3ca5b3 --- /dev/null +++ b/lib/public/Calendar/Events/CalendarObjectRestoredEvent.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar\Events; + +/** + * @since 32.0.0 + */ +class CalendarObjectRestoredEvent extends AbstractCalendarObjectEvent { +} diff --git a/lib/public/Calendar/Events/CalendarObjectUpdatedEvent.php b/lib/public/Calendar/Events/CalendarObjectUpdatedEvent.php new file mode 100644 index 00000000000..c06b2b8198f --- /dev/null +++ b/lib/public/Calendar/Events/CalendarObjectUpdatedEvent.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar\Events; + +/** + * @since 32.0.0 + */ +class CalendarObjectUpdatedEvent extends AbstractCalendarObjectEvent { +} diff --git a/lib/public/Calendar/IAvailabilityResult.php b/lib/public/Calendar/IAvailabilityResult.php new file mode 100644 index 00000000000..d437a5da047 --- /dev/null +++ b/lib/public/Calendar/IAvailabilityResult.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Calendar; + +/** + * DTO for the availability check results. + * Holds information about whether an attendee is available or not during the request time slot. + * + * @since 31.0.0 + */ +interface IAvailabilityResult { + /** + * Get the attendee's email address. + * + * @since 31.0.0 + */ + public function getAttendeeEmail(): string; + + /** + * Whether the attendee is available during the requested time slot. + * + * @since 31.0.0 + */ + public function isAvailable(): bool; +} diff --git a/lib/public/Calendar/ICalendar.php b/lib/public/Calendar/ICalendar.php index 2dfc1ca632f..50152d1240b 100644 --- a/lib/public/Calendar/ICalendar.php +++ b/lib/public/Calendar/ICalendar.php @@ -8,10 +8,18 @@ declare(strict_types=1); */ namespace OCP\Calendar; +use DateTimeInterface; + /** * Interface ICalendar * * @since 13.0.0 + * + * @psalm-type CalendarSearchOptions = array{ + * timerange?: array{start?: DateTimeInterface, end?: DateTimeInterface}, + * uid?: string, + * types?: string[], + * } */ interface ICalendar { /** @@ -41,13 +49,63 @@ interface ICalendar { public function getDisplayColor(): ?string; /** - * @param string $pattern which should match within the $searchProperties - * @param array $searchProperties defines the properties within the query pattern should match - * @param array $options - optional parameters: - * ['timerange' => ['start' => new DateTime(...), 'end' => new DateTime(...)]] - * @param int|null $limit - limit number of search results - * @param int|null $offset - offset for paging of search results - * @return array an array of events/journals/todos which are arrays of key-value-pairs. the events are sorted by start date (closest first, furthest last) + * Search the current calendar for matching events. + * + * This method searches for events in the calendar that match a given pattern within specified properties. + * The search is case-insensitive. It supports optional parameters such as a time range, limit, and offset. + * The results are sorted by start date, with the closest events appearing first. + * + * @param string $pattern A string to search for within the events. The search is done case-insensitive. + * @param array $searchProperties Defines the properties within which the pattern should match. + * @param array $options Optional parameters for the search: + * - 'timerange' element that can have 'start' (DateTimeInterface), 'end' (DateTimeInterface), or both. + * - 'uid' element to look for events with a given uid. + * - 'types' element to only return events for a given type (e.g. VEVENT or VTODO) + * @psalm-param CalendarSearchOptions $options + * @param int|null $limit Limit the number of search results. + * @param int|null $offset For paging of search results. + * @return array An array of events/journals/todos which are arrays of key-value-pairs. The events are sorted by start date (closest first, furthest last). + * + * Implementation Details: + * + * An event can consist of many sub-events, typically the case for events with recurrence rules. On a database level, + * there's only one event stored (with a matching first occurrence and last occurrence timestamp). Expanding an event + * into sub-events is done on the backend level. Using limit, offset, and timerange comes with some drawbacks. + * When asking the database for events, the result is ordered by the primary key to guarantee a stable order. + * After expanding the events into sub-events, they are sorted by the date (closest to furthest). + * + * Usage Examples: + * + * 1) Find 7 events within the next two weeks: + * + * $dateTime = (new DateTimeImmutable())->setTimestamp($this->timeFactory->getTime()); + * $inTwoWeeks = $dateTime->add(new DateInterval('P14D')); + * + * $calendar->search( + * '', + * [], + * ['timerange' => ['start' => $dateTime, 'end' => $inTwoWeeks]], + * 7 + * ); + * + * Note: When combining timerange and limit, it's possible that the expected outcome is not in the order you would expect. + * + * Example: Create 7 events for tomorrow, starting from 11:00, 30 minutes each. Then create an 8th event for tomorrow at 10:00. + * The above code will list the event at 11:00 first, missing the event at 10:00. The reason is the ordering by the primary key + * and expanding on the backend level. This is a technical limitation. The easiest workaround is to fetch more events + * than you actually need, with the downside of needing more resources. + * + * Related: + * - https://github.com/nextcloud/server/pull/45222 + * - https://github.com/nextcloud/server/issues/53002 + * + * 2) Find all events where the location property contains the string 'Berlin': + * + * $calendar->search( + * 'Berlin', + * ['LOCATION'] + * ); + * * @since 13.0.0 */ public function search(string $pattern, array $searchProperties = [], array $options = [], ?int $limit = null, ?int $offset = null): array; diff --git a/lib/public/Calendar/ICalendarEventBuilder.php b/lib/public/Calendar/ICalendarEventBuilder.php new file mode 100644 index 00000000000..c99dc60cc8c --- /dev/null +++ b/lib/public/Calendar/ICalendarEventBuilder.php @@ -0,0 +1,117 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Calendar; + +use DateTimeInterface; +use InvalidArgumentException; +use OCP\Calendar\Exceptions\CalendarException; + +/** + * The calendar event builder can be used to conveniently build a calendar event and then serialize + * it to a ICS string. The ICS string can be submitted to calendar instances implementing the + * {@see \OCP\Calendar\ICreateFromString} interface. + * + * Also note this class can not be injected directly with dependency injection. + * Instead, inject {@see \OCP\Calendar\IManager} and use + * {@see \OCP\Calendar\IManager::createEventBuilder()} afterwards. + * + * All setters return self to allow chaining method calls. + * + * @since 31.0.0 + */ +interface ICalendarEventBuilder { + /** + * Set the start date, time and time zone. + * This property is required! + * + * @since 31.0.0 + */ + public function setStartDate(DateTimeInterface $start): self; + + /** + * Set the end date, time and time zone. + * This property is required! + * + * @since 31.0.0 + */ + public function setEndDate(DateTimeInterface $end): self; + + /** + * Set the event summary or title. + * This property is required! + * + * @since 31.0.0 + */ + public function setSummary(string $summary): self; + + /** + * Set the event description. + * + * @since 31.0.0 + */ + public function setDescription(string $description): self; + + /** + * Set the event location. It can either be a physical address or a URL. + * + * @since 31.0.0 + */ + public function setLocation(string $location): self; + + /** + * Set the event status. + * + * @since 32.0.0 + */ + public function setStatus(CalendarEventStatus $status): static; + + /** + * Set the event organizer. + * This property is required if attendees are added! + * + * The "mailto:" prefix is optional and will be added automatically if it is missing. + * + * @since 31.0.0 + */ + public function setOrganizer(string $email, ?string $commonName = null): self; + + /** + * Add a new attendee to the event. + * Adding at least one attendee requires also setting the organizer! + * + * The "mailto:" prefix is optional and will be added automatically if it is missing. + * + * @since 31.0.0 + */ + public function addAttendee(string $email, ?string $commonName = null): self; + + /** + * Serialize the built event to an ICS string if all required properties set. + * + * @since 31.0.0 + * + * @return string The serialized ICS string + * + * @throws InvalidArgumentException If required properties were not set + */ + public function toIcs(): string; + + /** + * Create the event in the given calendar. + * + * @since 31.0.0 + * + * @return string The filename of the created event + * + * @throws InvalidArgumentException If required properties were not set + * @throws CalendarException If writing the event to the calendar fails + */ + public function createInCalendar(ICreateFromString $calendar): string; +} diff --git a/lib/public/Calendar/ICalendarExport.php b/lib/public/Calendar/ICalendarExport.php new file mode 100644 index 00000000000..d884c104a4a --- /dev/null +++ b/lib/public/Calendar/ICalendarExport.php @@ -0,0 +1,31 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar; + +use Generator; + +/** + * ICalendar Interface Extension to export data + * + * @since 32.0.0 + */ +interface ICalendarExport { + + /** + * Export objects + * + * @since 32.0.0 + * + * @param CalendarExportOptions|null $options + * + * @return Generator<\Sabre\VObject\Component\VCalendar> + */ + public function export(?CalendarExportOptions $options): Generator; + +} diff --git a/lib/public/Calendar/ICalendarIsEnabled.php b/lib/public/Calendar/ICalendarIsEnabled.php new file mode 100644 index 00000000000..6bcb487e3dc --- /dev/null +++ b/lib/public/Calendar/ICalendarIsEnabled.php @@ -0,0 +1,24 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Calendar; + +/** + * ICalendar Interface Extension + * + * @since 32.0.0 + */ +interface ICalendarIsEnabled { + + /** + * Indicates whether the calendar is enabled + * + * @since 32.0.0 + */ + public function isEnabled(): bool; + +} diff --git a/lib/public/Calendar/ICalendarIsShared.php b/lib/public/Calendar/ICalendarIsShared.php index 8121c826f4e..6f63c6eefd0 100644 --- a/lib/public/Calendar/ICalendarIsShared.php +++ b/lib/public/Calendar/ICalendarIsShared.php @@ -14,7 +14,7 @@ namespace OCP\Calendar; * @since 31.0.0 */ interface ICalendarIsShared { - + /** * Indicates whether the calendar is shared with the current user * diff --git a/lib/public/Calendar/ICalendarIsWritable.php b/lib/public/Calendar/ICalendarIsWritable.php index f80769e9033..5bf08a25cdc 100644 --- a/lib/public/Calendar/ICalendarIsWritable.php +++ b/lib/public/Calendar/ICalendarIsWritable.php @@ -14,7 +14,7 @@ namespace OCP\Calendar; * @since 31.0.0 */ interface ICalendarIsWritable { - + /** * Indicates whether the calendar can be modified * diff --git a/lib/public/Calendar/IManager.php b/lib/public/Calendar/IManager.php index bb3808f133c..124dc65f5f6 100644 --- a/lib/public/Calendar/IManager.php +++ b/lib/public/Calendar/IManager.php @@ -8,6 +8,9 @@ declare(strict_types=1); */ namespace OCP\Calendar; +use DateTimeInterface; +use OCP\IUser; + /** * This class provides access to the Nextcloud CalDAV backend. * Use this class exclusively if you want to access calendars. @@ -157,4 +160,28 @@ interface IManager { * @since 25.0.0 */ public function handleIMipCancel(string $principalUri, string $sender, ?string $replyTo, string $recipient, string $calendarData): bool; + + /** + * Create a new event builder instance. Please have a look at its documentation and the + * \OCP\Calendar\ICreateFromString interface on how to use it. + * + * @since 31.0.0 + */ + public function createEventBuilder(): ICalendarEventBuilder; + + /** + * Check the availability of the given organizer and attendees in the given time range. + * + * @since 31.0.0 + * + * @param IUser $organizer The organizing user from whose perspective to do the availability check. + * @param string[] $attendees Email addresses of attendees to check for (with or without a "mailto:" prefix). Only users on this instance can be checked. The rest will be silently ignored. + * @return IAvailabilityResult[] Availabilities of the organizer and all attendees which are also users on this instance. As such, the array might not contain an entry for each given attendee. + */ + public function checkAvailability( + DateTimeInterface $start, + DateTimeInterface $end, + IUser $organizer, + array $attendees, + ): array; } diff --git a/lib/public/Calendar/IMetadataProvider.php b/lib/public/Calendar/IMetadataProvider.php index bee840c955f..acacf7efdaf 100644 --- a/lib/public/Calendar/IMetadataProvider.php +++ b/lib/public/Calendar/IMetadataProvider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Calendar/Resource/IBackend.php b/lib/public/Calendar/Resource/IBackend.php index b43d79e3618..23d37c102f2 100644 --- a/lib/public/Calendar/Resource/IBackend.php +++ b/lib/public/Calendar/Resource/IBackend.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Calendar/Resource/IResource.php b/lib/public/Calendar/Resource/IResource.php index f284eee955f..15abe4e2d0f 100644 --- a/lib/public/Calendar/Resource/IResource.php +++ b/lib/public/Calendar/Resource/IResource.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Calendar/Resource/IResourceMetadata.php b/lib/public/Calendar/Resource/IResourceMetadata.php index acf02bc3609..29f628d6f7f 100644 --- a/lib/public/Calendar/Resource/IResourceMetadata.php +++ b/lib/public/Calendar/Resource/IResourceMetadata.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Calendar/Room/IBackend.php b/lib/public/Calendar/Room/IBackend.php index 52ec2fa5948..c99f5fbdb72 100644 --- a/lib/public/Calendar/Room/IBackend.php +++ b/lib/public/Calendar/Room/IBackend.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Calendar/Room/IRoom.php b/lib/public/Calendar/Room/IRoom.php index 580c676331f..526e65b8f5f 100644 --- a/lib/public/Calendar/Room/IRoom.php +++ b/lib/public/Calendar/Room/IRoom.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Calendar/Room/IRoomMetadata.php b/lib/public/Calendar/Room/IRoomMetadata.php index 3fb4089b6a7..15d4b501e12 100644 --- a/lib/public/Calendar/Room/IRoomMetadata.php +++ b/lib/public/Calendar/Room/IRoomMetadata.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Capabilities/IPublicCapability.php b/lib/public/Capabilities/IPublicCapability.php index 3936d6032af..1a9dd965b16 100644 --- a/lib/public/Capabilities/IPublicCapability.php +++ b/lib/public/Capabilities/IPublicCapability.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Collaboration/AutoComplete/IManager.php b/lib/public/Collaboration/AutoComplete/IManager.php index 976bbfb7f18..2d5443b921d 100644 --- a/lib/public/Collaboration/AutoComplete/IManager.php +++ b/lib/public/Collaboration/AutoComplete/IManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Collaboration/AutoComplete/ISorter.php b/lib/public/Collaboration/AutoComplete/ISorter.php index 4b9f2b72e7c..1009092af6a 100644 --- a/lib/public/Collaboration/AutoComplete/ISorter.php +++ b/lib/public/Collaboration/AutoComplete/ISorter.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Collaboration/Collaborators/ISearch.php b/lib/public/Collaboration/Collaborators/ISearch.php index 95151d49a86..d2c5c85c07f 100644 --- a/lib/public/Collaboration/Collaborators/ISearch.php +++ b/lib/public/Collaboration/Collaborators/ISearch.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Collaboration/Collaborators/ISearchPlugin.php b/lib/public/Collaboration/Collaborators/ISearchPlugin.php index ec875d7d017..e55a095e2b6 100644 --- a/lib/public/Collaboration/Collaborators/ISearchPlugin.php +++ b/lib/public/Collaboration/Collaborators/ISearchPlugin.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Collaboration/Collaborators/ISearchResult.php b/lib/public/Collaboration/Collaborators/ISearchResult.php index 8e693caa677..bcc5a91ce99 100644 --- a/lib/public/Collaboration/Collaborators/ISearchResult.php +++ b/lib/public/Collaboration/Collaborators/ISearchResult.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Collaboration/Collaborators/SearchResultType.php b/lib/public/Collaboration/Collaborators/SearchResultType.php index c5a8b4e303a..3fdbefdcf1f 100644 --- a/lib/public/Collaboration/Collaborators/SearchResultType.php +++ b/lib/public/Collaboration/Collaborators/SearchResultType.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Color.php b/lib/public/Color.php index c8ba3a1ff15..ed955b8f056 100644 --- a/lib/public/Color.php +++ b/lib/public/Color.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -125,7 +126,7 @@ class Color { * Calculate steps between two Colors * @param int $steps start color * @param Color[] $ends end color - * @return array{0: int, 1: int, 2: int} [r,g,b] steps for each color to go from $steps to $ends + * @return array{0: float, 1: float, 2: float} [r,g,b] steps for each color to go from $steps to $ends * @since 25.0.0 */ private static function stepCalc(int $steps, array $ends): array { diff --git a/lib/public/Comments/ICommentsEventHandler.php b/lib/public/Comments/ICommentsEventHandler.php index dc0a554ff11..148ead2c367 100644 --- a/lib/public/Comments/ICommentsEventHandler.php +++ b/lib/public/Comments/ICommentsEventHandler.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Constants.php b/lib/public/Constants.php index 62772d195b2..8d38ade7baf 100644 --- a/lib/public/Constants.php +++ b/lib/public/Constants.php @@ -18,20 +18,20 @@ namespace OCP; */ class Constants { /** - * CRUDS permissions. * @since 8.0.0 */ - public const PERMISSION_CREATE = 4; + public const PERMISSION_READ = 1; /** * @since 8.0.0 */ - public const PERMISSION_READ = 1; + public const PERMISSION_UPDATE = 2; /** + * CRUDS permissions. * @since 8.0.0 */ - public const PERMISSION_UPDATE = 2; + public const PERMISSION_CREATE = 4; /** * @since 8.0.0 diff --git a/lib/public/Contacts/ContactsMenu/IAction.php b/lib/public/Contacts/ContactsMenu/IAction.php index 4a7133a999b..00fe8ba35c4 100644 --- a/lib/public/Contacts/ContactsMenu/IAction.php +++ b/lib/public/Contacts/ContactsMenu/IAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Contacts/ContactsMenu/IActionFactory.php b/lib/public/Contacts/ContactsMenu/IActionFactory.php index a4785d1c70c..69e6030e95b 100644 --- a/lib/public/Contacts/ContactsMenu/IActionFactory.php +++ b/lib/public/Contacts/ContactsMenu/IActionFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Contacts/ContactsMenu/IContactsStore.php b/lib/public/Contacts/ContactsMenu/IContactsStore.php index ceb68d99849..67913a2d919 100644 --- a/lib/public/Contacts/ContactsMenu/IContactsStore.php +++ b/lib/public/Contacts/ContactsMenu/IContactsStore.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Contacts/ContactsMenu/IEntry.php b/lib/public/Contacts/ContactsMenu/IEntry.php index c361b71bb7c..9ae8a207297 100644 --- a/lib/public/Contacts/ContactsMenu/IEntry.php +++ b/lib/public/Contacts/ContactsMenu/IEntry.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Contacts/ContactsMenu/ILinkAction.php b/lib/public/Contacts/ContactsMenu/ILinkAction.php index 92bccfd8dda..559e04885c5 100644 --- a/lib/public/Contacts/ContactsMenu/ILinkAction.php +++ b/lib/public/Contacts/ContactsMenu/ILinkAction.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/DB/ISchemaWrapper.php b/lib/public/DB/ISchemaWrapper.php index 16b776c05b9..dcf22b52d3d 100644 --- a/lib/public/DB/ISchemaWrapper.php +++ b/lib/public/DB/ISchemaWrapper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/DB/QueryBuilder/IFunctionBuilder.php b/lib/public/DB/QueryBuilder/IFunctionBuilder.php index 84c3780dbce..480ec1cb1ac 100644 --- a/lib/public/DB/QueryBuilder/IFunctionBuilder.php +++ b/lib/public/DB/QueryBuilder/IFunctionBuilder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Defaults.php b/lib/public/Defaults.php index 9242a230024..6de22caa41e 100644 --- a/lib/public/Defaults.php +++ b/lib/public/Defaults.php @@ -29,7 +29,7 @@ class Defaults { */ public function __construct(?\OC_Defaults $defaults = null) { if ($defaults === null) { - $defaults = \OC::$server->get('ThemingDefaults'); + $defaults = \OCP\Server::get('ThemingDefaults'); } $this->defaults = $defaults; } diff --git a/lib/public/Diagnostics/IQueryLogger.php b/lib/public/Diagnostics/IQueryLogger.php index 1973168803d..07c999023da 100644 --- a/lib/public/Diagnostics/IQueryLogger.php +++ b/lib/public/Diagnostics/IQueryLogger.php @@ -31,7 +31,7 @@ interface IQueryLogger extends SQLLogger { * Mark the end of the current active query. Ending query should store \OCP\Diagnostics\IQuery to * be returned with getQueries() method. * - * @return mixed + * @return void * @since 8.0.0 */ public function stopQuery(); diff --git a/lib/public/DirectEditing/ACreateEmpty.php b/lib/public/DirectEditing/ACreateEmpty.php index f30cc2465f9..6ad499ec760 100644 --- a/lib/public/DirectEditing/ACreateEmpty.php +++ b/lib/public/DirectEditing/ACreateEmpty.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/DirectEditing/ACreateFromTemplate.php b/lib/public/DirectEditing/ACreateFromTemplate.php index 6348b5d3545..e56e9c09cbb 100644 --- a/lib/public/DirectEditing/ACreateFromTemplate.php +++ b/lib/public/DirectEditing/ACreateFromTemplate.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/DirectEditing/ATemplate.php b/lib/public/DirectEditing/ATemplate.php index cc0ed24336b..a70488d8e89 100644 --- a/lib/public/DirectEditing/ATemplate.php +++ b/lib/public/DirectEditing/ATemplate.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/DirectEditing/IToken.php b/lib/public/DirectEditing/IToken.php index 53a67883f54..64abbf939f4 100644 --- a/lib/public/DirectEditing/IToken.php +++ b/lib/public/DirectEditing/IToken.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/DirectEditing/RegisterDirectEditorEvent.php b/lib/public/DirectEditing/RegisterDirectEditorEvent.php index 72d5ea39fe8..cbf9b07185d 100644 --- a/lib/public/DirectEditing/RegisterDirectEditorEvent.php +++ b/lib/public/DirectEditing/RegisterDirectEditorEvent.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Encryption/Exceptions/InvalidHeaderException.php b/lib/public/Encryption/Exceptions/InvalidHeaderException.php new file mode 100644 index 00000000000..f7213577fb6 --- /dev/null +++ b/lib/public/Encryption/Exceptions/InvalidHeaderException.php @@ -0,0 +1,17 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCP\Encryption\Exceptions; + +use OCP\HintException; + +/** + * Class InvalidHeaderException + * + * @since 32.0.0 + */ +class InvalidHeaderException extends HintException { +} diff --git a/lib/public/EventDispatcher/GenericEvent.php b/lib/public/EventDispatcher/GenericEvent.php index fb0a7677672..7e646c4d6a7 100644 --- a/lib/public/EventDispatcher/GenericEvent.php +++ b/lib/public/EventDispatcher/GenericEvent.php @@ -18,10 +18,12 @@ use function array_key_exists; /** * Class GenericEvent * - * convenience reimplementation of \Symfony\Component\GenericEvent against + * convenience re-implementation of \Symfony\Component\GenericEvent against * \OCP\EventDispatcher\Event * * @since 18.0.0 + * @template-implements ArrayAccess<array-key, mixed> + * @template-implements IteratorAggregate<array-key, mixed> * @deprecated 22.0.0 use \OCP\EventDispatcher\Event */ class GenericEvent extends Event implements ArrayAccess, IteratorAggregate { diff --git a/lib/public/EventDispatcher/JsonSerializer.php b/lib/public/EventDispatcher/JsonSerializer.php index 1eb75ed7527..d05367b746d 100644 --- a/lib/public/EventDispatcher/JsonSerializer.php +++ b/lib/public/EventDispatcher/JsonSerializer.php @@ -9,6 +9,8 @@ declare(strict_types=1); namespace OCP\EventDispatcher; +use OC\Files\Node\NonExistingFile; +use OC\Files\Node\NonExistingFolder; use OCP\Files\FileInfo; use OCP\IUser; @@ -24,10 +26,16 @@ final class JsonSerializer { * @since 30.0.0 */ public static function serializeFileInfo(FileInfo $node): array { - return [ - 'id' => $node->getId(), - 'path' => $node->getPath(), - ]; + if ($node instanceof NonExistingFile || $node instanceof NonExistingFolder) { + return [ + 'path' => $node->getPath(), + ]; + } else { + return [ + 'id' => $node->getId(), + 'path' => $node->getPath(), + ]; + } } /** diff --git a/lib/public/Federation/Exceptions/ActionNotSupportedException.php b/lib/public/Federation/Exceptions/ActionNotSupportedException.php index 690e7a554c7..7f0e0f46907 100644 --- a/lib/public/Federation/Exceptions/ActionNotSupportedException.php +++ b/lib/public/Federation/Exceptions/ActionNotSupportedException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/Exceptions/AuthenticationFailedException.php b/lib/public/Federation/Exceptions/AuthenticationFailedException.php index f9482c3a19c..6ce5314844e 100644 --- a/lib/public/Federation/Exceptions/AuthenticationFailedException.php +++ b/lib/public/Federation/Exceptions/AuthenticationFailedException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/Exceptions/BadRequestException.php b/lib/public/Federation/Exceptions/BadRequestException.php index 52e3b0e0db4..0210437a8d5 100644 --- a/lib/public/Federation/Exceptions/BadRequestException.php +++ b/lib/public/Federation/Exceptions/BadRequestException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php b/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php index 606fb08d0fc..f753f5f3326 100644 --- a/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php +++ b/lib/public/Federation/Exceptions/ProviderAlreadyExistsException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php b/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php index 7f1218c349e..168eb2b8aeb 100644 --- a/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php +++ b/lib/public/Federation/Exceptions/ProviderCouldNotAddShareException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php b/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php index 4b3d0341fe9..64dfcf0f856 100644 --- a/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php +++ b/lib/public/Federation/Exceptions/ProviderDoesNotExistsException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/ICloudFederationFactory.php b/lib/public/Federation/ICloudFederationFactory.php index a25e4ee30f7..5238188b4fa 100644 --- a/lib/public/Federation/ICloudFederationFactory.php +++ b/lib/public/Federation/ICloudFederationFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/ICloudFederationNotification.php b/lib/public/Federation/ICloudFederationNotification.php index 8545c9d51f2..c550a936927 100644 --- a/lib/public/Federation/ICloudFederationNotification.php +++ b/lib/public/Federation/ICloudFederationNotification.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/ICloudFederationProvider.php b/lib/public/Federation/ICloudFederationProvider.php index 067ceba160e..b30041f81d6 100644 --- a/lib/public/Federation/ICloudFederationProvider.php +++ b/lib/public/Federation/ICloudFederationProvider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/ICloudFederationProviderManager.php b/lib/public/Federation/ICloudFederationProviderManager.php index 9f5258721ab..68adb4b4da7 100644 --- a/lib/public/Federation/ICloudFederationProviderManager.php +++ b/lib/public/Federation/ICloudFederationProviderManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Federation/ICloudFederationShare.php b/lib/public/Federation/ICloudFederationShare.php index 197ebf1af9a..0b67bbfadee 100644 --- a/lib/public/Federation/ICloudFederationShare.php +++ b/lib/public/Federation/ICloudFederationShare.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files.php b/lib/public/Files.php index 62c41c4ada1..b169032e16c 100644 --- a/lib/public/Files.php +++ b/lib/public/Files.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. @@ -9,6 +10,8 @@ namespace OCP; +use OCP\Files\IMimeTypeDetector; + /** * This class provides access to the internal filesystem abstraction layer. Use * this class exclusively if you want to access files @@ -18,12 +21,44 @@ namespace OCP; class Files { /** * Recursive deletion of folders + * + * @param string $dir path to the folder + * @param bool $deleteSelf if set to false only the content of the folder will be deleted * @return bool * @since 5.0.0 + * @since 32.0.0 added the $deleteSelf parameter * @deprecated 14.0.0 */ - public static function rmdirr($dir) { - return \OC_Helper::rmdirr($dir); + public static function rmdirr($dir, bool $deleteSelf = true) { + if (is_dir($dir)) { + $files = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($files as $fileInfo) { + /** @var \SplFileInfo $fileInfo */ + if ($fileInfo->isLink()) { + unlink($fileInfo->getPathname()); + } elseif ($fileInfo->isDir()) { + rmdir($fileInfo->getRealPath()); + } else { + unlink($fileInfo->getRealPath()); + } + } + if ($deleteSelf) { + rmdir($dir); + } + } elseif (file_exists($dir)) { + if ($deleteSelf) { + unlink($dir); + } + } + if (!$deleteSelf) { + return true; + } + + return !file_exists($dir); } /** @@ -35,7 +70,7 @@ class Files { * @deprecated 14.0.0 */ public static function getMimeType($path) { - return \OC::$server->getMimeTypeDetector()->detect($path); + return Server::get(IMimeTypeDetector::class)->detect($path); } /** @@ -51,15 +86,45 @@ class Files { /** * Copy the contents of one stream to another + * + * @template T of null|true * @param resource $source * @param resource $target - * @return int the number of bytes copied + * @param T $includeResult + * @return int|array + * @psalm-return (T is true ? array{0: int, 1: bool} : int) * @since 5.0.0 + * @since 32.0.0 added $includeResult parameter * @deprecated 14.0.0 */ - public static function streamCopy($source, $target) { - [$count, ] = \OC_Helper::streamCopy($source, $target); - return $count; + public static function streamCopy($source, $target, ?bool $includeResult = null) { + if (!$source or !$target) { + return $includeResult ? [0, false] : 0; + } + + $bufSize = 8192; + $count = 0; + $result = true; + while (!feof($source)) { + $buf = fread($source, $bufSize); + if ($buf === false) { + $result = false; + break; + } + + $bytesWritten = fwrite($target, $buf); + if ($bytesWritten !== false) { + $count += $bytesWritten; + } + + if ($bytesWritten === false + || ($bytesWritten < $bufSize && $bytesWritten < strlen($buf)) + ) { + $result = false; + break; + } + } + return $includeResult ? [$count, $result] : $count; } /** @@ -73,16 +138,4 @@ class Files { public static function buildNotExistingFileName($path, $filename) { return \OC_Helper::buildNotExistingFileName($path, $filename); } - - /** - * Gets the Storage for an app - creates the needed folder if they are not - * existent - * @param string $app - * @return \OC\Files\View - * @since 5.0.0 - * @deprecated 14.0.0 use IAppData instead - */ - public static function getStorage($app) { - return \OC_App::getStorage($app); - } } diff --git a/lib/public/Files/Cache/ICacheEntry.php b/lib/public/Files/Cache/ICacheEntry.php index 11d91e74105..28e673071fd 100644 --- a/lib/public/Files/Cache/ICacheEntry.php +++ b/lib/public/Files/Cache/ICacheEntry.php @@ -161,4 +161,12 @@ interface ICacheEntry extends ArrayAccess { * @since 25.0.0 */ public function getUnencryptedSize(): int; + + /** + * Get the file id of the parent folder + * + * @return int + * @since 32.0.0 + */ + public function getParentId(): int; } diff --git a/lib/public/Files/Cache/IWatcher.php b/lib/public/Files/Cache/IWatcher.php index 75ab14f85c2..62b90f672c6 100644 --- a/lib/public/Files/Cache/IWatcher.php +++ b/lib/public/Files/Cache/IWatcher.php @@ -76,4 +76,10 @@ interface IWatcher { * @since 9.0.0 */ public function cleanFolder($path); + + /** + * register a callback to be called whenever the watcher triggers and update + * @since 31.0.0 + */ + public function onUpdate(callable $callback): void; } diff --git a/lib/public/Files/Config/Event/UserMountAddedEvent.php b/lib/public/Files/Config/Event/UserMountAddedEvent.php new file mode 100644 index 00000000000..8abd7512188 --- /dev/null +++ b/lib/public/Files/Config/Event/UserMountAddedEvent.php @@ -0,0 +1,26 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Files\Config\Event; + +use OCP\EventDispatcher\Event; +use OCP\Files\Config\ICachedMountInfo; + +/** + * Event emitted when a user mount was added. + * + * @since 32.0.0 + */ +class UserMountAddedEvent extends Event { + public function __construct( + public readonly ICachedMountInfo $mountPoint, + ) { + parent::__construct(); + } +} diff --git a/lib/public/Files/Config/Event/UserMountRemovedEvent.php b/lib/public/Files/Config/Event/UserMountRemovedEvent.php new file mode 100644 index 00000000000..0de7cfc4a99 --- /dev/null +++ b/lib/public/Files/Config/Event/UserMountRemovedEvent.php @@ -0,0 +1,26 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Files\Config\Event; + +use OCP\EventDispatcher\Event; +use OCP\Files\Config\ICachedMountInfo; + +/** + * Event emitted when a user mount was removed. + * + * @since 32.0.0 + */ +class UserMountRemovedEvent extends Event { + public function __construct( + public readonly ICachedMountInfo $mountPoint, + ) { + parent::__construct(); + } +} diff --git a/lib/public/Files/Config/Event/UserMountUpdatedEvent.php b/lib/public/Files/Config/Event/UserMountUpdatedEvent.php new file mode 100644 index 00000000000..f797bef134e --- /dev/null +++ b/lib/public/Files/Config/Event/UserMountUpdatedEvent.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Files\Config\Event; + +use OCP\EventDispatcher\Event; +use OCP\Files\Config\ICachedMountInfo; + +/** + * Event emitted when a user mount was moved. + * + * @since 32.0.0 + */ +class UserMountUpdatedEvent extends Event { + public function __construct( + public readonly ICachedMountInfo $oldMountPoint, + public readonly ICachedMountInfo $newMountPoint, + ) { + parent::__construct(); + } +} diff --git a/lib/public/Files/Config/ICachedMountFileInfo.php b/lib/public/Files/Config/ICachedMountFileInfo.php index 7b331059645..a9b30d8ba6d 100644 --- a/lib/public/Files/Config/ICachedMountFileInfo.php +++ b/lib/public/Files/Config/ICachedMountFileInfo.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Conversion/ConversionMimeProvider.php b/lib/public/Files/Conversion/ConversionMimeProvider.php new file mode 100644 index 00000000000..0daf4a10648 --- /dev/null +++ b/lib/public/Files/Conversion/ConversionMimeProvider.php @@ -0,0 +1,66 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Files\Conversion; + +use JsonSerializable; + +/** + * A tuple-like object representing both an original and target + * MIME type for a file conversion + * + * @since 31.0.0 + */ +class ConversionMimeProvider implements JsonSerializable { + /** + * @param string $from The source MIME type of a file + * @param string $to The target MIME type for the file + * @param string $extension The file extension for the target MIME type (e.g. 'png') + * @param string $displayName The human-readable name of the target MIME type (e.g. 'Image (.png)') + * + * @since 31.0.0 + */ + public function __construct( + private string $from, + private string $to, + private string $extension, + private string $displayName, + ) { + } + + public function getFrom(): string { + return $this->from; + } + + public function getTo(): string { + return $this->to; + } + + public function getExtension(): string { + return $this->extension; + } + + public function getDisplayName(): string { + return $this->displayName; + } + + /** + * @return array{from: string, to: string, extension: string, displayName: string} + * + * @since 31.0.0 + */ + public function jsonSerialize(): array { + return [ + 'from' => $this->from, + 'to' => $this->to, + 'extension' => $this->extension, + 'displayName' => $this->displayName, + ]; + } +} diff --git a/lib/public/Files/Conversion/IConversionManager.php b/lib/public/Files/Conversion/IConversionManager.php new file mode 100644 index 00000000000..ed418129d3b --- /dev/null +++ b/lib/public/Files/Conversion/IConversionManager.php @@ -0,0 +1,46 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Files\Conversion; + +use OCP\Files\File; + +/** + * @since 31.0.0 + */ +interface IConversionManager { + /** + * Determines whether or not conversion providers are available + * + * @since 31.0.0 + */ + public function hasProviders(): bool; + + /** + * Gets all supported MIME type conversions + * + * @return list<ConversionMimeProvider> + * + * @since 31.0.0 + */ + public function getProviders(): array; + + /** + * Convert a file to a given MIME type + * + * @param File $file The file to be converted + * @param string $targetMimeType The MIME type to convert the file to + * @param ?string $destination The destination to save the converted file + * + * @return string Path to the converted file + * + * @since 31.0.0 + */ + public function convert(File $file, string $targetMimeType, ?string $destination = null): string; +} diff --git a/lib/public/Files/Conversion/IConversionProvider.php b/lib/public/Files/Conversion/IConversionProvider.php new file mode 100644 index 00000000000..3b5c5945c99 --- /dev/null +++ b/lib/public/Files/Conversion/IConversionProvider.php @@ -0,0 +1,41 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Files\Conversion; + +use OCP\Files\File; + +/** + * This interface is implemented by apps that provide + * a file conversion provider + * + * @since 31.0.0 + */ +interface IConversionProvider { + /** + * Get an array of MIME type tuples this conversion provider supports + * + * @return list<ConversionMimeProvider> + * + * @since 31.0.0 + */ + public function getSupportedMimeTypes(): array; + + /** + * Convert a file to a given MIME type + * + * @param File $file The file to be converted + * @param string $targetMimeType The MIME type to convert the file to + * + * @return resource|string Resource or string content of the file + * + * @since 31.0.0 + */ + public function convertFile(File $file, string $targetMimeType): mixed; +} diff --git a/lib/public/Files/DavUtil.php b/lib/public/Files/DavUtil.php index 40d17c77c88..6dde3179bb8 100644 --- a/lib/public/Files/DavUtil.php +++ b/lib/public/Files/DavUtil.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-only diff --git a/lib/public/Files/EmptyFileNameException.php b/lib/public/Files/EmptyFileNameException.php index ec13a9fc2be..1630ce63ea2 100644 --- a/lib/public/Files/EmptyFileNameException.php +++ b/lib/public/Files/EmptyFileNameException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Folder.php b/lib/public/Files/Folder.php index 3128a17c10c..a35d2d78bc9 100644 --- a/lib/public/Files/Folder.php +++ b/lib/public/Files/Folder.php @@ -199,4 +199,15 @@ interface Folder extends Node { * @since 9.1.0 */ public function getRecent($limit, $offset = 0); + + /** + * Verify if the given path is valid and allowed from this folder. + * + * @param string $path the path from this folder + * @param string $fileName + * @param bool $readonly Check only if the path is allowed for read-only access + * @throws InvalidPathException + * @since 32.0.0 + */ + public function verifyPath($fileName, $readonly = false): void; } diff --git a/lib/public/Files/GenericFileException.php b/lib/public/Files/GenericFileException.php index 288d668e3e7..66a3b5e5ac4 100644 --- a/lib/public/Files/GenericFileException.php +++ b/lib/public/Files/GenericFileException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/IAppData.php b/lib/public/Files/IAppData.php index e5a5c2b7143..4d0c4da6a8a 100644 --- a/lib/public/Files/IAppData.php +++ b/lib/public/Files/IAppData.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/IFilenameValidator.php b/lib/public/Files/IFilenameValidator.php index 2bd3bb945dc..9b7fa1e2e2e 100644 --- a/lib/public/Files/IFilenameValidator.php +++ b/lib/public/Files/IFilenameValidator.php @@ -36,4 +36,17 @@ interface IFilenameValidator { * @since 30.0.0 */ public function validateFilename(string $filename): void; + + /** + * Sanitize a give filename to comply with admin setup naming constrains. + * + * If no sanitizing is needed the same name is returned. + * + * @param string $name The filename to sanitize + * @param null|string $charReplacement Character to use for replacing forbidden ones - by default underscore, dash or space is used if allowed. + * @throws \InvalidArgumentException if no character replacement was given (and the default could not be applied) or the replacement is not valid. + * @since 32.0.0 + */ + public function sanitizeFilename(string $name, ?string $charReplacement = null): string; + } diff --git a/lib/public/Files/IMimeTypeDetector.php b/lib/public/Files/IMimeTypeDetector.php index 1c683cdd4b9..1e87cf932ce 100644 --- a/lib/public/Files/IMimeTypeDetector.php +++ b/lib/public/Files/IMimeTypeDetector.php @@ -14,11 +14,11 @@ namespace OCP\Files; * Interface IMimeTypeDetector * @since 8.2.0 * - * Interface to handle mimetypes (detection and icon retrieval) + * Interface to handle MIME type (detection and icon retrieval) **/ interface IMimeTypeDetector { /** - * detect mimetype only based on filename, content of file is not used + * Detect MIME type only based on filename, content of file is not used * @param string $path * @return string * @since 8.2.0 @@ -26,7 +26,7 @@ interface IMimeTypeDetector { public function detectPath($path); /** - * detect mimetype only based on the content of file + * Detect MIME type only based on the content of file * @param string $path * @return string * @since 18.0.0 @@ -34,7 +34,7 @@ interface IMimeTypeDetector { public function detectContent(string $path): string; /** - * detect mimetype based on both filename and content + * Detect MIME type based on both filename and content * * @param string $path * @return string @@ -43,7 +43,7 @@ interface IMimeTypeDetector { public function detect($path); /** - * Get a secure mimetype that won't expose potential XSS. + * Get a secure MIME type that won't expose potential XSS. * * @param string $mimeType * @return string @@ -52,7 +52,7 @@ interface IMimeTypeDetector { public function getSecureMimeType($mimeType); /** - * detect mimetype based on the content of a string + * Detect MIME type based on the content of a string * * @param string $data * @return string @@ -73,4 +73,26 @@ interface IMimeTypeDetector { * @since 28.0.0 */ public function getAllAliases(): array; + + /** + * Get all extension to MIME type mappings. + * + * The return format is an array of the file extension, as the key, + * mapped to a list where the first entry is the MIME type + * and the second entry is the secure MIME type (or null if none). + * Due to PHP idiosyncrasies if a numeric string is set as the extension, + * then also the array key (file extension) is a number instead of a string. + * + * @return array<list{string, string|null}> + * @since 32.0.0 + */ + public function getAllMappings(): array; + + /** + * Get all human readable mime names + * + * @return array<string,string> + * @since 32.0.0 + */ + public function getAllNamings(): array; } diff --git a/lib/public/Files/IMimeTypeLoader.php b/lib/public/Files/IMimeTypeLoader.php index 44261527d53..77c59fb2c0a 100644 --- a/lib/public/Files/IMimeTypeLoader.php +++ b/lib/public/Files/IMimeTypeLoader.php @@ -47,4 +47,14 @@ interface IMimeTypeLoader { * @since 8.2.0 */ public function reset(): void; + + /** + * Update filecache mimetype based on file extension + * + * @param string $ext + * @param int $mimeTypeId + * @return int + * @since 32.0.0 + */ + public function updateFilecache(string $ext, int $mimeTypeId): int; } diff --git a/lib/public/Files/InvalidDirectoryException.php b/lib/public/Files/InvalidDirectoryException.php index 7f87eed1a17..b9640209cbf 100644 --- a/lib/public/Files/InvalidDirectoryException.php +++ b/lib/public/Files/InvalidDirectoryException.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Notify/IChange.php b/lib/public/Files/Notify/IChange.php index 8f252411a5a..c7c758eec11 100644 --- a/lib/public/Files/Notify/IChange.php +++ b/lib/public/Files/Notify/IChange.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Notify/INotifyHandler.php b/lib/public/Files/Notify/INotifyHandler.php index 8777779ca4a..09b3dbca919 100644 --- a/lib/public/Files/Notify/INotifyHandler.php +++ b/lib/public/Files/Notify/INotifyHandler.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Notify/IRenameChange.php b/lib/public/Files/Notify/IRenameChange.php index 3e1ae7ed447..b1bfae5fc00 100644 --- a/lib/public/Files/Notify/IRenameChange.php +++ b/lib/public/Files/Notify/IRenameChange.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/ObjectStore/IObjectStoreMetaData.php b/lib/public/Files/ObjectStore/IObjectStoreMetaData.php new file mode 100644 index 00000000000..9683873be36 --- /dev/null +++ b/lib/public/Files/ObjectStore/IObjectStoreMetaData.php @@ -0,0 +1,47 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ +namespace OCP\Files\ObjectStore; + +/** + * Interface IObjectStoreMetaData + * + * @psalm-type ObjectMetaData = array{mtime?: \DateTime, etag?: string, size?: int, mimetype?: string, filename?: string, original-path?: string, original-storage?: string} + * + * @since 32.0.0 + */ +interface IObjectStoreMetaData { + /** + * Get metadata for an object. + * + * @param string $urn + * @return ObjectMetaData + * + * @since 32.0.0 + */ + public function getObjectMetaData(string $urn): array; + + /** + * List all objects in the object store. + * + * If the object store implementation can do it efficiently, the metadata for each object is also included. + * + * @param string $prefix + * @return \Iterator<array{urn: string, metadata: ?ObjectMetaData}> + * + * @since 32.0.0 + */ + public function listObjects(string $prefix = ''): \Iterator; + + /** + * @param string $urn the unified resource name used to identify the object + * @param resource $stream stream with the data to write + * @param ObjectMetaData $metaData the metadata to set for the object + * @throws \Exception when something goes wrong, message will be logged + * @since 32.0.0 + */ + public function writeObjectWithMetaData(string $urn, $stream, array $metaData): void; +} diff --git a/lib/public/Files/Search/ISearchBinaryOperator.php b/lib/public/Files/Search/ISearchBinaryOperator.php index 661be44596d..fa7ef4d1bb3 100644 --- a/lib/public/Files/Search/ISearchBinaryOperator.php +++ b/lib/public/Files/Search/ISearchBinaryOperator.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Search/ISearchComparison.php b/lib/public/Files/Search/ISearchComparison.php index 01b69f5d24c..ab298fa0a57 100644 --- a/lib/public/Files/Search/ISearchComparison.php +++ b/lib/public/Files/Search/ISearchComparison.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -51,7 +52,7 @@ interface ISearchComparison extends ISearchOperator { * @since 28.0.0 */ public const COMPARE_DEFINED = 'is-defined'; - + /** * @since 29.0.0 */ diff --git a/lib/public/Files/Search/ISearchOperator.php b/lib/public/Files/Search/ISearchOperator.php index a604bd96b9d..f6ae8edcbb1 100644 --- a/lib/public/Files/Search/ISearchOperator.php +++ b/lib/public/Files/Search/ISearchOperator.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Search/ISearchOrder.php b/lib/public/Files/Search/ISearchOrder.php index 23f71e2133e..e6e68849443 100644 --- a/lib/public/Files/Search/ISearchOrder.php +++ b/lib/public/Files/Search/ISearchOrder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Search/ISearchQuery.php b/lib/public/Files/Search/ISearchQuery.php index 109998aee65..1b400c56e5b 100644 --- a/lib/public/Files/Search/ISearchQuery.php +++ b/lib/public/Files/Search/ISearchQuery.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/SimpleFS/ISimpleFile.php b/lib/public/Files/SimpleFS/ISimpleFile.php index 2682c22580d..4e77299ab00 100644 --- a/lib/public/Files/SimpleFS/ISimpleFile.php +++ b/lib/public/Files/SimpleFS/ISimpleFile.php @@ -1,12 +1,15 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ namespace OCP\Files\SimpleFS; +use OCP\Files\GenericFileException; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\Lock\LockedException; /** * This interface allows to manage simple files. @@ -49,8 +52,10 @@ interface ISimpleFile { /** * Get the content * - * @throws NotPermittedException + * @throws GenericFileException + * @throws LockedException * @throws NotFoundException + * @throws NotPermittedException * @since 11.0.0 */ public function getContent(): string; @@ -59,8 +64,10 @@ interface ISimpleFile { * Overwrite the file * * @param string|resource $data - * @throws NotPermittedException + * @throws GenericFileException + * @throws LockedException * @throws NotFoundException + * @throws NotPermittedException * @since 11.0.0 */ public function putContent($data): void; diff --git a/lib/public/Files/SimpleFS/ISimpleFolder.php b/lib/public/Files/SimpleFS/ISimpleFolder.php index 79b9fca1dac..95efc676688 100644 --- a/lib/public/Files/SimpleFS/ISimpleFolder.php +++ b/lib/public/Files/SimpleFS/ISimpleFolder.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/SimpleFS/ISimpleRoot.php b/lib/public/Files/SimpleFS/ISimpleRoot.php index 5c01c6a2a2e..6be8a1d47c9 100644 --- a/lib/public/Files/SimpleFS/ISimpleRoot.php +++ b/lib/public/Files/SimpleFS/ISimpleRoot.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Storage/IChunkedFileWrite.php b/lib/public/Files/Storage/IChunkedFileWrite.php index e166a7f3b1f..0cf27814f0e 100644 --- a/lib/public/Files/Storage/IChunkedFileWrite.php +++ b/lib/public/Files/Storage/IChunkedFileWrite.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Storage/IDisableEncryptionStorage.php b/lib/public/Files/Storage/IDisableEncryptionStorage.php index 98a4b4897da..19951da2015 100644 --- a/lib/public/Files/Storage/IDisableEncryptionStorage.php +++ b/lib/public/Files/Storage/IDisableEncryptionStorage.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Storage/INotifyStorage.php b/lib/public/Files/Storage/INotifyStorage.php index 0e5cf53af21..063ff815581 100644 --- a/lib/public/Files/Storage/INotifyStorage.php +++ b/lib/public/Files/Storage/INotifyStorage.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files/Template/BeforeGetTemplatesEvent.php b/lib/public/Files/Template/BeforeGetTemplatesEvent.php index 006163c5f7f..9fb7453a50c 100644 --- a/lib/public/Files/Template/BeforeGetTemplatesEvent.php +++ b/lib/public/Files/Template/BeforeGetTemplatesEvent.php @@ -17,16 +17,19 @@ use OCP\EventDispatcher\Event; class BeforeGetTemplatesEvent extends Event { /** @var array<Template> */ private array $templates; + /** @var bool */ + private bool $withFields; /** * @param array<Template> $templates * * @since 30.0.0 */ - public function __construct(array $templates) { + public function __construct(array $templates, bool $withFields = false) { parent::__construct(); $this->templates = $templates; + $this->withFields = $withFields; } /** @@ -37,4 +40,13 @@ class BeforeGetTemplatesEvent extends Event { public function getTemplates(): array { return $this->templates; } + + /** + * @return bool + * + * @since 32.0.0 + */ + public function shouldGetFields(): bool { + return $this->withFields; + } } diff --git a/lib/public/Files/Template/ICustomTemplateProvider.php b/lib/public/Files/Template/ICustomTemplateProvider.php index 305f2c9a55e..6136bc4f1c0 100644 --- a/lib/public/Files/Template/ICustomTemplateProvider.php +++ b/lib/public/Files/Template/ICustomTemplateProvider.php @@ -17,7 +17,7 @@ interface ICustomTemplateProvider { /** * Return a list of additional templates that the template provider is offering * - * @return File[] + * @return Template[] * @since 21.0.0 */ public function getCustomTemplates(string $mimetype): array; diff --git a/lib/public/Files/Template/ITemplateManager.php b/lib/public/Files/Template/ITemplateManager.php index 9a81aa51ceb..df81bc5604e 100644 --- a/lib/public/Files/Template/ITemplateManager.php +++ b/lib/public/Files/Template/ITemplateManager.php @@ -39,6 +39,15 @@ interface ITemplateManager { public function listTemplates(): array; /** + * Get the fields for a given template + * + * @param int $fileId + * @return array + * @since 32.0.0 + */ + public function listTemplateFields(int $fileId): array; + + /** * @return bool * @since 21.0.0 */ diff --git a/lib/public/Files/Template/RegisterTemplateCreatorEvent.php b/lib/public/Files/Template/RegisterTemplateCreatorEvent.php index c931f3e2a78..a9e7fa01252 100644 --- a/lib/public/Files/Template/RegisterTemplateCreatorEvent.php +++ b/lib/public/Files/Template/RegisterTemplateCreatorEvent.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Files_FullTextSearch/Model/AFilesDocument.php b/lib/public/Files_FullTextSearch/Model/AFilesDocument.php index ba5f504fccf..297d6bc6ffc 100644 --- a/lib/public/Files_FullTextSearch/Model/AFilesDocument.php +++ b/lib/public/Files_FullTextSearch/Model/AFilesDocument.php @@ -16,7 +16,7 @@ use OCP\FullTextSearch\Model\IIndexDocument; * This is mostly used by 3rd party apps that want to complete the IIndexDocument * with more information about a file before its index: * - * \OC::$server->getEventDispatcher()->addListener( + * \OCP\Server::get(IEventDispatcher::class)->addListener( * '\OCA\Files_FullTextSearch::onFileIndexing', * function(GenericEvent $e) { * //@var \OCP\Files\Node $file diff --git a/lib/public/GlobalScale/IConfig.php b/lib/public/GlobalScale/IConfig.php index 31df152f644..bae5dd7aa66 100644 --- a/lib/public/GlobalScale/IConfig.php +++ b/lib/public/GlobalScale/IConfig.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Group/Backend/INamedBackend.php b/lib/public/Group/Backend/INamedBackend.php index 8b9ef9ffbba..d98cc8cdb83 100644 --- a/lib/public/Group/Backend/INamedBackend.php +++ b/lib/public/Group/Backend/INamedBackend.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Http/Client/IResponse.php b/lib/public/Http/Client/IResponse.php index deec2cf97b1..53032ef2a37 100644 --- a/lib/public/Http/Client/IResponse.php +++ b/lib/public/Http/Client/IResponse.php @@ -15,8 +15,9 @@ namespace OCP\Http\Client; */ interface IResponse { /** - * @return string|resource + * @return null|resource|string * @since 8.1.0 + * @sicne 8.2.0 with stream enabled, the function returns null or a resource */ public function getBody(); diff --git a/lib/public/IAddressBook.php b/lib/public/IAddressBook.php index 780b005fe8d..5a5cc487cee 100644 --- a/lib/public/IAddressBook.php +++ b/lib/public/IAddressBook.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2016 ownCloud, Inc. diff --git a/lib/public/IAddressBookEnabled.php b/lib/public/IAddressBookEnabled.php new file mode 100644 index 00000000000..ad93aa3f59a --- /dev/null +++ b/lib/public/IAddressBookEnabled.php @@ -0,0 +1,26 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors" + * SPDX-License-Identifier: AGPL-3.0-only + */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal Nextcloud classes + +namespace OCP; + +/** + * IAddressBook Interface extension for checking if the address book is enabled + * + * @since 32.0.0 + */ +interface IAddressBookEnabled extends IAddressBook { + /** + * Check if the address book is enabled + * @return bool + * @since 32.0.0 + */ + public function isEnabled(): bool; +} diff --git a/lib/public/IAppConfig.php b/lib/public/IAppConfig.php index fe894da8d31..fcc528fe11f 100644 --- a/lib/public/IAppConfig.php +++ b/lib/public/IAppConfig.php @@ -45,6 +45,9 @@ interface IAppConfig { /** @since 29.0.0 */ public const VALUE_ARRAY = 64; + /** @since 31.0.0 */ + public const FLAG_SENSITIVE = 1; // value is sensitive + /** * Get list of all apps that have at least one config value stored in database * @@ -504,4 +507,12 @@ interface IAppConfig { * @deprecated 29.0.0 Use {@see getAllValues()} or {@see searchValues()} */ public function getFilteredValues($app); + + /** + * Returns the installed version of all apps + * + * @return array<string, string> + * @since 32.0.0 + */ + public function getAppInstalledVersions(bool $onlyEnabled = false): array; } diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php index 36369732b64..e0fe603ec57 100644 --- a/lib/public/IDBConnection.php +++ b/lib/public/IDBConnection.php @@ -296,6 +296,21 @@ interface IDBConnection { public function dropTable(string $table): void; /** + * Truncate a table data if it exists + * + * Cascade is not supported on many platforms but would optionally cascade the truncate by + * following the foreign keys. + * + * @param string $table table name without the prefix + * @param bool $cascade whether to truncate cascading + * @throws Exception + * @since 32.0.0 + * + * @psalm-taint-sink sql $table + */ + public function truncateTable(string $table, bool $cascade): void; + + /** * Check if a table exists * * @param string $table table name without the prefix diff --git a/lib/public/IPreview.php b/lib/public/IPreview.php index 6ab4af1b7ca..3c9eadd4577 100644 --- a/lib/public/IPreview.php +++ b/lib/public/IPreview.php @@ -71,12 +71,14 @@ interface IPreview { * @param bool $crop * @param string $mode * @param string $mimeType To force a given mimetype for the file (files_versions needs this) + * @param bool $cacheResult Whether or not to cache the preview on the filesystem. Default to true. Can be useful to set to false to limit the amount of stored previews. * @return ISimpleFile * @throws NotFoundException * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) * @since 11.0.0 - \InvalidArgumentException was added in 12.0.0 + * @since 32.0.0 - getPreview($cacheResult) added the $cacheResult argument to the signature */ - public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null); + public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null, bool $cacheResult = true); /** * Returns true if the passed mime type is supported @@ -90,10 +92,12 @@ interface IPreview { * Check if a preview can be generated for a file * * @param \OCP\Files\FileInfo $file + * @param string|null $mimeType To force a given mimetype for the file * @return bool * @since 8.0.0 + * @since 32.0.0 - isAvailable($mimeType) added the $mimeType argument to the signature */ - public function isAvailable(\OCP\Files\FileInfo $file); + public function isAvailable(\OCP\Files\FileInfo $file, ?string $mimeType = null); /** * Generates previews of a file diff --git a/lib/public/IRequest.php b/lib/public/IRequest.php index dedff769f77..cbac143d775 100644 --- a/lib/public/IRequest.php +++ b/lib/public/IRequest.php @@ -84,7 +84,7 @@ interface IRequest { * @since 13.0.1 * @since 28.0.0 The regex has a group matching the version number */ - public const USER_AGENT_THUNDERBIRD_ADDON = '/^Mozilla\/5\.0 \([A-Za-z ]+\) Nextcloud\-Thunderbird v([^ ]*).*$/'; + public const USER_AGENT_THUNDERBIRD_ADDON = '/^Filelink for \*cloud\/([1-9]\d*\.\d+\.\d+)$/'; /** * @since 26.0.0 @@ -305,4 +305,14 @@ interface IRequest { * @since 8.1.0 */ public function getServerHost(): string; + + /** + * If decoding the request content failed, throw an exception. + * Currently only \JsonException for json decoding errors, + * but in the future may throw other exceptions for other decoding issues. + * + * @throws \Exception + * @since 32.0.0 + */ + public function throwDecodingExceptionIfAny(): void; } diff --git a/lib/public/IServerContainer.php b/lib/public/IServerContainer.php index 82da8779a66..6d5095c92da 100644 --- a/lib/public/IServerContainer.php +++ b/lib/public/IServerContainer.php @@ -8,10 +8,6 @@ declare(strict_types=1); */ namespace OCP; -use OCP\Federation\ICloudFederationFactory; -use OCP\Federation\ICloudFederationProviderManager; -use OCP\Log\ILogFactory; -use OCP\Security\IContentSecurityPolicyManager; use Psr\Container\ContainerInterface; /** @@ -26,35 +22,6 @@ use Psr\Container\ContainerInterface; * @since 6.0.0 */ interface IServerContainer extends ContainerInterface, IContainer { - /** - * The calendar manager will act as a broker between consumers for calendar information and - * providers which actual deliver the calendar information. - * - * @return \OCP\Calendar\IManager - * @since 13.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getCalendarManager(); - - /** - * The calendar resource backend manager will act as a broker between consumers - * for calendar resource information an providers which actual deliver the room information. - * - * @return \OCP\Calendar\Resource\IBackend - * @since 14.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getCalendarResourceBackendManager(); - - /** - * The calendar room backend manager will act as a broker between consumers - * for calendar room information an providers which actual deliver the room information. - * - * @return \OCP\Calendar\Room\IBackend - * @since 14.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getCalendarRoomBackendManager(); /** * The contacts manager will act as a broker between consumers for contacts information and @@ -78,25 +45,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getRequest(); /** - * Returns the preview manager which can create preview images for a given file - * - * @return \OCP\IPreview - * @since 6.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getPreviewManager(); - - /** - * Returns the tag manager which can get and set tags for different object types - * - * @see \OCP\ITagManager::load() - * @return \OCP\ITagManager - * @since 6.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getTagManager(); - - /** * Returns the root folder of ownCloud's data directory * * @return \OCP\Files\IRootFolder @@ -144,15 +92,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getUserSession(); /** - * Returns the navigation manager - * - * @return \OCP\INavigationManager - * @since 6.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getNavigationManager(); - - /** * Returns the config manager * * @return \OCP\IConfig @@ -189,24 +128,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getSecureRandom(); /** - * Returns a CredentialsManager instance - * - * @return \OCP\Security\ICredentialsManager - * @since 9.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getCredentialsManager(); - - /** - * Returns the app config manager - * - * @return \OCP\IAppConfig - * @since 7.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getAppConfig(); - - /** * @return \OCP\L10N\IFactory * @since 8.2.0 * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get @@ -238,13 +159,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getEncryptionFilesHelper(); /** - * @return \OCP\Encryption\Keys\IStorage - * @since 8.1.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getEncryptionKeyStorage(); - - /** * Returns the URL generator * * @return \OCP\IURLGenerator @@ -299,15 +213,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getDatabaseConnection(); /** - * Returns an avatar manager, used for avatar functionality - * - * @return \OCP\IAvatarManager - * @since 6.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getAvatarManager(); - - /** * Returns an job list for controlling background jobs * * @return \OCP\BackgroundJob\IJobList @@ -317,24 +222,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getJobList(); /** - * returns a log factory instance - * - * @return ILogFactory - * @since 14.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getLogFactory(); - - /** - * Returns a router for generating and matching urls - * - * @return \OCP\Route\IRouter - * @since 7.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getRouter(); - - /** * Get the certificate manager * * @return \OCP\ICertificateManager @@ -344,35 +231,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getCertificateManager(); /** - * Returns an instance of the HTTP client service - * - * @return \OCP\Http\Client\IClientService - * @since 8.1.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getHTTPClientService(); - - /** - * Get the active event logger - * - * @return \OCP\Diagnostics\IEventLogger - * @since 8.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getEventLogger(); - - /** - * Get the active query logger - * - * The returned logger only logs data when debug mode is enabled - * - * @return \OCP\Diagnostics\IQueryLogger - * @since 8.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getQueryLogger(); - - /** * Get the manager for temporary files and folders * * @return \OCP\ITempManager @@ -400,28 +258,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getWebRoot(); /** - * @return \OCP\Files\Config\IMountProviderCollection - * @since 8.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getMountProviderCollection(); - - /** - * Get the IniWrapper - * - * @return \bantu\IniGetWrapper\IniGetWrapper - * @since 8.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getIniWrapper(); - /** - * @return \OCP\Command\IBus - * @since 8.1.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getCommandBus(); - - /** * Creates a new mailer * * @return \OCP\Mail\IMailer @@ -440,13 +276,6 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getLockingProvider(); /** - * @return \OCP\Files\Mount\IMountManager - * @since 8.2.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getMountManager(); - - /** * Get the MimeTypeDetector * * @return \OCP\Files\IMimeTypeDetector @@ -474,108 +303,9 @@ interface IServerContainer extends ContainerInterface, IContainer { public function getNotificationManager(); /** - * @return \OCP\Comments\ICommentsManager - * @since 9.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getCommentsManager(); - - /** - * Returns the system-tag manager - * - * @return \OCP\SystemTag\ISystemTagManager - * - * @since 9.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getSystemTagManager(); - - /** - * Returns the system-tag object mapper - * - * @return \OCP\SystemTag\ISystemTagObjectMapper - * - * @since 9.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getSystemTagObjectMapper(); - - /** - * Returns the share manager - * - * @return \OCP\Share\IManager - * @since 9.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getShareManager(); - - /** - * @return IContentSecurityPolicyManager - * @since 9.0.0 - * @deprecated 17.0.0 Use the AddContentSecurityPolicyEvent - */ - public function getContentSecurityPolicyManager(); - - /** - * @return \OCP\IDateTimeZone - * @since 8.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getDateTimeZone(); - - /** - * @return \OCP\IDateTimeFormatter - * @since 8.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getDateTimeFormatter(); - - /** * @return \OCP\Federation\ICloudIdManager * @since 12.0.0 * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get */ public function getCloudIdManager(); - - /** - * @return \OCP\GlobalScale\IConfig - * @since 14.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getGlobalScaleConfig(); - - /** - * @return ICloudFederationFactory - * @since 14.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getCloudFederationFactory(); - - /** - * @return ICloudFederationProviderManager - * @since 14.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getCloudFederationProviderManager(); - - /** - * @return \OCP\Remote\Api\IApiFactory - * @since 13.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getRemoteApiFactory(); - - /** - * @return \OCP\Remote\IInstanceFactory - * @since 13.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getRemoteInstanceFactory(); - - /** - * @return \OCP\Files\Storage\IStorageFactory - * @since 15.0.0 - * @deprecated 20.0.0 have it injected or fetch it through \Psr\Container\ContainerInterface::get - */ - public function getStorageFactory(); } diff --git a/lib/public/ITempManager.php b/lib/public/ITempManager.php index 90db91b2ab4..ac8f829f357 100644 --- a/lib/public/ITempManager.php +++ b/lib/public/ITempManager.php @@ -16,20 +16,20 @@ interface ITempManager { /** * Create a temporary file and return the path * - * @param string $postFix - * @return string + * @param string $postFix Postfix appended to the temporary file name + * * @since 8.0.0 */ - public function getTemporaryFile($postFix = ''); + public function getTemporaryFile(string $postFix = ''): string|false; /** * Create a temporary folder and return the path * - * @param string $postFix - * @return string + * @param string $postFix Postfix appended to the temporary folder name + * * @since 8.0.0 */ - public function getTemporaryFolder($postFix = ''); + public function getTemporaryFolder(string $postFix = ''): string|false; /** * Remove the temporary files and folders generated during this request diff --git a/lib/public/IUser.php b/lib/public/IUser.php index 8c7d6a1283e..945e7e1602a 100644 --- a/lib/public/IUser.php +++ b/lib/public/IUser.php @@ -16,6 +16,11 @@ use InvalidArgumentException; */ interface IUser { /** + * @since 32.0.0 + */ + public const MAX_USERID_LENGTH = 64; + + /** * get the user id * * @return string @@ -50,13 +55,22 @@ interface IUser { * @return int * @since 8.0.0 */ - public function getLastLogin(); + public function getLastLogin(): int; + + /** + * Returns the timestamp of the user's first login, 0 if the user did never login, or -1 if the data is unknown (first login was on an older version) + * + * @since 31.0.0 + */ + public function getFirstLogin(): int; /** - * updates the timestamp of the most recent login of this user + * Updates the timestamp of the most recent login of this user (and first login if needed) + * + * @return bool whether this is the first login * @since 8.0.0 */ - public function updateLastLoginTimestamp(); + public function updateLastLoginTimestamp(): bool; /** * Delete the user @@ -141,6 +155,13 @@ interface IUser { public function canChangeDisplayName(); /** + * Check if the backend supports changing email + * + * @since 32.0.0 + */ + public function canChangeEmail(): bool; + + /** * check if the user is enabled * * @return bool @@ -260,6 +281,15 @@ interface IUser { public function getQuota(); /** + * Get the users' quota in machine readable form. If a specific quota is set + * for the user, then the quota is returned in bytes. Otherwise the default value is returned. + * If a default setting was not set, it is return as `\OCP\Files\FileInfo::SPACE_UNLIMITED`, i.e. quota is not limited. + * + * @since 32.0.0 + */ + public function getQuotaBytes(): int|float; + + /** * set the users' quota * * @param string $quota diff --git a/lib/public/IUserManager.php b/lib/public/IUserManager.php index 091ccd89048..dbd1e188bec 100644 --- a/lib/public/IUserManager.php +++ b/lib/public/IUserManager.php @@ -32,14 +32,14 @@ interface IUserManager { /** * register a user backend * - * @param \OCP\UserInterface $backend * @since 8.0.0 + * @return void */ - public function registerBackend($backend); + public function registerBackend(UserInterface $backend); /** * Get the active backends - * @return \OCP\UserInterface[] + * @return UserInterface[] * @since 8.0.0 */ public function getBackends(); @@ -47,16 +47,17 @@ interface IUserManager { /** * remove a user backend * - * @param \OCP\UserInterface $backend * @since 8.0.0 + * @return void */ - public function removeBackend($backend); + public function removeBackend(UserInterface $backend); /** * remove all user backends * @since 8.0.0 + * @return void */ - public function clearBackends() ; + public function clearBackends(); /** * get a user by user id @@ -164,6 +165,16 @@ interface IUserManager { public function countUsers(); /** + * Get how many users exists in total, whithin limit + * + * @param int $limit Limit the count to avoid resource waste. 0 to disable + * @param bool $onlyMappedUsers Count mapped users instead of all users for compatible backends + * + * @since 31.0.0 + */ + public function countUsersTotal(int $limit = 0, bool $onlyMappedUsers = false): int|false; + + /** * @param \Closure $callback * @psalm-param \Closure(\OCP\IUser):void $callback * @param string $search @@ -221,4 +232,15 @@ interface IUserManager { * @since 30.0.0 */ public function getLastLoggedInUsers(?int $limit = null, int $offset = 0, string $search = ''): array; + + /** + * Gets the list of users. + * An iterator is returned allowing the caller to stop the iteration at any time. + * The offset argument allows the caller to continue the iteration at a specific offset. + * + * @param int $offset from which offset to fetch + * @return \Iterator<IUser> list of IUser object + * @since 32.0.0 + */ + public function getSeenUsers(int $offset = 0): \Iterator; } diff --git a/lib/public/L10N/ILanguageIterator.php b/lib/public/L10N/ILanguageIterator.php index cba0feefdcf..27f850d4235 100644 --- a/lib/public/L10N/ILanguageIterator.php +++ b/lib/public/L10N/ILanguageIterator.php @@ -21,7 +21,7 @@ namespace OCP\L10N; * if settings are not present or truncating is not applicable, the iterator * skips to the next valid item itself * - * + * @template-extends \Iterator<int, string> * @since 14.0.0 */ interface ILanguageIterator extends \Iterator { @@ -36,22 +36,20 @@ interface ILanguageIterator extends \Iterator { * Move forward to next element * * @since 14.0.0 - * @return void */ - #[\ReturnTypeWillChange] - public function next(); + public function next(): void; /** * Return the key of the current element * * @since 14.0.0 */ - public function key():int; + public function key(): int; /** * Checks if current position is valid * * @since 14.0.0 */ - public function valid():bool; + public function valid(): bool; } diff --git a/lib/public/LDAP/IDeletionFlagSupport.php b/lib/public/LDAP/IDeletionFlagSupport.php index 89615c67307..1ae38e1a5d1 100644 --- a/lib/public/LDAP/IDeletionFlagSupport.php +++ b/lib/public/LDAP/IDeletionFlagSupport.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -17,7 +18,7 @@ interface IDeletionFlagSupport { * @since 11.0.0 */ public function flagRecord($uid); - + /** * Unflag record for deletion. * @param string $uid user id diff --git a/lib/public/LDAP/ILDAPProvider.php b/lib/public/LDAP/ILDAPProvider.php index 22f4b872adc..7e1f27eb368 100644 --- a/lib/public/LDAP/ILDAPProvider.php +++ b/lib/public/LDAP/ILDAPProvider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/LDAP/ILDAPProviderFactory.php b/lib/public/LDAP/ILDAPProviderFactory.php index f175a3abfd0..720027ce012 100644 --- a/lib/public/LDAP/ILDAPProviderFactory.php +++ b/lib/public/LDAP/ILDAPProviderFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Lock/LockedException.php b/lib/public/Lock/LockedException.php index ce41d2d7242..799886a2dbb 100644 --- a/lib/public/Lock/LockedException.php +++ b/lib/public/Lock/LockedException.php @@ -24,6 +24,8 @@ class LockedException extends \Exception { /** @var string|null */ private $existingLock; + private ?string $readablePath; + /** * LockedException constructor. * @@ -34,6 +36,7 @@ class LockedException extends \Exception { * @since 8.1.0 */ public function __construct(string $path, ?\Exception $previous = null, ?string $existingLock = null, ?string $readablePath = null) { + $this->readablePath = $readablePath; if ($readablePath) { $message = "\"$path\"(\"$readablePath\") is locked"; } else { @@ -62,4 +65,13 @@ class LockedException extends \Exception { public function getExistingLock(): ?string { return $this->existingLock; } + + /** + * @return ?string + * @since 32.0.0 + */ + public function getReadablePath(): ?string { + return $this->readablePath; + } + } diff --git a/lib/public/Lockdown/ILockdownManager.php b/lib/public/Lockdown/ILockdownManager.php index 4ae846ae8da..fe8adaecf91 100644 --- a/lib/public/Lockdown/ILockdownManager.php +++ b/lib/public/Lockdown/ILockdownManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Log/IFileBased.php b/lib/public/Log/IFileBased.php index e3ea25fad09..ace10ee1b68 100644 --- a/lib/public/Log/IFileBased.php +++ b/lib/public/Log/IFileBased.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Log/ILogFactory.php b/lib/public/Log/ILogFactory.php index 49b56ff102c..db7adca2192 100644 --- a/lib/public/Log/ILogFactory.php +++ b/lib/public/Log/ILogFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Log/IWriter.php b/lib/public/Log/IWriter.php index 8d2b438a0fe..2fcbc094881 100644 --- a/lib/public/Log/IWriter.php +++ b/lib/public/Log/IWriter.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Log/RotationTrait.php b/lib/public/Log/RotationTrait.php index 03100613c4c..73b3b16b665 100644 --- a/lib/public/Log/RotationTrait.php +++ b/lib/public/Log/RotationTrait.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Mail/IMailer.php b/lib/public/Mail/IMailer.php index 18eaef541c0..277f7863184 100644 --- a/lib/public/Mail/IMailer.php +++ b/lib/public/Mail/IMailer.php @@ -14,7 +14,7 @@ namespace OCP\Mail; * * Example usage: * - * $mailer = \OC::$server->get(\OCP\Mail\IMailer::class); + * $mailer = \OCP\Server::get(\OCP\Mail\IMailer::class); * $message = $mailer->createMessage(); * $message->setSubject('Your Subject'); * $message->setFrom(['cloud@domain.org' => 'Nextcloud Notifier']); diff --git a/lib/public/Mail/Provider/IAddress.php b/lib/public/Mail/Provider/IAddress.php index 121467390dc..47bb9148968 100644 --- a/lib/public/Mail/Provider/IAddress.php +++ b/lib/public/Mail/Provider/IAddress.php @@ -17,7 +17,7 @@ namespace OCP\Mail\Provider; * */ interface IAddress { - + /** * sets the mail address * diff --git a/lib/public/Mail/Provider/IManager.php b/lib/public/Mail/Provider/IManager.php index 3c639ef21ef..b55fed3f26f 100644 --- a/lib/public/Mail/Provider/IManager.php +++ b/lib/public/Mail/Provider/IManager.php @@ -17,7 +17,7 @@ namespace OCP\Mail\Provider; * */ interface IManager { - + /** * determine if any mail providers are registered * diff --git a/lib/public/Mail/Provider/IMessage.php b/lib/public/Mail/Provider/IMessage.php index e3dfbe6981d..599d9b0566d 100644 --- a/lib/public/Mail/Provider/IMessage.php +++ b/lib/public/Mail/Provider/IMessage.php @@ -17,7 +17,7 @@ namespace OCP\Mail\Provider; * */ interface IMessage { - + /** * arbitrary unique text string identifying this message * @@ -117,7 +117,7 @@ interface IMessage { * @return self return this object for command chaining */ public function setBcc(IAddress ...$value): self; - + /** * gets the blind copy to recipient(s) of this message * diff --git a/lib/public/Migration/Attributes/AddColumn.php b/lib/public/Migration/Attributes/AddColumn.php index 8d16b9b6e8d..d84a0c1f60c 100644 --- a/lib/public/Migration/Attributes/AddColumn.php +++ b/lib/public/Migration/Attributes/AddColumn.php @@ -23,8 +23,8 @@ class AddColumn extends ColumnMigrationAttribute { */ public function definition(): string { $type = is_null($this->getType()) ? '' : ' (' . $this->getType()->value . ')'; - return empty($this->getName()) ? - 'Addition of a new column' . $type . ' to table \'' . $this->getTable() . '\'' + return empty($this->getName()) + ? 'Addition of a new column' . $type . ' to table \'' . $this->getTable() . '\'' : 'Addition of column \'' . $this->getName() . '\'' . $type . ' to table \'' . $this->getTable() . '\''; } } diff --git a/lib/public/Migration/Attributes/DropColumn.php b/lib/public/Migration/Attributes/DropColumn.php index 1de0ba58489..a1cd5790cc7 100644 --- a/lib/public/Migration/Attributes/DropColumn.php +++ b/lib/public/Migration/Attributes/DropColumn.php @@ -22,8 +22,8 @@ class DropColumn extends ColumnMigrationAttribute { * @since 30.0.0 */ public function definition(): string { - return empty($this->getName()) ? - 'Deletion of a column from table \'' . $this->getTable() . '\'' + return empty($this->getName()) + ? 'Deletion of a column from table \'' . $this->getTable() . '\'' : 'Deletion of column \'' . $this->getName() . '\' from table \'' . $this->getTable() . '\''; } } diff --git a/lib/public/Migration/Attributes/ModifyColumn.php b/lib/public/Migration/Attributes/ModifyColumn.php index ef7250ffb34..6fc44ebb824 100644 --- a/lib/public/Migration/Attributes/ModifyColumn.php +++ b/lib/public/Migration/Attributes/ModifyColumn.php @@ -23,8 +23,8 @@ class ModifyColumn extends ColumnMigrationAttribute { */ public function definition(): string { $type = is_null($this->getType()) ? '' : ' to ' . $this->getType()->value; - return empty($this->getName()) ? - 'Modification of a column from table \'' . $this->getTable() . '\'' . $type + return empty($this->getName()) + ? 'Modification of a column from table \'' . $this->getTable() . '\'' . $type : 'Modification of column \'' . $this->getName() . '\' from table \'' . $this->getTable() . '\'' . $type; } } diff --git a/lib/public/Navigation/Events/LoadAdditionalEntriesEvent.php b/lib/public/Navigation/Events/LoadAdditionalEntriesEvent.php new file mode 100644 index 00000000000..61db417b927 --- /dev/null +++ b/lib/public/Navigation/Events/LoadAdditionalEntriesEvent.php @@ -0,0 +1,17 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Navigation\Events; + +use OCP\EventDispatcher\Event; + +/** + * @since 31.0.0 + */ +class LoadAdditionalEntriesEvent extends Event { +} diff --git a/lib/public/OCM/ICapabilityAwareOCMProvider.php b/lib/public/OCM/ICapabilityAwareOCMProvider.php new file mode 100644 index 00000000000..ae290abd2f8 --- /dev/null +++ b/lib/public/OCM/ICapabilityAwareOCMProvider.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\OCM; + +/** + * Version 1.1 and 1.2 extensions to the Open Cloud Mesh Discovery API + * @link https://github.com/cs3org/OCM-API/ + * @since 32.0.0 + */ +interface ICapabilityAwareOCMProvider extends IOCMProvider { + /** + * get the capabilities + * + * @return array + * @since 32.0.0 + */ + public function getCapabilities(): array; + + /** + * get the provider name + * + * @return string + * @since 32.0.0 + */ + public function getProvider(): string; + + /** + * returns the invite accept dialog + * + * @return string + * @since 32.0.0 + */ + public function getInviteAcceptDialog(): string; + + /** + * set the capabilities + * + * @param array $capabilities + * + * @return $this + * @since 32.0.0 + */ + public function setCapabilities(array $capabilities): static; + + /** + * set the invite accept dialog + * + * @param string $inviteAcceptDialog + * + * @return $this + * @since 32.0.0 + */ + public function setInviteAcceptDialog(string $inviteAcceptDialog): static; +} diff --git a/lib/public/OCM/IOCMProvider.php b/lib/public/OCM/IOCMProvider.php index a588d869655..7141b0a9ab9 100644 --- a/lib/public/OCM/IOCMProvider.php +++ b/lib/public/OCM/IOCMProvider.php @@ -16,6 +16,7 @@ use OCP\OCM\Exceptions\OCMProviderException; * Model based on the Open Cloud Mesh Discovery API * @link https://github.com/cs3org/OCM-API/ * @since 28.0.0 + * @deprecated 32.0.0 Please use {@see \OCP\OCM\ICapabilityAwareOCMProvider} */ interface IOCMProvider extends JsonSerializable { /** @@ -151,7 +152,7 @@ interface IOCMProvider extends JsonSerializable { * enabled: bool, * apiVersion: '1.0-proposal1', * endPoint: string, - * publicKey: array{ + * publicKey?: array{ * keyId: string, * publicKeyPem: string * }, diff --git a/lib/public/Profile/IProfileManager.php b/lib/public/Profile/IProfileManager.php index 0a1e6733e58..f4e90e39d12 100644 --- a/lib/public/Profile/IProfileManager.php +++ b/lib/public/Profile/IProfileManager.php @@ -9,10 +9,12 @@ declare(strict_types=1); namespace OCP\Profile; +use OC\Core\ResponseDefinitions; use OCP\Accounts\IAccountManager; use OCP\IUser; /** + * @psalm-import-type CoreProfileFields from ResponseDefinitions * @since 28.0.0 */ interface IProfileManager { @@ -83,7 +85,7 @@ interface IProfileManager { * Return the profile parameters of the target user that are visible to the visiting user * in an associative array * - * @return array{userId: string, address?: string|null, biography?: string|null, displayname?: string|null, headline?: string|null, isUserAvatarVisible?: bool, organisation?: string|null, pronouns?: string|null, role?: string|null, actions: list<array{id: string, icon: string, title: string, target: ?string}>} + * @psalm-return CoreProfileFields * @since 28.0.0 */ public function getProfileFields(IUser $targetUser, ?IUser $visitingUser): array; diff --git a/lib/public/Profiler/IProfile.php b/lib/public/Profiler/IProfile.php index ddbad4b4388..89eb709d061 100644 --- a/lib/public/Profiler/IProfile.php +++ b/lib/public/Profiler/IProfile.php @@ -17,7 +17,7 @@ use OCP\DataCollector\IDataCollector; * * ```php * <?php - * $profiler = \OC::$server->get(IProfiler::class); + * $profiler = \OCP\Server::get(IProfiler::class); * $profiles = $profiler->find('/settings/users', 10); * ``` * diff --git a/lib/public/Remote/Api/IApiCollection.php b/lib/public/Remote/Api/IApiCollection.php index da1964997bd..e7181ab20f2 100644 --- a/lib/public/Remote/Api/IApiCollection.php +++ b/lib/public/Remote/Api/IApiCollection.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Remote/Api/IApiFactory.php b/lib/public/Remote/Api/IApiFactory.php index 0e95dc98e70..2089c61be82 100644 --- a/lib/public/Remote/Api/IApiFactory.php +++ b/lib/public/Remote/Api/IApiFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Remote/Api/ICapabilitiesApi.php b/lib/public/Remote/Api/ICapabilitiesApi.php index d9ab037bcc6..d0e3fd7ad80 100644 --- a/lib/public/Remote/Api/ICapabilitiesApi.php +++ b/lib/public/Remote/Api/ICapabilitiesApi.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Remote/Api/IUserApi.php b/lib/public/Remote/Api/IUserApi.php index c8b5e64d003..268594c0340 100644 --- a/lib/public/Remote/Api/IUserApi.php +++ b/lib/public/Remote/Api/IUserApi.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Remote/ICredentials.php b/lib/public/Remote/ICredentials.php index efe87a350c8..c261d57093d 100644 --- a/lib/public/Remote/ICredentials.php +++ b/lib/public/Remote/ICredentials.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Remote/IInstance.php b/lib/public/Remote/IInstance.php index 47c10cb4ac1..6186c2e1819 100644 --- a/lib/public/Remote/IInstance.php +++ b/lib/public/Remote/IInstance.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Remote/IInstanceFactory.php b/lib/public/Remote/IInstanceFactory.php index 15435901a74..1cd2b3330ce 100644 --- a/lib/public/Remote/IInstanceFactory.php +++ b/lib/public/Remote/IInstanceFactory.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Remote/IUser.php b/lib/public/Remote/IUser.php index 3c22695c20b..329e8876c0d 100644 --- a/lib/public/Remote/IUser.php +++ b/lib/public/Remote/IUser.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/RichObjectStrings/Definitions.php b/lib/public/RichObjectStrings/Definitions.php index 5974659e16b..d6717e54aea 100644 --- a/lib/public/RichObjectStrings/Definitions.php +++ b/lib/public/RichObjectStrings/Definitions.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -374,6 +375,12 @@ class Definitions { 'description' => 'The blurhash of the image', 'example' => 'LEHV9uae2yk8pyo0adR*.7kCMdnj', ], + 'hide-download' => [ + 'since' => '31.0.5', + 'required' => false, + 'description' => 'Whether the download option should be hidden. If not set to `yes` the option can be shown', + 'example' => 'yes', + ], ], ], 'forms-form' => [ diff --git a/lib/public/RichObjectStrings/IValidator.php b/lib/public/RichObjectStrings/IValidator.php index 3bf83582adc..fc486663c73 100644 --- a/lib/public/RichObjectStrings/IValidator.php +++ b/lib/public/RichObjectStrings/IValidator.php @@ -26,6 +26,7 @@ namespace OCP\RichObjectStrings; * path?: string, * mimetype?: string, * 'preview-available'?: 'yes'|'no', + * 'hide-download'?: 'yes'|'no', * mtime?: string, * latitude?: string, * longitude?: string, diff --git a/lib/public/RichObjectStrings/InvalidObjectExeption.php b/lib/public/RichObjectStrings/InvalidObjectExeption.php index 0316310c5f9..603f4432ba6 100644 --- a/lib/public/RichObjectStrings/InvalidObjectExeption.php +++ b/lib/public/RichObjectStrings/InvalidObjectExeption.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Route/IRoute.php b/lib/public/Route/IRoute.php index fffd4b9c1a1..7dba6225aff 100644 --- a/lib/public/Route/IRoute.php +++ b/lib/public/Route/IRoute.php @@ -34,8 +34,9 @@ interface IRoute { * it is called directly * * @param string $file - * @return void + * @return $this * @since 7.0.0 + * @deprecated 32.0.0 Use a proper controller instead */ public function actionInclude($file); @@ -70,6 +71,7 @@ interface IRoute { * This function is called with $class set to a callable or * to the class with $function * @since 7.0.0 + * @deprecated 32.0.0 Use a proper controller instead */ public function action($class, $function = null); diff --git a/lib/public/Security/IContentSecurityPolicyManager.php b/lib/public/Security/IContentSecurityPolicyManager.php index 3df0da465b2..00cdcc2c454 100644 --- a/lib/public/Security/IContentSecurityPolicyManager.php +++ b/lib/public/Security/IContentSecurityPolicyManager.php @@ -24,7 +24,7 @@ interface IContentSecurityPolicyManager { * Note that the adjustment is only applied to applications that use AppFramework * controllers. * - * To use this from your `app.php` use `\OC::$server->getContentSecurityPolicyManager()->addDefaultPolicy($policy)`, + * To use this from your `app.php` use `\OCP\Server::get(IContentSecurityPolicyManager::class)->addDefaultPolicy($policy)`, * $policy has to be of type `\OCP\AppFramework\Http\ContentSecurityPolicy`. * * WARNING: Using this API incorrectly may make the instance more insecure. diff --git a/lib/public/Security/ICrypto.php b/lib/public/Security/ICrypto.php index c2ba4cc9c97..78b0fc14d6d 100644 --- a/lib/public/Security/ICrypto.php +++ b/lib/public/Security/ICrypto.php @@ -13,8 +13,8 @@ namespace OCP\Security; * it will use the secret defined in config.php as key. Additionally the message will be HMAC'd. * * Usage: - * $encryptWithDefaultPassword = \OC::$server->getCrypto()->encrypt('EncryptedText'); - * $encryptWithCustomPassword = \OC::$server->getCrypto()->encrypt('EncryptedText', 'password'); + * $encryptWithDefaultPassword = \OCP\Server::get(ICrypto::class)->encrypt('EncryptedText'); + * $encryptWithCustomPassword = \OCP\Server::get(ICrypto::class)->encrypt('EncryptedText', 'password'); * * @since 8.0.0 */ diff --git a/lib/public/Security/IHasher.php b/lib/public/Security/IHasher.php index d985ffe48ab..d0d6e4e9028 100644 --- a/lib/public/Security/IHasher.php +++ b/lib/public/Security/IHasher.php @@ -19,10 +19,10 @@ namespace OCP\Security; * * Usage: * // Hashing a message - * $hash = \OC::$server->get(\OCP\Security\IHasher::class)->hash('MessageToHash'); + * $hash = \OCP\Server::get(\OCP\Security\IHasher::class)->hash('MessageToHash'); * // Verifying a message - $newHash will contain the newly calculated hash * $newHash = null; - * var_dump(\OC::$server->get(\OCP\Security\IHasher::class)->verify('a', '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8', $newHash)); + * var_dump(\OCP\Server::get(\OCP\Security\IHasher::class)->verify('a', '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8', $newHash)); * var_dump($newHash); * * @since 8.0.0 diff --git a/lib/public/Security/ISecureRandom.php b/lib/public/Security/ISecureRandom.php index aa191ca348f..0f4a79e08e0 100644 --- a/lib/public/Security/ISecureRandom.php +++ b/lib/public/Security/ISecureRandom.php @@ -14,7 +14,7 @@ namespace OCP\Security; * use a fallback. * * Usage: - * \OC::$server->get(ISecureRandom::class)->generate(10); + * \OCP\Server::get(ISecureRandom::class)->generate(10); * * @since 8.0.0 */ diff --git a/lib/public/Server.php b/lib/public/Server.php index 55dbfed578e..e30d67701f6 100644 --- a/lib/public/Server.php +++ b/lib/public/Server.php @@ -15,6 +15,7 @@ use Psr\Container\NotFoundExceptionInterface; * use whenever possible dependency injections instead. * * ```php + * use OCP\ITagManager; * use OCP\Server; * * $tagManager = Server::get(ITagManager::class); @@ -24,12 +25,9 @@ use Psr\Container\NotFoundExceptionInterface; */ final class Server { /** - * @template T - * @param class-string<T>|string $serviceName - * @return T|mixed - * @psalm-template S as class-string<T>|string - * @psalm-param S $serviceName - * @psalm-return (S is class-string<T> ? T : mixed) + * @psalm-template T + * @psalm-param class-string<T>|string $serviceName + * @psalm-return ($serviceName is class-string<T> ? T : mixed) * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface * @since 25.0.0 diff --git a/lib/public/ServerVersion.php b/lib/public/ServerVersion.php index 637c34d3619..d44452d42d0 100644 --- a/lib/public/ServerVersion.php +++ b/lib/public/ServerVersion.php @@ -77,6 +77,12 @@ class ServerVersion { * @since 31.0.0 */ public function getChannel(): string { + $updaterChannel = Server::get(IConfig::class)->getSystemValueString('updater.release.channel', $this->channel); + + if (in_array($updaterChannel, ['beta', 'stable', 'enterprise', 'git'], true)) { + return $updaterChannel; + } + return $this->channel; } diff --git a/lib/public/Settings/IDeclarativeSettingsForm.php b/lib/public/Settings/IDeclarativeSettingsForm.php index d471cdf4a93..419905b7b23 100644 --- a/lib/public/Settings/IDeclarativeSettingsForm.php +++ b/lib/public/Settings/IDeclarativeSettingsForm.php @@ -27,6 +27,7 @@ namespace OCP\Settings; * label?: string, * default: mixed, * options?: list<string|array{name: string, value: mixed}>, + * sensitive?: boolean, * } * * @psalm-type DeclarativeSettingsFormFieldWithValue = DeclarativeSettingsFormField&array{ diff --git a/lib/public/Settings/IIconSection.php b/lib/public/Settings/IIconSection.php index e514a0176b7..4d0fe40aa29 100644 --- a/lib/public/Settings/IIconSection.php +++ b/lib/public/Settings/IIconSection.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Settings/IManager.php b/lib/public/Settings/IManager.php index 0bb1a396671..954fd3fdb56 100644 --- a/lib/public/Settings/IManager.php +++ b/lib/public/Settings/IManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Settings/ISettings.php b/lib/public/Settings/ISettings.php index a733eb7956d..e33556f0b4a 100644 --- a/lib/public/Settings/ISettings.php +++ b/lib/public/Settings/ISettings.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Share/Exceptions/ShareTokenException.php b/lib/public/Share/Exceptions/ShareTokenException.php new file mode 100644 index 00000000000..027d00640e9 --- /dev/null +++ b/lib/public/Share/Exceptions/ShareTokenException.php @@ -0,0 +1,16 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Share\Exceptions; + +use Exception; + +/** + * @since 31.0.0 + */ +class ShareTokenException extends Exception { +} diff --git a/lib/public/Share/IAttributes.php b/lib/public/Share/IAttributes.php index fad19c60aad..9ddd8275dd6 100644 --- a/lib/public/Share/IAttributes.php +++ b/lib/public/Share/IAttributes.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2019 ownCloud GmbH * SPDX-License-Identifier: AGPL-3.0-only diff --git a/lib/public/Share/IManager.php b/lib/public/Share/IManager.php index c3a8494a5ac..35915ad9d90 100644 --- a/lib/public/Share/IManager.php +++ b/lib/public/Share/IManager.php @@ -13,6 +13,7 @@ use OCP\Files\Node; use OCP\IUser; use OCP\Share\Exceptions\GenericShareException; use OCP\Share\Exceptions\ShareNotFound; +use OCP\Share\Exceptions\ShareTokenException; /** * This interface allows to manage sharing files between users and groups. @@ -463,6 +464,22 @@ interface IManager { */ public function ignoreSecondDisplayName(): bool; + + /** + * Check if custom tokens are allowed + * + * @since 31.0.0 + */ + public function allowCustomTokens(): bool; + + /** + * Check if the current user can view the share + * even if the download is disabled. + * + * @since 32.0.0 + */ + public function allowViewWithoutDownload(): bool; + /** * Check if the current user can enumerate the target user * @@ -476,11 +493,9 @@ interface IManager { /** * Check if sharing is disabled for the given user * - * @param string $userId - * @return bool * @since 9.0.0 */ - public function sharingDisabledForUser($userId); + public function sharingDisabledForUser(?string $userId): bool; /** * Check if outgoing server2server shares are allowed @@ -522,4 +537,12 @@ interface IManager { * @since 18.0.0 */ public function getAllShares(): iterable; + + /** + * Generate a unique share token + * + * @throws ShareTokenException Failed to generate a unique token + * @since 31.0.0 + */ + public function generateToken(): string; } diff --git a/lib/public/Share/IProviderFactory.php b/lib/public/Share/IProviderFactory.php index 34656af2d8c..9107274c8c1 100644 --- a/lib/public/Share/IProviderFactory.php +++ b/lib/public/Share/IProviderFactory.php @@ -39,7 +39,8 @@ interface IProviderFactory { /** * @since 21.0.0 - * @param string $shareProvier + * @since 32.0.0 Fix typo in parameter name + * @param string $shareProviderClass */ - public function registerProvider(string $shareProvier): void; + public function registerProvider(string $shareProviderClass): void; } diff --git a/lib/public/Share/IShare.php b/lib/public/Share/IShare.php index cdad084ac92..5d8c64e1314 100644 --- a/lib/public/Share/IShare.php +++ b/lib/public/Share/IShare.php @@ -379,7 +379,7 @@ interface IShare { public function getExpirationDate(); /** - * Set overwrite flag for falsy expiry date vavlues + * Set overwrite flag for falsy expiry date values * * @param bool $noExpirationDate * @return \OCP\Share\IShare The modified object @@ -633,4 +633,11 @@ interface IShare { * @since 31.0.0 */ public function getReminderSent(): bool; + + /** + * Check if the current user can see this share files contents. + * This will check the download permissions as well as the global + * admin setting to allow viewing files without downloading. + */ + public function canSeeContent(): bool; } diff --git a/lib/public/Share/IShareHelper.php b/lib/public/Share/IShareHelper.php index c4a33e717f9..152fc99a446 100644 --- a/lib/public/Share/IShareHelper.php +++ b/lib/public/Share/IShareHelper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php b/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php new file mode 100644 index 00000000000..e27da7682ce --- /dev/null +++ b/lib/public/Share/IShareProviderSupportsAllSharesInFolder.php @@ -0,0 +1,24 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\Share; + +use OCP\Files\Folder; + +/** + * Allows defining a IShareProvider with support for the getAllSharesInFolder method. + * + * @since 32.0.0 + */ +interface IShareProviderSupportsAllSharesInFolder extends IShareProvider { + /** + * Get all shares in a folder. + * + * @return array<int, list<IShare>> + * @since 32.0.0 + */ + public function getAllSharesInFolder(Folder $node): array; +} diff --git a/lib/public/SystemTag/ISystemTagManager.php b/lib/public/SystemTag/ISystemTagManager.php index 04804798114..96e775d6401 100644 --- a/lib/public/SystemTag/ISystemTagManager.php +++ b/lib/public/SystemTag/ISystemTagManager.php @@ -57,8 +57,10 @@ interface ISystemTagManager { * @return ISystemTag system tag * * @throws TagAlreadyExistsException if tag already exists + * @throws TagCreationForbiddenException if user doesn't have the right to create a new tag * * @since 9.0.0 + * @since 31.0.0 Can throw TagCreationForbiddenExceptionif user doesn't have the right to create a new tag */ public function createTag(string $tagName, bool $userVisible, bool $userAssignable): ISystemTag; @@ -118,6 +120,26 @@ interface ISystemTagManager { public function canUserAssignTag(ISystemTag $tag, ?IUser $user): bool; /** + * Checks whether the given user is allowed to create new tags + * + * @param IUser|null $user user to check permission for + * @return bool true if the user is allowed to create a new tag, false otherwise + * + * @since 31.0.0 + */ + public function canUserCreateTag(?IUser $user): bool; + + /** + * Checks whether the given user is allowed to update tags + * + * @param IUser|null $user user to check permission for + * @return bool true if the user is allowed to update a tag, false otherwise + * + * @since 31.0.0 + */ + public function canUserUpdateTag(?IUser $user): bool; + + /** * Checks whether the given user is allowed to see the tag with the given id. * * @param ISystemTag $tag tag to check permission for diff --git a/lib/public/SystemTag/MapperEvent.php b/lib/public/SystemTag/MapperEvent.php index f8f130d6473..821d1b5dc5e 100644 --- a/lib/public/SystemTag/MapperEvent.php +++ b/lib/public/SystemTag/MapperEvent.php @@ -9,13 +9,14 @@ declare(strict_types=1); namespace OCP\SystemTag; use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IWebhookCompatibleEvent; /** * Class MapperEvent * * @since 9.0.0 */ -class MapperEvent extends Event { +class MapperEvent extends Event implements IWebhookCompatibleEvent { /** * @since 9.0.0 * @deprecated 22.0.0 @@ -84,4 +85,17 @@ class MapperEvent extends Event { public function getTags(): array { return $this->tags; } + + /** + * @return array + * @since 32.0.0 + */ + public function getWebhookSerializable(): array { + return [ + 'eventType' => $this->getEvent(), + 'objectType' => $this->getObjectType(), + 'objectId' => $this->getObjectId(), + 'tagIds' => $this->getTags(), + ]; + } } diff --git a/lib/public/SystemTag/TagCreationForbiddenException.php b/lib/public/SystemTag/TagCreationForbiddenException.php new file mode 100644 index 00000000000..eeae38e31f7 --- /dev/null +++ b/lib/public/SystemTag/TagCreationForbiddenException.php @@ -0,0 +1,18 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace OCP\SystemTag; + +/** + * Exception when a user doesn't have the right to create a tag + * + * @since 31.0.0 + */ +class TagCreationForbiddenException extends \RuntimeException { +} diff --git a/lib/public/SystemTag/TagUpdateForbiddenException.php b/lib/public/SystemTag/TagUpdateForbiddenException.php new file mode 100644 index 00000000000..e5c1e76f6fe --- /dev/null +++ b/lib/public/SystemTag/TagUpdateForbiddenException.php @@ -0,0 +1,18 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace OCP\SystemTag; + +/** + * Exception when a user doesn't have the right to create a tag + * + * @since 31.0.1 + */ +class TagUpdateForbiddenException extends \RuntimeException { +} diff --git a/lib/public/TaskProcessing/EShapeType.php b/lib/public/TaskProcessing/EShapeType.php index cd8d6d837da..f6cfab6b38f 100644 --- a/lib/public/TaskProcessing/EShapeType.php +++ b/lib/public/TaskProcessing/EShapeType.php @@ -154,19 +154,19 @@ enum EShapeType: int { if ($this === EShapeType::ListOfImages && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) { throw new ValidationException('Non-image list item provided for ListOfImages slot'); } - if ($this === EShapeType::Audio && !is_string($value)) { + if ($this === EShapeType::Audio && !is_numeric($value)) { throw new ValidationException('Non-audio item provided for Audio slot'); } if ($this === EShapeType::ListOfAudios && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) { throw new ValidationException('Non-audio list item provided for ListOfAudio slot'); } - if ($this === EShapeType::Video && !is_string($value)) { + if ($this === EShapeType::Video && !is_numeric($value)) { throw new ValidationException('Non-video item provided for Video slot'); } if ($this === EShapeType::ListOfVideos && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) { throw new ValidationException('Non-video list item provided for ListOfTexts slot'); } - if ($this === EShapeType::File && !is_string($value)) { + if ($this === EShapeType::File && !is_numeric($value)) { throw new ValidationException('Non-file item provided for File slot'); } if ($this === EShapeType::ListOfFiles && (!is_array($value) || count(array_filter($value, fn ($item) => !is_numeric($item))) > 0)) { diff --git a/lib/public/TaskProcessing/Events/GetTaskProcessingProvidersEvent.php b/lib/public/TaskProcessing/Events/GetTaskProcessingProvidersEvent.php new file mode 100644 index 00000000000..10c94d20406 --- /dev/null +++ b/lib/public/TaskProcessing/Events/GetTaskProcessingProvidersEvent.php @@ -0,0 +1,68 @@ +<?php + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCP\TaskProcessing\Events; + +use OCP\EventDispatcher\Event; +use OCP\TaskProcessing\IProvider; +use OCP\TaskProcessing\ITaskType; + +/** + * Event dispatched by the server to collect Task Processing Providers + * and custom Task Types from listeners (like AppAPI). + * + * Listeners should add their providers and task types using the + * addProvider() and addTaskType() methods. + * + * @since 32.0.0 + */ +class GetTaskProcessingProvidersEvent extends Event { + /** @var IProvider[] */ + private array $providers = []; + + /** @var ITaskType[] */ + private array $taskTypes = []; + + /** + * Add a Task Processing Provider. + * + * @param IProvider $provider The provider instance to add. + * @since 32.0.0 + */ + public function addProvider(IProvider $provider): void { + $this->providers[] = $provider; + } + + /** + * Get all collected Task Processing Providers. + * + * @return IProvider[] + * @since 32.0.0 + */ + public function getProviders(): array { + return $this->providers; + } + + /** + * Add a custom Task Processing Task Type. + * + * @param ITaskType $taskType The task type instance to add. + * @since 32.0.0 + */ + public function addTaskType(ITaskType $taskType): void { + $this->taskTypes[] = $taskType; + } + + /** + * Get all collected custom Task Processing Task Types. + * + * @return ITaskType[] + * @since 32.0.0 + */ + public function getTaskTypes(): array { + return $this->taskTypes; + } +} diff --git a/lib/public/TaskProcessing/IManager.php b/lib/public/TaskProcessing/IManager.php index 1b59bb12ad4..f161030f5f4 100644 --- a/lib/public/TaskProcessing/IManager.php +++ b/lib/public/TaskProcessing/IManager.php @@ -46,10 +46,14 @@ interface IManager { public function getPreferredProvider(string $taskTypeId); /** + * @param bool $showDisabled if false, disabled task types will be filtered + * @param ?string $userId to check if the user is a guest. Will be obtained from session if left to default * @return array<string, array{name: string, description: string, inputShape: ShapeDescriptor[], inputShapeEnumValues: ShapeEnumValue[][], inputShapeDefaults: array<array-key, numeric|string>, optionalInputShape: ShapeDescriptor[], optionalInputShapeEnumValues: ShapeEnumValue[][], optionalInputShapeDefaults: array<array-key, numeric|string>, outputShape: ShapeDescriptor[], outputShapeEnumValues: ShapeEnumValue[][], optionalOutputShape: ShapeDescriptor[], optionalOutputShapeEnumValues: ShapeEnumValue[][]}> * @since 30.0.0 + * @since 31.0.0 Added the `showDisabled` argument. + * @since 31.0.7 Added the `userId` argument */ - public function getAvailableTaskTypes(): array; + public function getAvailableTaskTypes(bool $showDisabled = false, ?string $userId = null): array; /** * @param Task $task The task to run diff --git a/lib/public/TaskProcessing/TaskTypes/AudioToText.php b/lib/public/TaskProcessing/TaskTypes/AudioToText.php index 3f23d00d41b..1982d4c9d28 100644 --- a/lib/public/TaskProcessing/TaskTypes/AudioToText.php +++ b/lib/public/TaskProcessing/TaskTypes/AudioToText.php @@ -34,7 +34,7 @@ class AudioToText implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/ContextAgentInteraction.php b/lib/public/TaskProcessing/TaskTypes/ContextAgentInteraction.php index f5bef6b48e3..cd08d6f4e3d 100644 --- a/lib/public/TaskProcessing/TaskTypes/ContextAgentInteraction.php +++ b/lib/public/TaskProcessing/TaskTypes/ContextAgentInteraction.php @@ -31,7 +31,7 @@ class ContextAgentInteraction implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } /** @@ -39,7 +39,7 @@ class ContextAgentInteraction implements ITaskType { * @since 31.0.0 */ public function getName(): string { - return $this->l->t('ContextAgent'); + return 'ContextAgent'; // We do not translate this } /** diff --git a/lib/public/TaskProcessing/TaskTypes/ContextWrite.php b/lib/public/TaskProcessing/TaskTypes/ContextWrite.php index 36ee8f24d3f..fd5c6a8f58b 100644 --- a/lib/public/TaskProcessing/TaskTypes/ContextWrite.php +++ b/lib/public/TaskProcessing/TaskTypes/ContextWrite.php @@ -34,7 +34,7 @@ class ContextWrite implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/GenerateEmoji.php b/lib/public/TaskProcessing/TaskTypes/GenerateEmoji.php index 89ddfa58072..2cb22b3b455 100644 --- a/lib/public/TaskProcessing/TaskTypes/GenerateEmoji.php +++ b/lib/public/TaskProcessing/TaskTypes/GenerateEmoji.php @@ -34,7 +34,7 @@ class GenerateEmoji implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToImage.php b/lib/public/TaskProcessing/TaskTypes/TextToImage.php index a4b8070e8bb..ed956d244a1 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToImage.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToImage.php @@ -34,7 +34,7 @@ class TextToImage implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToSpeech.php b/lib/public/TaskProcessing/TaskTypes/TextToSpeech.php new file mode 100644 index 00000000000..ce35be32a6f --- /dev/null +++ b/lib/public/TaskProcessing/TaskTypes/TextToSpeech.php @@ -0,0 +1,92 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\TaskProcessing\TaskTypes; + +use OCP\IL10N; +use OCP\L10N\IFactory; +use OCP\TaskProcessing\EShapeType; +use OCP\TaskProcessing\ITaskType; +use OCP\TaskProcessing\ShapeDescriptor; + +/** + * This is the task processing task type for speech generation + * @since 32.0.0 + */ +class TextToSpeech implements ITaskType { + /** + * @since 32.0.0 + */ + public const ID = 'core:text2speech'; + + private IL10N $l; + + /** + * @param IFactory $l10nFactory + * @since 32.0.0 + */ + public function __construct( + IFactory $l10nFactory, + ) { + $this->l = $l10nFactory->get('lib'); + } + + + /** + * @inheritDoc + * @since 32.0.0 + */ + public function getName(): string { + return $this->l->t('Generate speech'); + } + + /** + * @inheritDoc + * @since 32.0.0 + */ + public function getDescription(): string { + return $this->l->t('Generate speech from a transcript'); + } + + /** + * @return string + * @since 32.0.0 + */ + public function getId(): string { + return self::ID; + } + + /** + * @return ShapeDescriptor[] + * @since 32.0.0 + */ + public function getInputShape(): array { + return [ + 'input' => new ShapeDescriptor( + $this->l->t('Prompt'), + $this->l->t('Write transcript that you want the assistant to generate speech from'), + EShapeType::Text + ), + ]; + } + + /** + * @return ShapeDescriptor[] + * @since 32.0.0 + */ + public function getOutputShape(): array { + return [ + 'speech' => new ShapeDescriptor( + $this->l->t('Output speech'), + $this->l->t('The generated speech'), + EShapeType::Audio + ), + ]; + } +} diff --git a/lib/public/TaskProcessing/TaskTypes/TextToText.php b/lib/public/TaskProcessing/TaskTypes/TextToText.php index 92eaf5629e8..c39d435688a 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToText.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToText.php @@ -34,7 +34,7 @@ class TextToText implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextChangeTone.php b/lib/public/TaskProcessing/TaskTypes/TextToTextChangeTone.php index bab60976454..0ea4575a187 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextChangeTone.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextChangeTone.php @@ -31,7 +31,7 @@ class TextToTextChangeTone implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } /** diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextChat.php b/lib/public/TaskProcessing/TaskTypes/TextToTextChat.php index e9169f64837..9cf1e7ef3ce 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextChat.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextChat.php @@ -34,7 +34,7 @@ class TextToTextChat implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextChatWithTools.php b/lib/public/TaskProcessing/TaskTypes/TextToTextChatWithTools.php index e09211e940b..ebc660a3af9 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextChatWithTools.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextChatWithTools.php @@ -31,7 +31,7 @@ class TextToTextChatWithTools implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } /** diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextFormalization.php b/lib/public/TaskProcessing/TaskTypes/TextToTextFormalization.php index 81eff28f3e9..70e38f78c0b 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextFormalization.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextFormalization.php @@ -34,7 +34,7 @@ class TextToTextFormalization implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php b/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php index 9907a3605b2..dde4ea03042 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php @@ -34,7 +34,7 @@ class TextToTextHeadline implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextProofread.php b/lib/public/TaskProcessing/TaskTypes/TextToTextProofread.php new file mode 100644 index 00000000000..508794490be --- /dev/null +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextProofread.php @@ -0,0 +1,91 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\TaskProcessing\TaskTypes; + +use OCP\IL10N; +use OCP\L10N\IFactory; +use OCP\TaskProcessing\EShapeType; +use OCP\TaskProcessing\ITaskType; +use OCP\TaskProcessing\ShapeDescriptor; + +/** + * This is the task processing task type for proofreading + * @since 31.0.0 + */ +class TextToTextProofread implements ITaskType { + /** + * @since 31.0.0 + */ + public const ID = 'core:text2text:proofread'; + private IL10N $l; + + /** + * @param IFactory $l10nFactory + * @since 31.0.0 + */ + public function __construct( + IFactory $l10nFactory, + ) { + $this->l = $l10nFactory->get('lib'); + } + + + /** + * @inheritDoc + * @since 31.0.0 + */ + public function getName(): string { + return $this->l->t('Proofread'); + } + + /** + * @inheritDoc + * @since 31.0.0 + */ + public function getDescription(): string { + return $this->l->t('Proofreads a text and lists corrections'); + } + + /** + * @return string + * @since 31.0.0 + */ + public function getId(): string { + return self::ID; + } + + /** + * @return ShapeDescriptor[] + * @since 31.0.0 + */ + public function getInputShape(): array { + return [ + 'input' => new ShapeDescriptor( + $this->l->t('Text'), + $this->l->t('The text to proofread'), + EShapeType::Text + ), + ]; + } + + /** + * @return ShapeDescriptor[] + * @since 31.0.0 + */ + public function getOutputShape(): array { + return [ + 'output' => new ShapeDescriptor( + $this->l->t('Corrections'), + $this->l->t('The corrections that should be made in your text'), + EShapeType::Text + ), + ]; + } +} diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextReformulation.php b/lib/public/TaskProcessing/TaskTypes/TextToTextReformulation.php index 44c1fddc73c..120f5316aee 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextReformulation.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextReformulation.php @@ -34,7 +34,7 @@ class TextToTextReformulation implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextSimplification.php b/lib/public/TaskProcessing/TaskTypes/TextToTextSimplification.php index 580b9d92755..d107e584e3a 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextSimplification.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextSimplification.php @@ -34,7 +34,7 @@ class TextToTextSimplification implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php b/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php index 8b00c64f915..601b478c0bd 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php @@ -33,7 +33,7 @@ class TextToTextSummary implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php b/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php index a08ec6d2c0f..943cc2e2fd4 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php @@ -34,7 +34,7 @@ class TextToTextTopics implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextTranslate.php b/lib/public/TaskProcessing/TaskTypes/TextToTextTranslate.php index 11b71ec3eb2..a02550226ee 100644 --- a/lib/public/TaskProcessing/TaskTypes/TextToTextTranslate.php +++ b/lib/public/TaskProcessing/TaskTypes/TextToTextTranslate.php @@ -34,7 +34,7 @@ class TextToTextTranslate implements ITaskType { public function __construct( IFactory $l10nFactory, ) { - $this->l = $l10nFactory->get('core'); + $this->l = $l10nFactory->get('lib'); } diff --git a/lib/public/Teams/ITeamManager.php b/lib/public/Teams/ITeamManager.php index 144a141f93e..3f737b4229c 100644 --- a/lib/public/Teams/ITeamManager.php +++ b/lib/public/Teams/ITeamManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Teams/ITeamResourceProvider.php b/lib/public/Teams/ITeamResourceProvider.php index 54c4879a47c..ff724ab8ae2 100644 --- a/lib/public/Teams/ITeamResourceProvider.php +++ b/lib/public/Teams/ITeamResourceProvider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Teams/Team.php b/lib/public/Teams/Team.php index 8ece28bf648..474ebaed84f 100644 --- a/lib/public/Teams/Team.php +++ b/lib/public/Teams/Team.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Teams/TeamResource.php b/lib/public/Teams/TeamResource.php index e9c6470b2c9..acb98380562 100644 --- a/lib/public/Teams/TeamResource.php +++ b/lib/public/Teams/TeamResource.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/Template.php b/lib/public/Template.php index 048697ffcc4..c29de52db4f 100644 --- a/lib/public/Template.php +++ b/lib/public/Template.php @@ -7,15 +7,23 @@ */ namespace OCP; +use OCP\Template\ITemplate; + +/* + * We have to require the functions file because this class contains aliases to the functions + */ +require_once __DIR__ . '/../private/Template/functions.php'; + /** * This class provides the template system for owncloud. You can use it to load * specific templates, add data and generate the html code * * @since 8.0.0 + * @deprecated 32.0.0 Use \OCP\Template\ITemplateManager instead */ -class Template extends \OC_Template { +class Template extends \OC_Template implements ITemplate { /** - * Make OC_Helper::imagePath available as a simple function + * Make \OCP\IURLGenerator::imagePath available as a simple function * * @see \OCP\IURLGenerator::imagePath * @@ -23,7 +31,7 @@ class Template extends \OC_Template { * @param string $image * @return string to the image * @since 8.0.0 - * @suppress PhanDeprecatedFunction + * @deprecated 32.0.0 Use the function directly instead */ public static function image_path($app, $image) { return \image_path($app, $image); @@ -31,12 +39,12 @@ class Template extends \OC_Template { /** - * Make OC_Helper::mimetypeIcon available as a simple function + * Make IMimeTypeDetector->mimeTypeIcon available as a simple function * * @param string $mimetype * @return string to the image of this file type. * @since 8.0.0 - * @suppress PhanDeprecatedFunction + * @deprecated 32.0.0 Use the function directly instead */ public static function mimetype_icon($mimetype) { return \mimetype_icon($mimetype); @@ -48,7 +56,7 @@ class Template extends \OC_Template { * @param string $path path to file * @return string to the preview of the image * @since 8.0.0 - * @suppress PhanDeprecatedFunction + * @deprecated 32.0.0 Use the function directly instead */ public static function preview_icon($path) { return \preview_icon($path); @@ -62,23 +70,23 @@ class Template extends \OC_Template { * @param string $token * @return string link to the preview * @since 8.0.0 - * @suppress PhanDeprecatedFunction + * @deprecated 32.0.0 Use the function directly instead */ public static function publicPreview_icon($path, $token) { return \publicPreview_icon($path, $token); } /** - * Make OC_Helper::humanFileSize available as a simple function + * Make \OCP\Util::humanFileSize available as a simple function * Example: 2048 to 2 kB. * * @param int $bytes in bytes * @return string size as string * @since 8.0.0 - * @suppress PhanDeprecatedFunction + * @deprecated 32.0.0 Use \OCP\Util::humanFileSize instead */ public static function human_file_size($bytes) { - return \human_file_size($bytes); + return Util::humanFileSize($bytes); } /** @@ -88,8 +96,8 @@ class Template extends \OC_Template { * @param boolean $dateOnly * @return string human readable interpretation of the timestamp * @since 8.0.0 - * @suppress PhanDeprecatedFunction * @suppress PhanTypeMismatchArgument + * @deprecated 32.0.0 Use the function directly instead */ public static function relative_modified_date($timestamp, $dateOnly = false) { return \relative_modified_date($timestamp, null, $dateOnly); @@ -103,7 +111,7 @@ class Template extends \OC_Template { * @param array $params the parameters * @return string html options * @since 8.0.0 - * @suppress PhanDeprecatedFunction + * @deprecated 32.0.0 Use the function directly instead */ public static function html_select_options($options, $selected, $params = []) { return \html_select_options($options, $selected, $params); diff --git a/lib/public/Template/ITemplate.php b/lib/public/Template/ITemplate.php new file mode 100644 index 00000000000..7131df4d17c --- /dev/null +++ b/lib/public/Template/ITemplate.php @@ -0,0 +1,47 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Template; + +/** + * @since 32.0.0 + */ +interface ITemplate { + /** + * Process the template + * @since 32.0.0 + */ + public function fetchPage(?array $additionalParams = null): string; + + /** + * Proceed the template and print its output. + * @since 32.0.0 + */ + public function printPage(): void; + + /** + * Assign variables + * + * This function assigns a variable. It can be accessed via $_[$key] in + * the template. + * + * If the key existed before, it will be overwritten + * @since 32.0.0 + */ + public function assign(string $key, mixed $value): void; + + /** + * Appends a variable + * + * This function assigns a variable in an array context. If the key already + * exists, the value will be appended. It can be accessed via + * $_[$key][$position] in the template. + */ + public function append(string $key, mixed $value): void; +} diff --git a/lib/public/Template/ITemplateManager.php b/lib/public/Template/ITemplateManager.php new file mode 100644 index 00000000000..05549bbddfd --- /dev/null +++ b/lib/public/Template/ITemplateManager.php @@ -0,0 +1,44 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Template; + +use OCP\AppFramework\Http\TemplateResponse; + +/** + * @since 32.0.0 + */ +interface ITemplateManager { + /** + * @param TemplateResponse::RENDER_AS_* $renderAs + * @throws TemplateNotFoundException if the template cannot be found + * @since 32.0.0 + */ + public function getTemplate(string $app, string $name, string $renderAs = TemplateResponse::RENDER_AS_BLANK, bool $registerCall = true): ITemplate; + + /** + * Shortcut to print a simple page for guests + * @since 32.0.0 + */ + public function printGuestPage(string $application, string $name, array $parameters = []): void; + + /** + * Print a fatal error page and terminates the script + * @since 32.0.0 + * @param string $error_msg The error message to show + * @param string $hint An optional hint message - needs to be properly escape + */ + public function printErrorPage(string $error_msg, string $hint = '', int $statusCode = 500): never; + + /** + * Print error page using Exception details + * @since 32.0.0 + */ + public function printExceptionErrorPage(\Throwable $exception, int $statusCode = 503): never; +} diff --git a/lib/public/Template/TemplateNotFoundException.php b/lib/public/Template/TemplateNotFoundException.php new file mode 100644 index 00000000000..e77fcd8646a --- /dev/null +++ b/lib/public/Template/TemplateNotFoundException.php @@ -0,0 +1,16 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Template; + +/** + * @since 32.0.0 + */ +class TemplateNotFoundException extends \Exception { +} diff --git a/lib/public/User/Backend/ICountUsersBackend.php b/lib/public/User/Backend/ICountUsersBackend.php index e337147dd14..194cf465cbe 100644 --- a/lib/public/User/Backend/ICountUsersBackend.php +++ b/lib/public/User/Backend/ICountUsersBackend.php @@ -10,6 +10,7 @@ namespace OCP\User\Backend; /** * @since 14.0.0 + * @deprecated 31.0.0 use and implement ILimitAwareCountUsersBackend instead. */ interface ICountUsersBackend { /** diff --git a/lib/public/User/Backend/ILimitAwareCountUsersBackend.php b/lib/public/User/Backend/ILimitAwareCountUsersBackend.php new file mode 100644 index 00000000000..a59c0bd8e04 --- /dev/null +++ b/lib/public/User/Backend/ILimitAwareCountUsersBackend.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\User\Backend; + +/** + * @since 31.0.0 + */ +interface ILimitAwareCountUsersBackend extends ICountUsersBackend { + /** + * @since 31.0.0 + * + * @param int $limit Limit to stop counting users if there are more than $limit. 0 to disable limiting. + * @return int|false The number of users (may be limited to $limit) on success false on failure + */ + public function countUsers(int $limit = 0): int|false; +} diff --git a/lib/public/Util.php b/lib/public/Util.php index 28da91c9a0f..b3111c54fc7 100644 --- a/lib/public/Util.php +++ b/lib/public/Util.php @@ -51,7 +51,7 @@ class Util { return $subscriptionRegistry->delegateHasExtendedSupport(); } catch (ContainerExceptionInterface $e) { } - return \OC::$server->getConfig()->getSystemValueBool('extendedSupport', false); + return \OCP\Server::get(IConfig::class)->getSystemValueBool('extendedSupport', false); } /** @@ -60,7 +60,7 @@ class Util { * @since 8.1.0 */ public static function setChannel($channel) { - \OC::$server->getConfig()->setSystemValue('updater.release.channel', $channel); + \OCP\Server::get(IConfig::class)->setSystemValue('updater.release.channel', $channel); } /** @@ -78,19 +78,16 @@ class Util { * * @return boolean * @since 7.0.0 - * @deprecated 9.1.0 Use \OC::$server->get(\OCP\Share\IManager::class)->sharingDisabledForUser + * @deprecated 9.1.0 Use Server::get(\OCP\Share\IManager::class)->sharingDisabledForUser */ public static function isSharingDisabledForUser() { if (self::$shareManager === null) { - self::$shareManager = \OC::$server->get(IManager::class); + self::$shareManager = Server::get(IManager::class); } - $user = \OC::$server->getUserSession()->getUser(); - if ($user !== null) { - $user = $user->getUID(); - } + $user = Server::get(\OCP\IUserSession::class)->getUser(); - return self::$shareManager->sharingDisabledForUser($user); + return self::$shareManager->sharingDisabledForUser($user?->getUID()); } /** @@ -102,13 +99,15 @@ class Util { } /** - * add a css file - * @param string $application - * @param string $file + * Add a css file + * + * @param string $application application id + * @param ?string $file filename + * @param bool $prepend prepend the style to the beginning of the list * @since 4.0.0 */ - public static function addStyle($application, $file = null) { - \OC_Util::addStyle($application, $file); + public static function addStyle(string $application, ?string $file = null, bool $prepend = false): void { + \OC_Util::addStyle($application, $file, $prepend); } /** @@ -183,7 +182,7 @@ class Util { */ public static function getScripts(): array { // Sort scriptDeps into sortedScriptDeps - $scriptSort = \OC::$server->get(AppScriptSort::class); + $scriptSort = \OCP\Server::get(AppScriptSort::class); $sortedScripts = $scriptSort->sort(self::$scripts, self::$scriptDeps); // Flatten array and remove duplicates @@ -210,7 +209,7 @@ class Util { */ public static function addTranslations($application, $languageCode = null, $init = false) { if (is_null($languageCode)) { - $languageCode = \OC::$server->get(IFactory::class)->findLanguage($application); + $languageCode = \OCP\Server::get(IFactory::class)->findLanguage($application); } if (!empty($application)) { $path = "$application/l10n/$languageCode"; @@ -248,7 +247,7 @@ class Util { * @since 4.0.0 - parameter $args was added in 4.5.0 */ public static function linkToAbsolute($app, $file, $args = []) { - $urlGenerator = \OC::$server->getURLGenerator(); + $urlGenerator = \OCP\Server::get(IURLGenerator::class); return $urlGenerator->getAbsoluteURL( $urlGenerator->linkTo($app, $file, $args) ); @@ -261,7 +260,7 @@ class Util { * @since 4.0.0 */ public static function linkToRemote($service) { - $urlGenerator = \OC::$server->getURLGenerator(); + $urlGenerator = \OCP\Server::get(IURLGenerator::class); $remoteBase = $urlGenerator->linkTo('', 'remote.php') . '/' . $service; return $urlGenerator->getAbsoluteURL( $remoteBase . (($service[strlen($service) - 1] != '/') ? '/' : '') @@ -274,7 +273,7 @@ class Util { * @since 5.0.0 */ public static function getServerHostName() { - $host_name = \OC::$server->getRequest()->getServerHost(); + $host_name = \OCP\Server::get(IRequest::class)->getServerHost(); // strip away port number (if existing) $colon_pos = strpos($host_name, ':'); if ($colon_pos != false) { @@ -300,13 +299,13 @@ class Util { * @since 5.0.0 */ public static function getDefaultEmailAddress(string $user_part): string { - $config = \OC::$server->getConfig(); + $config = \OCP\Server::get(IConfig::class); $user_part = $config->getSystemValueString('mail_from_address', $user_part); $host_name = self::getServerHostName(); $host_name = $config->getSystemValueString('mail_domain', $host_name); $defaultEmailAddress = $user_part . '@' . $host_name; - $mailer = \OC::$server->get(IMailer::class); + $mailer = \OCP\Server::get(IMailer::class); if ($mailer->validateMailAddress($defaultEmailAddress)) { return $defaultEmailAddress; } @@ -333,19 +332,70 @@ class Util { * @since 4.0.0 */ public static function humanFileSize(int|float $bytes): string { - return \OC_Helper::humanFileSize($bytes); + if ($bytes < 0) { + return '?'; + } + if ($bytes < 1024) { + return "$bytes B"; + } + $bytes = round($bytes / 1024, 0); + if ($bytes < 1024) { + return "$bytes KB"; + } + $bytes = round($bytes / 1024, 1); + if ($bytes < 1024) { + return "$bytes MB"; + } + $bytes = round($bytes / 1024, 1); + if ($bytes < 1024) { + return "$bytes GB"; + } + $bytes = round($bytes / 1024, 1); + if ($bytes < 1024) { + return "$bytes TB"; + } + + $bytes = round($bytes / 1024, 1); + return "$bytes PB"; } /** * Make a computer file size (2 kB to 2048) + * Inspired by: https://www.php.net/manual/en/function.filesize.php#92418 + * * @param string $str file size in a fancy format * @return false|int|float a file size in bytes - * - * Inspired by: https://www.php.net/manual/en/function.filesize.php#92418 * @since 4.0.0 */ public static function computerFileSize(string $str): false|int|float { - return \OC_Helper::computerFileSize($str); + $str = strtolower($str); + if (is_numeric($str)) { + return Util::numericToNumber($str); + } + + $bytes_array = [ + 'b' => 1, + 'k' => 1024, + 'kb' => 1024, + 'mb' => 1024 * 1024, + 'm' => 1024 * 1024, + 'gb' => 1024 * 1024 * 1024, + 'g' => 1024 * 1024 * 1024, + 'tb' => 1024 * 1024 * 1024 * 1024, + 't' => 1024 * 1024 * 1024 * 1024, + 'pb' => 1024 * 1024 * 1024 * 1024 * 1024, + 'p' => 1024 * 1024 * 1024 * 1024 * 1024, + ]; + + $bytes = (float)$str; + + if (preg_match('#([kmgtp]?b?)$#si', $str, $matches) && isset($bytes_array[$matches[1]])) { + $bytes *= $bytes_array[$matches[1]]; + } else { + return false; + } + + return Util::numericToNumber(round($bytes)); } /** @@ -384,7 +434,7 @@ class Util { /** * Cached encrypted CSRF token. Some static unit-tests of ownCloud compare - * multiple OC_Template elements which invoke `callRegister`. If the value + * multiple Template elements which invoke `callRegister`. If the value * would not be cached these unit-tests would fail. * @var string */ @@ -393,10 +443,11 @@ class Util { /** * Register an get/post call. This is important to prevent CSRF attacks * @since 4.5.0 + * @deprecated 32.0.0 directly use CsrfTokenManager instead */ public static function callRegister() { if (self::$token === '') { - self::$token = \OC::$server->get(CsrfTokenManager::class)->getToken()->getEncryptedValue(); + self::$token = \OCP\Server::get(CsrfTokenManager::class)->getToken()->getEncryptedValue(); } return self::$token; } @@ -408,7 +459,7 @@ class Util { * string or array of strings before displaying it on a web page. * * @param string|string[] $value - * @return string|string[] an array of sanitized strings or a single sanitized string, depends on the input parameter. + * @return ($value is array ? string[] : string) an array of sanitized strings or a single sanitized string, depends on the input parameter. * @since 4.5.0 */ public static function sanitizeHTML($value) { @@ -440,7 +491,12 @@ class Util { * @since 4.5.0 */ public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') { - return \OC_Helper::mb_array_change_key_case($input, $case, $encoding); + $case = ($case != MB_CASE_UPPER) ? MB_CASE_LOWER : MB_CASE_UPPER; + $ret = []; + foreach ($input as $k => $v) { + $ret[mb_convert_case($k, $case, $encoding)] = $v; + } + return $ret; } /** @@ -454,7 +510,18 @@ class Util { * @deprecated 15.0.0 */ public static function recursiveArraySearch($haystack, $needle, $index = null) { - return \OC_Helper::recursiveArraySearch($haystack, $needle, $index); + $aIt = new \RecursiveArrayIterator($haystack); + $it = new \RecursiveIteratorIterator($aIt); + + while ($it->valid()) { + if (((isset($index) and ($it->key() == $index)) or !isset($index)) and ($it->current() == $needle)) { + return $aIt->key(); + } + + $it->next(); + } + + return false; } /** @@ -466,7 +533,10 @@ class Util { * @since 5.0.0 */ public static function maxUploadFilesize(string $dir, int|float|null $free = null): int|float { - return \OC_Helper::maxUploadFilesize($dir, $free); + if (is_null($free) || $free < 0) { + $free = self::freeSpace($dir); + } + return min($free, self::uploadLimit()); } /** @@ -476,7 +546,13 @@ class Util { * @since 7.0.0 */ public static function freeSpace(string $dir): int|float { - return \OC_Helper::freeSpace($dir); + $freeSpace = \OC\Files\Filesystem::free_space($dir); + if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) { + $freeSpace = max($freeSpace, 0); + return $freeSpace; + } else { + return (INF > 0)? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188 + } } /** @@ -486,7 +562,16 @@ class Util { * @since 7.0.0 */ public static function uploadLimit(): int|float { - return \OC_Helper::uploadLimit(); + $ini = Server::get(IniGetWrapper::class); + $upload_max_filesize = self::computerFileSize($ini->get('upload_max_filesize')) ?: 0; + $post_max_size = self::computerFileSize($ini->get('post_max_size')) ?: 0; + if ($upload_max_filesize === 0 && $post_max_size === 0) { + return INF; + } elseif ($upload_max_filesize === 0 || $post_max_size === 0) { + return max($upload_max_filesize, $post_max_size); //only the non 0 value counts + } else { + return min($upload_max_filesize, $post_max_size); + } } /** @@ -531,7 +616,7 @@ class Util { */ public static function needUpgrade() { if (!isset(self::$needUpgradeCache)) { - self::$needUpgradeCache = \OC_Util::needUpgrade(\OC::$server->getSystemConfig()); + self::$needUpgradeCache = \OC_Util::needUpgrade(\OCP\Server::get(\OC\SystemConfig::class)); } return self::$needUpgradeCache; } diff --git a/lib/public/WorkflowEngine/ICheck.php b/lib/public/WorkflowEngine/ICheck.php index 79c1a864ae0..4671eb84c3e 100644 --- a/lib/public/WorkflowEngine/ICheck.php +++ b/lib/public/WorkflowEngine/ICheck.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/WorkflowEngine/IManager.php b/lib/public/WorkflowEngine/IManager.php index b9235abafef..f66a9460f06 100644 --- a/lib/public/WorkflowEngine/IManager.php +++ b/lib/public/WorkflowEngine/IManager.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/public/WorkflowEngine/IOperation.php b/lib/public/WorkflowEngine/IOperation.php index 9f867eb811a..cda20acb7e5 100644 --- a/lib/public/WorkflowEngine/IOperation.php +++ b/lib/public/WorkflowEngine/IOperation.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/unstable/Config/Lexicon/ConfigLexiconEntry.php b/lib/unstable/Config/Lexicon/ConfigLexiconEntry.php new file mode 100644 index 00000000000..d0d9b4cbd23 --- /dev/null +++ b/lib/unstable/Config/Lexicon/ConfigLexiconEntry.php @@ -0,0 +1,235 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace NCU\Config\Lexicon; + +use NCU\Config\ValueType; + +/** + * Model that represent config values within an app config lexicon. + * + * @see IConfigLexicon + * @experimental 31.0.0 + */ +class ConfigLexiconEntry { + /** @experimental 32.0.0 */ + public const RENAME_INVERT_BOOLEAN = 1; + + private string $definition = ''; + private ?string $default = null; + + /** + * @param string $key config key + * @param ValueType $type type of config value + * @param string $definition optional description of config key available when using occ command + * @param bool $lazy set config value as lazy + * @param int $flags set flags + * @param string|null $rename previous config key to migrate config value from + * @param bool $deprecated set config key as deprecated + * + * @experimental 31.0.0 + * @psalm-suppress PossiblyInvalidCast + * @psalm-suppress RiskyCast + */ + public function __construct( + private readonly string $key, + private readonly ValueType $type, + private null|string|int|float|bool|array $defaultRaw = null, + string $definition = '', + private readonly bool $lazy = false, + private readonly int $flags = 0, + private readonly bool $deprecated = false, + private readonly ?string $rename = null, + private readonly int $options = 0, + ) { + /** @psalm-suppress UndefinedClass */ + if (\OC::$CLI) { // only store definition if ran from CLI + $this->definition = $definition; + } + } + + /** + * returns the config key + * + * @return string config key + * @experimental 31.0.0 + */ + public function getKey(): string { + return $this->key; + } + + /** + * get expected type for config value + * + * @return ValueType + * @experimental 31.0.0 + */ + public function getValueType(): ValueType { + return $this->type; + } + + /** + * @param string $default + * @return string + * @experimental 31.0.0 + */ + private function convertFromString(string $default): string { + return $default; + } + + /** + * @param int $default + * @return string + * @experimental 31.0.0 + */ + private function convertFromInt(int $default): string { + return (string)$default; + } + + /** + * @param float $default + * @return string + * @experimental 31.0.0 + */ + private function convertFromFloat(float $default): string { + return (string)$default; + } + + /** + * @param bool $default + * @return string + * @experimental 31.0.0 + */ + private function convertFromBool(bool $default): string { + return ($default) ? '1' : '0'; + } + + /** + * @param array $default + * @return string + * @experimental 31.0.0 + */ + private function convertFromArray(array $default): string { + return json_encode($default); + } + + /** + * returns default value + * + * @return string|null NULL if no default is set + * @experimental 31.0.0 + */ + public function getDefault(): ?string { + if ($this->defaultRaw === null) { + return null; + } + + if ($this->default === null) { + $this->default = $this->convertToString($this->defaultRaw); + } + + return $this->default; + } + + /** + * convert $entry into string, based on the expected type for config value + * + * @param string|int|float|bool|array $entry + * + * @return string + * @experimental 31.0.0 + * @psalm-suppress PossiblyInvalidCast arrays are managed pre-cast + * @psalm-suppress RiskyCast + */ + public function convertToString(string|int|float|bool|array $entry): string { + // in case $default is array but is not expected to be an array... + if ($this->getValueType() !== ValueType::ARRAY && is_array($entry)) { + $entry = json_encode($entry, JSON_THROW_ON_ERROR); + } + + return match ($this->getValueType()) { + ValueType::MIXED => (string)$entry, + ValueType::STRING => $this->convertFromString((string)$entry), + ValueType::INT => $this->convertFromInt((int)$entry), + ValueType::FLOAT => $this->convertFromFloat((float)$entry), + ValueType::BOOL => $this->convertFromBool((bool)$entry), + ValueType::ARRAY => $this->convertFromArray((array)$entry) + }; + } + + /** + * returns definition + * + * @return string + * @experimental 31.0.0 + */ + public function getDefinition(): string { + return $this->definition; + } + + /** + * returns if config key is set as lazy + * + * @see IAppConfig for details on lazy config values + * @return bool TRUE if config value is lazy + * @experimental 31.0.0 + */ + public function isLazy(): bool { + return $this->lazy; + } + + /** + * returns flags + * + * @see IAppConfig for details on sensitive config values + * @return int bitflag about the config value + * @experimental 31.0.0 + */ + public function getFlags(): int { + return $this->flags; + } + + /** + * @param int $flag + * + * @return bool TRUE is config value bitflag contains $flag + * @experimental 31.0.0 + */ + public function isFlagged(int $flag): bool { + return (($flag & $this->getFlags()) === $flag); + } + + /** + * should be called/used only during migration/upgrade. + * link to an old config key. + * + * @return string|null not NULL if value can be imported from a previous key + * @experimental 32.0.0 + */ + public function getRename(): ?string { + return $this->rename; + } + + /** + * @experimental 32.0.0 + * @return bool TRUE if $option was set during the creation of the entry. + */ + public function hasOption(int $option): bool { + return (($option & $this->options) !== 0); + } + + /** + * returns if config key is set as deprecated + * + * @return bool TRUE if config si deprecated + * @experimental 31.0.0 + */ + public function isDeprecated(): bool { + return $this->deprecated; + } +} diff --git a/lib/unstable/Config/Lexicon/ConfigLexiconStrictness.php b/lib/unstable/Config/Lexicon/ConfigLexiconStrictness.php new file mode 100644 index 00000000000..a6490675c8a --- /dev/null +++ b/lib/unstable/Config/Lexicon/ConfigLexiconStrictness.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace NCU\Config\Lexicon; + +/** + * Strictness regarding using not-listed config keys + * + * - **ConfigLexiconStrictness::IGNORE** - fully ignore + * - **ConfigLexiconStrictness::NOTICE** - ignore and report + * - **ConfigLexiconStrictness::WARNING** - silently block (returns $default) and report + * - **ConfigLexiconStrictness::EXCEPTION** - block (throws exception) and report + * + * @experimental 31.0.0 + */ +enum ConfigLexiconStrictness { + /** @experimental 31.0.0 */ + case IGNORE; // fully ignore + /** @experimental 31.0.0 */ + case NOTICE; // ignore and report + /** @experimental 31.0.0 */ + case WARNING; // silently block (returns $default) and report + /** @experimental 31.0.0 */ + case EXCEPTION; // block (throws exception) and report +} diff --git a/lib/unstable/Config/Lexicon/IConfigLexicon.php b/lib/unstable/Config/Lexicon/IConfigLexicon.php new file mode 100644 index 00000000000..3fedb5f1f08 --- /dev/null +++ b/lib/unstable/Config/Lexicon/IConfigLexicon.php @@ -0,0 +1,44 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +namespace NCU\Config\Lexicon; + +/** + * This interface needs to be implemented if you want to define a config lexicon for your application + * The config lexicon is used to avoid conflicts and problems when storing/retrieving config values + * + * @experimental 31.0.0 + */ +interface IConfigLexicon { + + /** + * Define the expected behavior when using config + * keys not set within your application config lexicon. + * + * @see ConfigLexiconStrictness + * @return ConfigLexiconStrictness + * @experimental 31.0.0 + */ + public function getStrictness(): ConfigLexiconStrictness; + + /** + * define the list of entries of your application config lexicon, related to AppConfig. + * + * @return ConfigLexiconEntry[] + * @experimental 31.0.0 + */ + public function getAppConfigs(): array; + + /** + * define the list of entries of your application config lexicon, related to UserPreferences. + * + * @return ConfigLexiconEntry[] + * @experimental 31.0.0 + */ + public function getUserConfigs(): array; +} diff --git a/lib/unstable/Config/ValueType.php b/lib/unstable/Config/ValueType.php index 4f6c4181a9c..b1181674953 100644 --- a/lib/unstable/Config/ValueType.php +++ b/lib/unstable/Config/ValueType.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace NCU\Config; use NCU\Config\Exceptions\IncorrectTypeException; +use OCP\IAppConfig; use UnhandledMatchError; /** @@ -89,4 +90,28 @@ enum ValueType: int { throw new IncorrectTypeException('unknown type definition ' . $this->value); } } + + /** + * get corresponding AppConfig flag value + * + * @return int + * @throws IncorrectTypeException + * + * @experimental 31.0.0 + */ + public function toAppConfigFlag(): int { + try { + return match ($this) { + self::MIXED => IAppConfig::VALUE_MIXED, + self::STRING => IAppConfig::VALUE_STRING, + self::INT => IAppConfig::VALUE_INT, + self::FLOAT => IAppConfig::VALUE_FLOAT, + self::BOOL => IAppConfig::VALUE_BOOL, + self::ARRAY => IAppConfig::VALUE_ARRAY, + }; + } catch (UnhandledMatchError) { + throw new IncorrectTypeException('unknown type definition ' . $this->value); + } + } + } |