aboutsummaryrefslogtreecommitdiffstats
path: root/apps/dashboard
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dashboard')
-rw-r--r--apps/dashboard/.l10nignore4
-rw-r--r--apps/dashboard/README.md7
-rw-r--r--apps/dashboard/appinfo/info.xml36
-rw-r--r--apps/dashboard/composer/autoload.php25
-rw-r--r--apps/dashboard/composer/composer.json13
-rw-r--r--apps/dashboard/composer/composer.lock18
-rw-r--r--apps/dashboard/composer/composer/ClassLoader.php579
-rw-r--r--apps/dashboard/composer/composer/InstalledVersions.php359
-rw-r--r--apps/dashboard/composer/composer/LICENSE21
-rw-r--r--apps/dashboard/composer/composer/autoload_classmap.php14
-rw-r--r--apps/dashboard/composer/composer/autoload_namespaces.php9
-rw-r--r--apps/dashboard/composer/composer/autoload_psr4.php10
-rw-r--r--apps/dashboard/composer/composer/autoload_real.php37
-rw-r--r--apps/dashboard/composer/composer/autoload_static.php40
-rw-r--r--apps/dashboard/composer/composer/installed.json5
-rw-r--r--apps/dashboard/composer/composer/installed.php23
-rw-r--r--apps/dashboard/css/dashboard.css4
-rw-r--r--apps/dashboard/css/dashboard.css.map1
-rw-r--r--apps/dashboard/css/dashboard.css.map.license3
-rw-r--r--apps/dashboard/css/dashboard.scss51
-rw-r--r--apps/dashboard/img/dashboard.svg1
-rw-r--r--apps/dashboard/img/dashboard.svg.license4
-rw-r--r--apps/dashboard/l10n/.gitkeep0
-rw-r--r--apps/dashboard/l10n/ar.js28
-rw-r--r--apps/dashboard/l10n/ar.json26
-rw-r--r--apps/dashboard/l10n/ast.js26
-rw-r--r--apps/dashboard/l10n/ast.json24
-rw-r--r--apps/dashboard/l10n/be.js21
-rw-r--r--apps/dashboard/l10n/be.json19
-rw-r--r--apps/dashboard/l10n/bg.js25
-rw-r--r--apps/dashboard/l10n/bg.json23
-rw-r--r--apps/dashboard/l10n/ca.js28
-rw-r--r--apps/dashboard/l10n/ca.json26
-rw-r--r--apps/dashboard/l10n/cs.js28
-rw-r--r--apps/dashboard/l10n/cs.json26
-rw-r--r--apps/dashboard/l10n/da.js28
-rw-r--r--apps/dashboard/l10n/da.json26
-rw-r--r--apps/dashboard/l10n/de.js28
-rw-r--r--apps/dashboard/l10n/de.json26
-rw-r--r--apps/dashboard/l10n/de_DE.js28
-rw-r--r--apps/dashboard/l10n/de_DE.json26
-rw-r--r--apps/dashboard/l10n/el.js25
-rw-r--r--apps/dashboard/l10n/el.json23
-rw-r--r--apps/dashboard/l10n/en_GB.js28
-rw-r--r--apps/dashboard/l10n/en_GB.json26
-rw-r--r--apps/dashboard/l10n/es.js28
-rw-r--r--apps/dashboard/l10n/es.json26
-rw-r--r--apps/dashboard/l10n/es_EC.js25
-rw-r--r--apps/dashboard/l10n/es_EC.json23
-rw-r--r--apps/dashboard/l10n/es_MX.js26
-rw-r--r--apps/dashboard/l10n/es_MX.json24
-rw-r--r--apps/dashboard/l10n/et_EE.js28
-rw-r--r--apps/dashboard/l10n/et_EE.json26
-rw-r--r--apps/dashboard/l10n/eu.js28
-rw-r--r--apps/dashboard/l10n/eu.json26
-rw-r--r--apps/dashboard/l10n/fa.js28
-rw-r--r--apps/dashboard/l10n/fa.json26
-rw-r--r--apps/dashboard/l10n/fi.js25
-rw-r--r--apps/dashboard/l10n/fi.json23
-rw-r--r--apps/dashboard/l10n/fr.js28
-rw-r--r--apps/dashboard/l10n/fr.json26
-rw-r--r--apps/dashboard/l10n/ga.js28
-rw-r--r--apps/dashboard/l10n/ga.json26
-rw-r--r--apps/dashboard/l10n/gl.js28
-rw-r--r--apps/dashboard/l10n/gl.json26
-rw-r--r--apps/dashboard/l10n/he.js24
-rw-r--r--apps/dashboard/l10n/he.json22
-rw-r--r--apps/dashboard/l10n/hr.js25
-rw-r--r--apps/dashboard/l10n/hr.json23
-rw-r--r--apps/dashboard/l10n/hu.js28
-rw-r--r--apps/dashboard/l10n/hu.json26
-rw-r--r--apps/dashboard/l10n/id.js25
-rw-r--r--apps/dashboard/l10n/id.json23
-rw-r--r--apps/dashboard/l10n/is.js28
-rw-r--r--apps/dashboard/l10n/is.json26
-rw-r--r--apps/dashboard/l10n/it.js28
-rw-r--r--apps/dashboard/l10n/it.json26
-rw-r--r--apps/dashboard/l10n/ja.js28
-rw-r--r--apps/dashboard/l10n/ja.json26
-rw-r--r--apps/dashboard/l10n/ka_GE.js22
-rw-r--r--apps/dashboard/l10n/ka_GE.json20
-rw-r--r--apps/dashboard/l10n/ko.js24
-rw-r--r--apps/dashboard/l10n/ko.json22
-rw-r--r--apps/dashboard/l10n/lt_LT.js27
-rw-r--r--apps/dashboard/l10n/lt_LT.json25
-rw-r--r--apps/dashboard/l10n/mk.js25
-rw-r--r--apps/dashboard/l10n/mk.json23
-rw-r--r--apps/dashboard/l10n/nb.js26
-rw-r--r--apps/dashboard/l10n/nb.json24
-rw-r--r--apps/dashboard/l10n/nl.js28
-rw-r--r--apps/dashboard/l10n/nl.json26
-rw-r--r--apps/dashboard/l10n/oc.js24
-rw-r--r--apps/dashboard/l10n/oc.json22
-rw-r--r--apps/dashboard/l10n/pl.js28
-rw-r--r--apps/dashboard/l10n/pl.json26
-rw-r--r--apps/dashboard/l10n/pt_BR.js28
-rw-r--r--apps/dashboard/l10n/pt_BR.json26
-rw-r--r--apps/dashboard/l10n/pt_PT.js24
-rw-r--r--apps/dashboard/l10n/pt_PT.json22
-rw-r--r--apps/dashboard/l10n/ro.js27
-rw-r--r--apps/dashboard/l10n/ro.json25
-rw-r--r--apps/dashboard/l10n/ru.js28
-rw-r--r--apps/dashboard/l10n/ru.json26
-rw-r--r--apps/dashboard/l10n/sc.js25
-rw-r--r--apps/dashboard/l10n/sc.json23
-rw-r--r--apps/dashboard/l10n/sk.js28
-rw-r--r--apps/dashboard/l10n/sk.json26
-rw-r--r--apps/dashboard/l10n/sl.js26
-rw-r--r--apps/dashboard/l10n/sl.json24
-rw-r--r--apps/dashboard/l10n/sr.js28
-rw-r--r--apps/dashboard/l10n/sr.json26
-rw-r--r--apps/dashboard/l10n/sv.js28
-rw-r--r--apps/dashboard/l10n/sv.json26
-rw-r--r--apps/dashboard/l10n/sw.js28
-rw-r--r--apps/dashboard/l10n/sw.json26
-rw-r--r--apps/dashboard/l10n/th.js25
-rw-r--r--apps/dashboard/l10n/th.json23
-rw-r--r--apps/dashboard/l10n/tr.js28
-rw-r--r--apps/dashboard/l10n/tr.json26
-rw-r--r--apps/dashboard/l10n/ug.js26
-rw-r--r--apps/dashboard/l10n/ug.json24
-rw-r--r--apps/dashboard/l10n/uk.js28
-rw-r--r--apps/dashboard/l10n/uk.json26
-rw-r--r--apps/dashboard/l10n/uz.js28
-rw-r--r--apps/dashboard/l10n/uz.json26
-rw-r--r--apps/dashboard/l10n/vi.js25
-rw-r--r--apps/dashboard/l10n/vi.json23
-rw-r--r--apps/dashboard/l10n/zh_CN.js28
-rw-r--r--apps/dashboard/l10n/zh_CN.json26
-rw-r--r--apps/dashboard/l10n/zh_HK.js28
-rw-r--r--apps/dashboard/l10n/zh_HK.json26
-rw-r--r--apps/dashboard/l10n/zh_TW.js28
-rw-r--r--apps/dashboard/l10n/zh_TW.json26
-rw-r--r--apps/dashboard/lib/Controller/DashboardApiController.php234
-rw-r--r--apps/dashboard/lib/Controller/DashboardController.php87
-rw-r--r--apps/dashboard/lib/ResponseDefinitions.php46
-rw-r--r--apps/dashboard/lib/Service/DashboardService.php71
-rw-r--r--apps/dashboard/openapi.json764
-rw-r--r--apps/dashboard/openapi.json.license2
-rw-r--r--apps/dashboard/src/DashboardApp.vue761
-rw-r--r--apps/dashboard/src/components/ApiDashboardWidget.vue116
-rw-r--r--apps/dashboard/src/components/ApiDashboardWidgetItem.vue68
-rw-r--r--apps/dashboard/src/main.js26
-rw-r--r--apps/dashboard/src/mixins/isMobile.js28
-rw-r--r--apps/dashboard/templates/index.php8
-rw-r--r--apps/dashboard/tests/DashboardServiceTest.php100
146 files changed, 6403 insertions, 0 deletions
diff --git a/apps/dashboard/.l10nignore b/apps/dashboard/.l10nignore
new file mode 100644
index 00000000000..91aefac85dc
--- /dev/null
+++ b/apps/dashboard/.l10nignore
@@ -0,0 +1,4 @@
+# SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+# SPDX-License-Identifier: AGPL-3.0-or-later
+#webpack bundled files
+js/
diff --git a/apps/dashboard/README.md b/apps/dashboard/README.md
new file mode 100644
index 00000000000..bcadd1a30e1
--- /dev/null
+++ b/apps/dashboard/README.md
@@ -0,0 +1,7 @@
+<!--
+ - SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+ -->
+# Dashboard
+
+Background image documentation moved to theming folder at `apps/theming/README.md`. \ No newline at end of file
diff --git a/apps/dashboard/appinfo/info.xml b/apps/dashboard/appinfo/info.xml
new file mode 100644
index 00000000000..804a8981602
--- /dev/null
+++ b/apps/dashboard/appinfo/info.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+ - SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
+ <id>dashboard</id>
+ <name>Dashboard</name>
+ <summary>Dashboard app</summary>
+ <description><![CDATA[Start your day informed
+
+The Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking.]]>
+ </description>
+ <version>7.12.0</version>
+ <licence>agpl</licence>
+ <author>Julius Härtl</author>
+ <namespace>Dashboard</namespace>
+
+ <category>customization</category>
+
+ <bugs>https://github.com/nextcloud/server/issues</bugs>
+
+ <dependencies>
+ <nextcloud min-version="32" max-version="32"/>
+ </dependencies>
+
+ <navigations>
+ <navigation>
+ <name>Dashboard</name>
+ <route>dashboard.dashboard.index</route>
+ <icon>dashboard.svg</icon>
+ <order>-10</order>
+ </navigation>
+ </navigations>
+</info>
diff --git a/apps/dashboard/composer/autoload.php b/apps/dashboard/composer/autoload.php
new file mode 100644
index 00000000000..d7705e770bb
--- /dev/null
+++ b/apps/dashboard/composer/autoload.php
@@ -0,0 +1,25 @@
+<?php
+
+// autoload.php @generated by Composer
+
+if (PHP_VERSION_ID < 50600) {
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+ $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
+ if (!ini_get('display_errors')) {
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+ fwrite(STDERR, $err);
+ } elseif (!headers_sent()) {
+ echo $err;
+ }
+ }
+ trigger_error(
+ $err,
+ E_USER_ERROR
+ );
+}
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInitDashboard::getLoader();
diff --git a/apps/dashboard/composer/composer.json b/apps/dashboard/composer/composer.json
new file mode 100644
index 00000000000..890704b67b3
--- /dev/null
+++ b/apps/dashboard/composer/composer.json
@@ -0,0 +1,13 @@
+{
+ "config" : {
+ "vendor-dir": ".",
+ "optimize-autoloader": true,
+ "classmap-authoritative": true,
+ "autoloader-suffix": "Dashboard"
+ },
+ "autoload" : {
+ "psr-4": {
+ "OCA\\Dashboard\\": "../lib/"
+ }
+ }
+}
diff --git a/apps/dashboard/composer/composer.lock b/apps/dashboard/composer/composer.lock
new file mode 100644
index 00000000000..62a29d36726
--- /dev/null
+++ b/apps/dashboard/composer/composer.lock
@@ -0,0 +1,18 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "d751713988987e9331980363e24189ce",
+ "packages": [],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "plugin-api-version": "2.3.0"
+}
diff --git a/apps/dashboard/composer/composer/ClassLoader.php b/apps/dashboard/composer/composer/ClassLoader.php
new file mode 100644
index 00000000000..7824d8f7eaf
--- /dev/null
+++ b/apps/dashboard/composer/composer/ClassLoader.php
@@ -0,0 +1,579 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @see https://www.php-fig.org/psr/psr-0/
+ * @see https://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+ /** @var \Closure(string):void */
+ private static $includeFile;
+
+ /** @var string|null */
+ private $vendorDir;
+
+ // PSR-4
+ /**
+ * @var array<string, array<string, int>>
+ */
+ private $prefixLengthsPsr4 = array();
+ /**
+ * @var array<string, list<string>>
+ */
+ private $prefixDirsPsr4 = array();
+ /**
+ * @var list<string>
+ */
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ /**
+ * List of PSR-0 prefixes
+ *
+ * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
+ *
+ * @var array<string, array<string, list<string>>>
+ */
+ private $prefixesPsr0 = array();
+ /**
+ * @var list<string>
+ */
+ private $fallbackDirsPsr0 = array();
+
+ /** @var bool */
+ private $useIncludePath = false;
+
+ /**
+ * @var array<string, string>
+ */
+ private $classMap = array();
+
+ /** @var bool */
+ private $classMapAuthoritative = false;
+
+ /**
+ * @var array<string, bool>
+ */
+ private $missingClasses = array();
+
+ /** @var string|null */
+ private $apcuPrefix;
+
+ /**
+ * @var array<string, self>
+ */
+ private static $registeredLoaders = array();
+
+ /**
+ * @param string|null $vendorDir
+ */
+ public function __construct($vendorDir = null)
+ {
+ $this->vendorDir = $vendorDir;
+ self::initializeIncludeClosure();
+ }
+
+ /**
+ * @return array<string, list<string>>
+ */
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
+ }
+
+ return array();
+ }
+
+ /**
+ * @return array<string, list<string>>
+ */
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ /**
+ * @return list<string>
+ */
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ /**
+ * @return list<string>
+ */
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ /**
+ * @return array<string, string> Array of classname => path
+ */
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array<string, string> $classMap Class to filename map
+ *
+ * @return void
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @return void
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ $paths = (array) $paths;
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list<string>|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ $paths = (array) $paths;
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param list<string>|string $paths The PSR-0 base directories
+ *
+ * @return void
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list<string>|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ *
+ * @return void
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ *
+ * @return void
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+ *
+ * @param string|null $apcuPrefix
+ *
+ * @return void
+ */
+ public function setApcuPrefix($apcuPrefix)
+ {
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
+ }
+
+ /**
+ * The APCu prefix in use, or null if APCu caching is not enabled.
+ *
+ * @return string|null
+ */
+ public function getApcuPrefix()
+ {
+ return $this->apcuPrefix;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ *
+ * @return void
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+
+ if (null === $this->vendorDir) {
+ return;
+ }
+
+ if ($prepend) {
+ self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
+ } else {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ self::$registeredLoaders[$this->vendorDir] = $this;
+ }
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ *
+ * @return void
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+
+ if (null !== $this->vendorDir) {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ }
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return true|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ $includeFile = self::$includeFile;
+ $includeFile($file);
+
+ return true;
+ }
+
+ return null;
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+ return false;
+ }
+ if (null !== $this->apcuPrefix) {
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+ if ($hit) {
+ return $file;
+ }
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if (false === $file && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if (null !== $this->apcuPrefix) {
+ apcu_add($this->apcuPrefix.$class, $file);
+ }
+
+ if (false === $file) {
+ // Remember that this class does not exist.
+ $this->missingClasses[$class] = true;
+ }
+
+ return $file;
+ }
+
+ /**
+ * Returns the currently registered loaders keyed by their corresponding vendor directories.
+ *
+ * @return array<string, self>
+ */
+ public static function getRegisteredLoaders()
+ {
+ return self::$registeredLoaders;
+ }
+
+ /**
+ * @param string $class
+ * @param string $ext
+ * @return string|false
+ */
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ $subPath = $class;
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
+ $subPath = substr($subPath, 0, $lastPos);
+ $search = $subPath . '\\';
+ if (isset($this->prefixDirsPsr4[$search])) {
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
+ if (file_exists($file = $dir . $pathEnd)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+
+ return false;
+ }
+
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
+ {
+ if (self::$includeFile !== null) {
+ return;
+ }
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file
+ * @return void
+ */
+ self::$includeFile = \Closure::bind(static function($file) {
+ include $file;
+ }, null, null);
+ }
+}
diff --git a/apps/dashboard/composer/composer/InstalledVersions.php b/apps/dashboard/composer/composer/InstalledVersions.php
new file mode 100644
index 00000000000..51e734a774b
--- /dev/null
+++ b/apps/dashboard/composer/composer/InstalledVersions.php
@@ -0,0 +1,359 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ * Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer;
+
+use Composer\Autoload\ClassLoader;
+use Composer\Semver\VersionParser;
+
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require its presence, you can require `composer-runtime-api ^2.0`
+ *
+ * @final
+ */
+class InstalledVersions
+{
+ /**
+ * @var mixed[]|null
+ * @psalm-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[]}>}|array{}|null
+ */
+ private static $installed;
+
+ /**
+ * @var bool|null
+ */
+ private static $canGetVendors;
+
+ /**
+ * @var array[]
+ * @psalm-var array<string, 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[]}>}>
+ */
+ private static $installedByVendor = array();
+
+ /**
+ * Returns a list of all package names which are present, either by being installed, replaced or provided
+ *
+ * @return string[]
+ * @psalm-return list<string>
+ */
+ public static function getInstalledPackages()
+ {
+ $packages = array();
+ foreach (self::getInstalled() as $installed) {
+ $packages[] = array_keys($installed['versions']);
+ }
+
+ if (1 === \count($packages)) {
+ return $packages[0];
+ }
+
+ return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+ }
+
+ /**
+ * Returns a list of all package names with a specific type e.g. 'library'
+ *
+ * @param string $type
+ * @return string[]
+ * @psalm-return list<string>
+ */
+ public static function getInstalledPackagesByType($type)
+ {
+ $packagesByType = array();
+
+ foreach (self::getInstalled() as $installed) {
+ foreach ($installed['versions'] as $name => $package) {
+ if (isset($package['type']) && $package['type'] === $type) {
+ $packagesByType[] = $name;
+ }
+ }
+ }
+
+ return $packagesByType;
+ }
+
+ /**
+ * Checks whether the given package is installed
+ *
+ * This also returns true if the package name is provided or replaced by another package
+ *
+ * @param string $packageName
+ * @param bool $includeDevRequirements
+ * @return bool
+ */
+ public static function isInstalled($packageName, $includeDevRequirements = true)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (isset($installed['versions'][$packageName])) {
+ return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether the given package satisfies a version constraint
+ *
+ * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+ *
+ * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+ *
+ * @param VersionParser $parser Install composer/semver to have access to this class and functionality
+ * @param string $packageName
+ * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+ * @return bool
+ */
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
+ {
+ $constraint = $parser->parseConstraints((string) $constraint);
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+ return $provided->matches($constraint);
+ }
+
+ /**
+ * Returns a version constraint representing all the range(s) which are installed for a given package
+ *
+ * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+ * whether a given version of a package is installed, and not just whether it exists
+ *
+ * @param string $packageName
+ * @return string Version constraint usable with composer/semver
+ */
+ public static function getVersionRanges($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ $ranges = array();
+ if (isset($installed['versions'][$packageName]['pretty_version'])) {
+ $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+ }
+ if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+ }
+ if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+ }
+ if (array_key_exists('provided', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+ }
+
+ return implode(' || ', $ranges);
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['version'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['version'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getPrettyVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['pretty_version'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+ */
+ public static function getReference($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['reference'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['reference'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+ */
+ public static function getInstallPath($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @return array
+ * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
+ */
+ public static function getRootPackage()
+ {
+ $installed = self::getInstalled();
+
+ return $installed[0]['root'];
+ }
+
+ /**
+ * Returns the raw installed.php data for custom implementations
+ *
+ * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+ * @return array[]
+ * @psalm-return 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[]}>}
+ */
+ public static function getRawData()
+ {
+ @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ self::$installed = include __DIR__ . '/installed.php';
+ } else {
+ self::$installed = array();
+ }
+ }
+
+ return self::$installed;
+ }
+
+ /**
+ * Returns the raw data of all installed.php which are currently loaded for custom implementations
+ *
+ * @return array[]
+ * @psalm-return list<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[]}>}>
+ */
+ public static function getAllRawData()
+ {
+ return self::getInstalled();
+ }
+
+ /**
+ * Lets you reload the static array from another file
+ *
+ * This is only useful for complex integrations in which a project needs to use
+ * this class but then also needs to execute another project's autoloader in process,
+ * and wants to ensure both projects have access to their version of installed.php.
+ *
+ * A typical case would be PHPUnit, where it would need to make sure it reads all
+ * the data it needs from this class, then call reload() with
+ * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+ * the project in which it runs can then also use this class safely, without
+ * interference between PHPUnit's dependencies and the project's dependencies.
+ *
+ * @param array[] $data A vendor/composer/installed.php data set
+ * @return void
+ *
+ * @psalm-param 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[]}>} $data
+ */
+ public static function reload($data)
+ {
+ self::$installed = $data;
+ self::$installedByVendor = array();
+ }
+
+ /**
+ * @return array[]
+ * @psalm-return list<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[]}>}>
+ */
+ private static function getInstalled()
+ {
+ if (null === self::$canGetVendors) {
+ self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+ }
+
+ $installed = array();
+
+ if (self::$canGetVendors) {
+ foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ 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];
+ }
+ }
+ }
+ }
+
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ /** @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 __DIR__ . '/installed.php';
+ self::$installed = $required;
+ } else {
+ self::$installed = array();
+ }
+ }
+
+ if (self::$installed !== array()) {
+ $installed[] = self::$installed;
+ }
+
+ return $installed;
+ }
+}
diff --git a/apps/dashboard/composer/composer/LICENSE b/apps/dashboard/composer/composer/LICENSE
new file mode 100644
index 00000000000..f27399a042d
--- /dev/null
+++ b/apps/dashboard/composer/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/apps/dashboard/composer/composer/autoload_classmap.php b/apps/dashboard/composer/composer/autoload_classmap.php
new file mode 100644
index 00000000000..4a8609daeb0
--- /dev/null
+++ b/apps/dashboard/composer/composer/autoload_classmap.php
@@ -0,0 +1,14 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = $vendorDir;
+
+return array(
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
+ 'OCA\\Dashboard\\Controller\\DashboardApiController' => $baseDir . '/../lib/Controller/DashboardApiController.php',
+ 'OCA\\Dashboard\\Controller\\DashboardController' => $baseDir . '/../lib/Controller/DashboardController.php',
+ 'OCA\\Dashboard\\ResponseDefinitions' => $baseDir . '/../lib/ResponseDefinitions.php',
+ 'OCA\\Dashboard\\Service\\DashboardService' => $baseDir . '/../lib/Service/DashboardService.php',
+);
diff --git a/apps/dashboard/composer/composer/autoload_namespaces.php b/apps/dashboard/composer/composer/autoload_namespaces.php
new file mode 100644
index 00000000000..3f5c9296251
--- /dev/null
+++ b/apps/dashboard/composer/composer/autoload_namespaces.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = $vendorDir;
+
+return array(
+);
diff --git a/apps/dashboard/composer/composer/autoload_psr4.php b/apps/dashboard/composer/composer/autoload_psr4.php
new file mode 100644
index 00000000000..cb14f828b27
--- /dev/null
+++ b/apps/dashboard/composer/composer/autoload_psr4.php
@@ -0,0 +1,10 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(__DIR__);
+$baseDir = $vendorDir;
+
+return array(
+ 'OCA\\Dashboard\\' => array($baseDir . '/../lib'),
+);
diff --git a/apps/dashboard/composer/composer/autoload_real.php b/apps/dashboard/composer/composer/autoload_real.php
new file mode 100644
index 00000000000..8ec05d00837
--- /dev/null
+++ b/apps/dashboard/composer/composer/autoload_real.php
@@ -0,0 +1,37 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInitDashboard
+{
+ private static $loader;
+
+ public static function loadClassLoader($class)
+ {
+ if ('Composer\Autoload\ClassLoader' === $class) {
+ require __DIR__ . '/ClassLoader.php';
+ }
+ }
+
+ /**
+ * @return \Composer\Autoload\ClassLoader
+ */
+ public static function getLoader()
+ {
+ if (null !== self::$loader) {
+ return self::$loader;
+ }
+
+ spl_autoload_register(array('ComposerAutoloaderInitDashboard', 'loadClassLoader'), true, true);
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
+ spl_autoload_unregister(array('ComposerAutoloaderInitDashboard', 'loadClassLoader'));
+
+ require __DIR__ . '/autoload_static.php';
+ call_user_func(\Composer\Autoload\ComposerStaticInitDashboard::getInitializer($loader));
+
+ $loader->setClassMapAuthoritative(true);
+ $loader->register(true);
+
+ return $loader;
+ }
+}
diff --git a/apps/dashboard/composer/composer/autoload_static.php b/apps/dashboard/composer/composer/autoload_static.php
new file mode 100644
index 00000000000..72f839d3315
--- /dev/null
+++ b/apps/dashboard/composer/composer/autoload_static.php
@@ -0,0 +1,40 @@
+<?php
+
+// autoload_static.php @generated by Composer
+
+namespace Composer\Autoload;
+
+class ComposerStaticInitDashboard
+{
+ public static $prefixLengthsPsr4 = array (
+ 'O' =>
+ array (
+ 'OCA\\Dashboard\\' => 14,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'OCA\\Dashboard\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/../lib',
+ ),
+ );
+
+ public static $classMap = array (
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+ 'OCA\\Dashboard\\Controller\\DashboardApiController' => __DIR__ . '/..' . '/../lib/Controller/DashboardApiController.php',
+ 'OCA\\Dashboard\\Controller\\DashboardController' => __DIR__ . '/..' . '/../lib/Controller/DashboardController.php',
+ 'OCA\\Dashboard\\ResponseDefinitions' => __DIR__ . '/..' . '/../lib/ResponseDefinitions.php',
+ 'OCA\\Dashboard\\Service\\DashboardService' => __DIR__ . '/..' . '/../lib/Service/DashboardService.php',
+ );
+
+ public static function getInitializer(ClassLoader $loader)
+ {
+ return \Closure::bind(function () use ($loader) {
+ $loader->prefixLengthsPsr4 = ComposerStaticInitDashboard::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInitDashboard::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInitDashboard::$classMap;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/apps/dashboard/composer/composer/installed.json b/apps/dashboard/composer/composer/installed.json
new file mode 100644
index 00000000000..f20a6c47c6d
--- /dev/null
+++ b/apps/dashboard/composer/composer/installed.json
@@ -0,0 +1,5 @@
+{
+ "packages": [],
+ "dev": false,
+ "dev-package-names": []
+}
diff --git a/apps/dashboard/composer/composer/installed.php b/apps/dashboard/composer/composer/installed.php
new file mode 100644
index 00000000000..1a66c7f2416
--- /dev/null
+++ b/apps/dashboard/composer/composer/installed.php
@@ -0,0 +1,23 @@
+<?php return array(
+ 'root' => array(
+ 'name' => '__root__',
+ 'pretty_version' => 'dev-master',
+ 'version' => 'dev-master',
+ 'reference' => 'b1797842784b250fb01ed5e3bf130705eb94751b',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../',
+ 'aliases' => array(),
+ 'dev' => false,
+ ),
+ 'versions' => array(
+ '__root__' => array(
+ 'pretty_version' => 'dev-master',
+ 'version' => 'dev-master',
+ 'reference' => 'b1797842784b250fb01ed5e3bf130705eb94751b',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ ),
+);
diff --git a/apps/dashboard/css/dashboard.css b/apps/dashboard/css/dashboard.css
new file mode 100644
index 00000000000..555d524f5e8
--- /dev/null
+++ b/apps/dashboard/css/dashboard.css
@@ -0,0 +1,4 @@
+/*!
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */#header{background:rgba(0,0,0,0) !important;--color-header: rgba(24, 24, 24, 1)}#body-user.dashboard--dark #header{--color-header: rgba(255, 255, 255, 1)}#header:before{content:" ";display:block;position:absolute;background-image:linear-gradient(180deg, var(--color-header) 0%, transparent 100%);width:100%;height:70px;top:0;margin-top:-70px;transition:margin-top var(--animation-slow)}#body-user.dashboard--scrolled #header:before{margin-top:0}#body-user.theme--highcontrast #header{background-color:var(--color-header) !important}#body-user.theme--highcontrast #header:before{display:none}#content{padding-top:0 !important}#appmenu li a.active::before,#appmenu li:hover a::before,#appmenu li:hover a.active::before,#appmenu li a:focus::before{display:none !important}/*# sourceMappingURL=dashboard.css.map */
diff --git a/apps/dashboard/css/dashboard.css.map b/apps/dashboard/css/dashboard.css.map
new file mode 100644
index 00000000000..c0b088c930f
--- /dev/null
+++ b/apps/dashboard/css/dashboard.css.map
@@ -0,0 +1 @@
+{"version":3,"sourceRoot":"","sources":["dashboard.scss"],"names":[],"mappings":"AAAA;AAAA;AAAA;AAAA,GAIA,QACC,oCACA,oCAEA,mCACC,uCAID,eACC,YACA,cACA,kBACA,mFACA,WACA,YACA,MACA,iBACA,4CAEA,8CACC,aAKF,uCACC,gDAEA,8CACC,aAMH,SACC,yBAID,wHAIC","file":"dashboard.css"} \ No newline at end of file
diff --git a/apps/dashboard/css/dashboard.css.map.license b/apps/dashboard/css/dashboard.css.map.license
new file mode 100644
index 00000000000..d40c4ebf2cd
--- /dev/null
+++ b/apps/dashboard/css/dashboard.css.map.license
@@ -0,0 +1,3 @@
+SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later
+ \ No newline at end of file
diff --git a/apps/dashboard/css/dashboard.scss b/apps/dashboard/css/dashboard.scss
new file mode 100644
index 00000000000..1ae2633d05a
--- /dev/null
+++ b/apps/dashboard/css/dashboard.scss
@@ -0,0 +1,51 @@
+/*!
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+#header {
+ background: transparent !important;
+ --color-header: rgba(24, 24, 24, 1);
+
+ #body-user.dashboard--dark & {
+ --color-header: rgba(255, 255, 255, 1);
+ }
+
+ // Show gradient below navigation for visibility of icons when scrolled
+ &:before {
+ content: ' ';
+ display: block;
+ position: absolute;
+ background-image: linear-gradient(180deg, var(--color-header) 0%, transparent 100%);
+ width: 100%;
+ height: 70px;
+ top: 0;
+ margin-top: -70px;
+ transition: margin-top var(--animation-slow);
+
+ #body-user.dashboard--scrolled & {
+ margin-top: 0;
+ }
+ }
+
+ // Use flat color instead of gradient for high contrast theme
+ #body-user.theme--highcontrast & {
+ background-color: var(--color-header) !important;
+
+ &:before {
+ display: none;
+ }
+ }
+}
+
+// Move content up so it scrolls below navigation
+#content {
+ padding-top: 0 !important;
+}
+
+// Hide triangle indicators from navigation since they are out of place without the header bar
+#appmenu li a.active::before,
+#appmenu li:hover a::before,
+#appmenu li:hover a.active::before,
+#appmenu li a:focus::before {
+ display: none !important;
+}
diff --git a/apps/dashboard/img/dashboard.svg b/apps/dashboard/img/dashboard.svg
new file mode 100644
index 00000000000..f09b3e6ba3b
--- /dev/null
+++ b/apps/dashboard/img/dashboard.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px" fill="#fff"><path d="M216-240q-33 0-52.5-19.5T144-312v-336q0-33 19.5-52.5T216-720h48q33 0 52.5 19.5T336-648v336q0 33-19.5 52.5T264-240h-48Zm240 0q-33 0-52.5-19.5T384-312v-336q0-33 19.5-52.5T456-720h48q33 0 52.5 19.5T576-648v336q0 33-19.5 52.5T504-240h-48Zm240 0q-33 0-52.5-19.5T624-312v-336q0-33 19.5-52.5T696-720h48q33 0 52.5 19.5T816-648v336q0 33-19.5 52.5T744-240h-48Z"/></svg> \ No newline at end of file
diff --git a/apps/dashboard/img/dashboard.svg.license b/apps/dashboard/img/dashboard.svg.license
new file mode 100644
index 00000000000..7f927f9711c
--- /dev/null
+++ b/apps/dashboard/img/dashboard.svg.license
@@ -0,0 +1,4 @@
+SPDX-FileCopyrightText: 2018-2024 Google LLC
+SPDX-License-Identifier: Apache-2.0
+
+Source: Material Symbols icon "View Column"
diff --git a/apps/dashboard/l10n/.gitkeep b/apps/dashboard/l10n/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/apps/dashboard/l10n/.gitkeep
diff --git a/apps/dashboard/l10n/ar.js b/apps/dashboard/l10n/ar.js
new file mode 100644
index 00000000000..0f470b39637
--- /dev/null
+++ b/apps/dashboard/l10n/ar.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "الرئيسية",
+ "Dashboard app" : "تطبيق الصفحة الرئيسية",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "ابدأ يومك على اطِّلاع. \n\nتُعدُّ لوحة المعلومات dashboard في نكست كلاود هي نقطة البداية لليوم. إذ هي تُوفِّر لك نظرة عامة على مواعيدك القادمة و رسائل بريدك العاجلة و رسائل الدردشة و التذاكر الواردة و أحدث التغريدات و غير ذلك الكثير! يُمكِن للمستخدِم إضافة الأدوات التي يحبها و تغيير الخلفية حسب رغبته.",
+ "Weather" : "الطقس",
+ "Status" : "الحالة",
+ "Good morning" : "صباح الخير",
+ "Good morning, {name}" : "صباح الخير ، {name}",
+ "Good afternoon" : "مساء الخير",
+ "Good afternoon, {name}" : "مساء الخير، {name}",
+ "Good evening" : "مساء الخير",
+ "Good evening, {name}" : "مساء الخير، {name}",
+ "Hello" : "مرحباً",
+ "Hello, {name}" : "أهلا، {name} ",
+ "Happy birthday 🥳🤩🎂🎉" : "عيد ميلاد سعيد 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "عيد ميلاد سعيد, يا {name} 🥳🤩🎂🎉",
+ "Customize" : "تعديل",
+ "Edit widgets" : "تعديل أدوات الصفحة الرئيسية",
+ "Get more widgets from the App Store" : "يمكنك الحصول على المزيد من الأدوات من متجر التطبيقات",
+ "Weather service" : "خدمة الطقس",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "للحفاظ على خصوصيتك، يتم استدعاء بيانات حالة الطقس عبر خادم NextCloud الخاص بك نيابه عنك، وبالتالي فإن خدمة حالة الطقس لا تشارك معلوماتك الشخصية.",
+ "Weather data from Met.no" : "بيانات الطقس من Met.no",
+ "geocoding with Nominatim" : "الترميز الجغرافي مع Nominatim",
+ "elevation data from OpenTopoData" : "بيانات التقييم من OpenTopoData"
+},
+"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/apps/dashboard/l10n/ar.json b/apps/dashboard/l10n/ar.json
new file mode 100644
index 00000000000..45a0facbe46
--- /dev/null
+++ b/apps/dashboard/l10n/ar.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "الرئيسية",
+ "Dashboard app" : "تطبيق الصفحة الرئيسية",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "ابدأ يومك على اطِّلاع. \n\nتُعدُّ لوحة المعلومات dashboard في نكست كلاود هي نقطة البداية لليوم. إذ هي تُوفِّر لك نظرة عامة على مواعيدك القادمة و رسائل بريدك العاجلة و رسائل الدردشة و التذاكر الواردة و أحدث التغريدات و غير ذلك الكثير! يُمكِن للمستخدِم إضافة الأدوات التي يحبها و تغيير الخلفية حسب رغبته.",
+ "Weather" : "الطقس",
+ "Status" : "الحالة",
+ "Good morning" : "صباح الخير",
+ "Good morning, {name}" : "صباح الخير ، {name}",
+ "Good afternoon" : "مساء الخير",
+ "Good afternoon, {name}" : "مساء الخير، {name}",
+ "Good evening" : "مساء الخير",
+ "Good evening, {name}" : "مساء الخير، {name}",
+ "Hello" : "مرحباً",
+ "Hello, {name}" : "أهلا، {name} ",
+ "Happy birthday 🥳🤩🎂🎉" : "عيد ميلاد سعيد 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "عيد ميلاد سعيد, يا {name} 🥳🤩🎂🎉",
+ "Customize" : "تعديل",
+ "Edit widgets" : "تعديل أدوات الصفحة الرئيسية",
+ "Get more widgets from the App Store" : "يمكنك الحصول على المزيد من الأدوات من متجر التطبيقات",
+ "Weather service" : "خدمة الطقس",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "للحفاظ على خصوصيتك، يتم استدعاء بيانات حالة الطقس عبر خادم NextCloud الخاص بك نيابه عنك، وبالتالي فإن خدمة حالة الطقس لا تشارك معلوماتك الشخصية.",
+ "Weather data from Met.no" : "بيانات الطقس من Met.no",
+ "geocoding with Nominatim" : "الترميز الجغرافي مع Nominatim",
+ "elevation data from OpenTopoData" : "بيانات التقييم من OpenTopoData"
+},"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/apps/dashboard/l10n/ast.js b/apps/dashboard/l10n/ast.js
new file mode 100644
index 00000000000..30325efa25e
--- /dev/null
+++ b/apps/dashboard/l10n/ast.js
@@ -0,0 +1,26 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Panel",
+ "Dashboard app" : "L'aplicación Panel",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comienza'l día con tola información anovada\n\nEl Panel de Nextcloud ye'l llugar principal que t'ufre una vista xeneral d'eventos próximos, mensaxes urxentes y muncha información más. Los usuarios puen amestar los widgets que-yos presten y camudar el fondu al so gustu.",
+ "Weather" : "Clima",
+ "Status" : "Estáu",
+ "Good morning" : "Bonos díes",
+ "Good morning, {name}" : "Bonos díes, {name}",
+ "Good afternoon" : "Bones tardes",
+ "Good afternoon, {name}" : "Bones tardes, {name}",
+ "Good evening" : "Bones nueches",
+ "Good evening, {name}" : "Bones nueches, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar los widgets",
+ "Get more widgets from the App Store" : "Consigui más widgets de l'App Store",
+ "Weather service" : "Serviciu del clima",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Pa la to privacidá, los datos del clima solicítense dende esta instancia de Nextcloud y, polo tanto, el serviciu del clima no recibe nenguna información personal.",
+ "Weather data from Met.no" : "datos del clima de Met.no",
+ "geocoding with Nominatim" : "xeocodificación con Nominatim",
+ "elevation data from OpenTopoData" : "datos d'elevaciones d'OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/ast.json b/apps/dashboard/l10n/ast.json
new file mode 100644
index 00000000000..65ddc086f24
--- /dev/null
+++ b/apps/dashboard/l10n/ast.json
@@ -0,0 +1,24 @@
+{ "translations": {
+ "Dashboard" : "Panel",
+ "Dashboard app" : "L'aplicación Panel",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comienza'l día con tola información anovada\n\nEl Panel de Nextcloud ye'l llugar principal que t'ufre una vista xeneral d'eventos próximos, mensaxes urxentes y muncha información más. Los usuarios puen amestar los widgets que-yos presten y camudar el fondu al so gustu.",
+ "Weather" : "Clima",
+ "Status" : "Estáu",
+ "Good morning" : "Bonos díes",
+ "Good morning, {name}" : "Bonos díes, {name}",
+ "Good afternoon" : "Bones tardes",
+ "Good afternoon, {name}" : "Bones tardes, {name}",
+ "Good evening" : "Bones nueches",
+ "Good evening, {name}" : "Bones nueches, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar los widgets",
+ "Get more widgets from the App Store" : "Consigui más widgets de l'App Store",
+ "Weather service" : "Serviciu del clima",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Pa la to privacidá, los datos del clima solicítense dende esta instancia de Nextcloud y, polo tanto, el serviciu del clima no recibe nenguna información personal.",
+ "Weather data from Met.no" : "datos del clima de Met.no",
+ "geocoding with Nominatim" : "xeocodificación con Nominatim",
+ "elevation data from OpenTopoData" : "datos d'elevaciones d'OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/be.js b/apps/dashboard/l10n/be.js
new file mode 100644
index 00000000000..1241d374320
--- /dev/null
+++ b/apps/dashboard/l10n/be.js
@@ -0,0 +1,21 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Панэль кіравання",
+ "Dashboard app" : "Праграма Панэль кіравання",
+ "Weather" : "Надвор'е",
+ "Status" : "Стан",
+ "Good morning" : "Добрай раніцы",
+ "Good morning, {name}" : "Добрай раніцы, {name}",
+ "Good afternoon" : "Добры дзень",
+ "Good afternoon, {name}" : "Добры дзень, {name}",
+ "Good evening" : "Добры вечар",
+ "Good evening, {name}" : "Добры вечар, {name}",
+ "Hello" : "Вітаем",
+ "Hello, {name}" : "Вітаем, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "З народзінамі 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "З народзінамі, {name} 🥳🤩🎂🎉",
+ "Customize" : "Дапасаваць",
+ "Edit widgets" : "Рэдагаваць віджэты"
+},
+"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/apps/dashboard/l10n/be.json b/apps/dashboard/l10n/be.json
new file mode 100644
index 00000000000..fe7badbba4b
--- /dev/null
+++ b/apps/dashboard/l10n/be.json
@@ -0,0 +1,19 @@
+{ "translations": {
+ "Dashboard" : "Панэль кіравання",
+ "Dashboard app" : "Праграма Панэль кіравання",
+ "Weather" : "Надвор'е",
+ "Status" : "Стан",
+ "Good morning" : "Добрай раніцы",
+ "Good morning, {name}" : "Добрай раніцы, {name}",
+ "Good afternoon" : "Добры дзень",
+ "Good afternoon, {name}" : "Добры дзень, {name}",
+ "Good evening" : "Добры вечар",
+ "Good evening, {name}" : "Добры вечар, {name}",
+ "Hello" : "Вітаем",
+ "Hello, {name}" : "Вітаем, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "З народзінамі 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "З народзінамі, {name} 🥳🤩🎂🎉",
+ "Customize" : "Дапасаваць",
+ "Edit widgets" : "Рэдагаваць віджэты"
+},"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/apps/dashboard/l10n/bg.js b/apps/dashboard/l10n/bg.js
new file mode 100644
index 00000000000..52bf79b3acc
--- /dev/null
+++ b/apps/dashboard/l10n/bg.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Табло",
+ "Dashboard app" : "Приложение за Табло",
+ "Weather" : "Време",
+ "Status" : "Състояние",
+ "Good morning" : "Добро утро",
+ "Good morning, {name}" : "Добро утро, {name}",
+ "Good afternoon" : "Добър ден",
+ "Good afternoon, {name}" : "Добър ден, {name}",
+ "Good evening" : "Добър вечер",
+ "Good evening, {name}" : "Добър вечер, {name}",
+ "Hello" : "Здравейте",
+ "Hello, {name}" : "Здравейте, {name}",
+ "Customize" : "Персонизиране",
+ "Edit widgets" : "Редактиране на изпълнимите модули",
+ "Get more widgets from the App Store" : "Вземете повече приспособления от App Store",
+ "Weather service" : "Метеорологична услуга",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "За вашата поверителност данните за времето се изискват от Nextcloud сървъра ви от ваше име, така че метеорологичната служба не получава лична информация.",
+ "Weather data from Met.no" : "Данни за времето от Met.no",
+ "geocoding with Nominatim" : "геокодиране с Nominatim",
+ "elevation data from OpenTopoData" : " кота данни от OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/bg.json b/apps/dashboard/l10n/bg.json
new file mode 100644
index 00000000000..1d240b3440e
--- /dev/null
+++ b/apps/dashboard/l10n/bg.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Табло",
+ "Dashboard app" : "Приложение за Табло",
+ "Weather" : "Време",
+ "Status" : "Състояние",
+ "Good morning" : "Добро утро",
+ "Good morning, {name}" : "Добро утро, {name}",
+ "Good afternoon" : "Добър ден",
+ "Good afternoon, {name}" : "Добър ден, {name}",
+ "Good evening" : "Добър вечер",
+ "Good evening, {name}" : "Добър вечер, {name}",
+ "Hello" : "Здравейте",
+ "Hello, {name}" : "Здравейте, {name}",
+ "Customize" : "Персонизиране",
+ "Edit widgets" : "Редактиране на изпълнимите модули",
+ "Get more widgets from the App Store" : "Вземете повече приспособления от App Store",
+ "Weather service" : "Метеорологична услуга",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "За вашата поверителност данните за времето се изискват от Nextcloud сървъра ви от ваше име, така че метеорологичната служба не получава лична информация.",
+ "Weather data from Met.no" : "Данни за времето от Met.no",
+ "geocoding with Nominatim" : "геокодиране с Nominatim",
+ "elevation data from OpenTopoData" : " кота данни от OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/ca.js b/apps/dashboard/l10n/ca.js
new file mode 100644
index 00000000000..e1c49734018
--- /dev/null
+++ b/apps/dashboard/l10n/ca.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Tauler",
+ "Dashboard app" : "Aplicació Tauler",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comença el dia informat\n\nEl tauler de control de Nextcloud és el vostre punt de partida del dia, que us ofereix una visió general de les vostres properes cites, correus electrònics urgents, missatges de xat, entrades entrants, els darrers tuits i molt més! Les persones poden afegir els ginys que els agradin i canviar el fons al seu gust.",
+ "Weather" : "Temps",
+ "Status" : "Estat",
+ "Good morning" : "Bon dia",
+ "Good morning, {name}" : "Bon dia, {name}",
+ "Good afternoon" : "Bona tarda",
+ "Good afternoon, {name}" : "Bona tarda, {name}",
+ "Good evening" : "Bona nit",
+ "Good evening, {name}" : "Bona nit, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Per molts anys 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Per molts anys, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalitza",
+ "Edit widgets" : "Edita els ginys",
+ "Get more widgets from the App Store" : "Obtén més ginys a la botiga d'aplicacions",
+ "Weather service" : "Servei meteorològic",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Per a la vostra privadesa, les dades meteorològiques les sol·licita el servidor del Nextcloud en nom vostre perquè el servei meteorològic no rebi cap informació personal.",
+ "Weather data from Met.no" : "Dades meteorològiques de Met.no",
+ "geocoding with Nominatim" : "codis geogràfics amb Nominatim",
+ "elevation data from OpenTopoData" : "dades d'altitud d'OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/ca.json b/apps/dashboard/l10n/ca.json
new file mode 100644
index 00000000000..1a96361720c
--- /dev/null
+++ b/apps/dashboard/l10n/ca.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Tauler",
+ "Dashboard app" : "Aplicació Tauler",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comença el dia informat\n\nEl tauler de control de Nextcloud és el vostre punt de partida del dia, que us ofereix una visió general de les vostres properes cites, correus electrònics urgents, missatges de xat, entrades entrants, els darrers tuits i molt més! Les persones poden afegir els ginys que els agradin i canviar el fons al seu gust.",
+ "Weather" : "Temps",
+ "Status" : "Estat",
+ "Good morning" : "Bon dia",
+ "Good morning, {name}" : "Bon dia, {name}",
+ "Good afternoon" : "Bona tarda",
+ "Good afternoon, {name}" : "Bona tarda, {name}",
+ "Good evening" : "Bona nit",
+ "Good evening, {name}" : "Bona nit, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Per molts anys 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Per molts anys, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalitza",
+ "Edit widgets" : "Edita els ginys",
+ "Get more widgets from the App Store" : "Obtén més ginys a la botiga d'aplicacions",
+ "Weather service" : "Servei meteorològic",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Per a la vostra privadesa, les dades meteorològiques les sol·licita el servidor del Nextcloud en nom vostre perquè el servei meteorològic no rebi cap informació personal.",
+ "Weather data from Met.no" : "Dades meteorològiques de Met.no",
+ "geocoding with Nominatim" : "codis geogràfics amb Nominatim",
+ "elevation data from OpenTopoData" : "dades d'altitud d'OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/cs.js b/apps/dashboard/l10n/cs.js
new file mode 100644
index 00000000000..a50199ce469
--- /dev/null
+++ b/apps/dashboard/l10n/cs.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Nástěnka",
+ "Dashboard app" : "Aplikace Nástěnka",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Začněte svůj den informovaní\n\nNextcloud Nástěnka je váš úvodní bod dne, který vám podává přehled\nnadcházejících schůzek, neodkladných e-mailů, zpráv v chatech, příchozích\npožadavků, nejnovějších tweetů a mnoha dalšího! Lidé si\nmohou přidávat ovládací prvky, které chtějí a měnit pozadí dle své libosti.",
+ "Weather" : "Počasí",
+ "Status" : "Stav",
+ "Good morning" : "Dobré ráno",
+ "Good morning, {name}" : "Dobré ráno, {name}",
+ "Good afternoon" : "Dobré odpoledne",
+ "Good afternoon, {name}" : "Dobré odpoledne, {name}",
+ "Good evening" : "Dobrý večer",
+ "Good evening, {name}" : "Dobrý večer, {name}",
+ "Hello" : "Dobrý den",
+ "Hello, {name}" : "Dobrý den, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Všechno nejlepší k narozeninám 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Všechno nejlepší k narozeninám, {name} 🥳🤩🎂🎉",
+ "Customize" : "Přizpůsobit si",
+ "Edit widgets" : "Upravit ovládací prvky",
+ "Get more widgets from the App Store" : "Získat další ovládací prvky z katalogu aplikací",
+ "Weather service" : "Služba předpovědi počasí",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Vaše soukromí je chráněno tím, že komunikaci se službou předpovědi počasí zprostředkovává vámi využívaný Nextcloud server. Díky tomu služba, která tyto údaje poskytuje, neobdrží z vašeho počítače žádné osobní údaje.",
+ "Weather data from Met.no" : "Údaje o počasí z Met.no",
+ "geocoding with Nominatim" : "z popisu polohy na souřadnice převáděno službou Nominatim",
+ "elevation data from OpenTopoData" : "data o nadmořských výškách z OpenTopoData"
+},
+"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/apps/dashboard/l10n/cs.json b/apps/dashboard/l10n/cs.json
new file mode 100644
index 00000000000..8e0d2b79295
--- /dev/null
+++ b/apps/dashboard/l10n/cs.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Nástěnka",
+ "Dashboard app" : "Aplikace Nástěnka",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Začněte svůj den informovaní\n\nNextcloud Nástěnka je váš úvodní bod dne, který vám podává přehled\nnadcházejících schůzek, neodkladných e-mailů, zpráv v chatech, příchozích\npožadavků, nejnovějších tweetů a mnoha dalšího! Lidé si\nmohou přidávat ovládací prvky, které chtějí a měnit pozadí dle své libosti.",
+ "Weather" : "Počasí",
+ "Status" : "Stav",
+ "Good morning" : "Dobré ráno",
+ "Good morning, {name}" : "Dobré ráno, {name}",
+ "Good afternoon" : "Dobré odpoledne",
+ "Good afternoon, {name}" : "Dobré odpoledne, {name}",
+ "Good evening" : "Dobrý večer",
+ "Good evening, {name}" : "Dobrý večer, {name}",
+ "Hello" : "Dobrý den",
+ "Hello, {name}" : "Dobrý den, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Všechno nejlepší k narozeninám 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Všechno nejlepší k narozeninám, {name} 🥳🤩🎂🎉",
+ "Customize" : "Přizpůsobit si",
+ "Edit widgets" : "Upravit ovládací prvky",
+ "Get more widgets from the App Store" : "Získat další ovládací prvky z katalogu aplikací",
+ "Weather service" : "Služba předpovědi počasí",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Vaše soukromí je chráněno tím, že komunikaci se službou předpovědi počasí zprostředkovává vámi využívaný Nextcloud server. Díky tomu služba, která tyto údaje poskytuje, neobdrží z vašeho počítače žádné osobní údaje.",
+ "Weather data from Met.no" : "Údaje o počasí z Met.no",
+ "geocoding with Nominatim" : "z popisu polohy na souřadnice převáděno službou Nominatim",
+ "elevation data from OpenTopoData" : "data o nadmořských výškách z OpenTopoData"
+},"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/apps/dashboard/l10n/da.js b/apps/dashboard/l10n/da.js
new file mode 100644
index 00000000000..3f12d287e1f
--- /dev/null
+++ b/apps/dashboard/l10n/da.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Start din dag med gode informationer\n\nNextcloud Dashboard er dit udgangspunkt på dagen og giver dig et overblik over dine kommende aftaler, hastemails, chatbeskeder, indgående billetter, seneste tweets og meget mere! Folk kan tilføje de widgets, de kan lide, og ændre baggrunden efter deres smag.",
+ "Weather" : "Vejr",
+ "Status" : "Status",
+ "Good morning" : "God morgen",
+ "Good morning, {name}" : "God morgen {name}",
+ "Good afternoon" : "God eftermiddag",
+ "Good afternoon, {name}" : "God eftermiddag {name}",
+ "Good evening" : "God aften",
+ "Good evening, {name}" : "God aften {name}",
+ "Hello" : "Hej",
+ "Hello, {name}" : "Hej {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Tillykke med fødselsdagen 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Tillykke med fødselsdagen, {name} 🥳🤩🎂🎉",
+ "Customize" : "Tilpas",
+ "Edit widgets" : "Tilpas widgets",
+ "Get more widgets from the App Store" : "Få flere widgets fra App Store",
+ "Weather service" : "Vejret",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Af hensyn til dit privatliv, er det din Nextcloud-server der henter vejr-data og udbyderen modtager således ingen oplysninger om dig.",
+ "Weather data from Met.no" : "Vejr-data leveres af Met.no",
+ "geocoding with Nominatim" : "Geocoding med Nominatim",
+ "elevation data from OpenTopoData" : "Højde-data fra OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/da.json b/apps/dashboard/l10n/da.json
new file mode 100644
index 00000000000..c110ae91b79
--- /dev/null
+++ b/apps/dashboard/l10n/da.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Start din dag med gode informationer\n\nNextcloud Dashboard er dit udgangspunkt på dagen og giver dig et overblik over dine kommende aftaler, hastemails, chatbeskeder, indgående billetter, seneste tweets og meget mere! Folk kan tilføje de widgets, de kan lide, og ændre baggrunden efter deres smag.",
+ "Weather" : "Vejr",
+ "Status" : "Status",
+ "Good morning" : "God morgen",
+ "Good morning, {name}" : "God morgen {name}",
+ "Good afternoon" : "God eftermiddag",
+ "Good afternoon, {name}" : "God eftermiddag {name}",
+ "Good evening" : "God aften",
+ "Good evening, {name}" : "God aften {name}",
+ "Hello" : "Hej",
+ "Hello, {name}" : "Hej {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Tillykke med fødselsdagen 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Tillykke med fødselsdagen, {name} 🥳🤩🎂🎉",
+ "Customize" : "Tilpas",
+ "Edit widgets" : "Tilpas widgets",
+ "Get more widgets from the App Store" : "Få flere widgets fra App Store",
+ "Weather service" : "Vejret",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Af hensyn til dit privatliv, er det din Nextcloud-server der henter vejr-data og udbyderen modtager således ingen oplysninger om dig.",
+ "Weather data from Met.no" : "Vejr-data leveres af Met.no",
+ "geocoding with Nominatim" : "Geocoding med Nominatim",
+ "elevation data from OpenTopoData" : "Højde-data fra OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/de.js b/apps/dashboard/l10n/de.js
new file mode 100644
index 00000000000..b7cbd1adb43
--- /dev/null
+++ b/apps/dashboard/l10n/de.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard-App",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Starte informiert in den Tag\n\nDas Nextcloud Dashboard ist dein Ausgangspunkt für den Tag und gibt dir einen Überblick über deine anstehenden Termine, dringende E-Mails, Chatnachrichten, eingehende Tickets, neueste Tweets und vieles mehr! Benutzer können die gewünschten Widgets hinzufügen und den Hintergrund nach Belieben ändern.",
+ "Weather" : "Wetter",
+ "Status" : "Status",
+ "Good morning" : "Guten Morgen",
+ "Good morning, {name}" : "Guten Morgen {name}",
+ "Good afternoon" : "Guten Tag",
+ "Good afternoon, {name}" : "Guten Tag {name}",
+ "Good evening" : "Guten Abend",
+ "Good evening, {name}" : "Guten Abend {name}",
+ "Hello" : "Hallo",
+ "Hello, {name}" : "Hallo, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Alles Gute zum Geburtstag 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Alles Gute zum Geburtstag, {name} 🥳🤩🎂🎉",
+ "Customize" : "Anpassen",
+ "Edit widgets" : "Widgets bearbeiten",
+ "Get more widgets from the App Store" : "Hole dir weitere Widgets aus dem App-Store",
+ "Weather service" : "Wetterdienst",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Zu deinem Datenschutz werden die Wetterdaten von deinem Nextcloud-Server für dich angefordert, so dass der Wetterdienst keine persönlichen Informationen erhält.",
+ "Weather data from Met.no" : "Wetterdaten von Met.no",
+ "geocoding with Nominatim" : "Geokodierung mit Nominatim",
+ "elevation data from OpenTopoData" : "Höhendaten von OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/de.json b/apps/dashboard/l10n/de.json
new file mode 100644
index 00000000000..bb44568bf30
--- /dev/null
+++ b/apps/dashboard/l10n/de.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard-App",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Starte informiert in den Tag\n\nDas Nextcloud Dashboard ist dein Ausgangspunkt für den Tag und gibt dir einen Überblick über deine anstehenden Termine, dringende E-Mails, Chatnachrichten, eingehende Tickets, neueste Tweets und vieles mehr! Benutzer können die gewünschten Widgets hinzufügen und den Hintergrund nach Belieben ändern.",
+ "Weather" : "Wetter",
+ "Status" : "Status",
+ "Good morning" : "Guten Morgen",
+ "Good morning, {name}" : "Guten Morgen {name}",
+ "Good afternoon" : "Guten Tag",
+ "Good afternoon, {name}" : "Guten Tag {name}",
+ "Good evening" : "Guten Abend",
+ "Good evening, {name}" : "Guten Abend {name}",
+ "Hello" : "Hallo",
+ "Hello, {name}" : "Hallo, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Alles Gute zum Geburtstag 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Alles Gute zum Geburtstag, {name} 🥳🤩🎂🎉",
+ "Customize" : "Anpassen",
+ "Edit widgets" : "Widgets bearbeiten",
+ "Get more widgets from the App Store" : "Hole dir weitere Widgets aus dem App-Store",
+ "Weather service" : "Wetterdienst",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Zu deinem Datenschutz werden die Wetterdaten von deinem Nextcloud-Server für dich angefordert, so dass der Wetterdienst keine persönlichen Informationen erhält.",
+ "Weather data from Met.no" : "Wetterdaten von Met.no",
+ "geocoding with Nominatim" : "Geokodierung mit Nominatim",
+ "elevation data from OpenTopoData" : "Höhendaten von OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/de_DE.js b/apps/dashboard/l10n/de_DE.js
new file mode 100644
index 00000000000..4b9b21e1a34
--- /dev/null
+++ b/apps/dashboard/l10n/de_DE.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard-App",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Starten Sie informiert in den Tag\n\nDas Nextcloud Dashboard ist Ihr Ausgangspunkt für den Tag und gibt Ihnen einen Überblick über Ihre anstehenden Termine, dringende E-Mails, Chatnachrichten, eingehende Tickets, neueste Tweets und vieles mehr! Benutzer können die gewünschten Widgets hinzufügen und den Hintergrund nach Belieben ändern.",
+ "Weather" : "Wetter",
+ "Status" : "Status",
+ "Good morning" : "Guten Morgen",
+ "Good morning, {name}" : "Guten Morgen {name}",
+ "Good afternoon" : "Guten Tag",
+ "Good afternoon, {name}" : "Guten Tag {name}",
+ "Good evening" : "Guten Abend",
+ "Good evening, {name}" : "Guten Abend {name}",
+ "Hello" : "Hallo",
+ "Hello, {name}" : "Hallo, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Alles Gute zum Geburtstag 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Alles Gute zum Geburtstag, {name} 🥳🤩🎂🎉",
+ "Customize" : "Anpassen",
+ "Edit widgets" : "Widgets bearbeiten",
+ "Get more widgets from the App Store" : "Holen Sie sich weitere Widgets aus dem App-Store",
+ "Weather service" : "Wetterdienst",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Zu Ihrem Datenschutz werden die Wetterdaten von Ihrem Nextcloud-Server für Sie angefordert, so dass der Wetterdienst keine persönlichen Informationen erhält.",
+ "Weather data from Met.no" : "Wetterdaten von Met.no",
+ "geocoding with Nominatim" : "Geokodierung mit Nominatim",
+ "elevation data from OpenTopoData" : "Höhendaten von OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/de_DE.json b/apps/dashboard/l10n/de_DE.json
new file mode 100644
index 00000000000..4c8ffbec68d
--- /dev/null
+++ b/apps/dashboard/l10n/de_DE.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard-App",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Starten Sie informiert in den Tag\n\nDas Nextcloud Dashboard ist Ihr Ausgangspunkt für den Tag und gibt Ihnen einen Überblick über Ihre anstehenden Termine, dringende E-Mails, Chatnachrichten, eingehende Tickets, neueste Tweets und vieles mehr! Benutzer können die gewünschten Widgets hinzufügen und den Hintergrund nach Belieben ändern.",
+ "Weather" : "Wetter",
+ "Status" : "Status",
+ "Good morning" : "Guten Morgen",
+ "Good morning, {name}" : "Guten Morgen {name}",
+ "Good afternoon" : "Guten Tag",
+ "Good afternoon, {name}" : "Guten Tag {name}",
+ "Good evening" : "Guten Abend",
+ "Good evening, {name}" : "Guten Abend {name}",
+ "Hello" : "Hallo",
+ "Hello, {name}" : "Hallo, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Alles Gute zum Geburtstag 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Alles Gute zum Geburtstag, {name} 🥳🤩🎂🎉",
+ "Customize" : "Anpassen",
+ "Edit widgets" : "Widgets bearbeiten",
+ "Get more widgets from the App Store" : "Holen Sie sich weitere Widgets aus dem App-Store",
+ "Weather service" : "Wetterdienst",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Zu Ihrem Datenschutz werden die Wetterdaten von Ihrem Nextcloud-Server für Sie angefordert, so dass der Wetterdienst keine persönlichen Informationen erhält.",
+ "Weather data from Met.no" : "Wetterdaten von Met.no",
+ "geocoding with Nominatim" : "Geokodierung mit Nominatim",
+ "elevation data from OpenTopoData" : "Höhendaten von OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/el.js b/apps/dashboard/l10n/el.js
new file mode 100644
index 00000000000..81e121a93ee
--- /dev/null
+++ b/apps/dashboard/l10n/el.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Πίνακας ελέγχου",
+ "Dashboard app" : "Εφαρμογή Πίνακα Ελέγχου",
+ "Weather" : "Καιρός",
+ "Status" : "Κατάσταση",
+ "Good morning" : "Καλημέρα",
+ "Good morning, {name}" : "Καλημέρα, {name}",
+ "Good afternoon" : "Καλό απόγευμα",
+ "Good afternoon, {name}" : "Καλό απόγευμα, {name}",
+ "Good evening" : "Καλό βράδυ",
+ "Good evening, {name}" : "Καλό βράδυ, {name}",
+ "Hello" : "Γειά",
+ "Hello, {name}" : "Γειά, {name}",
+ "Customize" : "Προσαρμογή",
+ "Edit widgets" : "Επεξεργασία μικροεφαρμογών",
+ "Get more widgets from the App Store" : "Λάβετε περισσότερες μικροεφαρμογές από το App Store",
+ "Weather service" : "Υπηρεσία καιρού",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Για το απόρρητό σας, τα δεδομένα καιρού ζητούνται από τον διακομιστή Nextcloud για λογαριασμό σας, ώστε η υπηρεσία καιρού να μην λαμβάνει προσωπικά στοιχεία.",
+ "Weather data from Met.no" : "Δεδομένα καιρού από το Met.no",
+ "geocoding with Nominatim" : "geocoding με Nominatim",
+ "elevation data from OpenTopoData" : "δεδομένα elevation από OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/el.json b/apps/dashboard/l10n/el.json
new file mode 100644
index 00000000000..8c5cf787b36
--- /dev/null
+++ b/apps/dashboard/l10n/el.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Πίνακας ελέγχου",
+ "Dashboard app" : "Εφαρμογή Πίνακα Ελέγχου",
+ "Weather" : "Καιρός",
+ "Status" : "Κατάσταση",
+ "Good morning" : "Καλημέρα",
+ "Good morning, {name}" : "Καλημέρα, {name}",
+ "Good afternoon" : "Καλό απόγευμα",
+ "Good afternoon, {name}" : "Καλό απόγευμα, {name}",
+ "Good evening" : "Καλό βράδυ",
+ "Good evening, {name}" : "Καλό βράδυ, {name}",
+ "Hello" : "Γειά",
+ "Hello, {name}" : "Γειά, {name}",
+ "Customize" : "Προσαρμογή",
+ "Edit widgets" : "Επεξεργασία μικροεφαρμογών",
+ "Get more widgets from the App Store" : "Λάβετε περισσότερες μικροεφαρμογές από το App Store",
+ "Weather service" : "Υπηρεσία καιρού",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Για το απόρρητό σας, τα δεδομένα καιρού ζητούνται από τον διακομιστή Nextcloud για λογαριασμό σας, ώστε η υπηρεσία καιρού να μην λαμβάνει προσωπικά στοιχεία.",
+ "Weather data from Met.no" : "Δεδομένα καιρού από το Met.no",
+ "geocoding with Nominatim" : "geocoding με Nominatim",
+ "elevation data from OpenTopoData" : "δεδομένα elevation από OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/en_GB.js b/apps/dashboard/l10n/en_GB.js
new file mode 100644
index 00000000000..0a277fddf96
--- /dev/null
+++ b/apps/dashboard/l10n/en_GB.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking.",
+ "Weather" : "Weather",
+ "Status" : "Status",
+ "Good morning" : "Good morning",
+ "Good morning, {name}" : "Good morning, {name}",
+ "Good afternoon" : "Good afternoon",
+ "Good afternoon, {name}" : "Good afternoon, {name}",
+ "Good evening" : "Good evening",
+ "Good evening, {name}" : "Good evening, {name}",
+ "Hello" : "Hello",
+ "Hello, {name}" : "Hello, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Happy birthday 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Happy birthday, {name} 🥳🤩🎂🎉",
+ "Customize" : "Customise",
+ "Edit widgets" : "Edit widgets",
+ "Get more widgets from the App Store" : "Get more widgets from the App Store",
+ "Weather service" : "Weather service",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.",
+ "Weather data from Met.no" : "Weather data from Met.no",
+ "geocoding with Nominatim" : "geocoding with Nominatim",
+ "elevation data from OpenTopoData" : "elevation data from OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/en_GB.json b/apps/dashboard/l10n/en_GB.json
new file mode 100644
index 00000000000..456645e9a65
--- /dev/null
+++ b/apps/dashboard/l10n/en_GB.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking.",
+ "Weather" : "Weather",
+ "Status" : "Status",
+ "Good morning" : "Good morning",
+ "Good morning, {name}" : "Good morning, {name}",
+ "Good afternoon" : "Good afternoon",
+ "Good afternoon, {name}" : "Good afternoon, {name}",
+ "Good evening" : "Good evening",
+ "Good evening, {name}" : "Good evening, {name}",
+ "Hello" : "Hello",
+ "Hello, {name}" : "Hello, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Happy birthday 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Happy birthday, {name} 🥳🤩🎂🎉",
+ "Customize" : "Customise",
+ "Edit widgets" : "Edit widgets",
+ "Get more widgets from the App Store" : "Get more widgets from the App Store",
+ "Weather service" : "Weather service",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.",
+ "Weather data from Met.no" : "Weather data from Met.no",
+ "geocoding with Nominatim" : "geocoding with Nominatim",
+ "elevation data from OpenTopoData" : "elevation data from OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/es.js b/apps/dashboard/l10n/es.js
new file mode 100644
index 00000000000..06a26af9975
--- /dev/null
+++ b/apps/dashboard/l10n/es.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "App Dashboard",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comience su día informado\n\n¡El tablero de Nextcloud es su punto de partida del día, dándole una vista general de sus próximas citas, correos electrónicos urgentes, mensajes de chat, próximos tickets, últimos tweets y mucho más! Los usuarios podrán agregar los widgets que deseen y cambiar el fondo a gusto.",
+ "Weather" : "El tiempo",
+ "Status" : "Estado",
+ "Good morning" : "Buenos días",
+ "Good morning, {name}" : "Buenos días, {name}",
+ "Good afternoon" : "Buenas tardes",
+ "Good afternoon, {name}" : "Buenas tardes, {name}",
+ "Good evening" : "Buenas tardes",
+ "Good evening, {name}" : "Buenas tardes, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Feliz cumpleaños 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Feliz cumpleaños, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Conseguir más widgets desde la tienda de Apps",
+ "Weather service" : "Servicio meteorológico",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Para su privacidad, los datos meteorológicos son solicitados por su servidor Nextcloud en su nombre, de tal forma que el servicio no reciba información personal.",
+ "Weather data from Met.no" : "Datos meteorológicos de Met.no",
+ "geocoding with Nominatim" : "geocoding con Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData"
+},
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dashboard/l10n/es.json b/apps/dashboard/l10n/es.json
new file mode 100644
index 00000000000..3629d632d0e
--- /dev/null
+++ b/apps/dashboard/l10n/es.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "App Dashboard",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comience su día informado\n\n¡El tablero de Nextcloud es su punto de partida del día, dándole una vista general de sus próximas citas, correos electrónicos urgentes, mensajes de chat, próximos tickets, últimos tweets y mucho más! Los usuarios podrán agregar los widgets que deseen y cambiar el fondo a gusto.",
+ "Weather" : "El tiempo",
+ "Status" : "Estado",
+ "Good morning" : "Buenos días",
+ "Good morning, {name}" : "Buenos días, {name}",
+ "Good afternoon" : "Buenas tardes",
+ "Good afternoon, {name}" : "Buenas tardes, {name}",
+ "Good evening" : "Buenas tardes",
+ "Good evening, {name}" : "Buenas tardes, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Feliz cumpleaños 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Feliz cumpleaños, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Conseguir más widgets desde la tienda de Apps",
+ "Weather service" : "Servicio meteorológico",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Para su privacidad, los datos meteorológicos son solicitados por su servidor Nextcloud en su nombre, de tal forma que el servicio no reciba información personal.",
+ "Weather data from Met.no" : "Datos meteorológicos de Met.no",
+ "geocoding with Nominatim" : "geocoding con Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/es_EC.js b/apps/dashboard/l10n/es_EC.js
new file mode 100644
index 00000000000..4a68faffe73
--- /dev/null
+++ b/apps/dashboard/l10n/es_EC.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Tablero de control",
+ "Dashboard app" : "App Dashboard",
+ "Weather" : "Clima",
+ "Status" : "Estatus",
+ "Good morning" : "Buenos días",
+ "Good morning, {name}" : "Buenos días, {name}",
+ "Good afternoon" : "Buenas tardes",
+ "Good afternoon, {name}" : "Buenas tardes, {name}",
+ "Good evening" : "Buenas noches",
+ "Good evening, {name}" : "Buenas noches, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Conseguir más widgets desde la tienda de Apps",
+ "Weather service" : "Servicio meteorológico",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Por privacidad, los datos meteorológicos son solicitados por tu servidor Nextcloud en tu nombre de tal forma que el servicio no recibe información personal.",
+ "Weather data from Met.no" : "Datos meteorológicos de Met.no",
+ "geocoding with Nominatim" : "geocoding con Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData"
+},
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dashboard/l10n/es_EC.json b/apps/dashboard/l10n/es_EC.json
new file mode 100644
index 00000000000..fd17cc8eb02
--- /dev/null
+++ b/apps/dashboard/l10n/es_EC.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Tablero de control",
+ "Dashboard app" : "App Dashboard",
+ "Weather" : "Clima",
+ "Status" : "Estatus",
+ "Good morning" : "Buenos días",
+ "Good morning, {name}" : "Buenos días, {name}",
+ "Good afternoon" : "Buenas tardes",
+ "Good afternoon, {name}" : "Buenas tardes, {name}",
+ "Good evening" : "Buenas noches",
+ "Good evening, {name}" : "Buenas noches, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Conseguir más widgets desde la tienda de Apps",
+ "Weather service" : "Servicio meteorológico",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Por privacidad, los datos meteorológicos son solicitados por tu servidor Nextcloud en tu nombre de tal forma que el servicio no recibe información personal.",
+ "Weather data from Met.no" : "Datos meteorológicos de Met.no",
+ "geocoding with Nominatim" : "geocoding con Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/es_MX.js b/apps/dashboard/l10n/es_MX.js
new file mode 100644
index 00000000000..48520d3066e
--- /dev/null
+++ b/apps/dashboard/l10n/es_MX.js
@@ -0,0 +1,26 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Tablero de control",
+ "Dashboard app" : "Tablero de control",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comience su día informado\n\n¡El tablero de Nextcloud es su punto de partida del día, dándole una vista general de sus próximas citas, correos electrónicos urgentes, mensajes de chat, próximos tickets, últimos tweets y mucho más! Los usuarios podrán agregar los widgets que deseen y cambiar el fondo a gusto.",
+ "Weather" : "Clima",
+ "Status" : "Estatus",
+ "Good morning" : "Buenos días",
+ "Good morning, {name}" : "Buenos días, {name}",
+ "Good afternoon" : "Buenas tardes",
+ "Good afternoon, {name}" : "Buenas tardes, {name}",
+ "Good evening" : "Buenas tardes",
+ "Good evening, {name}" : "Buenas tardes, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Conseguir más widgets desde la tienda de Apps",
+ "Weather service" : "Servicio metereológico",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Por privacidad, los datos meteorológicos son solicitados por tu servidor Nextcloud en tu nombre de tal forma que el servicio no recibe información personal.",
+ "Weather data from Met.no" : "Datos meteorológicos de Met.no",
+ "geocoding with Nominatim" : "geocoding con Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData"
+},
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dashboard/l10n/es_MX.json b/apps/dashboard/l10n/es_MX.json
new file mode 100644
index 00000000000..737d4e16add
--- /dev/null
+++ b/apps/dashboard/l10n/es_MX.json
@@ -0,0 +1,24 @@
+{ "translations": {
+ "Dashboard" : "Tablero de control",
+ "Dashboard app" : "Tablero de control",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comience su día informado\n\n¡El tablero de Nextcloud es su punto de partida del día, dándole una vista general de sus próximas citas, correos electrónicos urgentes, mensajes de chat, próximos tickets, últimos tweets y mucho más! Los usuarios podrán agregar los widgets que deseen y cambiar el fondo a gusto.",
+ "Weather" : "Clima",
+ "Status" : "Estatus",
+ "Good morning" : "Buenos días",
+ "Good morning, {name}" : "Buenos días, {name}",
+ "Good afternoon" : "Buenas tardes",
+ "Good afternoon, {name}" : "Buenas tardes, {name}",
+ "Good evening" : "Buenas tardes",
+ "Good evening, {name}" : "Buenas tardes, {name}",
+ "Hello" : "Hola",
+ "Hello, {name}" : "Hola, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Conseguir más widgets desde la tienda de Apps",
+ "Weather service" : "Servicio metereológico",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Por privacidad, los datos meteorológicos son solicitados por tu servidor Nextcloud en tu nombre de tal forma que el servicio no recibe información personal.",
+ "Weather data from Met.no" : "Datos meteorológicos de Met.no",
+ "geocoding with Nominatim" : "geocoding con Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/et_EE.js b/apps/dashboard/l10n/et_EE.js
new file mode 100644
index 00000000000..0fb3ed71058
--- /dev/null
+++ b/apps/dashboard/l10n/et_EE.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Töölaud/Juhtpaneel",
+ "Dashboard app" : "Töölaua/juhtpaneeli rakendus",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Alusta oma päeva teadlikult\n\nNextcloudi avaleht on su päeva alguspunkt, mis annab ülevaate eelseisvatest kohtumistest, kiireloomulistest kirjadest, vestlussõnumitest, sissetulevatest päringutest, viimastest säutsudest ja paljust muust! Inimesed saavad lisada neile meeldivaid vidinaid ja muuta tausta oma maitse järgi.",
+ "Weather" : "Ilm",
+ "Status" : "Olek",
+ "Good morning" : "Tere hommikust",
+ "Good morning, {name}" : "Tere hommikust, {name}",
+ "Good afternoon" : "Tere päevast",
+ "Good afternoon, {name}" : "Tere päevast, {name}",
+ "Good evening" : "Tere õhtust",
+ "Good evening, {name}" : "Tere õhtust, {name}",
+ "Hello" : "Tere",
+ "Hello, {name}" : "Tere, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Palju õnne sünnipäevaks 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Palju õnne, {name} 🥳🤩🎂🎉",
+ "Customize" : "Kohanda",
+ "Edit widgets" : "Muuda vidinaid",
+ "Get more widgets from the App Store" : "Rakenduste Poest leiad veel vidinaid",
+ "Weather service" : "Ilmateenus",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Sinu privaatsuse huvides küsib su nimel ilmaandmeid Nextcloudi server, nii et ilmateenistus ei saa isiklikku teavet.",
+ "Weather data from Met.no" : "Met.no ilmaennustus",
+ "geocoding with Nominatim" : "geoprogrammeerimine Nominatimiga",
+ "elevation data from OpenTopoData" : "kõrgusandmed OpenTopoDatast"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/et_EE.json b/apps/dashboard/l10n/et_EE.json
new file mode 100644
index 00000000000..e0e04bd32ba
--- /dev/null
+++ b/apps/dashboard/l10n/et_EE.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Töölaud/Juhtpaneel",
+ "Dashboard app" : "Töölaua/juhtpaneeli rakendus",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Alusta oma päeva teadlikult\n\nNextcloudi avaleht on su päeva alguspunkt, mis annab ülevaate eelseisvatest kohtumistest, kiireloomulistest kirjadest, vestlussõnumitest, sissetulevatest päringutest, viimastest säutsudest ja paljust muust! Inimesed saavad lisada neile meeldivaid vidinaid ja muuta tausta oma maitse järgi.",
+ "Weather" : "Ilm",
+ "Status" : "Olek",
+ "Good morning" : "Tere hommikust",
+ "Good morning, {name}" : "Tere hommikust, {name}",
+ "Good afternoon" : "Tere päevast",
+ "Good afternoon, {name}" : "Tere päevast, {name}",
+ "Good evening" : "Tere õhtust",
+ "Good evening, {name}" : "Tere õhtust, {name}",
+ "Hello" : "Tere",
+ "Hello, {name}" : "Tere, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Palju õnne sünnipäevaks 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Palju õnne, {name} 🥳🤩🎂🎉",
+ "Customize" : "Kohanda",
+ "Edit widgets" : "Muuda vidinaid",
+ "Get more widgets from the App Store" : "Rakenduste Poest leiad veel vidinaid",
+ "Weather service" : "Ilmateenus",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Sinu privaatsuse huvides küsib su nimel ilmaandmeid Nextcloudi server, nii et ilmateenistus ei saa isiklikku teavet.",
+ "Weather data from Met.no" : "Met.no ilmaennustus",
+ "geocoding with Nominatim" : "geoprogrammeerimine Nominatimiga",
+ "elevation data from OpenTopoData" : "kõrgusandmed OpenTopoDatast"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/eu.js b/apps/dashboard/l10n/eu.js
new file mode 100644
index 00000000000..b448a10cc77
--- /dev/null
+++ b/apps/dashboard/l10n/eu.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Panela",
+ "Dashboard app" : "Panela aplikazioa",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Hasi zure eguna informatuta\n\nNextcloud Panela da zure eguneko abiapuntua, eta zure hurrengo hitzorduen, premiazko mezu elektronikoen, txat-mezuen, sarrerako txartelen, azken txioen eta askoz gehiagoren ikuspegi orokorra eskaintzen dizu! Erabiltzaileek gogoko trepetak gehi ditzakete eta atzealdea nahieran aldatu.",
+ "Weather" : "Eguraldia",
+ "Status" : "Egoera",
+ "Good morning" : "Egun on",
+ "Good morning, {name}" : "Egun on, {name}",
+ "Good afternoon" : "Arratsalde on",
+ "Good afternoon, {name}" : "Arratsalde on, {name}",
+ "Good evening" : "Gabon",
+ "Good evening, {name}" : "Gabon, {name}",
+ "Hello" : "Kaixo",
+ "Hello, {name}" : "Kaixo, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Zorionak 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Zorionak, {name} 🥳🤩🎂🎉",
+ "Customize" : "Pertsonalizatu",
+ "Edit widgets" : "Editatu trepetak",
+ "Get more widgets from the App Store" : "Lortu trepeta (widget) gehiago Aplikazioen Dendatik",
+ "Weather service" : "Eguraldi zerbitzua",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Zure pribatutasunaren mesedetan, eguraldiaren datuak Nextcloud zerbitzariak eskatzen ditu zure izenean, eguraldi zerbitzuak informazio pertsonalik ez jasotzeko.",
+ "Weather data from Met.no" : "Met.no-ko eguraldiaren datuak",
+ "geocoding with Nominatim" : "geokodetzea Nominatim-ekin",
+ "elevation data from OpenTopoData" : "altitude datuak OpenTopoData-tik"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/eu.json b/apps/dashboard/l10n/eu.json
new file mode 100644
index 00000000000..7aa15665f4a
--- /dev/null
+++ b/apps/dashboard/l10n/eu.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Panela",
+ "Dashboard app" : "Panela aplikazioa",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Hasi zure eguna informatuta\n\nNextcloud Panela da zure eguneko abiapuntua, eta zure hurrengo hitzorduen, premiazko mezu elektronikoen, txat-mezuen, sarrerako txartelen, azken txioen eta askoz gehiagoren ikuspegi orokorra eskaintzen dizu! Erabiltzaileek gogoko trepetak gehi ditzakete eta atzealdea nahieran aldatu.",
+ "Weather" : "Eguraldia",
+ "Status" : "Egoera",
+ "Good morning" : "Egun on",
+ "Good morning, {name}" : "Egun on, {name}",
+ "Good afternoon" : "Arratsalde on",
+ "Good afternoon, {name}" : "Arratsalde on, {name}",
+ "Good evening" : "Gabon",
+ "Good evening, {name}" : "Gabon, {name}",
+ "Hello" : "Kaixo",
+ "Hello, {name}" : "Kaixo, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Zorionak 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Zorionak, {name} 🥳🤩🎂🎉",
+ "Customize" : "Pertsonalizatu",
+ "Edit widgets" : "Editatu trepetak",
+ "Get more widgets from the App Store" : "Lortu trepeta (widget) gehiago Aplikazioen Dendatik",
+ "Weather service" : "Eguraldi zerbitzua",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Zure pribatutasunaren mesedetan, eguraldiaren datuak Nextcloud zerbitzariak eskatzen ditu zure izenean, eguraldi zerbitzuak informazio pertsonalik ez jasotzeko.",
+ "Weather data from Met.no" : "Met.no-ko eguraldiaren datuak",
+ "geocoding with Nominatim" : "geokodetzea Nominatim-ekin",
+ "elevation data from OpenTopoData" : "altitude datuak OpenTopoData-tik"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/fa.js b/apps/dashboard/l10n/fa.js
new file mode 100644
index 00000000000..919a62e38b7
--- /dev/null
+++ b/apps/dashboard/l10n/fa.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "پیشخوان",
+ "Dashboard app" : "برنامه پیشخوان",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "روز خود را با آگاهی شروع کنید\n\nپیشخوان نکست‌کلود، نقطهٔ شروع روز شماست و به شما یک نمای کلی از قرارهای ملاقات پیش رو، ایمیل‌های فوری، پیام‌های گفتگو، گزارش‌های دریافتی، آخرین توییت‌ها و موارد دیگر را در اختیار شما قرار می‌دهد. کاربران می‌توانند ابزارک‌هایی را که دوست دارند اضافه کنند و پس زمینه را به دلخواه خود تغییر دهند.",
+ "Weather" : "آب و هوا",
+ "Status" : "وضعیت",
+ "Good morning" : "صبح به‌خیر",
+ "Good morning, {name}" : "صبح به‌خیر، {name}",
+ "Good afternoon" : "بعد از ظهر به‌خیر",
+ "Good afternoon, {name}" : "بعد از ظهر به‌خیر {name}",
+ "Good evening" : "عصر به‌خیر",
+ "Good evening, {name}" : " عصر به‌خیر {name}",
+ "Hello" : "درود",
+ "Hello, {name}" : "درود {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "تولدت مبارک 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "تولدت مبارک، {name} 🥳🤩🎂🎉",
+ "Customize" : "سفارشی‌سازی",
+ "Edit widgets" : "ویرایش ابزارک‌ها",
+ "Get more widgets from the App Store" : "گرفتن ابزارک‌های بیش‌تر از فروشگاه کاره",
+ "Weather service" : "خدمت هواشناسی",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "برای محرمانگیتان، داده‌های آب و هوا از طرف کارساز نکست‌کلودتان درخواست می‌شود تا خدمت آب و هوا هیچ اطّلاعات شخصی‌ای دریافت نکند.",
+ "Weather data from Met.no" : "اطلاعات هواشناسی از Met.no",
+ "geocoding with Nominatim" : "کدگذاری جغرافیایی با Nominatim",
+ "elevation data from OpenTopoData" : "داده‌های ارتفاع از OpenTopoData"
+},
+"nplurals=2; plural=(n > 1);");
diff --git a/apps/dashboard/l10n/fa.json b/apps/dashboard/l10n/fa.json
new file mode 100644
index 00000000000..4f199569778
--- /dev/null
+++ b/apps/dashboard/l10n/fa.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "پیشخوان",
+ "Dashboard app" : "برنامه پیشخوان",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "روز خود را با آگاهی شروع کنید\n\nپیشخوان نکست‌کلود، نقطهٔ شروع روز شماست و به شما یک نمای کلی از قرارهای ملاقات پیش رو، ایمیل‌های فوری، پیام‌های گفتگو، گزارش‌های دریافتی، آخرین توییت‌ها و موارد دیگر را در اختیار شما قرار می‌دهد. کاربران می‌توانند ابزارک‌هایی را که دوست دارند اضافه کنند و پس زمینه را به دلخواه خود تغییر دهند.",
+ "Weather" : "آب و هوا",
+ "Status" : "وضعیت",
+ "Good morning" : "صبح به‌خیر",
+ "Good morning, {name}" : "صبح به‌خیر، {name}",
+ "Good afternoon" : "بعد از ظهر به‌خیر",
+ "Good afternoon, {name}" : "بعد از ظهر به‌خیر {name}",
+ "Good evening" : "عصر به‌خیر",
+ "Good evening, {name}" : " عصر به‌خیر {name}",
+ "Hello" : "درود",
+ "Hello, {name}" : "درود {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "تولدت مبارک 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "تولدت مبارک، {name} 🥳🤩🎂🎉",
+ "Customize" : "سفارشی‌سازی",
+ "Edit widgets" : "ویرایش ابزارک‌ها",
+ "Get more widgets from the App Store" : "گرفتن ابزارک‌های بیش‌تر از فروشگاه کاره",
+ "Weather service" : "خدمت هواشناسی",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "برای محرمانگیتان، داده‌های آب و هوا از طرف کارساز نکست‌کلودتان درخواست می‌شود تا خدمت آب و هوا هیچ اطّلاعات شخصی‌ای دریافت نکند.",
+ "Weather data from Met.no" : "اطلاعات هواشناسی از Met.no",
+ "geocoding with Nominatim" : "کدگذاری جغرافیایی با Nominatim",
+ "elevation data from OpenTopoData" : "داده‌های ارتفاع از OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n > 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/fi.js b/apps/dashboard/l10n/fi.js
new file mode 100644
index 00000000000..8b85ccc5a4f
--- /dev/null
+++ b/apps/dashboard/l10n/fi.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Kojelauta",
+ "Dashboard app" : "Kojelautasovellus",
+ "Weather" : "Sää",
+ "Status" : "Tila",
+ "Good morning" : "Hyvää huomenta",
+ "Good morning, {name}" : "Hyvää huomenta, {name}",
+ "Good afternoon" : "Hyvää iltapäivää",
+ "Good afternoon, {name}" : "Hyvää iltapäivää, {name}",
+ "Good evening" : "Hyvää iltaa",
+ "Good evening, {name}" : "Hyvää iltaa, {name}",
+ "Hello" : "Hei",
+ "Hello, {name}" : "Hei {name}",
+ "Customize" : "Mukauta",
+ "Edit widgets" : "Muokkaa pienoissovelluksia",
+ "Get more widgets from the App Store" : "Hae lisää pienoissovelluksia sovelluskaupasta",
+ "Weather service" : "Sääpalvelu",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Yksityisyytesi vuoksi Nextcloud-palvelin hakee säätiedot, joten sääpalvelulle ei lähetetä henkilökohtaisia tietojasi.",
+ "Weather data from Met.no" : "Säätiedot tarjoaa Met.no",
+ "geocoding with Nominatim" : "geokoodauksen Nominatim",
+ "elevation data from OpenTopoData" : "korkeustiedot OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/fi.json b/apps/dashboard/l10n/fi.json
new file mode 100644
index 00000000000..890492e010d
--- /dev/null
+++ b/apps/dashboard/l10n/fi.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Kojelauta",
+ "Dashboard app" : "Kojelautasovellus",
+ "Weather" : "Sää",
+ "Status" : "Tila",
+ "Good morning" : "Hyvää huomenta",
+ "Good morning, {name}" : "Hyvää huomenta, {name}",
+ "Good afternoon" : "Hyvää iltapäivää",
+ "Good afternoon, {name}" : "Hyvää iltapäivää, {name}",
+ "Good evening" : "Hyvää iltaa",
+ "Good evening, {name}" : "Hyvää iltaa, {name}",
+ "Hello" : "Hei",
+ "Hello, {name}" : "Hei {name}",
+ "Customize" : "Mukauta",
+ "Edit widgets" : "Muokkaa pienoissovelluksia",
+ "Get more widgets from the App Store" : "Hae lisää pienoissovelluksia sovelluskaupasta",
+ "Weather service" : "Sääpalvelu",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Yksityisyytesi vuoksi Nextcloud-palvelin hakee säätiedot, joten sääpalvelulle ei lähetetä henkilökohtaisia tietojasi.",
+ "Weather data from Met.no" : "Säätiedot tarjoaa Met.no",
+ "geocoding with Nominatim" : "geokoodauksen Nominatim",
+ "elevation data from OpenTopoData" : "korkeustiedot OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/fr.js b/apps/dashboard/l10n/fr.js
new file mode 100644
index 00000000000..342a2d26df4
--- /dev/null
+++ b/apps/dashboard/l10n/fr.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Tableau de bord",
+ "Dashboard app" : "App Tableau de bord",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des e-mails urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les personnes peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise.",
+ "Weather" : "Météo",
+ "Status" : "Statut",
+ "Good morning" : "Bonjour",
+ "Good morning, {name}" : "Bonjour {name}",
+ "Good afternoon" : "Bon après-midi",
+ "Good afternoon, {name}" : "Bon après-midi {name}",
+ "Good evening" : "Bonsoir",
+ "Good evening, {name}" : "Bonsoir {name}",
+ "Hello" : "Bonjour",
+ "Hello, {name}" : "Bonjour {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Joyeux anniversaire ! 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Joyeux anniversaire, {name} ! 🥳🤩🎂🎉",
+ "Customize" : "Personnaliser",
+ "Edit widgets" : "Modifier les widgets",
+ "Get more widgets from the App Store" : "Obtenez plus de widgets depuis le magasin d’applications",
+ "Weather service" : "Service météo",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Afin de protéger votre vie privée, les données météorologiques sont demandées par votre serveur Nextcloud à votre place afin que le service météo ne reçoive aucune information personnelle.",
+ "Weather data from Met.no" : "Données météo fournies par Met.no",
+ "geocoding with Nominatim" : "Géocodage avec Nominatim",
+ "elevation data from OpenTopoData" : "Données d’altitude provenant d’OpenTopoData"
+},
+"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dashboard/l10n/fr.json b/apps/dashboard/l10n/fr.json
new file mode 100644
index 00000000000..8dea9005139
--- /dev/null
+++ b/apps/dashboard/l10n/fr.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Tableau de bord",
+ "Dashboard app" : "App Tableau de bord",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Commencez votre journée en étant informé\n\nLe tableau de bord Nextcloud est votre point de départ de la journée, vous donnant un aperçu de vos rendez-vous à venir, des e-mails urgents, des messages de discussion, des tickets entrants, des derniers tweets et bien plus encore ! Les personnes peuvent ajouter les widgets qu’ils souhaitent et changer l’arrière-plan à leur guise.",
+ "Weather" : "Météo",
+ "Status" : "Statut",
+ "Good morning" : "Bonjour",
+ "Good morning, {name}" : "Bonjour {name}",
+ "Good afternoon" : "Bon après-midi",
+ "Good afternoon, {name}" : "Bon après-midi {name}",
+ "Good evening" : "Bonsoir",
+ "Good evening, {name}" : "Bonsoir {name}",
+ "Hello" : "Bonjour",
+ "Hello, {name}" : "Bonjour {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Joyeux anniversaire ! 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Joyeux anniversaire, {name} ! 🥳🤩🎂🎉",
+ "Customize" : "Personnaliser",
+ "Edit widgets" : "Modifier les widgets",
+ "Get more widgets from the App Store" : "Obtenez plus de widgets depuis le magasin d’applications",
+ "Weather service" : "Service météo",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Afin de protéger votre vie privée, les données météorologiques sont demandées par votre serveur Nextcloud à votre place afin que le service météo ne reçoive aucune information personnelle.",
+ "Weather data from Met.no" : "Données météo fournies par Met.no",
+ "geocoding with Nominatim" : "Géocodage avec Nominatim",
+ "elevation data from OpenTopoData" : "Données d’altitude provenant d’OpenTopoData"
+},"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/apps/dashboard/l10n/ga.js b/apps/dashboard/l10n/ga.js
new file mode 100644
index 00000000000..822af0b13b6
--- /dev/null
+++ b/apps/dashboard/l10n/ga.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Deais",
+ "Dashboard app" : "Aip deais",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Tosaigh do lá ar an eolas\n\nIs é an Painéal Nextcloud do phointe tosaigh den lá, ag tabhairt forbhreathnú duit ar do cheapacháin atá le teacht, ríomhphoist phráinneacha, teachtaireachtaí comhrá, ticéid ag teacht isteach, tweets is déanaí agus go leor eile! Is féidir le daoine na giuirléidí is maith leo a chur leis agus an cúlra a athrú dá dtaitníonn leo.",
+ "Weather" : "Aimsir",
+ "Status" : "Stádas",
+ "Good morning" : "Maidin mhaith",
+ "Good morning, {name}" : "Maidin mhaith, {name}",
+ "Good afternoon" : "Tráthnóna maith",
+ "Good afternoon, {name}" : "Tráthnóna maith, {name}",
+ "Good evening" : "Tráthnóna maith",
+ "Good evening, {name}" : "Tráthnóna maith, {name}",
+ "Hello" : "Dia dhuit",
+ "Hello, {name}" : "Dia dhuit, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Lá breithe shona duit 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Lá breithe shona duit, {name} 🥳🤩🎂🎉",
+ "Customize" : "Saincheap",
+ "Edit widgets" : "Cuir giuirléidí in eagar",
+ "Get more widgets from the App Store" : "Faigh tuilleadh giuirléidí ón Siopa Aip",
+ "Weather service" : "Seirbhís aimsire",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Ar mhaithe le do phríobháideachas, iarrann do fhreastalaí Nextcloud na sonraí aimsire ar do shon agus mar sin ní fhaigheann an tseirbhís aimsire aon fhaisnéis phearsanta.",
+ "Weather data from Met.no" : "Sonraí aimsire ó Met.no",
+ "geocoding with Nominatim" : "geochódú le Nominatim",
+ "elevation data from OpenTopoData" : "sonraí ardaithe ó OpenTopoData"
+},
+"nplurals=5; plural=(n==1 ? 0 : n==2 ? 1 : n<7 ? 2 : n<11 ? 3 : 4);");
diff --git a/apps/dashboard/l10n/ga.json b/apps/dashboard/l10n/ga.json
new file mode 100644
index 00000000000..15a81edad3a
--- /dev/null
+++ b/apps/dashboard/l10n/ga.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Deais",
+ "Dashboard app" : "Aip deais",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Tosaigh do lá ar an eolas\n\nIs é an Painéal Nextcloud do phointe tosaigh den lá, ag tabhairt forbhreathnú duit ar do cheapacháin atá le teacht, ríomhphoist phráinneacha, teachtaireachtaí comhrá, ticéid ag teacht isteach, tweets is déanaí agus go leor eile! Is féidir le daoine na giuirléidí is maith leo a chur leis agus an cúlra a athrú dá dtaitníonn leo.",
+ "Weather" : "Aimsir",
+ "Status" : "Stádas",
+ "Good morning" : "Maidin mhaith",
+ "Good morning, {name}" : "Maidin mhaith, {name}",
+ "Good afternoon" : "Tráthnóna maith",
+ "Good afternoon, {name}" : "Tráthnóna maith, {name}",
+ "Good evening" : "Tráthnóna maith",
+ "Good evening, {name}" : "Tráthnóna maith, {name}",
+ "Hello" : "Dia dhuit",
+ "Hello, {name}" : "Dia dhuit, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Lá breithe shona duit 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Lá breithe shona duit, {name} 🥳🤩🎂🎉",
+ "Customize" : "Saincheap",
+ "Edit widgets" : "Cuir giuirléidí in eagar",
+ "Get more widgets from the App Store" : "Faigh tuilleadh giuirléidí ón Siopa Aip",
+ "Weather service" : "Seirbhís aimsire",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Ar mhaithe le do phríobháideachas, iarrann do fhreastalaí Nextcloud na sonraí aimsire ar do shon agus mar sin ní fhaigheann an tseirbhís aimsire aon fhaisnéis phearsanta.",
+ "Weather data from Met.no" : "Sonraí aimsire ó Met.no",
+ "geocoding with Nominatim" : "geochódú le Nominatim",
+ "elevation data from OpenTopoData" : "sonraí ardaithe ó OpenTopoData"
+},"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/apps/dashboard/l10n/gl.js b/apps/dashboard/l10n/gl.js
new file mode 100644
index 00000000000..7fadf650ba6
--- /dev/null
+++ b/apps/dashboard/l10n/gl.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Taboleiro",
+ "Dashboard app" : "Aplicación de taboleiro",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comece o día informado\n\nO Taboleiro de Nextcloud é o seu punto de partida do día, onde atopará unha vista xeral das súas próximas citas, correos-e urxentes, mensaxes de parolas, billetes entrantes, chíos máis recentes e moito máis. A xente pode engadir os trebellos que lles gusten e cambiar o fondo ao seu antollo.",
+ "Weather" : "Meteoroloxía",
+ "Status" : "Estado",
+ "Good morning" : "Bos días",
+ "Good morning, {name}" : "Bos días, {name}",
+ "Good afternoon" : "Boas tardes",
+ "Good afternoon, {name}" : "Boas tardes, {name}",
+ "Good evening" : "Boas noites",
+ "Good evening, {name}" : "Boas noites, {name}",
+ "Hello" : "Hello",
+ "Hello, {name}" : "Ola, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Feliz aniversario 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Feliz aniversario, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar trebellos",
+ "Get more widgets from the App Store" : "Obter máis trebellos na tenda de aplicacións",
+ "Weather service" : "Servizo meteorolóxico",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Para a súa privacidade, o servidor de Nextcloud solicita os datos meteorolóxicos no seu nome para que o servizo meteorolóxico non reciba información persoal.",
+ "Weather data from Met.no" : "Datos meteorolóxicos de Met.no",
+ "geocoding with Nominatim" : "xeocodificación con Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/gl.json b/apps/dashboard/l10n/gl.json
new file mode 100644
index 00000000000..16691d49cf4
--- /dev/null
+++ b/apps/dashboard/l10n/gl.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Taboleiro",
+ "Dashboard app" : "Aplicación de taboleiro",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comece o día informado\n\nO Taboleiro de Nextcloud é o seu punto de partida do día, onde atopará unha vista xeral das súas próximas citas, correos-e urxentes, mensaxes de parolas, billetes entrantes, chíos máis recentes e moito máis. A xente pode engadir os trebellos que lles gusten e cambiar o fondo ao seu antollo.",
+ "Weather" : "Meteoroloxía",
+ "Status" : "Estado",
+ "Good morning" : "Bos días",
+ "Good morning, {name}" : "Bos días, {name}",
+ "Good afternoon" : "Boas tardes",
+ "Good afternoon, {name}" : "Boas tardes, {name}",
+ "Good evening" : "Boas noites",
+ "Good evening, {name}" : "Boas noites, {name}",
+ "Hello" : "Hello",
+ "Hello, {name}" : "Ola, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Feliz aniversario 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Feliz aniversario, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar trebellos",
+ "Get more widgets from the App Store" : "Obter máis trebellos na tenda de aplicacións",
+ "Weather service" : "Servizo meteorolóxico",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Para a súa privacidade, o servidor de Nextcloud solicita os datos meteorolóxicos no seu nome para que o servizo meteorolóxico non reciba información persoal.",
+ "Weather data from Met.no" : "Datos meteorolóxicos de Met.no",
+ "geocoding with Nominatim" : "xeocodificación con Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevación de OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/he.js b/apps/dashboard/l10n/he.js
new file mode 100644
index 00000000000..397f1663dcb
--- /dev/null
+++ b/apps/dashboard/l10n/he.js
@@ -0,0 +1,24 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "לוח בקרה",
+ "Dashboard app" : "אפליקציית לוח המחוונים",
+ "Weather" : "מזג אוויר",
+ "Status" : "מצב",
+ "Good morning" : "בוקר טוב",
+ "Good morning, {name}" : "בוקר טוב, {name}",
+ "Good afternoon" : "צהריים טובים",
+ "Good afternoon, {name}" : "צהריים טובים, {name}",
+ "Good evening" : "ערב טוב",
+ "Good evening, {name}" : "ערב טוב, {name}",
+ "Hello" : "שלום",
+ "Hello, {name}" : "שלום, {name}",
+ "Customize" : "התאמה אישית",
+ "Edit widgets" : "ערוך יישומונים",
+ "Weather service" : "שירות מזג אוויר",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "למען פרטיותך, נתוני מזג האוויר מתבקשים על ידי שרת Nextcloud עבורך, כך ששירות מזג האוויר אינו מקבל מידע אישי.",
+ "Weather data from Met.no" : "נתוני מזג אוויר מ- Met.no",
+ "geocoding with Nominatim" : "קידוד גיאוגרפי עם Nominatim",
+ "elevation data from OpenTopoData" : "נתוני גובה מ- OpenTopoData"
+},
+"nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;");
diff --git a/apps/dashboard/l10n/he.json b/apps/dashboard/l10n/he.json
new file mode 100644
index 00000000000..809102e7f40
--- /dev/null
+++ b/apps/dashboard/l10n/he.json
@@ -0,0 +1,22 @@
+{ "translations": {
+ "Dashboard" : "לוח בקרה",
+ "Dashboard app" : "אפליקציית לוח המחוונים",
+ "Weather" : "מזג אוויר",
+ "Status" : "מצב",
+ "Good morning" : "בוקר טוב",
+ "Good morning, {name}" : "בוקר טוב, {name}",
+ "Good afternoon" : "צהריים טובים",
+ "Good afternoon, {name}" : "צהריים טובים, {name}",
+ "Good evening" : "ערב טוב",
+ "Good evening, {name}" : "ערב טוב, {name}",
+ "Hello" : "שלום",
+ "Hello, {name}" : "שלום, {name}",
+ "Customize" : "התאמה אישית",
+ "Edit widgets" : "ערוך יישומונים",
+ "Weather service" : "שירות מזג אוויר",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "למען פרטיותך, נתוני מזג האוויר מתבקשים על ידי שרת Nextcloud עבורך, כך ששירות מזג האוויר אינו מקבל מידע אישי.",
+ "Weather data from Met.no" : "נתוני מזג אוויר מ- Met.no",
+ "geocoding with Nominatim" : "קידוד גיאוגרפי עם Nominatim",
+ "elevation data from OpenTopoData" : "נתוני גובה מ- OpenTopoData"
+},"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/apps/dashboard/l10n/hr.js b/apps/dashboard/l10n/hr.js
new file mode 100644
index 00000000000..55fdd74185e
--- /dev/null
+++ b/apps/dashboard/l10n/hr.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Nadzorna ploča",
+ "Dashboard app" : "Nadzorna ploča aplikacije",
+ "Weather" : "Vrijeme",
+ "Status" : "Status",
+ "Good morning" : "Dobro jutro",
+ "Good morning, {name}" : "Dobro jutro, {name}",
+ "Good afternoon" : "Dobar dan",
+ "Good afternoon, {name}" : "Dobar dan, {name}",
+ "Good evening" : "Dobar dan",
+ "Good evening, {name}" : "Dobar dan, {name}",
+ "Hello" : "Pozdrav",
+ "Hello, {name}" : "Pozdrav, {name}",
+ "Customize" : "Uredi",
+ "Edit widgets" : "Uredi widgete",
+ "Get more widgets from the App Store" : "Nabavite više widgeta iz trgovine aplikacijama",
+ "Weather service" : "Davatelj vremenske prognoze",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Radi zaštite vaše privatnosti, podatke o vremenskoj prognozi zahtijeva vaš Nextcloud poslužitelj u vaše ime kako davatelj vremenske prognoze ne bi primio vaše osobne podatke.",
+ "Weather data from Met.no" : "Podaci o vremenskoj prognozi iz Met.no",
+ "geocoding with Nominatim" : "geokodiranje uz Nominatim",
+ "elevation data from OpenTopoData" : "podaci o nadmorskoj visini iz OpenTopoData"
+},
+"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/apps/dashboard/l10n/hr.json b/apps/dashboard/l10n/hr.json
new file mode 100644
index 00000000000..69a474cf6fd
--- /dev/null
+++ b/apps/dashboard/l10n/hr.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Nadzorna ploča",
+ "Dashboard app" : "Nadzorna ploča aplikacije",
+ "Weather" : "Vrijeme",
+ "Status" : "Status",
+ "Good morning" : "Dobro jutro",
+ "Good morning, {name}" : "Dobro jutro, {name}",
+ "Good afternoon" : "Dobar dan",
+ "Good afternoon, {name}" : "Dobar dan, {name}",
+ "Good evening" : "Dobar dan",
+ "Good evening, {name}" : "Dobar dan, {name}",
+ "Hello" : "Pozdrav",
+ "Hello, {name}" : "Pozdrav, {name}",
+ "Customize" : "Uredi",
+ "Edit widgets" : "Uredi widgete",
+ "Get more widgets from the App Store" : "Nabavite više widgeta iz trgovine aplikacijama",
+ "Weather service" : "Davatelj vremenske prognoze",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Radi zaštite vaše privatnosti, podatke o vremenskoj prognozi zahtijeva vaš Nextcloud poslužitelj u vaše ime kako davatelj vremenske prognoze ne bi primio vaše osobne podatke.",
+ "Weather data from Met.no" : "Podaci o vremenskoj prognozi iz Met.no",
+ "geocoding with Nominatim" : "geokodiranje uz Nominatim",
+ "elevation data from OpenTopoData" : "podaci o nadmorskoj visini iz OpenTopoData"
+},"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/apps/dashboard/l10n/hu.js b/apps/dashboard/l10n/hu.js
new file mode 100644
index 00000000000..1d0666068f2
--- /dev/null
+++ b/apps/dashboard/l10n/hu.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Irányítópult",
+ "Dashboard app" : "Irányítópult alkalmazás",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Kezdje informáltan a napot\n\nA Nextcloud irányítópult a napja kezdőpontja, áttekintést nyújtva a közelgő találkozókról, sürgős levelekről, csevegőüzenetekről, hibajegyekről, a legfrissebb tweetekről és sok másról. Modulokat lehet hozzáadni, és tetszés szerint lehet hátteret választani.",
+ "Weather" : "Időjárás",
+ "Status" : "Állapot",
+ "Good morning" : "Jó reggelt",
+ "Good morning, {name}" : "Jó reggelt, {name}",
+ "Good afternoon" : "Jó napot",
+ "Good afternoon, {name}" : "Jó napot, {name}",
+ "Good evening" : "Jó estét",
+ "Good evening, {name}" : "Jó estét, {name}",
+ "Hello" : "Üdv",
+ "Hello, {name}" : "Üdv {name}!",
+ "Happy birthday 🥳🤩🎂🎉" : "Boldog születésnapot 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Boldog születésnapot, {name} 🥳🤩🎂🎉",
+ "Customize" : "Testreszabás",
+ "Edit widgets" : "Modulok szerkesztése",
+ "Get more widgets from the App Store" : "További modulok letöltése az alkalmazástárból.",
+ "Weather service" : "Időjárás szolgáltatás",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Az adatvédelem érdekében az információt a Nextcloud kiszolgáló kéri le az Ön nevében, így az Ön személyes adatai nem kerülnek az időjárási adatok szolgáltatójához.",
+ "Weather data from Met.no" : "Időjárási adatok a Met.no-tól",
+ "geocoding with Nominatim" : "geokódolás a Nominatimmal",
+ "elevation data from OpenTopoData" : "magassági adatok az OpenTopoDatától"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/hu.json b/apps/dashboard/l10n/hu.json
new file mode 100644
index 00000000000..97fa9de655c
--- /dev/null
+++ b/apps/dashboard/l10n/hu.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Irányítópult",
+ "Dashboard app" : "Irányítópult alkalmazás",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Kezdje informáltan a napot\n\nA Nextcloud irányítópult a napja kezdőpontja, áttekintést nyújtva a közelgő találkozókról, sürgős levelekről, csevegőüzenetekről, hibajegyekről, a legfrissebb tweetekről és sok másról. Modulokat lehet hozzáadni, és tetszés szerint lehet hátteret választani.",
+ "Weather" : "Időjárás",
+ "Status" : "Állapot",
+ "Good morning" : "Jó reggelt",
+ "Good morning, {name}" : "Jó reggelt, {name}",
+ "Good afternoon" : "Jó napot",
+ "Good afternoon, {name}" : "Jó napot, {name}",
+ "Good evening" : "Jó estét",
+ "Good evening, {name}" : "Jó estét, {name}",
+ "Hello" : "Üdv",
+ "Hello, {name}" : "Üdv {name}!",
+ "Happy birthday 🥳🤩🎂🎉" : "Boldog születésnapot 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Boldog születésnapot, {name} 🥳🤩🎂🎉",
+ "Customize" : "Testreszabás",
+ "Edit widgets" : "Modulok szerkesztése",
+ "Get more widgets from the App Store" : "További modulok letöltése az alkalmazástárból.",
+ "Weather service" : "Időjárás szolgáltatás",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Az adatvédelem érdekében az információt a Nextcloud kiszolgáló kéri le az Ön nevében, így az Ön személyes adatai nem kerülnek az időjárási adatok szolgáltatójához.",
+ "Weather data from Met.no" : "Időjárási adatok a Met.no-tól",
+ "geocoding with Nominatim" : "geokódolás a Nominatimmal",
+ "elevation data from OpenTopoData" : "magassági adatok az OpenTopoDatától"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/id.js b/apps/dashboard/l10n/id.js
new file mode 100644
index 00000000000..c9a18a05b31
--- /dev/null
+++ b/apps/dashboard/l10n/id.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Dasbor",
+ "Dashboard app" : "Aplikasi dasbor",
+ "Weather" : "Cuaca",
+ "Status" : "Status",
+ "Good morning" : "Selamat pagi",
+ "Good morning, {name}" : "Selamat pagi, {name}",
+ "Good afternoon" : "Selamat siang",
+ "Good afternoon, {name}" : "Selamat siang, {name}",
+ "Good evening" : "Selamat malam",
+ "Good evening, {name}" : "Selamat malam, {name}",
+ "Hello" : "Halo",
+ "Hello, {name}" : "Halo, {name}",
+ "Customize" : "Sesuaikan",
+ "Edit widgets" : "Edit widget",
+ "Get more widgets from the App Store" : "Dapatkan lebih banyak widget dari App Store",
+ "Weather service" : "Layanan cuaca",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Untuk privasi Anda, data cuaca diminta oleh server Nextcloud Anda atas nama Anda sehingga layanan cuaca tidak menerima informasi pribadi.",
+ "Weather data from Met.no" : "Data cuaca dari Met.no",
+ "geocoding with Nominatim" : "Secara khusus, dengan geocoding",
+ "elevation data from OpenTopoData" : "data ketinggian dari OpenTopoData"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/id.json b/apps/dashboard/l10n/id.json
new file mode 100644
index 00000000000..1b572f9f299
--- /dev/null
+++ b/apps/dashboard/l10n/id.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Dasbor",
+ "Dashboard app" : "Aplikasi dasbor",
+ "Weather" : "Cuaca",
+ "Status" : "Status",
+ "Good morning" : "Selamat pagi",
+ "Good morning, {name}" : "Selamat pagi, {name}",
+ "Good afternoon" : "Selamat siang",
+ "Good afternoon, {name}" : "Selamat siang, {name}",
+ "Good evening" : "Selamat malam",
+ "Good evening, {name}" : "Selamat malam, {name}",
+ "Hello" : "Halo",
+ "Hello, {name}" : "Halo, {name}",
+ "Customize" : "Sesuaikan",
+ "Edit widgets" : "Edit widget",
+ "Get more widgets from the App Store" : "Dapatkan lebih banyak widget dari App Store",
+ "Weather service" : "Layanan cuaca",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Untuk privasi Anda, data cuaca diminta oleh server Nextcloud Anda atas nama Anda sehingga layanan cuaca tidak menerima informasi pribadi.",
+ "Weather data from Met.no" : "Data cuaca dari Met.no",
+ "geocoding with Nominatim" : "Secara khusus, dengan geocoding",
+ "elevation data from OpenTopoData" : "data ketinggian dari OpenTopoData"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/is.js b/apps/dashboard/l10n/is.js
new file mode 100644
index 00000000000..dd76d9f206b
--- /dev/null
+++ b/apps/dashboard/l10n/is.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Stjórnborð",
+ "Dashboard app" : "Stjórnborðsforrit",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Byrjaðu daginn vel upplýst/ur\n\nNextcloud-stjórnborðið er útgangspunkturinn á deginum, sem gefur þér yfirlit um væntanleg stefnumót, áríðandi tölvupósta, spjallskilaboð, innlagðar verkbeiðnir, nýjustu tíst og margt fleira! Fólk getur bætt við þeim viðmótshlutum sem þeim sýnist og skipt um bakgrunn eftir sínum smekk.",
+ "Weather" : "Veður",
+ "Status" : "Staða",
+ "Good morning" : "Góðan morgunn",
+ "Good morning, {name}" : "Góðan morgunn, {name}",
+ "Good afternoon" : "Góðan dag",
+ "Good afternoon, {name}" : "Góðan daginn, {name}",
+ "Good evening" : "Gott kvöld",
+ "Good evening, {name}" : "Góða kvöldið, {name}",
+ "Hello" : "Halló",
+ "Hello, {name}" : "Halló, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Til hamingju með afmælið 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Til hamingju með afmælið {name} 🥳🤩🎂🎉",
+ "Customize" : "Sérsníða",
+ "Edit widgets" : "Breyta viðmótshlutum",
+ "Get more widgets from the App Store" : "Náðu í fleiri viðmótshluta í forritasafninu",
+ "Weather service" : "Veðurþjónusta",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Til að vernda friðhelgi þína, eru veðurgögn sótt af Nextcloud-þjóninum fyrir þína hönd, þannig að veðurþjónustan fær engin persónuleg gögn.",
+ "Weather data from Met.no" : "Veðurgögn frá Met.no",
+ "geocoding with Nominatim" : "staðsetningarkóðun með Nominatim",
+ "elevation data from OpenTopoData" : "hæðargögn frá OpenTopoData"
+},
+"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);");
diff --git a/apps/dashboard/l10n/is.json b/apps/dashboard/l10n/is.json
new file mode 100644
index 00000000000..3ff21287fd0
--- /dev/null
+++ b/apps/dashboard/l10n/is.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Stjórnborð",
+ "Dashboard app" : "Stjórnborðsforrit",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Byrjaðu daginn vel upplýst/ur\n\nNextcloud-stjórnborðið er útgangspunkturinn á deginum, sem gefur þér yfirlit um væntanleg stefnumót, áríðandi tölvupósta, spjallskilaboð, innlagðar verkbeiðnir, nýjustu tíst og margt fleira! Fólk getur bætt við þeim viðmótshlutum sem þeim sýnist og skipt um bakgrunn eftir sínum smekk.",
+ "Weather" : "Veður",
+ "Status" : "Staða",
+ "Good morning" : "Góðan morgunn",
+ "Good morning, {name}" : "Góðan morgunn, {name}",
+ "Good afternoon" : "Góðan dag",
+ "Good afternoon, {name}" : "Góðan daginn, {name}",
+ "Good evening" : "Gott kvöld",
+ "Good evening, {name}" : "Góða kvöldið, {name}",
+ "Hello" : "Halló",
+ "Hello, {name}" : "Halló, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Til hamingju með afmælið 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Til hamingju með afmælið {name} 🥳🤩🎂🎉",
+ "Customize" : "Sérsníða",
+ "Edit widgets" : "Breyta viðmótshlutum",
+ "Get more widgets from the App Store" : "Náðu í fleiri viðmótshluta í forritasafninu",
+ "Weather service" : "Veðurþjónusta",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Til að vernda friðhelgi þína, eru veðurgögn sótt af Nextcloud-þjóninum fyrir þína hönd, þannig að veðurþjónustan fær engin persónuleg gögn.",
+ "Weather data from Met.no" : "Veðurgögn frá Met.no",
+ "geocoding with Nominatim" : "staðsetningarkóðun með Nominatim",
+ "elevation data from OpenTopoData" : "hæðargögn frá OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/it.js b/apps/dashboard/l10n/it.js
new file mode 100644
index 00000000000..99e14e72265
--- /dev/null
+++ b/apps/dashboard/l10n/it.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Cruscotto",
+ "Dashboard app" : "Cruscotto",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Inizia la giornata informato\n\nIl cruscotto di Nextcloud è il tuo punto di partenza della giornata, in grado di offrire una panoramica dei prossimi appuntamenti, email urgenti, messaggi di chat, nuove richieste, ultimi tweet e molto altro ancora! Gli utenti possono aggiungere i widget che preferiscono e modificare lo sfondo a proprio piacimento.",
+ "Weather" : "Meteo",
+ "Status" : "Stato",
+ "Good morning" : "Buongiorno",
+ "Good morning, {name}" : "Buongiorno, {name}",
+ "Good afternoon" : "Buon pomeriggio",
+ "Good afternoon, {name}" : "Buon pomeriggio, {name}",
+ "Good evening" : "Buona sera",
+ "Good evening, {name}" : "Buona sera, {name}",
+ "Hello" : "Ciao",
+ "Hello, {name}" : "Ciao {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Buon compleanno 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Buon compleanno, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizza",
+ "Edit widgets" : "Modifica widget",
+ "Get more widgets from the App Store" : "Ottieni altri widget dal negozio delle applicazioni",
+ "Weather service" : "Servizio meteo",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Per la tua riservatezza, i dati meteorologici sono richiesti dal tuo server Nextcloud per tuo conto, per cui il servizio meteo non riceve informazioni personali.",
+ "Weather data from Met.no" : "Dati meteo da Met.no",
+ "geocoding with Nominatim" : "geocodifica conh Nominatim",
+ "elevation data from OpenTopoData" : "dati di elevazione da OpenTopoData"
+},
+"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dashboard/l10n/it.json b/apps/dashboard/l10n/it.json
new file mode 100644
index 00000000000..bd8d7040eb5
--- /dev/null
+++ b/apps/dashboard/l10n/it.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Cruscotto",
+ "Dashboard app" : "Cruscotto",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Inizia la giornata informato\n\nIl cruscotto di Nextcloud è il tuo punto di partenza della giornata, in grado di offrire una panoramica dei prossimi appuntamenti, email urgenti, messaggi di chat, nuove richieste, ultimi tweet e molto altro ancora! Gli utenti possono aggiungere i widget che preferiscono e modificare lo sfondo a proprio piacimento.",
+ "Weather" : "Meteo",
+ "Status" : "Stato",
+ "Good morning" : "Buongiorno",
+ "Good morning, {name}" : "Buongiorno, {name}",
+ "Good afternoon" : "Buon pomeriggio",
+ "Good afternoon, {name}" : "Buon pomeriggio, {name}",
+ "Good evening" : "Buona sera",
+ "Good evening, {name}" : "Buona sera, {name}",
+ "Hello" : "Ciao",
+ "Hello, {name}" : "Ciao {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Buon compleanno 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Buon compleanno, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizza",
+ "Edit widgets" : "Modifica widget",
+ "Get more widgets from the App Store" : "Ottieni altri widget dal negozio delle applicazioni",
+ "Weather service" : "Servizio meteo",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Per la tua riservatezza, i dati meteorologici sono richiesti dal tuo server Nextcloud per tuo conto, per cui il servizio meteo non riceve informazioni personali.",
+ "Weather data from Met.no" : "Dati meteo da Met.no",
+ "geocoding with Nominatim" : "geocodifica conh Nominatim",
+ "elevation data from OpenTopoData" : "dati di elevazione da OpenTopoData"
+},"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/ja.js b/apps/dashboard/l10n/ja.js
new file mode 100644
index 00000000000..68bd7d2c15c
--- /dev/null
+++ b/apps/dashboard/l10n/ja.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "ダッシュボード",
+ "Dashboard app" : "ダッシュボードアプリ",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "一日の始まりに情報を提供\n\nNextcloudダッシュボードは、一日のスタート地点であり、今後の予定、緊急のEメール、チャットメッセージ、受信チケット、最新のツイートなどの概要を提供します!好きなウィジェットを追加したり、背景を自分好みに変更することができます。",
+ "Weather" : "天気",
+ "Status" : "ステータス",
+ "Good morning" : "おはようございます",
+ "Good morning, {name}" : "おはようございます、{name} さん",
+ "Good afternoon" : "こんにちは",
+ "Good afternoon, {name}" : "こんにちは、{name} さん",
+ "Good evening" : "こんばんは",
+ "Good evening, {name}" : "こんばんは、{name} さん",
+ "Hello" : "こんにちは",
+ "Hello, {name}" : "こんにちは、{name} さん",
+ "Happy birthday 🥳🤩🎂🎉" : "お誕生日おめでとう 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "お誕生日おめでとう、{name} 🥳🤩🎂🎉",
+ "Customize" : "カスタマイズ",
+ "Edit widgets" : "ウィジェットを編集",
+ "Get more widgets from the App Store" : "アプリストアから他のガジェットを入手",
+ "Weather service" : "ウェザーサービス",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "あなたのプライバシーを保護するため、あなたに変わって Nextcloud サーバーが気象データをウェザーサービスに要求します。そのため、ウェザーサービスはあなたの個人情報を受け取ることはありません。",
+ "Weather data from Met.no" : "気象データ提供元は Met.no",
+ "geocoding with Nominatim" : "Nominatim でジオコーディング",
+ "elevation data from OpenTopoData" : "標高データ提供元は OpenTopoData です"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/ja.json b/apps/dashboard/l10n/ja.json
new file mode 100644
index 00000000000..a62e26cdddd
--- /dev/null
+++ b/apps/dashboard/l10n/ja.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "ダッシュボード",
+ "Dashboard app" : "ダッシュボードアプリ",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "一日の始まりに情報を提供\n\nNextcloudダッシュボードは、一日のスタート地点であり、今後の予定、緊急のEメール、チャットメッセージ、受信チケット、最新のツイートなどの概要を提供します!好きなウィジェットを追加したり、背景を自分好みに変更することができます。",
+ "Weather" : "天気",
+ "Status" : "ステータス",
+ "Good morning" : "おはようございます",
+ "Good morning, {name}" : "おはようございます、{name} さん",
+ "Good afternoon" : "こんにちは",
+ "Good afternoon, {name}" : "こんにちは、{name} さん",
+ "Good evening" : "こんばんは",
+ "Good evening, {name}" : "こんばんは、{name} さん",
+ "Hello" : "こんにちは",
+ "Hello, {name}" : "こんにちは、{name} さん",
+ "Happy birthday 🥳🤩🎂🎉" : "お誕生日おめでとう 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "お誕生日おめでとう、{name} 🥳🤩🎂🎉",
+ "Customize" : "カスタマイズ",
+ "Edit widgets" : "ウィジェットを編集",
+ "Get more widgets from the App Store" : "アプリストアから他のガジェットを入手",
+ "Weather service" : "ウェザーサービス",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "あなたのプライバシーを保護するため、あなたに変わって Nextcloud サーバーが気象データをウェザーサービスに要求します。そのため、ウェザーサービスはあなたの個人情報を受け取ることはありません。",
+ "Weather data from Met.no" : "気象データ提供元は Met.no",
+ "geocoding with Nominatim" : "Nominatim でジオコーディング",
+ "elevation data from OpenTopoData" : "標高データ提供元は OpenTopoData です"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/ka_GE.js b/apps/dashboard/l10n/ka_GE.js
new file mode 100644
index 00000000000..2b84c4dc4b4
--- /dev/null
+++ b/apps/dashboard/l10n/ka_GE.js
@@ -0,0 +1,22 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "მთავარი დაფა",
+ "Dashboard app" : "დეშბორდის აპი",
+ "Weather" : "ამინდი",
+ "Status" : "სტატუსი",
+ "Good morning" : "დილამშვიდობისა",
+ "Good morning, {name}" : "დილამშვიდობისა, {name}",
+ "Good afternoon" : "საღამომშვიდობისა",
+ "Good afternoon, {name}" : "საღამომშვიდობისა, {name}",
+ "Good evening" : "ღამემშვიდობისა",
+ "Good evening, {name}" : "ღამემშვიდობისა, {name}",
+ "Hello" : "გამარჯობა",
+ "Hello, {name}" : "გამარჯობა, {name}",
+ "Customize" : "პერსონალიზაცია",
+ "Edit widgets" : "ვიჯეტების დაედითება",
+ "Weather service" : "ამინდის სერვისი",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "თქვენი კონფენდენციალურობისთვის, ამინდზე ინფორმაცია მოთხოვნილია ჩვენი Nextcloud-ის სერვერის მიერ, ამჟამად ამინდის სერვისები თქვენს პირად ინფორმაციას არ მიიღებენ.",
+ "Weather data from Met.no" : "ამინდის პროგნოზი Met.no-დან"
+},
+"nplurals=2; plural=(n!=1);");
diff --git a/apps/dashboard/l10n/ka_GE.json b/apps/dashboard/l10n/ka_GE.json
new file mode 100644
index 00000000000..510fb9f0d22
--- /dev/null
+++ b/apps/dashboard/l10n/ka_GE.json
@@ -0,0 +1,20 @@
+{ "translations": {
+ "Dashboard" : "მთავარი დაფა",
+ "Dashboard app" : "დეშბორდის აპი",
+ "Weather" : "ამინდი",
+ "Status" : "სტატუსი",
+ "Good morning" : "დილამშვიდობისა",
+ "Good morning, {name}" : "დილამშვიდობისა, {name}",
+ "Good afternoon" : "საღამომშვიდობისა",
+ "Good afternoon, {name}" : "საღამომშვიდობისა, {name}",
+ "Good evening" : "ღამემშვიდობისა",
+ "Good evening, {name}" : "ღამემშვიდობისა, {name}",
+ "Hello" : "გამარჯობა",
+ "Hello, {name}" : "გამარჯობა, {name}",
+ "Customize" : "პერსონალიზაცია",
+ "Edit widgets" : "ვიჯეტების დაედითება",
+ "Weather service" : "ამინდის სერვისი",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "თქვენი კონფენდენციალურობისთვის, ამინდზე ინფორმაცია მოთხოვნილია ჩვენი Nextcloud-ის სერვერის მიერ, ამჟამად ამინდის სერვისები თქვენს პირად ინფორმაციას არ მიიღებენ.",
+ "Weather data from Met.no" : "ამინდის პროგნოზი Met.no-დან"
+},"pluralForm" :"nplurals=2; plural=(n!=1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/ko.js b/apps/dashboard/l10n/ko.js
new file mode 100644
index 00000000000..76e4ddfe2e6
--- /dev/null
+++ b/apps/dashboard/l10n/ko.js
@@ -0,0 +1,24 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "대시보드",
+ "Dashboard app" : "대시보드 앱",
+ "Weather" : "날씨",
+ "Status" : "상태",
+ "Good morning" : "좋은 아침입니다.",
+ "Good morning, {name}" : "{name}님, 좋은 아침입니다.",
+ "Good afternoon" : "안녕하세요.",
+ "Good afternoon, {name}" : "안녕하세요, {name}님.",
+ "Good evening" : "안녕하세요.",
+ "Good evening, {name}" : "안녕하세요, {name}님.",
+ "Hello" : "안녕하세요.",
+ "Hello, {name}" : "안녕하세요, {name}님.",
+ "Customize" : "사용자 지정",
+ "Edit widgets" : "위젯 편집",
+ "Weather service" : "날씨 서비스",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "개인정보 보호를 위해 사용자를 대신해 Nextcloud 서버에서 요청하므로 개인정보를 수신하지 않습니다.",
+ "Weather data from Met.no" : "Met.no의 날씨 데이터",
+ "geocoding with Nominatim" : "Nominatim으로 지오 코딩",
+ "elevation data from OpenTopoData" : "OpenTopoData의 고도 데이터"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/ko.json b/apps/dashboard/l10n/ko.json
new file mode 100644
index 00000000000..47e93dbc6c1
--- /dev/null
+++ b/apps/dashboard/l10n/ko.json
@@ -0,0 +1,22 @@
+{ "translations": {
+ "Dashboard" : "대시보드",
+ "Dashboard app" : "대시보드 앱",
+ "Weather" : "날씨",
+ "Status" : "상태",
+ "Good morning" : "좋은 아침입니다.",
+ "Good morning, {name}" : "{name}님, 좋은 아침입니다.",
+ "Good afternoon" : "안녕하세요.",
+ "Good afternoon, {name}" : "안녕하세요, {name}님.",
+ "Good evening" : "안녕하세요.",
+ "Good evening, {name}" : "안녕하세요, {name}님.",
+ "Hello" : "안녕하세요.",
+ "Hello, {name}" : "안녕하세요, {name}님.",
+ "Customize" : "사용자 지정",
+ "Edit widgets" : "위젯 편집",
+ "Weather service" : "날씨 서비스",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "개인정보 보호를 위해 사용자를 대신해 Nextcloud 서버에서 요청하므로 개인정보를 수신하지 않습니다.",
+ "Weather data from Met.no" : "Met.no의 날씨 데이터",
+ "geocoding with Nominatim" : "Nominatim으로 지오 코딩",
+ "elevation data from OpenTopoData" : "OpenTopoData의 고도 데이터"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/lt_LT.js b/apps/dashboard/l10n/lt_LT.js
new file mode 100644
index 00000000000..7552e456c5d
--- /dev/null
+++ b/apps/dashboard/l10n/lt_LT.js
@@ -0,0 +1,27 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Skydelis",
+ "Dashboard app" : "Skydelio programėlė",
+ "Weather" : "Orai",
+ "Status" : "Būsena",
+ "Good morning" : "Labas rytas",
+ "Good morning, {name}" : "Labas rytas, {name}",
+ "Good afternoon" : "Laba diena",
+ "Good afternoon, {name}" : "Laba diena, {name}",
+ "Good evening" : "Labas vakaras",
+ "Good evening, {name}" : "Labas vakaras, {name}",
+ "Hello" : "Sveiki",
+ "Hello, {name}" : "Sveiki, {name},",
+ "Happy birthday 🥳🤩🎂🎉" : "Su gimtadieniu 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Su gimtadieniu, {name} 🥳🤩🎂🎉",
+ "Customize" : "Tinkinti",
+ "Edit widgets" : "Taisyti valdiklius",
+ "Get more widgets from the App Store" : "Parsisiųsti įskiepių iš App Store",
+ "Weather service" : "Orų tarnyba",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Dėl jūsų privatumo, orų duomenys yra jūsų vardu užklausiami jūsų Nextcloud serverio, todėl orų tarnyba negauna jokios asmeninės informacijos.",
+ "Weather data from Met.no" : "Orų duomenys iš Met.no",
+ "geocoding with Nominatim" : "geografinis kodavimas naudojant Nominatim",
+ "elevation data from OpenTopoData" : "aukščio duomenys iš OpenTopoData"
+},
+"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/apps/dashboard/l10n/lt_LT.json b/apps/dashboard/l10n/lt_LT.json
new file mode 100644
index 00000000000..535d6f28253
--- /dev/null
+++ b/apps/dashboard/l10n/lt_LT.json
@@ -0,0 +1,25 @@
+{ "translations": {
+ "Dashboard" : "Skydelis",
+ "Dashboard app" : "Skydelio programėlė",
+ "Weather" : "Orai",
+ "Status" : "Būsena",
+ "Good morning" : "Labas rytas",
+ "Good morning, {name}" : "Labas rytas, {name}",
+ "Good afternoon" : "Laba diena",
+ "Good afternoon, {name}" : "Laba diena, {name}",
+ "Good evening" : "Labas vakaras",
+ "Good evening, {name}" : "Labas vakaras, {name}",
+ "Hello" : "Sveiki",
+ "Hello, {name}" : "Sveiki, {name},",
+ "Happy birthday 🥳🤩🎂🎉" : "Su gimtadieniu 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Su gimtadieniu, {name} 🥳🤩🎂🎉",
+ "Customize" : "Tinkinti",
+ "Edit widgets" : "Taisyti valdiklius",
+ "Get more widgets from the App Store" : "Parsisiųsti įskiepių iš App Store",
+ "Weather service" : "Orų tarnyba",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Dėl jūsų privatumo, orų duomenys yra jūsų vardu užklausiami jūsų Nextcloud serverio, todėl orų tarnyba negauna jokios asmeninės informacijos.",
+ "Weather data from Met.no" : "Orų duomenys iš Met.no",
+ "geocoding with Nominatim" : "geografinis kodavimas naudojant Nominatim",
+ "elevation data from OpenTopoData" : "aukščio duomenys iš OpenTopoData"
+},"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/apps/dashboard/l10n/mk.js b/apps/dashboard/l10n/mk.js
new file mode 100644
index 00000000000..576e9a45c02
--- /dev/null
+++ b/apps/dashboard/l10n/mk.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Табла",
+ "Dashboard app" : "Табла",
+ "Weather" : "Временска прогноза",
+ "Status" : "Статус",
+ "Good morning" : "Добро утро",
+ "Good morning, {name}" : "Добро утро, {name}",
+ "Good afternoon" : "Добар ден",
+ "Good afternoon, {name}" : "Добар ден, {name}",
+ "Good evening" : "Добровечер",
+ "Good evening, {name}" : "Добровечер, {name}",
+ "Hello" : "Здраво",
+ "Hello, {name}" : "Здраво, {name}",
+ "Customize" : "Прилагоди",
+ "Edit widgets" : "Уреди графички контроли",
+ "Get more widgets from the App Store" : "Преземи повеќе графички контроли од продавницата со апликации",
+ "Weather service" : "Сервис за временска прогноза",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "За ваша приватност, податоците за времето ги бара вашиот сервер во ваше име, така што метеоролошката служба не добива лични информации.",
+ "Weather data from Met.no" : "Податоци за временето од Met.no",
+ "geocoding with Nominatim" : "Геокодирање со Nominatim",
+ "elevation data from OpenTopoData" : "Податоци за височина од OpenTopoData"
+},
+"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;");
diff --git a/apps/dashboard/l10n/mk.json b/apps/dashboard/l10n/mk.json
new file mode 100644
index 00000000000..c3c5e0e1f68
--- /dev/null
+++ b/apps/dashboard/l10n/mk.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Табла",
+ "Dashboard app" : "Табла",
+ "Weather" : "Временска прогноза",
+ "Status" : "Статус",
+ "Good morning" : "Добро утро",
+ "Good morning, {name}" : "Добро утро, {name}",
+ "Good afternoon" : "Добар ден",
+ "Good afternoon, {name}" : "Добар ден, {name}",
+ "Good evening" : "Добровечер",
+ "Good evening, {name}" : "Добровечер, {name}",
+ "Hello" : "Здраво",
+ "Hello, {name}" : "Здраво, {name}",
+ "Customize" : "Прилагоди",
+ "Edit widgets" : "Уреди графички контроли",
+ "Get more widgets from the App Store" : "Преземи повеќе графички контроли од продавницата со апликации",
+ "Weather service" : "Сервис за временска прогноза",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "За ваша приватност, податоците за времето ги бара вашиот сервер во ваше име, така што метеоролошката служба не добива лични информации.",
+ "Weather data from Met.no" : "Податоци за временето од Met.no",
+ "geocoding with Nominatim" : "Геокодирање со Nominatim",
+ "elevation data from OpenTopoData" : "Податоци за височина од OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/nb.js b/apps/dashboard/l10n/nb.js
new file mode 100644
index 00000000000..4bcb04b188d
--- /dev/null
+++ b/apps/dashboard/l10n/nb.js
@@ -0,0 +1,26 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Instrumentpanel",
+ "Dashboard app" : "Instrumentpanel app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Start dagen din informert\n\nNextcloud-kontrollpanel er ditt utgangspunkt for dagen, og gir deg en oversikt over dine kommende avtaler, presserende e-poster, chatmeldinger, innkommende billetter, siste tvitringer og mye mer! Brukere kan legge til widgetene de liker og endre bakgrunnen etter eget ønske.",
+ "Weather" : "Vær",
+ "Status" : "Status",
+ "Good morning" : "God morgen",
+ "Good morning, {name}" : "God morgen, {name}",
+ "Good afternoon" : "God ettermiddag",
+ "Good afternoon, {name}" : "Good ettermiddag, {name}",
+ "Good evening" : "God kveld",
+ "Good evening, {name}" : "God kveld, {name}",
+ "Hello" : "Hallo",
+ "Hello, {name}" : "Hallo, {name}",
+ "Customize" : "Tilpass",
+ "Edit widgets" : "Rediger widgets",
+ "Get more widgets from the App Store" : "Få flere widgets fra app-butikken",
+ "Weather service" : "Værmelding",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Av hensyn til personvernet ditt blir værdataene bedt om av Nextcloud-serveren din på dine vegne, slik at værtjenesten ikke mottar personlig informasjon.",
+ "Weather data from Met.no" : "Værmelding fra Met.no",
+ "geocoding with Nominatim" : "geokoding med Nominatim",
+ "elevation data from OpenTopoData" : "høydedata fra OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/nb.json b/apps/dashboard/l10n/nb.json
new file mode 100644
index 00000000000..9f1ad8bc524
--- /dev/null
+++ b/apps/dashboard/l10n/nb.json
@@ -0,0 +1,24 @@
+{ "translations": {
+ "Dashboard" : "Instrumentpanel",
+ "Dashboard app" : "Instrumentpanel app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Start dagen din informert\n\nNextcloud-kontrollpanel er ditt utgangspunkt for dagen, og gir deg en oversikt over dine kommende avtaler, presserende e-poster, chatmeldinger, innkommende billetter, siste tvitringer og mye mer! Brukere kan legge til widgetene de liker og endre bakgrunnen etter eget ønske.",
+ "Weather" : "Vær",
+ "Status" : "Status",
+ "Good morning" : "God morgen",
+ "Good morning, {name}" : "God morgen, {name}",
+ "Good afternoon" : "God ettermiddag",
+ "Good afternoon, {name}" : "Good ettermiddag, {name}",
+ "Good evening" : "God kveld",
+ "Good evening, {name}" : "God kveld, {name}",
+ "Hello" : "Hallo",
+ "Hello, {name}" : "Hallo, {name}",
+ "Customize" : "Tilpass",
+ "Edit widgets" : "Rediger widgets",
+ "Get more widgets from the App Store" : "Få flere widgets fra app-butikken",
+ "Weather service" : "Værmelding",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Av hensyn til personvernet ditt blir værdataene bedt om av Nextcloud-serveren din på dine vegne, slik at værtjenesten ikke mottar personlig informasjon.",
+ "Weather data from Met.no" : "Værmelding fra Met.no",
+ "geocoding with Nominatim" : "geokoding med Nominatim",
+ "elevation data from OpenTopoData" : "høydedata fra OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/nl.js b/apps/dashboard/l10n/nl.js
new file mode 100644
index 00000000000..7fc3bdc2177
--- /dev/null
+++ b/apps/dashboard/l10n/nl.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard-app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Begin je dag geïnformeerd\n\nHet Nextcloud Dashboard is je startpunt van de dag en biedt je een overzicht van je aankomende afspraken, dringende e-mails, chatberichten, binnenkomende tickets, laatste tweets en nog veel meer! Mensen kunnen de widgets toevoegen die ze leuk vinden en de achtergrond naar wens aanpassen.",
+ "Weather" : "Weer",
+ "Status" : "Status",
+ "Good morning" : "Goedemorgen",
+ "Good morning, {name}" : "Goedemorgen, {name}",
+ "Good afternoon" : "Goedemiddag",
+ "Good afternoon, {name}" : "Goedemiddag, {name}",
+ "Good evening" : "Goedenavond",
+ "Good evening, {name}" : "Goedenavond, {name}",
+ "Hello" : "Hallo",
+ "Hello, {name}" : "Hallo, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Fijne verjaardag 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Fijne verjaardag, {name} 🥳🤩🎂🎉",
+ "Customize" : "Aanpassen",
+ "Edit widgets" : "Widgets bewerken",
+ "Get more widgets from the App Store" : "Haal meer widgets op uit de App Store",
+ "Weather service" : "Weerberichten",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Voor je privacy worden de weergegevens namens jou opgevraagd door je Nextcloud-server, zodat de weerservice geen persoonlijke informatie ontvangt.",
+ "Weather data from Met.no" : "Weerbericht via Met.no",
+ "geocoding with Nominatim" : "geocoding met Nominatim",
+ "elevation data from OpenTopoData" : "hoogtedata via OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/nl.json b/apps/dashboard/l10n/nl.json
new file mode 100644
index 00000000000..5b56e7b0cb9
--- /dev/null
+++ b/apps/dashboard/l10n/nl.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard-app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Begin je dag geïnformeerd\n\nHet Nextcloud Dashboard is je startpunt van de dag en biedt je een overzicht van je aankomende afspraken, dringende e-mails, chatberichten, binnenkomende tickets, laatste tweets en nog veel meer! Mensen kunnen de widgets toevoegen die ze leuk vinden en de achtergrond naar wens aanpassen.",
+ "Weather" : "Weer",
+ "Status" : "Status",
+ "Good morning" : "Goedemorgen",
+ "Good morning, {name}" : "Goedemorgen, {name}",
+ "Good afternoon" : "Goedemiddag",
+ "Good afternoon, {name}" : "Goedemiddag, {name}",
+ "Good evening" : "Goedenavond",
+ "Good evening, {name}" : "Goedenavond, {name}",
+ "Hello" : "Hallo",
+ "Hello, {name}" : "Hallo, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Fijne verjaardag 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Fijne verjaardag, {name} 🥳🤩🎂🎉",
+ "Customize" : "Aanpassen",
+ "Edit widgets" : "Widgets bewerken",
+ "Get more widgets from the App Store" : "Haal meer widgets op uit de App Store",
+ "Weather service" : "Weerberichten",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Voor je privacy worden de weergegevens namens jou opgevraagd door je Nextcloud-server, zodat de weerservice geen persoonlijke informatie ontvangt.",
+ "Weather data from Met.no" : "Weerbericht via Met.no",
+ "geocoding with Nominatim" : "geocoding met Nominatim",
+ "elevation data from OpenTopoData" : "hoogtedata via OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/oc.js b/apps/dashboard/l10n/oc.js
new file mode 100644
index 00000000000..4f737af8207
--- /dev/null
+++ b/apps/dashboard/l10n/oc.js
@@ -0,0 +1,24 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Tablèu de bòrd",
+ "Dashboard app" : "Aplicacion de tablèu de bòrd",
+ "Weather" : "Metèo",
+ "Status" : "Estat",
+ "Good morning" : "Bonjorn",
+ "Good morning, {name}" : "Bonjorn, {name}",
+ "Good afternoon" : "Bonjorn",
+ "Good afternoon, {name}" : "Bonjorn, {name}",
+ "Good evening" : "Bonser",
+ "Good evening, {name}" : "Bonser, {name}",
+ "Hello" : "Adieu",
+ "Hello, {name}" : "Adieu, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Obténer mai de widgets sus l’App Store",
+ "Weather service" : "Servici de metèo",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Per vòstre confidencialitat, las donadas de metèo son demandadas per vòstre servidor Nextcloud per vos per que lo servici de metèo aja pas cap de vòstras donadas personalas.",
+ "Weather data from Met.no" : "Donadas meteorologica de Met.no",
+ "geocoding with Nominatim" : "geocoding amb Nominatim"
+},
+"nplurals=2; plural=(n > 1);");
diff --git a/apps/dashboard/l10n/oc.json b/apps/dashboard/l10n/oc.json
new file mode 100644
index 00000000000..de9efa7a559
--- /dev/null
+++ b/apps/dashboard/l10n/oc.json
@@ -0,0 +1,22 @@
+{ "translations": {
+ "Dashboard" : "Tablèu de bòrd",
+ "Dashboard app" : "Aplicacion de tablèu de bòrd",
+ "Weather" : "Metèo",
+ "Status" : "Estat",
+ "Good morning" : "Bonjorn",
+ "Good morning, {name}" : "Bonjorn, {name}",
+ "Good afternoon" : "Bonjorn",
+ "Good afternoon, {name}" : "Bonjorn, {name}",
+ "Good evening" : "Bonser",
+ "Good evening, {name}" : "Bonser, {name}",
+ "Hello" : "Adieu",
+ "Hello, {name}" : "Adieu, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Obténer mai de widgets sus l’App Store",
+ "Weather service" : "Servici de metèo",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Per vòstre confidencialitat, las donadas de metèo son demandadas per vòstre servidor Nextcloud per vos per que lo servici de metèo aja pas cap de vòstras donadas personalas.",
+ "Weather data from Met.no" : "Donadas meteorologica de Met.no",
+ "geocoding with Nominatim" : "geocoding amb Nominatim"
+},"pluralForm" :"nplurals=2; plural=(n > 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/pl.js b/apps/dashboard/l10n/pl.js
new file mode 100644
index 00000000000..e82dafdff97
--- /dev/null
+++ b/apps/dashboard/l10n/pl.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Pulpit",
+ "Dashboard app" : "Aplikacja Pulpit",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Rozpocznij dzień świadomie\n\nPulpit nawigacyjny Nextcloud to punkt wyjścia dnia, zapewniający przegląd nadchodzących spotkań, pilnych e-maili, wiadomości na czacie, przychodzących zgłoszeń, najnowszych tweetów i wiele więcej! Ludzie mogą dodawać widżety, które im się podobają i zmieniać tło według własnych upodobań.",
+ "Weather" : "Pogoda",
+ "Status" : "Status",
+ "Good morning" : "Dzień dobry",
+ "Good morning, {name}" : "Dzień dobry, {name}",
+ "Good afternoon" : "Dzień dobry",
+ "Good afternoon, {name}" : "Dzień dobry, {name}",
+ "Good evening" : "Dobry wieczór",
+ "Good evening, {name}" : "Dobry wieczór, {name}",
+ "Hello" : "Witaj",
+ "Hello, {name}" : "Witaj {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Najlepsze życzenia urodzinowe 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Najlepsze życzenia urodzinowe, {name} 🥳🤩🎂🎉",
+ "Customize" : "Dostosuj",
+ "Edit widgets" : "Edytuj widżety",
+ "Get more widgets from the App Store" : "Pobierz więcej widżetów z Nextcloud App Store",
+ "Weather service" : "Serwis pogodowy",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Ze względu na Twoją prywatność dane pogodowe są pobierane przez serwer Nextcloud w Twoim imieniu. Usługa pogodowa nie otrzymuje żadnych danych osobowych.",
+ "Weather data from Met.no" : "Dane pogodowe z Met.no",
+ "geocoding with Nominatim" : "geokodowanie z Nominatim",
+ "elevation data from OpenTopoData" : "dane wysokościowe z OpenTopoData"
+},
+"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/apps/dashboard/l10n/pl.json b/apps/dashboard/l10n/pl.json
new file mode 100644
index 00000000000..5659df99fc7
--- /dev/null
+++ b/apps/dashboard/l10n/pl.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Pulpit",
+ "Dashboard app" : "Aplikacja Pulpit",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Rozpocznij dzień świadomie\n\nPulpit nawigacyjny Nextcloud to punkt wyjścia dnia, zapewniający przegląd nadchodzących spotkań, pilnych e-maili, wiadomości na czacie, przychodzących zgłoszeń, najnowszych tweetów i wiele więcej! Ludzie mogą dodawać widżety, które im się podobają i zmieniać tło według własnych upodobań.",
+ "Weather" : "Pogoda",
+ "Status" : "Status",
+ "Good morning" : "Dzień dobry",
+ "Good morning, {name}" : "Dzień dobry, {name}",
+ "Good afternoon" : "Dzień dobry",
+ "Good afternoon, {name}" : "Dzień dobry, {name}",
+ "Good evening" : "Dobry wieczór",
+ "Good evening, {name}" : "Dobry wieczór, {name}",
+ "Hello" : "Witaj",
+ "Hello, {name}" : "Witaj {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Najlepsze życzenia urodzinowe 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Najlepsze życzenia urodzinowe, {name} 🥳🤩🎂🎉",
+ "Customize" : "Dostosuj",
+ "Edit widgets" : "Edytuj widżety",
+ "Get more widgets from the App Store" : "Pobierz więcej widżetów z Nextcloud App Store",
+ "Weather service" : "Serwis pogodowy",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Ze względu na Twoją prywatność dane pogodowe są pobierane przez serwer Nextcloud w Twoim imieniu. Usługa pogodowa nie otrzymuje żadnych danych osobowych.",
+ "Weather data from Met.no" : "Dane pogodowe z Met.no",
+ "geocoding with Nominatim" : "geokodowanie z Nominatim",
+ "elevation data from OpenTopoData" : "dane wysokościowe z OpenTopoData"
+},"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/apps/dashboard/l10n/pt_BR.js b/apps/dashboard/l10n/pt_BR.js
new file mode 100644
index 00000000000..ebdafb1859f
--- /dev/null
+++ b/apps/dashboard/l10n/pt_BR.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Painel",
+ "Dashboard app" : "Aplicativo Painel",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comece o dia informado \n\nO Painel do Nextcloud (Nextcloud Dashboard) é o seu ponto de partida do dia, oferecendo uma visão geral de seus próximos compromissos, e-mails urgentes, mensagens de bate-papo, tickets recebidos, tweets mais recentes e muito mais! As pessoas podem adicionar os widgets que desejarem e alterar o plano de fundo de acordo com sua preferência.",
+ "Weather" : "Clima",
+ "Status" : "Status",
+ "Good morning" : "Bom dia",
+ "Good morning, {name}" : "Bom dia, {name}",
+ "Good afternoon" : "Boa tarde",
+ "Good afternoon, {name}" : "Boa tarde, {name}",
+ "Good evening" : "Boa noite",
+ "Good evening, {name}" : "Boa noite, {name}",
+ "Hello" : "Olá",
+ "Hello, {name}" : "Olá, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Feliz Aniversário 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Feliz Aniversário, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Obtenha mais widgets na Loja de Aplicativos",
+ "Weather service" : "Serviço de Clima",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Para sua privacidade, as informações de Tempo são solicitadas pelo servidor Nextcloud de forma que o serviço de Tempo não receba suas informações pessoais.",
+ "Weather data from Met.no" : "Dados de Tempo do Met.no",
+ "geocoding with Nominatim" : "geocodificado com Nominatim",
+ "elevation data from OpenTopoData" : "dados topográficos de OpenTopoData"
+},
+"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dashboard/l10n/pt_BR.json b/apps/dashboard/l10n/pt_BR.json
new file mode 100644
index 00000000000..d0f5b67d72f
--- /dev/null
+++ b/apps/dashboard/l10n/pt_BR.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Painel",
+ "Dashboard app" : "Aplicativo Painel",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Comece o dia informado \n\nO Painel do Nextcloud (Nextcloud Dashboard) é o seu ponto de partida do dia, oferecendo uma visão geral de seus próximos compromissos, e-mails urgentes, mensagens de bate-papo, tickets recebidos, tweets mais recentes e muito mais! As pessoas podem adicionar os widgets que desejarem e alterar o plano de fundo de acordo com sua preferência.",
+ "Weather" : "Clima",
+ "Status" : "Status",
+ "Good morning" : "Bom dia",
+ "Good morning, {name}" : "Bom dia, {name}",
+ "Good afternoon" : "Boa tarde",
+ "Good afternoon, {name}" : "Boa tarde, {name}",
+ "Good evening" : "Boa noite",
+ "Good evening, {name}" : "Boa noite, {name}",
+ "Hello" : "Olá",
+ "Hello, {name}" : "Olá, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Feliz Aniversário 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Feliz Aniversário, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar widgets",
+ "Get more widgets from the App Store" : "Obtenha mais widgets na Loja de Aplicativos",
+ "Weather service" : "Serviço de Clima",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Para sua privacidade, as informações de Tempo são solicitadas pelo servidor Nextcloud de forma que o serviço de Tempo não receba suas informações pessoais.",
+ "Weather data from Met.no" : "Dados de Tempo do Met.no",
+ "geocoding with Nominatim" : "geocodificado com Nominatim",
+ "elevation data from OpenTopoData" : "dados topográficos de OpenTopoData"
+},"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/apps/dashboard/l10n/pt_PT.js b/apps/dashboard/l10n/pt_PT.js
new file mode 100644
index 00000000000..9e79da2d959
--- /dev/null
+++ b/apps/dashboard/l10n/pt_PT.js
@@ -0,0 +1,24 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Painel de controlo",
+ "Dashboard app" : "Aplicação Painel de Controlo ",
+ "Weather" : "Tempo",
+ "Status" : "Estado",
+ "Good morning" : "Bom dia",
+ "Good morning, {name}" : "Bom dia, {name}",
+ "Good afternoon" : "Boa tarde",
+ "Good afternoon, {name}" : "Boa tarde, {name}",
+ "Good evening" : "Boa noite",
+ "Good evening, {name}" : "Boa noite, {name}",
+ "Hello" : "Olá",
+ "Hello, {name}" : "Olá, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar aplicação",
+ "Weather service" : "Metereologia",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Para sua privacidade, os dados de metereologia são requisitados pelo seu servidor Nextcloud em seu nome para que, desta forma, o serviço de metereologia não receba quaisquer dados pessoais.",
+ "Weather data from Met.no" : "Dados Metereológicos de Met.no",
+ "geocoding with Nominatim" : "geocodificação com Nominatim",
+ "elevation data from OpenTopoData" : "dados de elevação de OpenTopoData"
+},
+"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
diff --git a/apps/dashboard/l10n/pt_PT.json b/apps/dashboard/l10n/pt_PT.json
new file mode 100644
index 00000000000..04fa5681eff
--- /dev/null
+++ b/apps/dashboard/l10n/pt_PT.json
@@ -0,0 +1,22 @@
+{ "translations": {
+ "Dashboard" : "Painel de controlo",
+ "Dashboard app" : "Aplicação Painel de Controlo ",
+ "Weather" : "Tempo",
+ "Status" : "Estado",
+ "Good morning" : "Bom dia",
+ "Good morning, {name}" : "Bom dia, {name}",
+ "Good afternoon" : "Boa tarde",
+ "Good afternoon, {name}" : "Boa tarde, {name}",
+ "Good evening" : "Boa noite",
+ "Good evening, {name}" : "Boa noite, {name}",
+ "Hello" : "Olá",
+ "Hello, {name}" : "Olá, {name}",
+ "Customize" : "Personalizar",
+ "Edit widgets" : "Editar aplicação",
+ "Weather service" : "Metereologia",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Para sua privacidade, os dados de metereologia são requisitados pelo seu servidor Nextcloud em seu nome para que, desta forma, o serviço de metereologia não receba quaisquer dados pessoais.",
+ "Weather data from Met.no" : "Dados Metereológicos de Met.no",
+ "geocoding with Nominatim" : "geocodificação com Nominatim",
+ "elevation data from OpenTopoData" : "dados de elevação de OpenTopoData"
+},"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/apps/dashboard/l10n/ro.js b/apps/dashboard/l10n/ro.js
new file mode 100644
index 00000000000..994add35f36
--- /dev/null
+++ b/apps/dashboard/l10n/ro.js
@@ -0,0 +1,27 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Panou",
+ "Dashboard app" : "Panou de bord aplicație",
+ "Weather" : "Vreme",
+ "Status" : "Stare",
+ "Good morning" : "Bună dimineața",
+ "Good morning, {name}" : "Bună dimineața, {name}",
+ "Good afternoon" : "Bună ziua",
+ "Good afternoon, {name}" : "Bună ziua, {name}",
+ "Good evening" : "Bună seara",
+ "Good evening, {name}" : "Bună seara, {name}",
+ "Hello" : "Bună",
+ "Hello, {name}" : "Bună, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "La mulți ani 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "La mulți ani, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizează",
+ "Edit widgets" : "Editează widget",
+ "Get more widgets from the App Store" : "Obține mai multe widget-uri din App Store",
+ "Weather service" : "Serviciu de vreme",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Pentru securitatea ta, datele despre vreme sunt cerute de către serverul Nextcloud din partea ta pentru ca serviciul de vreme să nu primească date confidențiale.",
+ "Weather data from Met.no" : "Date despre vreme de la Met.no",
+ "geocoding with Nominatim" : "geocoding cu Nominatim",
+ "elevation data from OpenTopoData" : "date despre elevație de la OpenTopoData"
+},
+"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));");
diff --git a/apps/dashboard/l10n/ro.json b/apps/dashboard/l10n/ro.json
new file mode 100644
index 00000000000..02048973360
--- /dev/null
+++ b/apps/dashboard/l10n/ro.json
@@ -0,0 +1,25 @@
+{ "translations": {
+ "Dashboard" : "Panou",
+ "Dashboard app" : "Panou de bord aplicație",
+ "Weather" : "Vreme",
+ "Status" : "Stare",
+ "Good morning" : "Bună dimineața",
+ "Good morning, {name}" : "Bună dimineața, {name}",
+ "Good afternoon" : "Bună ziua",
+ "Good afternoon, {name}" : "Bună ziua, {name}",
+ "Good evening" : "Bună seara",
+ "Good evening, {name}" : "Bună seara, {name}",
+ "Hello" : "Bună",
+ "Hello, {name}" : "Bună, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "La mulți ani 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "La mulți ani, {name} 🥳🤩🎂🎉",
+ "Customize" : "Personalizează",
+ "Edit widgets" : "Editează widget",
+ "Get more widgets from the App Store" : "Obține mai multe widget-uri din App Store",
+ "Weather service" : "Serviciu de vreme",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Pentru securitatea ta, datele despre vreme sunt cerute de către serverul Nextcloud din partea ta pentru ca serviciul de vreme să nu primească date confidențiale.",
+ "Weather data from Met.no" : "Date despre vreme de la Met.no",
+ "geocoding with Nominatim" : "geocoding cu Nominatim",
+ "elevation data from OpenTopoData" : "date despre elevație de la OpenTopoData"
+},"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/apps/dashboard/l10n/ru.js b/apps/dashboard/l10n/ru.js
new file mode 100644
index 00000000000..0185325a1df
--- /dev/null
+++ b/apps/dashboard/l10n/ru.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Виджеты",
+ "Dashboard app" : "Приложение Виджеты",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Начните свой день информированным\n\nПанель инструментов Nextcloud — это ваша отправная точка дня, дающая вам обзор предстоящих встреч, срочных писем, сообщений чата, входящих тикетов, последних твитов и многого другого! Люди могут добавлять виджеты, которые им нравятся, и менять фон по своему вкусу.",
+ "Weather" : "Прогноз погоды",
+ "Status" : "Состояние",
+ "Good morning" : "Доброе утро",
+ "Good morning, {name}" : "Доброе утро, {name}",
+ "Good afternoon" : "Добрый день",
+ "Good afternoon, {name}" : "Добрый день, {name}",
+ "Good evening" : "Добрый вечер",
+ "Good evening, {name}" : "Добрый вечер, {name}",
+ "Hello" : "Здравствуйте",
+ "Hello, {name}" : "Здравствуйте, {name}!",
+ "Happy birthday 🥳🤩🎂🎉" : "С днём рождения! 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "С днём рождения, {name}! 🥳🤩🎂🎉",
+ "Customize" : "Настроить",
+ "Edit widgets" : "Редактировать виджеты",
+ "Get more widgets from the App Store" : "Загрузить виджеты из магазина приложений",
+ "Weather service" : "Погода",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "В целях вашей конфиденциальности данные о погоде запрашиваются вашим сервером Nextcloud от вашего имени, поэтому служба погоды не получает никакой личной информации.",
+ "Weather data from Met.no" : "Погода от Met.no",
+ "geocoding with Nominatim" : "геокодирование с Nominatim",
+ "elevation data from OpenTopoData" : "данные о высоте из OpenTopoData"
+},
+"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/apps/dashboard/l10n/ru.json b/apps/dashboard/l10n/ru.json
new file mode 100644
index 00000000000..34f140d3171
--- /dev/null
+++ b/apps/dashboard/l10n/ru.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Виджеты",
+ "Dashboard app" : "Приложение Виджеты",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Начните свой день информированным\n\nПанель инструментов Nextcloud — это ваша отправная точка дня, дающая вам обзор предстоящих встреч, срочных писем, сообщений чата, входящих тикетов, последних твитов и многого другого! Люди могут добавлять виджеты, которые им нравятся, и менять фон по своему вкусу.",
+ "Weather" : "Прогноз погоды",
+ "Status" : "Состояние",
+ "Good morning" : "Доброе утро",
+ "Good morning, {name}" : "Доброе утро, {name}",
+ "Good afternoon" : "Добрый день",
+ "Good afternoon, {name}" : "Добрый день, {name}",
+ "Good evening" : "Добрый вечер",
+ "Good evening, {name}" : "Добрый вечер, {name}",
+ "Hello" : "Здравствуйте",
+ "Hello, {name}" : "Здравствуйте, {name}!",
+ "Happy birthday 🥳🤩🎂🎉" : "С днём рождения! 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "С днём рождения, {name}! 🥳🤩🎂🎉",
+ "Customize" : "Настроить",
+ "Edit widgets" : "Редактировать виджеты",
+ "Get more widgets from the App Store" : "Загрузить виджеты из магазина приложений",
+ "Weather service" : "Погода",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "В целях вашей конфиденциальности данные о погоде запрашиваются вашим сервером Nextcloud от вашего имени, поэтому служба погоды не получает никакой личной информации.",
+ "Weather data from Met.no" : "Погода от Met.no",
+ "geocoding with Nominatim" : "геокодирование с Nominatim",
+ "elevation data from OpenTopoData" : "данные о высоте из OpenTopoData"
+},"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/apps/dashboard/l10n/sc.js b/apps/dashboard/l10n/sc.js
new file mode 100644
index 00000000000..05d4d523bcd
--- /dev/null
+++ b/apps/dashboard/l10n/sc.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Pannellu de controllu",
+ "Dashboard app" : "Aplicatzione de su pannellu de controllu",
+ "Weather" : "Tempus",
+ "Status" : "Istadu",
+ "Good morning" : "Bona die",
+ "Good morning, {name}" : "Bona die, {name}",
+ "Good afternoon" : "Salude",
+ "Good afternoon, {name}" : "Salude, {name}",
+ "Good evening" : "Salude",
+ "Good evening, {name}" : "Salude, {name}",
+ "Hello" : "Salude",
+ "Hello, {name}" : "Salude, {name}",
+ "Customize" : "Personaliza",
+ "Edit widgets" : "Modìfica ordìngios",
+ "Get more widgets from the App Store" : "Otene àteros trastos dae sa butega de is aplicatziones",
+ "Weather service" : "Servìtziu de su tempus",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Pro sa riservadesa tua, su serbidore Nextcloud rechedet is datos de su tempus pro tene, duncas su servìtziu de su tempus no retzit informatziones personales.",
+ "Weather data from Met.no" : "Datos de su tempus dae Met.no",
+ "geocoding with Nominatim" : "geocodìfica cun Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevada dae OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/sc.json b/apps/dashboard/l10n/sc.json
new file mode 100644
index 00000000000..f36e660234a
--- /dev/null
+++ b/apps/dashboard/l10n/sc.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Pannellu de controllu",
+ "Dashboard app" : "Aplicatzione de su pannellu de controllu",
+ "Weather" : "Tempus",
+ "Status" : "Istadu",
+ "Good morning" : "Bona die",
+ "Good morning, {name}" : "Bona die, {name}",
+ "Good afternoon" : "Salude",
+ "Good afternoon, {name}" : "Salude, {name}",
+ "Good evening" : "Salude",
+ "Good evening, {name}" : "Salude, {name}",
+ "Hello" : "Salude",
+ "Hello, {name}" : "Salude, {name}",
+ "Customize" : "Personaliza",
+ "Edit widgets" : "Modìfica ordìngios",
+ "Get more widgets from the App Store" : "Otene àteros trastos dae sa butega de is aplicatziones",
+ "Weather service" : "Servìtziu de su tempus",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Pro sa riservadesa tua, su serbidore Nextcloud rechedet is datos de su tempus pro tene, duncas su servìtziu de su tempus no retzit informatziones personales.",
+ "Weather data from Met.no" : "Datos de su tempus dae Met.no",
+ "geocoding with Nominatim" : "geocodìfica cun Nominatim",
+ "elevation data from OpenTopoData" : "datos de elevada dae OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/sk.js b/apps/dashboard/l10n/sk.js
new file mode 100644
index 00000000000..2716325c7e8
--- /dev/null
+++ b/apps/dashboard/l10n/sk.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Infopanel",
+ "Dashboard app" : "Aplikácia Infopanel",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Začnite svoj deň informovaní\n\nNextcloud Infopanel je vaším východiskovým bodom dňa, ktorý vám poskytne prehľad o vašich nadchádzajúcich stretnutiach, naliehavých e-mailoch, správach, prijatých lístkoch, najnovších tweetoch a mnohom ďalšom! Ľudia si môžu pridať rozšírenia, ktoré sa im páčia, a zmeniť si pozadie podľa svojich predstáv.",
+ "Weather" : "Počasie",
+ "Status" : "Stav",
+ "Good morning" : "Dobré ráno",
+ "Good morning, {name}" : "Dobré ráno, {name}",
+ "Good afternoon" : "Dobrý deň",
+ "Good afternoon, {name}" : "Dobrý deň, {name}",
+ "Good evening" : "Dobrý večer",
+ "Good evening, {name}" : "Dobrý večer, {name}",
+ "Hello" : "Ahoj",
+ "Hello, {name}" : "Ahoj, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Všetko najlepšie k narodeninám 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Všetko najlepšie k narodeninám, {name} 🥳🤩🎂🎉",
+ "Customize" : "Prispôsobiť",
+ "Edit widgets" : "Upraviť miniaplikácie",
+ "Get more widgets from the App Store" : "Získať viac miniaplikácií v Obchode s aplikáciami",
+ "Weather service" : "Služba počasie",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "V záujme vášho súkromia údaje o počasí vyžaduje váš server Nextcloud vo vašom mene, aby meteorologická služba nedostávala žiadne osobné informácie.",
+ "Weather data from Met.no" : "Dáta počasia z Met.no",
+ "geocoding with Nominatim" : "geokódovanie pomocou Nominatim",
+ "elevation data from OpenTopoData" : "dáta o nadmorskej výške z OpenTopoData"
+},
+"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/apps/dashboard/l10n/sk.json b/apps/dashboard/l10n/sk.json
new file mode 100644
index 00000000000..c74b055cb5d
--- /dev/null
+++ b/apps/dashboard/l10n/sk.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Infopanel",
+ "Dashboard app" : "Aplikácia Infopanel",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Začnite svoj deň informovaní\n\nNextcloud Infopanel je vaším východiskovým bodom dňa, ktorý vám poskytne prehľad o vašich nadchádzajúcich stretnutiach, naliehavých e-mailoch, správach, prijatých lístkoch, najnovších tweetoch a mnohom ďalšom! Ľudia si môžu pridať rozšírenia, ktoré sa im páčia, a zmeniť si pozadie podľa svojich predstáv.",
+ "Weather" : "Počasie",
+ "Status" : "Stav",
+ "Good morning" : "Dobré ráno",
+ "Good morning, {name}" : "Dobré ráno, {name}",
+ "Good afternoon" : "Dobrý deň",
+ "Good afternoon, {name}" : "Dobrý deň, {name}",
+ "Good evening" : "Dobrý večer",
+ "Good evening, {name}" : "Dobrý večer, {name}",
+ "Hello" : "Ahoj",
+ "Hello, {name}" : "Ahoj, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Všetko najlepšie k narodeninám 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Všetko najlepšie k narodeninám, {name} 🥳🤩🎂🎉",
+ "Customize" : "Prispôsobiť",
+ "Edit widgets" : "Upraviť miniaplikácie",
+ "Get more widgets from the App Store" : "Získať viac miniaplikácií v Obchode s aplikáciami",
+ "Weather service" : "Služba počasie",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "V záujme vášho súkromia údaje o počasí vyžaduje váš server Nextcloud vo vašom mene, aby meteorologická služba nedostávala žiadne osobné informácie.",
+ "Weather data from Met.no" : "Dáta počasia z Met.no",
+ "geocoding with Nominatim" : "geokódovanie pomocou Nominatim",
+ "elevation data from OpenTopoData" : "dáta o nadmorskej výške z OpenTopoData"
+},"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/apps/dashboard/l10n/sl.js b/apps/dashboard/l10n/sl.js
new file mode 100644
index 00000000000..9ee87af3e6e
--- /dev/null
+++ b/apps/dashboard/l10n/sl.js
@@ -0,0 +1,26 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Nadzorna plošča",
+ "Dashboard app" : "Program Nadzorna plošča",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Začnite dan s pravimi informacijami\n\nNadzorna plošča Nextcloud je prva točka dneva, ki vam omogoča\npregled prihajajočih sestankov, nujnih elektronskih sporočil in sporočil klepeta, podrobnosti o prejetih nalogah, najnovejših sporočilih z družbenih omrežij in še veliko več! Vsak uporabnik lahko doda gradnike in spreminja ozadje po svojih željah.",
+ "Weather" : "Vreme",
+ "Status" : "Stanje",
+ "Good morning" : "Dobro jutro",
+ "Good morning, {name}" : "Dobro jutro, {name}",
+ "Good afternoon" : "Dober dan",
+ "Good afternoon, {name}" : "Dober dan, {name}",
+ "Good evening" : "Dober večer",
+ "Good evening, {name}" : "Dober večer, {name}",
+ "Hello" : "Pozdravljeni",
+ "Hello, {name}" : "Pozdravljeni, {name}",
+ "Customize" : "Prilagodi",
+ "Edit widgets" : "Izbor gradnikov",
+ "Get more widgets from the App Store" : "Pridobi več gradnikov s spletišča App Store",
+ "Weather service" : "Vremenske storitve",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Za večjo zasebnost so podatki vremena pridobljeni prek strežnika Nextcloud, zato tretje osebe ne pridobijo nobenega vašega osebnega podatka.",
+ "Weather data from Met.no" : "Podatke vremena omogoča Met.no",
+ "geocoding with Nominatim" : "geokodiranje Nominatim",
+ "elevation data from OpenTopoData" : "podatke nadmorske višine OpenTopoData"
+},
+"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);");
diff --git a/apps/dashboard/l10n/sl.json b/apps/dashboard/l10n/sl.json
new file mode 100644
index 00000000000..fd64b0e1b56
--- /dev/null
+++ b/apps/dashboard/l10n/sl.json
@@ -0,0 +1,24 @@
+{ "translations": {
+ "Dashboard" : "Nadzorna plošča",
+ "Dashboard app" : "Program Nadzorna plošča",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Začnite dan s pravimi informacijami\n\nNadzorna plošča Nextcloud je prva točka dneva, ki vam omogoča\npregled prihajajočih sestankov, nujnih elektronskih sporočil in sporočil klepeta, podrobnosti o prejetih nalogah, najnovejših sporočilih z družbenih omrežij in še veliko več! Vsak uporabnik lahko doda gradnike in spreminja ozadje po svojih željah.",
+ "Weather" : "Vreme",
+ "Status" : "Stanje",
+ "Good morning" : "Dobro jutro",
+ "Good morning, {name}" : "Dobro jutro, {name}",
+ "Good afternoon" : "Dober dan",
+ "Good afternoon, {name}" : "Dober dan, {name}",
+ "Good evening" : "Dober večer",
+ "Good evening, {name}" : "Dober večer, {name}",
+ "Hello" : "Pozdravljeni",
+ "Hello, {name}" : "Pozdravljeni, {name}",
+ "Customize" : "Prilagodi",
+ "Edit widgets" : "Izbor gradnikov",
+ "Get more widgets from the App Store" : "Pridobi več gradnikov s spletišča App Store",
+ "Weather service" : "Vremenske storitve",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Za večjo zasebnost so podatki vremena pridobljeni prek strežnika Nextcloud, zato tretje osebe ne pridobijo nobenega vašega osebnega podatka.",
+ "Weather data from Met.no" : "Podatke vremena omogoča Met.no",
+ "geocoding with Nominatim" : "geokodiranje Nominatim",
+ "elevation data from OpenTopoData" : "podatke nadmorske višine OpenTopoData"
+},"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/apps/dashboard/l10n/sr.js b/apps/dashboard/l10n/sr.js
new file mode 100644
index 00000000000..e647f915fe7
--- /dev/null
+++ b/apps/dashboard/l10n/sr.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Контролна табла",
+ "Dashboard app" : "Апликација контролне табле",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Започните свој дан информацијама\n\nNextcloud Контролна табла је почетна тачка вашег дана, она вам даје преглед наредних састанака, хитних и-мејлова, чет порука, придошлих тикета, најновијих твитова и још пуно тога! Људи могу да додају виџете који им се свиђају и да по жељи измене позадину.",
+ "Weather" : "Време",
+ "Status" : "Статус",
+ "Good morning" : "Добро јутро",
+ "Good morning, {name}" : "Добро јутро, {name}",
+ "Good afternoon" : "Добар дан",
+ "Good afternoon, {name}" : "Добар дан, {name}",
+ "Good evening" : "Добро вече",
+ "Good evening, {name}" : "Добро вече, {name}",
+ "Hello" : "Здраво",
+ "Hello, {name}" : "Здраво, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Срећан рођендан 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Срећан рођендан {name} 🥳🤩🎂🎉",
+ "Customize" : "Прилагођавање",
+ "Edit widgets" : "Уређивање виџета",
+ "Get more widgets from the App Store" : "Преузмите још виџета из Продавнице апликација",
+ "Weather service" : "Метео сервис",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Ради чувања ваше приватности, временске податке са метеоролошког сервиса у ваше име захтева Nextcloud сервер, тако да се метеоролошком сервису не шаљу лични подаци.",
+ "Weather data from Met.no" : "Метеоролошки подаци са Met.no",
+ "geocoding with Nominatim" : "геокодирање са Nominatim",
+ "elevation data from OpenTopoData" : "висински подаци са OpenTopoData"
+},
+"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/apps/dashboard/l10n/sr.json b/apps/dashboard/l10n/sr.json
new file mode 100644
index 00000000000..05f1f7dda72
--- /dev/null
+++ b/apps/dashboard/l10n/sr.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Контролна табла",
+ "Dashboard app" : "Апликација контролне табле",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Започните свој дан информацијама\n\nNextcloud Контролна табла је почетна тачка вашег дана, она вам даје преглед наредних састанака, хитних и-мејлова, чет порука, придошлих тикета, најновијих твитова и још пуно тога! Људи могу да додају виџете који им се свиђају и да по жељи измене позадину.",
+ "Weather" : "Време",
+ "Status" : "Статус",
+ "Good morning" : "Добро јутро",
+ "Good morning, {name}" : "Добро јутро, {name}",
+ "Good afternoon" : "Добар дан",
+ "Good afternoon, {name}" : "Добар дан, {name}",
+ "Good evening" : "Добро вече",
+ "Good evening, {name}" : "Добро вече, {name}",
+ "Hello" : "Здраво",
+ "Hello, {name}" : "Здраво, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Срећан рођендан 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Срећан рођендан {name} 🥳🤩🎂🎉",
+ "Customize" : "Прилагођавање",
+ "Edit widgets" : "Уређивање виџета",
+ "Get more widgets from the App Store" : "Преузмите још виџета из Продавнице апликација",
+ "Weather service" : "Метео сервис",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Ради чувања ваше приватности, временске податке са метеоролошког сервиса у ваше име захтева Nextcloud сервер, тако да се метеоролошком сервису не шаљу лични подаци.",
+ "Weather data from Met.no" : "Метеоролошки подаци са Met.no",
+ "geocoding with Nominatim" : "геокодирање са Nominatim",
+ "elevation data from OpenTopoData" : "висински подаци са OpenTopoData"
+},"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/apps/dashboard/l10n/sv.js b/apps/dashboard/l10n/sv.js
new file mode 100644
index 00000000000..8e7c46e93c4
--- /dev/null
+++ b/apps/dashboard/l10n/sv.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Börja din dag informerad\n\nNextcloud Dashboard är din startpunkt för dagen och ger dig en översikt över dina kommande möten, brådskande e-postmeddelanden, chattmeddelanden, inkommande ärenden, senaste tweets och mycket mer! Användare kan lägga till widgetar de gillar och anpassa bakgrunden efter deras tycke.",
+ "Weather" : "Väder",
+ "Status" : "Status",
+ "Good morning" : "God morgon",
+ "Good morning, {name}" : "God morgon, {name}",
+ "Good afternoon" : "God eftermiddag",
+ "Good afternoon, {name}" : "God eftermiddag, {name}",
+ "Good evening" : "God kväll",
+ "Good evening, {name}" : "God kväll, {name}",
+ "Hello" : "Hej",
+ "Hello, {name}" : "Hej, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Grattis på födelsedagen 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Grattis på födelsedagen, {name} 🥳🤩🎂🎉",
+ "Customize" : "Anpassa",
+ "Edit widgets" : "Ändra widgetar",
+ "Get more widgets from the App Store" : "Hämta fler widgetar från Appstore",
+ "Weather service" : "Vädertjänst",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "För din integritet skull hämtas väderdata av din Nextcloud-server på dina vägnar så att vädertjänsten inte får någon personlig information.",
+ "Weather data from Met.no" : "Väderdata från Met.no",
+ "geocoding with Nominatim" : "geokodning med Nominatim",
+ "elevation data from OpenTopoData" : "höjddata från OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/sv.json b/apps/dashboard/l10n/sv.json
new file mode 100644
index 00000000000..4c6b6d239c4
--- /dev/null
+++ b/apps/dashboard/l10n/sv.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Dashboard",
+ "Dashboard app" : "Dashboard app",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Börja din dag informerad\n\nNextcloud Dashboard är din startpunkt för dagen och ger dig en översikt över dina kommande möten, brådskande e-postmeddelanden, chattmeddelanden, inkommande ärenden, senaste tweets och mycket mer! Användare kan lägga till widgetar de gillar och anpassa bakgrunden efter deras tycke.",
+ "Weather" : "Väder",
+ "Status" : "Status",
+ "Good morning" : "God morgon",
+ "Good morning, {name}" : "God morgon, {name}",
+ "Good afternoon" : "God eftermiddag",
+ "Good afternoon, {name}" : "God eftermiddag, {name}",
+ "Good evening" : "God kväll",
+ "Good evening, {name}" : "God kväll, {name}",
+ "Hello" : "Hej",
+ "Hello, {name}" : "Hej, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Grattis på födelsedagen 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Grattis på födelsedagen, {name} 🥳🤩🎂🎉",
+ "Customize" : "Anpassa",
+ "Edit widgets" : "Ändra widgetar",
+ "Get more widgets from the App Store" : "Hämta fler widgetar från Appstore",
+ "Weather service" : "Vädertjänst",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "För din integritet skull hämtas väderdata av din Nextcloud-server på dina vägnar så att vädertjänsten inte får någon personlig information.",
+ "Weather data from Met.no" : "Väderdata från Met.no",
+ "geocoding with Nominatim" : "geokodning med Nominatim",
+ "elevation data from OpenTopoData" : "höjddata från OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/sw.js b/apps/dashboard/l10n/sw.js
new file mode 100644
index 00000000000..91a3e892bc5
--- /dev/null
+++ b/apps/dashboard/l10n/sw.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : " Dashibodi",
+ "Dashboard app" : "Programu ya Dashibodi",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Anza siku yako ukiwa na taarifa\n\nDashibodi ya Nextcloud ndiyo kianzio chako cha siku, ikikupa muhtasari wa miadi yako ijayo, barua pepe za dharura, ujumbe wa gumzo, tiketi zinazoingia, twiti za hivi punde na mengi zaidi! Watu wanaweza kuongeza wijeti wanazopenda na kubadilisha usuli kwa kupenda kwao.",
+ "Weather" : "Hali ya hewa",
+ "Status" : "Wadhifa",
+ "Good morning" : "Habari za asubuhi",
+ "Good morning, {name}" : "Habari za asubuhi, {name}",
+ "Good afternoon" : "Habari za mchana",
+ "Good afternoon, {name}" : "Habari za mchana, {name}",
+ "Good evening" : "Habari za jioni",
+ "Good evening, {name}" : "Habari za jioni, {name}",
+ "Hello" : "Hello",
+ "Hello, {name}" : "Hello, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Heri ya siku ya kuzaliwa 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Heri ya siku ya kuzaliwa, {name} 🥳🤩🎂🎉",
+ "Customize" : "Geuza kukufaa",
+ "Edit widgets" : "Hariri wijeti",
+ "Get more widgets from the App Store" : "Pata wijeti zaidi kutoka kwenye hifadhi ya Programu",
+ "Weather service" : "Huduma ya hali ya hewa",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Kwa faragha yako, data ya hali ya hewa inaombwa na seva yako ya Nextcloud kwa niaba yako ili huduma ya hali ya hewa isipokee taarifa za kibinafsi.",
+ "Weather data from Met.no" : "Data za hali ya hewa kutoka Met.no",
+ "geocoding with Nominatim" : "geocoding na Nominatim",
+ "elevation data from OpenTopoData" : "data ya mwinuko kutoka OpenTopoData"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/sw.json b/apps/dashboard/l10n/sw.json
new file mode 100644
index 00000000000..8d5ff9f98cb
--- /dev/null
+++ b/apps/dashboard/l10n/sw.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : " Dashibodi",
+ "Dashboard app" : "Programu ya Dashibodi",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Anza siku yako ukiwa na taarifa\n\nDashibodi ya Nextcloud ndiyo kianzio chako cha siku, ikikupa muhtasari wa miadi yako ijayo, barua pepe za dharura, ujumbe wa gumzo, tiketi zinazoingia, twiti za hivi punde na mengi zaidi! Watu wanaweza kuongeza wijeti wanazopenda na kubadilisha usuli kwa kupenda kwao.",
+ "Weather" : "Hali ya hewa",
+ "Status" : "Wadhifa",
+ "Good morning" : "Habari za asubuhi",
+ "Good morning, {name}" : "Habari za asubuhi, {name}",
+ "Good afternoon" : "Habari za mchana",
+ "Good afternoon, {name}" : "Habari za mchana, {name}",
+ "Good evening" : "Habari za jioni",
+ "Good evening, {name}" : "Habari za jioni, {name}",
+ "Hello" : "Hello",
+ "Hello, {name}" : "Hello, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Heri ya siku ya kuzaliwa 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Heri ya siku ya kuzaliwa, {name} 🥳🤩🎂🎉",
+ "Customize" : "Geuza kukufaa",
+ "Edit widgets" : "Hariri wijeti",
+ "Get more widgets from the App Store" : "Pata wijeti zaidi kutoka kwenye hifadhi ya Programu",
+ "Weather service" : "Huduma ya hali ya hewa",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Kwa faragha yako, data ya hali ya hewa inaombwa na seva yako ya Nextcloud kwa niaba yako ili huduma ya hali ya hewa isipokee taarifa za kibinafsi.",
+ "Weather data from Met.no" : "Data za hali ya hewa kutoka Met.no",
+ "geocoding with Nominatim" : "geocoding na Nominatim",
+ "elevation data from OpenTopoData" : "data ya mwinuko kutoka OpenTopoData"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/th.js b/apps/dashboard/l10n/th.js
new file mode 100644
index 00000000000..3082d0967b0
--- /dev/null
+++ b/apps/dashboard/l10n/th.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "แดชบอร์ด",
+ "Dashboard app" : "แอปแดชบอร์ด",
+ "Weather" : "สภาพอากาศ",
+ "Status" : "สถานะ",
+ "Good morning" : "สวัสดีตอนเช้า",
+ "Good morning, {name}" : "สวัสดีตอนเช้า {name}",
+ "Good afternoon" : "สวัสดีตอนบ่าย",
+ "Good afternoon, {name}" : "สวัสดีตอนบ่าย {name}",
+ "Good evening" : "สวัสดีตอนเย็น",
+ "Good evening, {name}" : "สวัสดีตอนเย็น {name}",
+ "Hello" : "สวัสดี",
+ "Hello, {name}" : "สวัสดี {name}",
+ "Customize" : "ปรับแต่ง",
+ "Edit widgets" : "แก้ไขวิดเจ็ต",
+ "Get more widgets from the App Store" : "เลือกวิดเจ็ตจาก App Store",
+ "Weather service" : "บริการสภาพอากาศ",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "เพื่อความเป็นส่วนตัวของคุณ ข้อมูลสภาพอากาศถูกขอโดยเซิร์ฟเวอร์ Nextcloud ในนามของคุณ ดังนั้นบริการสภาพอากาศจึงไม่ได้รับข้อมูลส่วนบุคคลใด ๆ",
+ "Weather data from Met.no" : "ข้อมูลสภาพอากาศจาก Met.no",
+ "geocoding with Nominatim" : "พิกัดภูมิศาสตร์จาก Nominatim",
+ "elevation data from OpenTopoData" : "ข้อมูลความสูงจาก OpenTopoData"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/th.json b/apps/dashboard/l10n/th.json
new file mode 100644
index 00000000000..c8de5f7c716
--- /dev/null
+++ b/apps/dashboard/l10n/th.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "แดชบอร์ด",
+ "Dashboard app" : "แอปแดชบอร์ด",
+ "Weather" : "สภาพอากาศ",
+ "Status" : "สถานะ",
+ "Good morning" : "สวัสดีตอนเช้า",
+ "Good morning, {name}" : "สวัสดีตอนเช้า {name}",
+ "Good afternoon" : "สวัสดีตอนบ่าย",
+ "Good afternoon, {name}" : "สวัสดีตอนบ่าย {name}",
+ "Good evening" : "สวัสดีตอนเย็น",
+ "Good evening, {name}" : "สวัสดีตอนเย็น {name}",
+ "Hello" : "สวัสดี",
+ "Hello, {name}" : "สวัสดี {name}",
+ "Customize" : "ปรับแต่ง",
+ "Edit widgets" : "แก้ไขวิดเจ็ต",
+ "Get more widgets from the App Store" : "เลือกวิดเจ็ตจาก App Store",
+ "Weather service" : "บริการสภาพอากาศ",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "เพื่อความเป็นส่วนตัวของคุณ ข้อมูลสภาพอากาศถูกขอโดยเซิร์ฟเวอร์ Nextcloud ในนามของคุณ ดังนั้นบริการสภาพอากาศจึงไม่ได้รับข้อมูลส่วนบุคคลใด ๆ",
+ "Weather data from Met.no" : "ข้อมูลสภาพอากาศจาก Met.no",
+ "geocoding with Nominatim" : "พิกัดภูมิศาสตร์จาก Nominatim",
+ "elevation data from OpenTopoData" : "ข้อมูลความสูงจาก OpenTopoData"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/tr.js b/apps/dashboard/l10n/tr.js
new file mode 100644
index 00000000000..0ca94d0a5d0
--- /dev/null
+++ b/apps/dashboard/l10n/tr.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Pano",
+ "Dashboard app" : "Pano uygulaması",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Güne bilgilenerek başlayın\n\nNextcloud Pano, gününüzün başlangıç noktasıdır ve size yaklaşan randevularınız, acil e-postalarınız, sohbet iletileri, gelen destek istekleri, son tweetler gibi pek çok bilgi verir! Kişiler istedikleri başka pano bileşenlerini ekleyebilir ve arka planı değiştirebilir.",
+ "Weather" : "Hava durumu",
+ "Status" : "Durum",
+ "Good morning" : "Günaydın",
+ "Good morning, {name}" : "Günaydın, {name}",
+ "Good afternoon" : "Tünaydın",
+ "Good afternoon, {name}" : "Tünaydın, {name}",
+ "Good evening" : "İyi geceler",
+ "Good evening, {name}" : "İyi geceler, {name}",
+ "Hello" : "Merhaba",
+ "Hello, {name}" : "Merhaba {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Mutlu yıllar 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Mutlu yıllar, {name} 🥳🤩🎂🎉",
+ "Customize" : "Özelleştir",
+ "Edit widgets" : "Pano bileşenlerini düzenle",
+ "Get more widgets from the App Store" : "Uygulama mağazasından başka pano bileşenleri alın",
+ "Weather service" : "Hava durumu",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Kişisel gizliliğinizi korumak için Nextcloud sunucunuz hava durumu verilerini sizin adınıza ister. Böylece hava durumu hizmetine hiçbir kişisel bilgi aktarılmaz.",
+ "Weather data from Met.no" : "Hava durumu verileri Met.no tarafından sağlanıyor",
+ "geocoding with Nominatim" : "Nominatim ile coğrafi kodlama",
+ "elevation data from OpenTopoData" : "yükseklik verileri OpenTopoData tarafından sağlanıyor"
+},
+"nplurals=2; plural=(n > 1);");
diff --git a/apps/dashboard/l10n/tr.json b/apps/dashboard/l10n/tr.json
new file mode 100644
index 00000000000..714f1c70745
--- /dev/null
+++ b/apps/dashboard/l10n/tr.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Pano",
+ "Dashboard app" : "Pano uygulaması",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Güne bilgilenerek başlayın\n\nNextcloud Pano, gününüzün başlangıç noktasıdır ve size yaklaşan randevularınız, acil e-postalarınız, sohbet iletileri, gelen destek istekleri, son tweetler gibi pek çok bilgi verir! Kişiler istedikleri başka pano bileşenlerini ekleyebilir ve arka planı değiştirebilir.",
+ "Weather" : "Hava durumu",
+ "Status" : "Durum",
+ "Good morning" : "Günaydın",
+ "Good morning, {name}" : "Günaydın, {name}",
+ "Good afternoon" : "Tünaydın",
+ "Good afternoon, {name}" : "Tünaydın, {name}",
+ "Good evening" : "İyi geceler",
+ "Good evening, {name}" : "İyi geceler, {name}",
+ "Hello" : "Merhaba",
+ "Hello, {name}" : "Merhaba {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Mutlu yıllar 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Mutlu yıllar, {name} 🥳🤩🎂🎉",
+ "Customize" : "Özelleştir",
+ "Edit widgets" : "Pano bileşenlerini düzenle",
+ "Get more widgets from the App Store" : "Uygulama mağazasından başka pano bileşenleri alın",
+ "Weather service" : "Hava durumu",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Kişisel gizliliğinizi korumak için Nextcloud sunucunuz hava durumu verilerini sizin adınıza ister. Böylece hava durumu hizmetine hiçbir kişisel bilgi aktarılmaz.",
+ "Weather data from Met.no" : "Hava durumu verileri Met.no tarafından sağlanıyor",
+ "geocoding with Nominatim" : "Nominatim ile coğrafi kodlama",
+ "elevation data from OpenTopoData" : "yükseklik verileri OpenTopoData tarafından sağlanıyor"
+},"pluralForm" :"nplurals=2; plural=(n > 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/ug.js b/apps/dashboard/l10n/ug.js
new file mode 100644
index 00000000000..40ef3144e77
--- /dev/null
+++ b/apps/dashboard/l10n/ug.js
@@ -0,0 +1,26 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "باش تاختا",
+ "Dashboard app" : "باش تاختا دېتالى",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "ئۇچۇرلىرىڭىزنى باشلاڭ\n\nNextcloud باش تاختا سىزنىڭ شۇ كۈندىكى باشلىنىش نۇقتىڭىز بولۇپ ، سىزگە كەلگۈسىدىكى ئۇچرىشىشلىرىڭىز ، جىددى ئېلېكترونلۇق خەتلەر ، پاراڭلىشىش ئۇچۇرلىرى ، كەلگەن بېلەتلەر ، ئەڭ يېڭى tweet ۋە باشقىلار ھەققىدە ئومۇمىي چۈشەنچە بېرىدۇ. كىشىلەر ئۆزى ياقتۇرىدىغان كىچىك قوراللارنى قوشالايدۇ ۋە تەگلىكىنى خالىغانچە ئۆزگەرتەلەيدۇ.",
+ "Weather" : "ھاۋارايى",
+ "Status" : "ھالەت",
+ "Good morning" : "خەيرلىك ئەتىگەن!",
+ "Good morning, {name}" : "خەيرلىك ئەتىگەن ، {name}",
+ "Good afternoon" : "خەيرلىك چۈشتىن كېيىن",
+ "Good afternoon, {name}" : "خەيرلىك چۈشتىن كېيىن ، {name}",
+ "Good evening" : "خەيرلىك كەچ!",
+ "Good evening, {name}" : "خەيرلىك كەچ ، {name}",
+ "Hello" : "ياخشىمۇسىز",
+ "Hello, {name}" : "ياخشىمۇسىز ، {name}",
+ "Customize" : "Customize",
+ "Edit widgets" : "كىچىك قوراللارنى تەھرىرلەش",
+ "Get more widgets from the App Store" : "ئەپ دۇكىنىدىن تېخىمۇ كۆپ كىچىك قوراللارغا ئېرىشىڭ",
+ "Weather service" : "ھاۋارايى مۇلازىمىتى",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "شەخسىي مەخپىيەتلىكىڭىز ئۈچۈن ھاۋارايى سانلىق مەلۇماتلىرىڭىزنى Nextcloud مۇلازىمېتىرىڭىز تەلەپ قىلىدۇ ، شۇڭا ھاۋارايى مۇلازىمىتى ھېچقانداق شەخسىي ئۇچۇرغا ئېرىشەلمەيدۇ.",
+ "Weather data from Met.no" : "Met.no دىن كەلگەن ھاۋارايى سانلىق مەلۇماتلىرى",
+ "geocoding with Nominatim" : "Nominatim بىلەن جۇغراپىيىلىك كودلاش",
+ "elevation data from OpenTopoData" : "OpenTopoData دىن ئېگىزلىك سانلىق مەلۇماتلىرى"
+},
+"nplurals=2; plural=(n != 1);");
diff --git a/apps/dashboard/l10n/ug.json b/apps/dashboard/l10n/ug.json
new file mode 100644
index 00000000000..3b551538828
--- /dev/null
+++ b/apps/dashboard/l10n/ug.json
@@ -0,0 +1,24 @@
+{ "translations": {
+ "Dashboard" : "باش تاختا",
+ "Dashboard app" : "باش تاختا دېتالى",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "ئۇچۇرلىرىڭىزنى باشلاڭ\n\nNextcloud باش تاختا سىزنىڭ شۇ كۈندىكى باشلىنىش نۇقتىڭىز بولۇپ ، سىزگە كەلگۈسىدىكى ئۇچرىشىشلىرىڭىز ، جىددى ئېلېكترونلۇق خەتلەر ، پاراڭلىشىش ئۇچۇرلىرى ، كەلگەن بېلەتلەر ، ئەڭ يېڭى tweet ۋە باشقىلار ھەققىدە ئومۇمىي چۈشەنچە بېرىدۇ. كىشىلەر ئۆزى ياقتۇرىدىغان كىچىك قوراللارنى قوشالايدۇ ۋە تەگلىكىنى خالىغانچە ئۆزگەرتەلەيدۇ.",
+ "Weather" : "ھاۋارايى",
+ "Status" : "ھالەت",
+ "Good morning" : "خەيرلىك ئەتىگەن!",
+ "Good morning, {name}" : "خەيرلىك ئەتىگەن ، {name}",
+ "Good afternoon" : "خەيرلىك چۈشتىن كېيىن",
+ "Good afternoon, {name}" : "خەيرلىك چۈشتىن كېيىن ، {name}",
+ "Good evening" : "خەيرلىك كەچ!",
+ "Good evening, {name}" : "خەيرلىك كەچ ، {name}",
+ "Hello" : "ياخشىمۇسىز",
+ "Hello, {name}" : "ياخشىمۇسىز ، {name}",
+ "Customize" : "Customize",
+ "Edit widgets" : "كىچىك قوراللارنى تەھرىرلەش",
+ "Get more widgets from the App Store" : "ئەپ دۇكىنىدىن تېخىمۇ كۆپ كىچىك قوراللارغا ئېرىشىڭ",
+ "Weather service" : "ھاۋارايى مۇلازىمىتى",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "شەخسىي مەخپىيەتلىكىڭىز ئۈچۈن ھاۋارايى سانلىق مەلۇماتلىرىڭىزنى Nextcloud مۇلازىمېتىرىڭىز تەلەپ قىلىدۇ ، شۇڭا ھاۋارايى مۇلازىمىتى ھېچقانداق شەخسىي ئۇچۇرغا ئېرىشەلمەيدۇ.",
+ "Weather data from Met.no" : "Met.no دىن كەلگەن ھاۋارايى سانلىق مەلۇماتلىرى",
+ "geocoding with Nominatim" : "Nominatim بىلەن جۇغراپىيىلىك كودلاش",
+ "elevation data from OpenTopoData" : "OpenTopoData دىن ئېگىزلىك سانلىق مەلۇماتلىرى"
+},"pluralForm" :"nplurals=2; plural=(n != 1);"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/uk.js b/apps/dashboard/l10n/uk.js
new file mode 100644
index 00000000000..3310f78cbc6
--- /dev/null
+++ b/apps/dashboard/l10n/uk.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Майстерня",
+ "Dashboard app" : "Застосунок з панеллю віджетів ",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Почніть свій день з інформацією\n\nПанель управління Nextcloud — це ваша відправна точка на початку дня, яка надає огляд ваших майбутніх зустрічей, термінових електронних листів, повідомлень у чаті, вхідних квитків, останніх твітів та багато іншого! Користувачі можуть додавати вподобані віджети та змінювати фон на свій смак.",
+ "Weather" : "Погода",
+ "Status" : "Статус",
+ "Good morning" : "Доброго ранку",
+ "Good morning, {name}" : "Доброго ранку, {name}",
+ "Good afternoon" : "Добрий день",
+ "Good afternoon, {name}" : "Добрий день, {name}",
+ "Good evening" : "Добрий вечір",
+ "Good evening, {name}" : "Добрий вечір, {name}",
+ "Hello" : "Привіт",
+ "Hello, {name}" : "Привіт, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "З Днем народження 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "З Днем народження, {name} 🥳🤩🎂🎉",
+ "Customize" : "Редагувати",
+ "Edit widgets" : "Редагувати віджети",
+ "Get more widgets from the App Store" : "Більше віджетів у каталозі застосунків",
+ "Weather service" : "Погода",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Для забезпечення вашої конфіденційності дані про погоду запитуються вашим сервером Nextcloud від вашого імені, тому служба погоди не отримує особисту інформацію.",
+ "Weather data from Met.no" : "Дані про погоду з Met.no",
+ "geocoding with Nominatim" : "геокодування за допомогою Nominatim",
+ "elevation data from OpenTopoData" : "дані про висоту з OpenTopoData"
+},
+"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/apps/dashboard/l10n/uk.json b/apps/dashboard/l10n/uk.json
new file mode 100644
index 00000000000..8e69d9b812b
--- /dev/null
+++ b/apps/dashboard/l10n/uk.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Майстерня",
+ "Dashboard app" : "Застосунок з панеллю віджетів ",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Почніть свій день з інформацією\n\nПанель управління Nextcloud — це ваша відправна точка на початку дня, яка надає огляд ваших майбутніх зустрічей, термінових електронних листів, повідомлень у чаті, вхідних квитків, останніх твітів та багато іншого! Користувачі можуть додавати вподобані віджети та змінювати фон на свій смак.",
+ "Weather" : "Погода",
+ "Status" : "Статус",
+ "Good morning" : "Доброго ранку",
+ "Good morning, {name}" : "Доброго ранку, {name}",
+ "Good afternoon" : "Добрий день",
+ "Good afternoon, {name}" : "Добрий день, {name}",
+ "Good evening" : "Добрий вечір",
+ "Good evening, {name}" : "Добрий вечір, {name}",
+ "Hello" : "Привіт",
+ "Hello, {name}" : "Привіт, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "З Днем народження 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "З Днем народження, {name} 🥳🤩🎂🎉",
+ "Customize" : "Редагувати",
+ "Edit widgets" : "Редагувати віджети",
+ "Get more widgets from the App Store" : "Більше віджетів у каталозі застосунків",
+ "Weather service" : "Погода",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Для забезпечення вашої конфіденційності дані про погоду запитуються вашим сервером Nextcloud від вашого імені, тому служба погоди не отримує особисту інформацію.",
+ "Weather data from Met.no" : "Дані про погоду з Met.no",
+ "geocoding with Nominatim" : "геокодування за допомогою Nominatim",
+ "elevation data from OpenTopoData" : "дані про висоту з OpenTopoData"
+},"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/apps/dashboard/l10n/uz.js b/apps/dashboard/l10n/uz.js
new file mode 100644
index 00000000000..23282080b47
--- /dev/null
+++ b/apps/dashboard/l10n/uz.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Boshqaruv paneli",
+ "Dashboard app" : "Boshqaruv paneli ilovasi",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Kuningizni xabardorlik bilan boshlang\n\nNextcloud Dashboard - bu kunning boshlang'ich nuqtasi bo'lib, sizga bo'lajak uchrashuvlar, shoshilinch elektron pochta xabarlari, chat xabarlari, kiruvchi chiptalar, so'nggi tvitlar va boshqalar haqida umumiy ma'lumot beradi! Odamlar o'zlari yoqtirgan vidjetlarni qo'shishlari va fonni o'z xohishlariga ko'ra o'zgartirishlari mumkin.",
+ "Weather" : "Ob-havo",
+ "Status" : "Status",
+ "Good morning" : "Xayrli tong",
+ "Good morning, {name}" : "Xayrli tong, {name}",
+ "Good afternoon" : "Hayrli kun",
+ "Good afternoon, {name}" : "Hayrli kun, {name}",
+ "Good evening" : "Hayrli kech",
+ "Good evening, {name}" : "Hayrli kech, {name}",
+ "Hello" : "Assalomu aleykum",
+ "Hello, {name}" : "Assalomu aleykum, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Tug'ilgan kun muborak bo'lsin 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Tug'ilgan kun muborak bo'lsin, {name} 🥳🤩🎂🎉",
+ "Customize" : "Moslashtirish",
+ "Edit widgets" : "Vidjetlarni tahrirlash",
+ "Get more widgets from the App Store" : "App Store'dan ko'proq vidjetlarni oling",
+ "Weather service" : "Ob-havo xizmati",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Maxfiyligingiz uchun ob-havo maʼlumotlari sizning nomingizdan Nextcloud serveringiz tomonidan soʻraladi, shuning uchun ob-havo xizmati shaxsiy maʼlumotlarni olmaydi.",
+ "Weather data from Met.no" : "Met.no dan ob-havo ma'lumotlari",
+ "geocoding with Nominatim" : "Nominatim bilan geokodlash",
+ "elevation data from OpenTopoData" : "OpenTopoData dan balandlik ma'lumotlari"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/uz.json b/apps/dashboard/l10n/uz.json
new file mode 100644
index 00000000000..b2b24b7dcdb
--- /dev/null
+++ b/apps/dashboard/l10n/uz.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "Boshqaruv paneli",
+ "Dashboard app" : "Boshqaruv paneli ilovasi",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "Kuningizni xabardorlik bilan boshlang\n\nNextcloud Dashboard - bu kunning boshlang'ich nuqtasi bo'lib, sizga bo'lajak uchrashuvlar, shoshilinch elektron pochta xabarlari, chat xabarlari, kiruvchi chiptalar, so'nggi tvitlar va boshqalar haqida umumiy ma'lumot beradi! Odamlar o'zlari yoqtirgan vidjetlarni qo'shishlari va fonni o'z xohishlariga ko'ra o'zgartirishlari mumkin.",
+ "Weather" : "Ob-havo",
+ "Status" : "Status",
+ "Good morning" : "Xayrli tong",
+ "Good morning, {name}" : "Xayrli tong, {name}",
+ "Good afternoon" : "Hayrli kun",
+ "Good afternoon, {name}" : "Hayrli kun, {name}",
+ "Good evening" : "Hayrli kech",
+ "Good evening, {name}" : "Hayrli kech, {name}",
+ "Hello" : "Assalomu aleykum",
+ "Hello, {name}" : "Assalomu aleykum, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "Tug'ilgan kun muborak bo'lsin 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "Tug'ilgan kun muborak bo'lsin, {name} 🥳🤩🎂🎉",
+ "Customize" : "Moslashtirish",
+ "Edit widgets" : "Vidjetlarni tahrirlash",
+ "Get more widgets from the App Store" : "App Store'dan ko'proq vidjetlarni oling",
+ "Weather service" : "Ob-havo xizmati",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Maxfiyligingiz uchun ob-havo maʼlumotlari sizning nomingizdan Nextcloud serveringiz tomonidan soʻraladi, shuning uchun ob-havo xizmati shaxsiy maʼlumotlarni olmaydi.",
+ "Weather data from Met.no" : "Met.no dan ob-havo ma'lumotlari",
+ "geocoding with Nominatim" : "Nominatim bilan geokodlash",
+ "elevation data from OpenTopoData" : "OpenTopoData dan balandlik ma'lumotlari"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/vi.js b/apps/dashboard/l10n/vi.js
new file mode 100644
index 00000000000..dbe1b126d44
--- /dev/null
+++ b/apps/dashboard/l10n/vi.js
@@ -0,0 +1,25 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "Tổng quan",
+ "Dashboard app" : "Ứng dụng Tổng quan",
+ "Weather" : "Thời tiết",
+ "Status" : "Trạng thái",
+ "Good morning" : "Chào buổi sáng",
+ "Good morning, {name}" : "Chào buổi sáng, {name}",
+ "Good afternoon" : "Chào buổi chiều",
+ "Good afternoon, {name}" : "Chào buổi chiều, {name}",
+ "Good evening" : "Chào buổi tối",
+ "Good evening, {name}" : "Chào buổi tối, {name}",
+ "Hello" : "Xin chào",
+ "Hello, {name}" : "Xin chào, {name}",
+ "Customize" : "Tuỳ chỉnh",
+ "Edit widgets" : "Chỉnh sửa widget",
+ "Get more widgets from the App Store" : "Tải thêm widget từ App Store",
+ "Weather service" : "Dịch vụ thời tiết",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Vì quyền riêng tư của bạn, dữ liệu thời tiết được yêu cầu bởi máy chủ Nextcloud thay mặt bạn để dịch vụ thời tiết không nhận được thông tin cá nhân.",
+ "Weather data from Met.no" : "Dữ liệu thời tiết từ Met.no",
+ "geocoding with Nominatim" : "mã hóa địa lý với Nominatim",
+ "elevation data from OpenTopoData" : "dữ liệu độ cao từ OpenTopoData"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/vi.json b/apps/dashboard/l10n/vi.json
new file mode 100644
index 00000000000..7b302629c4a
--- /dev/null
+++ b/apps/dashboard/l10n/vi.json
@@ -0,0 +1,23 @@
+{ "translations": {
+ "Dashboard" : "Tổng quan",
+ "Dashboard app" : "Ứng dụng Tổng quan",
+ "Weather" : "Thời tiết",
+ "Status" : "Trạng thái",
+ "Good morning" : "Chào buổi sáng",
+ "Good morning, {name}" : "Chào buổi sáng, {name}",
+ "Good afternoon" : "Chào buổi chiều",
+ "Good afternoon, {name}" : "Chào buổi chiều, {name}",
+ "Good evening" : "Chào buổi tối",
+ "Good evening, {name}" : "Chào buổi tối, {name}",
+ "Hello" : "Xin chào",
+ "Hello, {name}" : "Xin chào, {name}",
+ "Customize" : "Tuỳ chỉnh",
+ "Edit widgets" : "Chỉnh sửa widget",
+ "Get more widgets from the App Store" : "Tải thêm widget từ App Store",
+ "Weather service" : "Dịch vụ thời tiết",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "Vì quyền riêng tư của bạn, dữ liệu thời tiết được yêu cầu bởi máy chủ Nextcloud thay mặt bạn để dịch vụ thời tiết không nhận được thông tin cá nhân.",
+ "Weather data from Met.no" : "Dữ liệu thời tiết từ Met.no",
+ "geocoding with Nominatim" : "mã hóa địa lý với Nominatim",
+ "elevation data from OpenTopoData" : "dữ liệu độ cao từ OpenTopoData"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/zh_CN.js b/apps/dashboard/l10n/zh_CN.js
new file mode 100644
index 00000000000..0f6c8dcd4c3
--- /dev/null
+++ b/apps/dashboard/l10n/zh_CN.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "仪表盘",
+ "Dashboard app" : "仪表盘应用",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "在通知中开启你新的一天\n\nNextcloud仪表盘是你一天的起点,为你提供未来会议、紧急邮件、聊天信息、新入订单、最新推文和更多信息的概述总览!用户可以添加喜爱的小组件,或是修改成喜欢的背景。",
+ "Weather" : "天气",
+ "Status" : "状态",
+ "Good morning" : "早上好",
+ "Good morning, {name}" : "早上好,{name}",
+ "Good afternoon" : "下午好",
+ "Good afternoon, {name}" : "下午好,{name}",
+ "Good evening" : "晚上好",
+ "Good evening, {name}" : "晚上好,{name}",
+ "Hello" : "你好",
+ "Hello, {name}" : "你好, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "生日快乐 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "生日快乐,{name} 🥳🤩🎂🎉",
+ "Customize" : "自定义",
+ "Edit widgets" : "编辑小部件",
+ "Get more widgets from the App Store" : "从应用商店获取更多小部件",
+ "Weather service" : "天气服务",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "为了您的隐私,天气数据由您的 Nextcloud 服务器为您获取,这样天气服务就无法获得您的个人信息。",
+ "Weather data from Met.no" : "天气数据来自 Met.no",
+ "geocoding with Nominatim" : "使用 Nominatim 地理编码",
+ "elevation data from OpenTopoData" : "海拔数据来自 OpenTopoData"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/zh_CN.json b/apps/dashboard/l10n/zh_CN.json
new file mode 100644
index 00000000000..49d2e660723
--- /dev/null
+++ b/apps/dashboard/l10n/zh_CN.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "仪表盘",
+ "Dashboard app" : "仪表盘应用",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "在通知中开启你新的一天\n\nNextcloud仪表盘是你一天的起点,为你提供未来会议、紧急邮件、聊天信息、新入订单、最新推文和更多信息的概述总览!用户可以添加喜爱的小组件,或是修改成喜欢的背景。",
+ "Weather" : "天气",
+ "Status" : "状态",
+ "Good morning" : "早上好",
+ "Good morning, {name}" : "早上好,{name}",
+ "Good afternoon" : "下午好",
+ "Good afternoon, {name}" : "下午好,{name}",
+ "Good evening" : "晚上好",
+ "Good evening, {name}" : "晚上好,{name}",
+ "Hello" : "你好",
+ "Hello, {name}" : "你好, {name}",
+ "Happy birthday 🥳🤩🎂🎉" : "生日快乐 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "生日快乐,{name} 🥳🤩🎂🎉",
+ "Customize" : "自定义",
+ "Edit widgets" : "编辑小部件",
+ "Get more widgets from the App Store" : "从应用商店获取更多小部件",
+ "Weather service" : "天气服务",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "为了您的隐私,天气数据由您的 Nextcloud 服务器为您获取,这样天气服务就无法获得您的个人信息。",
+ "Weather data from Met.no" : "天气数据来自 Met.no",
+ "geocoding with Nominatim" : "使用 Nominatim 地理编码",
+ "elevation data from OpenTopoData" : "海拔数据来自 OpenTopoData"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/zh_HK.js b/apps/dashboard/l10n/zh_HK.js
new file mode 100644
index 00000000000..3ec3def4cc4
--- /dev/null
+++ b/apps/dashboard/l10n/zh_HK.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "儀表板",
+ "Dashboard app" : "儀表板應用程式",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "開始您新的一天\n\nNextcloud 儀表板是您一天的起點,為您提供您即將到來的約會概覽、緊急電郵、聊天訊息、新到的工單、最新的推文以及更多!人仕可以新增他們喜愛的小工具與變更他們喜愛的背景。",
+ "Weather" : "天氣",
+ "Status" : "狀態",
+ "Good morning" : "早晨",
+ "Good morning, {name}" : "早晨,{name}",
+ "Good afternoon" : "午安",
+ "Good afternoon, {name}" : "午安,{name}",
+ "Good evening" : "晚安",
+ "Good evening, {name}" : "晚安,{name}",
+ "Hello" : "哈囉",
+ "Hello, {name}" : "哈囉,{name}",
+ "Happy birthday 🥳🤩🎂🎉" : "生日快樂 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "生日快樂,{name} 🥳🤩🎂🎉",
+ "Customize" : "自訂",
+ "Edit widgets" : "編輯小工具",
+ "Get more widgets from the App Store" : "從 App Store 取得更多小工具",
+ "Weather service" : "天氣服務",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "為了保護您的隱私,Nextcloud 會代您請求氣象資料,因此天氣服務不會收到您的個人資訊。",
+ "Weather data from Met.no" : "氣象資訊來自 Met.no",
+ "geocoding with Nominatim" : "使用 Nominatim 來進行地理編碼",
+ "elevation data from OpenTopoData" : "來自 OpenTopoData 的海拔資料"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/zh_HK.json b/apps/dashboard/l10n/zh_HK.json
new file mode 100644
index 00000000000..6efb17e03a4
--- /dev/null
+++ b/apps/dashboard/l10n/zh_HK.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "儀表板",
+ "Dashboard app" : "儀表板應用程式",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "開始您新的一天\n\nNextcloud 儀表板是您一天的起點,為您提供您即將到來的約會概覽、緊急電郵、聊天訊息、新到的工單、最新的推文以及更多!人仕可以新增他們喜愛的小工具與變更他們喜愛的背景。",
+ "Weather" : "天氣",
+ "Status" : "狀態",
+ "Good morning" : "早晨",
+ "Good morning, {name}" : "早晨,{name}",
+ "Good afternoon" : "午安",
+ "Good afternoon, {name}" : "午安,{name}",
+ "Good evening" : "晚安",
+ "Good evening, {name}" : "晚安,{name}",
+ "Hello" : "哈囉",
+ "Hello, {name}" : "哈囉,{name}",
+ "Happy birthday 🥳🤩🎂🎉" : "生日快樂 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "生日快樂,{name} 🥳🤩🎂🎉",
+ "Customize" : "自訂",
+ "Edit widgets" : "編輯小工具",
+ "Get more widgets from the App Store" : "從 App Store 取得更多小工具",
+ "Weather service" : "天氣服務",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "為了保護您的隱私,Nextcloud 會代您請求氣象資料,因此天氣服務不會收到您的個人資訊。",
+ "Weather data from Met.no" : "氣象資訊來自 Met.no",
+ "geocoding with Nominatim" : "使用 Nominatim 來進行地理編碼",
+ "elevation data from OpenTopoData" : "來自 OpenTopoData 的海拔資料"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/l10n/zh_TW.js b/apps/dashboard/l10n/zh_TW.js
new file mode 100644
index 00000000000..274caee814d
--- /dev/null
+++ b/apps/dashboard/l10n/zh_TW.js
@@ -0,0 +1,28 @@
+OC.L10N.register(
+ "dashboard",
+ {
+ "Dashboard" : "儀表板",
+ "Dashboard app" : "儀表板應用程式",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "開始您新的一天\n\nNextcloud 儀表板是您一天的起點,為您提供您即將到來的約會概覽、緊急電子郵件、聊天訊息、到來的工單、最新的推文以及更多!使用者可以新增他們喜愛的小工具與變更他們喜愛的背景。",
+ "Weather" : "天氣",
+ "Status" : "狀態",
+ "Good morning" : "早安",
+ "Good morning, {name}" : "早安,{name}",
+ "Good afternoon" : "午安",
+ "Good afternoon, {name}" : "午安,{name}",
+ "Good evening" : "晚安",
+ "Good evening, {name}" : "晚安,{name}",
+ "Hello" : "嗨",
+ "Hello, {name}" : "嗨,{name}",
+ "Happy birthday 🥳🤩🎂🎉" : "生日快樂 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "生日快樂,{name} 🥳🤩🎂🎉",
+ "Customize" : "自訂",
+ "Edit widgets" : "編輯小工具",
+ "Get more widgets from the App Store" : "從應用程式商店取得更多小工具",
+ "Weather service" : "天氣服務",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "為了保護您的隱私,Nextcloud 伺服器會代您請求氣象資料,因此天氣服務不會收到您的個人資訊。",
+ "Weather data from Met.no" : "氣象資訊來自 Met.no",
+ "geocoding with Nominatim" : "地理編碼使用 Nominatim",
+ "elevation data from OpenTopoData" : "海拔資料來自 OpenTopoData"
+},
+"nplurals=1; plural=0;");
diff --git a/apps/dashboard/l10n/zh_TW.json b/apps/dashboard/l10n/zh_TW.json
new file mode 100644
index 00000000000..381dc1b6254
--- /dev/null
+++ b/apps/dashboard/l10n/zh_TW.json
@@ -0,0 +1,26 @@
+{ "translations": {
+ "Dashboard" : "儀表板",
+ "Dashboard app" : "儀表板應用程式",
+ "Start your day informed\n\nThe Nextcloud Dashboard is your starting point of the day, giving you an overview of your upcoming appointments, urgent emails, chat messages, incoming tickets, latest tweets and much more! People can add the widgets they like and change the background to their liking." : "開始您新的一天\n\nNextcloud 儀表板是您一天的起點,為您提供您即將到來的約會概覽、緊急電子郵件、聊天訊息、到來的工單、最新的推文以及更多!使用者可以新增他們喜愛的小工具與變更他們喜愛的背景。",
+ "Weather" : "天氣",
+ "Status" : "狀態",
+ "Good morning" : "早安",
+ "Good morning, {name}" : "早安,{name}",
+ "Good afternoon" : "午安",
+ "Good afternoon, {name}" : "午安,{name}",
+ "Good evening" : "晚安",
+ "Good evening, {name}" : "晚安,{name}",
+ "Hello" : "嗨",
+ "Hello, {name}" : "嗨,{name}",
+ "Happy birthday 🥳🤩🎂🎉" : "生日快樂 🥳🤩🎂🎉",
+ "Happy birthday, {name} 🥳🤩🎂🎉" : "生日快樂,{name} 🥳🤩🎂🎉",
+ "Customize" : "自訂",
+ "Edit widgets" : "編輯小工具",
+ "Get more widgets from the App Store" : "從應用程式商店取得更多小工具",
+ "Weather service" : "天氣服務",
+ "For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information." : "為了保護您的隱私,Nextcloud 伺服器會代您請求氣象資料,因此天氣服務不會收到您的個人資訊。",
+ "Weather data from Met.no" : "氣象資訊來自 Met.no",
+ "geocoding with Nominatim" : "地理編碼使用 Nominatim",
+ "elevation data from OpenTopoData" : "海拔資料來自 OpenTopoData"
+},"pluralForm" :"nplurals=1; plural=0;"
+} \ No newline at end of file
diff --git a/apps/dashboard/lib/Controller/DashboardApiController.php b/apps/dashboard/lib/Controller/DashboardApiController.php
new file mode 100644
index 00000000000..d31cede85b7
--- /dev/null
+++ b/apps/dashboard/lib/Controller/DashboardApiController.php
@@ -0,0 +1,234 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Dashboard\Controller;
+
+use OCA\Dashboard\ResponseDefinitions;
+use OCA\Dashboard\Service\DashboardService;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\ApiRoute;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\OCSController;
+use OCP\Dashboard\IAPIWidget;
+use OCP\Dashboard\IAPIWidgetV2;
+use OCP\Dashboard\IButtonWidget;
+use OCP\Dashboard\IIconWidget;
+use OCP\Dashboard\IManager;
+use OCP\Dashboard\IOptionWidget;
+use OCP\Dashboard\IReloadableWidget;
+use OCP\Dashboard\IWidget;
+use OCP\Dashboard\Model\WidgetButton;
+use OCP\Dashboard\Model\WidgetItem;
+
+use OCP\Dashboard\Model\WidgetOptions;
+use OCP\IConfig;
+use OCP\IRequest;
+
+/**
+ * @psalm-import-type DashboardWidget from ResponseDefinitions
+ * @psalm-import-type DashboardWidgetItem from ResponseDefinitions
+ * @psalm-import-type DashboardWidgetItems from ResponseDefinitions
+ */
+class DashboardApiController extends OCSController {
+
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ private IManager $dashboardManager,
+ private IConfig $config,
+ private ?string $userId,
+ private DashboardService $service,
+ ) {
+ parent::__construct($appName, $request);
+ }
+
+ /**
+ * @param string[] $widgetIds Limit widgets to given ids
+ * @return IWidget[]
+ */
+ private function getShownWidgets(array $widgetIds): array {
+ if (empty($widgetIds)) {
+ $systemDefault = $this->config->getAppValue('dashboard', 'layout', 'recommendations,spreed,mail,calendar');
+ $widgetIds = explode(',', $this->config->getUserValue($this->userId, 'dashboard', 'layout', $systemDefault));
+ }
+
+ return array_filter(
+ $this->dashboardManager->getWidgets(),
+ static function (IWidget $widget) use ($widgetIds) {
+ return in_array($widget->getId(), $widgetIds);
+ },
+ );
+ }
+
+ /**
+ * Get the items for the widgets
+ *
+ * @param array<string, string> $sinceIds Array indexed by widget Ids, contains date/id from which we want the new items
+ * @param int $limit Limit number of result items per widget
+ * @psalm-param int<1, 30> $limit
+ * @param list<string> $widgets Limit results to specific widgets
+ * @return DataResponse<Http::STATUS_OK, array<string, list<DashboardWidgetItem>>, array{}>
+ *
+ * 200: Widget items returned
+ */
+ #[NoAdminRequired]
+ #[NoCSRFRequired]
+ #[ApiRoute(verb: 'GET', url: '/api/v1/widget-items')]
+ public function getWidgetItems(array $sinceIds = [], int $limit = 7, array $widgets = []): DataResponse {
+ $items = [];
+ $widgets = $this->getShownWidgets($widgets);
+ foreach ($widgets as $widget) {
+ if ($widget instanceof IAPIWidget) {
+ $items[$widget->getId()] = array_map(static function (WidgetItem $item) {
+ return $item->jsonSerialize();
+ }, $widget->getItems($this->userId, $sinceIds[$widget->getId()] ?? null, $limit));
+ }
+ }
+
+ return new DataResponse($items);
+ }
+
+ /**
+ * Get the items for the widgets
+ *
+ * @param array<string, string> $sinceIds Array indexed by widget Ids, contains date/id from which we want the new items
+ * @param int $limit Limit number of result items per widget, not more than 30 are allowed
+ * @psalm-param int<1, 30> $limit
+ * @param list<string> $widgets Limit results to specific widgets
+ * @return DataResponse<Http::STATUS_OK, array<string, DashboardWidgetItems>, array{}>
+ *
+ * 200: Widget items returned
+ */
+ #[NoAdminRequired]
+ #[NoCSRFRequired]
+ #[ApiRoute(verb: 'GET', url: '/api/v2/widget-items')]
+ public function getWidgetItemsV2(array $sinceIds = [], int $limit = 7, array $widgets = []): DataResponse {
+ $items = [];
+ $widgets = $this->getShownWidgets($widgets);
+ foreach ($widgets as $widget) {
+ if ($widget instanceof IAPIWidgetV2) {
+ $items[$widget->getId()] = $widget
+ ->getItemsV2($this->userId, $sinceIds[$widget->getId()] ?? null, $limit)
+ ->jsonSerialize();
+ }
+ }
+
+ return new DataResponse($items);
+ }
+
+ /**
+ * Get the widgets
+ *
+ * @return DataResponse<Http::STATUS_OK, array<string, DashboardWidget>, array{}>
+ *
+ * 200: Widgets returned
+ */
+ #[NoAdminRequired]
+ #[NoCSRFRequired]
+ #[ApiRoute(verb: 'GET', url: '/api/v1/widgets')]
+ public function getWidgets(): DataResponse {
+ $widgets = $this->dashboardManager->getWidgets();
+
+ $items = array_map(function (IWidget $widget) {
+ $options = ($widget instanceof IOptionWidget) ? $widget->getWidgetOptions() : WidgetOptions::getDefault();
+ $data = [
+ 'id' => $widget->getId(),
+ 'title' => $widget->getTitle(),
+ 'order' => $widget->getOrder(),
+ 'icon_class' => $widget->getIconClass(),
+ 'icon_url' => ($widget instanceof IIconWidget) ? $widget->getIconUrl() : '',
+ 'widget_url' => $widget->getUrl(),
+ 'item_icons_round' => $options->withRoundItemIcons(),
+ 'item_api_versions' => [],
+ 'reload_interval' => 0,
+ ];
+ if ($widget instanceof IButtonWidget) {
+ $data += [
+ 'buttons' => array_map(function (WidgetButton $button) {
+ return [
+ 'type' => $button->getType(),
+ 'text' => $button->getText(),
+ 'link' => $button->getLink(),
+ ];
+ }, $widget->getWidgetButtons($this->userId)),
+ ];
+ }
+ if ($widget instanceof IReloadableWidget) {
+ $data['reload_interval'] = $widget->getReloadInterval();
+ }
+ if ($widget instanceof IAPIWidget) {
+ $data['item_api_versions'][] = 1;
+ }
+ if ($widget instanceof IAPIWidgetV2) {
+ $data['item_api_versions'][] = 2;
+ }
+ return $data;
+ }, $widgets);
+
+ return new DataResponse($items);
+ }
+
+ /**
+ * Get the layout
+ *
+ * @return DataResponse<Http::STATUS_OK, array{layout: list<string>}, array{}>
+ *
+ * 200: Layout returned
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'GET', url: '/api/v3/layout')]
+ public function getLayout(): DataResponse {
+ return new DataResponse(['layout' => $this->service->getLayout()]);
+ }
+
+ /**
+ * Update the layout
+ *
+ * @param list<string> $layout The new layout
+ * @return DataResponse<Http::STATUS_OK, array{layout: list<string>}, array{}>
+ *
+ * 200: Statuses updated successfully
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'POST', url: '/api/v3/layout')]
+ public function updateLayout(array $layout): DataResponse {
+ $this->config->setUserValue($this->userId, 'dashboard', 'layout', implode(',', $layout));
+ return new DataResponse(['layout' => $layout]);
+ }
+
+ /**
+ * Get the statuses
+ *
+ * @return DataResponse<Http::STATUS_OK, array{statuses: list<string>}, array{}>
+ *
+ * 200: Statuses returned
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'GET', url: '/api/v3/statuses')]
+ public function getStatuses(): DataResponse {
+ return new DataResponse(['statuses' => $this->service->getStatuses()]);
+ }
+
+ /**
+ * Update the statuses
+ *
+ * @param list<string> $statuses The new statuses
+ * @return DataResponse<Http::STATUS_OK, array{statuses: list<string>}, array{}>
+ *
+ * 200: Statuses updated successfully
+ */
+ #[NoAdminRequired]
+ #[ApiRoute(verb: 'POST', url: '/api/v3/statuses')]
+ public function updateStatuses(array $statuses): DataResponse {
+ $this->config->setUserValue($this->userId, 'dashboard', 'statuses', implode(',', $statuses));
+ return new DataResponse(['statuses' => $statuses]);
+ }
+}
diff --git a/apps/dashboard/lib/Controller/DashboardController.php b/apps/dashboard/lib/Controller/DashboardController.php
new file mode 100644
index 00000000000..da7e0901115
--- /dev/null
+++ b/apps/dashboard/lib/Controller/DashboardController.php
@@ -0,0 +1,87 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Dashboard\Controller;
+
+use OCA\Dashboard\Service\DashboardService;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\FrontpageRoute;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
+use OCP\AppFramework\Http\Attribute\OpenAPI;
+use OCP\AppFramework\Http\FeaturePolicy;
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\AppFramework\Services\IInitialState;
+use OCP\Dashboard\IIconWidget;
+use OCP\Dashboard\IManager;
+use OCP\Dashboard\IWidget;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\IConfig;
+use OCP\IL10N;
+use OCP\IRequest;
+use OCP\Util;
+
+#[OpenAPI(scope: OpenAPI::SCOPE_IGNORE)]
+class DashboardController extends Controller {
+
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ private IInitialState $initialState,
+ private IEventDispatcher $eventDispatcher,
+ private IManager $dashboardManager,
+ private IConfig $config,
+ private IL10N $l10n,
+ private ?string $userId,
+ private DashboardService $service,
+ ) {
+ parent::__construct($appName, $request);
+ }
+
+ /**
+ * @return TemplateResponse
+ */
+ #[NoCSRFRequired]
+ #[NoAdminRequired]
+ #[FrontpageRoute(verb: 'GET', url: '/')]
+ public function index(): TemplateResponse {
+ Util::addStyle('dashboard', 'dashboard');
+ Util::addScript('dashboard', 'main', 'theming');
+
+ $widgets = array_map(function (IWidget $widget) {
+ return [
+ 'id' => $widget->getId(),
+ 'title' => $widget->getTitle(),
+ 'iconClass' => $widget->getIconClass(),
+ 'iconUrl' => $widget instanceof IIconWidget ? $widget->getIconUrl() : '',
+ 'url' => $widget->getUrl()
+ ];
+ }, $this->dashboardManager->getWidgets());
+
+ $this->initialState->provideInitialState('panels', $widgets);
+ $this->initialState->provideInitialState('statuses', $this->service->getStatuses());
+ $this->initialState->provideInitialState('layout', $this->service->getLayout());
+ $this->initialState->provideInitialState('appStoreEnabled', $this->config->getSystemValueBool('appstoreenabled', true));
+ $this->initialState->provideInitialState('firstRun', $this->config->getUserValue($this->userId, 'dashboard', 'firstRun', '1') === '1');
+ $this->initialState->provideInitialState('birthdate', $this->service->getBirthdate());
+ $this->config->setUserValue($this->userId, 'dashboard', 'firstRun', '0');
+
+ $response = new TemplateResponse('dashboard', 'index', [
+ 'id-app-content' => '#app-dashboard',
+ 'id-app-navigation' => null,
+ 'pageTitle' => $this->l10n->t('Dashboard'),
+ ]);
+
+ // For the weather widget we should allow the geolocation
+ $featurePolicy = new FeaturePolicy();
+ $featurePolicy->addAllowedGeoLocationDomain('\'self\'');
+ $response->setFeaturePolicy($featurePolicy);
+
+ return $response;
+ }
+}
diff --git a/apps/dashboard/lib/ResponseDefinitions.php b/apps/dashboard/lib/ResponseDefinitions.php
new file mode 100644
index 00000000000..be5a4d56883
--- /dev/null
+++ b/apps/dashboard/lib/ResponseDefinitions.php
@@ -0,0 +1,46 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Dashboard;
+
+/**
+ * @psalm-type DashboardWidget = array{
+ * id: string,
+ * title: string,
+ * order: int,
+ * icon_class: string,
+ * icon_url: string,
+ * widget_url: ?string,
+ * item_icons_round: bool,
+ * item_api_versions: list<int>,
+ * reload_interval: int,
+ * buttons?: list<array{
+ * type: string,
+ * text: string,
+ * link: string,
+ * }>,
+ * }
+ *
+ * @psalm-type DashboardWidgetItem = array{
+ * subtitle: string,
+ * title: string,
+ * link: string,
+ * iconUrl: string,
+ * overlayIconUrl: string,
+ * sinceId: string,
+ * }
+ *
+ * @psalm-type DashboardWidgetItems = array{
+ * items: list<DashboardWidgetItem>,
+ * emptyContentMessage: string,
+ * halfEmptyContentMessage: string,
+ * }
+ */
+class ResponseDefinitions {
+}
diff --git a/apps/dashboard/lib/Service/DashboardService.php b/apps/dashboard/lib/Service/DashboardService.php
new file mode 100644
index 00000000000..bb5333c2cc7
--- /dev/null
+++ b/apps/dashboard/lib/Service/DashboardService.php
@@ -0,0 +1,71 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OCA\Dashboard\Service;
+
+use JsonException;
+use OCP\Accounts\IAccountManager;
+use OCP\Accounts\PropertyDoesNotExistException;
+use OCP\IConfig;
+use OCP\IUserManager;
+
+class DashboardService {
+ public function __construct(
+ private IConfig $config,
+ private ?string $userId,
+ private IUserManager $userManager,
+ private IAccountManager $accountManager,
+ ) {
+
+ }
+
+ /**
+ * @return list<string>
+ */
+ public function getLayout(): array {
+ $systemDefault = $this->config->getAppValue('dashboard', 'layout', 'recommendations,spreed,mail,calendar');
+ return array_values(array_filter(explode(',', $this->config->getUserValue($this->userId, 'dashboard', 'layout', $systemDefault)), fn (string $value) => $value !== ''));
+ }
+
+ /**
+ * @return list<string>
+ */
+ public function getStatuses() {
+ $configStatuses = $this->config->getUserValue($this->userId, 'dashboard', 'statuses', '');
+ try {
+ // Parse the old format
+ /** @var array<string, bool> $statuses */
+ $statuses = json_decode($configStatuses, true, 512, JSON_THROW_ON_ERROR);
+ // We avoid getting an empty array as it will not produce an object in UI's JS
+ return array_keys(array_filter($statuses, static fn (bool $value) => $value));
+ } catch (JsonException $e) {
+ return array_values(array_filter(explode(',', $configStatuses), fn (string $value) => $value !== ''));
+ }
+ }
+
+ public function getBirthdate(): string {
+ if ($this->userId === null) {
+ return '';
+ }
+
+ $user = $this->userManager->get($this->userId);
+ if ($user === null) {
+ return '';
+ }
+
+ $account = $this->accountManager->getAccount($user);
+
+ try {
+ $birthdate = $account->getProperty(IAccountManager::PROPERTY_BIRTHDATE);
+ } catch (PropertyDoesNotExistException) {
+ return '';
+ }
+
+ return $birthdate->getValue();
+ }
+}
diff --git a/apps/dashboard/openapi.json b/apps/dashboard/openapi.json
new file mode 100644
index 00000000000..775d21adb50
--- /dev/null
+++ b/apps/dashboard/openapi.json
@@ -0,0 +1,764 @@
+{
+ "openapi": "3.0.3",
+ "info": {
+ "title": "dashboard",
+ "version": "0.0.1",
+ "description": "Dashboard app",
+ "license": {
+ "name": "agpl"
+ }
+ },
+ "components": {
+ "securitySchemes": {
+ "basic_auth": {
+ "type": "http",
+ "scheme": "basic"
+ },
+ "bearer_auth": {
+ "type": "http",
+ "scheme": "bearer"
+ }
+ },
+ "schemas": {
+ "OCSMeta": {
+ "type": "object",
+ "required": [
+ "status",
+ "statuscode"
+ ],
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "statuscode": {
+ "type": "integer"
+ },
+ "message": {
+ "type": "string"
+ },
+ "totalitems": {
+ "type": "string"
+ },
+ "itemsperpage": {
+ "type": "string"
+ }
+ }
+ },
+ "Widget": {
+ "type": "object",
+ "required": [
+ "id",
+ "title",
+ "order",
+ "icon_class",
+ "icon_url",
+ "widget_url",
+ "item_icons_round",
+ "item_api_versions",
+ "reload_interval"
+ ],
+ "properties": {
+ "id": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "order": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "icon_class": {
+ "type": "string"
+ },
+ "icon_url": {
+ "type": "string"
+ },
+ "widget_url": {
+ "type": "string",
+ "nullable": true
+ },
+ "item_icons_round": {
+ "type": "boolean"
+ },
+ "item_api_versions": {
+ "type": "array",
+ "items": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ "reload_interval": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "buttons": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "type",
+ "text",
+ "link"
+ ],
+ "properties": {
+ "type": {
+ "type": "string"
+ },
+ "text": {
+ "type": "string"
+ },
+ "link": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ },
+ "WidgetItem": {
+ "type": "object",
+ "required": [
+ "subtitle",
+ "title",
+ "link",
+ "iconUrl",
+ "overlayIconUrl",
+ "sinceId"
+ ],
+ "properties": {
+ "subtitle": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "link": {
+ "type": "string"
+ },
+ "iconUrl": {
+ "type": "string"
+ },
+ "overlayIconUrl": {
+ "type": "string"
+ },
+ "sinceId": {
+ "type": "string"
+ }
+ }
+ },
+ "WidgetItems": {
+ "type": "object",
+ "required": [
+ "items",
+ "emptyContentMessage",
+ "halfEmptyContentMessage"
+ ],
+ "properties": {
+ "items": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/WidgetItem"
+ }
+ },
+ "emptyContentMessage": {
+ "type": "string"
+ },
+ "halfEmptyContentMessage": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "paths": {
+ "/ocs/v2.php/apps/dashboard/api/v1/widget-items": {
+ "get": {
+ "operationId": "dashboard_api-get-widget-items",
+ "summary": "Get the items for the widgets",
+ "tags": [
+ "dashboard_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "sinceIds",
+ "in": "query",
+ "description": "Array indexed by widget Ids, contains date/id from which we want the new items",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Limit number of result items per widget",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 7,
+ "minimum": 1,
+ "maximum": 30
+ }
+ },
+ {
+ "name": "widgets[]",
+ "in": "query",
+ "description": "Limit results to specific widgets",
+ "schema": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Widget items returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/WidgetItem"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/dashboard/api/v2/widget-items": {
+ "get": {
+ "operationId": "dashboard_api-get-widget-items-v2",
+ "summary": "Get the items for the widgets",
+ "tags": [
+ "dashboard_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "sinceIds",
+ "in": "query",
+ "description": "Array indexed by widget Ids, contains date/id from which we want the new items",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "limit",
+ "in": "query",
+ "description": "Limit number of result items per widget, not more than 30 are allowed",
+ "schema": {
+ "type": "integer",
+ "format": "int64",
+ "default": 7,
+ "minimum": 1,
+ "maximum": 30
+ }
+ },
+ {
+ "name": "widgets[]",
+ "in": "query",
+ "description": "Limit results to specific widgets",
+ "schema": {
+ "type": "array",
+ "default": [],
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Widget items returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/WidgetItems"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/dashboard/api/v1/widgets": {
+ "get": {
+ "operationId": "dashboard_api-get-widgets",
+ "summary": "Get the widgets",
+ "tags": [
+ "dashboard_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Widgets returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/Widget"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/dashboard/api/v3/layout": {
+ "get": {
+ "operationId": "dashboard_api-get-layout",
+ "summary": "Get the layout",
+ "tags": [
+ "dashboard_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Layout returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "layout"
+ ],
+ "properties": {
+ "layout": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "dashboard_api-update-layout",
+ "summary": "Update the layout",
+ "tags": [
+ "dashboard_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "layout"
+ ],
+ "properties": {
+ "layout": {
+ "type": "array",
+ "description": "The new layout",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Statuses updated successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "layout"
+ ],
+ "properties": {
+ "layout": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/ocs/v2.php/apps/dashboard/api/v3/statuses": {
+ "get": {
+ "operationId": "dashboard_api-get-statuses",
+ "summary": "Get the statuses",
+ "tags": [
+ "dashboard_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Statuses returned",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "statuses"
+ ],
+ "properties": {
+ "statuses": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "dashboard_api-update-statuses",
+ "summary": "Update the statuses",
+ "tags": [
+ "dashboard_api"
+ ],
+ "security": [
+ {
+ "bearer_auth": []
+ },
+ {
+ "basic_auth": []
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "statuses"
+ ],
+ "properties": {
+ "statuses": {
+ "type": "array",
+ "description": "The new statuses",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "OCS-APIRequest",
+ "in": "header",
+ "description": "Required to be true for the API request to pass",
+ "required": true,
+ "schema": {
+ "type": "boolean",
+ "default": true
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Statuses updated successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "required": [
+ "ocs"
+ ],
+ "properties": {
+ "ocs": {
+ "type": "object",
+ "required": [
+ "meta",
+ "data"
+ ],
+ "properties": {
+ "meta": {
+ "$ref": "#/components/schemas/OCSMeta"
+ },
+ "data": {
+ "type": "object",
+ "required": [
+ "statuses"
+ ],
+ "properties": {
+ "statuses": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/apps/dashboard/openapi.json.license b/apps/dashboard/openapi.json.license
new file mode 100644
index 00000000000..83559daa9dc
--- /dev/null
+++ b/apps/dashboard/openapi.json.license
@@ -0,0 +1,2 @@
+SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+SPDX-License-Identifier: AGPL-3.0-or-later \ No newline at end of file
diff --git a/apps/dashboard/src/DashboardApp.vue b/apps/dashboard/src/DashboardApp.vue
new file mode 100644
index 00000000000..afc874be2c9
--- /dev/null
+++ b/apps/dashboard/src/DashboardApp.vue
@@ -0,0 +1,761 @@
+<!--
+ - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+ -->
+<template>
+ <main id="app-dashboard">
+ <h2>{{ greeting.text }}</h2>
+ <ul class="statuses">
+ <li v-for="status in sortedRegisteredStatus"
+ :id="'status-' + status"
+ :key="status">
+ <div :ref="'status-' + status" />
+ </li>
+ </ul>
+
+ <Draggable v-model="layout"
+ class="panels"
+ v-bind="{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}"
+ handle=".panel--header"
+ @end="saveLayout">
+ <template v-for="panelId in layout">
+ <div v-if="isApiWidgetV2(panels[panelId].id)"
+ :key="`${panels[panelId].id}-v2`"
+ class="panel">
+ <div class="panel--header">
+ <h2>
+ <img v-if="apiWidgets[panels[panelId].id].icon_url" :src="apiWidgets[panels[panelId].id].icon_url" alt="">
+ <span v-else :class="apiWidgets[panels[panelId].id].icon_class" aria-hidden="true" />
+ {{ apiWidgets[panels[panelId].id].title }}
+ </h2>
+ </div>
+ <div class="panel--content">
+ <ApiDashboardWidget :widget="apiWidgets[panels[panelId].id]"
+ :data="apiWidgetItems[panels[panelId].id]"
+ :loading="loadingItems" />
+ </div>
+ </div>
+ <div v-else :key="panels[panelId].id" class="panel">
+ <div class="panel--header">
+ <h2>
+ <span :class="panels[panelId].iconClass" aria-hidden="true" />
+ {{ panels[panelId].title }}
+ </h2>
+ </div>
+ <div class="panel--content" :class="{ loading: !panels[panelId].mounted }">
+ <div :ref="panels[panelId].id" :data-id="panels[panelId].id" />
+ </div>
+ </div>
+ </template>
+ </Draggable>
+
+ <div class="footer">
+ <NcButton @click="showModal">
+ <template #icon>
+ <Pencil :size="20" />
+ </template>
+ {{ t('dashboard', 'Customize') }}
+ </NcButton>
+ </div>
+
+ <NcModal v-if="modal" size="large" @close="closeModal">
+ <div class="modal__content">
+ <h2>{{ t('dashboard', 'Edit widgets') }}</h2>
+ <ol class="panels">
+ <li v-for="status in sortedAllStatuses" :key="status" :class="'panel-' + status">
+ <input :id="'status-checkbox-' + status"
+ type="checkbox"
+ class="checkbox"
+ :checked="isStatusActive(status)"
+ @input="updateStatusCheckbox(status, $event.target.checked)">
+ <label :for="'status-checkbox-' + status">
+ <NcUserStatusIcon v-if="status === 'status'" status="online" aria-hidden="true" />
+ <span v-else :class="statusInfo[status].icon" aria-hidden="true" />
+ {{ statusInfo[status].text }}
+ </label>
+ </li>
+ </ol>
+ <Draggable v-model="layout"
+ class="panels"
+ tag="ol"
+ v-bind="{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}"
+ handle=".draggable"
+ @end="saveLayout">
+ <li v-for="panel in sortedPanels" :key="panel.id" :class="'panel-' + panel.id">
+ <input :id="'panel-checkbox-' + panel.id"
+ type="checkbox"
+ class="checkbox"
+ :checked="isActive(panel)"
+ @input="updateCheckbox(panel, $event.target.checked)">
+ <label :for="'panel-checkbox-' + panel.id" :class="{ draggable: isActive(panel) }">
+ <img v-if="panel.iconUrl" alt="" :src="panel.iconUrl">
+ <span v-else :class="panel.iconClass" aria-hidden="true" />
+ {{ panel.title }}
+ </label>
+ </li>
+ </Draggable>
+
+ <a v-if="isAdmin && appStoreEnabled" :href="appStoreUrl" class="button">{{ t('dashboard', 'Get more widgets from the App Store') }}</a>
+
+ <div v-if="statuses.weather && isStatusActive('weather')">
+ <h2>{{ t('dashboard', 'Weather service') }}</h2>
+ <p>
+ {{ t('dashboard', 'For your privacy, the weather data is requested by your Nextcloud server on your behalf so the weather service receives no personal information.') }}
+ </p>
+ <p class="credits--end">
+ <a href="https://api.met.no/doc/TermsOfService" target="_blank" rel="noopener">{{ t('dashboard', 'Weather data from Met.no') }}</a>,
+ <a href="https://wiki.osmfoundation.org/wiki/Privacy_Policy" target="_blank" rel="noopener">{{ t('dashboard', 'geocoding with Nominatim') }}</a>,
+ <a href="https://www.opentopodata.org/#public-api" target="_blank" rel="noopener">{{ t('dashboard', 'elevation data from OpenTopoData') }}</a>.
+ </p>
+ </div>
+ </div>
+ </NcModal>
+ </main>
+</template>
+
+<script>
+import { generateUrl, generateOcsUrl } from '@nextcloud/router'
+import { getCurrentUser } from '@nextcloud/auth'
+import { loadState } from '@nextcloud/initial-state'
+import axios from '@nextcloud/axios'
+import NcButton from '@nextcloud/vue/components/NcButton'
+import Draggable from 'vuedraggable'
+import NcModal from '@nextcloud/vue/components/NcModal'
+import NcUserStatusIcon from '@nextcloud/vue/components/NcUserStatusIcon'
+import Pencil from 'vue-material-design-icons/Pencil.vue'
+import Vue from 'vue'
+
+import isMobile from './mixins/isMobile.js'
+import ApiDashboardWidget from './components/ApiDashboardWidget.vue'
+
+const panels = loadState('dashboard', 'panels')
+const firstRun = loadState('dashboard', 'firstRun')
+const birthdate = new Date(loadState('dashboard', 'birthdate'))
+
+const statusInfo = {
+ weather: {
+ text: t('dashboard', 'Weather'),
+ icon: 'icon-weather-status',
+ },
+ status: {
+ text: t('dashboard', 'Status'),
+ },
+}
+
+export default {
+ name: 'DashboardApp',
+ components: {
+ ApiDashboardWidget,
+ NcButton,
+ Draggable,
+ NcModal,
+ Pencil,
+ NcUserStatusIcon,
+ },
+ mixins: [
+ isMobile,
+ ],
+
+ data() {
+ return {
+ isAdmin: getCurrentUser().isAdmin,
+ timer: new Date(),
+ registeredStatus: [],
+ callbacks: {},
+ callbacksStatus: {},
+ allCallbacksStatus: {},
+ statusInfo,
+ enabledStatuses: loadState('dashboard', 'statuses'),
+ panels,
+ firstRun,
+ displayName: getCurrentUser()?.displayName,
+ uid: getCurrentUser()?.uid,
+ layout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),
+ modal: false,
+ appStoreUrl: generateUrl('/settings/apps/dashboard'),
+ appStoreEnabled: loadState('dashboard', 'appStoreEnabled', true),
+ statuses: {},
+ apiWidgets: [],
+ apiWidgetItems: {},
+ loadingItems: true,
+ birthdate,
+ }
+ },
+ computed: {
+ greeting() {
+ const time = this.timer.getHours()
+ const isBirthday = this.birthdate instanceof Date
+ && this.birthdate.getMonth() === this.timer.getMonth()
+ && this.birthdate.getDate() === this.timer.getDate()
+
+ // Determine part of the day
+ let partOfDay
+ if (isBirthday) {
+ partOfDay = 'birthday'
+ } else if (time >= 22 || time < 5) {
+ partOfDay = 'night'
+ } else if (time >= 18) {
+ partOfDay = 'evening'
+ } else if (time >= 12) {
+ partOfDay = 'afternoon'
+ } else {
+ partOfDay = 'morning'
+ }
+
+ // Define the greetings
+ const good = {
+ morning: {
+ generic: t('dashboard', 'Good morning'),
+ withName: t('dashboard', 'Good morning, {name}', { name: this.displayName }, undefined, { escape: false }),
+ },
+ afternoon: {
+ generic: t('dashboard', 'Good afternoon'),
+ withName: t('dashboard', 'Good afternoon, {name}', { name: this.displayName }, undefined, { escape: false }),
+ },
+ evening: {
+ generic: t('dashboard', 'Good evening'),
+ withName: t('dashboard', 'Good evening, {name}', { name: this.displayName }, undefined, { escape: false }),
+ },
+ night: {
+ // Don't use "Good night" as it's not a greeting
+ generic: t('dashboard', 'Hello'),
+ withName: t('dashboard', 'Hello, {name}', { name: this.displayName }, undefined, { escape: false }),
+ },
+ birthday: {
+ generic: t('dashboard', 'Happy birthday 🥳🤩🎂🎉'),
+ withName: t('dashboard', 'Happy birthday, {name} 🥳🤩🎂🎉', { name: this.displayName }, undefined, { escape: false }),
+ },
+ }
+
+ // Figure out which greeting to show
+ const shouldShowName = this.displayName && this.uid !== this.displayName
+ return { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }
+ },
+
+ isActive() {
+ return (panel) => this.layout.indexOf(panel.id) > -1
+ },
+ isStatusActive() {
+ return (status) => this.enabledStatuses.findIndex((s) => s === status) !== -1
+ },
+
+ sortedAllStatuses() {
+ return Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)
+ },
+ sortedPanels() {
+ return Object.values(this.panels).sort((a, b) => {
+ const indexA = this.layout.indexOf(a.id)
+ const indexB = this.layout.indexOf(b.id)
+ if (indexA === -1 || indexB === -1) {
+ return indexB - indexA || a.id - b.id
+ }
+ return indexA - indexB || a.id - b.id
+ })
+ },
+ sortedRegisteredStatus() {
+ return this.registeredStatus.slice().sort(this.sortStatuses)
+ },
+ },
+
+ watch: {
+ callbacks() {
+ this.rerenderPanels()
+ },
+ callbacksStatus() {
+ for (const app in this.callbacksStatus) {
+ const element = this.$refs['status-' + app]
+ if (this.statuses[app] && this.statuses[app].mounted) {
+ continue
+ }
+ if (element) {
+ this.callbacksStatus[app](element[0])
+ Vue.set(this.statuses, app, { mounted: true })
+ } else {
+ console.error('Failed to register panel in the frontend as no backend data was provided for ' + app)
+ }
+ }
+ },
+ },
+
+ async created() {
+ await this.fetchApiWidgets()
+
+ const apiWidgetIdsToFetch = Object
+ .values(this.apiWidgets)
+ .filter(widget => this.isApiWidgetV2(widget.id) && this.layout.includes(widget.id))
+ .map(widget => widget.id)
+ await Promise.all(apiWidgetIdsToFetch.map(id => this.fetchApiWidgetItems([id], true)))
+
+ for (const widget of Object.values(this.apiWidgets)) {
+ if (widget.reload_interval > 0) {
+ setInterval(async () => {
+ if (!this.layout.includes(widget.id)) {
+ return
+ }
+
+ await this.fetchApiWidgetItems([widget.id], true)
+ }, widget.reload_interval * 1000)
+ }
+ }
+ },
+ mounted() {
+ this.updateSkipLink()
+ window.addEventListener('scroll', this.handleScroll)
+
+ setInterval(() => {
+ this.timer = new Date()
+ }, 30000)
+
+ if (this.firstRun) {
+ window.addEventListener('scroll', this.disableFirstrunHint)
+ }
+ },
+ destroyed() {
+ window.removeEventListener('scroll', this.handleScroll)
+ },
+
+ methods: {
+ /**
+ * Method to register panels that will be called by the integrating apps
+ *
+ * @param {string} app The unique app id for the widget
+ * @param {Function} callback The callback function to register a panel which gets the DOM element passed as parameter
+ */
+ register(app, callback) {
+ Vue.set(this.callbacks, app, callback)
+ },
+ registerStatus(app, callback) {
+ // always save callbacks in case user enables the status later
+ Vue.set(this.allCallbacksStatus, app, callback)
+ // register only if status is enabled or missing from config
+ if (this.isStatusActive(app)) {
+ this.registeredStatus.push(app)
+ this.$nextTick(() => {
+ Vue.set(this.callbacksStatus, app, callback)
+ })
+ }
+ },
+ rerenderPanels() {
+ for (const app in this.callbacks) {
+ // TODO: Properly rerender v2 widgets
+ if (this.isApiWidgetV2(this.panels[app].id)) {
+ continue
+ }
+
+ const element = this.$refs[app]
+ if (this.layout.indexOf(app) === -1) {
+ continue
+ }
+ if (this.panels[app] && this.panels[app].mounted) {
+ continue
+ }
+ if (element) {
+ this.callbacks[app](element[0], {
+ widget: this.panels[app],
+ })
+ Vue.set(this.panels[app], 'mounted', true)
+ } else {
+ console.error('Failed to register panel in the frontend as no backend data was provided for ' + app)
+ }
+ }
+ },
+ saveLayout() {
+ axios.post(generateOcsUrl('/apps/dashboard/api/v3/layout'), {
+ layout: this.layout,
+ })
+ },
+ saveStatuses() {
+ axios.post(generateOcsUrl('/apps/dashboard/api/v3/statuses'), {
+ statuses: this.enabledStatuses,
+ })
+ },
+ showModal() {
+ this.modal = true
+ this.firstRun = false
+ },
+ closeModal() {
+ this.modal = false
+ },
+ updateCheckbox(panel, currentValue) {
+ const index = this.layout.indexOf(panel.id)
+ if (!currentValue && index > -1) {
+ this.layout.splice(index, 1)
+ } else {
+ this.layout.push(panel.id)
+ if (this.isApiWidgetV2(panel.id)) {
+ this.fetchApiWidgetItems([panel.id], true)
+ }
+ }
+ Vue.set(this.panels[panel.id], 'mounted', false)
+ this.saveLayout()
+ this.$nextTick(() => this.rerenderPanels())
+ },
+ disableFirstrunHint() {
+ window.removeEventListener('scroll', this.disableFirstrunHint)
+ setTimeout(() => {
+ this.firstRun = false
+ }, 1000)
+ },
+ updateSkipLink() {
+ // Make sure "Skip to main content" link points to the app content
+ document.getElementsByClassName('skip-navigation')[0].setAttribute('href', '#app-dashboard')
+ },
+ updateStatusCheckbox(app, checked) {
+ if (checked) {
+ this.enableStatus(app)
+ } else {
+ this.disableStatus(app)
+ }
+ },
+ enableStatus(app) {
+ this.enabledStatuses.push(app)
+ this.registerStatus(app, this.allCallbacksStatus[app])
+ this.saveStatuses()
+ },
+ disableStatus(app) {
+ const i = this.enabledStatuses.findIndex((s) => s === app)
+ if (i !== -1) {
+ this.enabledStatuses.splice(i, 1)
+ }
+ const j = this.registeredStatus.findIndex((s) => s === app)
+ if (j !== -1) {
+ this.registeredStatus.splice(j, 1)
+ Vue.set(this.statuses, app, { mounted: false })
+ this.$nextTick(() => {
+ Vue.delete(this.callbacksStatus, app)
+ })
+ }
+ this.saveStatuses()
+ },
+ sortStatuses(a, b) {
+ const al = a.toLowerCase()
+ const bl = b.toLowerCase()
+ return al > bl
+ ? 1
+ : al < bl
+ ? -1
+ : 0
+ },
+ handleScroll() {
+ if (window.scrollY > 70) {
+ document.body.classList.add('dashboard--scrolled')
+ } else {
+ document.body.classList.remove('dashboard--scrolled')
+ }
+ },
+ async fetchApiWidgets() {
+ const { data } = await axios.get(generateOcsUrl('/apps/dashboard/api/v1/widgets'))
+ this.apiWidgets = data.ocs.data
+ },
+ async fetchApiWidgetItems(widgetIds, merge = false) {
+ try {
+ const url = generateOcsUrl('/apps/dashboard/api/v2/widget-items')
+ const params = new URLSearchParams(widgetIds.map(id => ['widgets[]', id]))
+ const response = await axios.get(`${url}?${params.toString()}`)
+ const widgetItems = response.data.ocs.data
+ if (merge) {
+ this.apiWidgetItems = Object.assign({}, this.apiWidgetItems, widgetItems)
+ } else {
+ this.apiWidgetItems = widgetItems
+ }
+ } finally {
+ this.loadingItems = false
+ }
+ },
+ isApiWidgetV2(id) {
+ for (const widget of Object.values(this.apiWidgets)) {
+ if (widget.id === id && widget.item_api_versions.includes(2)) {
+ return true
+ }
+ }
+ return false
+ },
+ },
+}
+</script>
+
+<style lang="scss" scoped>
+#app-dashboard {
+ width: 100%;
+ min-height: 100%;
+ background-size: cover;
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+
+ > h2 {
+ // this is shown directly on the background image / color
+ color: var(--color-background-plain-text);
+ text-align: center;
+ font-size: 32px;
+ line-height: 130%;
+ padding: 1rem 0;
+ }
+}
+
+.panels {
+ width: auto;
+ margin: auto;
+ max-width: 1800px;
+ display: flex;
+ justify-content: center;
+ flex-direction: row;
+ align-items: flex-start;
+ flex-wrap: wrap;
+}
+
+.panel, .panels > div {
+ // Ensure the maxcontrast color is set for the background
+ --color-text-maxcontrast: var(--color-text-maxcontrast-background-blur, var(--color-main-text));
+ width: 320px;
+ max-width: 100%;
+ margin: 16px;
+ align-self: stretch;
+ background-color: var(--color-main-background-blur);
+ -webkit-backdrop-filter: var(--filter-background-blur);
+ backdrop-filter: var(--filter-background-blur);
+ border-radius: var(--border-radius-container-large);
+
+ #body-user.theme--highcontrast & {
+ border: 2px solid var(--color-border);
+ }
+
+ &.sortable-ghost {
+ opacity: 0.1;
+ }
+
+ & > .panel--header {
+ display: flex;
+ z-index: 1;
+ top: 50px;
+ padding: 16px;
+ cursor: grab;
+
+ &,
+ :deep(*) {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ }
+
+ &:active {
+ cursor: grabbing;
+ }
+
+ a {
+ flex-grow: 1;
+ }
+
+ > h2 {
+ display: block;
+ align-items: center;
+ flex-grow: 1;
+ margin: 0;
+ font-size: 20px;
+ line-height: 24px;
+ font-weight: bold;
+ padding: 16px 8px;
+ height: 56px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ cursor: grab;
+
+ img,
+ span {
+ background-size: 32px;
+ width: 32px;
+ height: 32px;
+ background-position: center;
+ float: left;
+ margin-top: -6px;
+ margin-inline: 6px 16px;
+ }
+
+ img {
+ filter: var(--background-invert-if-dark);
+ }
+ }
+ }
+
+ & > .panel--content {
+ margin: 0 16px 16px 16px;
+ height: 424px;
+ // We specifically do not want scrollbars inside widgets
+ overflow: visible;
+ }
+
+ // No need to extend height of widgets if only one column is shown
+ @media only screen and (max-width: 709px) {
+ & > .panel--content {
+ height: auto;
+ }
+ }
+}
+
+.footer {
+ display: flex;
+ justify-content: center;
+ transition: bottom var(--animation-slow) ease-in-out;
+ padding: 1rem 0;
+}
+
+.edit-panels {
+ display: inline-block;
+ margin:auto;
+ background-position: 16px center;
+ padding: 12px 16px;
+ padding-inline-start: 36px;
+ border-radius: var(--border-radius-pill);
+ max-width: 200px;
+ opacity: 1;
+ text-align: center;
+}
+
+.button,
+.button-vue,
+.edit-panels,
+.statuses :deep(.action-item .action-item__menutoggle),
+.statuses :deep(.action-item.action-item--open .action-item__menutoggle) {
+ // Ensure the maxcontrast color is set for the background
+ --color-text-maxcontrast: var(--color-text-maxcontrast-background-blur, var(--color-main-text));
+ background-color: var(--color-main-background-blur);
+ -webkit-backdrop-filter: var(--filter-background-blur);
+ backdrop-filter: var(--filter-background-blur);
+ opacity: 1 !important;
+
+ &:hover,
+ &:focus,
+ &:active {
+ background-color: var(--color-background-hover)!important;
+ }
+ &:focus-visible {
+ box-shadow: 0 0 0 4px var(--color-main-background) !important;
+ outline: 2px solid var(--color-main-text) !important;
+ }
+}
+
+.modal__content {
+ padding: 32px 16px;
+ text-align: center;
+
+ ol {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ list-style-type: none;
+ padding-bottom: 16px;
+ }
+ li {
+ label {
+ position: relative;
+ display: block;
+ padding: 48px 16px 14px 16px;
+ margin: 8px;
+ width: 140px;
+ background-color: var(--color-background-hover);
+ border: 2px solid var(--color-main-background);
+ border-radius: var(--border-radius-large);
+ text-align: start;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ img,
+ span {
+ position: absolute;
+ top: 16px;
+ width: 24px;
+ height: 24px;
+ background-size: 24px;
+ }
+
+ img {
+ filter: var(--background-invert-if-dark);
+ }
+
+ &:hover {
+ border-color: var(--color-primary-element);
+ }
+ }
+
+ // Do not invert status icons
+ &:not(.panel-status) label span {
+ filter: var(--background-invert-if-dark);
+ }
+
+ input[type='checkbox'].checkbox + label:before {
+ position: absolute;
+ inset-inline-end: 12px;
+ top: 16px;
+ }
+
+ input:focus + label {
+ border-color: var(--color-primary-element);
+ }
+ }
+
+ h2 {
+ font-weight: bold;
+ margin-top: 12px;
+ }
+
+ // Adjust design of 'Get more widgets' button
+ .button {
+ display: inline-block;
+ padding: 10px 16px;
+ margin: 0;
+ }
+
+ p {
+ max-width: 650px;
+ margin: 0 auto;
+
+ a:hover,
+ a:focus {
+ border-bottom: 2px solid var(--color-border);
+ }
+ }
+
+ .credits--end {
+ padding-bottom: 32px;
+ color: var(--color-text-maxcontrast);
+
+ a {
+ color: var(--color-text-maxcontrast);
+ }
+ }
+}
+
+.flip-list-move {
+ transition: transform var(--animation-slow);
+}
+
+.statuses {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ flex-wrap: wrap;
+ margin-bottom: 36px;
+
+ & > li {
+ margin: 8px;
+ }
+}
+</style>
+<style>
+html, body {
+ background-attachment: fixed;
+}
+
+#body-user #header {
+ position: fixed;
+}
+
+#content {
+ overflow: auto;
+}
+</style>
diff --git a/apps/dashboard/src/components/ApiDashboardWidget.vue b/apps/dashboard/src/components/ApiDashboardWidget.vue
new file mode 100644
index 00000000000..4aa8628fac8
--- /dev/null
+++ b/apps/dashboard/src/components/ApiDashboardWidget.vue
@@ -0,0 +1,116 @@
+<!--
+ - SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+ -->
+<template>
+ <NcDashboardWidget :items="items"
+ :show-more-label="showMoreLabel"
+ :show-more-url="showMoreUrl"
+ :loading="loading"
+ :show-items-and-empty-content="!!halfEmptyContentMessage"
+ :half-empty-content-message="halfEmptyContentMessage">
+ <template #default="{ item }">
+ <ApiDashboardWidgetItem :item="item" :icon-size="iconSize" :rounded-icons="widget.item_icons_round" />
+ </template>
+ <template #empty-content>
+ <NcEmptyContent v-if="items.length === 0"
+ :description="emptyContentMessage">
+ <template #icon>
+ <CheckIcon v-if="emptyContentMessage" :size="65" />
+ </template>
+ <template #action>
+ <NcButton v-if="setupButton" :href="setupButton.link">
+ {{ setupButton.text }}
+ </NcButton>
+ </template>
+ </NcEmptyContent>
+ </template>
+ </NcDashboardWidget>
+</template>
+
+<script>
+import NcButton from '@nextcloud/vue/components/NcButton'
+import NcDashboardWidget from '@nextcloud/vue/components/NcDashboardWidget'
+import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
+import CheckIcon from 'vue-material-design-icons/Check.vue'
+import ApiDashboardWidgetItem from './ApiDashboardWidgetItem.vue'
+
+export default {
+ name: 'ApiDashboardWidget',
+ components: {
+ ApiDashboardWidgetItem,
+ CheckIcon,
+ NcDashboardWidget,
+ NcEmptyContent,
+ NcButton,
+ },
+ props: {
+ widget: {
+ type: [Object, undefined],
+ default: undefined,
+ },
+ data: {
+ type: [Object, undefined],
+ default: undefined,
+ },
+ loading: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ iconSize: 44,
+ }
+ },
+ computed: {
+ /** @return {object[]} */
+ items() {
+ return this.data?.items ?? []
+ },
+
+ /** @return {string} */
+ emptyContentMessage() {
+ return this.data?.emptyContentMessage ?? ''
+ },
+
+ /** @return {string} */
+ halfEmptyContentMessage() {
+ return this.data?.halfEmptyContentMessage ?? ''
+ },
+
+ /** @return {object|undefined} */
+ newButton() {
+ // TODO: Render new button in the template
+ // I couldn't find a widget that makes use of the button. Furthermore, there is no convenient
+ // way to render such a button using the official widget component.
+ return this.widget?.buttons?.find(button => button.type === 'new')
+ },
+
+ /** @return {object|undefined} */
+ moreButton() {
+ return this.widget?.buttons?.find(button => button.type === 'more')
+ },
+
+ /** @return {object|undefined} */
+ setupButton() {
+ return this.widget?.buttons?.find(button => button.type === 'setup')
+ },
+
+ /** @return {string|undefined} */
+ showMoreLabel() {
+ return this.moreButton?.text
+ },
+
+ /** @return {string|undefined} */
+ showMoreUrl() {
+ return this.moreButton?.link
+ },
+ },
+ mounted() {
+ const size = window.getComputedStyle(document.body).getPropertyValue('--default-clickable-area')
+ const numeric = Number.parseFloat(size)
+ this.iconSize = Number.isNaN(numeric) ? 44 : numeric
+ },
+}
+</script>
diff --git a/apps/dashboard/src/components/ApiDashboardWidgetItem.vue b/apps/dashboard/src/components/ApiDashboardWidgetItem.vue
new file mode 100644
index 00000000000..2caa7868fb3
--- /dev/null
+++ b/apps/dashboard/src/components/ApiDashboardWidgetItem.vue
@@ -0,0 +1,68 @@
+<!--
+ - SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+ -->
+<script setup lang="ts">
+import { ref } from 'vue'
+import NcAvatar from '@nextcloud/vue/components/NcAvatar'
+import NcDashboardWidgetItem from '@nextcloud/vue/components/NcDashboardWidgetItem'
+import IconFile from 'vue-material-design-icons/File.vue'
+
+defineProps({
+ item: {
+ type: Object,
+ required: true,
+ },
+ iconSize: {
+ type: Number,
+ required: true,
+ },
+ roundedIcons: {
+ type: Boolean,
+ default: true,
+ },
+})
+
+/**
+ * True as soon as the image is loaded
+ */
+const imageLoaded = ref(false)
+/**
+ * True if the image failed to load and we should show a fallback
+ */
+const loadingImageFailed = ref(false)
+</script>
+
+<template>
+ <NcDashboardWidgetItem :target-url="item.link"
+ :overlay-icon-url="item.overlayIconUrl ? item.overlayIconUrl : ''"
+ :main-text="item.title"
+ :sub-text="item.subtitle">
+ <template #avatar>
+ <template v-if="item.iconUrl">
+ <NcAvatar v-if="roundedIcons"
+ :size="iconSize"
+ :url="item.iconUrl" />
+ <template v-else>
+ <img v-show="!loadingImageFailed"
+ alt=""
+ class="api-dashboard-widget-item__icon"
+ :class="{'hidden-visually': !imageLoaded }"
+ :src="item.iconUrl"
+ @error="loadingImageFailed = true"
+ @load="imageLoaded = true">
+ <!-- Placeholder while the image is loaded and also the fallback if the URL is broken -->
+ <IconFile v-if="!imageLoaded"
+ :size="iconSize" />
+ </template>
+ </template>
+ </template>
+ </NcDashboardWidgetItem>
+</template>
+
+<style scoped>
+.api-dashboard-widget-item__icon {
+ height: var(--default-clickable-area);
+ width: var(--default-clickable-area);
+}
+</style>
diff --git a/apps/dashboard/src/main.js b/apps/dashboard/src/main.js
new file mode 100644
index 00000000000..68d896a3a17
--- /dev/null
+++ b/apps/dashboard/src/main.js
@@ -0,0 +1,26 @@
+/**
+ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import { getCSPNonce } from '@nextcloud/auth'
+import { t } from '@nextcloud/l10n'
+import VTooltip from '@nextcloud/vue/directives/Tooltip'
+import Vue from 'vue'
+
+import DashboardApp from './DashboardApp.vue'
+
+// eslint-disable-next-line camelcase
+__webpack_nonce__ = getCSPNonce()
+
+Vue.directive('Tooltip', VTooltip)
+
+Vue.prototype.t = t
+
+const Dashboard = Vue.extend(DashboardApp)
+const Instance = new Dashboard({}).$mount('#app-content-vue')
+
+window.OCA.Dashboard = {
+ register: (app, callback) => Instance.register(app, callback),
+ registerStatus: (app, callback) => Instance.registerStatus(app, callback),
+}
diff --git a/apps/dashboard/src/mixins/isMobile.js b/apps/dashboard/src/mixins/isMobile.js
new file mode 100644
index 00000000000..d4062f8c7e0
--- /dev/null
+++ b/apps/dashboard/src/mixins/isMobile.js
@@ -0,0 +1,28 @@
+/**
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+export default {
+ data() {
+ return {
+ isMobile: this._isMobile(),
+ }
+ },
+ beforeMount() {
+ window.addEventListener('resize', this._onResize)
+ },
+ beforeDestroy() {
+ window.removeEventListener('resize', this._onResize)
+ },
+ methods: {
+ _onResize() {
+ // Update mobile mode
+ this.isMobile = this._isMobile()
+ },
+ _isMobile() {
+ // check if content width is under 768px
+ return document.documentElement.clientWidth < 768
+ },
+ },
+}
diff --git a/apps/dashboard/templates/index.php b/apps/dashboard/templates/index.php
new file mode 100644
index 00000000000..53222710b98
--- /dev/null
+++ b/apps/dashboard/templates/index.php
@@ -0,0 +1,8 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+?>
+<div id="app-content-vue"></div>
diff --git a/apps/dashboard/tests/DashboardServiceTest.php b/apps/dashboard/tests/DashboardServiceTest.php
new file mode 100644
index 00000000000..ebcd06cdf03
--- /dev/null
+++ b/apps/dashboard/tests/DashboardServiceTest.php
@@ -0,0 +1,100 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Dashboard\Tests;
+
+use OC\Accounts\Account;
+use OCA\Dashboard\Service\DashboardService;
+use OCP\Accounts\IAccountManager;
+use OCP\IConfig;
+use OCP\IUser;
+use OCP\IUserManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use Test\TestCase;
+
+class DashboardServiceTest extends TestCase {
+
+ private IConfig&MockObject $config;
+ private IUserManager&MockObject $userManager;
+ private IAccountManager&MockObject $accountManager;
+ private DashboardService $service;
+
+ protected function setUp(): void {
+ parent::setUp();
+
+ $this->config = $this->createMock(IConfig::class);
+ $this->userManager = $this->createMock(IUserManager::class);
+ $this->accountManager = $this->createMock(IAccountManager::class);
+
+ $this->service = new DashboardService(
+ $this->config,
+ 'alice',
+ $this->userManager,
+ $this->accountManager,
+ );
+ }
+
+ public function testGetBirthdate(): void {
+ $user = $this->createMock(IUser::class);
+ $this->userManager->method('get')
+ ->willReturn($user);
+
+ $account = new Account($user);
+ $account->setProperty(
+ IAccountManager::PROPERTY_BIRTHDATE,
+ '2024-12-10T00:00:00.000Z',
+ IAccountManager::SCOPE_LOCAL,
+ IAccountManager::VERIFIED,
+ );
+
+ $this->accountManager->method('getAccount')
+ ->willReturn($account);
+
+ $birthdate = $this->service->getBirthdate();
+
+ $this->assertEquals('2024-12-10T00:00:00.000Z', $birthdate);
+ }
+
+ public function testGetBirthdatePropertyDoesNotExist(): void {
+ $user = $this->createMock(IUser::class);
+ $this->userManager->method('get')
+ ->willReturn($user);
+
+ $account = new Account($user);
+ $this->accountManager->method('getAccount')
+ ->willReturn($account);
+
+ $birthdate = $this->service->getBirthdate();
+
+ $this->assertEquals('', $birthdate);
+ }
+
+ public function testGetBirthdateUserNotFound(): void {
+ $this->userManager->method('get')
+ ->willReturn(null);
+
+ $birthdate = $this->service->getBirthdate();
+
+ $this->assertEquals('', $birthdate);
+ }
+
+ public function testGetBirthdateNoUserId(): void {
+ $service = new DashboardService(
+ $this->config,
+ null,
+ $this->userManager,
+ $this->accountManager,
+ );
+
+ $birthdate = $service->getBirthdate();
+
+ $this->assertEquals('', $birthdate);
+ }
+
+}