diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3ff0a141480..33a6f2e4e76 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -52,6 +52,9 @@ RUN { \ echo "xdebug.start_with_request=yes"; \ } >> /etc/php/8.3/apache2/conf.d/20-xdebug.ini +# Increase PHP memory limit to 512mb +RUN sed -i 's/memory_limit = .*/memory_limit = 512M/' /etc/php/8.3/apache2/php.ini + # Docker RUN apt-get -y install \ apt-transport-https \ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4caf4b2cd19..f1983388e2f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,7 +1,7 @@ # App maintainers /apps/admin_audit/appinfo/info.xml @luka-nextcloud @blizzz /apps/cloud_federation_api/appinfo/info.xml @mejo- -/apps/comments/appinfo/info.xml @marcelklehr @Pytal +/apps/comments/appinfo/info.xml @edward-ly @Pytal /apps/contactsinteraction/appinfo/info.xml @kesselb @miaulalala @ChristophWurst @GretaD @hamza221 @st3iny /apps/dashboard/appinfo/info.xml @julien-nc @juliushaertl /apps/dav/lib/CalDAV @ChristophWurst @miaulalala @tcitworld diff --git a/.github/workflows/phpunit-oci.yml b/.github/workflows/phpunit-oci.yml index 041d2175271..0fd06f7879d 100644 --- a/.github/workflows/phpunit-oci.yml +++ b/.github/workflows/phpunit-oci.yml @@ -51,15 +51,21 @@ jobs: runs-on: ubuntu-latest needs: changes - if: needs.changes.outputs.src != 'false' && ${{ github.repository_owner != 'nextcloud-gmbh' }} + if: ${{ needs.changes.outputs.src != 'false' && github.repository_owner != 'nextcloud-gmbh' }} strategy: + fail-fast: false matrix: - oracle-versions: ['11'] - php-versions: ['8.1', '8.2', '8.3'] include: - - php-versions: '8.3' + - oracle-versions: '11' + php-versions: '8.1' + - oracle-versions: '18' + php-versions: '8.1' coverage: ${{ github.event_name != 'pull_request' }} + - oracle-versions: '21' + php-versions: '8.2' + - oracle-versions: '23' + php-versions: '8.3' name: Oracle ${{ matrix.oracle-versions }} (PHP ${{ matrix.php-versions }}) - database tests @@ -71,23 +77,21 @@ jobs: options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3 oracle: - image: ghcr.io/gvenzl/oracle-xe:${{ matrix.oracle-versions }} + image: ghcr.io/gvenzl/oracle-${{ matrix.oracle-versions < 23 && 'xe' || 'free' }}:${{ matrix.oracle-versions }} # Provide passwords and other environment variables to container env: - ORACLE_RANDOM_PASSWORD: true - APP_USER: oc_autotest - APP_USER_PASSWORD: nextcloud + ORACLE_PASSWORD: oracle # Forward Oracle port ports: - - 4444:1521/tcp + - 1521:1521 # Provide healthcheck script options for startup options: >- --health-cmd healthcheck.sh - --health-interval 10s - --health-timeout 5s + --health-interval 20s + --health-timeout 10s --health-retries 10 steps: @@ -111,13 +115,11 @@ jobs: run: composer i - name: Set up Nextcloud - env: - DB_PORT: 4444 run: | mkdir data cp tests/redis.config.php config/ cp tests/preseed-config.php config/config.php - ./occ maintenance:install --verbose --database=oci --database-name=XE --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=oc_autotest --database-pass=nextcloud --admin-user admin --admin-pass admin + ./occ maintenance:install --verbose --database=oci --database-name=${{ matrix.oracle-versions < 23 && 'XE' || 'FREE' }} --database-host=127.0.0.1 --database-port=1521 --database-user=system --database-pass=oracle --admin-user admin --admin-pass admin php -f tests/enable_all.php | grep -i -C9999 error && echo "Error during app setup" && exit 1 || exit 0 - name: PHPUnit diff --git a/3rdparty b/3rdparty index 72598ddd873..e153540bcc9 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit 72598ddd873afd5643d62ddfc4d962d04b2b4519 +Subproject commit e153540bcc9c2dca7742763e071b07b97d3d55b8 diff --git a/apps/comments/l10n/sl.js b/apps/comments/l10n/sl.js index ab3702955e1..f0bc060da05 100644 --- a/apps/comments/l10n/sl.js +++ b/apps/comments/l10n/sl.js @@ -9,11 +9,14 @@ OC.L10N.register( "%1$s commented on %2$s" : "%1$s napiše opombo na %2$s", "{author} commented on {file}" : "{author} napiše opombo na {file}", "Comments for files" : "Vpisane so opombe k datotekam", + "You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "Uporabnik, ki je sicer že izbrisan, vas omenja v opombi k datoteki »{file}«.", "{user} mentioned you in a comment on \"{file}\"" : "{user} vas omeni v opombi k datoteki »{file}«", "Files app plugin to add comments to files" : "Vstavek programa Datoteke za dodajanje opomb k datotekam", "Edit comment" : "Uredi opombo", "Delete comment" : "Izbriši opombo", "Cancel edit" : "Prekliči urejanje", + "New comment" : "Nova opomba", + "Write a comment …" : "Dopišite opombo ...", "Post comment" : "Objavi opombo", "@ for mentions, : for emoji, / for smart picker" : "@ za omenjanje osebe, : za izris izraznih ikon, / za pametni izbirnik", "Could not reload comments" : "Opomb ni mogoče posodobiti", @@ -29,6 +32,7 @@ OC.L10N.register( "An error occurred while trying to delete the comment" : "Prišlo je do napake med brisanjem opombe", "An error occurred while trying to create the comment" : "Prišlo je do napake med ustvarjanjem opombe", "You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Uporabnik, ki je sicer že izbrisan, vas omeni v opombi k datoteki »{file}«.", + "Write a message …" : "Zapišite sporočilo ...", "\"@\" for mentions, \":\" for emoji, \"/\" for smart picker" : "» @ « za omenjanje, » : « za izrazne ikone, » / « za pametni izbirnik", "_%n unread comment_::_%n unread comments_" : ["%n neprebrana opomba","%n neprebrani opombi","%n neprebrane opombe","%n neprebranih opomb"] }, diff --git a/apps/comments/l10n/sl.json b/apps/comments/l10n/sl.json index 3bb2f9b4501..71c1c96ff3c 100644 --- a/apps/comments/l10n/sl.json +++ b/apps/comments/l10n/sl.json @@ -7,11 +7,14 @@ "%1$s commented on %2$s" : "%1$s napiše opombo na %2$s", "{author} commented on {file}" : "{author} napiše opombo na {file}", "Comments for files" : "Vpisane so opombe k datotekam", + "You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "Uporabnik, ki je sicer že izbrisan, vas omenja v opombi k datoteki »{file}«.", "{user} mentioned you in a comment on \"{file}\"" : "{user} vas omeni v opombi k datoteki »{file}«", "Files app plugin to add comments to files" : "Vstavek programa Datoteke za dodajanje opomb k datotekam", "Edit comment" : "Uredi opombo", "Delete comment" : "Izbriši opombo", "Cancel edit" : "Prekliči urejanje", + "New comment" : "Nova opomba", + "Write a comment …" : "Dopišite opombo ...", "Post comment" : "Objavi opombo", "@ for mentions, : for emoji, / for smart picker" : "@ za omenjanje osebe, : za izris izraznih ikon, / za pametni izbirnik", "Could not reload comments" : "Opomb ni mogoče posodobiti", @@ -27,6 +30,7 @@ "An error occurred while trying to delete the comment" : "Prišlo je do napake med brisanjem opombe", "An error occurred while trying to create the comment" : "Prišlo je do napake med ustvarjanjem opombe", "You were mentioned on \"{file}\", in a comment by a user that has since been deleted" : "Uporabnik, ki je sicer že izbrisan, vas omeni v opombi k datoteki »{file}«.", + "Write a message …" : "Zapišite sporočilo ...", "\"@\" for mentions, \":\" for emoji, \"/\" for smart picker" : "» @ « za omenjanje, » : « za izrazne ikone, » / « za pametni izbirnik", "_%n unread comment_::_%n unread comments_" : ["%n neprebrana opomba","%n neprebrani opombi","%n neprebrane opombe","%n neprebranih opomb"] },"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);" diff --git a/apps/contactsinteraction/l10n/hu.js b/apps/contactsinteraction/l10n/hu.js index b57afec42b5..2fe82456f05 100644 --- a/apps/contactsinteraction/l10n/hu.js +++ b/apps/contactsinteraction/l10n/hu.js @@ -3,6 +3,8 @@ OC.L10N.register( { "Recently contacted" : "Legutóbbi kapcsolatfelvételek", "Contacts Interaction" : "Kapcsolatfelvételek", + "Manages interaction between accounts and contacts" : "A fiókok és a kapcsolataik közötti interakciót kezeli", + "Collect data about accounts and contacts interactions and provide an address book for the data" : "Adatokat gyűjt a fiókok és kapcsolataik közötti interakciókról, és címjegyzéket biztosít az adatokhoz", "Manages interaction between users and contacts" : "A felhasználók és a kapcsolataik közötti interakciót kezeli", "Collect data about user and contacts interactions and provide an address book for the data" : "Adatokat gyűjt a felhasználók és kapcsolataik közötti interakciókról, és címjegyzéket biztosít az adatokhoz" }, diff --git a/apps/contactsinteraction/l10n/hu.json b/apps/contactsinteraction/l10n/hu.json index 4554dd95ab9..f40008aff72 100644 --- a/apps/contactsinteraction/l10n/hu.json +++ b/apps/contactsinteraction/l10n/hu.json @@ -1,6 +1,8 @@ { "translations": { "Recently contacted" : "Legutóbbi kapcsolatfelvételek", "Contacts Interaction" : "Kapcsolatfelvételek", + "Manages interaction between accounts and contacts" : "A fiókok és a kapcsolataik közötti interakciót kezeli", + "Collect data about accounts and contacts interactions and provide an address book for the data" : "Adatokat gyűjt a fiókok és kapcsolataik közötti interakciókról, és címjegyzéket biztosít az adatokhoz", "Manages interaction between users and contacts" : "A felhasználók és a kapcsolataik közötti interakciót kezeli", "Collect data about user and contacts interactions and provide an address book for the data" : "Adatokat gyűjt a felhasználók és kapcsolataik közötti interakciókról, és címjegyzéket biztosít az adatokhoz" },"pluralForm" :"nplurals=2; plural=(n != 1);" diff --git a/apps/contactsinteraction/l10n/sl.js b/apps/contactsinteraction/l10n/sl.js index 57bd205a2ea..8a19a9db385 100644 --- a/apps/contactsinteraction/l10n/sl.js +++ b/apps/contactsinteraction/l10n/sl.js @@ -3,6 +3,8 @@ OC.L10N.register( { "Recently contacted" : "Nedavno v stiku", "Contacts Interaction" : "Povezave stikov", + "Manages interaction between accounts and contacts" : "Upravlja povezave med uporabniki in stiki", + "Collect data about accounts and contacts interactions and provide an address book for the data" : "Zbiranje podatkov o povezavah med uporabniki in stiki ter pripravljanje imenika zbranih podatkov povezav.", "Manages interaction between users and contacts" : "Upravlja povezave med uporabniki in stiki", "Collect data about user and contacts interactions and provide an address book for the data" : "Zbiranje podatkov o povezavah med uporabniki in stiki ter pripravljanje imenika zbranih podatkov povezav." }, diff --git a/apps/contactsinteraction/l10n/sl.json b/apps/contactsinteraction/l10n/sl.json index fee04d99667..ca661af4f67 100644 --- a/apps/contactsinteraction/l10n/sl.json +++ b/apps/contactsinteraction/l10n/sl.json @@ -1,6 +1,8 @@ { "translations": { "Recently contacted" : "Nedavno v stiku", "Contacts Interaction" : "Povezave stikov", + "Manages interaction between accounts and contacts" : "Upravlja povezave med uporabniki in stiki", + "Collect data about accounts and contacts interactions and provide an address book for the data" : "Zbiranje podatkov o povezavah med uporabniki in stiki ter pripravljanje imenika zbranih podatkov povezav.", "Manages interaction between users and contacts" : "Upravlja povezave med uporabniki in stiki", "Collect data about user and contacts interactions and provide an address book for the data" : "Zbiranje podatkov o povezavah med uporabniki in stiki ter pripravljanje imenika zbranih podatkov povezav." },"pluralForm" :"nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);" diff --git a/apps/contactsinteraction/lib/Db/CardSearchDao.php b/apps/contactsinteraction/lib/Db/CardSearchDao.php index 962f9ff768b..0929cb7efa0 100644 --- a/apps/contactsinteraction/lib/Db/CardSearchDao.php +++ b/apps/contactsinteraction/lib/Db/CardSearchDao.php @@ -29,24 +29,24 @@ class CardSearchDao { $cardQuery = $this->db->getQueryBuilder(); $propQuery = $this->db->getQueryBuilder(); - $propOr = $propQuery->expr()->orX(); + $additionalWheres = []; if ($uid !== null) { - $propOr->add($propQuery->expr()->andX( + $additionalWheres[] = $propQuery->expr()->andX( $propQuery->expr()->eq('name', $cardQuery->createNamedParameter('UID')), $propQuery->expr()->eq('value', $cardQuery->createNamedParameter($uid)) - )); + ); } if ($email !== null) { - $propOr->add($propQuery->expr()->andX( + $additionalWheres[] = $propQuery->expr()->andX( $propQuery->expr()->eq('name', $cardQuery->createNamedParameter('EMAIL')), $propQuery->expr()->eq('value', $cardQuery->createNamedParameter($email)) - )); + ); } if ($cloudId !== null) { - $propOr->add($propQuery->expr()->andX( + $additionalWheres[] = $propQuery->expr()->andX( $propQuery->expr()->eq('name', $cardQuery->createNamedParameter('CLOUD')), $propQuery->expr()->eq('value', $cardQuery->createNamedParameter($cloudId)) - )); + ); } $addressbooksQuery->selectDistinct('id') ->from('addressbooks') @@ -54,8 +54,12 @@ class CardSearchDao { $propQuery->selectDistinct('cardid') ->from('cards_properties') ->where($propQuery->expr()->in('addressbookid', $propQuery->createFunction($addressbooksQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY)) - ->andWhere($propOr) ->groupBy('cardid'); + + if (!empty($additionalWheres)) { + $propQuery->andWhere($propQuery->expr()->orX(...$additionalWheres)); + } + $cardQuery->select('carddata') ->from('cards') ->where($cardQuery->expr()->in('id', $cardQuery->createFunction($propQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY)) diff --git a/apps/contactsinteraction/lib/Db/RecentContactMapper.php b/apps/contactsinteraction/lib/Db/RecentContactMapper.php index e0b2ac723fb..c835b5287c8 100644 --- a/apps/contactsinteraction/lib/Db/RecentContactMapper.php +++ b/apps/contactsinteraction/lib/Db/RecentContactMapper.php @@ -61,23 +61,25 @@ class RecentContactMapper extends QBMapper { ?string $cloudId): array { $qb = $this->db->getQueryBuilder(); - $or = $qb->expr()->orX(); + $additionalWheres = []; if ($uid !== null) { - $or->add($qb->expr()->eq('uid', $qb->createNamedParameter($uid))); + $additionalWheres[] = $qb->expr()->eq('uid', $qb->createNamedParameter($uid)); } if ($email !== null) { - $or->add($qb->expr()->eq('email', $qb->createNamedParameter($email))); + $additionalWheres[] = $qb->expr()->eq('email', $qb->createNamedParameter($email)); } if ($cloudId !== null) { - $or->add($qb->expr()->eq('federated_cloud_id', $qb->createNamedParameter($cloudId))); + $additionalWheres[] = $qb->expr()->eq('federated_cloud_id', $qb->createNamedParameter($cloudId)); } $select = $qb ->select('*') ->from($this->getTableName()) - ->where($or) - ->andWhere($qb->expr()->eq('actor_uid', $qb->createNamedParameter($user->getUID()))); + ->where($qb->expr()->eq('actor_uid', $qb->createNamedParameter($user->getUID()))); + if (!empty($additionalWheres)) { + $select->andWhere($select->expr()->orX(...$additionalWheres)); + } return $this->findEntities($select); } diff --git a/apps/dashboard/l10n/sl.js b/apps/dashboard/l10n/sl.js index ebabe20b8c0..222bfc31864 100644 --- a/apps/dashboard/l10n/sl.js +++ b/apps/dashboard/l10n/sl.js @@ -3,6 +3,7 @@ OC.L10N.register( { "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.", "\"{title} icon\"" : "»Ikona {title}«", "Customize" : "Prilagodi", "Edit widgets" : "Izbor gradnikov", diff --git a/apps/dashboard/l10n/sl.json b/apps/dashboard/l10n/sl.json index 2dfdde07885..fd9a33d9d43 100644 --- a/apps/dashboard/l10n/sl.json +++ b/apps/dashboard/l10n/sl.json @@ -1,6 +1,7 @@ { "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.", "\"{title} icon\"" : "»Ikona {title}«", "Customize" : "Prilagodi", "Edit widgets" : "Izbor gradnikov", diff --git a/apps/dav/appinfo/v1/publicwebdav.php b/apps/dav/appinfo/v1/publicwebdav.php index 5ef383e1dd5..38753374150 100644 --- a/apps/dav/appinfo/v1/publicwebdav.php +++ b/apps/dav/appinfo/v1/publicwebdav.php @@ -87,6 +87,7 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct $view = new \OC\Files\View($node->getPath()); $filesDropPlugin->setView($view); + $filesDropPlugin->setShare($share); return $view; }); diff --git a/apps/dav/appinfo/v2/publicremote.php b/apps/dav/appinfo/v2/publicremote.php index bdc4169dd4e..44cf4214505 100644 --- a/apps/dav/appinfo/v2/publicremote.php +++ b/apps/dav/appinfo/v2/publicremote.php @@ -116,6 +116,7 @@ $server = $serverFactory->createServer($baseuri, $requestUri, $authPlugin, funct $view = new View($node->getPath()); $filesDropPlugin->setView($view); + $filesDropPlugin->setShare($share); return $view; }); diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index ff1fb0637ad..90b09822c33 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -59,6 +59,9 @@ return array( 'OCA\\DAV\\CalDAV\\CalendarProvider' => $baseDir . '/../lib/CalDAV/CalendarProvider.php', 'OCA\\DAV\\CalDAV\\CalendarRoot' => $baseDir . '/../lib/CalDAV/CalendarRoot.php', 'OCA\\DAV\\CalDAV\\EventComparisonService' => $baseDir . '/../lib/CalDAV/EventComparisonService.php', + 'OCA\\DAV\\CalDAV\\EventReader' => $baseDir . '/../lib/CalDAV/EventReader.php', + 'OCA\\DAV\\CalDAV\\EventReaderRDate' => $baseDir . '/../lib/CalDAV/EventReaderRDate.php', + 'OCA\\DAV\\CalDAV\\EventReaderRRule' => $baseDir . '/../lib/CalDAV/EventReaderRRule.php', 'OCA\\DAV\\CalDAV\\FreeBusy\\FreeBusyGenerator' => $baseDir . '/../lib/CalDAV/FreeBusy/FreeBusyGenerator.php', 'OCA\\DAV\\CalDAV\\ICSExportPlugin\\ICSExportPlugin' => $baseDir . '/../lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php', 'OCA\\DAV\\CalDAV\\IRestorable' => $baseDir . '/../lib/CalDAV/IRestorable.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 081915e95f2..aa9eef72659 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -74,6 +74,9 @@ class ComposerStaticInitDAV 'OCA\\DAV\\CalDAV\\CalendarProvider' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarProvider.php', 'OCA\\DAV\\CalDAV\\CalendarRoot' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarRoot.php', 'OCA\\DAV\\CalDAV\\EventComparisonService' => __DIR__ . '/..' . '/../lib/CalDAV/EventComparisonService.php', + 'OCA\\DAV\\CalDAV\\EventReader' => __DIR__ . '/..' . '/../lib/CalDAV/EventReader.php', + 'OCA\\DAV\\CalDAV\\EventReaderRDate' => __DIR__ . '/..' . '/../lib/CalDAV/EventReaderRDate.php', + 'OCA\\DAV\\CalDAV\\EventReaderRRule' => __DIR__ . '/..' . '/../lib/CalDAV/EventReaderRRule.php', 'OCA\\DAV\\CalDAV\\FreeBusy\\FreeBusyGenerator' => __DIR__ . '/..' . '/../lib/CalDAV/FreeBusy/FreeBusyGenerator.php', 'OCA\\DAV\\CalDAV\\ICSExportPlugin\\ICSExportPlugin' => __DIR__ . '/..' . '/../lib/CalDAV/ICSExportPlugin/ICSExportPlugin.php', 'OCA\\DAV\\CalDAV\\IRestorable' => __DIR__ . '/..' . '/../lib/CalDAV/IRestorable.php', diff --git a/apps/dav/l10n/ar.js b/apps/dav/l10n/ar.js index ddf3e3aeacf..ab6981257b0 100644 --- a/apps/dav/l10n/ar.js +++ b/apps/dav/l10n/ar.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "الوصف: %s", "Where: %s" : "المكان: %s", "%1$s via %2$s" : "%1$s عبر %2$s", + "In a %1$s on %2$s for the entire day" : "عند %1$s في %2$s كامل اليوم", + "In a %1$s on %2$s between %3$s - %4$s" : "عند %1$s في %2$s بين %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "عند %1$s %2$s في %3$s كامل اليوم", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "عند %1$s %2$s في %3$s بين %4$s - %5$s", + "Could not generate when statement" : "يتعذّر تكوين عبارة \"متى\"", + "Every Day for the entire day" : "كل يوم كامل اليوم", + "Every Day for the entire day until %1$s" : "كل يوم كامل اليوم حتى %1$s", + "Every Day between %1$s - %2$s" : "كل يوم بين%1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "كل يوم بين %1$s - %2$s حتى %3$s", + "Every %1$d Days for the entire day" : "كل أيام %1$d كامل اليوم", + "Every %1$d Days for the entire day until %2$s" : "كل أيام %1$d كل اليوم حتى %2$s", + "Every %1$d Days between %2$s - %3$s" : "كل أيام %1$d بين %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "كل أيام %1$d بين %2$s - %3$s حتى %4$s", + "Could not generate event recurrence statement" : "يتعذّر توليد عبارة تكرار الحدث", + "Every Week on %1$s for the entire day" : "كل أسبوع أيام %1$s كامل اليوم", + "Every Week on %1$s for the entire day until %2$s" : "كل أسبوع أيام %1$s كامل اليوم حتى %2$s", + "Every Week on %1$s between %2$s - %3$s" : "كل أسبوع أيام %1$s بين %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "كل أسبوع أيام %1$s بين %2$s - %3$s حتى %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "كل%1$d أسبوع أيام %2$s كامل اليوم", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "كل %1$d أسبوع أيام %2$s كامل اليوم حتى %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "كل %1$d أسبوع أيام %2$s بين %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "كل %1$d أسبوع %2$s بين %3$s - %4$s حتى %5$s", + "Every Month on the %1$s for the entire day" : "كل شهر أيام %1$s كامل اليوم", + "Every Month on the %1$s for the entire day until %2$s" : "كل شهر أيام %1$s كامل اليوم حتى %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "كل شهر أيام %1$s بين %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "كل شهر أيام %1$s بين %2$s - %3$s حتى %4$s", + "Every %1$d Months on the %2$s for the entire day" : "كل %1$d شهر أيام %2$s كامل اليوم", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "كل %1$d شهر أيام %2$s كامل اليوم حتى %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "كل %1$d شهر أيام %2$s بين %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "كل %1$d شهر أيام %2$s بين %3$s - %4$s حتى %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "كل سنة في %1$s أيام %2$s كامل اليوم", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "كل سنة في %1$s أيام %2$s كامل اليوم حتى %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "كل سنة في %1$s أيام %2$s بين %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "كل سنة في %1$s أيام %2$s بين %3$s - %4$s حتى %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "كل %1$d سنة في %2$s أيام %3$s كامل اليوم", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "كل %1$d سنة في %2$s أيام %3$s كامل اليوم حتى %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "كل %1$d سنة في %2$s أيام %3$s بين %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "كل %1$d سنة في %2$s أيام %3$s بين %4$s - %5$s حتى %6$s", + "On specific dates for the entire day until %1$s" : "في تورايخ محددة كامل اليوم حتى%1$s", + "On specific dates between %1$s - %2$s until %3$s" : "في تواريخ محددة بين %1$s - %2$s حتى %3$s", + "In a %1$s on %2$s" : "عند %1$s في %2$s", + "In a %1$s on %2$s then on %3$s" : "عند %1$s في %2$s ثم في%3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "عند %1$s في %2$s ثم في %3$s و %4$s", + "In %1$s %2$s on %3$s" : "عند %1$s %2$s في %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "عند %1$s %2$s في %3$s ثم في %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "عند %1$s %2$s في %3$s ثم في %4$s و%5$s", + "Could not generate next recurrence statement" : "يتعذّر توليد عبارة التكرار التالي", "Cancelled: %1$s" : "مُلغىً: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" تمّ إلغاؤه", "Re: %1$s" : "إعادة: %1$s", @@ -86,14 +133,44 @@ OC.L10N.register( "Organizer:" : "تنظيم:", "Attendees:" : "الحُضُور:", "Title:" : "العنوان:", - "Date and time:" : "التاريخ و الوقت:", + "When:" : "متى:", "Location:" : "المكان :", "Link:" : "الرابط:", + "Occurring:" : "التكرار:", "Accept" : "قبول", "Decline" : "رفض", "More options …" : "مزيد مِن الخيارات…", "More options at %s" : "خيارات أخرى في %s", - "Contacts" : "المُراسِلون", + "Monday" : "الإثنين", + "Tuesday" : "الثلاثاء", + "Wednesday" : "الأربعاء", + "Thursday" : "الخميس", + "Friday" : "الجمعة", + "Saturday" : "السبت", + "Sunday" : "الأحد", + "January" : "يناير", + "February" : "فبراير", + "March" : "مارس", + "April" : "أبريل", + "May" : "مايو", + "June" : "يونيو", + "July" : "يوليو", + "August" : "اغسطس", + "September" : "سبتمبر", + "October" : "أكتوبر", + "November" : "نوفمبر", + "December" : "ديسمبر", + "First" : "أول", + "Second" : "ثاني", + "Third" : "ثالث", + "Fourth" : "رابع", + "Fifty" : "خامس", + "Last" : "آخِر", + "Second Last" : "ما قبل الأخير", + "Third Last" : "الثالث من الآخِر", + "Fourth Last" : "الرابع من الآخِر", + "Fifty Last" : "الخامس من الآخِر", + "Contacts" : "جهات الاتصال", "{actor} created address book {addressbook}" : "{actor} أنشأ دفتر العناوين {addressbook}", "You created address book {addressbook}" : "أنت أنشأت دفتر العناوين {addressbook}", "{actor} deleted address book {addressbook}" : "{actor} قام بحذف دفتر العناوين {addressbook}", @@ -176,20 +253,13 @@ OC.L10N.register( "No working hours set" : "لم يتم تحديد ساعات العمل", "Add slot" : "أضِف فُرَضَةً slot زمنيّةً", "Weekdays" : "أيام الأسبوع", - "Monday" : "الإثنين", - "Tuesday" : "الثلاثاء", - "Wednesday" : "الأربعاء", - "Thursday" : "الخميس", - "Friday" : "الجمعة", - "Saturday" : "السبت", - "Sunday" : "الأحد", "Pick a start time for {dayName}" : "إختَر وقت البدء ليوم {dayName}", "Pick a end time for {dayName}" : "إختَر وقت الانتهاء ليوم {dayName}", - "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "قم بتعيين حالة المستخدم تلقائيًا على \"عدم الإزعاج\" خارج نطاق أوقات التوافر لكتم جميع الإشعارات", - "Failed to load availability" : "إخفاق في تحميل أوقات التوافر", - "Saved availability" : "تمّ حفظ أوقات التوافر", - "Failed to save availability" : "إخفاق في حفظ أوقات التواجد", - "Availability" : "أوقات التواجد availability", + "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "قم بتعيين حالة المستخدم تلقائيًا على \"عدم الإزعاج\" خارج نطاق أوقات التواجد لكتم جميع الإشعارات", + "Failed to load availability" : "إخفاق في تحميل أوقات التواجد", + "Saved availability" : "تمّ حفظ أوقات التواجد", + "Failed to save availability" : "تعذّر حفظ أوقات التواجد", + "Availability" : "أوقات التواجد ", "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "إذا قمت بضبط ساعات عملك، سيرى الآخرون متى تكون خارج المكتب عندما يقومون بحجز اجتماع معك.", "Absence" : "غياب", "Configure your next absence period." : "قٌم بتهيئة فترة غيابك القادمة.", diff --git a/apps/dav/l10n/ar.json b/apps/dav/l10n/ar.json index fc6d2b43c0d..fefc511eb90 100644 --- a/apps/dav/l10n/ar.json +++ b/apps/dav/l10n/ar.json @@ -70,6 +70,53 @@ "Description: %s" : "الوصف: %s", "Where: %s" : "المكان: %s", "%1$s via %2$s" : "%1$s عبر %2$s", + "In a %1$s on %2$s for the entire day" : "عند %1$s في %2$s كامل اليوم", + "In a %1$s on %2$s between %3$s - %4$s" : "عند %1$s في %2$s بين %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "عند %1$s %2$s في %3$s كامل اليوم", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "عند %1$s %2$s في %3$s بين %4$s - %5$s", + "Could not generate when statement" : "يتعذّر تكوين عبارة \"متى\"", + "Every Day for the entire day" : "كل يوم كامل اليوم", + "Every Day for the entire day until %1$s" : "كل يوم كامل اليوم حتى %1$s", + "Every Day between %1$s - %2$s" : "كل يوم بين%1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "كل يوم بين %1$s - %2$s حتى %3$s", + "Every %1$d Days for the entire day" : "كل أيام %1$d كامل اليوم", + "Every %1$d Days for the entire day until %2$s" : "كل أيام %1$d كل اليوم حتى %2$s", + "Every %1$d Days between %2$s - %3$s" : "كل أيام %1$d بين %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "كل أيام %1$d بين %2$s - %3$s حتى %4$s", + "Could not generate event recurrence statement" : "يتعذّر توليد عبارة تكرار الحدث", + "Every Week on %1$s for the entire day" : "كل أسبوع أيام %1$s كامل اليوم", + "Every Week on %1$s for the entire day until %2$s" : "كل أسبوع أيام %1$s كامل اليوم حتى %2$s", + "Every Week on %1$s between %2$s - %3$s" : "كل أسبوع أيام %1$s بين %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "كل أسبوع أيام %1$s بين %2$s - %3$s حتى %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "كل%1$d أسبوع أيام %2$s كامل اليوم", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "كل %1$d أسبوع أيام %2$s كامل اليوم حتى %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "كل %1$d أسبوع أيام %2$s بين %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "كل %1$d أسبوع %2$s بين %3$s - %4$s حتى %5$s", + "Every Month on the %1$s for the entire day" : "كل شهر أيام %1$s كامل اليوم", + "Every Month on the %1$s for the entire day until %2$s" : "كل شهر أيام %1$s كامل اليوم حتى %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "كل شهر أيام %1$s بين %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "كل شهر أيام %1$s بين %2$s - %3$s حتى %4$s", + "Every %1$d Months on the %2$s for the entire day" : "كل %1$d شهر أيام %2$s كامل اليوم", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "كل %1$d شهر أيام %2$s كامل اليوم حتى %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "كل %1$d شهر أيام %2$s بين %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "كل %1$d شهر أيام %2$s بين %3$s - %4$s حتى %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "كل سنة في %1$s أيام %2$s كامل اليوم", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "كل سنة في %1$s أيام %2$s كامل اليوم حتى %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "كل سنة في %1$s أيام %2$s بين %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "كل سنة في %1$s أيام %2$s بين %3$s - %4$s حتى %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "كل %1$d سنة في %2$s أيام %3$s كامل اليوم", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "كل %1$d سنة في %2$s أيام %3$s كامل اليوم حتى %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "كل %1$d سنة في %2$s أيام %3$s بين %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "كل %1$d سنة في %2$s أيام %3$s بين %4$s - %5$s حتى %6$s", + "On specific dates for the entire day until %1$s" : "في تورايخ محددة كامل اليوم حتى%1$s", + "On specific dates between %1$s - %2$s until %3$s" : "في تواريخ محددة بين %1$s - %2$s حتى %3$s", + "In a %1$s on %2$s" : "عند %1$s في %2$s", + "In a %1$s on %2$s then on %3$s" : "عند %1$s في %2$s ثم في%3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "عند %1$s في %2$s ثم في %3$s و %4$s", + "In %1$s %2$s on %3$s" : "عند %1$s %2$s في %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "عند %1$s %2$s في %3$s ثم في %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "عند %1$s %2$s في %3$s ثم في %4$s و%5$s", + "Could not generate next recurrence statement" : "يتعذّر توليد عبارة التكرار التالي", "Cancelled: %1$s" : "مُلغىً: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" تمّ إلغاؤه", "Re: %1$s" : "إعادة: %1$s", @@ -84,14 +131,44 @@ "Organizer:" : "تنظيم:", "Attendees:" : "الحُضُور:", "Title:" : "العنوان:", - "Date and time:" : "التاريخ و الوقت:", + "When:" : "متى:", "Location:" : "المكان :", "Link:" : "الرابط:", + "Occurring:" : "التكرار:", "Accept" : "قبول", "Decline" : "رفض", "More options …" : "مزيد مِن الخيارات…", "More options at %s" : "خيارات أخرى في %s", - "Contacts" : "المُراسِلون", + "Monday" : "الإثنين", + "Tuesday" : "الثلاثاء", + "Wednesday" : "الأربعاء", + "Thursday" : "الخميس", + "Friday" : "الجمعة", + "Saturday" : "السبت", + "Sunday" : "الأحد", + "January" : "يناير", + "February" : "فبراير", + "March" : "مارس", + "April" : "أبريل", + "May" : "مايو", + "June" : "يونيو", + "July" : "يوليو", + "August" : "اغسطس", + "September" : "سبتمبر", + "October" : "أكتوبر", + "November" : "نوفمبر", + "December" : "ديسمبر", + "First" : "أول", + "Second" : "ثاني", + "Third" : "ثالث", + "Fourth" : "رابع", + "Fifty" : "خامس", + "Last" : "آخِر", + "Second Last" : "ما قبل الأخير", + "Third Last" : "الثالث من الآخِر", + "Fourth Last" : "الرابع من الآخِر", + "Fifty Last" : "الخامس من الآخِر", + "Contacts" : "جهات الاتصال", "{actor} created address book {addressbook}" : "{actor} أنشأ دفتر العناوين {addressbook}", "You created address book {addressbook}" : "أنت أنشأت دفتر العناوين {addressbook}", "{actor} deleted address book {addressbook}" : "{actor} قام بحذف دفتر العناوين {addressbook}", @@ -174,20 +251,13 @@ "No working hours set" : "لم يتم تحديد ساعات العمل", "Add slot" : "أضِف فُرَضَةً slot زمنيّةً", "Weekdays" : "أيام الأسبوع", - "Monday" : "الإثنين", - "Tuesday" : "الثلاثاء", - "Wednesday" : "الأربعاء", - "Thursday" : "الخميس", - "Friday" : "الجمعة", - "Saturday" : "السبت", - "Sunday" : "الأحد", "Pick a start time for {dayName}" : "إختَر وقت البدء ليوم {dayName}", "Pick a end time for {dayName}" : "إختَر وقت الانتهاء ليوم {dayName}", - "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "قم بتعيين حالة المستخدم تلقائيًا على \"عدم الإزعاج\" خارج نطاق أوقات التوافر لكتم جميع الإشعارات", - "Failed to load availability" : "إخفاق في تحميل أوقات التوافر", - "Saved availability" : "تمّ حفظ أوقات التوافر", - "Failed to save availability" : "إخفاق في حفظ أوقات التواجد", - "Availability" : "أوقات التواجد availability", + "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "قم بتعيين حالة المستخدم تلقائيًا على \"عدم الإزعاج\" خارج نطاق أوقات التواجد لكتم جميع الإشعارات", + "Failed to load availability" : "إخفاق في تحميل أوقات التواجد", + "Saved availability" : "تمّ حفظ أوقات التواجد", + "Failed to save availability" : "تعذّر حفظ أوقات التواجد", + "Availability" : "أوقات التواجد ", "If you configure your working hours, other people will see when you are out of office when they book a meeting." : "إذا قمت بضبط ساعات عملك، سيرى الآخرون متى تكون خارج المكتب عندما يقومون بحجز اجتماع معك.", "Absence" : "غياب", "Configure your next absence period." : "قٌم بتهيئة فترة غيابك القادمة.", diff --git a/apps/dav/l10n/ast.js b/apps/dav/l10n/ast.js index e0adc74d3b3..5f298baa291 100644 --- a/apps/dav/l10n/ast.js +++ b/apps/dav/l10n/ast.js @@ -92,6 +92,25 @@ OC.L10N.register( "Decline" : "Refugar", "More options …" : "Más opciones…", "More options at %s" : "Más opciones en «%s»", + "Monday" : "Llunes", + "Tuesday" : "Martes", + "Wednesday" : "Miércoles", + "Thursday" : "Xueves", + "Friday" : "Vienres", + "Saturday" : "Sábadu", + "Sunday" : "Domingu", + "January" : "Xineru", + "February" : "Febreru", + "March" : "Marzu", + "April" : "Abril", + "May" : "Mayu", + "June" : "Xunu", + "July" : "Xunetu", + "August" : "Agostu", + "September" : "Setiembre", + "October" : "Ochobre", + "November" : "Payares", + "December" : "Avientu", "Contacts" : "Contautos", "{actor} created address book {addressbook}" : "{actor} creó la llibreta de direiciones «{addressbook}»", "You created address book {addressbook}" : "Creesti la llibreta de direiciones «{addressbook}»", @@ -171,13 +190,6 @@ OC.L10N.register( "No working hours set" : "Nun s'afitó nenguna hora llaboral", "Add slot" : "Amestar una ralura", "Weekdays" : "Díes de la selmana", - "Monday" : "Llunes", - "Tuesday" : "Martes", - "Wednesday" : "Miércoles", - "Thursday" : "Xueves", - "Friday" : "Vienres", - "Saturday" : "Sábadu", - "Sunday" : "Domingu", "Pick a start time for {dayName}" : "Escueyi una hora de comienzu pal {dayName}", "Pick a end time for {dayName}" : "Escueyi una hora de fin pal {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Afitar automáticamente l'estáu a «Nun molestar» fuera de la disponibilidá pa desactivar tolos avisos.", diff --git a/apps/dav/l10n/ast.json b/apps/dav/l10n/ast.json index 78010a72189..63fcc3046e8 100644 --- a/apps/dav/l10n/ast.json +++ b/apps/dav/l10n/ast.json @@ -90,6 +90,25 @@ "Decline" : "Refugar", "More options …" : "Más opciones…", "More options at %s" : "Más opciones en «%s»", + "Monday" : "Llunes", + "Tuesday" : "Martes", + "Wednesday" : "Miércoles", + "Thursday" : "Xueves", + "Friday" : "Vienres", + "Saturday" : "Sábadu", + "Sunday" : "Domingu", + "January" : "Xineru", + "February" : "Febreru", + "March" : "Marzu", + "April" : "Abril", + "May" : "Mayu", + "June" : "Xunu", + "July" : "Xunetu", + "August" : "Agostu", + "September" : "Setiembre", + "October" : "Ochobre", + "November" : "Payares", + "December" : "Avientu", "Contacts" : "Contautos", "{actor} created address book {addressbook}" : "{actor} creó la llibreta de direiciones «{addressbook}»", "You created address book {addressbook}" : "Creesti la llibreta de direiciones «{addressbook}»", @@ -169,13 +188,6 @@ "No working hours set" : "Nun s'afitó nenguna hora llaboral", "Add slot" : "Amestar una ralura", "Weekdays" : "Díes de la selmana", - "Monday" : "Llunes", - "Tuesday" : "Martes", - "Wednesday" : "Miércoles", - "Thursday" : "Xueves", - "Friday" : "Vienres", - "Saturday" : "Sábadu", - "Sunday" : "Domingu", "Pick a start time for {dayName}" : "Escueyi una hora de comienzu pal {dayName}", "Pick a end time for {dayName}" : "Escueyi una hora de fin pal {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Afitar automáticamente l'estáu a «Nun molestar» fuera de la disponibilidá pa desactivar tolos avisos.", diff --git a/apps/dav/l10n/bg.js b/apps/dav/l10n/bg.js index 244296b767e..7e07b6c76d1 100644 --- a/apps/dav/l10n/bg.js +++ b/apps/dav/l10n/bg.js @@ -92,6 +92,27 @@ OC.L10N.register( "Decline" : "Отхвърляне", "More options …" : "Още опции ...", "More options at %s" : "Още опции при %s", + "Monday" : "Понеделник", + "Tuesday" : "Вторник", + "Wednesday" : "Сряда", + "Thursday" : "Четвъртък", + "Friday" : "Петък", + "Saturday" : "Събота", + "Sunday" : "Неделя", + "January" : "Януари", + "February" : "Февруари", + "March" : "Март", + "April" : "Април", + "May" : "Май", + "June" : "Юни", + "July" : "Юли", + "August" : "Август", + "September" : "Септември", + "October" : "Октомври", + "November" : "Ноември", + "December" : "Декември", + "First" : "Първо", + "Last" : "Последно", "Contacts" : "Контакти", "{actor} created address book {addressbook}" : "{actor} създаде адресна книга {addressbook}", "You created address book {addressbook}" : "Вие създадохте адресна книга {addressbook}", @@ -155,13 +176,6 @@ OC.L10N.register( "Delete slot" : "Изтриване на слот", "No working hours set" : "Няма зададено работно време", "Add slot" : "Добавяне на слот", - "Monday" : "Понеделник", - "Tuesday" : "Вторник", - "Wednesday" : "Сряда", - "Thursday" : "Четвъртък", - "Friday" : "Петък", - "Saturday" : "Събота", - "Sunday" : "Неделя", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматично задаване на потребителският статус на „Не безпокойте“ извън достъпността, за заглушаване на всички известия.", "Failed to load availability" : "Неуспешно зареждане на наличност", "Saved availability" : "Запазена наличност", diff --git a/apps/dav/l10n/bg.json b/apps/dav/l10n/bg.json index 7c4d2b65842..76cc4bd4212 100644 --- a/apps/dav/l10n/bg.json +++ b/apps/dav/l10n/bg.json @@ -90,6 +90,27 @@ "Decline" : "Отхвърляне", "More options …" : "Още опции ...", "More options at %s" : "Още опции при %s", + "Monday" : "Понеделник", + "Tuesday" : "Вторник", + "Wednesday" : "Сряда", + "Thursday" : "Четвъртък", + "Friday" : "Петък", + "Saturday" : "Събота", + "Sunday" : "Неделя", + "January" : "Януари", + "February" : "Февруари", + "March" : "Март", + "April" : "Април", + "May" : "Май", + "June" : "Юни", + "July" : "Юли", + "August" : "Август", + "September" : "Септември", + "October" : "Октомври", + "November" : "Ноември", + "December" : "Декември", + "First" : "Първо", + "Last" : "Последно", "Contacts" : "Контакти", "{actor} created address book {addressbook}" : "{actor} създаде адресна книга {addressbook}", "You created address book {addressbook}" : "Вие създадохте адресна книга {addressbook}", @@ -153,13 +174,6 @@ "Delete slot" : "Изтриване на слот", "No working hours set" : "Няма зададено работно време", "Add slot" : "Добавяне на слот", - "Monday" : "Понеделник", - "Tuesday" : "Вторник", - "Wednesday" : "Сряда", - "Thursday" : "Четвъртък", - "Friday" : "Петък", - "Saturday" : "Събота", - "Sunday" : "Неделя", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматично задаване на потребителският статус на „Не безпокойте“ извън достъпността, за заглушаване на всички известия.", "Failed to load availability" : "Неуспешно зареждане на наличност", "Saved availability" : "Запазена наличност", diff --git a/apps/dav/l10n/ca.js b/apps/dav/l10n/ca.js index cd2399fb624..58a4f06c44f 100644 --- a/apps/dav/l10n/ca.js +++ b/apps/dav/l10n/ca.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Organització:", "Attendees:" : "Assistents:", "Title:" : "Títol:", + "When:" : "Quan:", "Location:" : "Ubicació:", "Link:" : "Enllaç:", "Accept" : "Accepta", "Decline" : "Rebutja", "More options …" : "Més opcions…", "More options at %s" : "Més opcions a %s", + "Monday" : "Dilluns", + "Tuesday" : "Dimarts", + "Wednesday" : "Dimecres", + "Thursday" : "Dijous", + "Friday" : "Divendres", + "Saturday" : "Dissabte", + "Sunday" : "Diumenge", + "January" : "Gener", + "February" : "Febrer", + "March" : "Març", + "April" : "Abril", + "May" : "Maig", + "June" : "Juny", + "July" : "Juliol", + "August" : "Agost", + "September" : "Setembre", + "October" : "Octubre", + "November" : "Novembre", + "December" : "Desembre", + "First" : "Primer", + "Last" : "Últim", "Contacts" : "Contactes", "{actor} created address book {addressbook}" : "{actor} ha creat la llibreta d'adreces {addressbook}", "You created address book {addressbook}" : "Heu creat la llibreta d'adreces {addressbook}", @@ -171,13 +193,6 @@ OC.L10N.register( "No working hours set" : "No s'ha definit cap horari laboral", "Add slot" : "Afegeix una franja", "Weekdays" : "Dies de la setmana", - "Monday" : "Dilluns", - "Tuesday" : "Dimarts", - "Wednesday" : "Dimecres", - "Thursday" : "Dijous", - "Friday" : "Divendres", - "Saturday" : "Dissabte", - "Sunday" : "Diumenge", "Pick a start time for {dayName}" : "Trieu una hora d'inici per a {dayName}", "Pick a end time for {dayName}" : "Trieu una hora de finalització per a {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Estableix automàticament l'estat de l'usuari com a «No molesteu» fora de la disponibilitat per a silenciar totes les notificacions", diff --git a/apps/dav/l10n/ca.json b/apps/dav/l10n/ca.json index 523ce961c5a..728f7d9a163 100644 --- a/apps/dav/l10n/ca.json +++ b/apps/dav/l10n/ca.json @@ -84,12 +84,34 @@ "Organizer:" : "Organització:", "Attendees:" : "Assistents:", "Title:" : "Títol:", + "When:" : "Quan:", "Location:" : "Ubicació:", "Link:" : "Enllaç:", "Accept" : "Accepta", "Decline" : "Rebutja", "More options …" : "Més opcions…", "More options at %s" : "Més opcions a %s", + "Monday" : "Dilluns", + "Tuesday" : "Dimarts", + "Wednesday" : "Dimecres", + "Thursday" : "Dijous", + "Friday" : "Divendres", + "Saturday" : "Dissabte", + "Sunday" : "Diumenge", + "January" : "Gener", + "February" : "Febrer", + "March" : "Març", + "April" : "Abril", + "May" : "Maig", + "June" : "Juny", + "July" : "Juliol", + "August" : "Agost", + "September" : "Setembre", + "October" : "Octubre", + "November" : "Novembre", + "December" : "Desembre", + "First" : "Primer", + "Last" : "Últim", "Contacts" : "Contactes", "{actor} created address book {addressbook}" : "{actor} ha creat la llibreta d'adreces {addressbook}", "You created address book {addressbook}" : "Heu creat la llibreta d'adreces {addressbook}", @@ -169,13 +191,6 @@ "No working hours set" : "No s'ha definit cap horari laboral", "Add slot" : "Afegeix una franja", "Weekdays" : "Dies de la setmana", - "Monday" : "Dilluns", - "Tuesday" : "Dimarts", - "Wednesday" : "Dimecres", - "Thursday" : "Dijous", - "Friday" : "Divendres", - "Saturday" : "Dissabte", - "Sunday" : "Diumenge", "Pick a start time for {dayName}" : "Trieu una hora d'inici per a {dayName}", "Pick a end time for {dayName}" : "Trieu una hora de finalització per a {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Estableix automàticament l'estat de l'usuari com a «No molesteu» fora de la disponibilitat per a silenciar totes les notificacions", diff --git a/apps/dav/l10n/cs.js b/apps/dav/l10n/cs.js index 18a80738bb7..2e425051593 100644 --- a/apps/dav/l10n/cs.js +++ b/apps/dav/l10n/cs.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Organizátor:", "Attendees:" : "Účastníci:", "Title:" : "Název:", + "When:" : "Kdy:", "Location:" : "Umístění:", "Link:" : "Odkaz:", "Accept" : "Přijmout", "Decline" : "Odmítnout", "More options …" : "Další volby…", "More options at %s" : "Další volby viz %s", + "Monday" : "pondělí", + "Tuesday" : "úterý", + "Wednesday" : "středa", + "Thursday" : "čtvrtek", + "Friday" : "pátek", + "Saturday" : "sobota", + "Sunday" : "neděle", + "January" : "leden", + "February" : "únor", + "March" : "březen", + "April" : "duben", + "May" : "květen", + "June" : "červen", + "July" : "červenec", + "August" : "srpen", + "September" : "září", + "October" : "říjen", + "November" : "listopad", + "December" : "prosinec", + "First" : "První", + "Last" : "Poslední", "Contacts" : "Kontakty", "{actor} created address book {addressbook}" : "{actor} vytvořil(a) adresář kontaktů {addressbook}", "You created address book {addressbook}" : "Vytvořili jste adresář kontaktů {addressbook}", @@ -168,13 +190,6 @@ OC.L10N.register( "Delete slot" : "Smazat slot", "No working hours set" : "Nenastaveny pracovní hodiny", "Add slot" : "Přidat slot", - "Monday" : "pondělí", - "Tuesday" : "úterý", - "Wednesday" : "středa", - "Thursday" : "čtvrtek", - "Friday" : "pátek", - "Saturday" : "sobota", - "Sunday" : "neděle", "Pick a start time for {dayName}" : "Vyberte začátek pro {dayName}", "Pick a end time for {dayName}" : "Vyberte konec pro {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "V době, kdy není k dispozici, automaticky nastavit stav uživatele jako „Nerušit“ a ztlumit tak veškerá upozornění pro něho.", diff --git a/apps/dav/l10n/cs.json b/apps/dav/l10n/cs.json index f6af6278004..619749c9e04 100644 --- a/apps/dav/l10n/cs.json +++ b/apps/dav/l10n/cs.json @@ -84,12 +84,34 @@ "Organizer:" : "Organizátor:", "Attendees:" : "Účastníci:", "Title:" : "Název:", + "When:" : "Kdy:", "Location:" : "Umístění:", "Link:" : "Odkaz:", "Accept" : "Přijmout", "Decline" : "Odmítnout", "More options …" : "Další volby…", "More options at %s" : "Další volby viz %s", + "Monday" : "pondělí", + "Tuesday" : "úterý", + "Wednesday" : "středa", + "Thursday" : "čtvrtek", + "Friday" : "pátek", + "Saturday" : "sobota", + "Sunday" : "neděle", + "January" : "leden", + "February" : "únor", + "March" : "březen", + "April" : "duben", + "May" : "květen", + "June" : "červen", + "July" : "červenec", + "August" : "srpen", + "September" : "září", + "October" : "říjen", + "November" : "listopad", + "December" : "prosinec", + "First" : "První", + "Last" : "Poslední", "Contacts" : "Kontakty", "{actor} created address book {addressbook}" : "{actor} vytvořil(a) adresář kontaktů {addressbook}", "You created address book {addressbook}" : "Vytvořili jste adresář kontaktů {addressbook}", @@ -166,13 +188,6 @@ "Delete slot" : "Smazat slot", "No working hours set" : "Nenastaveny pracovní hodiny", "Add slot" : "Přidat slot", - "Monday" : "pondělí", - "Tuesday" : "úterý", - "Wednesday" : "středa", - "Thursday" : "čtvrtek", - "Friday" : "pátek", - "Saturday" : "sobota", - "Sunday" : "neděle", "Pick a start time for {dayName}" : "Vyberte začátek pro {dayName}", "Pick a end time for {dayName}" : "Vyberte konec pro {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "V době, kdy není k dispozici, automaticky nastavit stav uživatele jako „Nerušit“ a ztlumit tak veškerá upozornění pro něho.", diff --git a/apps/dav/l10n/da.js b/apps/dav/l10n/da.js index 569cd319aed..942cb73b0e6 100644 --- a/apps/dav/l10n/da.js +++ b/apps/dav/l10n/da.js @@ -86,13 +86,32 @@ OC.L10N.register( "Organizer:" : "Arrangør:", "Attendees:" : "Deltagere:", "Title:" : "Titel:", - "Date and time:" : "Dato og tid:", + "When:" : "Hvornår:", "Location:" : "Sted:", "Link:" : "Link:", "Accept" : "Accepter", "Decline" : "Afvis", "More options …" : "Flere indstillinger…", "More options at %s" : "Flere muligheder på %s", + "Monday" : "Mandag", + "Tuesday" : "Tirsdag", + "Wednesday" : "Onsdag", + "Thursday" : "Torsdag", + "Friday" : "Fredag", + "Saturday" : "Lørdag", + "Sunday" : "Søndag", + "January" : "Januar", + "February" : "Februar", + "March" : "Marts", + "April" : "April", + "May" : "Maj", + "June" : "Juni", + "July" : "Juli", + "August" : "August", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "December", "Contacts" : "Kontakter", "{actor} created address book {addressbook}" : "{actor} oprettede adressebog {addressbook}", "You created address book {addressbook}" : "Du oprettede adressebog {addressbook}", @@ -173,13 +192,6 @@ OC.L10N.register( "No working hours set" : "Arbejdstider er ikke sat", "Add slot" : "Tilføj slot", "Weekdays" : "Hverdage", - "Monday" : "Mandag", - "Tuesday" : "Tirsdag", - "Wednesday" : "Onsdag", - "Thursday" : "Torsdag", - "Friday" : "Fredag", - "Saturday" : "Lørdag", - "Sunday" : "Søndag", "Pick a start time for {dayName}" : "Vælg et starttidspunkt for {dayName}", "Pick a end time for {dayName}" : "Vælg et sluttidspunkt for {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Indstil automatisk brugerstatus til \"Forstyr ikke\" uden for tilgængelighed for at slå alle notifikationer fra.", diff --git a/apps/dav/l10n/da.json b/apps/dav/l10n/da.json index 200ee3253b7..3657acc6b58 100644 --- a/apps/dav/l10n/da.json +++ b/apps/dav/l10n/da.json @@ -84,13 +84,32 @@ "Organizer:" : "Arrangør:", "Attendees:" : "Deltagere:", "Title:" : "Titel:", - "Date and time:" : "Dato og tid:", + "When:" : "Hvornår:", "Location:" : "Sted:", "Link:" : "Link:", "Accept" : "Accepter", "Decline" : "Afvis", "More options …" : "Flere indstillinger…", "More options at %s" : "Flere muligheder på %s", + "Monday" : "Mandag", + "Tuesday" : "Tirsdag", + "Wednesday" : "Onsdag", + "Thursday" : "Torsdag", + "Friday" : "Fredag", + "Saturday" : "Lørdag", + "Sunday" : "Søndag", + "January" : "Januar", + "February" : "Februar", + "March" : "Marts", + "April" : "April", + "May" : "Maj", + "June" : "Juni", + "July" : "Juli", + "August" : "August", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "December", "Contacts" : "Kontakter", "{actor} created address book {addressbook}" : "{actor} oprettede adressebog {addressbook}", "You created address book {addressbook}" : "Du oprettede adressebog {addressbook}", @@ -171,13 +190,6 @@ "No working hours set" : "Arbejdstider er ikke sat", "Add slot" : "Tilføj slot", "Weekdays" : "Hverdage", - "Monday" : "Mandag", - "Tuesday" : "Tirsdag", - "Wednesday" : "Onsdag", - "Thursday" : "Torsdag", - "Friday" : "Fredag", - "Saturday" : "Lørdag", - "Sunday" : "Søndag", "Pick a start time for {dayName}" : "Vælg et starttidspunkt for {dayName}", "Pick a end time for {dayName}" : "Vælg et sluttidspunkt for {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Indstil automatisk brugerstatus til \"Forstyr ikke\" uden for tilgængelighed for at slå alle notifikationer fra.", diff --git a/apps/dav/l10n/de.js b/apps/dav/l10n/de.js index 6da6d0f414f..15b40369102 100644 --- a/apps/dav/l10n/de.js +++ b/apps/dav/l10n/de.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "Beschreibung: %s", "Where: %s" : "Ort: %s", "%1$s via %2$s" : "%1$s über %2$s", + "In a %1$s on %2$s for the entire day" : "In einer %1$s am %2$s für den ganzen Tag", + "In a %1$s on %2$s between %3$s - %4$s" : "In einer %1$s am %2$s zwischen %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "In %1$s %2$s am %3$s für den ganzen Tag", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "In %1$s %2$s am %3$s zwischen %4$s - %5$s", + "Could not generate when statement" : "Wann-Angabe konnte nicht erzeugt werden.", + "Every Day for the entire day" : "Jeden Tag für den ganzen Tag", + "Every Day for the entire day until %1$s" : "Jeden Tag für den ganzen Tag bis %1$s", + "Every Day between %1$s - %2$s" : "Jeden Tag zwischen %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Jeden Tag zwischen %1$s - %2$s bis %3$s", + "Every %1$d Days for the entire day" : "Alle %1$d Tage für den ganzen Tag", + "Every %1$d Days for the entire day until %2$s" : "Alle %1$d Tage für den ganzen Tag bis %2$s", + "Every %1$d Days between %2$s - %3$s" : "Alle %1$d Tage zwischen %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Alle %1$d Tage zwischen %2$s - %3$s bis %4$s", + "Could not generate event recurrence statement" : "Angabe für Terminwiederholung konnte nicht erzeugt werden.", + "Every Week on %1$s for the entire day" : "Jede Woche am %1$s für den ganzen Tag", + "Every Week on %1$s for the entire day until %2$s" : "Jede Woche am %1$s für den ganzen Tag bis %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Jede Woche am %1$s zwischen %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Jede Woche am %1$s zwischen %2$s - %3$s bis %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Alle %1$d Wochen am %2$s für den ganzen Tag", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Alle %1$d Wochen am %2$s für den ganzen Tag bis %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Alle %1$d Wochen am %2$s zwischen %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Alle %1$d Wochen am %2$s zwischen %3$s - %4$s bis %5$s", + "Every Month on the %1$s for the entire day" : "Jeden Monat am %1$s für den ganzen Tag", + "Every Month on the %1$s for the entire day until %2$s" : "Jeden Monat am %1$s für den ganzen Tag bis %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Jeden Monat am %1$s zwischen %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Jeden Monat am %1$s zwischen %2$s - %3$s bis %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Alle %1$d Monate am %2$s für den ganzen Tag", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Alle %1$d Monate am %2$s für den ganzen Tag bis %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Alle %1$d Monate am %2$s zwischen %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Alle %1$d Monate am %2$s zwischen %3$s - %4$s bis %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Jedes Jahr im %1$s am %2$s für den ganzen Tag", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Jedes Jahr im %1$s am %2$s für den ganzen Tag bis %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Jedes Jahr im %1$s am %2$s zwischen %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Jedes Jahr im %1$s am %2$s zwischen %3$s - %4$s bis %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Alle %1$d Jahre im %2$s am %3$s für den ganzen Tag", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Alle %1$d Jahre im %2$s am %3$s für den ganzen Tag bis %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Alle %1$d Jahre im %2$s am %3$s zwischen %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Alle %1$d Jahre im %2$s am %3$s zwischen %4$s - %5$s bis %6$s", + "On specific dates for the entire day until %1$s" : "An bestimmten Tagen für den ganzen Tag bis %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "An bestimmten Tagen zwischen %1$s - %2$s bis %3$s", + "In a %1$s on %2$s" : "In einer %1$s am %2$s ", + "In a %1$s on %2$s then on %3$s" : "In einer %1$s am %2$s danach am %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "In einer %1$s am %2$s danach am %3$s und %4$s", + "In %1$s %2$s on %3$s" : "In %1$s %2$s am %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "In %1$s %2$s am %3$s danach am %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "In %1$s %2$s am %3$s danach am %4$s und %5$s", + "Could not generate next recurrence statement" : "Angabe für nächste Wiederholung konnte nicht erzeugt werden.", "Cancelled: %1$s" : "Abgesagt: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" wurde abgesagt.", "Re: %1$s" : "Re: %1$s", @@ -86,13 +133,39 @@ OC.L10N.register( "Organizer:" : "Organisator:", "Attendees:" : "Teilnehmer:", "Title:" : "Titel:", - "Date and time:" : "Datum und Zeit:", + "When:" : "Wann:", "Location:" : "Ort:", "Link:" : "Link:", + "Occurring:" : "Vorkommend:", "Accept" : "Akzeptieren", "Decline" : "Ablehnen", "More options …" : "Weitere Optionen …", "More options at %s" : "Weitere Optionen unter %s", + "Monday" : "Montag", + "Tuesday" : "Dienstag", + "Wednesday" : "Mittwoch", + "Thursday" : "Donnerstag", + "Friday" : "Freitag", + "Saturday" : "Samstag", + "Sunday" : "Sonntag", + "January" : "Januar", + "February" : "Februar", + "March" : "März", + "April" : "April", + "May" : "Mai", + "June" : "Juni", + "July" : "Juli", + "August" : "August", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "Dezember", + "First" : "Erste", + "Second" : "2.", + "Third" : "3.", + "Fourth" : "4.", + "Fifty" : "5.", + "Last" : "Letzte", "Contacts" : "Kontakte", "{actor} created address book {addressbook}" : "{actor} hat das Adressbuch {addressbook} erstellt", "You created address book {addressbook}" : "Du hast das Adressbuch {addressbook} erstellt", @@ -161,6 +234,7 @@ OC.L10N.register( "Out of office replacement (optional)" : "Abwesenheitsvertretung (optional)", "Name of the replacement" : "Name der Vertretung", "No results." : "Keine Ergebnisse", + "Start typing." : "Beginne mit Schreiben", "Short absence status" : "Kurze Abwesenheits Meldung", "Long absence Message" : "Lange Abwesenheits Meldung", "Save" : "Speichern", @@ -175,13 +249,6 @@ OC.L10N.register( "No working hours set" : "Keine Arbeitszeiten konfiguriert", "Add slot" : "Slot hinzufügen", "Weekdays" : "Wochentage", - "Monday" : "Montag", - "Tuesday" : "Dienstag", - "Wednesday" : "Mittwoch", - "Thursday" : "Donnerstag", - "Friday" : "Freitag", - "Saturday" : "Samstag", - "Sunday" : "Sonntag", "Pick a start time for {dayName}" : "Eine Startzeit für {dayName} wählen", "Pick a end time for {dayName}" : "Eine Endezeit für {dayName} wählen", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setze den Benutzerstatus automatisch auf „Nicht stören“, wenn du nicht erreichbar bist, um alle Benachrichtigungen stumm zu schalten.", diff --git a/apps/dav/l10n/de.json b/apps/dav/l10n/de.json index 76f234f74d9..52b064230ad 100644 --- a/apps/dav/l10n/de.json +++ b/apps/dav/l10n/de.json @@ -70,6 +70,53 @@ "Description: %s" : "Beschreibung: %s", "Where: %s" : "Ort: %s", "%1$s via %2$s" : "%1$s über %2$s", + "In a %1$s on %2$s for the entire day" : "In einer %1$s am %2$s für den ganzen Tag", + "In a %1$s on %2$s between %3$s - %4$s" : "In einer %1$s am %2$s zwischen %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "In %1$s %2$s am %3$s für den ganzen Tag", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "In %1$s %2$s am %3$s zwischen %4$s - %5$s", + "Could not generate when statement" : "Wann-Angabe konnte nicht erzeugt werden.", + "Every Day for the entire day" : "Jeden Tag für den ganzen Tag", + "Every Day for the entire day until %1$s" : "Jeden Tag für den ganzen Tag bis %1$s", + "Every Day between %1$s - %2$s" : "Jeden Tag zwischen %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Jeden Tag zwischen %1$s - %2$s bis %3$s", + "Every %1$d Days for the entire day" : "Alle %1$d Tage für den ganzen Tag", + "Every %1$d Days for the entire day until %2$s" : "Alle %1$d Tage für den ganzen Tag bis %2$s", + "Every %1$d Days between %2$s - %3$s" : "Alle %1$d Tage zwischen %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Alle %1$d Tage zwischen %2$s - %3$s bis %4$s", + "Could not generate event recurrence statement" : "Angabe für Terminwiederholung konnte nicht erzeugt werden.", + "Every Week on %1$s for the entire day" : "Jede Woche am %1$s für den ganzen Tag", + "Every Week on %1$s for the entire day until %2$s" : "Jede Woche am %1$s für den ganzen Tag bis %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Jede Woche am %1$s zwischen %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Jede Woche am %1$s zwischen %2$s - %3$s bis %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Alle %1$d Wochen am %2$s für den ganzen Tag", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Alle %1$d Wochen am %2$s für den ganzen Tag bis %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Alle %1$d Wochen am %2$s zwischen %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Alle %1$d Wochen am %2$s zwischen %3$s - %4$s bis %5$s", + "Every Month on the %1$s for the entire day" : "Jeden Monat am %1$s für den ganzen Tag", + "Every Month on the %1$s for the entire day until %2$s" : "Jeden Monat am %1$s für den ganzen Tag bis %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Jeden Monat am %1$s zwischen %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Jeden Monat am %1$s zwischen %2$s - %3$s bis %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Alle %1$d Monate am %2$s für den ganzen Tag", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Alle %1$d Monate am %2$s für den ganzen Tag bis %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Alle %1$d Monate am %2$s zwischen %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Alle %1$d Monate am %2$s zwischen %3$s - %4$s bis %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Jedes Jahr im %1$s am %2$s für den ganzen Tag", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Jedes Jahr im %1$s am %2$s für den ganzen Tag bis %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Jedes Jahr im %1$s am %2$s zwischen %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Jedes Jahr im %1$s am %2$s zwischen %3$s - %4$s bis %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Alle %1$d Jahre im %2$s am %3$s für den ganzen Tag", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Alle %1$d Jahre im %2$s am %3$s für den ganzen Tag bis %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Alle %1$d Jahre im %2$s am %3$s zwischen %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Alle %1$d Jahre im %2$s am %3$s zwischen %4$s - %5$s bis %6$s", + "On specific dates for the entire day until %1$s" : "An bestimmten Tagen für den ganzen Tag bis %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "An bestimmten Tagen zwischen %1$s - %2$s bis %3$s", + "In a %1$s on %2$s" : "In einer %1$s am %2$s ", + "In a %1$s on %2$s then on %3$s" : "In einer %1$s am %2$s danach am %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "In einer %1$s am %2$s danach am %3$s und %4$s", + "In %1$s %2$s on %3$s" : "In %1$s %2$s am %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "In %1$s %2$s am %3$s danach am %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "In %1$s %2$s am %3$s danach am %4$s und %5$s", + "Could not generate next recurrence statement" : "Angabe für nächste Wiederholung konnte nicht erzeugt werden.", "Cancelled: %1$s" : "Abgesagt: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" wurde abgesagt.", "Re: %1$s" : "Re: %1$s", @@ -84,13 +131,39 @@ "Organizer:" : "Organisator:", "Attendees:" : "Teilnehmer:", "Title:" : "Titel:", - "Date and time:" : "Datum und Zeit:", + "When:" : "Wann:", "Location:" : "Ort:", "Link:" : "Link:", + "Occurring:" : "Vorkommend:", "Accept" : "Akzeptieren", "Decline" : "Ablehnen", "More options …" : "Weitere Optionen …", "More options at %s" : "Weitere Optionen unter %s", + "Monday" : "Montag", + "Tuesday" : "Dienstag", + "Wednesday" : "Mittwoch", + "Thursday" : "Donnerstag", + "Friday" : "Freitag", + "Saturday" : "Samstag", + "Sunday" : "Sonntag", + "January" : "Januar", + "February" : "Februar", + "March" : "März", + "April" : "April", + "May" : "Mai", + "June" : "Juni", + "July" : "Juli", + "August" : "August", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "Dezember", + "First" : "Erste", + "Second" : "2.", + "Third" : "3.", + "Fourth" : "4.", + "Fifty" : "5.", + "Last" : "Letzte", "Contacts" : "Kontakte", "{actor} created address book {addressbook}" : "{actor} hat das Adressbuch {addressbook} erstellt", "You created address book {addressbook}" : "Du hast das Adressbuch {addressbook} erstellt", @@ -159,6 +232,7 @@ "Out of office replacement (optional)" : "Abwesenheitsvertretung (optional)", "Name of the replacement" : "Name der Vertretung", "No results." : "Keine Ergebnisse", + "Start typing." : "Beginne mit Schreiben", "Short absence status" : "Kurze Abwesenheits Meldung", "Long absence Message" : "Lange Abwesenheits Meldung", "Save" : "Speichern", @@ -173,13 +247,6 @@ "No working hours set" : "Keine Arbeitszeiten konfiguriert", "Add slot" : "Slot hinzufügen", "Weekdays" : "Wochentage", - "Monday" : "Montag", - "Tuesday" : "Dienstag", - "Wednesday" : "Mittwoch", - "Thursday" : "Donnerstag", - "Friday" : "Freitag", - "Saturday" : "Samstag", - "Sunday" : "Sonntag", "Pick a start time for {dayName}" : "Eine Startzeit für {dayName} wählen", "Pick a end time for {dayName}" : "Eine Endezeit für {dayName} wählen", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setze den Benutzerstatus automatisch auf „Nicht stören“, wenn du nicht erreichbar bist, um alle Benachrichtigungen stumm zu schalten.", diff --git a/apps/dav/l10n/de_DE.js b/apps/dav/l10n/de_DE.js index a882bd7b243..5cabdf98bc3 100644 --- a/apps/dav/l10n/de_DE.js +++ b/apps/dav/l10n/de_DE.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "Beschreibung: %s", "Where: %s" : "Ort: %s", "%1$s via %2$s" : "%1$s über %2$s", + "In a %1$s on %2$s for the entire day" : "In einer %1$s am %2$s für den ganzen Tag", + "In a %1$s on %2$s between %3$s - %4$s" : "In einer %1$s am %2$s zwischen %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "In %1$s %2$s am %3$s für den ganzen Tag", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "In %1$s %2$s am %3$s zwischen %4$s - %5$s", + "Could not generate when statement" : "Wann-Angabe konnte nicht erzeugt werden", + "Every Day for the entire day" : "Jeden Tag für den ganzen Tag", + "Every Day for the entire day until %1$s" : "Jeden Tag für den ganzen Tag bis %1$s", + "Every Day between %1$s - %2$s" : "Jeden Tag zwischen %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Jeden Tag zwischen %1$s - %2$s bis %3$s", + "Every %1$d Days for the entire day" : "Alle %1$d Tage für den ganzen Tag", + "Every %1$d Days for the entire day until %2$s" : "Alle %1$d Tage für den ganzen Tag bis %2$s", + "Every %1$d Days between %2$s - %3$s" : "Alle %1$d Tage zwischen %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Alle %1$d Tage zwischen %2$s - %3$s bis %4$s", + "Could not generate event recurrence statement" : "Terminwiederholungsangabe konnte nicht erzeugt werden", + "Every Week on %1$s for the entire day" : "Jede Woche am %1$s für den ganzen Tag", + "Every Week on %1$s for the entire day until %2$s" : "Jede Woche am %1$s für den ganzen Tag bis %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Jede Woche am %1$s zwischen %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Jede Woche am %1$s zwischen %2$s - %3$s bis %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Alle %1$d Wochen am %2$s für den ganzen Tag", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Alle %1$d Wochen am %2$s für den ganzen Tag bis %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Alle %1$d Wochen am %2$s zwischen %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Alle %1$d Wochen am %2$s zwischen %3$s - %4$s bis %5$s", + "Every Month on the %1$s for the entire day" : "Jeden Monat am %1$s für den ganzen Tag", + "Every Month on the %1$s for the entire day until %2$s" : "Jeden Monat am %1$s für den ganzen Tag bis %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Jeden Monat am %1$s zwischen %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Jeden Monat am %1$s zwischen %2$s - %3$s bis %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Alle %1$d Monate am %2$s für den ganzen Tag", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Alle %1$d Monate am %2$s für den ganzen Tag bis %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Alle %1$d Monate am %2$s zwischen %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Alle %1$d Monate am %2$s zwischen %3$s - %4$s bis %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Jedes Jahr im %1$s am %2$s für den ganzen Tag", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Jedes Jahr im %1$s am %2$s für den ganzen Tag bis %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Jedes Jahr im %1$s am %2$s zwischen %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Jedes Jahr im %1$s am %2$s zwischen %3$s - %4$s bis %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Alle %1$d Jahre im %2$s am %3$s für den ganzen Tag", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Alle %1$d Jahre im %2$s am %3$s für den ganzen Tag bis %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Alle %1$d Jahre im %2$s am %3$s zwischen %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Alle %1$d Jahre im %2$s am %3$s zwischen %4$s - %5$s bis %6$s", + "On specific dates for the entire day until %1$s" : "An bestimmten Tagen für den ganzen Tag bis %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "An bestimmten Tagen zwischen %1$s - %2$s bis %3$s", + "In a %1$s on %2$s" : "In einer %1$s am %2$s ", + "In a %1$s on %2$s then on %3$s" : "In einer %1$s am %2$s danach am %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "In einer %1$s am %2$s danach am %3$s und %4$s", + "In %1$s %2$s on %3$s" : "In %1$s %2$s am %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "In %1$s %2$s am %3$s danach am %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "In %1$s %2$s am %3$s danach am %4$s und %5$s", + "Could not generate next recurrence statement" : "Nächste Wiederholungsangabe konnte nicht erzeugt werden", "Cancelled: %1$s" : "Abgesagt: %1$s", "\"%1$s\" has been canceled" : "\"%1$s“ wurde abgesagt.", "Re: %1$s" : "Re: %1$s", @@ -86,13 +133,43 @@ OC.L10N.register( "Organizer:" : "Organisator:", "Attendees:" : "Teilnehmer:", "Title:" : "Titel:", - "Date and time:" : "Datum und Uhrzeit:", + "When:" : "Wann:", "Location:" : "Ort:", "Link:" : "Link:", + "Occurring:" : "Vorkommend:", "Accept" : "Akzeptieren", "Decline" : "Ablehnen", "More options …" : "Weitere Optionen …", "More options at %s" : "Weitere Optionen unter %s", + "Monday" : "Montag", + "Tuesday" : "Dienstag", + "Wednesday" : "Mittwoch", + "Thursday" : "Donnerstag", + "Friday" : "Freitag", + "Saturday" : "Samstag", + "Sunday" : "Sonntag", + "January" : "Januar", + "February" : "Februar", + "March" : "März", + "April" : "April", + "May" : "Mai", + "June" : "Juni", + "July" : "Juli", + "August" : "August", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "Dezember", + "First" : "Erstes", + "Second" : "Zweites", + "Third" : "Drittes", + "Fourth" : "Viertes", + "Fifty" : "Fünftes", + "Last" : "Letztes", + "Second Last" : "Vorletztes", + "Third Last" : "Drittletztes", + "Fourth Last" : "Viertletztes", + "Fifty Last" : "Fünftletztes", "Contacts" : "Kontakte", "{actor} created address book {addressbook}" : "{actor} hat das Adressbuch {addressbook} erstellt", "You created address book {addressbook}" : "Sie haben das Adressbuch {addressbook} erstellt", @@ -176,13 +253,6 @@ OC.L10N.register( "No working hours set" : "Arbeitsfreie Stunden gesetzt", "Add slot" : "Zeitfenster hinzufügen", "Weekdays" : "Wochentage", - "Monday" : "Montag", - "Tuesday" : "Dienstag", - "Wednesday" : "Mittwoch", - "Thursday" : "Donnerstag", - "Friday" : "Freitag", - "Saturday" : "Samstag", - "Sunday" : "Sonntag", "Pick a start time for {dayName}" : "Eine Startzeit für {dayName} wählen", "Pick a end time for {dayName}" : "Eine Endezeit für {dayName} wählen", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setzen Sie den Benutzerstatus wenn Sie nicht erreichbar sind automatisch auf „Nicht stören“, um alle Benachrichtigungen stumm zu schalten.", diff --git a/apps/dav/l10n/de_DE.json b/apps/dav/l10n/de_DE.json index f0a40921985..cdcc06f8d87 100644 --- a/apps/dav/l10n/de_DE.json +++ b/apps/dav/l10n/de_DE.json @@ -70,6 +70,53 @@ "Description: %s" : "Beschreibung: %s", "Where: %s" : "Ort: %s", "%1$s via %2$s" : "%1$s über %2$s", + "In a %1$s on %2$s for the entire day" : "In einer %1$s am %2$s für den ganzen Tag", + "In a %1$s on %2$s between %3$s - %4$s" : "In einer %1$s am %2$s zwischen %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "In %1$s %2$s am %3$s für den ganzen Tag", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "In %1$s %2$s am %3$s zwischen %4$s - %5$s", + "Could not generate when statement" : "Wann-Angabe konnte nicht erzeugt werden", + "Every Day for the entire day" : "Jeden Tag für den ganzen Tag", + "Every Day for the entire day until %1$s" : "Jeden Tag für den ganzen Tag bis %1$s", + "Every Day between %1$s - %2$s" : "Jeden Tag zwischen %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Jeden Tag zwischen %1$s - %2$s bis %3$s", + "Every %1$d Days for the entire day" : "Alle %1$d Tage für den ganzen Tag", + "Every %1$d Days for the entire day until %2$s" : "Alle %1$d Tage für den ganzen Tag bis %2$s", + "Every %1$d Days between %2$s - %3$s" : "Alle %1$d Tage zwischen %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Alle %1$d Tage zwischen %2$s - %3$s bis %4$s", + "Could not generate event recurrence statement" : "Terminwiederholungsangabe konnte nicht erzeugt werden", + "Every Week on %1$s for the entire day" : "Jede Woche am %1$s für den ganzen Tag", + "Every Week on %1$s for the entire day until %2$s" : "Jede Woche am %1$s für den ganzen Tag bis %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Jede Woche am %1$s zwischen %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Jede Woche am %1$s zwischen %2$s - %3$s bis %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Alle %1$d Wochen am %2$s für den ganzen Tag", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Alle %1$d Wochen am %2$s für den ganzen Tag bis %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Alle %1$d Wochen am %2$s zwischen %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Alle %1$d Wochen am %2$s zwischen %3$s - %4$s bis %5$s", + "Every Month on the %1$s for the entire day" : "Jeden Monat am %1$s für den ganzen Tag", + "Every Month on the %1$s for the entire day until %2$s" : "Jeden Monat am %1$s für den ganzen Tag bis %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Jeden Monat am %1$s zwischen %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Jeden Monat am %1$s zwischen %2$s - %3$s bis %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Alle %1$d Monate am %2$s für den ganzen Tag", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Alle %1$d Monate am %2$s für den ganzen Tag bis %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Alle %1$d Monate am %2$s zwischen %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Alle %1$d Monate am %2$s zwischen %3$s - %4$s bis %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Jedes Jahr im %1$s am %2$s für den ganzen Tag", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Jedes Jahr im %1$s am %2$s für den ganzen Tag bis %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Jedes Jahr im %1$s am %2$s zwischen %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Jedes Jahr im %1$s am %2$s zwischen %3$s - %4$s bis %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Alle %1$d Jahre im %2$s am %3$s für den ganzen Tag", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Alle %1$d Jahre im %2$s am %3$s für den ganzen Tag bis %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Alle %1$d Jahre im %2$s am %3$s zwischen %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Alle %1$d Jahre im %2$s am %3$s zwischen %4$s - %5$s bis %6$s", + "On specific dates for the entire day until %1$s" : "An bestimmten Tagen für den ganzen Tag bis %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "An bestimmten Tagen zwischen %1$s - %2$s bis %3$s", + "In a %1$s on %2$s" : "In einer %1$s am %2$s ", + "In a %1$s on %2$s then on %3$s" : "In einer %1$s am %2$s danach am %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "In einer %1$s am %2$s danach am %3$s und %4$s", + "In %1$s %2$s on %3$s" : "In %1$s %2$s am %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "In %1$s %2$s am %3$s danach am %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "In %1$s %2$s am %3$s danach am %4$s und %5$s", + "Could not generate next recurrence statement" : "Nächste Wiederholungsangabe konnte nicht erzeugt werden", "Cancelled: %1$s" : "Abgesagt: %1$s", "\"%1$s\" has been canceled" : "\"%1$s“ wurde abgesagt.", "Re: %1$s" : "Re: %1$s", @@ -84,13 +131,43 @@ "Organizer:" : "Organisator:", "Attendees:" : "Teilnehmer:", "Title:" : "Titel:", - "Date and time:" : "Datum und Uhrzeit:", + "When:" : "Wann:", "Location:" : "Ort:", "Link:" : "Link:", + "Occurring:" : "Vorkommend:", "Accept" : "Akzeptieren", "Decline" : "Ablehnen", "More options …" : "Weitere Optionen …", "More options at %s" : "Weitere Optionen unter %s", + "Monday" : "Montag", + "Tuesday" : "Dienstag", + "Wednesday" : "Mittwoch", + "Thursday" : "Donnerstag", + "Friday" : "Freitag", + "Saturday" : "Samstag", + "Sunday" : "Sonntag", + "January" : "Januar", + "February" : "Februar", + "March" : "März", + "April" : "April", + "May" : "Mai", + "June" : "Juni", + "July" : "Juli", + "August" : "August", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "Dezember", + "First" : "Erstes", + "Second" : "Zweites", + "Third" : "Drittes", + "Fourth" : "Viertes", + "Fifty" : "Fünftes", + "Last" : "Letztes", + "Second Last" : "Vorletztes", + "Third Last" : "Drittletztes", + "Fourth Last" : "Viertletztes", + "Fifty Last" : "Fünftletztes", "Contacts" : "Kontakte", "{actor} created address book {addressbook}" : "{actor} hat das Adressbuch {addressbook} erstellt", "You created address book {addressbook}" : "Sie haben das Adressbuch {addressbook} erstellt", @@ -174,13 +251,6 @@ "No working hours set" : "Arbeitsfreie Stunden gesetzt", "Add slot" : "Zeitfenster hinzufügen", "Weekdays" : "Wochentage", - "Monday" : "Montag", - "Tuesday" : "Dienstag", - "Wednesday" : "Mittwoch", - "Thursday" : "Donnerstag", - "Friday" : "Freitag", - "Saturday" : "Samstag", - "Sunday" : "Sonntag", "Pick a start time for {dayName}" : "Eine Startzeit für {dayName} wählen", "Pick a end time for {dayName}" : "Eine Endezeit für {dayName} wählen", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setzen Sie den Benutzerstatus wenn Sie nicht erreichbar sind automatisch auf „Nicht stören“, um alle Benachrichtigungen stumm zu schalten.", diff --git a/apps/dav/l10n/en_GB.js b/apps/dav/l10n/en_GB.js index e380b998cc7..cf026e159b9 100644 --- a/apps/dav/l10n/en_GB.js +++ b/apps/dav/l10n/en_GB.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "Description: %s", "Where: %s" : "Where: %s", "%1$s via %2$s" : "%1$s via %2$s", + "In a %1$s on %2$s for the entire day" : "In a %1$s on %2$s for the entire day", + "In a %1$s on %2$s between %3$s - %4$s" : "In a %1$s on %2$s between %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "In %1$s %2$s on %3$s for the entire day", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "In %1$s %2$s on %3$s between %4$s - %5$s", + "Could not generate when statement" : "Could not generate when statement", + "Every Day for the entire day" : "Every Day for the entire day", + "Every Day for the entire day until %1$s" : "Every Day for the entire day until %1$s", + "Every Day between %1$s - %2$s" : "Every Day between %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Every Day between %1$s - %2$s until %3$s", + "Every %1$d Days for the entire day" : "Every %1$d Days for the entire day", + "Every %1$d Days for the entire day until %2$s" : "Every %1$d Days for the entire day until %2$s", + "Every %1$d Days between %2$s - %3$s" : "Every %1$d Days between %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Every %1$d Days between %2$s - %3$s until %4$s", + "Could not generate event recurrence statement" : "Could not generate event recurrence statement", + "Every Week on %1$s for the entire day" : "Every Week on %1$s for the entire day", + "Every Week on %1$s for the entire day until %2$s" : "Every Week on %1$s for the entire day until %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Every Week on %1$s between %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Every Week on %1$s between %2$s - %3$s until %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Every %1$d Weeks on %2$s for the entire day", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Every %1$d Weeks on %2$s for the entire day until %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Every %1$d Weeks on %2$s between %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s", + "Every Month on the %1$s for the entire day" : "Every Month on the %1$s for the entire day", + "Every Month on the %1$s for the entire day until %2$s" : "Every Month on the %1$s for the entire day until %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Every Month on the %1$s between %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Every Month on the %1$s between %2$s - %3$s until %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Every %1$d Months on the %2$s for the entire day", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Every %1$d Months on the %2$s for the entire day until %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Every %1$d Months on the %2$s between %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Every Year in %1$s on the %2$s for the entire day", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Every Year in %1$s on the %2$s for the entire day until %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Every Year in %1$s on the %2$s between %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Every %1$d Years in %2$s on the %3$s for the entire day", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s", + "On specific dates for the entire day until %1$s" : "On specific dates for the entire day until %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "On specific dates between %1$s - %2$s until %3$s", + "In a %1$s on %2$s" : "In a %1$s on %2$s", + "In a %1$s on %2$s then on %3$s" : "In a %1$s on %2$s then on %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "In a %1$s on %2$s then on %3$s and %4$s", + "In %1$s %2$s on %3$s" : "In %1$s %2$s on %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "In %1$s %2$s on %3$s then on %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "In %1$s %2$s on %3$s then on %4$s and %5$s", + "Could not generate next recurrence statement" : "Could not generate next recurrence statement", "Cancelled: %1$s" : "Cancelled: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" has been cancelled", "Re: %1$s" : "Re: %1$s", @@ -86,13 +133,43 @@ OC.L10N.register( "Organizer:" : "Organiser:", "Attendees:" : "Attendees:", "Title:" : "Title:", - "Date and time:" : "Date and time:", + "When:" : "When:", "Location:" : "Location:", "Link:" : "Link:", + "Occurring:" : "Occurring:", "Accept" : "Accept", "Decline" : "Decline", "More options …" : "More options …", "More options at %s" : "More options at %s", + "Monday" : "Monday", + "Tuesday" : "Tuesday", + "Wednesday" : "Wednesday", + "Thursday" : "Thursday", + "Friday" : "Friday", + "Saturday" : "Saturday", + "Sunday" : "Sunday", + "January" : "January", + "February" : "February", + "March" : "March", + "April" : "April", + "May" : "May", + "June" : "June", + "July" : "July", + "August" : "August", + "September" : "September", + "October" : "October", + "November" : "November", + "December" : "December", + "First" : "First", + "Second" : "Second", + "Third" : "Third", + "Fourth" : "Fourth", + "Fifty" : "Fifty", + "Last" : "Last", + "Second Last" : "Second Last", + "Third Last" : "Third Last", + "Fourth Last" : "Fourth Last", + "Fifty Last" : "Fifty Last", "Contacts" : "Contacts", "{actor} created address book {addressbook}" : "{actor} created address book {addressbook}", "You created address book {addressbook}" : "You created address book {addressbook}", @@ -176,13 +253,6 @@ OC.L10N.register( "No working hours set" : "No working hours set", "Add slot" : "Add slot", "Weekdays" : "Weekdays", - "Monday" : "Monday", - "Tuesday" : "Tuesday", - "Wednesday" : "Wednesday", - "Thursday" : "Thursday", - "Friday" : "Friday", - "Saturday" : "Saturday", - "Sunday" : "Sunday", "Pick a start time for {dayName}" : "Pick a start time for {dayName}", "Pick a end time for {dayName}" : "Pick a end time for {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications.", diff --git a/apps/dav/l10n/en_GB.json b/apps/dav/l10n/en_GB.json index 2259fe8d0fb..00802ed836e 100644 --- a/apps/dav/l10n/en_GB.json +++ b/apps/dav/l10n/en_GB.json @@ -70,6 +70,53 @@ "Description: %s" : "Description: %s", "Where: %s" : "Where: %s", "%1$s via %2$s" : "%1$s via %2$s", + "In a %1$s on %2$s for the entire day" : "In a %1$s on %2$s for the entire day", + "In a %1$s on %2$s between %3$s - %4$s" : "In a %1$s on %2$s between %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "In %1$s %2$s on %3$s for the entire day", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "In %1$s %2$s on %3$s between %4$s - %5$s", + "Could not generate when statement" : "Could not generate when statement", + "Every Day for the entire day" : "Every Day for the entire day", + "Every Day for the entire day until %1$s" : "Every Day for the entire day until %1$s", + "Every Day between %1$s - %2$s" : "Every Day between %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Every Day between %1$s - %2$s until %3$s", + "Every %1$d Days for the entire day" : "Every %1$d Days for the entire day", + "Every %1$d Days for the entire day until %2$s" : "Every %1$d Days for the entire day until %2$s", + "Every %1$d Days between %2$s - %3$s" : "Every %1$d Days between %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Every %1$d Days between %2$s - %3$s until %4$s", + "Could not generate event recurrence statement" : "Could not generate event recurrence statement", + "Every Week on %1$s for the entire day" : "Every Week on %1$s for the entire day", + "Every Week on %1$s for the entire day until %2$s" : "Every Week on %1$s for the entire day until %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Every Week on %1$s between %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Every Week on %1$s between %2$s - %3$s until %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Every %1$d Weeks on %2$s for the entire day", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Every %1$d Weeks on %2$s for the entire day until %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Every %1$d Weeks on %2$s between %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s", + "Every Month on the %1$s for the entire day" : "Every Month on the %1$s for the entire day", + "Every Month on the %1$s for the entire day until %2$s" : "Every Month on the %1$s for the entire day until %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Every Month on the %1$s between %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Every Month on the %1$s between %2$s - %3$s until %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Every %1$d Months on the %2$s for the entire day", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Every %1$d Months on the %2$s for the entire day until %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Every %1$d Months on the %2$s between %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Every Year in %1$s on the %2$s for the entire day", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Every Year in %1$s on the %2$s for the entire day until %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Every Year in %1$s on the %2$s between %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Every %1$d Years in %2$s on the %3$s for the entire day", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s", + "On specific dates for the entire day until %1$s" : "On specific dates for the entire day until %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "On specific dates between %1$s - %2$s until %3$s", + "In a %1$s on %2$s" : "In a %1$s on %2$s", + "In a %1$s on %2$s then on %3$s" : "In a %1$s on %2$s then on %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "In a %1$s on %2$s then on %3$s and %4$s", + "In %1$s %2$s on %3$s" : "In %1$s %2$s on %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "In %1$s %2$s on %3$s then on %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "In %1$s %2$s on %3$s then on %4$s and %5$s", + "Could not generate next recurrence statement" : "Could not generate next recurrence statement", "Cancelled: %1$s" : "Cancelled: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" has been cancelled", "Re: %1$s" : "Re: %1$s", @@ -84,13 +131,43 @@ "Organizer:" : "Organiser:", "Attendees:" : "Attendees:", "Title:" : "Title:", - "Date and time:" : "Date and time:", + "When:" : "When:", "Location:" : "Location:", "Link:" : "Link:", + "Occurring:" : "Occurring:", "Accept" : "Accept", "Decline" : "Decline", "More options …" : "More options …", "More options at %s" : "More options at %s", + "Monday" : "Monday", + "Tuesday" : "Tuesday", + "Wednesday" : "Wednesday", + "Thursday" : "Thursday", + "Friday" : "Friday", + "Saturday" : "Saturday", + "Sunday" : "Sunday", + "January" : "January", + "February" : "February", + "March" : "March", + "April" : "April", + "May" : "May", + "June" : "June", + "July" : "July", + "August" : "August", + "September" : "September", + "October" : "October", + "November" : "November", + "December" : "December", + "First" : "First", + "Second" : "Second", + "Third" : "Third", + "Fourth" : "Fourth", + "Fifty" : "Fifty", + "Last" : "Last", + "Second Last" : "Second Last", + "Third Last" : "Third Last", + "Fourth Last" : "Fourth Last", + "Fifty Last" : "Fifty Last", "Contacts" : "Contacts", "{actor} created address book {addressbook}" : "{actor} created address book {addressbook}", "You created address book {addressbook}" : "You created address book {addressbook}", @@ -174,13 +251,6 @@ "No working hours set" : "No working hours set", "Add slot" : "Add slot", "Weekdays" : "Weekdays", - "Monday" : "Monday", - "Tuesday" : "Tuesday", - "Wednesday" : "Wednesday", - "Thursday" : "Thursday", - "Friday" : "Friday", - "Saturday" : "Saturday", - "Sunday" : "Sunday", "Pick a start time for {dayName}" : "Pick a start time for {dayName}", "Pick a end time for {dayName}" : "Pick a end time for {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications.", diff --git a/apps/dav/l10n/es.js b/apps/dav/l10n/es.js index 81cc3dc2867..811c0eb9cf4 100644 --- a/apps/dav/l10n/es.js +++ b/apps/dav/l10n/es.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Organizador:", "Attendees:" : "Asistentes:", "Title:" : "Título:", + "When:" : "Cuándo:", "Location:" : "Ubicación:", "Link:" : "Enlace:", "Accept" : "Aceptar", "Decline" : "Rechazar", "More options …" : "Más opciones...", "More options at %s" : "Más opciones en %s", + "Monday" : "Lunes", + "Tuesday" : "Martes", + "Wednesday" : "Miércoles", + "Thursday" : "Jueves", + "Friday" : "Viernes", + "Saturday" : "Sábado", + "Sunday" : "Domingo", + "January" : "Enero", + "February" : "Febrero", + "March" : "Marzo", + "April" : "Abril", + "May" : "Mayo", + "June" : "Junio", + "July" : "Julio", + "August" : "Agosto", + "September" : "Septiembre", + "October" : "Octubre", + "November" : "Noviembre", + "December" : "Diciembre", + "First" : "Primera", + "Last" : "Última", "Contacts" : "Contactos", "{actor} created address book {addressbook}" : "{actor} ha creado la libreta de direcciones {addressbook}", "You created address book {addressbook}" : "Has creado la libreta de direcciones {adressbook}", @@ -171,13 +193,6 @@ OC.L10N.register( "No working hours set" : "No se han establecido horas de funcionamiento", "Add slot" : "Añadir espacio", "Weekdays" : "Días de semana", - "Monday" : "Lunes", - "Tuesday" : "Martes", - "Wednesday" : "Miércoles", - "Thursday" : "Jueves", - "Friday" : "Viernes", - "Saturday" : "Sábado", - "Sunday" : "Domingo", "Pick a start time for {dayName}" : "Elija una hora de inicio para {dayName}", "Pick a end time for {dayName}" : "Elija una hora fin para {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Cambiar automáticamente el estado del usuario a \"No molestar\" cuando no esté disponible para silenciar todas las notificaciones.", diff --git a/apps/dav/l10n/es.json b/apps/dav/l10n/es.json index 52f0b7e6acc..2c757187061 100644 --- a/apps/dav/l10n/es.json +++ b/apps/dav/l10n/es.json @@ -84,12 +84,34 @@ "Organizer:" : "Organizador:", "Attendees:" : "Asistentes:", "Title:" : "Título:", + "When:" : "Cuándo:", "Location:" : "Ubicación:", "Link:" : "Enlace:", "Accept" : "Aceptar", "Decline" : "Rechazar", "More options …" : "Más opciones...", "More options at %s" : "Más opciones en %s", + "Monday" : "Lunes", + "Tuesday" : "Martes", + "Wednesday" : "Miércoles", + "Thursday" : "Jueves", + "Friday" : "Viernes", + "Saturday" : "Sábado", + "Sunday" : "Domingo", + "January" : "Enero", + "February" : "Febrero", + "March" : "Marzo", + "April" : "Abril", + "May" : "Mayo", + "June" : "Junio", + "July" : "Julio", + "August" : "Agosto", + "September" : "Septiembre", + "October" : "Octubre", + "November" : "Noviembre", + "December" : "Diciembre", + "First" : "Primera", + "Last" : "Última", "Contacts" : "Contactos", "{actor} created address book {addressbook}" : "{actor} ha creado la libreta de direcciones {addressbook}", "You created address book {addressbook}" : "Has creado la libreta de direcciones {adressbook}", @@ -169,13 +191,6 @@ "No working hours set" : "No se han establecido horas de funcionamiento", "Add slot" : "Añadir espacio", "Weekdays" : "Días de semana", - "Monday" : "Lunes", - "Tuesday" : "Martes", - "Wednesday" : "Miércoles", - "Thursday" : "Jueves", - "Friday" : "Viernes", - "Saturday" : "Sábado", - "Sunday" : "Domingo", "Pick a start time for {dayName}" : "Elija una hora de inicio para {dayName}", "Pick a end time for {dayName}" : "Elija una hora fin para {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Cambiar automáticamente el estado del usuario a \"No molestar\" cuando no esté disponible para silenciar todas las notificaciones.", diff --git a/apps/dav/l10n/es_EC.js b/apps/dav/l10n/es_EC.js index 29576adbdbf..6cf3712ea47 100644 --- a/apps/dav/l10n/es_EC.js +++ b/apps/dav/l10n/es_EC.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Organizador:", "Attendees:" : "Asistentes:", "Title:" : "Título:", + "When:" : "Cuándo:", "Location:" : "Ubicación:", "Link:" : "Enlace:", "Accept" : "Aceptar", "Decline" : "Declinar", "More options …" : "Más opciones...", "More options at %s" : "Más opciones en %s", + "Monday" : "Lunes", + "Tuesday" : "Martes", + "Wednesday" : "Miércoles", + "Thursday" : "Jueves", + "Friday" : "Viernes", + "Saturday" : "Sábado", + "Sunday" : "Domingo", + "January" : "Enero", + "February" : "Febrero", + "March" : "Marzo", + "April" : "Abril", + "May" : "Mayo", + "June" : "Junio", + "July" : "Julio", + "August" : "Agosto", + "September" : "Septiembre", + "October" : "Octubre", + "November" : "Noviembre", + "December" : "Diciembre", + "First" : "Primero", + "Last" : "Último", "Contacts" : "Contactos", "{actor} created address book {addressbook}" : "{actor} creó la libreta de direcciones {addressbook}", "You created address book {addressbook}" : "Creaste la libreta de direcciones {addressbook}", @@ -157,13 +179,6 @@ OC.L10N.register( "Delete slot" : "Eliminar ranura", "No working hours set" : "No se han establecido horas de trabajo", "Add slot" : "Agregar ranura", - "Monday" : "Lunes", - "Tuesday" : "Martes", - "Wednesday" : "Miércoles", - "Thursday" : "Jueves", - "Friday" : "Viernes", - "Saturday" : "Sábado", - "Sunday" : "Domingo", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Configurar automáticamente el estado del usuario como \"No molestar\" fuera de la disponibilidad para silenciar todas las notificaciones.", "Failed to load availability" : "Error al cargar la disponibilidad", "Saved availability" : "Disponibilidad guardada", diff --git a/apps/dav/l10n/es_EC.json b/apps/dav/l10n/es_EC.json index c0e995f17f9..e69f1fd2589 100644 --- a/apps/dav/l10n/es_EC.json +++ b/apps/dav/l10n/es_EC.json @@ -84,12 +84,34 @@ "Organizer:" : "Organizador:", "Attendees:" : "Asistentes:", "Title:" : "Título:", + "When:" : "Cuándo:", "Location:" : "Ubicación:", "Link:" : "Enlace:", "Accept" : "Aceptar", "Decline" : "Declinar", "More options …" : "Más opciones...", "More options at %s" : "Más opciones en %s", + "Monday" : "Lunes", + "Tuesday" : "Martes", + "Wednesday" : "Miércoles", + "Thursday" : "Jueves", + "Friday" : "Viernes", + "Saturday" : "Sábado", + "Sunday" : "Domingo", + "January" : "Enero", + "February" : "Febrero", + "March" : "Marzo", + "April" : "Abril", + "May" : "Mayo", + "June" : "Junio", + "July" : "Julio", + "August" : "Agosto", + "September" : "Septiembre", + "October" : "Octubre", + "November" : "Noviembre", + "December" : "Diciembre", + "First" : "Primero", + "Last" : "Último", "Contacts" : "Contactos", "{actor} created address book {addressbook}" : "{actor} creó la libreta de direcciones {addressbook}", "You created address book {addressbook}" : "Creaste la libreta de direcciones {addressbook}", @@ -155,13 +177,6 @@ "Delete slot" : "Eliminar ranura", "No working hours set" : "No se han establecido horas de trabajo", "Add slot" : "Agregar ranura", - "Monday" : "Lunes", - "Tuesday" : "Martes", - "Wednesday" : "Miércoles", - "Thursday" : "Jueves", - "Friday" : "Viernes", - "Saturday" : "Sábado", - "Sunday" : "Domingo", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Configurar automáticamente el estado del usuario como \"No molestar\" fuera de la disponibilidad para silenciar todas las notificaciones.", "Failed to load availability" : "Error al cargar la disponibilidad", "Saved availability" : "Disponibilidad guardada", diff --git a/apps/dav/l10n/es_MX.js b/apps/dav/l10n/es_MX.js index 2f400b7774a..235cc466a7b 100644 --- a/apps/dav/l10n/es_MX.js +++ b/apps/dav/l10n/es_MX.js @@ -86,13 +86,32 @@ OC.L10N.register( "Organizer:" : "Organizador:", "Attendees:" : "Asistentes:", "Title:" : "Título:", - "Date and time:" : "Fecha y hora:", + "When:" : "Cuándo:", "Location:" : "Ubicación:", "Link:" : "Enlace:", "Accept" : "Aceptar", "Decline" : "Rechazar", "More options …" : "Más opciones ...", "More options at %s" : "Más opciones en %s", + "Monday" : "Lunes", + "Tuesday" : "Martes", + "Wednesday" : "Miércoles", + "Thursday" : "Jueves", + "Friday" : "Viernes", + "Saturday" : "Sábado", + "Sunday" : "Domingo", + "January" : "Enero", + "February" : "Febrero", + "March" : "Marzo", + "April" : "Abril", + "May" : "Mayo", + "June" : "Junio", + "July" : "Julio", + "August" : "Agosto", + "September" : "Septiembre", + "October" : "Octubre", + "November" : "Noviembre", + "December" : "Diciembre", "Contacts" : "Contactos", "{actor} created address book {addressbook}" : "{actor} creó la libreta de direcciones {addressbook}", "You created address book {addressbook}" : "Ha creado la libreta de direcciones {adressbook}", @@ -176,13 +195,6 @@ OC.L10N.register( "No working hours set" : "No se han establecido las horas de trabajo", "Add slot" : "Añadir ranura", "Weekdays" : "Días laborales", - "Monday" : "Lunes", - "Tuesday" : "Martes", - "Wednesday" : "Miércoles", - "Thursday" : "Jueves", - "Friday" : "Viernes", - "Saturday" : "Sábado", - "Sunday" : "Domingo", "Pick a start time for {dayName}" : "Elija una hora de inicio para {dayName}", "Pick a end time for {dayName}" : "Elija una hora fin para {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Establecer automáticamente el estado de usuario como \"No molestar\" fuera de la disponibilidad para silenciar todas las notificaciones.", diff --git a/apps/dav/l10n/es_MX.json b/apps/dav/l10n/es_MX.json index 2736b342da3..29ccb78a231 100644 --- a/apps/dav/l10n/es_MX.json +++ b/apps/dav/l10n/es_MX.json @@ -84,13 +84,32 @@ "Organizer:" : "Organizador:", "Attendees:" : "Asistentes:", "Title:" : "Título:", - "Date and time:" : "Fecha y hora:", + "When:" : "Cuándo:", "Location:" : "Ubicación:", "Link:" : "Enlace:", "Accept" : "Aceptar", "Decline" : "Rechazar", "More options …" : "Más opciones ...", "More options at %s" : "Más opciones en %s", + "Monday" : "Lunes", + "Tuesday" : "Martes", + "Wednesday" : "Miércoles", + "Thursday" : "Jueves", + "Friday" : "Viernes", + "Saturday" : "Sábado", + "Sunday" : "Domingo", + "January" : "Enero", + "February" : "Febrero", + "March" : "Marzo", + "April" : "Abril", + "May" : "Mayo", + "June" : "Junio", + "July" : "Julio", + "August" : "Agosto", + "September" : "Septiembre", + "October" : "Octubre", + "November" : "Noviembre", + "December" : "Diciembre", "Contacts" : "Contactos", "{actor} created address book {addressbook}" : "{actor} creó la libreta de direcciones {addressbook}", "You created address book {addressbook}" : "Ha creado la libreta de direcciones {adressbook}", @@ -174,13 +193,6 @@ "No working hours set" : "No se han establecido las horas de trabajo", "Add slot" : "Añadir ranura", "Weekdays" : "Días laborales", - "Monday" : "Lunes", - "Tuesday" : "Martes", - "Wednesday" : "Miércoles", - "Thursday" : "Jueves", - "Friday" : "Viernes", - "Saturday" : "Sábado", - "Sunday" : "Domingo", "Pick a start time for {dayName}" : "Elija una hora de inicio para {dayName}", "Pick a end time for {dayName}" : "Elija una hora fin para {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Establecer automáticamente el estado de usuario como \"No molestar\" fuera de la disponibilidad para silenciar todas las notificaciones.", diff --git a/apps/dav/l10n/eu.js b/apps/dav/l10n/eu.js index 1fe1cfaacc6..b4d2b71dbfa 100644 --- a/apps/dav/l10n/eu.js +++ b/apps/dav/l10n/eu.js @@ -86,13 +86,34 @@ OC.L10N.register( "Organizer:" : "Antolatzailea:", "Attendees:" : "Parte-hartzaileak:", "Title:" : "Izenburua:", - "Date and time:" : "Data eta ordua:", + "When:" : "Noiz:", "Location:" : "Kokapena:", "Link:" : "Esteka:", "Accept" : "Onartu", "Decline" : "Uko egin", "More options …" : "Aukera gehiago …", "More options at %s" : "Aukera gehiago hemen %s ", + "Monday" : "Astelehena", + "Tuesday" : "Asteartea", + "Wednesday" : "Asteazkena", + "Thursday" : "Osteguna", + "Friday" : "Ostirala", + "Saturday" : "Larunbata", + "Sunday" : "Igandea", + "January" : "Urtarrila", + "February" : "Otsaila", + "March" : "Martxoa", + "April" : "Apirila", + "May" : "Maiatza", + "June" : "Ekaina", + "July" : "Uztaila", + "August" : "Abuztua", + "September" : "Iraila", + "October" : "Urria", + "November" : "Azaroa", + "December" : "Abendua", + "First" : "Lehenengoa", + "Last" : "Azkena", "Contacts" : "Kontaktuak", "{actor} created address book {addressbook}" : "{actor}-(e)k {addressbook} helbide-liburua sortu du ", "You created address book {addressbook}" : "{addressbook} helbide-liburua sortu duzu", @@ -172,13 +193,6 @@ OC.L10N.register( "No working hours set" : "Ez dira laneko orduak ezarri", "Add slot" : "Gehitu tartea", "Weekdays" : "Astegunak", - "Monday" : "Astelehena", - "Tuesday" : "Asteartea", - "Wednesday" : "Asteazkena", - "Thursday" : "Osteguna", - "Friday" : "Ostirala", - "Saturday" : "Larunbata", - "Sunday" : "Igandea", "Pick a start time for {dayName}" : "Hautatu hasiera ordu bat {dayName}(e)rako", "Pick a end time for {dayName}" : "Hautatu bukaera ordu bat {dayName}(e)rako", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Eskuragarri ez egotean, ezarri automatikoki erabiltzailearen egoera \"Ez molestatu\" moduan jakinarazpen guztiak isilarazteko.", diff --git a/apps/dav/l10n/eu.json b/apps/dav/l10n/eu.json index 6d51172db04..a9353cb3d1a 100644 --- a/apps/dav/l10n/eu.json +++ b/apps/dav/l10n/eu.json @@ -84,13 +84,34 @@ "Organizer:" : "Antolatzailea:", "Attendees:" : "Parte-hartzaileak:", "Title:" : "Izenburua:", - "Date and time:" : "Data eta ordua:", + "When:" : "Noiz:", "Location:" : "Kokapena:", "Link:" : "Esteka:", "Accept" : "Onartu", "Decline" : "Uko egin", "More options …" : "Aukera gehiago …", "More options at %s" : "Aukera gehiago hemen %s ", + "Monday" : "Astelehena", + "Tuesday" : "Asteartea", + "Wednesday" : "Asteazkena", + "Thursday" : "Osteguna", + "Friday" : "Ostirala", + "Saturday" : "Larunbata", + "Sunday" : "Igandea", + "January" : "Urtarrila", + "February" : "Otsaila", + "March" : "Martxoa", + "April" : "Apirila", + "May" : "Maiatza", + "June" : "Ekaina", + "July" : "Uztaila", + "August" : "Abuztua", + "September" : "Iraila", + "October" : "Urria", + "November" : "Azaroa", + "December" : "Abendua", + "First" : "Lehenengoa", + "Last" : "Azkena", "Contacts" : "Kontaktuak", "{actor} created address book {addressbook}" : "{actor}-(e)k {addressbook} helbide-liburua sortu du ", "You created address book {addressbook}" : "{addressbook} helbide-liburua sortu duzu", @@ -170,13 +191,6 @@ "No working hours set" : "Ez dira laneko orduak ezarri", "Add slot" : "Gehitu tartea", "Weekdays" : "Astegunak", - "Monday" : "Astelehena", - "Tuesday" : "Asteartea", - "Wednesday" : "Asteazkena", - "Thursday" : "Osteguna", - "Friday" : "Ostirala", - "Saturday" : "Larunbata", - "Sunday" : "Igandea", "Pick a start time for {dayName}" : "Hautatu hasiera ordu bat {dayName}(e)rako", "Pick a end time for {dayName}" : "Hautatu bukaera ordu bat {dayName}(e)rako", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Eskuragarri ez egotean, ezarri automatikoki erabiltzailearen egoera \"Ez molestatu\" moduan jakinarazpen guztiak isilarazteko.", diff --git a/apps/dav/l10n/fa.js b/apps/dav/l10n/fa.js index 1dd8117c467..e059c2e1d09 100644 --- a/apps/dav/l10n/fa.js +++ b/apps/dav/l10n/fa.js @@ -92,6 +92,27 @@ OC.L10N.register( "Decline" : "کاهش می یابد", "More options …" : "More options …", "More options at %s" : "More options at %s", + "Monday" : "دوشنبه", + "Tuesday" : "سه شنبه", + "Wednesday" : "چهارشنبه", + "Thursday" : "پنجشنبه", + "Friday" : "جمعه", + "Saturday" : "شنبه", + "Sunday" : "یکشنبه", + "January" : "ژانویه", + "February" : "فوریه", + "March" : "مارس", + "April" : "آوریل", + "May" : "مه", + "June" : "ژوئن", + "July" : "جولای", + "August" : "اوت", + "September" : "سپتامبر", + "October" : "اکتبر", + "November" : "نوامبر", + "December" : "دسامبر", + "First" : "First", + "Last" : "Last", "Contacts" : "مخاطبین", "{actor} created address book {addressbook}" : "{actor} created address book {addressbook}", "You created address book {addressbook}" : "دفترچه آدرس ساخته شد", @@ -157,13 +178,6 @@ OC.L10N.register( "Delete slot" : "Delete slot", "No working hours set" : "ساعات کاری تعیین نشده است", "Add slot" : "Add slot", - "Monday" : "دوشنبه", - "Tuesday" : "سه شنبه", - "Wednesday" : "چهارشنبه", - "Thursday" : "پنجشنبه", - "Friday" : "جمعه", - "Saturday" : "شنبه", - "Sunday" : "یکشنبه", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "وضعیت کاربر بصورت خودکار به \"مزاحم نشوید\" تغییر داده شود تا همه ی اعلان ها خاموش شوند", "Failed to load availability" : "Failed to load availability", "Saved availability" : "Saved availability", diff --git a/apps/dav/l10n/fa.json b/apps/dav/l10n/fa.json index fbd5f8a10bb..638319918e3 100644 --- a/apps/dav/l10n/fa.json +++ b/apps/dav/l10n/fa.json @@ -90,6 +90,27 @@ "Decline" : "کاهش می یابد", "More options …" : "More options …", "More options at %s" : "More options at %s", + "Monday" : "دوشنبه", + "Tuesday" : "سه شنبه", + "Wednesday" : "چهارشنبه", + "Thursday" : "پنجشنبه", + "Friday" : "جمعه", + "Saturday" : "شنبه", + "Sunday" : "یکشنبه", + "January" : "ژانویه", + "February" : "فوریه", + "March" : "مارس", + "April" : "آوریل", + "May" : "مه", + "June" : "ژوئن", + "July" : "جولای", + "August" : "اوت", + "September" : "سپتامبر", + "October" : "اکتبر", + "November" : "نوامبر", + "December" : "دسامبر", + "First" : "First", + "Last" : "Last", "Contacts" : "مخاطبین", "{actor} created address book {addressbook}" : "{actor} created address book {addressbook}", "You created address book {addressbook}" : "دفترچه آدرس ساخته شد", @@ -155,13 +176,6 @@ "Delete slot" : "Delete slot", "No working hours set" : "ساعات کاری تعیین نشده است", "Add slot" : "Add slot", - "Monday" : "دوشنبه", - "Tuesday" : "سه شنبه", - "Wednesday" : "چهارشنبه", - "Thursday" : "پنجشنبه", - "Friday" : "جمعه", - "Saturday" : "شنبه", - "Sunday" : "یکشنبه", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "وضعیت کاربر بصورت خودکار به \"مزاحم نشوید\" تغییر داده شود تا همه ی اعلان ها خاموش شوند", "Failed to load availability" : "Failed to load availability", "Saved availability" : "Saved availability", diff --git a/apps/dav/l10n/fi.js b/apps/dav/l10n/fi.js index 4c82746255a..76cec39ebde 100644 --- a/apps/dav/l10n/fi.js +++ b/apps/dav/l10n/fi.js @@ -66,12 +66,34 @@ OC.L10N.register( "Organizer:" : "Järjestäjä:", "Attendees:" : "Osallistujat:", "Title:" : "Otsikko:", + "When:" : "Milloin:", "Location:" : "Sijainti:", "Link:" : "Linkki:", "Accept" : "Hyväksy", "Decline" : "Kieltäydy", "More options …" : "Lisää valintoja…", "More options at %s" : "Lisää valintoja kohteessa %s", + "Monday" : "Maanantai", + "Tuesday" : "Tiistai", + "Wednesday" : "Keskiviikko", + "Thursday" : "Torstai", + "Friday" : "Perjantai", + "Saturday" : "Lauantai", + "Sunday" : "Sunnuntai", + "January" : "tammikuu", + "February" : "helmikuu", + "March" : "maaliskuu", + "April" : "huhtikuu", + "May" : "toukokuu", + "June" : "kesäkuu", + "July" : "heinäkuu", + "August" : "elokuu", + "September" : "syyskuu", + "October" : "lokakuu", + "November" : "marraskuu", + "December" : "joulukuu", + "First" : "Ensimmäinen", + "Last" : "Viimeinen", "Contacts" : "Yhteystiedot", "{actor} created address book {addressbook}" : "{actor} loi osoitekirjan {addressbook}", "You created address book {addressbook}" : "Loit osoitekirjan {addressbook}", @@ -123,13 +145,6 @@ OC.L10N.register( "No working hours set" : "Työskentelytunteja ei ole asetettu", "Add slot" : "Lisää aikarako", "Weekdays" : "Viikonpäivät", - "Monday" : "Maanantai", - "Tuesday" : "Tiistai", - "Wednesday" : "Keskiviikko", - "Thursday" : "Torstai", - "Friday" : "Perjantai", - "Saturday" : "Lauantai", - "Sunday" : "Sunnuntai", "Failed to load availability" : "Saatavuuden lataaminen epäonnistui", "Availability" : "Saatavuus", "Calendar server" : "Kalenteripalvelin", diff --git a/apps/dav/l10n/fi.json b/apps/dav/l10n/fi.json index a524c0140db..189c1a9a952 100644 --- a/apps/dav/l10n/fi.json +++ b/apps/dav/l10n/fi.json @@ -64,12 +64,34 @@ "Organizer:" : "Järjestäjä:", "Attendees:" : "Osallistujat:", "Title:" : "Otsikko:", + "When:" : "Milloin:", "Location:" : "Sijainti:", "Link:" : "Linkki:", "Accept" : "Hyväksy", "Decline" : "Kieltäydy", "More options …" : "Lisää valintoja…", "More options at %s" : "Lisää valintoja kohteessa %s", + "Monday" : "Maanantai", + "Tuesday" : "Tiistai", + "Wednesday" : "Keskiviikko", + "Thursday" : "Torstai", + "Friday" : "Perjantai", + "Saturday" : "Lauantai", + "Sunday" : "Sunnuntai", + "January" : "tammikuu", + "February" : "helmikuu", + "March" : "maaliskuu", + "April" : "huhtikuu", + "May" : "toukokuu", + "June" : "kesäkuu", + "July" : "heinäkuu", + "August" : "elokuu", + "September" : "syyskuu", + "October" : "lokakuu", + "November" : "marraskuu", + "December" : "joulukuu", + "First" : "Ensimmäinen", + "Last" : "Viimeinen", "Contacts" : "Yhteystiedot", "{actor} created address book {addressbook}" : "{actor} loi osoitekirjan {addressbook}", "You created address book {addressbook}" : "Loit osoitekirjan {addressbook}", @@ -121,13 +143,6 @@ "No working hours set" : "Työskentelytunteja ei ole asetettu", "Add slot" : "Lisää aikarako", "Weekdays" : "Viikonpäivät", - "Monday" : "Maanantai", - "Tuesday" : "Tiistai", - "Wednesday" : "Keskiviikko", - "Thursday" : "Torstai", - "Friday" : "Perjantai", - "Saturday" : "Lauantai", - "Sunday" : "Sunnuntai", "Failed to load availability" : "Saatavuuden lataaminen epäonnistui", "Availability" : "Saatavuus", "Calendar server" : "Kalenteripalvelin", diff --git a/apps/dav/l10n/fr.js b/apps/dav/l10n/fr.js index 951cbe7e239..a004724d3da 100644 --- a/apps/dav/l10n/fr.js +++ b/apps/dav/l10n/fr.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Organisateur :", "Attendees:" : "Participants :", "Title:" : "Titre :", + "When:" : "Quand :", "Location:" : "Lieu :", "Link:" : "Lien :", "Accept" : "Accepter", "Decline" : "Décliner", "More options …" : "Plus d'options…", "More options at %s" : "Plus d'options à %s", + "Monday" : "Lundi", + "Tuesday" : "Mardi", + "Wednesday" : "Mercredi", + "Thursday" : "Jeudi", + "Friday" : "Vendredi", + "Saturday" : "Samedi", + "Sunday" : "Dimanche", + "January" : "Janvier", + "February" : "Février", + "March" : "Mars", + "April" : "Avril", + "May" : "Mai", + "June" : "Juin", + "July" : "Juillet", + "August" : "Août", + "September" : "Septembre", + "October" : "Octobre", + "November" : "Novembre", + "December" : "Décembre", + "First" : "Première", + "Last" : "Dernière", "Contacts" : "Contacts", "{actor} created address book {addressbook}" : "{actor} a créé le carnet d'adresses {addressbook}", "You created address book {addressbook}" : "Vous avez créé le carnet d'adresses {addressbook}", @@ -171,13 +193,6 @@ OC.L10N.register( "No working hours set" : "Heures de travail non définies", "Add slot" : "Ajouter un créneau", "Weekdays" : "Jours de la semaine", - "Monday" : "Lundi", - "Tuesday" : "Mardi", - "Wednesday" : "Mercredi", - "Thursday" : "Jeudi", - "Friday" : "Vendredi", - "Saturday" : "Samedi", - "Sunday" : "Dimanche", "Pick a start time for {dayName}" : "Choisissez une heure de début pour {dayName}", "Pick a end time for {dayName}" : "Choisissez une heure de fin pour {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Définir automatiquement le statut « Ne pas déranger » en dehors des heures de disponibilités pour désactiver toutes les notifications.", diff --git a/apps/dav/l10n/fr.json b/apps/dav/l10n/fr.json index abaff02f3cd..4ebd7cc74d2 100644 --- a/apps/dav/l10n/fr.json +++ b/apps/dav/l10n/fr.json @@ -84,12 +84,34 @@ "Organizer:" : "Organisateur :", "Attendees:" : "Participants :", "Title:" : "Titre :", + "When:" : "Quand :", "Location:" : "Lieu :", "Link:" : "Lien :", "Accept" : "Accepter", "Decline" : "Décliner", "More options …" : "Plus d'options…", "More options at %s" : "Plus d'options à %s", + "Monday" : "Lundi", + "Tuesday" : "Mardi", + "Wednesday" : "Mercredi", + "Thursday" : "Jeudi", + "Friday" : "Vendredi", + "Saturday" : "Samedi", + "Sunday" : "Dimanche", + "January" : "Janvier", + "February" : "Février", + "March" : "Mars", + "April" : "Avril", + "May" : "Mai", + "June" : "Juin", + "July" : "Juillet", + "August" : "Août", + "September" : "Septembre", + "October" : "Octobre", + "November" : "Novembre", + "December" : "Décembre", + "First" : "Première", + "Last" : "Dernière", "Contacts" : "Contacts", "{actor} created address book {addressbook}" : "{actor} a créé le carnet d'adresses {addressbook}", "You created address book {addressbook}" : "Vous avez créé le carnet d'adresses {addressbook}", @@ -169,13 +191,6 @@ "No working hours set" : "Heures de travail non définies", "Add slot" : "Ajouter un créneau", "Weekdays" : "Jours de la semaine", - "Monday" : "Lundi", - "Tuesday" : "Mardi", - "Wednesday" : "Mercredi", - "Thursday" : "Jeudi", - "Friday" : "Vendredi", - "Saturday" : "Samedi", - "Sunday" : "Dimanche", "Pick a start time for {dayName}" : "Choisissez une heure de début pour {dayName}", "Pick a end time for {dayName}" : "Choisissez une heure de fin pour {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Définir automatiquement le statut « Ne pas déranger » en dehors des heures de disponibilités pour désactiver toutes les notifications.", diff --git a/apps/dav/l10n/ga.js b/apps/dav/l10n/ga.js index e640406284c..17e81955e37 100644 --- a/apps/dav/l10n/ga.js +++ b/apps/dav/l10n/ga.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "Cur síos: %s", "Where: %s" : "Cá: %s", "%1$s via %2$s" : "%1$s trí %2$s", + "In a %1$s on %2$s for the entire day" : "I %1$s ar %2$s ar feadh an lae ar fad", + "In a %1$s on %2$s between %3$s - %4$s" : "I %1$s ar %2$s idir %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "I %1$s %2$s ar %3$s ar feadh an lae ar fad", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "I %1$s %2$s ar %3$s idir %4$s - %5$s", + "Could not generate when statement" : "Níorbh fhéidir a ghiniúint nuair a ráiteas", + "Every Day for the entire day" : "Gach Lá don lá ar fad", + "Every Day for the entire day until %1$s" : "Gach Lá ar feadh an lae ar fad go dtí %1$s", + "Every Day between %1$s - %2$s" : "Gach Lá idir %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Gach Lá idir %1$s - %2$s go %3$s", + "Every %1$d Days for the entire day" : "Gach %1$d lá don lá ar fad", + "Every %1$d Days for the entire day until %2$s" : "Gach %1$d Laethanta don lá iomlán go dtí %2$s", + "Every %1$d Days between %2$s - %3$s" : "Gach %1$d Laethanta idir %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Gach %1$d Laethanta idir %2$s - %3$s go %4$s", + "Could not generate event recurrence statement" : "Níorbh fhéidir ráiteas atarlaithe teagmhais a ghiniúint", + "Every Week on %1$s for the entire day" : "Gach seachtain ar %1$s don lá ar fad", + "Every Week on %1$s for the entire day until %2$s" : "Gach seachtain ar %1$s don lá ar fad go dtí %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Gach Seachtain ar %1$s idir %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Gach Seachtain ar %1$s idir %2$s - %3$s go %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Gach %1$d seachtain ar %2$s don lá ar fad", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Gach %1$d seachtain ar %2$s ar feadh an lae ar fad go dtí %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Gach %1$d Seachtain ar %2$s idir %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Gach %1$d Seachtain ar %2$s idir %3$s - %4$s go %5$s", + "Every Month on the %1$s for the entire day" : "Gach Mí ar an %1$s don lá ar fad", + "Every Month on the %1$s for the entire day until %2$s" : "Gach Mí ar an %1$s don lá iomlán go dtí %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Gach Mí ar an %1$s idir %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Gach Mí ar an %1$s idir %2$s - %3$s go %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Gach %1$d Míonna ar an %2$s ar feadh an lae ar fad", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Gach %1$d Míonna ar an %2$s ar feadh an lae ar fad go dtí %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Gach %1$d Mí ar an %2$s idir %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Gach %1$d Mí ar an %2$s idir %3$s - %4$s go %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Gach Bliain i %1$s ar an %2$s ar feadh an lae ar fad", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Gach Bliain i %1$s ar an %2$s ar feadh an lae ar fad go dtí %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Gach Bliain i %1$s ar an %2$s idir %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Gach Bliain i %1$s ar an %2$s idir %3$s - %4$s go %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Gach %1$d Bliain i %2$s ar an %3$s don lá ar fad", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Gach %1$d Bliain i %2$s ar an %3$s don lá ar fad go dtí %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Gach %1$d Bliain i %2$s ar an %3$s idir %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Gach %1$d Bliain i %2$s ar an %3$s idir %4$s - %5$s go %6$s", + "On specific dates for the entire day until %1$s" : "Ar dhátaí ar leith don lá iomlán go dtí %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "Ar dhátaí sonracha idir %1$s - %2$s go %3$s", + "In a %1$s on %2$s" : "I %1$s ar %2$s", + "In a %1$s on %2$s then on %3$s" : "I %1$s ar %2$s ansin ar %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "I %1$s ar %2$s ansin ar %3$s agus %4$s", + "In %1$s %2$s on %3$s" : "I %1$s %2$s ar %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "I %1$s %2$s ar %3$s ansin ar %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "I %1$s %2$s ar %3$s ansin ar %4$s agus %5$s", + "Could not generate next recurrence statement" : "Níorbh fhéidir an chéad ráiteas atarlaithe eile a ghiniúint", "Cancelled: %1$s" : "Ar ceal: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" curtha ar ceal", "Re: %1$s" : "Maidir le: %1$s", @@ -86,13 +133,43 @@ OC.L10N.register( "Organizer:" : "Eagraí:", "Attendees:" : "Lucht freastail:", "Title:" : "Teideal:", - "Date and time:" : "Dáta agus am:", + "When:" : "Cathain:", "Location:" : "Suíomh:", "Link:" : "Nasc:", + "Occurring:" : "Ag tarlú:", "Accept" : "Glac", "Decline" : "Meath", "More options …" : "Tuilleadh roghanna…", "More options at %s" : "Tuilleadh roghanna ag %s", + "Monday" : "Luan", + "Tuesday" : "Máirt", + "Wednesday" : "Céadaoin", + "Thursday" : "Déardaoin", + "Friday" : "Aoine", + "Saturday" : "Sathairn", + "Sunday" : "Domhnach", + "January" : "Eanáir", + "February" : "Feabhra", + "March" : "Márta", + "April" : "Aibreán", + "May" : "Bealtaine", + "June" : "Meitheamh", + "July" : "Iúil", + "August" : "Lúnasa", + "September" : "Meán Fómhair", + "October" : "Deireadh Fómhair", + "November" : "Samhain", + "December" : "Nollaig", + "First" : "Ar dtús", + "Second" : "Dara", + "Third" : "Tríú", + "Fourth" : "Ceathrú", + "Fifty" : "Caoga", + "Last" : "Seo caite", + "Second Last" : "Dara Deireanach", + "Third Last" : "An Tríú Deireanach", + "Fourth Last" : "Ceathrú Deireanach", + "Fifty Last" : "Caoga Deireanach", "Contacts" : "Teagmhálaithe", "{actor} created address book {addressbook}" : "chruthaigh {actor} leabhar seoltaí {addressbook}", "You created address book {addressbook}" : "Chruthaigh tú leabhar seoltaí {addressbook}", @@ -176,13 +253,6 @@ OC.L10N.register( "No working hours set" : "Níl aon uaireanta oibre socraithe", "Add slot" : "Cuir sliotán", "Weekdays" : "Laethanta na seachtaine", - "Monday" : "Luan", - "Tuesday" : "Máirt", - "Wednesday" : "Céadaoin", - "Thursday" : "Déardaoin", - "Friday" : "Aoine", - "Saturday" : "Sathairn", - "Sunday" : "Domhnach", "Pick a start time for {dayName}" : "Roghnaigh am tosaithe le haghaidh {dayName}", "Pick a end time for {dayName}" : "Roghnaigh am críochnaithe le haghaidh {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Socraigh stádas úsáideora go huathoibríoch mar \"Ná cuir isteach\" taobh amuigh den infhaighteacht chun gach fógra a bhalbhú.", diff --git a/apps/dav/l10n/ga.json b/apps/dav/l10n/ga.json index ed6d0c8c3d7..5002ac9ff09 100644 --- a/apps/dav/l10n/ga.json +++ b/apps/dav/l10n/ga.json @@ -70,6 +70,53 @@ "Description: %s" : "Cur síos: %s", "Where: %s" : "Cá: %s", "%1$s via %2$s" : "%1$s trí %2$s", + "In a %1$s on %2$s for the entire day" : "I %1$s ar %2$s ar feadh an lae ar fad", + "In a %1$s on %2$s between %3$s - %4$s" : "I %1$s ar %2$s idir %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "I %1$s %2$s ar %3$s ar feadh an lae ar fad", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "I %1$s %2$s ar %3$s idir %4$s - %5$s", + "Could not generate when statement" : "Níorbh fhéidir a ghiniúint nuair a ráiteas", + "Every Day for the entire day" : "Gach Lá don lá ar fad", + "Every Day for the entire day until %1$s" : "Gach Lá ar feadh an lae ar fad go dtí %1$s", + "Every Day between %1$s - %2$s" : "Gach Lá idir %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Gach Lá idir %1$s - %2$s go %3$s", + "Every %1$d Days for the entire day" : "Gach %1$d lá don lá ar fad", + "Every %1$d Days for the entire day until %2$s" : "Gach %1$d Laethanta don lá iomlán go dtí %2$s", + "Every %1$d Days between %2$s - %3$s" : "Gach %1$d Laethanta idir %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Gach %1$d Laethanta idir %2$s - %3$s go %4$s", + "Could not generate event recurrence statement" : "Níorbh fhéidir ráiteas atarlaithe teagmhais a ghiniúint", + "Every Week on %1$s for the entire day" : "Gach seachtain ar %1$s don lá ar fad", + "Every Week on %1$s for the entire day until %2$s" : "Gach seachtain ar %1$s don lá ar fad go dtí %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Gach Seachtain ar %1$s idir %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Gach Seachtain ar %1$s idir %2$s - %3$s go %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Gach %1$d seachtain ar %2$s don lá ar fad", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Gach %1$d seachtain ar %2$s ar feadh an lae ar fad go dtí %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Gach %1$d Seachtain ar %2$s idir %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Gach %1$d Seachtain ar %2$s idir %3$s - %4$s go %5$s", + "Every Month on the %1$s for the entire day" : "Gach Mí ar an %1$s don lá ar fad", + "Every Month on the %1$s for the entire day until %2$s" : "Gach Mí ar an %1$s don lá iomlán go dtí %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Gach Mí ar an %1$s idir %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Gach Mí ar an %1$s idir %2$s - %3$s go %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Gach %1$d Míonna ar an %2$s ar feadh an lae ar fad", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Gach %1$d Míonna ar an %2$s ar feadh an lae ar fad go dtí %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Gach %1$d Mí ar an %2$s idir %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Gach %1$d Mí ar an %2$s idir %3$s - %4$s go %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Gach Bliain i %1$s ar an %2$s ar feadh an lae ar fad", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Gach Bliain i %1$s ar an %2$s ar feadh an lae ar fad go dtí %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Gach Bliain i %1$s ar an %2$s idir %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Gach Bliain i %1$s ar an %2$s idir %3$s - %4$s go %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Gach %1$d Bliain i %2$s ar an %3$s don lá ar fad", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Gach %1$d Bliain i %2$s ar an %3$s don lá ar fad go dtí %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Gach %1$d Bliain i %2$s ar an %3$s idir %4$s - %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Gach %1$d Bliain i %2$s ar an %3$s idir %4$s - %5$s go %6$s", + "On specific dates for the entire day until %1$s" : "Ar dhátaí ar leith don lá iomlán go dtí %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "Ar dhátaí sonracha idir %1$s - %2$s go %3$s", + "In a %1$s on %2$s" : "I %1$s ar %2$s", + "In a %1$s on %2$s then on %3$s" : "I %1$s ar %2$s ansin ar %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "I %1$s ar %2$s ansin ar %3$s agus %4$s", + "In %1$s %2$s on %3$s" : "I %1$s %2$s ar %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "I %1$s %2$s ar %3$s ansin ar %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "I %1$s %2$s ar %3$s ansin ar %4$s agus %5$s", + "Could not generate next recurrence statement" : "Níorbh fhéidir an chéad ráiteas atarlaithe eile a ghiniúint", "Cancelled: %1$s" : "Ar ceal: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" curtha ar ceal", "Re: %1$s" : "Maidir le: %1$s", @@ -84,13 +131,43 @@ "Organizer:" : "Eagraí:", "Attendees:" : "Lucht freastail:", "Title:" : "Teideal:", - "Date and time:" : "Dáta agus am:", + "When:" : "Cathain:", "Location:" : "Suíomh:", "Link:" : "Nasc:", + "Occurring:" : "Ag tarlú:", "Accept" : "Glac", "Decline" : "Meath", "More options …" : "Tuilleadh roghanna…", "More options at %s" : "Tuilleadh roghanna ag %s", + "Monday" : "Luan", + "Tuesday" : "Máirt", + "Wednesday" : "Céadaoin", + "Thursday" : "Déardaoin", + "Friday" : "Aoine", + "Saturday" : "Sathairn", + "Sunday" : "Domhnach", + "January" : "Eanáir", + "February" : "Feabhra", + "March" : "Márta", + "April" : "Aibreán", + "May" : "Bealtaine", + "June" : "Meitheamh", + "July" : "Iúil", + "August" : "Lúnasa", + "September" : "Meán Fómhair", + "October" : "Deireadh Fómhair", + "November" : "Samhain", + "December" : "Nollaig", + "First" : "Ar dtús", + "Second" : "Dara", + "Third" : "Tríú", + "Fourth" : "Ceathrú", + "Fifty" : "Caoga", + "Last" : "Seo caite", + "Second Last" : "Dara Deireanach", + "Third Last" : "An Tríú Deireanach", + "Fourth Last" : "Ceathrú Deireanach", + "Fifty Last" : "Caoga Deireanach", "Contacts" : "Teagmhálaithe", "{actor} created address book {addressbook}" : "chruthaigh {actor} leabhar seoltaí {addressbook}", "You created address book {addressbook}" : "Chruthaigh tú leabhar seoltaí {addressbook}", @@ -174,13 +251,6 @@ "No working hours set" : "Níl aon uaireanta oibre socraithe", "Add slot" : "Cuir sliotán", "Weekdays" : "Laethanta na seachtaine", - "Monday" : "Luan", - "Tuesday" : "Máirt", - "Wednesday" : "Céadaoin", - "Thursday" : "Déardaoin", - "Friday" : "Aoine", - "Saturday" : "Sathairn", - "Sunday" : "Domhnach", "Pick a start time for {dayName}" : "Roghnaigh am tosaithe le haghaidh {dayName}", "Pick a end time for {dayName}" : "Roghnaigh am críochnaithe le haghaidh {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Socraigh stádas úsáideora go huathoibríoch mar \"Ná cuir isteach\" taobh amuigh den infhaighteacht chun gach fógra a bhalbhú.", diff --git a/apps/dav/l10n/gl.js b/apps/dav/l10n/gl.js index 809737112a9..06799347fef 100644 --- a/apps/dav/l10n/gl.js +++ b/apps/dav/l10n/gl.js @@ -34,8 +34,8 @@ OC.L10N.register( "You updated event {event} in calendar {calendar}" : "Vde. actualizou o evento {event} no calendario {calendar}", "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} moveu o evento {event} do calendario {sourceCalendar} ao calendario {targetCalendar}", "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "Moveu o evento {evento} do calendario {sourceCalendar} ao calendario {targetCalendar}", - "{actor} restored event {event} of calendar {calendar}" : "{actor} restaurou o evento {evento} do calendario {calendar}", - "You restored event {event} of calendar {calendar}" : "Restaurou o evento {evento} do calendario {calendar}", + "{actor} restored event {event} of calendar {calendar}" : "{actor} restaurou o evento {event} do calendario {calendar}", + "You restored event {event} of calendar {calendar}" : "Restaurou o evento {event} do calendario {calendar}", "Busy" : "Ocupado", "{actor} created to-do {todo} in list {calendar}" : "{actor} creou a tarefa pendente {todo} na lista {calendar}", "You created to-do {todo} in list {calendar}" : "Creou a tarefa pendente {todo} na lista {calendar}", @@ -72,6 +72,43 @@ OC.L10N.register( "Description: %s" : "Descrición: %s", "Where: %s" : "Onde: %s", "%1$s via %2$s" : "%1$s mediante %2$s", + "Could not generate when statement" : "Non foi posíbel xerar a declaración when (cando)", + "Every Day for the entire day" : "Todos os días durante todo o día", + "Every Day for the entire day until %1$s" : "Todos os días durante todo o día ata %1$s", + "Every Day between %1$s - %2$s" : "Todos os días entre %1$s e %2$s", + "Every Day between %1$s - %2$s until %3$s" : " Todos os días entre %1$s e %2$s ata %3$s", + "Every %1$d Days for the entire day" : "Cada %1$d días durante todo o día", + "Every %1$d Days for the entire day until %2$s" : "Cada %1$d días durante todo o día ata %2$s", + "Every %1$d Days between %2$s - %3$s" : "Cada %1$d días entre %2$s e %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Cada %1$d días entre %2$s e %3$s ata %4$s", + "Could not generate event recurrence statement" : "Non foi posíbel xerar a declaración de recorrencia do evento", + "Every Week on %1$s for the entire day" : "Todas as semanas o %1$s durante todo o día", + "Every Week on %1$s for the entire day until %2$s" : "Todas as semanas o %1$s durante todo o día ata %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Todas as semanas o %1$s entre %2$s e %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Todas as semanas o %1$s entre %2$s e %3$s ata %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Cada %1$d semanas o %2$s durante todo o día", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Cada %1$d semanas o %2$s durante todo o día ata %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Cada %1$d semanas o %2$s entre %3$s e %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Cada %1$d semanas o %2$s entre %3$s e %4$s ata %5$s", + "Every Month on the %1$s for the entire day" : "Todos os meses o %1$s durante todo o día", + "Every Month on the %1$s for the entire day until %2$s" : "Todos os meses o %1$s durante todo o día ata %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Todos os meses o %1$s entre %2$s e %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todos os meses o %1$s entre %2$s e %3$s ata %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Cada %1$d meses o %2$s durante todo o día", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Cada %1$d meses o %2$s durante todo o día ata %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Cada %1$d meses o %2$s entre %3$s e %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Cada %1$d meses o %2$s entre %3$s e %4$s ata %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Todos os anos en %1$s, o %2$s durante todo o día", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todos os anos en %1$s, o %2$s durante todo o día ata %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todos os anos en %1$s, o %2$s entre %3$s e %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todos os anos en %1$s, o %2$s entre %3$s e %4$s ata %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Cada %1$d anos en %2$s, o %3$s durante todo o día", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Cada %1$d anos en %2$s, o %3$s durante todo o día ata %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Cada %1$d anos en %2$s, o %3$s entre %4$s e %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Cada %1$d anos en %2$s, o %3$s entre %4$s e %5$s ata %6$s", + "On specific dates for the entire day until %1$s" : "En datas concretas durante todo o día ata %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "En datas concretas entre %1$s e %2$s ata %3$s", + "Could not generate next recurrence statement" : "Non foi posíbel xerar a seguinte declaración de recorrencia", "Cancelled: %1$s" : "Cancelado: %1$s", "\"%1$s\" has been canceled" : "Cancelouse «%1$s»", "Re: %1$s" : "Re: %1$s", @@ -86,13 +123,43 @@ OC.L10N.register( "Organizer:" : "Organizador:", "Attendees:" : "Asistentes:", "Title:" : "Título:", - "Date and time:" : "Día e hora:", + "When:" : "Cando:", "Location:" : "Lugar:", "Link:" : "Ligazón:", + "Occurring:" : "Acaecendo:", "Accept" : "Aceptar", "Decline" : "Declinar", "More options …" : "Máis opcións…", "More options at %s" : "Máis opcións en %s", + "Monday" : "luns", + "Tuesday" : "martes", + "Wednesday" : "mércores", + "Thursday" : "xoves", + "Friday" : "venres", + "Saturday" : "sábado", + "Sunday" : "domingo", + "January" : "xaneiro", + "February" : "febreiro", + "March" : "marzo", + "April" : "abril", + "May" : "maio", + "June" : "xuño", + "July" : "xullo", + "August" : "agosto", + "September" : "setembro", + "October" : "outubro", + "November" : "novembro", + "December" : "decembro", + "First" : "Primeiro", + "Second" : "Segundo", + "Third" : "Terceiro", + "Fourth" : "Cuarto", + "Fifty" : "Cincuenta", + "Last" : "Último", + "Second Last" : "Penúltimo", + "Third Last" : "Antepenúltimo", + "Fourth Last" : "Trasantepenúltimo", + "Fifty Last" : "Cincuenta últimos", "Contacts" : "Contactos", "{actor} created address book {addressbook}" : "{actor} creou o caderno de enderezos {addressbook}", "You created address book {addressbook}" : "Vde. creou o caderno de enderezos {addressbook}", @@ -148,7 +215,7 @@ OC.L10N.register( "DAV system address book" : "Caderno de enderezos do sistema DAV", "No outstanding DAV system address book sync." : "Non hai sincronización pendente do caderno de enderezos do sistema DAV.", "The DAV system address book sync has not run yet as your instance has more than 1000 users or because an error occurred. Please run it manually by calling \"occ dav:sync-system-addressbook\"." : "A sincronización do caderno de enderezos do sistema DAV aínda non foi executada aínda porque a súa instancia ten máis de 1000 usuarios ou porque se produciu un erro. Execútea manualmente con occ dav:sync-system-addressbook.", - "WebDAV endpoint" : "Terminación WebDAV", + "WebDAV endpoint" : "Punto final WebDAV", "Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Non foi posíbel comprobar que o seu servidor web estea configurado correctamente para permitir a sincronización de ficheiros a través de WebDAV. Compróbeo manualmente.", "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "O servidor non foi configurado correctamente para permitir a sincronización de ficheiros, semella que a interface WebDAV non está a funcionar.", "Your web server is properly set up to allow file synchronization over WebDAV." : "O seu servidor web está configurado correctamente para permitir a sincronización de ficheiros a través de WebDAV.", @@ -176,13 +243,6 @@ OC.L10N.register( "No working hours set" : "Sen horario de traballo estabelecido", "Add slot" : "Engadir franxa horaria", "Weekdays" : "Días laborábeis", - "Monday" : "luns", - "Tuesday" : "martes", - "Wednesday" : "mércores", - "Thursday" : "xoves", - "Friday" : "venres", - "Saturday" : "sábado", - "Sunday" : "domingo", "Pick a start time for {dayName}" : "Escolla unha hora de inicio para {dayName}", "Pick a end time for {dayName}" : "Escolla unha hora de finalización para {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Definir automaticamente o estado do usuario en «Non molestar» fóra de dispoñibilidade para silenciar todas as notificacións.", diff --git a/apps/dav/l10n/gl.json b/apps/dav/l10n/gl.json index 27ddd4f44c7..136bf4c4fac 100644 --- a/apps/dav/l10n/gl.json +++ b/apps/dav/l10n/gl.json @@ -32,8 +32,8 @@ "You updated event {event} in calendar {calendar}" : "Vde. actualizou o evento {event} no calendario {calendar}", "{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} moveu o evento {event} do calendario {sourceCalendar} ao calendario {targetCalendar}", "You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "Moveu o evento {evento} do calendario {sourceCalendar} ao calendario {targetCalendar}", - "{actor} restored event {event} of calendar {calendar}" : "{actor} restaurou o evento {evento} do calendario {calendar}", - "You restored event {event} of calendar {calendar}" : "Restaurou o evento {evento} do calendario {calendar}", + "{actor} restored event {event} of calendar {calendar}" : "{actor} restaurou o evento {event} do calendario {calendar}", + "You restored event {event} of calendar {calendar}" : "Restaurou o evento {event} do calendario {calendar}", "Busy" : "Ocupado", "{actor} created to-do {todo} in list {calendar}" : "{actor} creou a tarefa pendente {todo} na lista {calendar}", "You created to-do {todo} in list {calendar}" : "Creou a tarefa pendente {todo} na lista {calendar}", @@ -70,6 +70,43 @@ "Description: %s" : "Descrición: %s", "Where: %s" : "Onde: %s", "%1$s via %2$s" : "%1$s mediante %2$s", + "Could not generate when statement" : "Non foi posíbel xerar a declaración when (cando)", + "Every Day for the entire day" : "Todos os días durante todo o día", + "Every Day for the entire day until %1$s" : "Todos os días durante todo o día ata %1$s", + "Every Day between %1$s - %2$s" : "Todos os días entre %1$s e %2$s", + "Every Day between %1$s - %2$s until %3$s" : " Todos os días entre %1$s e %2$s ata %3$s", + "Every %1$d Days for the entire day" : "Cada %1$d días durante todo o día", + "Every %1$d Days for the entire day until %2$s" : "Cada %1$d días durante todo o día ata %2$s", + "Every %1$d Days between %2$s - %3$s" : "Cada %1$d días entre %2$s e %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Cada %1$d días entre %2$s e %3$s ata %4$s", + "Could not generate event recurrence statement" : "Non foi posíbel xerar a declaración de recorrencia do evento", + "Every Week on %1$s for the entire day" : "Todas as semanas o %1$s durante todo o día", + "Every Week on %1$s for the entire day until %2$s" : "Todas as semanas o %1$s durante todo o día ata %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Todas as semanas o %1$s entre %2$s e %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Todas as semanas o %1$s entre %2$s e %3$s ata %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Cada %1$d semanas o %2$s durante todo o día", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Cada %1$d semanas o %2$s durante todo o día ata %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Cada %1$d semanas o %2$s entre %3$s e %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Cada %1$d semanas o %2$s entre %3$s e %4$s ata %5$s", + "Every Month on the %1$s for the entire day" : "Todos os meses o %1$s durante todo o día", + "Every Month on the %1$s for the entire day until %2$s" : "Todos os meses o %1$s durante todo o día ata %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Todos os meses o %1$s entre %2$s e %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todos os meses o %1$s entre %2$s e %3$s ata %4$s", + "Every %1$d Months on the %2$s for the entire day" : "Cada %1$d meses o %2$s durante todo o día", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "Cada %1$d meses o %2$s durante todo o día ata %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "Cada %1$d meses o %2$s entre %3$s e %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Cada %1$d meses o %2$s entre %3$s e %4$s ata %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Todos os anos en %1$s, o %2$s durante todo o día", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todos os anos en %1$s, o %2$s durante todo o día ata %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todos os anos en %1$s, o %2$s entre %3$s e %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todos os anos en %1$s, o %2$s entre %3$s e %4$s ata %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "Cada %1$d anos en %2$s, o %3$s durante todo o día", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Cada %1$d anos en %2$s, o %3$s durante todo o día ata %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Cada %1$d anos en %2$s, o %3$s entre %4$s e %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Cada %1$d anos en %2$s, o %3$s entre %4$s e %5$s ata %6$s", + "On specific dates for the entire day until %1$s" : "En datas concretas durante todo o día ata %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "En datas concretas entre %1$s e %2$s ata %3$s", + "Could not generate next recurrence statement" : "Non foi posíbel xerar a seguinte declaración de recorrencia", "Cancelled: %1$s" : "Cancelado: %1$s", "\"%1$s\" has been canceled" : "Cancelouse «%1$s»", "Re: %1$s" : "Re: %1$s", @@ -84,13 +121,43 @@ "Organizer:" : "Organizador:", "Attendees:" : "Asistentes:", "Title:" : "Título:", - "Date and time:" : "Día e hora:", + "When:" : "Cando:", "Location:" : "Lugar:", "Link:" : "Ligazón:", + "Occurring:" : "Acaecendo:", "Accept" : "Aceptar", "Decline" : "Declinar", "More options …" : "Máis opcións…", "More options at %s" : "Máis opcións en %s", + "Monday" : "luns", + "Tuesday" : "martes", + "Wednesday" : "mércores", + "Thursday" : "xoves", + "Friday" : "venres", + "Saturday" : "sábado", + "Sunday" : "domingo", + "January" : "xaneiro", + "February" : "febreiro", + "March" : "marzo", + "April" : "abril", + "May" : "maio", + "June" : "xuño", + "July" : "xullo", + "August" : "agosto", + "September" : "setembro", + "October" : "outubro", + "November" : "novembro", + "December" : "decembro", + "First" : "Primeiro", + "Second" : "Segundo", + "Third" : "Terceiro", + "Fourth" : "Cuarto", + "Fifty" : "Cincuenta", + "Last" : "Último", + "Second Last" : "Penúltimo", + "Third Last" : "Antepenúltimo", + "Fourth Last" : "Trasantepenúltimo", + "Fifty Last" : "Cincuenta últimos", "Contacts" : "Contactos", "{actor} created address book {addressbook}" : "{actor} creou o caderno de enderezos {addressbook}", "You created address book {addressbook}" : "Vde. creou o caderno de enderezos {addressbook}", @@ -146,7 +213,7 @@ "DAV system address book" : "Caderno de enderezos do sistema DAV", "No outstanding DAV system address book sync." : "Non hai sincronización pendente do caderno de enderezos do sistema DAV.", "The DAV system address book sync has not run yet as your instance has more than 1000 users or because an error occurred. Please run it manually by calling \"occ dav:sync-system-addressbook\"." : "A sincronización do caderno de enderezos do sistema DAV aínda non foi executada aínda porque a súa instancia ten máis de 1000 usuarios ou porque se produciu un erro. Execútea manualmente con occ dav:sync-system-addressbook.", - "WebDAV endpoint" : "Terminación WebDAV", + "WebDAV endpoint" : "Punto final WebDAV", "Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Non foi posíbel comprobar que o seu servidor web estea configurado correctamente para permitir a sincronización de ficheiros a través de WebDAV. Compróbeo manualmente.", "Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "O servidor non foi configurado correctamente para permitir a sincronización de ficheiros, semella que a interface WebDAV non está a funcionar.", "Your web server is properly set up to allow file synchronization over WebDAV." : "O seu servidor web está configurado correctamente para permitir a sincronización de ficheiros a través de WebDAV.", @@ -174,13 +241,6 @@ "No working hours set" : "Sen horario de traballo estabelecido", "Add slot" : "Engadir franxa horaria", "Weekdays" : "Días laborábeis", - "Monday" : "luns", - "Tuesday" : "martes", - "Wednesday" : "mércores", - "Thursday" : "xoves", - "Friday" : "venres", - "Saturday" : "sábado", - "Sunday" : "domingo", "Pick a start time for {dayName}" : "Escolla unha hora de inicio para {dayName}", "Pick a end time for {dayName}" : "Escolla unha hora de finalización para {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Definir automaticamente o estado do usuario en «Non molestar» fóra de dispoñibilidade para silenciar todas as notificacións.", diff --git a/apps/dav/l10n/hr.js b/apps/dav/l10n/hr.js index c7256707f6d..1d4f4d9200f 100644 --- a/apps/dav/l10n/hr.js +++ b/apps/dav/l10n/hr.js @@ -63,12 +63,34 @@ OC.L10N.register( "Organizer:" : "Organizator:", "Attendees:" : "Polaznici:", "Title:" : "Naslov:", + "When:" : "Kada:", "Location:" : "Lokacija:", "Link:" : "Poveznica:", "Accept" : "Prihvati", "Decline" : "Odbij", "More options …" : "Više mogućnosti…", "More options at %s" : "Više mogućnosti na %s", + "Monday" : "Ponedjeljak", + "Tuesday" : "Utorak", + "Wednesday" : "Srijeda", + "Thursday" : "Četvrtak", + "Friday" : "Petak", + "Saturday" : "Subota", + "Sunday" : "Nedjelja", + "January" : "Siječanj", + "February" : "Veljača", + "March" : "Ožujak", + "April" : "Travanj", + "May" : "Svibanj", + "June" : "Lipanj", + "July" : "Srpanj", + "August" : "Kolovoz", + "September" : "Rujan", + "October" : "Listopad", + "November" : "Studeni", + "December" : "Prosinac", + "First" : "Prvi", + "Last" : "Zadnji", "Contacts" : "Kontakti", "{actor} created address book {addressbook}" : "{actor} je stvorio adresar {addressbook}", "You created address book {addressbook}" : "Stvorili ste adresar {addressbook}", @@ -113,13 +135,6 @@ OC.L10N.register( "to" : "do", "Delete slot" : "Izbriši mjesto", "Add slot" : "Dodaj mjesto", - "Monday" : "Ponedjeljak", - "Tuesday" : "Utorak", - "Wednesday" : "Srijeda", - "Thursday" : "Četvrtak", - "Friday" : "Petak", - "Saturday" : "Subota", - "Sunday" : "Nedjelja", "Availability" : "Raspoloživost", "Calendar server" : "Poslužitelj kalendara", "Send invitations to attendees" : "Pošaljite pozive sudionicima", diff --git a/apps/dav/l10n/hr.json b/apps/dav/l10n/hr.json index 1aebbc88d36..9686e89c7c0 100644 --- a/apps/dav/l10n/hr.json +++ b/apps/dav/l10n/hr.json @@ -61,12 +61,34 @@ "Organizer:" : "Organizator:", "Attendees:" : "Polaznici:", "Title:" : "Naslov:", + "When:" : "Kada:", "Location:" : "Lokacija:", "Link:" : "Poveznica:", "Accept" : "Prihvati", "Decline" : "Odbij", "More options …" : "Više mogućnosti…", "More options at %s" : "Više mogućnosti na %s", + "Monday" : "Ponedjeljak", + "Tuesday" : "Utorak", + "Wednesday" : "Srijeda", + "Thursday" : "Četvrtak", + "Friday" : "Petak", + "Saturday" : "Subota", + "Sunday" : "Nedjelja", + "January" : "Siječanj", + "February" : "Veljača", + "March" : "Ožujak", + "April" : "Travanj", + "May" : "Svibanj", + "June" : "Lipanj", + "July" : "Srpanj", + "August" : "Kolovoz", + "September" : "Rujan", + "October" : "Listopad", + "November" : "Studeni", + "December" : "Prosinac", + "First" : "Prvi", + "Last" : "Zadnji", "Contacts" : "Kontakti", "{actor} created address book {addressbook}" : "{actor} je stvorio adresar {addressbook}", "You created address book {addressbook}" : "Stvorili ste adresar {addressbook}", @@ -111,13 +133,6 @@ "to" : "do", "Delete slot" : "Izbriši mjesto", "Add slot" : "Dodaj mjesto", - "Monday" : "Ponedjeljak", - "Tuesday" : "Utorak", - "Wednesday" : "Srijeda", - "Thursday" : "Četvrtak", - "Friday" : "Petak", - "Saturday" : "Subota", - "Sunday" : "Nedjelja", "Availability" : "Raspoloživost", "Calendar server" : "Poslužitelj kalendara", "Send invitations to attendees" : "Pošaljite pozive sudionicima", diff --git a/apps/dav/l10n/hu.js b/apps/dav/l10n/hu.js index a62c065a9cf..e9efbd0f703 100644 --- a/apps/dav/l10n/hu.js +++ b/apps/dav/l10n/hu.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Szervező:", "Attendees:" : "Résztvevők:", "Title:" : "Cím:", + "When:" : "Mikor:", "Location:" : "Hely:", "Link:" : "Hivatkozás:", "Accept" : "Elfogadás", "Decline" : "Elutasítás", "More options …" : "További lehetőségek…", "More options at %s" : "További lehetőségek itt: %s", + "Monday" : "Hétfő", + "Tuesday" : "Kedd", + "Wednesday" : "Szerda", + "Thursday" : "Csütörtök", + "Friday" : "Péntek", + "Saturday" : "Szombat", + "Sunday" : "Vasárnap", + "January" : "Január", + "February" : "Február", + "March" : "Március", + "April" : "Április", + "May" : "Május", + "June" : "Június", + "July" : "Július", + "August" : "Augusztus", + "September" : "Szeptember", + "October" : "Október", + "November" : "November", + "December" : "December", + "First" : "Első", + "Last" : "Utolsó", "Contacts" : "Névjegyek", "{actor} created address book {addressbook}" : "{actor} létrehozta a következő címjegyzéket: {addressbook}", "You created address book {addressbook}" : "Létrehozta a következő címjegyzéket: {addressbook}", @@ -159,13 +181,6 @@ OC.L10N.register( "Delete slot" : "Idősáv törlése", "No working hours set" : "Nincs munkaidő beállítva", "Add slot" : "Idősáv hozzáadása", - "Monday" : "Hétfő", - "Tuesday" : "Kedd", - "Wednesday" : "Szerda", - "Thursday" : "Csütörtök", - "Friday" : "Péntek", - "Saturday" : "Szombat", - "Sunday" : "Vasárnap", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Az elérhetőségi időn túl, a felhasználói állapot automatikus beállítása „Ne zavarjanak” módba az összes értesítés némításához.", "Failed to load availability" : "Az elérhetőség betöltése sikertelen", "Saved availability" : "Elérhetőség mentve", diff --git a/apps/dav/l10n/hu.json b/apps/dav/l10n/hu.json index 02450de30c2..07bdd9556db 100644 --- a/apps/dav/l10n/hu.json +++ b/apps/dav/l10n/hu.json @@ -84,12 +84,34 @@ "Organizer:" : "Szervező:", "Attendees:" : "Résztvevők:", "Title:" : "Cím:", + "When:" : "Mikor:", "Location:" : "Hely:", "Link:" : "Hivatkozás:", "Accept" : "Elfogadás", "Decline" : "Elutasítás", "More options …" : "További lehetőségek…", "More options at %s" : "További lehetőségek itt: %s", + "Monday" : "Hétfő", + "Tuesday" : "Kedd", + "Wednesday" : "Szerda", + "Thursday" : "Csütörtök", + "Friday" : "Péntek", + "Saturday" : "Szombat", + "Sunday" : "Vasárnap", + "January" : "Január", + "February" : "Február", + "March" : "Március", + "April" : "Április", + "May" : "Május", + "June" : "Június", + "July" : "Július", + "August" : "Augusztus", + "September" : "Szeptember", + "October" : "Október", + "November" : "November", + "December" : "December", + "First" : "Első", + "Last" : "Utolsó", "Contacts" : "Névjegyek", "{actor} created address book {addressbook}" : "{actor} létrehozta a következő címjegyzéket: {addressbook}", "You created address book {addressbook}" : "Létrehozta a következő címjegyzéket: {addressbook}", @@ -157,13 +179,6 @@ "Delete slot" : "Idősáv törlése", "No working hours set" : "Nincs munkaidő beállítva", "Add slot" : "Idősáv hozzáadása", - "Monday" : "Hétfő", - "Tuesday" : "Kedd", - "Wednesday" : "Szerda", - "Thursday" : "Csütörtök", - "Friday" : "Péntek", - "Saturday" : "Szombat", - "Sunday" : "Vasárnap", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Az elérhetőségi időn túl, a felhasználói állapot automatikus beállítása „Ne zavarjanak” módba az összes értesítés némításához.", "Failed to load availability" : "Az elérhetőség betöltése sikertelen", "Saved availability" : "Elérhetőség mentve", diff --git a/apps/dav/l10n/is.js b/apps/dav/l10n/is.js index 3f7cb7120c0..28a0ec073ff 100644 --- a/apps/dav/l10n/is.js +++ b/apps/dav/l10n/is.js @@ -86,12 +86,32 @@ OC.L10N.register( "Organizer:" : "Skipuleggjandi:", "Attendees:" : "Þáttakendur:", "Title:" : "Titill:", + "When:" : "Hvenær:", "Location:" : "Staðsetning:", "Link:" : "Tengill:", "Accept" : "Samþykkja", "Decline" : "Hafna", "More options …" : "Fleiri valkostir ...", "More options at %s" : "Fleiri valkostir á %s", + "Monday" : "Mánudagur", + "Tuesday" : "Þriðjudagur", + "Wednesday" : "Miðvikudagur", + "Thursday" : "Fimmtudagur", + "Friday" : "Föstudagur", + "Saturday" : "Laugardagur", + "Sunday" : "Sunnudagur", + "January" : "Janúar", + "February" : "Febrúar", + "March" : "Mars", + "April" : "Apríl", + "May" : "Maí", + "June" : "Júní", + "July" : "Júlí", + "August" : "Ágúst", + "September" : "September", + "October" : "Október", + "November" : "Nóvember", + "December" : "Desember", "Contacts" : "Tengiliðir", "{actor} created address book {addressbook}" : "{actor} útbjó nafnaskrána {addressbook}", "You created address book {addressbook}" : "Þú bjóst til nafnaskrána {addressbook}", @@ -168,13 +188,6 @@ OC.L10N.register( "Delete slot" : "Eyða tímahólfi", "No working hours set" : "Enginn vinnutími stilltur", "Add slot" : "Bæta við tímahólfi", - "Monday" : "Mánudagur", - "Tuesday" : "Þriðjudagur", - "Wednesday" : "Miðvikudagur", - "Thursday" : "Fimmtudagur", - "Friday" : "Föstudagur", - "Saturday" : "Laugardagur", - "Sunday" : "Sunnudagur", "Pick a start time for {dayName}" : "Veldu upphafstíma fyrir {dayName}", "Pick a end time for {dayName}" : "Veldu lokatíma fyrir {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setja stöðu notenda sjálfkrafa á \"Ekki ónáða\" utan þess lausa tíma sem viðkomandi er tiltækur, til að þagga niður í öllum tilkynningum.", diff --git a/apps/dav/l10n/is.json b/apps/dav/l10n/is.json index 5038c24abfa..d3da8d8c7e3 100644 --- a/apps/dav/l10n/is.json +++ b/apps/dav/l10n/is.json @@ -84,12 +84,32 @@ "Organizer:" : "Skipuleggjandi:", "Attendees:" : "Þáttakendur:", "Title:" : "Titill:", + "When:" : "Hvenær:", "Location:" : "Staðsetning:", "Link:" : "Tengill:", "Accept" : "Samþykkja", "Decline" : "Hafna", "More options …" : "Fleiri valkostir ...", "More options at %s" : "Fleiri valkostir á %s", + "Monday" : "Mánudagur", + "Tuesday" : "Þriðjudagur", + "Wednesday" : "Miðvikudagur", + "Thursday" : "Fimmtudagur", + "Friday" : "Föstudagur", + "Saturday" : "Laugardagur", + "Sunday" : "Sunnudagur", + "January" : "Janúar", + "February" : "Febrúar", + "March" : "Mars", + "April" : "Apríl", + "May" : "Maí", + "June" : "Júní", + "July" : "Júlí", + "August" : "Ágúst", + "September" : "September", + "October" : "Október", + "November" : "Nóvember", + "December" : "Desember", "Contacts" : "Tengiliðir", "{actor} created address book {addressbook}" : "{actor} útbjó nafnaskrána {addressbook}", "You created address book {addressbook}" : "Þú bjóst til nafnaskrána {addressbook}", @@ -166,13 +186,6 @@ "Delete slot" : "Eyða tímahólfi", "No working hours set" : "Enginn vinnutími stilltur", "Add slot" : "Bæta við tímahólfi", - "Monday" : "Mánudagur", - "Tuesday" : "Þriðjudagur", - "Wednesday" : "Miðvikudagur", - "Thursday" : "Fimmtudagur", - "Friday" : "Föstudagur", - "Saturday" : "Laugardagur", - "Sunday" : "Sunnudagur", "Pick a start time for {dayName}" : "Veldu upphafstíma fyrir {dayName}", "Pick a end time for {dayName}" : "Veldu lokatíma fyrir {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Setja stöðu notenda sjálfkrafa á \"Ekki ónáða\" utan þess lausa tíma sem viðkomandi er tiltækur, til að þagga niður í öllum tilkynningum.", diff --git a/apps/dav/l10n/it.js b/apps/dav/l10n/it.js index bf3779710f9..44ab48d9a87 100644 --- a/apps/dav/l10n/it.js +++ b/apps/dav/l10n/it.js @@ -86,13 +86,34 @@ OC.L10N.register( "Organizer:" : "Organizzatore:", "Attendees:" : "Partecipanti:", "Title:" : "Titolo:", - "Date and time:" : "Data e ora:", + "When:" : "Quando:", "Location:" : "Posizione:", "Link:" : "Collegamento:", "Accept" : "Accetta", "Decline" : "Rifiuta", "More options …" : "Altre opzioni...", "More options at %s" : "Altre opzioni alle %s", + "Monday" : "Lunedì", + "Tuesday" : "Martedì", + "Wednesday" : "Mercoledì", + "Thursday" : "Giovedì", + "Friday" : "Venerdì", + "Saturday" : "Sabato", + "Sunday" : "Domenica", + "January" : "Gennaio", + "February" : "Febbraio", + "March" : "Marzo", + "April" : "Aprile", + "May" : "Maggio", + "June" : "Giugno", + "July" : "Luglio", + "August" : "Agosto", + "September" : "Settembre", + "October" : "Ottobre", + "November" : "Novembre", + "December" : "Dicembre", + "First" : "Primo", + "Last" : "Ultimo", "Contacts" : "Contatti", "{actor} created address book {addressbook}" : "{actor} ha creato la rubrica {addressbook}", "You created address book {addressbook}" : "Hai creato la rubrica {addressbook}", @@ -172,13 +193,6 @@ OC.L10N.register( "No working hours set" : "Orari lavorativi non impostati", "Add slot" : "Aggiungi slot", "Weekdays" : "Giorni feriali", - "Monday" : "Lunedì", - "Tuesday" : "Martedì", - "Wednesday" : "Mercoledì", - "Thursday" : "Giovedì", - "Friday" : "Venerdì", - "Saturday" : "Sabato", - "Sunday" : "Domenica", "Pick a start time for {dayName}" : "Scegli un orario di inizio per {dayName}", "Pick a end time for {dayName}" : "Scegli un orario di fine per {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Imposta automaticamente lo stato dell'utente su \"Non disturbare\" al di fuori della disponibilità per disattivare tutte le notifiche.", diff --git a/apps/dav/l10n/it.json b/apps/dav/l10n/it.json index 6986a03aa47..fd8acbd5655 100644 --- a/apps/dav/l10n/it.json +++ b/apps/dav/l10n/it.json @@ -84,13 +84,34 @@ "Organizer:" : "Organizzatore:", "Attendees:" : "Partecipanti:", "Title:" : "Titolo:", - "Date and time:" : "Data e ora:", + "When:" : "Quando:", "Location:" : "Posizione:", "Link:" : "Collegamento:", "Accept" : "Accetta", "Decline" : "Rifiuta", "More options …" : "Altre opzioni...", "More options at %s" : "Altre opzioni alle %s", + "Monday" : "Lunedì", + "Tuesday" : "Martedì", + "Wednesday" : "Mercoledì", + "Thursday" : "Giovedì", + "Friday" : "Venerdì", + "Saturday" : "Sabato", + "Sunday" : "Domenica", + "January" : "Gennaio", + "February" : "Febbraio", + "March" : "Marzo", + "April" : "Aprile", + "May" : "Maggio", + "June" : "Giugno", + "July" : "Luglio", + "August" : "Agosto", + "September" : "Settembre", + "October" : "Ottobre", + "November" : "Novembre", + "December" : "Dicembre", + "First" : "Primo", + "Last" : "Ultimo", "Contacts" : "Contatti", "{actor} created address book {addressbook}" : "{actor} ha creato la rubrica {addressbook}", "You created address book {addressbook}" : "Hai creato la rubrica {addressbook}", @@ -170,13 +191,6 @@ "No working hours set" : "Orari lavorativi non impostati", "Add slot" : "Aggiungi slot", "Weekdays" : "Giorni feriali", - "Monday" : "Lunedì", - "Tuesday" : "Martedì", - "Wednesday" : "Mercoledì", - "Thursday" : "Giovedì", - "Friday" : "Venerdì", - "Saturday" : "Sabato", - "Sunday" : "Domenica", "Pick a start time for {dayName}" : "Scegli un orario di inizio per {dayName}", "Pick a end time for {dayName}" : "Scegli un orario di fine per {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Imposta automaticamente lo stato dell'utente su \"Non disturbare\" al di fuori della disponibilità per disattivare tutte le notifiche.", diff --git a/apps/dav/l10n/ja.js b/apps/dav/l10n/ja.js index 130daf34c9d..31c1bdc796e 100644 --- a/apps/dav/l10n/ja.js +++ b/apps/dav/l10n/ja.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "説明:%s", "Where: %s" : "場所:%s", "%1$s via %2$s" : "%1$s に %2$s から", + "In a %1$s on %2$s for the entire day" : "一日中%2$sの%1$sで", + "In a %1$s on %2$s between %3$s - %4$s" : "%3$sから%4$sの間の%2$sの%1$sで", + "In %1$s %2$s on %3$s for the entire day" : "終日、%3$sの%1$s %2$sにて", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "%4$s-%5$s間の%3$sで%1$s %2$sに", + "Could not generate when statement" : "when文を生成できませんでした", + "Every Day for the entire day" : "毎日、終日", + "Every Day for the entire day until %1$s" : "%1$sまでの終日、毎日", + "Every Day between %1$s - %2$s" : "%1$sから%2$sの間の毎日", + "Every Day between %1$s - %2$s until %3$s" : "%1$sから%2$sの間で%3$sまで毎日", + "Every %1$d Days for the entire day" : "%1$d日ごとに終日", + "Every %1$d Days for the entire day until %2$s" : "%1$d日ごと、%2$sまで終日", + "Every %1$d Days between %2$s - %3$s" : "%2$s~%3$sの間で%1$d日ごと", + "Every %1$d Days between %2$s - %3$s until %4$s" : "%1$d日ごと %2$s~%3$sの間、%4$sまで", + "Could not generate event recurrence statement" : "イベントの再帰ステートメントを生成できませんでした", + "Every Week on %1$s for the entire day" : "毎週%1$sで終日", + "Every Week on %1$s for the entire day until %2$s" : "毎週%1$sに%2$sまで終日", + "Every Week on %1$s between %2$s - %3$s" : "毎週%1$s、%2$s~%3$sの間", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "毎週%1$s、%2$s~%3$sの間に%4$sまで", + "Every %1$d Weeks on %2$s for the entire day" : "%1$d週ごと%2$sで終日", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "%1$d週ごと%2$sに%3$sまで終日", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "%1$d週ごとの%2$s %3$s~%4$sの間", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "%1$d週ごと%2$s %5$sまで%3$s~%4$sの間", + "Every Month on the %1$s for the entire day" : "毎月%1$sに終日", + "Every Month on the %1$s for the entire day until %2$s" : "毎月%1$s、%2$sまでの終日", + "Every Month on the %1$s between %2$s - %3$s" : "毎月%2$s~%3$sの間の%1$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "毎月、%2$s~%3$sの間の%1$sに、%4$sまで", + "Every %1$d Months on the %2$s for the entire day" : "%1$dカ月ごとの%2$sに終日", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "%1$dカ月ごとの%2$s、%3$sまで終日", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "%1$dカ月ごとの%2$s、%3$s~%4$sの間", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "%1$dカ月ごとの%2$s、%3$s~%4$sの間、%5$sまで", + "Every Year in %1$s on the %2$s for the entire day" : "毎年%1$s %2$sに終日", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "毎年%1$s %2$s %3$sまで終日", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "毎年%1$s %2$s %3$s~%4$sの間の終日", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "毎年%1$s %2$s %3$s~ %4$s %5$sまで ", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "%1$d年ごとの%2$s %3$sの終日", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "%1$d年ごとの%2$s %3$s %4$sまでの終日", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "%1$d年ごとの%2$s %3$s %4$s~%5$sの間", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "%1$d年ごとの%2$s %3$s %4$s~%5$sの間、%6$sまで", + "On specific dates for the entire day until %1$s" : "%1$sまでの特定の日付の終日", + "On specific dates between %1$s - %2$s until %3$s" : "%1$s~%2$sの間、%3$sまでの特定の日付", + "In a %1$s on %2$s" : "%2$sの%1$s", + "In a %1$s on %2$s then on %3$s" : "%2$sそして%3$sの%1$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "%2$sそして%3$sと%4$sの%1$s", + "In %1$s %2$s on %3$s" : "%3$sの%1$s %2$s", + "In %1$s %2$s on %3$s then on %4$s" : "%3$sそして%4$sの%1$s %2$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "%3$sそして%4$sと%5$sの%1$s %2$s", + "Could not generate next recurrence statement" : "次の再帰ステートメントを生成できませんでした", "Cancelled: %1$s" : "キャンセル: %1$s", "\"%1$s\" has been canceled" : "%1$sはキャンセルされました", "Re: %1$s" : "更新: %1$s", @@ -86,13 +133,43 @@ OC.L10N.register( "Organizer:" : "主催者:", "Attendees:" : "参加者:", "Title:" : "タイトル:", - "Date and time:" : "日時", + "When:" : "いつ:", "Location:" : "場所:", "Link:" : "リンク:", + "Occurring:" : "発生:", "Accept" : "承諾", "Decline" : "拒否", "More options …" : "他のオプション …", "More options at %s" : "%s のその他のオプション", + "Monday" : "月曜日", + "Tuesday" : "火曜日", + "Wednesday" : "水曜日", + "Thursday" : "木曜日", + "Friday" : "金曜日", + "Saturday" : "土曜日", + "Sunday" : "日曜日", + "January" : "1月", + "February" : "2月", + "March" : "3月", + "April" : "4月", + "May" : "5月", + "June" : "6月", + "July" : "7月", + "August" : "8月", + "September" : "9月", + "October" : "10月", + "November" : "11月", + "December" : "12月", + "First" : "第1", + "Second" : "第2", + "Third" : "第3", + "Fourth" : "第4", + "Fifty" : "第50", + "Last" : "最後", + "Second Last" : "最後から2番目", + "Third Last" : "最後から3番目", + "Fourth Last" : "最後から4番目", + "Fifty Last" : "最後から50番目", "Contacts" : "連絡先", "{actor} created address book {addressbook}" : "{actor}がアドレス帳 {addressbook}を作成しました", "You created address book {addressbook}" : "アドレス帳 {addressbook}を作成しました", @@ -176,13 +253,6 @@ OC.L10N.register( "No working hours set" : "勤務時間未設定", "Add slot" : "スロットを追加", "Weekdays" : "平日", - "Monday" : "月曜日", - "Tuesday" : "火曜日", - "Wednesday" : "水曜日", - "Thursday" : "木曜日", - "Friday" : "金曜日", - "Saturday" : "土曜日", - "Sunday" : "日曜日", "Pick a start time for {dayName}" : "{dayName} 開始時間を指定してください", "Pick a end time for {dayName}" : "{dayName} の終了時間を指定してください", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "利用時間外は自動的にユーザーステータスを\"非通知\" に設定し、すべての通知をミュートします。", diff --git a/apps/dav/l10n/ja.json b/apps/dav/l10n/ja.json index 8429a931a44..b3d90ee1bf1 100644 --- a/apps/dav/l10n/ja.json +++ b/apps/dav/l10n/ja.json @@ -70,6 +70,53 @@ "Description: %s" : "説明:%s", "Where: %s" : "場所:%s", "%1$s via %2$s" : "%1$s に %2$s から", + "In a %1$s on %2$s for the entire day" : "一日中%2$sの%1$sで", + "In a %1$s on %2$s between %3$s - %4$s" : "%3$sから%4$sの間の%2$sの%1$sで", + "In %1$s %2$s on %3$s for the entire day" : "終日、%3$sの%1$s %2$sにて", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "%4$s-%5$s間の%3$sで%1$s %2$sに", + "Could not generate when statement" : "when文を生成できませんでした", + "Every Day for the entire day" : "毎日、終日", + "Every Day for the entire day until %1$s" : "%1$sまでの終日、毎日", + "Every Day between %1$s - %2$s" : "%1$sから%2$sの間の毎日", + "Every Day between %1$s - %2$s until %3$s" : "%1$sから%2$sの間で%3$sまで毎日", + "Every %1$d Days for the entire day" : "%1$d日ごとに終日", + "Every %1$d Days for the entire day until %2$s" : "%1$d日ごと、%2$sまで終日", + "Every %1$d Days between %2$s - %3$s" : "%2$s~%3$sの間で%1$d日ごと", + "Every %1$d Days between %2$s - %3$s until %4$s" : "%1$d日ごと %2$s~%3$sの間、%4$sまで", + "Could not generate event recurrence statement" : "イベントの再帰ステートメントを生成できませんでした", + "Every Week on %1$s for the entire day" : "毎週%1$sで終日", + "Every Week on %1$s for the entire day until %2$s" : "毎週%1$sに%2$sまで終日", + "Every Week on %1$s between %2$s - %3$s" : "毎週%1$s、%2$s~%3$sの間", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "毎週%1$s、%2$s~%3$sの間に%4$sまで", + "Every %1$d Weeks on %2$s for the entire day" : "%1$d週ごと%2$sで終日", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "%1$d週ごと%2$sに%3$sまで終日", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "%1$d週ごとの%2$s %3$s~%4$sの間", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "%1$d週ごと%2$s %5$sまで%3$s~%4$sの間", + "Every Month on the %1$s for the entire day" : "毎月%1$sに終日", + "Every Month on the %1$s for the entire day until %2$s" : "毎月%1$s、%2$sまでの終日", + "Every Month on the %1$s between %2$s - %3$s" : "毎月%2$s~%3$sの間の%1$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "毎月、%2$s~%3$sの間の%1$sに、%4$sまで", + "Every %1$d Months on the %2$s for the entire day" : "%1$dカ月ごとの%2$sに終日", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "%1$dカ月ごとの%2$s、%3$sまで終日", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "%1$dカ月ごとの%2$s、%3$s~%4$sの間", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "%1$dカ月ごとの%2$s、%3$s~%4$sの間、%5$sまで", + "Every Year in %1$s on the %2$s for the entire day" : "毎年%1$s %2$sに終日", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "毎年%1$s %2$s %3$sまで終日", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "毎年%1$s %2$s %3$s~%4$sの間の終日", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "毎年%1$s %2$s %3$s~ %4$s %5$sまで ", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "%1$d年ごとの%2$s %3$sの終日", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "%1$d年ごとの%2$s %3$s %4$sまでの終日", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "%1$d年ごとの%2$s %3$s %4$s~%5$sの間", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "%1$d年ごとの%2$s %3$s %4$s~%5$sの間、%6$sまで", + "On specific dates for the entire day until %1$s" : "%1$sまでの特定の日付の終日", + "On specific dates between %1$s - %2$s until %3$s" : "%1$s~%2$sの間、%3$sまでの特定の日付", + "In a %1$s on %2$s" : "%2$sの%1$s", + "In a %1$s on %2$s then on %3$s" : "%2$sそして%3$sの%1$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "%2$sそして%3$sと%4$sの%1$s", + "In %1$s %2$s on %3$s" : "%3$sの%1$s %2$s", + "In %1$s %2$s on %3$s then on %4$s" : "%3$sそして%4$sの%1$s %2$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "%3$sそして%4$sと%5$sの%1$s %2$s", + "Could not generate next recurrence statement" : "次の再帰ステートメントを生成できませんでした", "Cancelled: %1$s" : "キャンセル: %1$s", "\"%1$s\" has been canceled" : "%1$sはキャンセルされました", "Re: %1$s" : "更新: %1$s", @@ -84,13 +131,43 @@ "Organizer:" : "主催者:", "Attendees:" : "参加者:", "Title:" : "タイトル:", - "Date and time:" : "日時", + "When:" : "いつ:", "Location:" : "場所:", "Link:" : "リンク:", + "Occurring:" : "発生:", "Accept" : "承諾", "Decline" : "拒否", "More options …" : "他のオプション …", "More options at %s" : "%s のその他のオプション", + "Monday" : "月曜日", + "Tuesday" : "火曜日", + "Wednesday" : "水曜日", + "Thursday" : "木曜日", + "Friday" : "金曜日", + "Saturday" : "土曜日", + "Sunday" : "日曜日", + "January" : "1月", + "February" : "2月", + "March" : "3月", + "April" : "4月", + "May" : "5月", + "June" : "6月", + "July" : "7月", + "August" : "8月", + "September" : "9月", + "October" : "10月", + "November" : "11月", + "December" : "12月", + "First" : "第1", + "Second" : "第2", + "Third" : "第3", + "Fourth" : "第4", + "Fifty" : "第50", + "Last" : "最後", + "Second Last" : "最後から2番目", + "Third Last" : "最後から3番目", + "Fourth Last" : "最後から4番目", + "Fifty Last" : "最後から50番目", "Contacts" : "連絡先", "{actor} created address book {addressbook}" : "{actor}がアドレス帳 {addressbook}を作成しました", "You created address book {addressbook}" : "アドレス帳 {addressbook}を作成しました", @@ -174,13 +251,6 @@ "No working hours set" : "勤務時間未設定", "Add slot" : "スロットを追加", "Weekdays" : "平日", - "Monday" : "月曜日", - "Tuesday" : "火曜日", - "Wednesday" : "水曜日", - "Thursday" : "木曜日", - "Friday" : "金曜日", - "Saturday" : "土曜日", - "Sunday" : "日曜日", "Pick a start time for {dayName}" : "{dayName} 開始時間を指定してください", "Pick a end time for {dayName}" : "{dayName} の終了時間を指定してください", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "利用時間外は自動的にユーザーステータスを\"非通知\" に設定し、すべての通知をミュートします。", diff --git a/apps/dav/l10n/ka.js b/apps/dav/l10n/ka.js index f468868840e..bb79114cf9e 100644 --- a/apps/dav/l10n/ka.js +++ b/apps/dav/l10n/ka.js @@ -92,6 +92,25 @@ OC.L10N.register( "Decline" : "Decline", "More options …" : "More options …", "More options at %s" : "More options at %s", + "Monday" : "Monday", + "Tuesday" : "Tuesday", + "Wednesday" : "Wednesday", + "Thursday" : "Thursday", + "Friday" : "Friday", + "Saturday" : "Saturday", + "Sunday" : "Sunday", + "January" : "January", + "February" : "February", + "March" : "March", + "April" : "April", + "May" : "May", + "June" : "June", + "July" : "July", + "August" : "August", + "September" : "September", + "October" : "October", + "November" : "November", + "December" : "December", "Contacts" : "Contacts", "{actor} created address book {addressbook}" : "{actor} created address book {addressbook}", "You created address book {addressbook}" : "You created address book {addressbook}", @@ -168,13 +187,6 @@ OC.L10N.register( "Delete slot" : "Delete slot", "No working hours set" : "No working hours set", "Add slot" : "Add slot", - "Monday" : "Monday", - "Tuesday" : "Tuesday", - "Wednesday" : "Wednesday", - "Thursday" : "Thursday", - "Friday" : "Friday", - "Saturday" : "Saturday", - "Sunday" : "Sunday", "Pick a start time for {dayName}" : "Pick a start time for {dayName}", "Pick a end time for {dayName}" : "Pick a end time for {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications.", diff --git a/apps/dav/l10n/ka.json b/apps/dav/l10n/ka.json index 6d94d22be0b..f38151e614f 100644 --- a/apps/dav/l10n/ka.json +++ b/apps/dav/l10n/ka.json @@ -90,6 +90,25 @@ "Decline" : "Decline", "More options …" : "More options …", "More options at %s" : "More options at %s", + "Monday" : "Monday", + "Tuesday" : "Tuesday", + "Wednesday" : "Wednesday", + "Thursday" : "Thursday", + "Friday" : "Friday", + "Saturday" : "Saturday", + "Sunday" : "Sunday", + "January" : "January", + "February" : "February", + "March" : "March", + "April" : "April", + "May" : "May", + "June" : "June", + "July" : "July", + "August" : "August", + "September" : "September", + "October" : "October", + "November" : "November", + "December" : "December", "Contacts" : "Contacts", "{actor} created address book {addressbook}" : "{actor} created address book {addressbook}", "You created address book {addressbook}" : "You created address book {addressbook}", @@ -166,13 +185,6 @@ "Delete slot" : "Delete slot", "No working hours set" : "No working hours set", "Add slot" : "Add slot", - "Monday" : "Monday", - "Tuesday" : "Tuesday", - "Wednesday" : "Wednesday", - "Thursday" : "Thursday", - "Friday" : "Friday", - "Saturday" : "Saturday", - "Sunday" : "Sunday", "Pick a start time for {dayName}" : "Pick a start time for {dayName}", "Pick a end time for {dayName}" : "Pick a end time for {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications.", diff --git a/apps/dav/l10n/ko.js b/apps/dav/l10n/ko.js index 61fff0cb4f1..584e106fec6 100644 --- a/apps/dav/l10n/ko.js +++ b/apps/dav/l10n/ko.js @@ -86,12 +86,32 @@ OC.L10N.register( "Organizer:" : "주최자:", "Attendees:" : "참석자:", "Title:" : "제목:", + "When:" : "일시:", "Location:" : "위치:", "Link:" : "링크:", "Accept" : "수락", "Decline" : "거절", "More options …" : "더 많은 옵션 …", "More options at %s" : "%s에 더 많은 옵션 있음", + "Monday" : "월요일", + "Tuesday" : "화요일", + "Wednesday" : "수요일", + "Thursday" : "목요일", + "Friday" : "금요일", + "Saturday" : "토요일", + "Sunday" : "일요일", + "January" : "1월", + "February" : "2월", + "March" : "3월", + "April" : "4월", + "May" : "5월", + "June" : "6월", + "July" : "7월", + "August" : "8월", + "September" : "9월", + "October" : "10월", + "November" : "11월", + "December" : "12월", "Contacts" : "연락처", "{actor} created address book {addressbook}" : "{actor}님이 주소록 {addressbook}을(를) 생성함", "You created address book {addressbook}" : "주소록 {addressbook}을(를) 생성함", @@ -167,13 +187,6 @@ OC.L10N.register( "Delete slot" : "시간대 삭제", "No working hours set" : "업무 시간이 설정되지 않음", "Add slot" : "시간대 추가", - "Monday" : "월요일", - "Tuesday" : "화요일", - "Wednesday" : "수요일", - "Thursday" : "목요일", - "Friday" : "금요일", - "Saturday" : "토요일", - "Sunday" : "일요일", "Pick a start time for {dayName}" : "{dayName} 시작 시각을 지정하십시오", "Pick a end time for {dayName}" : "{dayName} 종료 시각을 지정하십시오", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "다른 용무 중일 때 자동으로 사용자를 '방해 금지' 모드로 설정해 모든 알림을 음소거합니다.", diff --git a/apps/dav/l10n/ko.json b/apps/dav/l10n/ko.json index 876ae488275..db5e8992e35 100644 --- a/apps/dav/l10n/ko.json +++ b/apps/dav/l10n/ko.json @@ -84,12 +84,32 @@ "Organizer:" : "주최자:", "Attendees:" : "참석자:", "Title:" : "제목:", + "When:" : "일시:", "Location:" : "위치:", "Link:" : "링크:", "Accept" : "수락", "Decline" : "거절", "More options …" : "더 많은 옵션 …", "More options at %s" : "%s에 더 많은 옵션 있음", + "Monday" : "월요일", + "Tuesday" : "화요일", + "Wednesday" : "수요일", + "Thursday" : "목요일", + "Friday" : "금요일", + "Saturday" : "토요일", + "Sunday" : "일요일", + "January" : "1월", + "February" : "2월", + "March" : "3월", + "April" : "4월", + "May" : "5월", + "June" : "6월", + "July" : "7월", + "August" : "8월", + "September" : "9월", + "October" : "10월", + "November" : "11월", + "December" : "12월", "Contacts" : "연락처", "{actor} created address book {addressbook}" : "{actor}님이 주소록 {addressbook}을(를) 생성함", "You created address book {addressbook}" : "주소록 {addressbook}을(를) 생성함", @@ -165,13 +185,6 @@ "Delete slot" : "시간대 삭제", "No working hours set" : "업무 시간이 설정되지 않음", "Add slot" : "시간대 추가", - "Monday" : "월요일", - "Tuesday" : "화요일", - "Wednesday" : "수요일", - "Thursday" : "목요일", - "Friday" : "금요일", - "Saturday" : "토요일", - "Sunday" : "일요일", "Pick a start time for {dayName}" : "{dayName} 시작 시각을 지정하십시오", "Pick a end time for {dayName}" : "{dayName} 종료 시각을 지정하십시오", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "다른 용무 중일 때 자동으로 사용자를 '방해 금지' 모드로 설정해 모든 알림을 음소거합니다.", diff --git a/apps/dav/l10n/mk.js b/apps/dav/l10n/mk.js index 02aeab1c044..11ca67b34a2 100644 --- a/apps/dav/l10n/mk.js +++ b/apps/dav/l10n/mk.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Организатор:", "Attendees:" : "Присутни:", "Title:" : "Наслов:", + "When:" : "Кога:", "Location:" : "Локација:", "Link:" : "Линк:", "Accept" : "Прифати", "Decline" : "Одбиј", "More options …" : "Повеќе опции ...", "More options at %s" : "Повеќе опции на %s", + "Monday" : "Понеделник", + "Tuesday" : "Вторник", + "Wednesday" : "Среда", + "Thursday" : "Четврток", + "Friday" : "Петок", + "Saturday" : "Сабота", + "Sunday" : "Недела", + "January" : "Јануари", + "February" : "Февруари", + "March" : "Март", + "April" : "Април", + "May" : "Мај", + "June" : "Јуни", + "July" : "Јули", + "August" : "Август", + "September" : "Септември", + "October" : "Октомври", + "November" : "Ноември", + "December" : "Декември", + "First" : "Прва", + "Last" : "Последна", "Contacts" : "Контакти", "{actor} created address book {addressbook}" : "{actor} креираше адресар {addressbook}", "You created address book {addressbook}" : "Креиравте адресар {addressbook}", @@ -150,13 +172,6 @@ OC.L10N.register( "No working hours set" : "Не се поставени работни часови", "Add slot" : "Додади слот", "Weekdays" : "Работни денови", - "Monday" : "Понеделник", - "Tuesday" : "Вторник", - "Wednesday" : "Среда", - "Thursday" : "Четврток", - "Friday" : "Петок", - "Saturday" : "Сабота", - "Sunday" : "Недела", "Pick a start time for {dayName}" : "Избери почетно време за {dayName}", "Pick a end time for {dayName}" : "Избери крајно време за {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматско поставување на статус во \"Не вознемирувај\" недостапен за да ги занемите сите известувања.", diff --git a/apps/dav/l10n/mk.json b/apps/dav/l10n/mk.json index ae5298ca4f6..5e78816131e 100644 --- a/apps/dav/l10n/mk.json +++ b/apps/dav/l10n/mk.json @@ -84,12 +84,34 @@ "Organizer:" : "Организатор:", "Attendees:" : "Присутни:", "Title:" : "Наслов:", + "When:" : "Кога:", "Location:" : "Локација:", "Link:" : "Линк:", "Accept" : "Прифати", "Decline" : "Одбиј", "More options …" : "Повеќе опции ...", "More options at %s" : "Повеќе опции на %s", + "Monday" : "Понеделник", + "Tuesday" : "Вторник", + "Wednesday" : "Среда", + "Thursday" : "Четврток", + "Friday" : "Петок", + "Saturday" : "Сабота", + "Sunday" : "Недела", + "January" : "Јануари", + "February" : "Февруари", + "March" : "Март", + "April" : "Април", + "May" : "Мај", + "June" : "Јуни", + "July" : "Јули", + "August" : "Август", + "September" : "Септември", + "October" : "Октомври", + "November" : "Ноември", + "December" : "Декември", + "First" : "Прва", + "Last" : "Последна", "Contacts" : "Контакти", "{actor} created address book {addressbook}" : "{actor} креираше адресар {addressbook}", "You created address book {addressbook}" : "Креиравте адресар {addressbook}", @@ -148,13 +170,6 @@ "No working hours set" : "Не се поставени работни часови", "Add slot" : "Додади слот", "Weekdays" : "Работни денови", - "Monday" : "Понеделник", - "Tuesday" : "Вторник", - "Wednesday" : "Среда", - "Thursday" : "Четврток", - "Friday" : "Петок", - "Saturday" : "Сабота", - "Sunday" : "Недела", "Pick a start time for {dayName}" : "Избери почетно време за {dayName}", "Pick a end time for {dayName}" : "Избери крајно време за {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматско поставување на статус во \"Не вознемирувај\" недостапен за да ги занемите сите известувања.", diff --git a/apps/dav/l10n/nb.js b/apps/dav/l10n/nb.js index 34e140e1864..39d92e3dee5 100644 --- a/apps/dav/l10n/nb.js +++ b/apps/dav/l10n/nb.js @@ -72,6 +72,25 @@ OC.L10N.register( "Description: %s" : "Beskrivelse: %s", "Where: %s" : "Hvor: %s", "%1$s via %2$s" : "%1$s via %2$s", + "In a %1$s on %2$s for the entire day" : "Om %1$s på %2$s for hele dagen", + "In a %1$s on %2$s between %3$s - %4$s" : "Om %1$s på %2$s mellom %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "Om %1$s %2$s på %3$s for hele dagen", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "Om %1$s %2$s på %3$s mellom %4$s - %5$s", + "Could not generate when statement" : "Kunne ikke generere når-beskrivelse", + "Every Day for the entire day" : "Hver dag for hele dagen", + "Every Day for the entire day until %1$s" : "Hver dag for hele dagen til %1$s", + "Every Day between %1$s - %2$s" : "Hver dag mellom %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Hver dag mellom %1$s - %2$s til %3$s", + "Every %1$d Days for the entire day" : "Hver %1$d dag for hele dagen", + "Every %1$d Days for the entire day until %2$s" : "Hver %1$d dag for hele dagen til %2$s", + "Every %1$d Days between %2$s - %3$s" : "Hver %1$d dag mellom %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Hver %1$d dag mellom %2$s - %3$s til %4$s", + "Could not generate event recurrence statement" : "Kunne ikke generere gjentakelse-beskrivelse", + "Every Week on %1$s for the entire day" : "Hver uke på %1$s for hele dagen", + "Every Week on %1$s for the entire day until %2$s" : "Hver uke på %1$s for hele dagen til %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Hver uke på %1$s mellom %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Hver uke på %1$s mellom %2$s - %3$s til %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Hver %1$d uke på %2$s for hele dagen", "Cancelled: %1$s" : "Kansellerte: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" har blitt kansellert", "Re: %1$s" : "Sv: %1$s", @@ -86,13 +105,43 @@ OC.L10N.register( "Organizer:" : "Arrangør:", "Attendees:" : "Deltakere:", "Title:" : "Tittel:", - "Date and time:" : "Dato og tid:", + "When:" : "Når:", "Location:" : "Sted:", "Link:" : "Lenke:", + "Occurring:" : "Forekommer:", "Accept" : "Aksepter", "Decline" : "Avslå", "More options …" : "Flere alternativer ...", "More options at %s" : "Flere alternativer ved %s", + "Monday" : "Mandag", + "Tuesday" : "Tirsdag", + "Wednesday" : "Onsdag", + "Thursday" : "Torsdag", + "Friday" : "Fredag", + "Saturday" : "Lørdag", + "Sunday" : "Søndag", + "January" : "Januar", + "February" : "Februar", + "March" : "Mars", + "April" : "April", + "May" : "Mai", + "June" : "Juni", + "July" : "Juli", + "August" : "August", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "Desember", + "First" : "Først", + "Second" : "Andre", + "Third" : "Tredje", + "Fourth" : "Fjerde", + "Fifty" : "Femti", + "Last" : "Siste", + "Second Last" : "Nest sist", + "Third Last" : "Tredje sist", + "Fourth Last" : "Fjerde sist", + "Fifty Last" : "Femti siste", "Contacts" : "Kontakter", "{actor} created address book {addressbook}" : "{actor} opprettet adresseboken {addressbook}", "You created address book {addressbook}" : "Du opprettet adresseboken {addressbook}", @@ -176,13 +225,6 @@ OC.L10N.register( "No working hours set" : "Ingen arbeidstid satt", "Add slot" : "Legg til tidsrom", "Weekdays" : "Ukedager", - "Monday" : "Mandag", - "Tuesday" : "Tirsdag", - "Wednesday" : "Onsdag", - "Thursday" : "Torsdag", - "Friday" : "Fredag", - "Saturday" : "Lørdag", - "Sunday" : "Søndag", "Pick a start time for {dayName}" : "Velg et starttidspunkt for {dayName}", "Pick a end time for {dayName}" : "Velg et sluttidspunkt for {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Sett brukerstatus automatisk til «Ikke forstyrr» utenfor arbeidstid for å dempe alle varsler.", diff --git a/apps/dav/l10n/nb.json b/apps/dav/l10n/nb.json index 38339fd6253..bb289869c81 100644 --- a/apps/dav/l10n/nb.json +++ b/apps/dav/l10n/nb.json @@ -70,6 +70,25 @@ "Description: %s" : "Beskrivelse: %s", "Where: %s" : "Hvor: %s", "%1$s via %2$s" : "%1$s via %2$s", + "In a %1$s on %2$s for the entire day" : "Om %1$s på %2$s for hele dagen", + "In a %1$s on %2$s between %3$s - %4$s" : "Om %1$s på %2$s mellom %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "Om %1$s %2$s på %3$s for hele dagen", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "Om %1$s %2$s på %3$s mellom %4$s - %5$s", + "Could not generate when statement" : "Kunne ikke generere når-beskrivelse", + "Every Day for the entire day" : "Hver dag for hele dagen", + "Every Day for the entire day until %1$s" : "Hver dag for hele dagen til %1$s", + "Every Day between %1$s - %2$s" : "Hver dag mellom %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Hver dag mellom %1$s - %2$s til %3$s", + "Every %1$d Days for the entire day" : "Hver %1$d dag for hele dagen", + "Every %1$d Days for the entire day until %2$s" : "Hver %1$d dag for hele dagen til %2$s", + "Every %1$d Days between %2$s - %3$s" : "Hver %1$d dag mellom %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Hver %1$d dag mellom %2$s - %3$s til %4$s", + "Could not generate event recurrence statement" : "Kunne ikke generere gjentakelse-beskrivelse", + "Every Week on %1$s for the entire day" : "Hver uke på %1$s for hele dagen", + "Every Week on %1$s for the entire day until %2$s" : "Hver uke på %1$s for hele dagen til %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Hver uke på %1$s mellom %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Hver uke på %1$s mellom %2$s - %3$s til %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Hver %1$d uke på %2$s for hele dagen", "Cancelled: %1$s" : "Kansellerte: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" har blitt kansellert", "Re: %1$s" : "Sv: %1$s", @@ -84,13 +103,43 @@ "Organizer:" : "Arrangør:", "Attendees:" : "Deltakere:", "Title:" : "Tittel:", - "Date and time:" : "Dato og tid:", + "When:" : "Når:", "Location:" : "Sted:", "Link:" : "Lenke:", + "Occurring:" : "Forekommer:", "Accept" : "Aksepter", "Decline" : "Avslå", "More options …" : "Flere alternativer ...", "More options at %s" : "Flere alternativer ved %s", + "Monday" : "Mandag", + "Tuesday" : "Tirsdag", + "Wednesday" : "Onsdag", + "Thursday" : "Torsdag", + "Friday" : "Fredag", + "Saturday" : "Lørdag", + "Sunday" : "Søndag", + "January" : "Januar", + "February" : "Februar", + "March" : "Mars", + "April" : "April", + "May" : "Mai", + "June" : "Juni", + "July" : "Juli", + "August" : "August", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "Desember", + "First" : "Først", + "Second" : "Andre", + "Third" : "Tredje", + "Fourth" : "Fjerde", + "Fifty" : "Femti", + "Last" : "Siste", + "Second Last" : "Nest sist", + "Third Last" : "Tredje sist", + "Fourth Last" : "Fjerde sist", + "Fifty Last" : "Femti siste", "Contacts" : "Kontakter", "{actor} created address book {addressbook}" : "{actor} opprettet adresseboken {addressbook}", "You created address book {addressbook}" : "Du opprettet adresseboken {addressbook}", @@ -174,13 +223,6 @@ "No working hours set" : "Ingen arbeidstid satt", "Add slot" : "Legg til tidsrom", "Weekdays" : "Ukedager", - "Monday" : "Mandag", - "Tuesday" : "Tirsdag", - "Wednesday" : "Onsdag", - "Thursday" : "Torsdag", - "Friday" : "Fredag", - "Saturday" : "Lørdag", - "Sunday" : "Søndag", "Pick a start time for {dayName}" : "Velg et starttidspunkt for {dayName}", "Pick a end time for {dayName}" : "Velg et sluttidspunkt for {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Sett brukerstatus automatisk til «Ikke forstyrr» utenfor arbeidstid for å dempe alle varsler.", diff --git a/apps/dav/l10n/nl.js b/apps/dav/l10n/nl.js index 039eefde1de..452dbe702cd 100644 --- a/apps/dav/l10n/nl.js +++ b/apps/dav/l10n/nl.js @@ -79,12 +79,34 @@ OC.L10N.register( "Organizer:" : "Organisator:", "Attendees:" : "Deelnemers:", "Title:" : "Titel:", + "When:" : "Wanneer:", "Location:" : "Locatie:", "Link:" : "Link:", "Accept" : "Accepteren", "Decline" : "Afwijzen", "More options …" : "Meer opties …", "More options at %s" : "Meer opties op %s", + "Monday" : "maandag", + "Tuesday" : "dinsdag", + "Wednesday" : "woensdag", + "Thursday" : "donderdag", + "Friday" : "vrijdag", + "Saturday" : "zaterdag", + "Sunday" : "zondag", + "January" : "Januari", + "February" : "Februari", + "March" : "Maart", + "April" : "April", + "May" : "Mei", + "June" : "Juni", + "July" : "Juli", + "August" : "Augustus", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "December", + "First" : "Eerste", + "Last" : "Laatste", "Contacts" : "Contactpersonen", "{actor} created address book {addressbook}" : "{actor} creëerde adresboek {addressbook}", "You created address book {addressbook}" : "Je creëerde adresboek {addressbook}", @@ -142,13 +164,6 @@ OC.L10N.register( "Delete slot" : "Verwijder slot", "No working hours set" : "Geen werkuren ingesteld", "Add slot" : "Voeg slot toe", - "Monday" : "maandag", - "Tuesday" : "dinsdag", - "Wednesday" : "woensdag", - "Thursday" : "donderdag", - "Friday" : "vrijdag", - "Saturday" : "zaterdag", - "Sunday" : "zondag", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Stel de gebruikersstatus automatisch in op \"Niet storen\" buiten de beschikbaarheid om alle meldingen te dempen.", "Failed to load availability" : "Kon beschikbaarheid niet laden", "Availability" : "Beschikbaarheid", diff --git a/apps/dav/l10n/nl.json b/apps/dav/l10n/nl.json index a3a30d8add4..bc040d4e19c 100644 --- a/apps/dav/l10n/nl.json +++ b/apps/dav/l10n/nl.json @@ -77,12 +77,34 @@ "Organizer:" : "Organisator:", "Attendees:" : "Deelnemers:", "Title:" : "Titel:", + "When:" : "Wanneer:", "Location:" : "Locatie:", "Link:" : "Link:", "Accept" : "Accepteren", "Decline" : "Afwijzen", "More options …" : "Meer opties …", "More options at %s" : "Meer opties op %s", + "Monday" : "maandag", + "Tuesday" : "dinsdag", + "Wednesday" : "woensdag", + "Thursday" : "donderdag", + "Friday" : "vrijdag", + "Saturday" : "zaterdag", + "Sunday" : "zondag", + "January" : "Januari", + "February" : "Februari", + "March" : "Maart", + "April" : "April", + "May" : "Mei", + "June" : "Juni", + "July" : "Juli", + "August" : "Augustus", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "December", + "First" : "Eerste", + "Last" : "Laatste", "Contacts" : "Contactpersonen", "{actor} created address book {addressbook}" : "{actor} creëerde adresboek {addressbook}", "You created address book {addressbook}" : "Je creëerde adresboek {addressbook}", @@ -140,13 +162,6 @@ "Delete slot" : "Verwijder slot", "No working hours set" : "Geen werkuren ingesteld", "Add slot" : "Voeg slot toe", - "Monday" : "maandag", - "Tuesday" : "dinsdag", - "Wednesday" : "woensdag", - "Thursday" : "donderdag", - "Friday" : "vrijdag", - "Saturday" : "zaterdag", - "Sunday" : "zondag", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Stel de gebruikersstatus automatisch in op \"Niet storen\" buiten de beschikbaarheid om alle meldingen te dempen.", "Failed to load availability" : "Kon beschikbaarheid niet laden", "Availability" : "Beschikbaarheid", diff --git a/apps/dav/l10n/pl.js b/apps/dav/l10n/pl.js index 6b013d924bc..1ddd0efa28c 100644 --- a/apps/dav/l10n/pl.js +++ b/apps/dav/l10n/pl.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Organizator:", "Attendees:" : "Uczestnicy:", "Title:" : "Tytuł:", + "When:" : "Kiedy:", "Location:" : "Lokalizacja:", "Link:" : "Link: ", "Accept" : "Akceptuj", "Decline" : "Odrzuć", "More options …" : "Więcej opcji…", "More options at %s" : "Więcej opcji na %s", + "Monday" : "Poniedziałek", + "Tuesday" : "Wtorek", + "Wednesday" : "Środa", + "Thursday" : "Czwartek", + "Friday" : "Piątek", + "Saturday" : "Sobota", + "Sunday" : "Niedziela", + "January" : "Styczeń", + "February" : "Luty", + "March" : "Marzec", + "April" : "Kwiecień", + "May" : "Maj", + "June" : "Czerwiec", + "July" : "Lipiec", + "August" : "Sierpień", + "September" : "Wrzesień", + "October" : "Październik", + "November" : "Listopad", + "December" : "Grudzień", + "First" : "Pierwsza", + "Last" : "Ostatnia", "Contacts" : "Kontakty", "{actor} created address book {addressbook}" : "{actor} utworzył książkę adresową {addressbook}", "You created address book {addressbook}" : "Utworzyłeś książkę adresową {addressbook}", @@ -166,13 +188,7 @@ OC.L10N.register( "Delete slot" : "Usuń przedział czasu", "No working hours set" : "Nie ustawiono godzin pracy", "Add slot" : "Dodaj przedział czasu", - "Monday" : "Poniedziałek", - "Tuesday" : "Wtorek", - "Wednesday" : "Środa", - "Thursday" : "Czwartek", - "Friday" : "Piątek", - "Saturday" : "Sobota", - "Sunday" : "Niedziela", + "Weekdays" : "Dni powszednie", "Pick a start time for {dayName}" : "Wybierz dzień rozpoczęcia {dayName}", "Pick a end time for {dayName}" : "Wybierz dzień zakończenia {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatycznie ustaw status użytkownika na \"Nie przeszkadzać\" poza dostępnością, aby wyciszyć wszystkie powiadomienia.", diff --git a/apps/dav/l10n/pl.json b/apps/dav/l10n/pl.json index 6a0c9749857..59f59e9e4d4 100644 --- a/apps/dav/l10n/pl.json +++ b/apps/dav/l10n/pl.json @@ -84,12 +84,34 @@ "Organizer:" : "Organizator:", "Attendees:" : "Uczestnicy:", "Title:" : "Tytuł:", + "When:" : "Kiedy:", "Location:" : "Lokalizacja:", "Link:" : "Link: ", "Accept" : "Akceptuj", "Decline" : "Odrzuć", "More options …" : "Więcej opcji…", "More options at %s" : "Więcej opcji na %s", + "Monday" : "Poniedziałek", + "Tuesday" : "Wtorek", + "Wednesday" : "Środa", + "Thursday" : "Czwartek", + "Friday" : "Piątek", + "Saturday" : "Sobota", + "Sunday" : "Niedziela", + "January" : "Styczeń", + "February" : "Luty", + "March" : "Marzec", + "April" : "Kwiecień", + "May" : "Maj", + "June" : "Czerwiec", + "July" : "Lipiec", + "August" : "Sierpień", + "September" : "Wrzesień", + "October" : "Październik", + "November" : "Listopad", + "December" : "Grudzień", + "First" : "Pierwsza", + "Last" : "Ostatnia", "Contacts" : "Kontakty", "{actor} created address book {addressbook}" : "{actor} utworzył książkę adresową {addressbook}", "You created address book {addressbook}" : "Utworzyłeś książkę adresową {addressbook}", @@ -164,13 +186,7 @@ "Delete slot" : "Usuń przedział czasu", "No working hours set" : "Nie ustawiono godzin pracy", "Add slot" : "Dodaj przedział czasu", - "Monday" : "Poniedziałek", - "Tuesday" : "Wtorek", - "Wednesday" : "Środa", - "Thursday" : "Czwartek", - "Friday" : "Piątek", - "Saturday" : "Sobota", - "Sunday" : "Niedziela", + "Weekdays" : "Dni powszednie", "Pick a start time for {dayName}" : "Wybierz dzień rozpoczęcia {dayName}", "Pick a end time for {dayName}" : "Wybierz dzień zakończenia {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatycznie ustaw status użytkownika na \"Nie przeszkadzać\" poza dostępnością, aby wyciszyć wszystkie powiadomienia.", diff --git a/apps/dav/l10n/pt_BR.js b/apps/dav/l10n/pt_BR.js index 406312ec952..4e76249dd0b 100644 --- a/apps/dav/l10n/pt_BR.js +++ b/apps/dav/l10n/pt_BR.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "Descrição: %s", "Where: %s" : "Onde: %s", "%1$s via %2$s" : "%1$s via %2$s", + "In a %1$s on %2$s for the entire day" : "Em %1$s em %2$s durante todo o dia", + "In a %1$s on %2$s between %3$s - %4$s" : "Em um %1$s sobre %2$s entre %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "Em %1$s %2$s em %3$s durante todo o dia", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "Em %1$s %2$s em %3$s entre %4$s - %5$s", + "Could not generate when statement" : "Não foi possível gerar a instrução Quando", + "Every Day for the entire day" : "Todos os dias durante todo o dia", + "Every Day for the entire day until %1$s" : "Todos os dias durante todo o dia até %1$s", + "Every Day between %1$s - %2$s" : "Todos os dias entre %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Todos os dias entre %1$s - %2$s até %3$s", + "Every %1$d Days for the entire day" : "A cada %1$d dias durante o dia inteiro", + "Every %1$d Days for the entire day until %2$s" : "Cada %1$d dias durante todo o dia até %2$s", + "Every %1$d Days between %2$s - %3$s" : "Todo os %1$d Dias entre %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Todo os %1$d Dias entre %2$s - %3$s até %4$s", + "Could not generate event recurrence statement" : "Não foi possível gerar a instrução de recorrência do evento", + "Every Week on %1$s for the entire day" : "Todas as semanas em %1$s durante o dia inteiro", + "Every Week on %1$s for the entire day until %2$s" : "Toda semana em %1$s durante todo o dia até %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Toda semana em %1$s entre %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Toda semana em %1$s entre %2$s - %3$s até %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Todas as %1$d Semanas em %2$s durante o dia inteiro", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Todas as %1$d Semanas em %2$s durante todo o dia até %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Todas as %1$d Semanas em %2$s entre %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Todas as %1$d Semanas em %2$s entre %3$s - %4$s até %5$s", + "Every Month on the %1$s for the entire day" : "Todo mês em %1$s durante todo o dia", + "Every Month on the %1$s for the entire day until %2$s" : "Todos os meses em %1$s durante todo o dia até %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Todo mês nos %1$s entre %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todo mês nos %1$s entre %2$s - %3$s até%4$s", + "Every %1$d Months on the %2$s for the entire day" : "A cada %1$d Meses nos %2$s durante o dia inteiro", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "A cada %1$d Meses no %2$s durante todo o dia até%3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "A cada %1$d Meses nos %2$s entre %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "A cada %1$d Meses nos %2$s entre %3$s - %4$s até %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Todos os anos em %1$s em %2$s durante todo o dia", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todos os anos em %1$s em %2$s durante todo o dia até %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todos os anos em %1$s nos %2$s entre %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todos os anos em %1$s nos %2$s entre %3$s - %4$s até %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "A cada %1$d Anos em %2$s nos %3$s durante o dia inteiro", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "A cada %1$d Anos em %2$s nos %3$s durante todo o dia até %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "A cada %1$d Anos em %2$s nos %3$s entre %4$s - %5$s ", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "A cada %1$d Anos em %2$s nos %3$s entre %4$s - %5$s até%6$s", + "On specific dates for the entire day until %1$s" : "Em datas específicas durante todo o dia até %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "Em datas específicas entre %1$s - %2$s até%3$s", + "In a %1$s on %2$s" : "Em um %1$s em %2$s", + "In a %1$s on %2$s then on %3$s" : "Em %1$s em %2$s e depois %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "Em %1$s em %2$s, depois em %3$s e %4$s", + "In %1$s %2$s on %3$s" : "Em %1$s %2$s em %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "In %1$s %2$s em %3$s então em %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "Em %1$s %2$s em %3$s depois em %4$s e %5$s", + "Could not generate next recurrence statement" : "Não foi possível gerar a próxima instrução de recorrência", "Cancelled: %1$s" : "Cancelado: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" foi cancelado", "Re: %1$s" : "Remetente: %1$s", @@ -86,13 +133,43 @@ OC.L10N.register( "Organizer:" : "Organizador:", "Attendees:" : "Participantes:", "Title:" : "Título:", - "Date and time:" : "Data e hora:", + "When:" : "Quando:", "Location:" : "Localização:", "Link:" : "Link:", + "Occurring:" : "Ocorrendo:", "Accept" : "Aceitar", "Decline" : "Rejeitar", "More options …" : "Mais opções...", "More options at %s" : "Mais opções em %s", + "Monday" : "Segunda-feira", + "Tuesday" : "Terça-feira", + "Wednesday" : "Quarta-feira", + "Thursday" : "Quinta-feira", + "Friday" : "Sexta-feira", + "Saturday" : "Sábado ", + "Sunday" : "Domingo", + "January" : "Janeiro", + "February" : "Fevereiro", + "March" : "Março", + "April" : "Abril", + "May" : "Maio", + "June" : "Junho", + "July" : "Julho", + "August" : "Agosto", + "September" : "Setembro", + "October" : "Outubro", + "November" : "Novembro", + "December" : "Dezembro", + "First" : "Primeiro", + "Second" : "Segunda", + "Third" : "Terça", + "Fourth" : "Quarta", + "Fifty" : "Quinta", + "Last" : "Última", + "Second Last" : "Último segundo", + "Third Last" : "Terceiro Último", + "Fourth Last" : "Quarto Último", + "Fifty Last" : "Quinto Último", "Contacts" : "Contatos", "{actor} created address book {addressbook}" : "{actor} criou o livro de endereço {addressbook}", "You created address book {addressbook}" : "Você criou o catálogo de endereços {addressbook}", @@ -176,13 +253,6 @@ OC.L10N.register( "No working hours set" : "Sem horário de trabalho definido", "Add slot" : "Adicionar slot ", "Weekdays" : "Dias da semana", - "Monday" : "Segunda-feira", - "Tuesday" : "Terça-feira", - "Wednesday" : "Quarta-feira", - "Thursday" : "Quinta-feira", - "Friday" : "Sexta-feira", - "Saturday" : "Sábado ", - "Sunday" : "Domingo", "Pick a start time for {dayName}" : "Selecione um horário de início para {dayName}", "Pick a end time for {dayName}" : "Selecione um horário de fim para {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Defina automaticamente o status do usuário como \"Não perturbe\" fora de disponibilidade para silenciar todas as notificações.", diff --git a/apps/dav/l10n/pt_BR.json b/apps/dav/l10n/pt_BR.json index 05ed3078d08..68334f880c2 100644 --- a/apps/dav/l10n/pt_BR.json +++ b/apps/dav/l10n/pt_BR.json @@ -70,6 +70,53 @@ "Description: %s" : "Descrição: %s", "Where: %s" : "Onde: %s", "%1$s via %2$s" : "%1$s via %2$s", + "In a %1$s on %2$s for the entire day" : "Em %1$s em %2$s durante todo o dia", + "In a %1$s on %2$s between %3$s - %4$s" : "Em um %1$s sobre %2$s entre %3$s - %4$s", + "In %1$s %2$s on %3$s for the entire day" : "Em %1$s %2$s em %3$s durante todo o dia", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "Em %1$s %2$s em %3$s entre %4$s - %5$s", + "Could not generate when statement" : "Não foi possível gerar a instrução Quando", + "Every Day for the entire day" : "Todos os dias durante todo o dia", + "Every Day for the entire day until %1$s" : "Todos os dias durante todo o dia até %1$s", + "Every Day between %1$s - %2$s" : "Todos os dias entre %1$s - %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Todos os dias entre %1$s - %2$s até %3$s", + "Every %1$d Days for the entire day" : "A cada %1$d dias durante o dia inteiro", + "Every %1$d Days for the entire day until %2$s" : "Cada %1$d dias durante todo o dia até %2$s", + "Every %1$d Days between %2$s - %3$s" : "Todo os %1$d Dias entre %2$s - %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Todo os %1$d Dias entre %2$s - %3$s até %4$s", + "Could not generate event recurrence statement" : "Não foi possível gerar a instrução de recorrência do evento", + "Every Week on %1$s for the entire day" : "Todas as semanas em %1$s durante o dia inteiro", + "Every Week on %1$s for the entire day until %2$s" : "Toda semana em %1$s durante todo o dia até %2$s", + "Every Week on %1$s between %2$s - %3$s" : "Toda semana em %1$s entre %2$s - %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "Toda semana em %1$s entre %2$s - %3$s até %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "Todas as %1$d Semanas em %2$s durante o dia inteiro", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "Todas as %1$d Semanas em %2$s durante todo o dia até %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "Todas as %1$d Semanas em %2$s entre %3$s - %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Todas as %1$d Semanas em %2$s entre %3$s - %4$s até %5$s", + "Every Month on the %1$s for the entire day" : "Todo mês em %1$s durante todo o dia", + "Every Month on the %1$s for the entire day until %2$s" : "Todos os meses em %1$s durante todo o dia até %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "Todo mês nos %1$s entre %2$s - %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "Todo mês nos %1$s entre %2$s - %3$s até%4$s", + "Every %1$d Months on the %2$s for the entire day" : "A cada %1$d Meses nos %2$s durante o dia inteiro", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "A cada %1$d Meses no %2$s durante todo o dia até%3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "A cada %1$d Meses nos %2$s entre %3$s - %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "A cada %1$d Meses nos %2$s entre %3$s - %4$s até %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "Todos os anos em %1$s em %2$s durante todo o dia", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "Todos os anos em %1$s em %2$s durante todo o dia até %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "Todos os anos em %1$s nos %2$s entre %3$s - %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Todos os anos em %1$s nos %2$s entre %3$s - %4$s até %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "A cada %1$d Anos em %2$s nos %3$s durante o dia inteiro", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "A cada %1$d Anos em %2$s nos %3$s durante todo o dia até %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "A cada %1$d Anos em %2$s nos %3$s entre %4$s - %5$s ", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "A cada %1$d Anos em %2$s nos %3$s entre %4$s - %5$s até%6$s", + "On specific dates for the entire day until %1$s" : "Em datas específicas durante todo o dia até %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "Em datas específicas entre %1$s - %2$s até%3$s", + "In a %1$s on %2$s" : "Em um %1$s em %2$s", + "In a %1$s on %2$s then on %3$s" : "Em %1$s em %2$s e depois %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "Em %1$s em %2$s, depois em %3$s e %4$s", + "In %1$s %2$s on %3$s" : "Em %1$s %2$s em %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "In %1$s %2$s em %3$s então em %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "Em %1$s %2$s em %3$s depois em %4$s e %5$s", + "Could not generate next recurrence statement" : "Não foi possível gerar a próxima instrução de recorrência", "Cancelled: %1$s" : "Cancelado: %1$s", "\"%1$s\" has been canceled" : "\"%1$s\" foi cancelado", "Re: %1$s" : "Remetente: %1$s", @@ -84,13 +131,43 @@ "Organizer:" : "Organizador:", "Attendees:" : "Participantes:", "Title:" : "Título:", - "Date and time:" : "Data e hora:", + "When:" : "Quando:", "Location:" : "Localização:", "Link:" : "Link:", + "Occurring:" : "Ocorrendo:", "Accept" : "Aceitar", "Decline" : "Rejeitar", "More options …" : "Mais opções...", "More options at %s" : "Mais opções em %s", + "Monday" : "Segunda-feira", + "Tuesday" : "Terça-feira", + "Wednesday" : "Quarta-feira", + "Thursday" : "Quinta-feira", + "Friday" : "Sexta-feira", + "Saturday" : "Sábado ", + "Sunday" : "Domingo", + "January" : "Janeiro", + "February" : "Fevereiro", + "March" : "Março", + "April" : "Abril", + "May" : "Maio", + "June" : "Junho", + "July" : "Julho", + "August" : "Agosto", + "September" : "Setembro", + "October" : "Outubro", + "November" : "Novembro", + "December" : "Dezembro", + "First" : "Primeiro", + "Second" : "Segunda", + "Third" : "Terça", + "Fourth" : "Quarta", + "Fifty" : "Quinta", + "Last" : "Última", + "Second Last" : "Último segundo", + "Third Last" : "Terceiro Último", + "Fourth Last" : "Quarto Último", + "Fifty Last" : "Quinto Último", "Contacts" : "Contatos", "{actor} created address book {addressbook}" : "{actor} criou o livro de endereço {addressbook}", "You created address book {addressbook}" : "Você criou o catálogo de endereços {addressbook}", @@ -174,13 +251,6 @@ "No working hours set" : "Sem horário de trabalho definido", "Add slot" : "Adicionar slot ", "Weekdays" : "Dias da semana", - "Monday" : "Segunda-feira", - "Tuesday" : "Terça-feira", - "Wednesday" : "Quarta-feira", - "Thursday" : "Quinta-feira", - "Friday" : "Sexta-feira", - "Saturday" : "Sábado ", - "Sunday" : "Domingo", "Pick a start time for {dayName}" : "Selecione um horário de início para {dayName}", "Pick a end time for {dayName}" : "Selecione um horário de fim para {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Defina automaticamente o status do usuário como \"Não perturbe\" fora de disponibilidade para silenciar todas as notificações.", diff --git a/apps/dav/l10n/ru.js b/apps/dav/l10n/ru.js index 4d906b924d4..74487d3e568 100644 --- a/apps/dav/l10n/ru.js +++ b/apps/dav/l10n/ru.js @@ -86,13 +86,34 @@ OC.L10N.register( "Organizer:" : "Организатор:", "Attendees:" : "Участники:", "Title:" : "Название:", - "Date and time:" : "Дата и время:", + "When:" : "Когда:", "Location:" : "Местонахождение:", "Link:" : "Ссылка:", "Accept" : "Принять", "Decline" : "Отклонить", "More options …" : "Дополнительные параметры…", "More options at %s" : "Дополнительные параметры на %s", + "Monday" : "Понедельник", + "Tuesday" : "Вторник", + "Wednesday" : "Среда", + "Thursday" : "Четверг", + "Friday" : "Пятница", + "Saturday" : "Суббота", + "Sunday" : "Воскресенье", + "January" : "Январь", + "February" : "Февраль", + "March" : "Март", + "April" : "Апрель", + "May" : "Май", + "June" : "Июнь", + "July" : "Июль", + "August" : "Август", + "September" : "Сентябрь", + "October" : "Октябрь", + "November" : "Ноябрь", + "December" : "Декабрь", + "First" : "Первый", + "Last" : "Последний", "Contacts" : "Контакты", "{actor} created address book {addressbook}" : "{actor} создал(а) адресную книгу «{addressbook}»", "You created address book {addressbook}" : "Вы создали адресную книгу «{addressbook}»", @@ -170,13 +191,6 @@ OC.L10N.register( "No working hours set" : "Рабочие часы не указаны", "Add slot" : "Добавить интервал", "Weekdays" : "Дни недели", - "Monday" : "Понедельник", - "Tuesday" : "Вторник", - "Wednesday" : "Среда", - "Thursday" : "Четверг", - "Friday" : "Пятница", - "Saturday" : "Суббота", - "Sunday" : "Воскресенье", "Pick a start time for {dayName}" : "Выберите время начала в {dayName}", "Pick a end time for {dayName}" : "Выберите время окончания в {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматически изменять статус на «Не беспокоить» вне интервала доступности для отключения уведомлений.", diff --git a/apps/dav/l10n/ru.json b/apps/dav/l10n/ru.json index 6bcccea0e73..82eeb83f902 100644 --- a/apps/dav/l10n/ru.json +++ b/apps/dav/l10n/ru.json @@ -84,13 +84,34 @@ "Organizer:" : "Организатор:", "Attendees:" : "Участники:", "Title:" : "Название:", - "Date and time:" : "Дата и время:", + "When:" : "Когда:", "Location:" : "Местонахождение:", "Link:" : "Ссылка:", "Accept" : "Принять", "Decline" : "Отклонить", "More options …" : "Дополнительные параметры…", "More options at %s" : "Дополнительные параметры на %s", + "Monday" : "Понедельник", + "Tuesday" : "Вторник", + "Wednesday" : "Среда", + "Thursday" : "Четверг", + "Friday" : "Пятница", + "Saturday" : "Суббота", + "Sunday" : "Воскресенье", + "January" : "Январь", + "February" : "Февраль", + "March" : "Март", + "April" : "Апрель", + "May" : "Май", + "June" : "Июнь", + "July" : "Июль", + "August" : "Август", + "September" : "Сентябрь", + "October" : "Октябрь", + "November" : "Ноябрь", + "December" : "Декабрь", + "First" : "Первый", + "Last" : "Последний", "Contacts" : "Контакты", "{actor} created address book {addressbook}" : "{actor} создал(а) адресную книгу «{addressbook}»", "You created address book {addressbook}" : "Вы создали адресную книгу «{addressbook}»", @@ -168,13 +189,6 @@ "No working hours set" : "Рабочие часы не указаны", "Add slot" : "Добавить интервал", "Weekdays" : "Дни недели", - "Monday" : "Понедельник", - "Tuesday" : "Вторник", - "Wednesday" : "Среда", - "Thursday" : "Четверг", - "Friday" : "Пятница", - "Saturday" : "Суббота", - "Sunday" : "Воскресенье", "Pick a start time for {dayName}" : "Выберите время начала в {dayName}", "Pick a end time for {dayName}" : "Выберите время окончания в {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматически изменять статус на «Не беспокоить» вне интервала доступности для отключения уведомлений.", diff --git a/apps/dav/l10n/sc.js b/apps/dav/l10n/sc.js index d22054d95ca..523d7c393c6 100644 --- a/apps/dav/l10n/sc.js +++ b/apps/dav/l10n/sc.js @@ -63,12 +63,34 @@ OC.L10N.register( "Organizer:" : "Organizadore: ", "Attendees:" : "Partetzipadores:", "Title:" : "Tìtulos:", + "When:" : "Cando:", "Location:" : "Positzione:", "Link:" : "Ligòngiu:", "Accept" : "Atzeta", "Decline" : "Refuda", "More options …" : "Àteras optziones ...", "More options at %s" : "Àteras optziones a is %s", + "Monday" : "Lunis", + "Tuesday" : "Martis", + "Wednesday" : "Mércuris", + "Thursday" : "Giòbia", + "Friday" : "Chenàbura", + "Saturday" : "Sàbudu", + "Sunday" : "Domìnigu", + "January" : "Ghennàrgiu", + "February" : "Freàrgiu", + "March" : "Martzu", + "April" : "Abrile", + "May" : "Maju", + "June" : "Làmparas", + "July" : "Mese de Trìulas/Argiolas", + "August" : "Austu", + "September" : "Cabudanni", + "October" : "Mese de Ladàmini/ Santu Aine", + "November" : "Sant'Andria", + "December" : "Nadale", + "First" : "Primu", + "Last" : "Ùrtimu", "Contacts" : "Cuntatos", "{actor} created address book {addressbook}" : "{actor} at creadu sa rubrica {addressbook}", "You created address book {addressbook}" : "As creadu sa rubrica {addressbook}", @@ -109,13 +131,6 @@ OC.L10N.register( "WebDAV" : "WebDAV", "Save" : "Sarva", "to" : "a", - "Monday" : "Lunis", - "Tuesday" : "Martis", - "Wednesday" : "Mércuris", - "Thursday" : "Giòbia", - "Friday" : "Chenàbura", - "Saturday" : "Sàbudu", - "Sunday" : "Domìnigu", "Calendar server" : "Serbidore calendàriu", "Send invitations to attendees" : "Imbia invitos de partetzipatziones", "Automatically generate a birthday calendar" : "Gènera in automàticu su calendàriu de cumpleannos", diff --git a/apps/dav/l10n/sc.json b/apps/dav/l10n/sc.json index cda578ba5d1..ef13cf2e942 100644 --- a/apps/dav/l10n/sc.json +++ b/apps/dav/l10n/sc.json @@ -61,12 +61,34 @@ "Organizer:" : "Organizadore: ", "Attendees:" : "Partetzipadores:", "Title:" : "Tìtulos:", + "When:" : "Cando:", "Location:" : "Positzione:", "Link:" : "Ligòngiu:", "Accept" : "Atzeta", "Decline" : "Refuda", "More options …" : "Àteras optziones ...", "More options at %s" : "Àteras optziones a is %s", + "Monday" : "Lunis", + "Tuesday" : "Martis", + "Wednesday" : "Mércuris", + "Thursday" : "Giòbia", + "Friday" : "Chenàbura", + "Saturday" : "Sàbudu", + "Sunday" : "Domìnigu", + "January" : "Ghennàrgiu", + "February" : "Freàrgiu", + "March" : "Martzu", + "April" : "Abrile", + "May" : "Maju", + "June" : "Làmparas", + "July" : "Mese de Trìulas/Argiolas", + "August" : "Austu", + "September" : "Cabudanni", + "October" : "Mese de Ladàmini/ Santu Aine", + "November" : "Sant'Andria", + "December" : "Nadale", + "First" : "Primu", + "Last" : "Ùrtimu", "Contacts" : "Cuntatos", "{actor} created address book {addressbook}" : "{actor} at creadu sa rubrica {addressbook}", "You created address book {addressbook}" : "As creadu sa rubrica {addressbook}", @@ -107,13 +129,6 @@ "WebDAV" : "WebDAV", "Save" : "Sarva", "to" : "a", - "Monday" : "Lunis", - "Tuesday" : "Martis", - "Wednesday" : "Mércuris", - "Thursday" : "Giòbia", - "Friday" : "Chenàbura", - "Saturday" : "Sàbudu", - "Sunday" : "Domìnigu", "Calendar server" : "Serbidore calendàriu", "Send invitations to attendees" : "Imbia invitos de partetzipatziones", "Automatically generate a birthday calendar" : "Gènera in automàticu su calendàriu de cumpleannos", diff --git a/apps/dav/l10n/sk.js b/apps/dav/l10n/sk.js index df8aab7db1d..054699d762b 100644 --- a/apps/dav/l10n/sk.js +++ b/apps/dav/l10n/sk.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Organizátor:", "Attendees:" : "Účastníci:", "Title:" : "Názov:", + "When:" : "Kedy:", "Location:" : "Miesto:", "Link:" : "Odkaz:", "Accept" : "Schváliť", "Decline" : "Odmietnuť", "More options …" : "Ďalšie nastavenia ...", "More options at %s" : "Ďalšie nastavenia %s", + "Monday" : "Pondelok", + "Tuesday" : "Utorok", + "Wednesday" : "Streda", + "Thursday" : "Štvrtok", + "Friday" : "Piatok", + "Saturday" : "Sobota", + "Sunday" : "Nedeľa", + "January" : "Január", + "February" : "Február", + "March" : "Marec", + "April" : "Apríl", + "May" : "Máj", + "June" : "Jún", + "July" : "Júl", + "August" : "August", + "September" : "September", + "October" : "Október", + "November" : "November", + "December" : "December", + "First" : "Prvé", + "Last" : "Posledné", "Contacts" : "Kontakty", "{actor} created address book {addressbook}" : "{actor} vytvoril adresár {addressbook}", "You created address book {addressbook}" : "Vytvorili ste adresár {addressbook}", @@ -171,13 +193,6 @@ OC.L10N.register( "No working hours set" : "Nenastavená pracovná doba", "Add slot" : "Pridať slot", "Weekdays" : "Pracovné dni", - "Monday" : "Pondelok", - "Tuesday" : "Utorok", - "Wednesday" : "Streda", - "Thursday" : "Štvrtok", - "Friday" : "Piatok", - "Saturday" : "Sobota", - "Sunday" : "Nedeľa", "Pick a start time for {dayName}" : "Vyberte začiatočný čas pre {dayName}", "Pick a end time for {dayName}" : "Vyberte koncový čas pre {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automaticky nastaviť stav používateľa na „Nerušiť“ ak nie ste dostupný, pre stlmenie všetkých upozornení.", diff --git a/apps/dav/l10n/sk.json b/apps/dav/l10n/sk.json index 1911593afed..6cc2058136e 100644 --- a/apps/dav/l10n/sk.json +++ b/apps/dav/l10n/sk.json @@ -84,12 +84,34 @@ "Organizer:" : "Organizátor:", "Attendees:" : "Účastníci:", "Title:" : "Názov:", + "When:" : "Kedy:", "Location:" : "Miesto:", "Link:" : "Odkaz:", "Accept" : "Schváliť", "Decline" : "Odmietnuť", "More options …" : "Ďalšie nastavenia ...", "More options at %s" : "Ďalšie nastavenia %s", + "Monday" : "Pondelok", + "Tuesday" : "Utorok", + "Wednesday" : "Streda", + "Thursday" : "Štvrtok", + "Friday" : "Piatok", + "Saturday" : "Sobota", + "Sunday" : "Nedeľa", + "January" : "Január", + "February" : "Február", + "March" : "Marec", + "April" : "Apríl", + "May" : "Máj", + "June" : "Jún", + "July" : "Júl", + "August" : "August", + "September" : "September", + "October" : "Október", + "November" : "November", + "December" : "December", + "First" : "Prvé", + "Last" : "Posledné", "Contacts" : "Kontakty", "{actor} created address book {addressbook}" : "{actor} vytvoril adresár {addressbook}", "You created address book {addressbook}" : "Vytvorili ste adresár {addressbook}", @@ -169,13 +191,6 @@ "No working hours set" : "Nenastavená pracovná doba", "Add slot" : "Pridať slot", "Weekdays" : "Pracovné dni", - "Monday" : "Pondelok", - "Tuesday" : "Utorok", - "Wednesday" : "Streda", - "Thursday" : "Štvrtok", - "Friday" : "Piatok", - "Saturday" : "Sobota", - "Sunday" : "Nedeľa", "Pick a start time for {dayName}" : "Vyberte začiatočný čas pre {dayName}", "Pick a end time for {dayName}" : "Vyberte koncový čas pre {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automaticky nastaviť stav používateľa na „Nerušiť“ ak nie ste dostupný, pre stlmenie všetkých upozornení.", diff --git a/apps/dav/l10n/sl.js b/apps/dav/l10n/sl.js index c0face70ba7..3ba5ce63a3c 100644 --- a/apps/dav/l10n/sl.js +++ b/apps/dav/l10n/sl.js @@ -86,12 +86,34 @@ OC.L10N.register( "Organizer:" : "Organizator:", "Attendees:" : "Udeleženci:", "Title:" : "Naslov:", + "When:" : "Kdaj:", "Location:" : "Mesto:", "Link:" : "Povezava:", "Accept" : "Sprejmi", "Decline" : "Zavrni", "More options …" : "Več možnosti ...", "More options at %s" : "Več možnosti je na %s", + "Monday" : "ponedeljek", + "Tuesday" : "torek", + "Wednesday" : "sreda", + "Thursday" : "četrtek", + "Friday" : "petek", + "Saturday" : "sobota", + "Sunday" : "nedelja", + "January" : "januar", + "February" : "februar", + "March" : "marec", + "April" : "april", + "May" : "maj", + "June" : "junij", + "July" : "julij", + "August" : "avgust", + "September" : "september", + "October" : "oktober", + "November" : "november", + "December" : "december", + "First" : "Prvi", + "Last" : "Zadnji", "Contacts" : "Stiki", "{actor} created address book {addressbook}" : "{actor} ustvari imenik {addressbook}", "You created address book {addressbook}" : "Ustvarite imenik {addressbook}", @@ -165,13 +187,7 @@ OC.L10N.register( "Delete slot" : "Izbriši možnost", "No working hours set" : "Ni navedenih delovnih ur", "Add slot" : "Dodaj možnost", - "Monday" : "ponedeljek", - "Tuesday" : "torek", - "Wednesday" : "sreda", - "Thursday" : "četrtek", - "Friday" : "petek", - "Saturday" : "sobota", - "Sunday" : "nedelja", + "Weekdays" : "Delovni dnevi", "Pick a start time for {dayName}" : "Izbor časa začetka za {dayName}", "Pick a end time for {dayName}" : "Izbor časa konca za {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Samodejno nastavi stanje uporabnika na »Ne moti« in zavračaj prikaz obvestil izven časa razpoložljivosti.", diff --git a/apps/dav/l10n/sl.json b/apps/dav/l10n/sl.json index b8b5e810dda..ebf6811e140 100644 --- a/apps/dav/l10n/sl.json +++ b/apps/dav/l10n/sl.json @@ -84,12 +84,34 @@ "Organizer:" : "Organizator:", "Attendees:" : "Udeleženci:", "Title:" : "Naslov:", + "When:" : "Kdaj:", "Location:" : "Mesto:", "Link:" : "Povezava:", "Accept" : "Sprejmi", "Decline" : "Zavrni", "More options …" : "Več možnosti ...", "More options at %s" : "Več možnosti je na %s", + "Monday" : "ponedeljek", + "Tuesday" : "torek", + "Wednesday" : "sreda", + "Thursday" : "četrtek", + "Friday" : "petek", + "Saturday" : "sobota", + "Sunday" : "nedelja", + "January" : "januar", + "February" : "februar", + "March" : "marec", + "April" : "april", + "May" : "maj", + "June" : "junij", + "July" : "julij", + "August" : "avgust", + "September" : "september", + "October" : "oktober", + "November" : "november", + "December" : "december", + "First" : "Prvi", + "Last" : "Zadnji", "Contacts" : "Stiki", "{actor} created address book {addressbook}" : "{actor} ustvari imenik {addressbook}", "You created address book {addressbook}" : "Ustvarite imenik {addressbook}", @@ -163,13 +185,7 @@ "Delete slot" : "Izbriši možnost", "No working hours set" : "Ni navedenih delovnih ur", "Add slot" : "Dodaj možnost", - "Monday" : "ponedeljek", - "Tuesday" : "torek", - "Wednesday" : "sreda", - "Thursday" : "četrtek", - "Friday" : "petek", - "Saturday" : "sobota", - "Sunday" : "nedelja", + "Weekdays" : "Delovni dnevi", "Pick a start time for {dayName}" : "Izbor časa začetka za {dayName}", "Pick a end time for {dayName}" : "Izbor časa konca za {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Samodejno nastavi stanje uporabnika na »Ne moti« in zavračaj prikaz obvestil izven časa razpoložljivosti.", diff --git a/apps/dav/l10n/sr.js b/apps/dav/l10n/sr.js index d008fc4d29f..5840e71817f 100644 --- a/apps/dav/l10n/sr.js +++ b/apps/dav/l10n/sr.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "Опис: %s", "Where: %s" : "Место: %s", "%1$s via %2$s" : "%1$s преко %2$s", + "In a %1$s on %2$s for the entire day" : "У %1$s дана %2$s током целог дана", + "In a %1$s on %2$s between %3$s - %4$s" : "У %1$s дана %2$s од %3$s до %4$s", + "In %1$s %2$s on %3$s for the entire day" : "У %1$s %2$s дана %3$s током целог дана", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "У %1$s %2$s дана %3$s од %4$s до %5$s", + "Could not generate when statement" : "Не може да се генерише одредба када", + "Every Day for the entire day" : "Сваки дан током целог дана", + "Every Day for the entire day until %1$s" : "Сваки дан током целог дана, све до %1$s", + "Every Day between %1$s - %2$s" : "Сваки дан од %1$s до %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Сваки дан од %1$s до %2$s све до %3$s", + "Every %1$d Days for the entire day" : "Сваких %1$d дана током целог дана", + "Every %1$d Days for the entire day until %2$s" : "Сваких %1$d дана током целог дана све до %2$s", + "Every %1$d Days between %2$s - %3$s" : "Сваких %1$d дана од %2$s до %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Сваких %1$d дана од %2$s до %3$s све до %4$s", + "Could not generate event recurrence statement" : "Не може да се генерише одредба понављања", + "Every Week on %1$s for the entire day" : "%1$s сваке недеље током целог дана", + "Every Week on %1$s for the entire day until %2$s" : "%1$s сваке недеље током целог дана све до %2$s", + "Every Week on %1$s between %2$s - %3$s" : "%1$s сваке недеље од %2$s до %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "%1$s сваке недеље од %2$s до %3$s све до %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "%2$s сваких %1$d недеља током целог дана", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "%2$s сваких %1$d недеља током целог дана све до %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "%2$s сваких %1$d недеља од %3$s до %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "%2$s сваких %1$d недеља од %3$s до %4$s све до %5$s", + "Every Month on the %1$s for the entire day" : "%1$s сваког месеца током целог дана", + "Every Month on the %1$s for the entire day until %2$s" : "%1$s сваког месеца током целог дана све до %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "%1$s сваког месеца од %2$s до %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "%1$s сваког месеца од %2$s до %3$s све до %4$s", + "Every %1$d Months on the %2$s for the entire day" : "%2$s сваких %1$d месеци током целог дана", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "%2$s сваких %1$d месеци током целог дана све до %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "%2$s сваких %1$d месеци од %3$s до %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "%2$s сваких %1$d месеци од %3$s до %4$s све до %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "%1$s сваке године дана %2$s током целог дана", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "%1$s сваке године, дана %2$s током целог дана све до %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "%1$s сваке године, дана %2$s од %3$s до %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "%1$s сваке године, дана %2$s од %3$s до %4$s све до %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "%2$s сваких %1$d година, дана %3$s током целог дана", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "%2$s сваких %1$d година, дана %3$s током целог дана све до %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "%2$s сваких %1$d година, дана %3$s од %4$s до %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "%2$s сваких %1$d година, дана %3$s од %4$s до %5$s све до %6$s", + "On specific dates for the entire day until %1$s" : "Одређених дана током целог дана, све до %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "Одређених дана од %1$s до %2$s све до %3$s", + "In a %1$s on %2$s" : "За %1$s у %2$s", + "In a %1$s on %2$s then on %3$s" : "За %1$s у %2$s, па онда %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "За %1$s у %2$s, па онда %3$s и %4$s", + "In %1$s %2$s on %3$s" : "За %1$s %2$s у %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "За %1$s %2$s у %3$s, па онда у %4$s ", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "За %1$s %2$s у %3$s, па онда у %4$s и %5$s ", + "Could not generate next recurrence statement" : "Није могла да се генерише одредба следћег појављивања", "Cancelled: %1$s" : "Отказано: %1$s", "\"%1$s\" has been canceled" : "„%1$s” је отказано", "Re: %1$s" : "Одг: %1$s", @@ -86,13 +133,43 @@ OC.L10N.register( "Organizer:" : "Организатор:", "Attendees:" : "Присутни:", "Title:" : "Наслов:", - "Date and time:" : "Датум и време:", + "When:" : "Време:", "Location:" : "Локација:", "Link:" : "Веза:", + "Occurring:" : "Појављивање:", "Accept" : "Прихвати", "Decline" : "Одбиј", "More options …" : "Још опција…", "More options at %s" : "Још опција на %s", + "Monday" : "Понедељак", + "Tuesday" : "Уторак", + "Wednesday" : "Среда", + "Thursday" : "Четвртак", + "Friday" : "Петак", + "Saturday" : "Субота", + "Sunday" : "Недеља", + "January" : "Јануар", + "February" : "Фебруар", + "March" : "Март", + "April" : "Април", + "May" : "Мај", + "June" : "Јун", + "July" : "Јул", + "August" : "Август", + "September" : "Септембар", + "October" : "Октобар", + "November" : "Новембар", + "December" : "Децембар", + "First" : "Прва", + "Second" : "Друго", + "Third" : "Треће", + "Fourth" : "Четврто", + "Fifty" : "Пето", + "Last" : "Последња", + "Second Last" : "Претпоследње", + "Third Last" : "Треће од краја", + "Fourth Last" : "Четврто од краја", + "Fifty Last" : "Пето од краја", "Contacts" : "Контакти", "{actor} created address book {addressbook}" : "{actor} је креирао адресар {addressbook}", "You created address book {addressbook}" : "Креирали сте адресар {addressbook}", @@ -176,13 +253,6 @@ OC.L10N.register( "No working hours set" : "Нису подешени радни сати", "Add slot" : "Додај термин", "Weekdays" : "Дани у недељи", - "Monday" : "Понедељак", - "Tuesday" : "Уторак", - "Wednesday" : "Среда", - "Thursday" : "Четвртак", - "Friday" : "Петак", - "Saturday" : "Субота", - "Sunday" : "Недеља", "Pick a start time for {dayName}" : "Изаберите време почетка за {dayName}", "Pick a end time for {dayName}" : "Изаберите време завршетка за {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Аутоматски поставља статус кориниска на „Не узнемиравај” како би се ван доступности пригушила сва обавештења.", diff --git a/apps/dav/l10n/sr.json b/apps/dav/l10n/sr.json index f31e14a04ba..3d40364654a 100644 --- a/apps/dav/l10n/sr.json +++ b/apps/dav/l10n/sr.json @@ -70,6 +70,53 @@ "Description: %s" : "Опис: %s", "Where: %s" : "Место: %s", "%1$s via %2$s" : "%1$s преко %2$s", + "In a %1$s on %2$s for the entire day" : "У %1$s дана %2$s током целог дана", + "In a %1$s on %2$s between %3$s - %4$s" : "У %1$s дана %2$s од %3$s до %4$s", + "In %1$s %2$s on %3$s for the entire day" : "У %1$s %2$s дана %3$s током целог дана", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "У %1$s %2$s дана %3$s од %4$s до %5$s", + "Could not generate when statement" : "Не може да се генерише одредба када", + "Every Day for the entire day" : "Сваки дан током целог дана", + "Every Day for the entire day until %1$s" : "Сваки дан током целог дана, све до %1$s", + "Every Day between %1$s - %2$s" : "Сваки дан од %1$s до %2$s", + "Every Day between %1$s - %2$s until %3$s" : "Сваки дан од %1$s до %2$s све до %3$s", + "Every %1$d Days for the entire day" : "Сваких %1$d дана током целог дана", + "Every %1$d Days for the entire day until %2$s" : "Сваких %1$d дана током целог дана све до %2$s", + "Every %1$d Days between %2$s - %3$s" : "Сваких %1$d дана од %2$s до %3$s", + "Every %1$d Days between %2$s - %3$s until %4$s" : "Сваких %1$d дана од %2$s до %3$s све до %4$s", + "Could not generate event recurrence statement" : "Не може да се генерише одредба понављања", + "Every Week on %1$s for the entire day" : "%1$s сваке недеље током целог дана", + "Every Week on %1$s for the entire day until %2$s" : "%1$s сваке недеље током целог дана све до %2$s", + "Every Week on %1$s between %2$s - %3$s" : "%1$s сваке недеље од %2$s до %3$s", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "%1$s сваке недеље од %2$s до %3$s све до %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "%2$s сваких %1$d недеља током целог дана", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "%2$s сваких %1$d недеља током целог дана све до %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "%2$s сваких %1$d недеља од %3$s до %4$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "%2$s сваких %1$d недеља од %3$s до %4$s све до %5$s", + "Every Month on the %1$s for the entire day" : "%1$s сваког месеца током целог дана", + "Every Month on the %1$s for the entire day until %2$s" : "%1$s сваког месеца током целог дана све до %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "%1$s сваког месеца од %2$s до %3$s", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "%1$s сваког месеца од %2$s до %3$s све до %4$s", + "Every %1$d Months on the %2$s for the entire day" : "%2$s сваких %1$d месеци током целог дана", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "%2$s сваких %1$d месеци током целог дана све до %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "%2$s сваких %1$d месеци од %3$s до %4$s", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "%2$s сваких %1$d месеци од %3$s до %4$s све до %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "%1$s сваке године дана %2$s током целог дана", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "%1$s сваке године, дана %2$s током целог дана све до %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "%1$s сваке године, дана %2$s од %3$s до %4$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "%1$s сваке године, дана %2$s од %3$s до %4$s све до %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "%2$s сваких %1$d година, дана %3$s током целог дана", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "%2$s сваких %1$d година, дана %3$s током целог дана све до %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "%2$s сваких %1$d година, дана %3$s од %4$s до %5$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "%2$s сваких %1$d година, дана %3$s од %4$s до %5$s све до %6$s", + "On specific dates for the entire day until %1$s" : "Одређених дана током целог дана, све до %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "Одређених дана од %1$s до %2$s све до %3$s", + "In a %1$s on %2$s" : "За %1$s у %2$s", + "In a %1$s on %2$s then on %3$s" : "За %1$s у %2$s, па онда %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "За %1$s у %2$s, па онда %3$s и %4$s", + "In %1$s %2$s on %3$s" : "За %1$s %2$s у %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "За %1$s %2$s у %3$s, па онда у %4$s ", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "За %1$s %2$s у %3$s, па онда у %4$s и %5$s ", + "Could not generate next recurrence statement" : "Није могла да се генерише одредба следћег појављивања", "Cancelled: %1$s" : "Отказано: %1$s", "\"%1$s\" has been canceled" : "„%1$s” је отказано", "Re: %1$s" : "Одг: %1$s", @@ -84,13 +131,43 @@ "Organizer:" : "Организатор:", "Attendees:" : "Присутни:", "Title:" : "Наслов:", - "Date and time:" : "Датум и време:", + "When:" : "Време:", "Location:" : "Локација:", "Link:" : "Веза:", + "Occurring:" : "Појављивање:", "Accept" : "Прихвати", "Decline" : "Одбиј", "More options …" : "Још опција…", "More options at %s" : "Још опција на %s", + "Monday" : "Понедељак", + "Tuesday" : "Уторак", + "Wednesday" : "Среда", + "Thursday" : "Четвртак", + "Friday" : "Петак", + "Saturday" : "Субота", + "Sunday" : "Недеља", + "January" : "Јануар", + "February" : "Фебруар", + "March" : "Март", + "April" : "Април", + "May" : "Мај", + "June" : "Јун", + "July" : "Јул", + "August" : "Август", + "September" : "Септембар", + "October" : "Октобар", + "November" : "Новембар", + "December" : "Децембар", + "First" : "Прва", + "Second" : "Друго", + "Third" : "Треће", + "Fourth" : "Четврто", + "Fifty" : "Пето", + "Last" : "Последња", + "Second Last" : "Претпоследње", + "Third Last" : "Треће од краја", + "Fourth Last" : "Четврто од краја", + "Fifty Last" : "Пето од краја", "Contacts" : "Контакти", "{actor} created address book {addressbook}" : "{actor} је креирао адресар {addressbook}", "You created address book {addressbook}" : "Креирали сте адресар {addressbook}", @@ -174,13 +251,6 @@ "No working hours set" : "Нису подешени радни сати", "Add slot" : "Додај термин", "Weekdays" : "Дани у недељи", - "Monday" : "Понедељак", - "Tuesday" : "Уторак", - "Wednesday" : "Среда", - "Thursday" : "Четвртак", - "Friday" : "Петак", - "Saturday" : "Субота", - "Sunday" : "Недеља", "Pick a start time for {dayName}" : "Изаберите време почетка за {dayName}", "Pick a end time for {dayName}" : "Изаберите време завршетка за {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Аутоматски поставља статус кориниска на „Не узнемиравај” како би се ван доступности пригушила сва обавештења.", diff --git a/apps/dav/l10n/sv.js b/apps/dav/l10n/sv.js index 89fd0b00e40..8d5fcb67b4d 100644 --- a/apps/dav/l10n/sv.js +++ b/apps/dav/l10n/sv.js @@ -86,13 +86,34 @@ OC.L10N.register( "Organizer:" : "Arrangör:", "Attendees:" : "Deltagare:", "Title:" : "Titel:", - "Date and time:" : "Datum och tid:", + "When:" : "När", "Location:" : "Ort:", "Link:" : "Länk:", "Accept" : "Acceptera", "Decline" : "Avböj", "More options …" : "Fler alternativ ...", "More options at %s" : "Fler alternativ på %s", + "Monday" : "Måndag", + "Tuesday" : "Tisdag", + "Wednesday" : "Onsdag", + "Thursday" : "Torsdag", + "Friday" : "Fredag", + "Saturday" : "Lördag", + "Sunday" : "Söndag", + "January" : "Januari", + "February" : "Februari", + "March" : "Mars", + "April" : "April", + "May" : "Maj", + "June" : "Juni", + "July" : "Juli", + "August" : "Augusti", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "December", + "First" : "Första", + "Last" : "Sista", "Contacts" : "Kontakter", "{actor} created address book {addressbook}" : "{actor} skapade adressboken {addressbook}", "You created address book {addressbook}" : "Du skapade adressboken {addressbook}", @@ -174,13 +195,6 @@ OC.L10N.register( "No working hours set" : "Inga arbetstimmar satta", "Add slot" : "Lägg till lucka", "Weekdays" : "Vardagar", - "Monday" : "Måndag", - "Tuesday" : "Tisdag", - "Wednesday" : "Onsdag", - "Thursday" : "Torsdag", - "Friday" : "Fredag", - "Saturday" : "Lördag", - "Sunday" : "Söndag", "Pick a start time for {dayName}" : "Välj en starttid för {dayName}", "Pick a end time for {dayName}" : "Välj en sluttid för {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Sätt automatiskt användarstatus till \"Stör ej\" utanför tillgängliga tider för att tysta alla notifikationer.", diff --git a/apps/dav/l10n/sv.json b/apps/dav/l10n/sv.json index 1e2507a2a7d..9f0df05e37b 100644 --- a/apps/dav/l10n/sv.json +++ b/apps/dav/l10n/sv.json @@ -84,13 +84,34 @@ "Organizer:" : "Arrangör:", "Attendees:" : "Deltagare:", "Title:" : "Titel:", - "Date and time:" : "Datum och tid:", + "When:" : "När", "Location:" : "Ort:", "Link:" : "Länk:", "Accept" : "Acceptera", "Decline" : "Avböj", "More options …" : "Fler alternativ ...", "More options at %s" : "Fler alternativ på %s", + "Monday" : "Måndag", + "Tuesday" : "Tisdag", + "Wednesday" : "Onsdag", + "Thursday" : "Torsdag", + "Friday" : "Fredag", + "Saturday" : "Lördag", + "Sunday" : "Söndag", + "January" : "Januari", + "February" : "Februari", + "March" : "Mars", + "April" : "April", + "May" : "Maj", + "June" : "Juni", + "July" : "Juli", + "August" : "Augusti", + "September" : "September", + "October" : "Oktober", + "November" : "November", + "December" : "December", + "First" : "Första", + "Last" : "Sista", "Contacts" : "Kontakter", "{actor} created address book {addressbook}" : "{actor} skapade adressboken {addressbook}", "You created address book {addressbook}" : "Du skapade adressboken {addressbook}", @@ -172,13 +193,6 @@ "No working hours set" : "Inga arbetstimmar satta", "Add slot" : "Lägg till lucka", "Weekdays" : "Vardagar", - "Monday" : "Måndag", - "Tuesday" : "Tisdag", - "Wednesday" : "Onsdag", - "Thursday" : "Torsdag", - "Friday" : "Fredag", - "Saturday" : "Lördag", - "Sunday" : "Söndag", "Pick a start time for {dayName}" : "Välj en starttid för {dayName}", "Pick a end time for {dayName}" : "Välj en sluttid för {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Sätt automatiskt användarstatus till \"Stör ej\" utanför tillgängliga tider för att tysta alla notifikationer.", diff --git a/apps/dav/l10n/tr.js b/apps/dav/l10n/tr.js index cb1ea16c712..5cdea7f25db 100644 --- a/apps/dav/l10n/tr.js +++ b/apps/dav/l10n/tr.js @@ -86,13 +86,34 @@ OC.L10N.register( "Organizer:" : "Düzenleyen:", "Attendees:" : "Katılımcılar:", "Title:" : "Başlık:", - "Date and time:" : "Tarih ve saat:", + "When:" : "Zaman:", "Location:" : "Konum:", "Link:" : "Bağlantı:", "Accept" : "Kabul et", "Decline" : "Reddet", "More options …" : "Diğer seçenekler …", "More options at %s" : "%s üzerindeki diğer seçenekler", + "Monday" : "Pazartesi", + "Tuesday" : "Salı", + "Wednesday" : "Çarşamba", + "Thursday" : "Perşembe", + "Friday" : "Cuma", + "Saturday" : "Cumartesi", + "Sunday" : "Pazar", + "January" : "Ocak", + "February" : "Şubat", + "March" : "Mart", + "April" : "Nisan", + "May" : "Mayıs", + "June" : "Haziran", + "July" : "Temmuz", + "August" : "Ağustos", + "September" : "Eylül", + "October" : "Ekim", + "November" : "Kasım", + "December" : "Aralık", + "First" : "İlk", + "Last" : "Son", "Contacts" : "Kişiler", "{actor} created address book {addressbook}" : "{actor}, {addressbook} adres defterini ekledi", "You created address book {addressbook}" : "{addressbook} adres defterini eklediniz", @@ -172,13 +193,6 @@ OC.L10N.register( "No working hours set" : "Çalışma saatleri ayarlanmamış", "Add slot" : "Aralık ekle", "Weekdays" : "Hafta içi günleri", - "Monday" : "Pazartesi", - "Tuesday" : "Salı", - "Wednesday" : "Çarşamba", - "Thursday" : "Perşembe", - "Friday" : "Cuma", - "Saturday" : "Cumartesi", - "Sunday" : "Pazar", "Pick a start time for {dayName}" : "{dayName} için başlangıç zamanını seçin", "Pick a end time for {dayName}" : "{dayName} için bitiş zamanını seçin", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Tüm bildirimleri sessize almak için, uygunluk durumu dışında kullanıcı durumu otomatik olarak \"Rahatsız etmeyin\" olarak ayarlanır.", diff --git a/apps/dav/l10n/tr.json b/apps/dav/l10n/tr.json index 00b84b41f4b..f333265a337 100644 --- a/apps/dav/l10n/tr.json +++ b/apps/dav/l10n/tr.json @@ -84,13 +84,34 @@ "Organizer:" : "Düzenleyen:", "Attendees:" : "Katılımcılar:", "Title:" : "Başlık:", - "Date and time:" : "Tarih ve saat:", + "When:" : "Zaman:", "Location:" : "Konum:", "Link:" : "Bağlantı:", "Accept" : "Kabul et", "Decline" : "Reddet", "More options …" : "Diğer seçenekler …", "More options at %s" : "%s üzerindeki diğer seçenekler", + "Monday" : "Pazartesi", + "Tuesday" : "Salı", + "Wednesday" : "Çarşamba", + "Thursday" : "Perşembe", + "Friday" : "Cuma", + "Saturday" : "Cumartesi", + "Sunday" : "Pazar", + "January" : "Ocak", + "February" : "Şubat", + "March" : "Mart", + "April" : "Nisan", + "May" : "Mayıs", + "June" : "Haziran", + "July" : "Temmuz", + "August" : "Ağustos", + "September" : "Eylül", + "October" : "Ekim", + "November" : "Kasım", + "December" : "Aralık", + "First" : "İlk", + "Last" : "Son", "Contacts" : "Kişiler", "{actor} created address book {addressbook}" : "{actor}, {addressbook} adres defterini ekledi", "You created address book {addressbook}" : "{addressbook} adres defterini eklediniz", @@ -170,13 +191,6 @@ "No working hours set" : "Çalışma saatleri ayarlanmamış", "Add slot" : "Aralık ekle", "Weekdays" : "Hafta içi günleri", - "Monday" : "Pazartesi", - "Tuesday" : "Salı", - "Wednesday" : "Çarşamba", - "Thursday" : "Perşembe", - "Friday" : "Cuma", - "Saturday" : "Cumartesi", - "Sunday" : "Pazar", "Pick a start time for {dayName}" : "{dayName} için başlangıç zamanını seçin", "Pick a end time for {dayName}" : "{dayName} için bitiş zamanını seçin", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Tüm bildirimleri sessize almak için, uygunluk durumu dışında kullanıcı durumu otomatik olarak \"Rahatsız etmeyin\" olarak ayarlanır.", diff --git a/apps/dav/l10n/uk.js b/apps/dav/l10n/uk.js index c695273717b..87f9ce7cc8f 100644 --- a/apps/dav/l10n/uk.js +++ b/apps/dav/l10n/uk.js @@ -86,13 +86,32 @@ OC.L10N.register( "Organizer:" : "Організатор:", "Attendees:" : "Учасники:", "Title:" : "Назва:", - "Date and time:" : "Дата та час:", + "When:" : "Коли:", "Location:" : "Місцевість:", "Link:" : "Посилання:", "Accept" : "Прийняти", "Decline" : "Відхилити", "More options …" : "Більше варіантів …", "More options at %s" : "Більше варіантів на %s", + "Monday" : "Понеділок", + "Tuesday" : "Вівторок", + "Wednesday" : "Середа", + "Thursday" : "Четвер", + "Friday" : "П'ятниця", + "Saturday" : "Субота", + "Sunday" : "Неділя", + "January" : "Січень", + "February" : "Лютий", + "March" : "Березень", + "April" : "Квітень", + "May" : "Травень", + "June" : "Червень", + "July" : "Липень", + "August" : "Серпень", + "September" : "Вересень", + "October" : "Жовтень", + "November" : "Листопад", + "December" : "Грудень", "Contacts" : "Контакти", "{actor} created address book {addressbook}" : "{actor} створив(-ла) адресну книгу {addressbook}", "You created address book {addressbook}" : "Ви створили адресну книгу {addressbook}", @@ -176,13 +195,6 @@ OC.L10N.register( "No working hours set" : "Робочий час не встановлено", "Add slot" : "Додати діапазон", "Weekdays" : "Дні тижня", - "Monday" : "Понеділок", - "Tuesday" : "Вівторок", - "Wednesday" : "Середа", - "Thursday" : "Четвер", - "Friday" : "П'ятниця", - "Saturday" : "Субота", - "Sunday" : "Неділя", "Pick a start time for {dayName}" : "Виберіть час початку для {dayName}", "Pick a end time for {dayName}" : "Виберіть час завершення для {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматично встановлювати статус користувача у \"Не турбувати\", коли ви не доступні. В цей проміжок часу ви не отримуватимете сповіщення.", diff --git a/apps/dav/l10n/uk.json b/apps/dav/l10n/uk.json index 6b74d5712d2..e932e3021a8 100644 --- a/apps/dav/l10n/uk.json +++ b/apps/dav/l10n/uk.json @@ -84,13 +84,32 @@ "Organizer:" : "Організатор:", "Attendees:" : "Учасники:", "Title:" : "Назва:", - "Date and time:" : "Дата та час:", + "When:" : "Коли:", "Location:" : "Місцевість:", "Link:" : "Посилання:", "Accept" : "Прийняти", "Decline" : "Відхилити", "More options …" : "Більше варіантів …", "More options at %s" : "Більше варіантів на %s", + "Monday" : "Понеділок", + "Tuesday" : "Вівторок", + "Wednesday" : "Середа", + "Thursday" : "Четвер", + "Friday" : "П'ятниця", + "Saturday" : "Субота", + "Sunday" : "Неділя", + "January" : "Січень", + "February" : "Лютий", + "March" : "Березень", + "April" : "Квітень", + "May" : "Травень", + "June" : "Червень", + "July" : "Липень", + "August" : "Серпень", + "September" : "Вересень", + "October" : "Жовтень", + "November" : "Листопад", + "December" : "Грудень", "Contacts" : "Контакти", "{actor} created address book {addressbook}" : "{actor} створив(-ла) адресну книгу {addressbook}", "You created address book {addressbook}" : "Ви створили адресну книгу {addressbook}", @@ -174,13 +193,6 @@ "No working hours set" : "Робочий час не встановлено", "Add slot" : "Додати діапазон", "Weekdays" : "Дні тижня", - "Monday" : "Понеділок", - "Tuesday" : "Вівторок", - "Wednesday" : "Середа", - "Thursday" : "Четвер", - "Friday" : "П'ятниця", - "Saturday" : "Субота", - "Sunday" : "Неділя", "Pick a start time for {dayName}" : "Виберіть час початку для {dayName}", "Pick a end time for {dayName}" : "Виберіть час завершення для {dayName}", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Автоматично встановлювати статус користувача у \"Не турбувати\", коли ви не доступні. В цей проміжок часу ви не отримуватимете сповіщення.", diff --git a/apps/dav/l10n/zh_CN.js b/apps/dav/l10n/zh_CN.js index 917bb3a32d9..f6921839899 100644 --- a/apps/dav/l10n/zh_CN.js +++ b/apps/dav/l10n/zh_CN.js @@ -86,13 +86,34 @@ OC.L10N.register( "Organizer:" : "组织者:", "Attendees:" : "与会者:", "Title:" : "标题:", - "Date and time:" : "日期和时间:", + "When:" : "时间:", "Location:" : "地区:", "Link:" : "链接:", "Accept" : "接受", "Decline" : "拒绝", "More options …" : "更多选项", "More options at %s" : "在%s的更多选项", + "Monday" : "周一", + "Tuesday" : "周二", + "Wednesday" : "周三", + "Thursday" : "周四", + "Friday" : "周五", + "Saturday" : "周六", + "Sunday" : "周日", + "January" : "一月", + "February" : "二月", + "March" : "三月", + "April" : "四月", + "May" : "五月", + "June" : "六月", + "July" : "七月", + "August" : "八月", + "September" : "九月", + "October" : "十月", + "November" : "十一月", + "December" : "十二月", + "First" : "第一个", + "Last" : "最后一个", "Contacts" : "联系人", "{actor} created address book {addressbook}" : "{actor} 创建了通讯录 {addressbook}", "You created address book {addressbook}" : "你创建了通讯录 {addressbook}", @@ -172,13 +193,6 @@ OC.L10N.register( "No working hours set" : "尚未设置工作时间", "Add slot" : "添加插槽", "Weekdays" : "工作日", - "Monday" : "周一", - "Tuesday" : "周二", - "Wednesday" : "周三", - "Thursday" : "周四", - "Friday" : "周五", - "Saturday" : "周六", - "Sunday" : "周日", "Pick a start time for {dayName}" : "选择 {dayName} 的开始时间", "Pick a end time for {dayName}" : "选择 {dayName} 的结束时间", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "不在可用时间内时,自动将用户状态设置为“请勿打扰”并静音所有通知。", diff --git a/apps/dav/l10n/zh_CN.json b/apps/dav/l10n/zh_CN.json index b8c52093ea7..d2c0c1d5c4f 100644 --- a/apps/dav/l10n/zh_CN.json +++ b/apps/dav/l10n/zh_CN.json @@ -84,13 +84,34 @@ "Organizer:" : "组织者:", "Attendees:" : "与会者:", "Title:" : "标题:", - "Date and time:" : "日期和时间:", + "When:" : "时间:", "Location:" : "地区:", "Link:" : "链接:", "Accept" : "接受", "Decline" : "拒绝", "More options …" : "更多选项", "More options at %s" : "在%s的更多选项", + "Monday" : "周一", + "Tuesday" : "周二", + "Wednesday" : "周三", + "Thursday" : "周四", + "Friday" : "周五", + "Saturday" : "周六", + "Sunday" : "周日", + "January" : "一月", + "February" : "二月", + "March" : "三月", + "April" : "四月", + "May" : "五月", + "June" : "六月", + "July" : "七月", + "August" : "八月", + "September" : "九月", + "October" : "十月", + "November" : "十一月", + "December" : "十二月", + "First" : "第一个", + "Last" : "最后一个", "Contacts" : "联系人", "{actor} created address book {addressbook}" : "{actor} 创建了通讯录 {addressbook}", "You created address book {addressbook}" : "你创建了通讯录 {addressbook}", @@ -170,13 +191,6 @@ "No working hours set" : "尚未设置工作时间", "Add slot" : "添加插槽", "Weekdays" : "工作日", - "Monday" : "周一", - "Tuesday" : "周二", - "Wednesday" : "周三", - "Thursday" : "周四", - "Friday" : "周五", - "Saturday" : "周六", - "Sunday" : "周日", "Pick a start time for {dayName}" : "选择 {dayName} 的开始时间", "Pick a end time for {dayName}" : "选择 {dayName} 的结束时间", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "不在可用时间内时,自动将用户状态设置为“请勿打扰”并静音所有通知。", diff --git a/apps/dav/l10n/zh_HK.js b/apps/dav/l10n/zh_HK.js index c33ae3c26f0..996176e8177 100644 --- a/apps/dav/l10n/zh_HK.js +++ b/apps/dav/l10n/zh_HK.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "描述:%s", "Where: %s" : "地點:%s", "%1$s via %2$s" : "%1$s 由 %2$s", + "In a %1$s on %2$s for the entire day" : "%1$s 的 %2$s 整天", + "In a %1$s on %2$s between %3$s - %4$s" : "%1$s 的 %2$s 於 %3$s - %4$s 之間", + "In %1$s %2$s on %3$s for the entire day" : "%1$s %2$s 的 %3$s 整天", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "%1$s %2$s 的 %3$s 於 %4$s - %5$s 之間", + "Could not generate when statement" : "無法產生 when 陳述", + "Every Day for the entire day" : "每天一整天", + "Every Day for the entire day until %1$s" : "每天一整天,直至 %1$s", + "Every Day between %1$s - %2$s" : "每天於 %1$s - %2$s 之間", + "Every Day between %1$s - %2$s until %3$s" : "每天於 %1$s - %2$s 之間,直至 %3$s", + "Every %1$d Days for the entire day" : "每 %1$d 天整天", + "Every %1$d Days for the entire day until %2$s" : "每 %1$d 天整天,直至 %2$s", + "Every %1$d Days between %2$s - %3$s" : "每 %1$d 天於 %2$s - %3$s 之間", + "Every %1$d Days between %2$s - %3$s until %4$s" : "每 %1$d 天於 %2$s - %3$s 之間,直至 %4$s", + "Could not generate event recurrence statement" : "無法產生事件重複陳述", + "Every Week on %1$s for the entire day" : "每週於 %1$s 整天", + "Every Week on %1$s for the entire day until %2$s" : "每週於 %1$s 整天,直到 %2$s", + "Every Week on %1$s between %2$s - %3$s" : "每週於 %1$s,在 %2$s - %3$s 之間", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "每週於 %1$s,在 %2$s - %3$s 之間,直到 %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "每 %1$d 週於 %2$s 整天", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "每 %1$d 週於 %2$s 整天,直至 %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "每 %1$d 週於 %2$s,在 %3$s - %4$s 之間", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "每 %1$d 週於 %2$s,在 %3$s - %4$s 之間,直至 %5$s", + "Every Month on the %1$s for the entire day" : "每個月於 %1$s 整天", + "Every Month on the %1$s for the entire day until %2$s" : "每個月於 %1$s 整天,直至 %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "每個月於 %1$s,在 %2$s - %3$s 之間", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "每個月於 %1$s,在 %2$s - %3$s 之間,直至 %4$s", + "Every %1$d Months on the %2$s for the entire day" : "每 %1$d 個月於 %2$s 整天", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "每 %1$d 個月於 %2$s 整天,直至 %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "每 %1$d 個月於 %2$s,在 %3$s - %4$s 之間", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "每 %1$d 個月於 %2$s,在 %3$s - %4$s 之間,直至 %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "每年於 %1$s 的 %2$s 整天", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "每年於 %1$s 的 %2$s 整天,直至 %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "每年於 %1$s 的 %2$s,在 %3$s - %4$s 之間", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "每年於 %1$s 的 %2$s,在 %3$s - %4$s 之間,直至 %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "每 %1$d 年於 %2$s 的 %3$s 整天", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "每 %1$d 年於 %2$s 的 %3$s 整天,直至 %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "每 %1$d 年於 %2$s 的 %3$s,在 %4$s - %5$s 之間", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "每 %1$d 年於 %2$s 的 %3$s,在 %4$s - %5$s 之間,直至 %6$s", + "On specific dates for the entire day until %1$s" : "在特定日期的整天,直至 %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "在 %1$s - %2$s 之間的特定日期,直至 %3$s", + "In a %1$s on %2$s" : "在 %1$s 的 %2$s", + "In a %1$s on %2$s then on %3$s" : "在 %1$s 的 %2$s,然後 %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "在 %1$s 的 %2$s,然後 %3$s 與 %4$s", + "In %1$s %2$s on %3$s" : "在 %1$s %2$s 的 %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "在 %1$s %2$s 的 %3$s,然後 %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "在 %1$s %2$s 的 %3$s,然後 %4$s 與 %5$s", + "Could not generate next recurrence statement" : "無法產生下一個重複語句", "Cancelled: %1$s" : "已取消:%1$s", "\"%1$s\" has been canceled" : "\"%1$s\" 已被取消", "Re: %1$s" : "關於: %1$s", @@ -86,13 +133,43 @@ OC.L10N.register( "Organizer:" : "主辦單位:", "Attendees:" : "參加者:", "Title:" : "標題:", - "Date and time:" : "日期和時間:", + "When:" : "時間:", "Location:" : "位置:", "Link:" : "連結:", + "Occurring:" : "發生:", "Accept" : "接受", "Decline" : "拒絕", "More options …" : "更多選項 ...", "More options at %s" : "%s有更多選項", + "Monday" : "星期一", + "Tuesday" : "星期二", + "Wednesday" : "星期三", + "Thursday" : "星期四", + "Friday" : "星期五", + "Saturday" : "星期六", + "Sunday" : "星期日", + "January" : "一月", + "February" : "二月", + "March" : "三月", + "April" : "四月", + "May" : "五月", + "June" : "六月", + "July" : "七月", + "August" : "八月", + "September" : "九月", + "October" : "十月", + "November" : "十一月", + "December" : "十二月", + "First" : "首頁", + "Second" : "第二", + "Third" : "第三", + "Fourth" : "第四", + "Fifty" : "五十", + "Last" : "最後", + "Second Last" : "尾二", + "Third Last" : "尾三", + "Fourth Last" : "尾四", + "Fifty Last" : "尾五", "Contacts" : "聯絡人", "{actor} created address book {addressbook}" : "{actor} 創建了通訊錄 {addressbook} ", "You created address book {addressbook}" : "您創建了通訊錄 {addressbook} ", @@ -176,13 +253,6 @@ OC.L10N.register( "No working hours set" : "尚未設置工作時間", "Add slot" : "新增欄位", "Weekdays" : "平日", - "Monday" : "星期一", - "Tuesday" : "星期二", - "Wednesday" : "星期三", - "Thursday" : "星期四", - "Friday" : "星期五", - "Saturday" : "星期六", - "Sunday" : "星期日", "Pick a start time for {dayName}" : "為 {dayName} 挑選開始時間", "Pick a end time for {dayName}" : "為 {dayName} 挑選結束時間", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "在忙碌時,自動將用戶狀態設定為「請勿打擾」以靜音所有通知。", diff --git a/apps/dav/l10n/zh_HK.json b/apps/dav/l10n/zh_HK.json index 75c5a12be33..4875ba98718 100644 --- a/apps/dav/l10n/zh_HK.json +++ b/apps/dav/l10n/zh_HK.json @@ -70,6 +70,53 @@ "Description: %s" : "描述:%s", "Where: %s" : "地點:%s", "%1$s via %2$s" : "%1$s 由 %2$s", + "In a %1$s on %2$s for the entire day" : "%1$s 的 %2$s 整天", + "In a %1$s on %2$s between %3$s - %4$s" : "%1$s 的 %2$s 於 %3$s - %4$s 之間", + "In %1$s %2$s on %3$s for the entire day" : "%1$s %2$s 的 %3$s 整天", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "%1$s %2$s 的 %3$s 於 %4$s - %5$s 之間", + "Could not generate when statement" : "無法產生 when 陳述", + "Every Day for the entire day" : "每天一整天", + "Every Day for the entire day until %1$s" : "每天一整天,直至 %1$s", + "Every Day between %1$s - %2$s" : "每天於 %1$s - %2$s 之間", + "Every Day between %1$s - %2$s until %3$s" : "每天於 %1$s - %2$s 之間,直至 %3$s", + "Every %1$d Days for the entire day" : "每 %1$d 天整天", + "Every %1$d Days for the entire day until %2$s" : "每 %1$d 天整天,直至 %2$s", + "Every %1$d Days between %2$s - %3$s" : "每 %1$d 天於 %2$s - %3$s 之間", + "Every %1$d Days between %2$s - %3$s until %4$s" : "每 %1$d 天於 %2$s - %3$s 之間,直至 %4$s", + "Could not generate event recurrence statement" : "無法產生事件重複陳述", + "Every Week on %1$s for the entire day" : "每週於 %1$s 整天", + "Every Week on %1$s for the entire day until %2$s" : "每週於 %1$s 整天,直到 %2$s", + "Every Week on %1$s between %2$s - %3$s" : "每週於 %1$s,在 %2$s - %3$s 之間", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "每週於 %1$s,在 %2$s - %3$s 之間,直到 %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "每 %1$d 週於 %2$s 整天", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "每 %1$d 週於 %2$s 整天,直至 %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "每 %1$d 週於 %2$s,在 %3$s - %4$s 之間", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "每 %1$d 週於 %2$s,在 %3$s - %4$s 之間,直至 %5$s", + "Every Month on the %1$s for the entire day" : "每個月於 %1$s 整天", + "Every Month on the %1$s for the entire day until %2$s" : "每個月於 %1$s 整天,直至 %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "每個月於 %1$s,在 %2$s - %3$s 之間", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "每個月於 %1$s,在 %2$s - %3$s 之間,直至 %4$s", + "Every %1$d Months on the %2$s for the entire day" : "每 %1$d 個月於 %2$s 整天", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "每 %1$d 個月於 %2$s 整天,直至 %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "每 %1$d 個月於 %2$s,在 %3$s - %4$s 之間", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "每 %1$d 個月於 %2$s,在 %3$s - %4$s 之間,直至 %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "每年於 %1$s 的 %2$s 整天", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "每年於 %1$s 的 %2$s 整天,直至 %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "每年於 %1$s 的 %2$s,在 %3$s - %4$s 之間", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "每年於 %1$s 的 %2$s,在 %3$s - %4$s 之間,直至 %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "每 %1$d 年於 %2$s 的 %3$s 整天", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "每 %1$d 年於 %2$s 的 %3$s 整天,直至 %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "每 %1$d 年於 %2$s 的 %3$s,在 %4$s - %5$s 之間", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "每 %1$d 年於 %2$s 的 %3$s,在 %4$s - %5$s 之間,直至 %6$s", + "On specific dates for the entire day until %1$s" : "在特定日期的整天,直至 %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "在 %1$s - %2$s 之間的特定日期,直至 %3$s", + "In a %1$s on %2$s" : "在 %1$s 的 %2$s", + "In a %1$s on %2$s then on %3$s" : "在 %1$s 的 %2$s,然後 %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "在 %1$s 的 %2$s,然後 %3$s 與 %4$s", + "In %1$s %2$s on %3$s" : "在 %1$s %2$s 的 %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "在 %1$s %2$s 的 %3$s,然後 %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "在 %1$s %2$s 的 %3$s,然後 %4$s 與 %5$s", + "Could not generate next recurrence statement" : "無法產生下一個重複語句", "Cancelled: %1$s" : "已取消:%1$s", "\"%1$s\" has been canceled" : "\"%1$s\" 已被取消", "Re: %1$s" : "關於: %1$s", @@ -84,13 +131,43 @@ "Organizer:" : "主辦單位:", "Attendees:" : "參加者:", "Title:" : "標題:", - "Date and time:" : "日期和時間:", + "When:" : "時間:", "Location:" : "位置:", "Link:" : "連結:", + "Occurring:" : "發生:", "Accept" : "接受", "Decline" : "拒絕", "More options …" : "更多選項 ...", "More options at %s" : "%s有更多選項", + "Monday" : "星期一", + "Tuesday" : "星期二", + "Wednesday" : "星期三", + "Thursday" : "星期四", + "Friday" : "星期五", + "Saturday" : "星期六", + "Sunday" : "星期日", + "January" : "一月", + "February" : "二月", + "March" : "三月", + "April" : "四月", + "May" : "五月", + "June" : "六月", + "July" : "七月", + "August" : "八月", + "September" : "九月", + "October" : "十月", + "November" : "十一月", + "December" : "十二月", + "First" : "首頁", + "Second" : "第二", + "Third" : "第三", + "Fourth" : "第四", + "Fifty" : "五十", + "Last" : "最後", + "Second Last" : "尾二", + "Third Last" : "尾三", + "Fourth Last" : "尾四", + "Fifty Last" : "尾五", "Contacts" : "聯絡人", "{actor} created address book {addressbook}" : "{actor} 創建了通訊錄 {addressbook} ", "You created address book {addressbook}" : "您創建了通訊錄 {addressbook} ", @@ -174,13 +251,6 @@ "No working hours set" : "尚未設置工作時間", "Add slot" : "新增欄位", "Weekdays" : "平日", - "Monday" : "星期一", - "Tuesday" : "星期二", - "Wednesday" : "星期三", - "Thursday" : "星期四", - "Friday" : "星期五", - "Saturday" : "星期六", - "Sunday" : "星期日", "Pick a start time for {dayName}" : "為 {dayName} 挑選開始時間", "Pick a end time for {dayName}" : "為 {dayName} 挑選結束時間", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "在忙碌時,自動將用戶狀態設定為「請勿打擾」以靜音所有通知。", diff --git a/apps/dav/l10n/zh_TW.js b/apps/dav/l10n/zh_TW.js index 63498df4cc4..51021af3b7a 100644 --- a/apps/dav/l10n/zh_TW.js +++ b/apps/dav/l10n/zh_TW.js @@ -72,6 +72,53 @@ OC.L10N.register( "Description: %s" : "描述:%s", "Where: %s" : "地點:%s", "%1$s via %2$s" : "%1$s 由 %2$s", + "In a %1$s on %2$s for the entire day" : "%1$s 的 %2$s 整天", + "In a %1$s on %2$s between %3$s - %4$s" : "%1$s 的 %2$s 於 %3$s - %4$s 之間", + "In %1$s %2$s on %3$s for the entire day" : "%1$s %2$s 的 %3$s 整天", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "%1$s %2$s 的 %3$s 於 %4$s - %5$s 之間", + "Could not generate when statement" : "無法產生 when 陳述", + "Every Day for the entire day" : "每天一整天", + "Every Day for the entire day until %1$s" : "每天一整天,直到 %1$s", + "Every Day between %1$s - %2$s" : "每天於 %1$s - %2$s 之間", + "Every Day between %1$s - %2$s until %3$s" : "每天於 %1$s - %2$s 之間,直到 %3$s", + "Every %1$d Days for the entire day" : "每 %1$d 天整天", + "Every %1$d Days for the entire day until %2$s" : "每 %1$d 天整天,直到 %2$s", + "Every %1$d Days between %2$s - %3$s" : "每 %1$d 天於 %2$s - %3$s 之間", + "Every %1$d Days between %2$s - %3$s until %4$s" : "每 %1$d 天於 %2$s - %3$s 之間,直到 %4$s", + "Could not generate event recurrence statement" : "無法產生事件重複陳述", + "Every Week on %1$s for the entire day" : "每週於 %1$s 整天", + "Every Week on %1$s for the entire day until %2$s" : "每週於 %1$s 整天,直到 %2$s", + "Every Week on %1$s between %2$s - %3$s" : "每週於 %1$s,在 %2$s - %3$s 之間", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "每週於 %1$s,在 %2$s - %3$s 之間,直到 %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "每 %1$d 週於 %2$s 整天", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "每 %1$d 週於 %2$s 整天,直到 %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "每 %1$d 週於 %2$s,在 %3$s - %4$s 之間", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "每 %1$d 週於 %2$s,在 %3$s - %4$s 之間,直到 %5$s", + "Every Month on the %1$s for the entire day" : "每個月於 %1$s 整天", + "Every Month on the %1$s for the entire day until %2$s" : "每個月於 %1$s 整天,直到 %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "每個月於 %1$s,在 %2$s - %3$s 之間", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "每個月於 %1$s,在 %2$s - %3$s 之間,直到 %4$s", + "Every %1$d Months on the %2$s for the entire day" : "每 %1$d 個月於 %2$s 整天", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "每 %1$d 個月於 %2$s 整天,直到 %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "每 %1$d 個月於 %2$s,在 %3$s - %4$s 之間", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "每 %1$d 個月於 %2$s,在 %3$s - %4$s 之間,直到 %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "每年於 %1$s 的 %2$s 整天", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "每年於 %1$s 的 %2$s 整天,直到 %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "每年於 %1$s 的 %2$s,在 %3$s - %4$s 之間", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "每年於 %1$s 的 %2$s,在 %3$s - %4$s 之間,直到 %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "每 %1$d 年於 %2$s 的 %3$s 整天", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "每 %1$d 年於 %2$s 的 %3$s 整天,直到 %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "每 %1$d 年於 %2$s 的 %3$s,在 %4$s - %5$s 之間", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "每 %1$d 年於 %2$s 的 %3$s,在 %4$s - %5$s 之間,直到 %6$s", + "On specific dates for the entire day until %1$s" : "在特定日期的整天,直到 %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "在 %1$s - %2$s 之間的特定日期,直到 %3$s", + "In a %1$s on %2$s" : "在 %1$s 的 %2$s", + "In a %1$s on %2$s then on %3$s" : "在 %1$s 的 %2$s,然後 %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "在 %1$s 的 %2$s,然後 %3$s 與 %4$s", + "In %1$s %2$s on %3$s" : "在 %1$s %2$s 的 %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "在 %1$s %2$s 的 %3$s,然後 %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "在 %1$s %2$s 的 %3$s,然後 %4$s 與 %5$s", + "Could not generate next recurrence statement" : "無法產生下一個重複陳述", "Cancelled: %1$s" : "已取消:%1$s", "\"%1$s\" has been canceled" : "「%1$s」已取消", "Re: %1$s" : "回覆:%1$s", @@ -86,13 +133,43 @@ OC.L10N.register( "Organizer:" : "組織者:", "Attendees:" : "參與者:", "Title:" : "標題:", - "Date and time:" : "日期與時間:", + "When:" : "時間:", "Location:" : "地點:", "Link:" : "連結:", + "Occurring:" : "發生:", "Accept" : "接受", "Decline" : "拒絕", "More options …" : "更多選項……", "More options at %s" : "%s 有更多選項", + "Monday" : "週一", + "Tuesday" : "週二", + "Wednesday" : "週三", + "Thursday" : "週四", + "Friday" : "週五", + "Saturday" : "週六", + "Sunday" : "週日", + "January" : "一月", + "February" : "二月", + "March" : "三月", + "April" : "四月", + "May" : "五月", + "June" : "六月", + "July" : "七月", + "August" : "八月", + "September" : "九月", + "October" : "十月", + "November" : "十一月", + "December" : "十二月", + "First" : "第一個", + "Second" : "第二", + "Third" : "第三", + "Fourth" : "第四", + "Fifty" : "五十", + "Last" : "最後", + "Second Last" : "倒數第二", + "Third Last" : "倒數第三", + "Fourth Last" : "倒數第四", + "Fifty Last" : "倒數五十", "Contacts" : "聯絡人", "{actor} created address book {addressbook}" : "{actor} 建立了通訊錄 {addressbook}", "You created address book {addressbook}" : "您建立了通訊錄 {addressbook}", @@ -176,13 +253,6 @@ OC.L10N.register( "No working hours set" : "未設定工作時間", "Add slot" : "新增欄位", "Weekdays" : "週間", - "Monday" : "週一", - "Tuesday" : "週二", - "Wednesday" : "週三", - "Thursday" : "週四", - "Friday" : "週五", - "Saturday" : "週六", - "Sunday" : "週日", "Pick a start time for {dayName}" : "為 {dayName} 挑選開始時間", "Pick a end time for {dayName}" : "為 {dayName} 挑選結束時間", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "在忙碌時,自動將使用者狀態設定為「請勿打擾」以靜音所有通知。", diff --git a/apps/dav/l10n/zh_TW.json b/apps/dav/l10n/zh_TW.json index 8aaa7d736cc..2f93ffea531 100644 --- a/apps/dav/l10n/zh_TW.json +++ b/apps/dav/l10n/zh_TW.json @@ -70,6 +70,53 @@ "Description: %s" : "描述:%s", "Where: %s" : "地點:%s", "%1$s via %2$s" : "%1$s 由 %2$s", + "In a %1$s on %2$s for the entire day" : "%1$s 的 %2$s 整天", + "In a %1$s on %2$s between %3$s - %4$s" : "%1$s 的 %2$s 於 %3$s - %4$s 之間", + "In %1$s %2$s on %3$s for the entire day" : "%1$s %2$s 的 %3$s 整天", + "In %1$s %2$s on %3$s between %4$s - %5$s" : "%1$s %2$s 的 %3$s 於 %4$s - %5$s 之間", + "Could not generate when statement" : "無法產生 when 陳述", + "Every Day for the entire day" : "每天一整天", + "Every Day for the entire day until %1$s" : "每天一整天,直到 %1$s", + "Every Day between %1$s - %2$s" : "每天於 %1$s - %2$s 之間", + "Every Day between %1$s - %2$s until %3$s" : "每天於 %1$s - %2$s 之間,直到 %3$s", + "Every %1$d Days for the entire day" : "每 %1$d 天整天", + "Every %1$d Days for the entire day until %2$s" : "每 %1$d 天整天,直到 %2$s", + "Every %1$d Days between %2$s - %3$s" : "每 %1$d 天於 %2$s - %3$s 之間", + "Every %1$d Days between %2$s - %3$s until %4$s" : "每 %1$d 天於 %2$s - %3$s 之間,直到 %4$s", + "Could not generate event recurrence statement" : "無法產生事件重複陳述", + "Every Week on %1$s for the entire day" : "每週於 %1$s 整天", + "Every Week on %1$s for the entire day until %2$s" : "每週於 %1$s 整天,直到 %2$s", + "Every Week on %1$s between %2$s - %3$s" : "每週於 %1$s,在 %2$s - %3$s 之間", + "Every Week on %1$s between %2$s - %3$s until %4$s" : "每週於 %1$s,在 %2$s - %3$s 之間,直到 %4$s", + "Every %1$d Weeks on %2$s for the entire day" : "每 %1$d 週於 %2$s 整天", + "Every %1$d Weeks on %2$s for the entire day until %3$s" : "每 %1$d 週於 %2$s 整天,直到 %3$s", + "Every %1$d Weeks on %2$s between %3$s - %4$s" : "每 %1$d 週於 %2$s,在 %3$s - %4$s 之間", + "Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "每 %1$d 週於 %2$s,在 %3$s - %4$s 之間,直到 %5$s", + "Every Month on the %1$s for the entire day" : "每個月於 %1$s 整天", + "Every Month on the %1$s for the entire day until %2$s" : "每個月於 %1$s 整天,直到 %2$s", + "Every Month on the %1$s between %2$s - %3$s" : "每個月於 %1$s,在 %2$s - %3$s 之間", + "Every Month on the %1$s between %2$s - %3$s until %4$s" : "每個月於 %1$s,在 %2$s - %3$s 之間,直到 %4$s", + "Every %1$d Months on the %2$s for the entire day" : "每 %1$d 個月於 %2$s 整天", + "Every %1$d Months on the %2$s for the entire day until %3$s" : "每 %1$d 個月於 %2$s 整天,直到 %3$s", + "Every %1$d Months on the %2$s between %3$s - %4$s" : "每 %1$d 個月於 %2$s,在 %3$s - %4$s 之間", + "Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "每 %1$d 個月於 %2$s,在 %3$s - %4$s 之間,直到 %5$s", + "Every Year in %1$s on the %2$s for the entire day" : "每年於 %1$s 的 %2$s 整天", + "Every Year in %1$s on the %2$s for the entire day until %3$s" : "每年於 %1$s 的 %2$s 整天,直到 %3$s", + "Every Year in %1$s on the %2$s between %3$s - %4$s" : "每年於 %1$s 的 %2$s,在 %3$s - %4$s 之間", + "Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "每年於 %1$s 的 %2$s,在 %3$s - %4$s 之間,直到 %5$s", + "Every %1$d Years in %2$s on the %3$s for the entire day" : "每 %1$d 年於 %2$s 的 %3$s 整天", + "Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "每 %1$d 年於 %2$s 的 %3$s 整天,直到 %4$s", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "每 %1$d 年於 %2$s 的 %3$s,在 %4$s - %5$s 之間", + "Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "每 %1$d 年於 %2$s 的 %3$s,在 %4$s - %5$s 之間,直到 %6$s", + "On specific dates for the entire day until %1$s" : "在特定日期的整天,直到 %1$s", + "On specific dates between %1$s - %2$s until %3$s" : "在 %1$s - %2$s 之間的特定日期,直到 %3$s", + "In a %1$s on %2$s" : "在 %1$s 的 %2$s", + "In a %1$s on %2$s then on %3$s" : "在 %1$s 的 %2$s,然後 %3$s", + "In a %1$s on %2$s then on %3$s and %4$s" : "在 %1$s 的 %2$s,然後 %3$s 與 %4$s", + "In %1$s %2$s on %3$s" : "在 %1$s %2$s 的 %3$s", + "In %1$s %2$s on %3$s then on %4$s" : "在 %1$s %2$s 的 %3$s,然後 %4$s", + "In %1$s %2$s on %3$s then on %4$s and %5$s" : "在 %1$s %2$s 的 %3$s,然後 %4$s 與 %5$s", + "Could not generate next recurrence statement" : "無法產生下一個重複陳述", "Cancelled: %1$s" : "已取消:%1$s", "\"%1$s\" has been canceled" : "「%1$s」已取消", "Re: %1$s" : "回覆:%1$s", @@ -84,13 +131,43 @@ "Organizer:" : "組織者:", "Attendees:" : "參與者:", "Title:" : "標題:", - "Date and time:" : "日期與時間:", + "When:" : "時間:", "Location:" : "地點:", "Link:" : "連結:", + "Occurring:" : "發生:", "Accept" : "接受", "Decline" : "拒絕", "More options …" : "更多選項……", "More options at %s" : "%s 有更多選項", + "Monday" : "週一", + "Tuesday" : "週二", + "Wednesday" : "週三", + "Thursday" : "週四", + "Friday" : "週五", + "Saturday" : "週六", + "Sunday" : "週日", + "January" : "一月", + "February" : "二月", + "March" : "三月", + "April" : "四月", + "May" : "五月", + "June" : "六月", + "July" : "七月", + "August" : "八月", + "September" : "九月", + "October" : "十月", + "November" : "十一月", + "December" : "十二月", + "First" : "第一個", + "Second" : "第二", + "Third" : "第三", + "Fourth" : "第四", + "Fifty" : "五十", + "Last" : "最後", + "Second Last" : "倒數第二", + "Third Last" : "倒數第三", + "Fourth Last" : "倒數第四", + "Fifty Last" : "倒數五十", "Contacts" : "聯絡人", "{actor} created address book {addressbook}" : "{actor} 建立了通訊錄 {addressbook}", "You created address book {addressbook}" : "您建立了通訊錄 {addressbook}", @@ -174,13 +251,6 @@ "No working hours set" : "未設定工作時間", "Add slot" : "新增欄位", "Weekdays" : "週間", - "Monday" : "週一", - "Tuesday" : "週二", - "Wednesday" : "週三", - "Thursday" : "週四", - "Friday" : "週五", - "Saturday" : "週六", - "Sunday" : "週日", "Pick a start time for {dayName}" : "為 {dayName} 挑選開始時間", "Pick a end time for {dayName}" : "為 {dayName} 挑選結束時間", "Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "在忙碌時,自動將使用者狀態設定為「請勿打擾」以靜音所有通知。", diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php index cc6c4344c3c..49e99201df1 100644 --- a/apps/dav/lib/CalDAV/CalDavBackend.php +++ b/apps/dav/lib/CalDAV/CalDavBackend.php @@ -65,6 +65,7 @@ use Sabre\VObject\ParseException; use Sabre\VObject\Property; use Sabre\VObject\Reader; use Sabre\VObject\Recur\EventIterator; +use Sabre\VObject\Recur\NoInstancesException; use function array_column; use function array_map; use function array_merge; @@ -1874,12 +1875,12 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription } if (!empty($searchProperties)) { - $or = $innerQuery->expr()->orX(); + $or = []; foreach ($searchProperties as $searchProperty) { - $or->add($innerQuery->expr()->eq('op.name', - $outerQuery->createNamedParameter($searchProperty))); + $or[] = $innerQuery->expr()->eq('op.name', + $outerQuery->createNamedParameter($searchProperty)); } - $innerQuery->andWhere($or); + $innerQuery->andWhere($innerQuery->expr()->orX(...$or)); } if ($pattern !== '') { @@ -1923,12 +1924,12 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription } if (!empty($options['types'])) { - $or = $outerQuery->expr()->orX(); + $or = []; foreach ($options['types'] as $type) { - $or->add($outerQuery->expr()->eq('componenttype', - $outerQuery->createNamedParameter($type))); + $or[] = $outerQuery->expr()->eq('componenttype', + $outerQuery->createNamedParameter($type)); } - $outerQuery->andWhere($or); + $outerQuery->andWhere($outerQuery->expr()->orX(...$or)); } $outerQuery->andWhere($outerQuery->expr()->in('c.id', $outerQuery->createFunction($innerQuery->getSQL()))); @@ -2149,16 +2150,17 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $escapePattern = !\array_key_exists('escape_like_param', $options) || $options['escape_like_param'] !== false; $calendarObjectIdQuery = $this->db->getQueryBuilder(); - $calendarOr = $calendarObjectIdQuery->expr()->orX(); - $searchOr = $calendarObjectIdQuery->expr()->orX(); + $calendarOr = []; + $searchOr = []; // Fetch calendars and subscription $calendars = $this->getCalendarsForUser($principalUri); $subscriptions = $this->getSubscriptionsForUser($principalUri); foreach ($calendars as $calendar) { - $calendarAnd = $calendarObjectIdQuery->expr()->andX(); - $calendarAnd->add($calendarObjectIdQuery->expr()->eq('cob.calendarid', $calendarObjectIdQuery->createNamedParameter((int)$calendar['id']))); - $calendarAnd->add($calendarObjectIdQuery->expr()->eq('cob.calendartype', $calendarObjectIdQuery->createNamedParameter(self::CALENDAR_TYPE_CALENDAR))); + $calendarAnd = $calendarObjectIdQuery->expr()->andX( + $calendarObjectIdQuery->expr()->eq('cob.calendarid', $calendarObjectIdQuery->createNamedParameter((int)$calendar['id'])), + $calendarObjectIdQuery->expr()->eq('cob.calendartype', $calendarObjectIdQuery->createNamedParameter(self::CALENDAR_TYPE_CALENDAR)), + ); // If it's shared, limit search to public events if (isset($calendar['{http://owncloud.org/ns}owner-principal']) @@ -2166,12 +2168,13 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $calendarAnd->add($calendarObjectIdQuery->expr()->eq('co.classification', $calendarObjectIdQuery->createNamedParameter(self::CLASSIFICATION_PUBLIC))); } - $calendarOr->add($calendarAnd); + $calendarOr[] = $calendarAnd; } foreach ($subscriptions as $subscription) { - $subscriptionAnd = $calendarObjectIdQuery->expr()->andX(); - $subscriptionAnd->add($calendarObjectIdQuery->expr()->eq('cob.calendarid', $calendarObjectIdQuery->createNamedParameter((int)$subscription['id']))); - $subscriptionAnd->add($calendarObjectIdQuery->expr()->eq('cob.calendartype', $calendarObjectIdQuery->createNamedParameter(self::CALENDAR_TYPE_SUBSCRIPTION))); + $subscriptionAnd = $calendarObjectIdQuery->expr()->andX( + $calendarObjectIdQuery->expr()->eq('cob.calendarid', $calendarObjectIdQuery->createNamedParameter((int)$subscription['id'])), + $calendarObjectIdQuery->expr()->eq('cob.calendartype', $calendarObjectIdQuery->createNamedParameter(self::CALENDAR_TYPE_SUBSCRIPTION)), + ); // If it's shared, limit search to public events if (isset($subscription['{http://owncloud.org/ns}owner-principal']) @@ -2179,28 +2182,30 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $subscriptionAnd->add($calendarObjectIdQuery->expr()->eq('co.classification', $calendarObjectIdQuery->createNamedParameter(self::CLASSIFICATION_PUBLIC))); } - $calendarOr->add($subscriptionAnd); + $calendarOr[] = $subscriptionAnd; } foreach ($searchProperties as $property) { - $propertyAnd = $calendarObjectIdQuery->expr()->andX(); - $propertyAnd->add($calendarObjectIdQuery->expr()->eq('cob.name', $calendarObjectIdQuery->createNamedParameter($property, IQueryBuilder::PARAM_STR))); - $propertyAnd->add($calendarObjectIdQuery->expr()->isNull('cob.parameter')); + $propertyAnd = $calendarObjectIdQuery->expr()->andX( + $calendarObjectIdQuery->expr()->eq('cob.name', $calendarObjectIdQuery->createNamedParameter($property, IQueryBuilder::PARAM_STR)), + $calendarObjectIdQuery->expr()->isNull('cob.parameter'), + ); - $searchOr->add($propertyAnd); + $searchOr[] = $propertyAnd; } foreach ($searchParameters as $property => $parameter) { - $parameterAnd = $calendarObjectIdQuery->expr()->andX(); - $parameterAnd->add($calendarObjectIdQuery->expr()->eq('cob.name', $calendarObjectIdQuery->createNamedParameter($property, IQueryBuilder::PARAM_STR))); - $parameterAnd->add($calendarObjectIdQuery->expr()->eq('cob.parameter', $calendarObjectIdQuery->createNamedParameter($parameter, IQueryBuilder::PARAM_STR_ARRAY))); + $parameterAnd = $calendarObjectIdQuery->expr()->andX( + $calendarObjectIdQuery->expr()->eq('cob.name', $calendarObjectIdQuery->createNamedParameter($property, IQueryBuilder::PARAM_STR)), + $calendarObjectIdQuery->expr()->eq('cob.parameter', $calendarObjectIdQuery->createNamedParameter($parameter, IQueryBuilder::PARAM_STR_ARRAY)), + ); - $searchOr->add($parameterAnd); + $searchOr[] = $parameterAnd; } - if ($calendarOr->count() === 0) { + if (empty($calendarOr)) { return []; } - if ($searchOr->count() === 0) { + if (empty($searchOr)) { return []; } @@ -2208,8 +2213,8 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription ->from($this->dbObjectPropertiesTable, 'cob') ->leftJoin('cob', 'calendarobjects', 'co', $calendarObjectIdQuery->expr()->eq('co.id', 'cob.objectid')) ->andWhere($calendarObjectIdQuery->expr()->in('co.componenttype', $calendarObjectIdQuery->createNamedParameter($componentTypes, IQueryBuilder::PARAM_STR_ARRAY))) - ->andWhere($calendarOr) - ->andWhere($searchOr) + ->andWhere($calendarObjectIdQuery->expr()->orX(...$calendarOr)) + ->andWhere($calendarObjectIdQuery->expr()->orX(...$searchOr)) ->andWhere($calendarObjectIdQuery->expr()->isNull('deleted_at')); if ($pattern !== '') { @@ -2987,7 +2992,15 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription $lastOccurrence = $firstOccurrence; } } else { - $it = new EventIterator($vEvents); + try { + $it = new EventIterator($vEvents); + } catch (NoInstancesException $e) { + $this->logger->debug('Caught no instance exception for calendar data. This usually indicates invalid calendar data.', [ + 'app' => 'dav', + 'exception' => $e, + ]); + throw new Forbidden($e->getMessage()); + } $maxDate = new DateTime(self::MAX_DATE); $firstOccurrence = $it->getDtStart()->getTimestamp(); if ($it->isInfinite()) { diff --git a/apps/dav/lib/CalDAV/EventReader.php b/apps/dav/lib/CalDAV/EventReader.php new file mode 100644 index 00000000000..99e5677d432 --- /dev/null +++ b/apps/dav/lib/CalDAV/EventReader.php @@ -0,0 +1,758 @@ + 'Monday', 'TU' => 'Tuesday', 'WE' => 'Wednesday', 'TH' => 'Thursday', 'FR' => 'Friday', 'SA' => 'Saturday', 'SU' => 'Sunday' + ]; + protected array $monthNamesMap = [ + 1 => 'January', 2 => 'February', 3 => 'March', 4 => 'April', 5 => 'May', 6 => 'June', + 7 => 'July', 8 => 'August', 9 => 'September', 10 => 'October', 11 => 'November', 12 => 'December' + ]; + protected array $relativePositionNamesMap = [ + 1 => 'First', 2 => 'Second', 3 => 'Third', 4 => 'Fourth', 5 => 'Fifty', + -1 => 'Last', -2 => 'Second Last', -3 => 'Third Last', -4 => 'Fourth Last', -5 => 'Fifty Last' + ]; + + /** + * Initilizes the Event Reader + * + * There is several ways to set up the iterator. + * + * 1. You can pass a VCALENDAR component (as object or string) and a UID. + * 2. You can pass an array of VEVENTs (all UIDS should match). + * 3. You can pass a single VEVENT component (as object or string). + * + * Only the second method is recommended. The other 1 and 3 will be removed + * at some point in the future. + * + * The $uid parameter is only required for the first method. + * + * @since 30.0.0 + * + * @param VCalendar|VEvent|Array|String $input + * @param string|null $uid + * @param DateTimeZone|null $timeZone reference timezone for floating dates and times + */ + public function __construct(VCalendar|VEvent|array|string $input, ?string $uid = null, ?DateTimeZone $timeZone = null) { + + // evaluate if the input is a string and convert it to and vobject if required + if (is_string($input)) { + $input = Reader::read($input); + } + // evaluate if input is a single event vobject and convert it to a collection + if ($input instanceof VEvent) { + $events = [$input]; + } + // evaluate if input is a calendar vobject + elseif ($input instanceof VCalendar) { + // Calendar + UID mode. + if ($uid === null) { + throw new InvalidArgumentException('The UID argument is required when a VCALENDAR object is used'); + } + // extract events from calendar + $events = $input->getByUID($uid); + // evaluate if any event where found + if (count($events) === 0) { + throw new InvalidArgumentException('This VCALENDAR did not have an event with UID: '.$uid); + } + // extract calendar timezone + if (isset($input->VTIMEZONE) && isset($input->VTIMEZONE->TZID)) { + $calendarTimeZone = new DateTimeZone($input->VTIMEZONE->TZID->getValue()); + } + } + // evaluate if input is a collection of event vobjects + elseif (is_array($input)) { + $events = $input; + } else { + throw new InvalidArgumentException('Invalid input data type'); + } + // find base event instance and remove it from events collection + foreach ($events as $key => $vevent) { + if (!isset($vevent->{'RECURRENCE-ID'})) { + $this->baseEvent = $vevent; + unset($events[$key]); + } + } + + // No base event was found. CalDAV does allow cases where only + // overridden instances are stored. + // + // In this particular case, we're just going to grab the first + // event and use that instead. This may not always give the + // desired result. + if (!isset($this->baseEvent) && count($events) > 0) { + $this->baseEvent = array_shift($events); + } + + // determain the event starting time zone + // we require this to align all other dates times + // evaluate if timezone paramater was used (treat this as a override) + if ($timeZone !== null) { + $this->baseEventStartTimeZone = $timeZone; + } + // evaluate if event start date has a timezone parameter + elseif (isset($this->baseEvent->DTSTART->parameters['TZID'])) { + $this->baseEventStartTimeZone = new DateTimeZone($this->baseEvent->DTSTART->parameters['TZID']->getValue()); + } + // evaluate if event parent calendar has a time zone + elseif (isset($calendarTimeZone)) { + $this->baseEventStartTimeZone = clone $calendarTimeZone; + } + // otherwise, as a last resort use the UTC timezone + else { + $this->baseEventStartTimeZone = new DateTimeZone('UTC'); + } + + // determain the event end time zone + // we require this to align all other dates and times + // evaluate if timezone paramater was used (treat this as a override) + if ($timeZone !== null) { + $this->baseEventEndTimeZone = $timeZone; + } + // evaluate if event end date has a timezone parameter + elseif (isset($this->baseEvent->DTEND->parameters['TZID'])) { + $this->baseEventEndTimeZone = new DateTimeZone($this->baseEvent->DTEND->parameters['TZID']->getValue()); + } + // evaluate if event parent calendar has a time zone + elseif (isset($calendarTimeZone)) { + $this->baseEventEndTimeZone = clone $calendarTimeZone; + } + // otherwise, as a last resort use the start date time zone + else { + $this->baseEventEndTimeZone = clone $this->baseEventStartTimeZone; + } + // extract start date and time + $this->baseEventStartDate = $this->baseEvent->DTSTART->getDateTime($this->baseEventStartTimeZone); + $this->baseEventStartDateFloating = $this->baseEvent->DTSTART->isFloating(); + // determine event end date and duration + // evaluate if end date exists + // extract end date and calculate duration + if (isset($this->baseEvent->DTEND)) { + $this->baseEventEndDate = $this->baseEvent->DTEND->getDateTime($this->baseEventEndTimeZone); + $this->baseEventEndDateFloating = $this->baseEvent->DTEND->isFloating(); + $this->baseEventDuration = + $this->baseEvent->DTEND->getDateTime($this->baseEventEndTimeZone)->getTimeStamp() - + $this->baseEventStartDate->getTimeStamp(); + } + // evaluate if duration exists + // extract duration and calculate end date + elseif (isset($this->baseEvent->DURATION)) { + $this->baseEventDuration = $this->baseEvent->DURATION->getDateInterval(); + $this->baseEventEndDate = ((clone $this->baseEventStartDate)->add($this->baseEventDuration)); + } + // evaluate if start date is floating + // set duration to 24 hours and calculate the end date + // according to the rfc any event without a end date or duration is a complete day + elseif ($this->baseEventStartDateFloating == true) { + $this->baseEventDuration = 86400; + $this->baseEventEndDate = ((clone $this->baseEventStartDate)->add($this->baseEventDuration)); + } + // otherwise, set duration to zero this should never happen + else { + $this->baseEventDuration = 0; + $this->baseEventEndDate = $this->baseEventStartDate; + } + // evaluate if RRULE exist and construct iterator + if (isset($this->baseEvent->RRULE)) { + $this->rruleIterator = new EventReaderRRule( + $this->baseEvent->RRULE->getParts(), + $this->baseEventStartDate + ); + } + // evaluate if RDATE exist and construct iterator + if (isset($this->baseEvent->RDATE)) { + $this->rdateIterator = new EventReaderRDate( + $this->baseEvent->RDATE->getValue(), + $this->baseEventStartDate + ); + } + // evaluate if EXRULE exist and construct iterator + if (isset($this->baseEvent->EXRULE)) { + $this->eruleIterator = new EventReaderRRule( + $this->baseEvent->EXRULE->getParts(), + $this->baseEventStartDate + ); + } + // evaluate if EXDATE exist and construct iterator + if (isset($this->baseEvent->EXDATE)) { + $this->edateIterator = new EventReaderRDate( + $this->baseEvent->EXDATE->getValue(), + $this->baseEventStartDate + ); + } + // construct collection of modified events with recurrence id as hash + foreach ($events as $vevent) { + $this->recurrenceModified[$vevent->{'RECURRENCE-ID'}->getDateTime($this->baseEventStartTimeZone)->getTimeStamp()] = $vevent; + } + + $this->recurrenceCurrentDate = clone $this->baseEventStartDate; + } + + /** + * retrieve date and time of event start + * + * @since 30.0.0 + * + * @return DateTime + */ + public function startDateTime(): DateTime { + return DateTime::createFromInterface($this->baseEventStartDate); + } + + /** + * retrieve time zone of event start + * + * @since 30.0.0 + * + * @return DateTimeZone + */ + public function startTimeZone(): DateTimeZone { + return $this->baseEventStartTimeZone; + } + + /** + * retrieve date and time of event end + * + * @since 30.0.0 + * + * @return DateTime + */ + public function endDateTime(): DateTime { + return DateTime::createFromInterface($this->baseEventEndDate); + } + + /** + * retrieve time zone of event end + * + * @since 30.0.0 + * + * @return DateTimeZone + */ + public function endTimeZone(): DateTimeZone { + return $this->baseEventEndTimeZone; + } + + /** + * is this an all day event + * + * @since 30.0.0 + * + * @return bool + */ + public function entireDay(): bool { + return $this->baseEventStartDateFloating; + } + + /** + * is this a recurring event + * + * @since 30.0.0 + * + * @return bool + */ + public function recurs(): bool { + return ($this->rruleIterator !== null || $this->rdateIterator !== null); + } + + /** + * event recurrence pattern + * + * @since 30.0.0 + * + * @return string|null R - Relative or A - Absolute + */ + public function recurringPattern(): string | null { + if ($this->rruleIterator === null && $this->rdateIterator === null) { + return null; + } + if ($this->rruleIterator?->isRelative()) { + return 'R'; + } + return 'A'; + } + + /** + * event recurrence precision + * + * @since 30.0.0 + * + * @return string|null daily, weekly, monthly, yearly, fixed + */ + public function recurringPrecision(): string | null { + if ($this->rruleIterator !== null) { + return $this->rruleIterator->precision(); + } + if ($this->rdateIterator !== null) { + return 'fixed'; + } + return null; + } + + /** + * event recurrence interval + * + * @since 30.0.0 + * + * @return int|null + */ + public function recurringInterval(): int | null { + return $this->rruleIterator?->interval(); + } + + /** + * event recurrence conclusion + * + * returns true if RRULE with UNTIL or COUNT (calculated) is used + * returns true RDATE is used + * returns false if RRULE or RDATE are absent, or RRRULE is infinite + * + * @since 30.0.0 + * + * @return bool + */ + public function recurringConcludes(): bool { + + // retrieve rrule conclusions + if ($this->rruleIterator?->concludesOn() !== null || + $this->rruleIterator?->concludesAfter() !== null) { + return true; + } + // retrieve rdate conclusions + if ($this->rdateIterator?->concludesAfter() !== null) { + return true; + } + + return false; + + } + + /** + * event recurrence conclusion iterations + * + * returns the COUNT value if RRULE is used + * returns the collection count if RDATE is used + * returns combined count of RRULE COUNT and RDATE if both are used + * returns null if RRULE and RDATE are absent + * + * @since 30.0.0 + * + * @return int|null + */ + public function recurringConcludesAfter(): int | null { + + // construct count place holder + $count = 0; + // retrieve and add RRULE iterations count + $count += (int) $this->rruleIterator?->concludesAfter(); + // retrieve and add RDATE iterations count + $count += (int) $this->rdateIterator?->concludesAfter(); + // return count + return !empty($count) ? $count : null; + + } + + /** + * event recurrence conclusion date + * + * returns the last date of UNTIL or COUNT (calculated) if RRULE is used + * returns the last date in the collection if RDATE is used + * returns the highest date if both RRULE and RDATE are used + * returns null if RRULE and RDATE are absent or RRULE is infinite + * + * @since 30.0.0 + * + * @return DateTime|null + */ + public function recurringConcludesOn(): DateTime | null { + + if ($this->rruleIterator !== null) { + // retrieve rrule conclusion date + $rrule = $this->rruleIterator->concludes(); + // evaluate if rrule conclusion is null + // if this is null that means the recurrence is infinate + if ($rrule === null) { + return null; + } + } + // retrieve rdate conclusion date + if ($this->rdateIterator !== null) { + $rdate = $this->rdateIterator->concludes(); + } + // evaluate if both rrule and rdate have date + if (isset($rdate) && isset($rrule)) { + // return the highest date + return (($rdate > $rrule) ? $rdate : $rrule); + } elseif (isset($rrule)) { + return $rrule; + } elseif (isset($rdate)) { + return $rdate; + } + + return null; + + } + + /** + * event recurrence days of the week + * + * returns collection of RRULE BYDAY day(s) ['MO','WE','FR'] + * returns blank collection if RRULE is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringDaysOfWeek(): array { + // evaluate if RRULE exists and return day(s) of the week + return $this->rruleIterator !== null ? $this->rruleIterator->daysOfWeek() : []; + } + + /** + * event recurrence days of the week (named) + * + * returns collection of RRULE BYDAY day(s) ['Monday','Wednesday','Friday'] + * returns blank collection if RRULE is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringDaysOfWeekNamed(): array { + // evaluate if RRULE exists and extract day(s) of the week + $days = $this->rruleIterator !== null ? $this->rruleIterator->daysOfWeek() : []; + // convert numberic month to month name + foreach ($days as $key => $value) { + $days[$key] = $this->dayNamesMap[$value]; + } + // return names collection + return $days; + } + + /** + * event recurrence days of the month + * + * returns collection of RRULE BYMONTHDAY day(s) [7, 15, 31] + * returns blank collection if RRULE is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringDaysOfMonth(): array { + // evaluate if RRULE exists and return day(s) of the month + return $this->rruleIterator !== null ? $this->rruleIterator->daysOfMonth() : []; + } + + /** + * event recurrence days of the year + * + * returns collection of RRULE BYYEARDAY day(s) [57, 205, 365] + * returns blank collection if RRULE is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringDaysOfYear(): array { + // evaluate if RRULE exists and return day(s) of the year + return $this->rruleIterator !== null ? $this->rruleIterator->daysOfYear() : []; + } + + /** + * event recurrence weeks of the month + * + * returns collection of RRULE SETPOS weeks(s) [1, 3, -1] + * returns blank collection if RRULE is absent or SETPOS is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringWeeksOfMonth(): array { + // evaluate if RRULE exists and RRULE is relative return relative position(s) + return $this->rruleIterator?->isRelative() ? $this->rruleIterator->relativePosition() : []; + } + + /** + * event recurrence weeks of the month (named) + * + * returns collection of RRULE SETPOS weeks(s) [1, 3, -1] + * returns blank collection if RRULE is absent or SETPOS is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringWeeksOfMonthNamed(): array { + // evaluate if RRULE exists and extract relative position(s) + $positions = $this->rruleIterator?->isRelative() ? $this->rruleIterator->relativePosition() : []; + // convert numberic relative position to relative label + foreach ($positions as $key => $value) { + $positions[$key] = $this->relativePositionNamesMap[$value]; + } + // return positions collection + return $positions; + } + + /** + * event recurrence weeks of the year + * + * returns collection of RRULE BYWEEKNO weeks(s) [12, 32, 52] + * returns blank collection if RRULE is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringWeeksOfYear(): array { + // evaluate if RRULE exists and return weeks(s) of the year + return $this->rruleIterator !== null ? $this->rruleIterator->weeksOfYear() : []; + } + + /** + * event recurrence months of the year + * + * returns collection of RRULE BYMONTH month(s) [3, 7, 12] + * returns blank collection if RRULE is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringMonthsOfYear(): array { + // evaluate if RRULE exists and return month(s) of the year + return $this->rruleIterator !== null ? $this->rruleIterator->monthsOfYear() : []; + } + + /** + * event recurrence months of the year (named) + * + * returns collection of RRULE BYMONTH month(s) [3, 7, 12] + * returns blank collection if RRULE is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringMonthsOfYearNamed(): array { + // evaluate if RRULE exists and extract month(s) of the year + $months = $this->rruleIterator !== null ? $this->rruleIterator->monthsOfYear() : []; + // convert numberic month to month name + foreach ($months as $key => $value) { + $months[$key] = $this->monthNamesMap[$value]; + } + // return months collection + return $months; + } + + /** + * event recurrence relative positions + * + * returns collection of RRULE SETPOS value(s) [1, 5, -3] + * returns blank collection if RRULE is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringRelativePosition(): array { + // evaluate if RRULE exists and return relative position(s) + return $this->rruleIterator !== null ? $this->rruleIterator->relativePosition() : []; + } + + /** + * event recurrence relative positions (named) + * + * returns collection of RRULE SETPOS [1, 3, -1] + * returns blank collection if RRULE is absent or SETPOS is absent, RDATE presents or absents has no affect + * + * @since 30.0.0 + * + * @return array + */ + public function recurringRelativePositionNamed(): array { + // evaluate if RRULE exists and extract relative position(s) + $positions = $this->rruleIterator?->isRelative() ? $this->rruleIterator->relativePosition() : []; + // convert numberic relative position to relative label + foreach ($positions as $key => $value) { + $positions[$key] = $this->relativePositionNamesMap[$value]; + } + // return positions collection + return $positions; + } + + /** + * event recurrence date + * + * returns date of currently selected recurrence + * + * @since 30.0.0 + * + * @return DateTime + */ + public function recurrenceDate(): DateTime | null { + if ($this->recurrenceCurrentDate !== null) { + return DateTime::createFromInterface($this->recurrenceCurrentDate); + } else { + return null; + } + } + + /** + * event recurrence rewind + * + * sets the current recurrence to the first recurrence in the collection + * + * @since 30.0.0 + * + * @return void + */ + public function recurrenceRewind(): void { + // rewind and increment rrule + if ($this->rruleIterator !== null) { + $this->rruleIterator->rewind(); + } + // rewind and increment rdate + if ($this->rdateIterator !== null) { + $this->rdateIterator->rewind(); + } + // rewind and increment exrule + if ($this->eruleIterator !== null) { + $this->eruleIterator->rewind(); + } + // rewind and increment exdate + if ($this->edateIterator !== null) { + $this->edateIterator->rewind(); + } + // set current date to event start date + $this->recurrenceCurrentDate = clone $this->baseEventStartDate; + } + + /** + * event recurrence advance + * + * sets the current recurrence to the next recurrence in the collection + * + * @since 30.0.0 + * + * @return void + */ + public function recurrenceAdvance(): void { + // place holders + $nextOccurrenceDate = null; + $nextExceptionDate = null; + $rruleDate = null; + $rdateDate = null; + $eruleDate = null; + $edateDate = null; + // evaludate if rrule is set and advance one interation past current date + if ($this->rruleIterator !== null) { + // forward rrule to the next future date + while ($this->rruleIterator->valid() && $this->rruleIterator->current() <= $this->recurrenceCurrentDate) { + $this->rruleIterator->next(); + } + $rruleDate = $this->rruleIterator->current(); + } + // evaludate if rdate is set and advance one interation past current date + if ($this->rdateIterator !== null) { + // forward rdate to the next future date + while ($this->rdateIterator->valid() && $this->rdateIterator->current() <= $this->recurrenceCurrentDate) { + $this->rdateIterator->next(); + } + $rdateDate = $this->rdateIterator->current(); + } + if ($rruleDate !== null && $rdateDate !== null) { + $nextOccurrenceDate = ($rruleDate <= $rdateDate) ? $rruleDate : $rdateDate; + } elseif ($rruleDate !== null) { + $nextOccurrenceDate = $rruleDate; + } elseif ($rdateDate !== null) { + $nextOccurrenceDate = $rdateDate; + } + + // evaludate if exrule is set and advance one interation past current date + if ($this->eruleIterator !== null) { + // forward exrule to the next future date + while ($this->eruleIterator->valid() && $this->eruleIterator->current() <= $this->recurrenceCurrentDate) { + $this->eruleIterator->next(); + } + $eruleDate = $this->eruleIterator->current(); + } + // evaludate if exdate is set and advance one interation past current date + if ($this->edateIterator !== null) { + // forward exdate to the next future date + while ($this->edateIterator->valid() && $this->edateIterator->current() <= $this->recurrenceCurrentDate) { + $this->edateIterator->next(); + } + $edateDate = $this->edateIterator->current(); + } + // evaludate if exrule and exdate are set and set nextExDate to the first next date + if ($eruleDate !== null && $edateDate !== null) { + $nextExceptionDate = ($eruleDate <= $edateDate) ? $eruleDate : $edateDate; + } elseif ($eruleDate !== null) { + $nextExceptionDate = $eruleDate; + } elseif ($edateDate !== null) { + $nextExceptionDate = $edateDate; + } + // if the next date is part of exrule or exdate find another date + if ($nextOccurrenceDate !== null && $nextExceptionDate !== null && $nextOccurrenceDate == $nextExceptionDate) { + $this->recurrenceCurrentDate = $nextOccurrenceDate; + $this->recurrenceAdvance(); + } else { + $this->recurrenceCurrentDate = $nextOccurrenceDate; + } + } + + /** + * event recurrence advance + * + * sets the current recurrence to the next recurrence in the collection after the specific date + * + * @since 30.0.0 + * + * @param DateTimeInterface $dt date and time to advance + * + * @return void + */ + public function recurrenceAdvanceTo(DateTimeInterface $dt): void { + while ($this->recurrenceCurrentDate !== null && $this->recurrenceCurrentDate < $dt) { + $this->recurrenceAdvance(); + } + } + +} diff --git a/apps/dav/lib/CalDAV/EventReaderRDate.php b/apps/dav/lib/CalDAV/EventReaderRDate.php new file mode 100644 index 00000000000..65362be4b07 --- /dev/null +++ b/apps/dav/lib/CalDAV/EventReaderRDate.php @@ -0,0 +1,35 @@ +concludesOn(); + } + + public function concludesAfter(): int | null { + return !empty($this->dates) ? count($this->dates) : null; + } + + public function concludesOn(): DateTime | null { + if (count($this->dates) > 0) { + return new DateTime( + $this->dates[array_key_last($this->dates)], + $this->startDate->getTimezone() + ); + } + + return null; + } + +} diff --git a/apps/dav/lib/CalDAV/EventReaderRRule.php b/apps/dav/lib/CalDAV/EventReaderRRule.php new file mode 100644 index 00000000000..965abb4c9cd --- /dev/null +++ b/apps/dav/lib/CalDAV/EventReaderRRule.php @@ -0,0 +1,87 @@ +frequency; + } + + public function interval(): int { + return $this->interval; + } + + public function concludes(): DateTime | null { + // evaluate if until value is a date + if ($this->until instanceof DateTimeInterface) { + return DateTime::createFromInterface($this->until); + } + // evaluate if count value is higher than 0 + if ($this->count > 0) { + // temporarily store current recurrence date and counter + $currentReccuranceDate = $this->currentDate; + $currentCounter = $this->counter; + // iterate over occurrences until last one (subtract 2 from count for start and end occurrence) + while ($this->counter <= ($this->count - 2)) { + $this->next(); + } + // temporarly store last reccurance date + $lastReccuranceDate = $this->currentDate; + // restore current recurrence date and counter + $this->currentDate = $currentReccuranceDate; + $this->counter = $currentCounter; + // return last recurrence date + return DateTime::createFromInterface($lastReccuranceDate); + } + + return null; + } + + public function concludesAfter(): int | null { + return !empty($this->count) ? $this->count : null; + } + + public function concludesOn(): DateTime | null { + return isset($this->until) ? DateTime::createFromInterface($this->until) : null; + } + + public function daysOfWeek(): array { + return $this->byDay; + } + + public function daysOfMonth(): array { + return $this->byMonthDay; + } + + public function daysOfYear(): array { + return $this->byYearDay; + } + + public function weeksOfYear(): array { + return $this->byWeekNo; + } + + public function monthsOfYear(): array { + return $this->byMonth; + } + + public function isRelative(): bool { + return isset($this->bySetPos); + } + + public function relativePosition(): array { + return $this->bySetPos; + } + +} diff --git a/apps/dav/lib/CalDAV/Schedule/IMipService.php b/apps/dav/lib/CalDAV/Schedule/IMipService.php index 5141f519588..14272cb5206 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipService.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipService.php @@ -9,6 +9,8 @@ declare(strict_types=1); namespace OCA\DAV\CalDAV\Schedule; use OC\URLGenerator; +use OCA\DAV\CalDAV\EventReader; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\IDBConnection; use OCP\IL10N; @@ -31,6 +33,7 @@ class IMipService { private ISecureRandom $random; private L10NFactory $l10nFactory; private IL10N $l10n; + private ITimeFactory $timeFactory; /** @var string[] */ private const STRING_DIFF = [ @@ -44,7 +47,8 @@ class IMipService { IConfig $config, IDBConnection $db, ISecureRandom $random, - L10NFactory $l10nFactory) { + L10NFactory $l10nFactory, + ITimeFactory $timeFactory) { $this->urlGenerator = $urlGenerator; $this->config = $config; $this->db = $db; @@ -52,6 +56,7 @@ class IMipService { $this->l10nFactory = $l10nFactory; $default = $this->l10nFactory->findGenericLanguage(); $this->l10n = $this->l10nFactory->get('dav', $default); + $this->timeFactory = $timeFactory; } /** @@ -130,9 +135,13 @@ class IMipService { * @return array */ public function buildBodyData(VEvent $vEvent, ?VEvent $oldVEvent): array { + + // construct event reader + $eventReaderCurrent = new EventReader($vEvent); + $eventReaderPrevious = !empty($oldVEvent) ? new EventReader($oldVEvent) : null; $defaultVal = ''; $data = []; - $data['meeting_when'] = $this->generateWhenString($vEvent); + $data['meeting_when'] = $this->generateWhenString($eventReaderCurrent); foreach(self::STRING_DIFF as $key => $property) { $data[$key] = self::readPropertyWithDefault($vEvent, $property, $defaultVal); @@ -145,7 +154,7 @@ class IMipService { } if(!empty($oldVEvent)) { - $oldMeetingWhen = $this->generateWhenString($oldVEvent); + $oldMeetingWhen = $this->generateWhenString($eventReaderPrevious); $data['meeting_title_html'] = $this->generateDiffString($vEvent, $oldVEvent, 'SUMMARY', $data['meeting_title']); $data['meeting_description_html'] = $this->generateDiffString($vEvent, $oldVEvent, 'DESCRIPTION', $data['meeting_description']); $data['meeting_location_html'] = $this->generateLinkifiedDiffString($vEvent, $oldVEvent, 'LOCATION', $data['meeting_location']); @@ -153,107 +162,415 @@ class IMipService { $oldUrl = self::readPropertyWithDefault($oldVEvent, 'URL', $defaultVal); $data['meeting_url_html'] = !empty($oldUrl) && $oldUrl !== $data['meeting_url'] ? sprintf('%1$s', $oldUrl) : $data['meeting_url']; - $data['meeting_when_html'] = - ($oldMeetingWhen !== $data['meeting_when'] && $oldMeetingWhen !== null) - ? sprintf("%s
%s", $oldMeetingWhen, $data['meeting_when']) - : $data['meeting_when']; + $data['meeting_when_html'] = $oldMeetingWhen !== $data['meeting_when'] ? sprintf("%s
%s", $oldMeetingWhen, $data['meeting_when']) : $data['meeting_when']; } + // generate occuring next string + if ($eventReaderCurrent->recurs()) { + $data['meeting_occurring'] = $this->generateOccurringString($eventReaderCurrent); + } + return $data; } /** - * @param IL10N $this->l10n - * @param VEvent $vevent - * @return false|int|string + * genarates a when string based on if a event has an recurrence or not + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string */ - public function generateWhenString(VEvent $vevent) { - /** @var Property\ICalendar\DateTime $dtstart */ - $dtstart = $vevent->DTSTART; - if (isset($vevent->DTEND)) { - /** @var Property\ICalendar\DateTime $dtend */ - $dtend = $vevent->DTEND; - } elseif (isset($vevent->DURATION)) { - $isFloating = $dtstart->isFloating(); - $dtend = clone $dtstart; - $endDateTime = $dtend->getDateTime(); - $endDateTime = $endDateTime->add(DateTimeParser::parse($vevent->DURATION->getValue())); - $dtend->setDateTime($endDateTime, $isFloating); - } elseif (!$dtstart->hasTime()) { - $isFloating = $dtstart->isFloating(); - $dtend = clone $dtstart; - $endDateTime = $dtend->getDateTime(); - $endDateTime = $endDateTime->modify('+1 day'); - $dtend->setDateTime($endDateTime, $isFloating); + public function generateWhenString(EventReader $er): string { + return match ($er->recurs()) { + true => $this->generateWhenStringRecurring($er), + false => $this->generateWhenStringSingular($er) + }; + } + + /** + * genarates a when string for a non recurring event + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string + */ + public function generateWhenStringSingular(EventReader $er): string { + // calculate time differnce from now to start of event + $occuring = $this->minimizeInterval($this->timeFactory->getDateTime()->diff($er->recurrenceDate())); + // extract start date + $startDate = $this->l10n->l('date', $er->startDateTime(), ['width' => 'full']); + // time of the day + if (!$er->entireDay()) { + $startTime = $this->l10n->l('time', $er->startDateTime(), ['width' => 'short']); + $startTime .= $er->startTimeZone() != $er->endTimeZone() ? ' (' . $er->startTimeZone()->getName() . ')' : ''; + $endTime = $this->l10n->l('time', $er->endDateTime(), ['width' => 'short']) . ' (' . $er->endTimeZone()->getName() . ')'; + } + // generate localized when string + // TRANSLATORS + // Indicates when a calendar event will happen, shown on invitation emails + // Output produced in order: + // In a day/week/month/year on July 1, 2024 for the entire day + // In a day/week/month/year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) + // In 2 days/weeks/monthss/years on July 1, 2024 for the entire day + // In 2 days/weeks/monthss/years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto) + return match ([($occuring[0] > 1), !empty($endTime)]) { + [false, false] => $this->l10n->t('In a %1$s on %2$s for the entire day', [$occuring[1], $startDate]), + [false, true] => $this->l10n->t('In a %1$s on %2$s between %3$s - %4$s', [$occuring[1], $startDate, $startTime, $endTime]), + [true, false] => $this->l10n->t('In %1$s %2$s on %3$s for the entire day', [$occuring[0], $occuring[1], $startDate]), + [true, true] => $this->l10n->t('In %1$s %2$s on %3$s between %4$s - %5$s', [$occuring[0], $occuring[1], $startDate, $startTime, $endTime]), + default => $this->l10n->t('Could not generate when statement') + }; + } + + /** + * genarates a when string based on recurrance precision/frequency + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string + */ + public function generateWhenStringRecurring(EventReader $er): string { + return match ($er->recurringPrecision()) { + 'daily' => $this->generateWhenStringRecurringDaily($er), + 'weekly' => $this->generateWhenStringRecurringWeekly($er), + 'monthly' => $this->generateWhenStringRecurringMonthly($er), + 'yearly' => $this->generateWhenStringRecurringYearly($er), + 'fixed' => $this->generateWhenStringRecurringFixed($er), + }; + } + + /** + * genarates a when string for a daily precision/frequency + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string + */ + public function generateWhenStringRecurringDaily(EventReader $er): string { + + // initialize + $interval = (int) $er->recurringInterval(); + $startTime = ''; + $endTime = ''; + $conclusion = ''; + // time of the day + if (!$er->entireDay()) { + $startTime = $this->l10n->l('time', $er->startDateTime(), ['width' => 'short']); + $startTime .= $er->startTimeZone() != $er->endTimeZone() ? ' (' . $er->startTimeZone()->getName() . ')' : ''; + $endTime = $this->l10n->l('time', $er->endDateTime(), ['width' => 'short']) . ' (' . $er->endTimeZone()->getName() . ')'; + } + // conclusion + if ($er->recurringConcludes()) { + $conclusion = $this->l10n->l('date', $er->recurringConcludesOn(), ['width' => 'long']); + } + // generate localized when string + // TRANSLATORS + // Indicates when a calendar event will happen, shown on invitation emails + // Output produced in order: + // Every Day for the entire day + // Every Day for the entire day until July 13, 2024 + // Every Day between 8:00 AM - 9:00 AM (America/Toronto) + // Every Day between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024 + // Every 3 Days for the entire day + // Every 3 Days for the entire day until July 13, 2024 + // Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto) + // Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024 + return match ([($interval > 1), !empty($startTime), !empty($conclusion)]) { + [false, false, false] => $this->l10n->t('Every Day for the entire day'), + [false, false, true] => $this->l10n->t('Every Day for the entire day until %1$s', [$conclusion]), + [false, true, false] => $this->l10n->t('Every Day between %1$s - %2$s', [$startTime, $endTime]), + [false, true, true] => $this->l10n->t('Every Day between %1$s - %2$s until %3$s', [$startTime, $endTime, $conclusion]), + [true, false, false] => $this->l10n->t('Every %1$d Days for the entire day', [$interval]), + [true, false, true] => $this->l10n->t('Every %1$d Days for the entire day until %2$s', [$interval, $conclusion]), + [true, true, false] => $this->l10n->t('Every %1$d Days between %2$s - %3$s', [$interval, $startTime, $endTime]), + [true, true, true] => $this->l10n->t('Every %1$d Days between %2$s - %3$s until %4$s', [$interval, $startTime, $endTime, $conclusion]), + default => $this->l10n->t('Could not generate event recurrence statement') + }; + + } + + /** + * genarates a when string for a weekly precision/frequency + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string + */ + public function generateWhenStringRecurringWeekly(EventReader $er): string { + + // initialize + $interval = (int) $er->recurringInterval(); + $startTime = ''; + $endTime = ''; + $conclusion = ''; + // days of the week + $days = implode(', ', array_map(function ($value) { return $this->localizeDayName($value); }, $er->recurringDaysOfWeekNamed())); + // time of the day + if (!$er->entireDay()) { + $startTime = $this->l10n->l('time', $er->startDateTime(), ['width' => 'short']); + $startTime .= $er->startTimeZone() != $er->endTimeZone() ? ' (' . $er->startTimeZone()->getName() . ')' : ''; + $endTime = $this->l10n->l('time', $er->endDateTime(), ['width' => 'short']) . ' (' . $er->endTimeZone()->getName() . ')'; + } + // conclusion + if ($er->recurringConcludes()) { + $conclusion = $this->l10n->l('date', $er->recurringConcludesOn(), ['width' => 'long']); + } + // generate localized when string + // TRANSLATORS + // Indicates when a calendar event will happen, shown on invitation emails + // Output produced in order: + // Every Week on Monday, Wednesday, Friday for the entire day + // Every Week on Monday, Wednesday, Friday for the entire day until July 13, 2024 + // Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) + // Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024 + // Every 2 Weeks on Monday, Wednesday, Friday for the entire day + // Every 2 Weeks on Monday, Wednesday, Friday for the entire day until July 13, 2024 + // Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) + // Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024 + return match ([($interval > 1), !empty($startTime), !empty($conclusion)]) { + [false, false, false] => $this->l10n->t('Every Week on %1$s for the entire day', [$days]), + [false, false, true] => $this->l10n->t('Every Week on %1$s for the entire day until %2$s', [$days, $conclusion]), + [false, true, false] => $this->l10n->t('Every Week on %1$s between %2$s - %3$s', [$days, $startTime, $endTime]), + [false, true, true] => $this->l10n->t('Every Week on %1$s between %2$s - %3$s until %4$s', [$days, $startTime, $endTime, $conclusion]), + [true, false, false] => $this->l10n->t('Every %1$d Weeks on %2$s for the entire day', [$interval, $days]), + [true, false, true] => $this->l10n->t('Every %1$d Weeks on %2$s for the entire day until %3$s', [$interval, $days, $conclusion]), + [true, true, false] => $this->l10n->t('Every %1$d Weeks on %2$s between %3$s - %4$s', [$interval, $days, $startTime, $endTime]), + [true, true, true] => $this->l10n->t('Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s', [$interval, $days, $startTime, $endTime, $conclusion]), + default => $this->l10n->t('Could not generate event recurrence statement') + }; + + } + + /** + * genarates a when string for a monthly precision/frequency + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string + */ + public function generateWhenStringRecurringMonthly(EventReader $er): string { + + // initialize + $interval = (int) $er->recurringInterval(); + $startTime = ''; + $endTime = ''; + $conclusion = ''; + // days of month + if ($er->recurringPattern() === 'R') { + $days = implode(', ', array_map(function ($value) { return $this->localizeRelativePositionName($value); }, $er->recurringRelativePositionNamed())) . ' ' . + implode(', ', array_map(function ($value) { return $this->localizeDayName($value); }, $er->recurringDaysOfWeekNamed())); } else { - $dtend = clone $dtstart; + $days = implode(', ', $er->recurringDaysOfMonth()); } - - /** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtstart */ - /** @var \DateTimeImmutable $dtstartDt */ - $dtstartDt = $dtstart->getDateTime(); - - /** @var Property\ICalendar\Date | Property\ICalendar\DateTime $dtend */ - /** @var \DateTimeImmutable $dtendDt */ - $dtendDt = $dtend->getDateTime(); - - $diff = $dtstartDt->diff($dtendDt); - - $dtstartDt = new \DateTime($dtstartDt->format(\DateTimeInterface::ATOM)); - $dtendDt = new \DateTime($dtendDt->format(\DateTimeInterface::ATOM)); - - if ($dtstart instanceof Property\ICalendar\Date) { - // One day event - if ($diff->days === 1) { - return $this->l10n->l('date', $dtstartDt, ['width' => 'medium']); - } - - // DTEND is exclusive, so if the ics data says 2020-01-01 to 2020-01-05, - // the email should show 2020-01-01 to 2020-01-04. - $dtendDt->modify('-1 day'); - - //event that spans over multiple days - $localeStart = $this->l10n->l('date', $dtstartDt, ['width' => 'medium']); - $localeEnd = $this->l10n->l('date', $dtendDt, ['width' => 'medium']); - - return $localeStart . ' - ' . $localeEnd; + // time of the day + if (!$er->entireDay()) { + $startTime = $this->l10n->l('time', $er->startDateTime(), ['width' => 'short']); + $startTime .= $er->startTimeZone() != $er->endTimeZone() ? ' (' . $er->startTimeZone()->getName() . ')' : ''; + $endTime = $this->l10n->l('time', $er->endDateTime(), ['width' => 'short']) . ' (' . $er->endTimeZone()->getName() . ')'; } - - /** @var Property\ICalendar\DateTime $dtstart */ - /** @var Property\ICalendar\DateTime $dtend */ - $isFloating = $dtstart->isFloating(); - $startTimezone = $endTimezone = null; - if (!$isFloating) { - $prop = $dtstart->offsetGet('TZID'); - if ($prop instanceof Parameter) { - $startTimezone = $prop->getValue(); - } - - $prop = $dtend->offsetGet('TZID'); - if ($prop instanceof Parameter) { - $endTimezone = $prop->getValue(); - } + // conclusion + if ($er->recurringConcludes()) { + $conclusion = $this->l10n->l('date', $er->recurringConcludesOn(), ['width' => 'long']); } + // generate localized when string + // TRANSLATORS + // Indicates when a calendar event will happen, shown on invitation emails + // Output produced in order, output varies depending on if the event is absolute or releative: + // Absolute: Every Month on the 1, 8 for the entire day + // Relative: Every Month on the First Sunday, Saturday for the entire day + // Absolute: Every Month on the 1, 8 for the entire day until December 31, 2024 + // Relative: Every Month on the First Sunday, Saturday for the entire day until December 31, 2024 + // Absolute: Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) + // Relative: Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) + // Absolute: Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024 + // Relative: Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024 + // Absolute: Every 2 Months on the 1, 8 for the entire day + // Relative: Every 2 Months on the First Sunday, Saturday for the entire day + // Absolute: Every 2 Months on the 1, 8 for the entire day until December 31, 2024 + // Relative: Every 2 Months on the First Sunday, Saturday for the entire day until December 31, 2024 + // Absolute: Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) + // Relative: Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) + // Absolute: Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024 + // Relative: Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024 + return match ([($interval > 1), !empty($startTime), !empty($conclusion)]) { + [false, false, false] => $this->l10n->t('Every Month on the %1$s for the entire day', [$days]), + [false, false, true] => $this->l10n->t('Every Month on the %1$s for the entire day until %2$s', [$days, $conclusion]), + [false, true, false] => $this->l10n->t('Every Month on the %1$s between %2$s - %3$s', [$days, $startTime, $endTime]), + [false, true, true] => $this->l10n->t('Every Month on the %1$s between %2$s - %3$s until %4$s', [$days, $startTime, $endTime, $conclusion]), + [true, false, false] => $this->l10n->t('Every %1$d Months on the %2$s for the entire day', [$interval, $days]), + [true, false, true] => $this->l10n->t('Every %1$d Months on the %2$s for the entire day until %3$s', [$interval, $days, $conclusion]), + [true, true, false] => $this->l10n->t('Every %1$d Months on the %2$s between %3$s - %4$s', [$interval, $days, $startTime, $endTime]), + [true, true, true] => $this->l10n->t('Every %1$d Months on the %2$s between %3$s - %4$s until %5$s', [$interval, $days, $startTime, $endTime, $conclusion]), + default => $this->l10n->t('Could not generate event recurrence statement') + }; + } - $localeStart = $this->l10n->l('weekdayName', $dtstartDt, ['width' => 'abbreviated']) . ', ' . - $this->l10n->l('datetime', $dtstartDt, ['width' => 'medium|short']); - - // always show full date with timezone if timezones are different - if ($startTimezone !== $endTimezone) { - $localeEnd = $this->l10n->l('datetime', $dtendDt, ['width' => 'medium|short']); - - return $localeStart . ' (' . $startTimezone . ') - ' . - $localeEnd . ' (' . $endTimezone . ')'; - } - - // show only end time if date is the same - if ($dtstartDt->format('Y-m-d') === $dtendDt->format('Y-m-d')) { - $localeEnd = $this->l10n->l('time', $dtendDt, ['width' => 'short']); + /** + * genarates a when string for a yearly precision/frequency + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string + */ + public function generateWhenStringRecurringYearly(EventReader $er): string { + + // initialize + $interval = (int) $er->recurringInterval(); + $startTime = ''; + $endTime = ''; + $conclusion = ''; + // months of year + $months = implode(', ', array_map(function ($value) { return $this->localizeMonthName($value); }, $er->recurringMonthsOfYearNamed())); + // days of month + if ($er->recurringPattern() === 'R') { + $days = implode(', ', array_map(function ($value) { return $this->localizeRelativePositionName($value); }, $er->recurringRelativePositionNamed())) . ' ' . + implode(', ', array_map(function ($value) { return $this->localizeDayName($value); }, $er->recurringDaysOfWeekNamed())); } else { - $localeEnd = $this->l10n->l('weekdayName', $dtendDt, ['width' => 'abbreviated']) . ', ' . - $this->l10n->l('datetime', $dtendDt, ['width' => 'medium|short']); + $days = $er->startDateTime()->format('jS'); } + // time of the day + if (!$er->entireDay()) { + $startTime = $this->l10n->l('time', $er->startDateTime(), ['width' => 'short']); + $startTime .= $er->startTimeZone() != $er->endTimeZone() ? ' (' . $er->startTimeZone()->getName() . ')' : ''; + $endTime = $this->l10n->l('time', $er->endDateTime(), ['width' => 'short']) . ' (' . $er->endTimeZone()->getName() . ')'; + } + // conclusion + if ($er->recurringConcludes()) { + $conclusion = $this->l10n->l('date', $er->recurringConcludesOn(), ['width' => 'long']); + } + // generate localized when string + // TRANSLATORS + // Indicates when a calendar event will happen, shown on invitation emails + // Output produced in order, output varies depending on if the event is absolute or releative: + // Absolute: Every Year in July on the 1st for the entire day + // Relative: Every Year in July on the First Sunday, Saturday for the entire day + // Absolute: Every Year in July on the 1st for the entire day until July 31, 2026 + // Relative: Every Year in July on the First Sunday, Saturday for the entire day until July 31, 2026 + // Absolute: Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) + // Relative: Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) + // Absolute: Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026 + // Relative: Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026 + // Absolute: Every 2 Years in July on the 1st for the entire day + // Relative: Every 2 Years in July on the First Sunday, Saturday for the entire day + // Absolute: Every 2 Years in July on the 1st for the entire day until July 31, 2026 + // Relative: Every 2 Years in July on the First Sunday, Saturday for the entire day until July 31, 2026 + // Absolute: Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) + // Relative: Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) + // Absolute: Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026 + // Relative: Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026 + return match ([($interval > 1), !empty($startTime), !empty($conclusion)]) { + [false, false, false] => $this->l10n->t('Every Year in %1$s on the %2$s for the entire day', [$months, $days]), + [false, false, true] => $this->l10n->t('Every Year in %1$s on the %2$s for the entire day until %3$s', [$months, $days, $conclusion]), + [false, true, false] => $this->l10n->t('Every Year in %1$s on the %2$s between %3$s - %4$s', [$months, $days, $startTime, $endTime]), + [false, true, true] => $this->l10n->t('Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s', [$months, $days, $startTime, $endTime, $conclusion]), + [true, false, false] => $this->l10n->t('Every %1$d Years in %2$s on the %3$s for the entire day', [$interval, $months, $days]), + [true, false, true] => $this->l10n->t('Every %1$d Years in %2$s on the %3$s for the entire day until %4$s', [$interval, $months, $days, $conclusion]), + [true, true, false] => $this->l10n->t('Every %1$d Years in %2$s on the %3$s between %4$s - %5$s', [$interval, $months, $days, $startTime, $endTime]), + [true, true, true] => $this->l10n->t('Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s', [$interval, $months, $days, $startTime, $endTime, $conclusion]), + default => $this->l10n->t('Could not generate event recurrence statement') + }; + } + + /** + * genarates a when string for a fixed precision/frequency + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string + */ + public function generateWhenStringRecurringFixed(EventReader $er): string { + // initialize + $startTime = ''; + $endTime = ''; + $conclusion = ''; + // time of the day + if (!$er->entireDay()) { + $startTime = $this->l10n->l('time', $er->startDateTime(), ['width' => 'short']); + $startTime .= $er->startTimeZone() != $er->endTimeZone() ? ' (' . $er->startTimeZone()->getName() . ')' : ''; + $endTime = $this->l10n->l('time', $er->endDateTime(), ['width' => 'short']) . ' (' . $er->endTimeZone()->getName() . ')'; + } + // conclusion + $conclusion = $this->l10n->l('date', $er->recurringConcludesOn(), ['width' => 'long']); + // generate localized when string + // TRANSLATORS + // Indicates when a calendar event will happen, shown on invitation emails + // Output produced in order: + // On specific dates for the entire day until July 13, 2024 + // On specific dates between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024 + return match (!empty($startTime)) { + false => $this->l10n->t('On specific dates for the entire day until %1$s', [$conclusion]), + true => $this->l10n->t('On specific dates between %1$s - %2$s until %3$s', [$startTime, $endTime, $conclusion]), + }; + } + + /** + * genarates a occurring next string for a recurring event + * + * @since 30.0.0 + * + * @param EventReader $er + * + * @return string + */ + public function generateOccurringString(EventReader $er): string { + + // reset to initial occurance + $er->recurrenceRewind(); + // forward to current date + $er->recurrenceAdvanceTo($this->timeFactory->getDateTime()); + // calculate time differnce from now to start of next event occurance and minimize it + $occuranceIn = $this->minimizeInterval($this->timeFactory->getDateTime()->diff($er->recurrenceDate())); + // store next occurance value + $occurance = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']); + // forward one occurance + $er->recurrenceAdvance(); + // evaluate if occurance is valid + if ($er->recurrenceDate() !== null) { + // store following occurance value + $occurance2 = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']); + // forward one occurance + $er->recurrenceAdvance(); + // evaluate if occurance is valid + if ($er->recurrenceDate()) { + // store following occurance value + $occurance3 = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']); + } + } + // generate localized when string + // TRANSLATORS + // Indicates when a calendar event will happen, shown on invitation emails + // Output produced in order: + // In a day/week/month/year on July 1, 2024 + // In a day/week/month/year on July 1, 2024 then on July 3, 2024 + // In a day/week/month/year on July 1, 2024 then on July 3, 2024 and July 5, 2024 + // In 2 days/weeks/months/years on July 1, 2024 + // In 2 days/weeks/months/years on July 1, 2024 then on July 3, 2024 + // In 2 days/weeks/months/years on July 1, 2024 then on July 3, 2024 and July 5, 2024 + return match ([($occuranceIn[0] > 1), !empty($occurance2), !empty($occurance3)]) { + [false, false, false] => $this->l10n->t('In a %1$s on %2$s', [$occuranceIn[1], $occurance]), + [false, true, false] => $this->l10n->t('In a %1$s on %2$s then on %3$s', [$occuranceIn[1], $occurance, $occurance2]), + [false, true, true] => $this->l10n->t('In a %1$s on %2$s then on %3$s and %4$s', [$occuranceIn[1], $occurance, $occurance2, $occurance3]), + [true, false, false] => $this->l10n->t('In %1$s %2$s on %3$s', [$occuranceIn[0], $occuranceIn[1], $occurance]), + [true, true, false] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s', [$occuranceIn[0], $occuranceIn[1], $occurance, $occurance2]), + [true, true, true] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s and %5$s', [$occuranceIn[0], $occuranceIn[1], $occurance, $occurance2, $occurance3]), + default => $this->l10n->t('Could not generate next recurrence statement') + }; - return $localeStart . ' - ' . $localeEnd . ' (' . $startTimezone . ')'; } /** @@ -261,12 +578,13 @@ class IMipService { * @return array */ public function buildCancelledBodyData(VEvent $vEvent): array { + // construct event reader + $eventReaderCurrent = new EventReader($vEvent); $defaultVal = ''; $strikethrough = "%s"; - $newMeetingWhen = $this->generateWhenString($vEvent); + $newMeetingWhen = $this->generateWhenString($eventReaderCurrent); $newSummary = isset($vEvent->SUMMARY) && (string)$vEvent->SUMMARY !== '' ? (string)$vEvent->SUMMARY : $this->l10n->t('Untitled event'); - ; $newDescription = isset($vEvent->DESCRIPTION) && (string)$vEvent->DESCRIPTION !== '' ? (string)$vEvent->DESCRIPTION : $defaultVal; $newUrl = isset($vEvent->URL) && (string)$vEvent->URL !== '' ? sprintf('%1$s', $vEvent->URL) : $defaultVal; $newLocation = isset($vEvent->LOCATION) && (string)$vEvent->LOCATION !== '' ? (string)$vEvent->LOCATION : $defaultVal; @@ -522,7 +840,7 @@ class IMipService { $data['meeting_title_html'] ?? $data['meeting_title'], $this->l10n->t('Title:'), $this->getAbsoluteImagePath('caldav/title.png'), $data['meeting_title'], '', IMipPlugin::IMIP_INDENT); if ($data['meeting_when'] !== '') { - $template->addBodyListItem($data['meeting_when_html'] ?? $data['meeting_when'], $this->l10n->t('Date and time:'), + $template->addBodyListItem($data['meeting_when_html'] ?? $data['meeting_when'], $this->l10n->t('When:'), $this->getAbsoluteImagePath('caldav/time.png'), $data['meeting_when'], '', IMipPlugin::IMIP_INDENT); } if ($data['meeting_location'] !== '') { @@ -533,6 +851,10 @@ class IMipService { $template->addBodyListItem($data['meeting_url_html'] ?? $data['meeting_url'], $this->l10n->t('Link:'), $this->getAbsoluteImagePath('caldav/link.png'), $data['meeting_url'], '', IMipPlugin::IMIP_INDENT); } + if (isset($data['meeting_occurring'])) { + $template->addBodyListItem($data['meeting_occurring_html'] ?? $data['meeting_occurring'], $this->l10n->t('Occurring:'), + $this->getAbsoluteImagePath('caldav/time.png'), $data['meeting_occurring'], '', IMipPlugin::IMIP_INDENT); + } $this->addAttendees($template, $vevent); @@ -643,10 +965,104 @@ class IMipService { return false; } $type = $cuType->getValue() ?? 'INDIVIDUAL'; - if (\in_array(strtoupper($type), ['RESOURCE', 'ROOM'], true)) { + if (\in_array(strtoupper($type), ['RESOURCE', 'ROOM', 'UNKNOWN'], true)) { // Don't send emails to things return true; } return false; } + + public function minimizeInterval(\DateInterval $dateInterval): array { + // evaluate if time interval is in the past + if ($dateInterval->invert == 1) { + return [1, 'the past']; + } + // evaluate interval parts and return smallest time period + if ($dateInterval->y > 0) { + $interval = $dateInterval->y; + $scale = ($dateInterval->y > 1) ? 'years' : 'year'; + } elseif ($dateInterval->m > 0) { + $interval = $dateInterval->m; + $scale = ($dateInterval->m > 1) ? 'months' : 'month'; + } elseif ($dateInterval->d >= 7) { + $interval = (int)($dateInterval->d / 7); + $scale = ((int)($dateInterval->d / 7) > 1) ? 'weeks' : 'week'; + } elseif ($dateInterval->d > 0) { + $interval = $dateInterval->d; + $scale = ($dateInterval->d > 1) ? 'days' : 'day'; + } elseif ($dateInterval->h > 0) { + $interval = $dateInterval->h; + $scale = ($dateInterval->h > 1) ? 'hours' : 'hour'; + } else { + $interval = $dateInterval->i; + $scale = 'minutes'; + } + + return [$interval, $scale]; + } + + /** + * Localizes week day names to another language + * + * @param string $value + * + * @return string + */ + public function localizeDayName(string $value): string { + return match ($value) { + 'Monday' => $this->l10n->t('Monday'), + 'Tuesday' => $this->l10n->t('Tuesday'), + 'Wednesday' => $this->l10n->t('Wednesday'), + 'Thursday' => $this->l10n->t('Thursday'), + 'Friday' => $this->l10n->t('Friday'), + 'Saturday' => $this->l10n->t('Saturday'), + 'Sunday' => $this->l10n->t('Sunday'), + }; + } + + /** + * Localizes month names to another language + * + * @param string $value + * + * @return string + */ + public function localizeMonthName(string $value): string { + return match ($value) { + 'January' => $this->l10n->t('January'), + 'February' => $this->l10n->t('February'), + 'March' => $this->l10n->t('March'), + 'April' => $this->l10n->t('April'), + 'May' => $this->l10n->t('May'), + 'June' => $this->l10n->t('June'), + 'July' => $this->l10n->t('July'), + 'August' => $this->l10n->t('August'), + 'September' => $this->l10n->t('September'), + 'October' => $this->l10n->t('October'), + 'November' => $this->l10n->t('November'), + 'December' => $this->l10n->t('December'), + }; + } + + /** + * Localizes relative position names to another language + * + * @param string $value + * + * @return string + */ + public function localizeRelativePositionName(string $value): string { + return match ($value) { + 'First' => $this->l10n->t('First'), + 'Second' => $this->l10n->t('Second'), + 'Third' => $this->l10n->t('Third'), + 'Fourth' => $this->l10n->t('Fourth'), + 'Fifty' => $this->l10n->t('Fifty'), + 'Last' => $this->l10n->t('Last'), + 'Second Last' => $this->l10n->t('Second Last'), + 'Third Last' => $this->l10n->t('Third Last'), + 'Fourth Last' => $this->l10n->t('Fourth Last'), + 'Fifty Last' => $this->l10n->t('Fifty Last'), + }; + } } diff --git a/apps/dav/lib/CalDAV/Schedule/Plugin.php b/apps/dav/lib/CalDAV/Schedule/Plugin.php index 9e1006e72c0..897901a61a4 100644 --- a/apps/dav/lib/CalDAV/Schedule/Plugin.php +++ b/apps/dav/lib/CalDAV/Schedule/Plugin.php @@ -130,6 +130,11 @@ class Plugin extends \Sabre\CalDAV\Schedule\Plugin { if ($result === null) { $result = []; } + + // iterate through items and html decode values + foreach ($result as $key => $value) { + $result[$key] = urldecode($value); + } return $result; } diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php index cdbbc228047..9d787c917d3 100644 --- a/apps/dav/lib/CardDAV/CardDavBackend.php +++ b/apps/dav/lib/CardDAV/CardDavBackend.php @@ -1148,20 +1148,20 @@ class CardDavBackend implements BackendInterface, SyncSupport { /** * FIXME Find a way to match only 4 last digits * BDAY can be --1018 without year or 20001019 with it - * $bDayOr = $query2->expr()->orX(); + * $bDayOr = []; * if ($options['since'] instanceof DateTimeFilter) { - * $bDayOr->add( + * $bDayOr[] = * $query2->expr()->gte('SUBSTR(cp_bday.value, -4)', - * $query2->createNamedParameter($options['since']->get()->format('md'))) + * $query2->createNamedParameter($options['since']->get()->format('md')) * ); * } * if ($options['until'] instanceof DateTimeFilter) { - * $bDayOr->add( + * $bDayOr[] = * $query2->expr()->lte('SUBSTR(cp_bday.value, -4)', - * $query2->createNamedParameter($options['until']->get()->format('md'))) + * $query2->createNamedParameter($options['until']->get()->format('md')) * ); * } - * $query2->andWhere($bDayOr); + * $query2->andWhere($query2->expr()->orX(...$bDayOr)); */ } diff --git a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php index c499f806eba..336930cf17d 100644 --- a/apps/dav/lib/Connector/Sabre/DavAclPlugin.php +++ b/apps/dav/lib/Connector/Sabre/DavAclPlugin.php @@ -11,6 +11,7 @@ use OCA\DAV\CalDAV\CachedSubscription; use OCA\DAV\CalDAV\Calendar; use OCA\DAV\CardDAV\AddressBook; use Sabre\CalDAV\Principal\User; +use Sabre\DAV\Exception\Forbidden; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\INode; use Sabre\DAV\PropFind; @@ -49,13 +50,19 @@ class DavAclPlugin extends \Sabre\DAVACL\Plugin { $type = 'Node'; break; } - throw new NotFound( - sprintf( - "%s with name '%s' could not be found", - $type, - $node->getName() - ) - ); + + if ($this->getCurrentUserPrincipal() === $node->getOwner()) { + throw new Forbidden("Access denied"); + } else { + throw new NotFound( + sprintf( + "%s with name '%s' could not be found", + $type, + $node->getName() + ) + ); + } + } return $access; diff --git a/apps/dav/lib/DAV/CustomPropertiesBackend.php b/apps/dav/lib/DAV/CustomPropertiesBackend.php index ab62ae36c2c..f4dd9b2d038 100644 --- a/apps/dav/lib/DAV/CustomPropertiesBackend.php +++ b/apps/dav/lib/DAV/CustomPropertiesBackend.php @@ -411,7 +411,7 @@ class CustomPropertiesBackend implements BackendInterface { // request only a subset $sql .= ' AND `propertyname` in (?)'; $whereValues[] = $requestedProperties; - $whereTypes[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY; + $whereTypes[] = IQueryBuilder::PARAM_STR_ARRAY; } $result = $this->connection->executeQuery( diff --git a/apps/dav/lib/Files/Sharing/FilesDropPlugin.php b/apps/dav/lib/Files/Sharing/FilesDropPlugin.php index 2f4bacf69d4..69328d42272 100644 --- a/apps/dav/lib/Files/Sharing/FilesDropPlugin.php +++ b/apps/dav/lib/Files/Sharing/FilesDropPlugin.php @@ -6,6 +6,7 @@ namespace OCA\DAV\Files\Sharing; use OC\Files\View; +use OCP\Share\IShare; use Sabre\DAV\Exception\MethodNotAllowed; use Sabre\DAV\ServerPlugin; use Sabre\HTTP\RequestInterface; @@ -16,20 +17,19 @@ use Sabre\HTTP\ResponseInterface; */ class FilesDropPlugin extends ServerPlugin { - /** @var View */ - private $view; + private ?View $view = null; + private ?IShare $share = null; + private bool $enabled = false; - /** @var bool */ - private $enabled = false; - - /** - * @param View $view - */ - public function setView($view) { + public function setView(View $view): void { $this->view = $view; } - public function enable() { + public function setShare(IShare $share): void { + $this->share = $share; + } + + public function enable(): void { $this->enabled = true; } @@ -42,25 +42,51 @@ class FilesDropPlugin extends ServerPlugin { * @return void * @throws MethodNotAllowed */ - public function initialize(\Sabre\DAV\Server $server) { + public function initialize(\Sabre\DAV\Server $server): void { $server->on('beforeMethod:*', [$this, 'beforeMethod'], 999); $this->enabled = false; } - public function beforeMethod(RequestInterface $request, ResponseInterface $response) { - if (!$this->enabled) { + public function beforeMethod(RequestInterface $request, ResponseInterface $response): void { + if (!$this->enabled || $this->share === null || $this->view === null) { return; } + // Only allow file drop if ($request->getMethod() !== 'PUT') { throw new MethodNotAllowed('Only PUT is allowed on files drop'); } + // Always upload at the root level $path = explode('/', $request->getPath()); $path = array_pop($path); + // Extract the attributes for the file request + $isFileRequest = false; + $attributes = $this->share->getAttributes(); + $nickName = $request->getHeader('X-NC-Nickname'); + if ($attributes !== null) { + $isFileRequest = $attributes->getAttribute('fileRequest', 'enabled') === true; + } + + // We need a valid nickname for file requests + if ($isFileRequest && ($nickName == null || trim($nickName) === '')) { + throw new MethodNotAllowed('Nickname is required for file requests'); + } + + // If this is a file request we need to create a folder for the user + if ($isFileRequest) { + // Check if the folder already exists + if (!($this->view->file_exists($nickName) === true)) { + $this->view->mkdir($nickName); + } + // Put all files in the subfolder + $path = $nickName . '/' . $path; + } + $newName = \OC_Helper::buildNotExistingFileNameForView('/', $path, $this->view); $url = $request->getBaseUrl() . $newName; $request->setUrl($url); } + } diff --git a/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php b/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php index cbce847a298..c7f57dcb117 100644 --- a/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php +++ b/apps/dav/lib/Migration/CalDAVRemoveEmptyValue.php @@ -5,7 +5,6 @@ */ namespace OCA\DAV\Migration; -use Doctrine\DBAL\Platforms\OraclePlatform; use OCA\DAV\CalDAV\CalDavBackend; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; @@ -75,7 +74,7 @@ class CalDAVRemoveEmptyValue implements IRepairStep { } protected function getInvalidObjects($pattern) { - if ($this->db->getDatabasePlatform() instanceof OraclePlatform) { + if ($this->db->getDatabaseProvider() === IDBConnection::PLATFORM_ORACLE) { $rows = []; $chunkSize = 500; $query = $this->db->getQueryBuilder(); diff --git a/apps/dav/tests/unit/CalDAV/EventReaderTest.php b/apps/dav/tests/unit/CalDAV/EventReaderTest.php new file mode 100644 index 00000000000..23f0172131d --- /dev/null +++ b/apps/dav/tests/unit/CalDAV/EventReaderTest.php @@ -0,0 +1,1025 @@ +vCalendar1a = new VCalendar(); + $vEvent = $this->vCalendar1a->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']); + $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']); + $vEvent->add('SUMMARY', 'Test Recurrance Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + // construct calendar with a 1 hour event and different start/end time zones + $this->vCalendar1b = new VCalendar(); + $vEvent = $this->vCalendar1b->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']); + $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Vancouver']); + $vEvent->add('SUMMARY', 'Test Recurrance Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + // construct calendar with a 1 hour event and global time zone + $this->vCalendar1c = new VCalendar(); + // time zone component + $vTimeZone = $this->vCalendar1c->add('VTIMEZONE'); + $vTimeZone->add('TZID', 'America/Toronto'); + // event component + $vEvent = $this->vCalendar1c->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701T080000'); + $vEvent->add('DTEND', '20240701T090000'); + $vEvent->add('SUMMARY', 'Test Recurrance Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + // construct calendar with a 1 hour event and no time zone + $this->vCalendar1d = new VCalendar(); + $vEvent = $this->vCalendar1d->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701T080000'); + $vEvent->add('DTEND', '20240701T090000'); + $vEvent->add('SUMMARY', 'Test Recurrance Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + // construct calendar with a full day event + $this->vCalendar2 = new VCalendar(); + // time zone component + $vTimeZone = $this->vCalendar2->add('VTIMEZONE'); + $vTimeZone->add('TZID', 'America/Toronto'); + // event component + $vEvent = $this->vCalendar2->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701'); + $vEvent->add('DTEND', '20240702'); + $vEvent->add('SUMMARY', 'Test Recurrance Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + // construct calendar with a multi day event + $this->vCalendar3 = new VCalendar(); + // time zone component + $vTimeZone = $this->vCalendar3->add('VTIMEZONE'); + $vTimeZone->add('TZID', 'America/Toronto'); + // event component + $vEvent = $this->vCalendar3->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701'); + $vEvent->add('DTEND', '20240706'); + $vEvent->add('SUMMARY', 'Test Recurrance Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + } + + public function testConstructFromCalendarString(): void { + + // construct event reader + $er = new EventReader($this->vCalendar1a->serialize(), '96a0e6b1-d886-4a55-a60d-152b31401dcc'); + // test object creation + $this->assertInstanceOf(EventReader::class, $er); + + } + + public function testConstructFromCalendarObject(): void { + + // construct event reader + $er = new EventReader($this->vCalendar1a, '96a0e6b1-d886-4a55-a60d-152b31401dcc'); + // test object creation + $this->assertInstanceOf(EventReader::class, $er); + + } + + public function testConstructFromEventObject(): void { + + // construct event reader + $er = new EventReader($this->vCalendar1a->VEVENT[0]); + // test object creation + $this->assertInstanceOf(EventReader::class, $er); + + } + + public function testStartDateTime(): void { + + /** test day part event with same start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime()); + + /** test day part event with different start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime()); + + /** test day part event with global time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->startDateTime()); + + /** test day part event with no time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('UTC')))), $er->startDateTime()); + + /** test full day event */ + // construct event reader + $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T000000', (new DateTimeZone('America/Toronto')))), $er->startDateTime()); + + /** test multi day event */ + // construct event reader + $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T000000', (new DateTimeZone('America/Toronto')))), $er->startDateTime()); + + } + + public function testStartTimeZone(): void { + + /** test day part event with same start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone()); + + /** test day part event with different start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone()); + + /** test day part event with global time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone()); + + /** test day part event with no time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('UTC')), $er->startTimeZone()); + + /** test full day event */ + // construct event reader + $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone()); + + /** test multi day event */ + // construct event reader + $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->startTimeZone()); + + } + + public function testEndDate(): void { + + /** test day part event with same start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Toronto')))), $er->endDateTime()); + + /** test day part event with different start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Vancouver')))), $er->endDateTime()); + + /** test day part event with global time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('America/Toronto')))), $er->endDateTime()); + + /** test day part event with no time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240701T090000', (new DateTimeZone('UTC')))), $er->endDateTime()); + + /** test full day event */ + // construct event reader + $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240702T000000', (new DateTimeZone('America/Toronto')))), $er->endDateTime()); + + /** test multi day event */ + // construct event reader + $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240706T000000', (new DateTimeZone('America/Toronto')))), $er->endDateTime()); + + } + + public function testEndTimeZone(): void { + + /** test day part event with same start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone()); + + /** test day part event with different start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1b, $this->vCalendar1b->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Vancouver')), $er->endTimeZone()); + + /** test day part event with global time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1c, $this->vCalendar1c->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone()); + + /** test day part event with no time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1d, $this->vCalendar1d->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('UTC')), $er->endTimeZone()); + + /** test full day event */ + // construct event reader + $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone()); + + /** test multi day event */ + // construct event reader + $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new DateTimeZone('America/Toronto')), $er->endTimeZone()); + + } + + public function testEntireDay(): void { + + /** test day part event with same start/end time zone */ + // construct event reader + $er = new EventReader($this->vCalendar1a, $this->vCalendar1a->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertFalse($er->entireDay()); + + /** test full day event */ + // construct event reader + $er = new EventReader($this->vCalendar2, $this->vCalendar2->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->entireDay()); + + /** test multi day event */ + // construct event reader + $er = new EventReader($this->vCalendar3, $this->vCalendar3->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->entireDay()); + + } + + public function testRecurs(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertFalse($er->recurs()); + + /** test rrule recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->recurs()); + + /** test rdate recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->recurs()); + + } + + public function testRecurringPattern(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertNull($er->recurringPattern()); + + /** test absolute rrule recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals('A', $er->recurringPattern()); + + /** test relative rrule recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=MO;BYSETPOS=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals('R', $er->recurringPattern()); + + /** test rdate recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals('A', $er->recurringPattern()); + + } + + public function testRecurringPrecision(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertNull($er->recurringPrecision()); + + /** test daily rrule recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals('daily', $er->recurringPrecision()); + + /** test weekly rrule recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals('weekly', $er->recurringPrecision()); + + /** test monthly rrule recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8,15'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals('monthly', $er->recurringPrecision()); + + /** test yearly rrule recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYMONTHDAY=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals('yearly', $er->recurringPrecision()); + + /** test rdate recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals('fixed', $er->recurringPrecision()); + + } + + public function testRecurringInterval(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertNull($er->recurringInterval()); + + /** test daily rrule recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals(2, $er->recurringInterval()); + + /** test rdate recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertNull($er->recurringInterval()); + + } + + public function testRecurringConcludes(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertFalse($er->recurringConcludes()); + + /** test rrule recurrance with no end */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertFalse($er->recurringConcludes()); + + /** test rrule recurrance with until date end */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;UNTIL=20240712T080000Z;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->recurringConcludes()); + + /** test rrule recurrance with iteration end */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->recurringConcludes()); + + /** test rdate recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->recurringConcludes()); + + /** test rrule and rdate recurrance with rdate as last date */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR'); + $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240715'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->recurringConcludes()); + + /** test rrule and rdate recurrance with rrule as last date */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=7;BYDAY=MO,WE,FR'); + $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240713'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertTrue($er->recurringConcludes()); + + } + + public function testRecurringConcludesAfter(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertNull($er->recurringConcludesAfter()); + + /** test rrule recurrance with count */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals(6, $er->recurringConcludesAfter()); + + /** test rdate recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals(2, $er->recurringConcludesAfter()); + + /** test rrule and rdate recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR'); + $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240715'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals(8, $er->recurringConcludesAfter()); + + } + + public function testRecurringConcludesOn(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertNull($er->recurringConcludesOn()); + + /** test rrule recurrance with no end */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertNull($er->recurringConcludesOn()); + + /** test rrule recurrance with until date end */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;UNTIL=20240712T080000Z;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + + // TODO: Fix until time zone + //$this->assertEquals((new \DateTime('20240712T080000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn()); + + /** test rdate recurrance */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703,20240705'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240705T000000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn()); + + /** test rrule and rdate recurrance with rdate as last date */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR'); + $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240715'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240715T000000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn()); + + /** test rrule and rdate recurrance with rrule as last date */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=7;BYDAY=MO,WE,FR'); + $vCalendar->VEVENT[0]->add('RDATE', '20240706,20240713'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals((new \DateTime('20240715T080000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn()); + + } + + public function testRecurringDaysOfWeek(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringDaysOfWeek()); + + /** test rrule recurrance with weekly days*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;UNTIL=20240712T080000Z;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals(['MO','WE','FR'], $er->recurringDaysOfWeek()); + + } + + public function testRecurringDaysOfWeekNamed(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringDaysOfWeekNamed()); + + /** test rrule recurrance with weekly days*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;UNTIL=20240712T080000Z;BYDAY=MO,WE,FR'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals(['Monday','Wednesday','Friday'], $er->recurringDaysOfWeekNamed()); + + } + + public function testRecurringDaysOfMonth(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringDaysOfMonth()); + + /** test rrule recurrance with monthly absolute dates*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=6,13,20,27'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([6,13,20,27], $er->recurringDaysOfMonth()); + + } + + public function testRecurringDaysOfYear(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringDaysOfYear()); + + /** test rrule recurrance with monthly absolute dates*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYYEARDAY=1,30,180,365'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([1,30,180,365], $er->recurringDaysOfYear()); + + } + + public function testRecurringWeeksOfMonth(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringWeeksOfMonth()); + + /** test rrule recurrance with monthly days*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=MO;BYSETPOS=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([1], $er->recurringWeeksOfMonth()); + + } + + public function testRecurringWeeksOfMonthNamed(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringWeeksOfMonthNamed()); + + /** test rrule recurrance with weekly days*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=MO;BYSETPOS=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals(['First'], $er->recurringWeeksOfMonthNamed()); + + } + + public function testRecurringWeeksOfYear(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringWeeksOfYear()); + + /** test rrule recurrance with monthly days*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;INTERVAL=1;BYWEEKNO=35,42;BYDAY=TU'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([35,42], $er->recurringWeeksOfYear()); + + } + + public function testRecurringMonthsOfYear(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringMonthsOfYear()); + + /** test rrule recurrance with monthly days*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;INTERVAL=1;BYMONTH=7;BYMONTHDAY=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([7], $er->recurringMonthsOfYear()); + + } + + public function testRecurringMonthsOfYearNamed(): void { + + /** test no recurrance */ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals([], $er->recurringMonthsOfYearNamed()); + + /** test rrule recurrance with weekly days*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;INTERVAL=1;BYMONTH=7;BYMONTHDAY=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test set by constructor + $this->assertEquals(['July'], $er->recurringMonthsOfYearNamed()); + + } + + public function testRecurringIterationDaily(): void { + + /** test rrule recurrance with daily frequency*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;UNTIL=20240714T040000Z'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test initial recurrance + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240704T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240707T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240710T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240713T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance (This is past the last recurrance and should return null) + $er->recurrenceAdvance(); + $this->assertNull($er->recurrenceDate()); + // test rewind to initial recurrance + $er->recurrenceRewind(); + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvanceTo((new \DateTime('20240709T080000'))); + $this->assertEquals((new \DateTime('20240710T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + + } + + public function testRecurringIterationWeekly(): void { + + /** test rrule recurrance with weekly frequency*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20240713T040000Z'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test initial recurrance + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240703T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240705T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240708T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240710T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240712T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance (This is past the last recurrance and should return null) + $er->recurrenceAdvance(); + $this->assertNull($er->recurrenceDate()); + // test rewind to initial recurrance + $er->recurrenceRewind(); + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvanceTo((new \DateTime('20240709T080000'))); + $this->assertEquals((new \DateTime('20240710T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + + } + + public function testRecurringIterationMonthlyAbsolute(): void { + + /** test rrule recurrance with monthly absolute frequency on the 1st of each month*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;COUNT=3;BYMONTHDAY=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test initial recurrance + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240801T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240901T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance (This is past the last recurrance and should return null) + $er->recurrenceAdvance(); + $this->assertNull($er->recurrenceDate()); + // test rewind to initial recurrance + $er->recurrenceRewind(); + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvanceTo((new \DateTime('20240809T080000'))); + $this->assertEquals((new \DateTime('20240901T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + + } + + public function testRecurringIterationMonthlyRelative(): void { + + /** test rrule recurrance with monthly relative frequency on the first monday of each month*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;COUNT=3;BYDAY=MO;BYSETPOS=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test initial recurrance + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240805T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240902T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance (This is past the last recurrance and should return null) + $er->recurrenceAdvance(); + $this->assertNull($er->recurrenceDate()); + // test rewind to initial recurrance + $er->recurrenceRewind(); + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvanceTo((new \DateTime('20240809T080000'))); + $this->assertEquals((new \DateTime('20240902T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + + } + + public function testRecurringIterationYearlyAbsolute(): void { + + /** test rrule recurrance with yearly absolute frequency on the 1st of july*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;COUNT=3;BYMONTH=7'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test initial recurrance + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20250701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20260701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance (This is past the last recurrance and should return null) + $er->recurrenceAdvance(); + $this->assertNull($er->recurrenceDate()); + // test rewind to initial recurrance + $er->recurrenceRewind(); + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvanceTo((new \DateTime('20250809T080000'))); + $this->assertEquals((new \DateTime('20260701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + + } + + public function testRecurringIterationYearlyRelative(): void { + + /** test rrule recurrance with yearly relative frequency on the first monday of july*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;COUNT=3;BYMONTH=7;BYDAY=MO;BYSETPOS=1'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test initial recurrance + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20250707T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20260706T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance (This is past the last recurrance and should return null) + $er->recurrenceAdvance(); + $this->assertNull($er->recurrenceDate()); + // test rewind to initial recurrance + $er->recurrenceRewind(); + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvanceTo((new \DateTime('20250809T080000'))); + $this->assertEquals((new \DateTime('20260706T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + + } + + public function testRecurringIterationFixed(): void { + + /** test rrule recurrance with yearly relative frequency on the first monday of july*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703T080000,20240905T080000,20241231T080000'); + // construct event reader + $er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test initial recurrance + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240703T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20240905T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvance(); + $this->assertEquals((new \DateTime('20241231T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance (This is past the last recurrance and should return null) + $er->recurrenceAdvance(); + $this->assertNull($er->recurrenceDate()); + // test rewind to initial recurrance + $er->recurrenceRewind(); + $this->assertEquals((new \DateTime('20240701T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + // test next recurrance + $er->recurrenceAdvanceTo((new \DateTime('20240809T080000'))); + $this->assertEquals((new \DateTime('20240905T080000', (new DateTimeZone('America/Toronto')))), $er->recurrenceDate()); + + } + +} diff --git a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php index e4a9f1b75d0..667604f9b3e 100644 --- a/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php +++ b/apps/dav/tests/unit/CalDAV/Schedule/IMipServiceTest.php @@ -10,15 +10,15 @@ namespace OCA\DAV\Tests\unit\CalDAV\Schedule; use OC\L10N\L10N; use OC\L10N\LazyL10N; use OC\URLGenerator; +use OCA\DAV\CalDAV\EventReader; use OCA\DAV\CalDAV\Schedule\IMipService; +use OCP\AppFramework\Utility\ITimeFactory; use OCP\IConfig; use OCP\IDBConnection; use OCP\L10N\IFactory as L10NFactory; use OCP\Security\ISecureRandom; use PHPUnit\Framework\MockObject\MockObject; use Sabre\VObject\Component\VCalendar; -use Sabre\VObject\Component\VEvent; -use Sabre\VObject\ITip\Message; use Sabre\VObject\Property\ICalendar\DateTime; use Test\TestCase; @@ -41,9 +41,23 @@ class IMipServiceTest extends TestCase { /** @var L10N|MockObject */ private $l10n; + /** @var ITimeFactory|MockObject */ + private $timeFactory; + /** @var IMipService */ private $service; + /** @var VCalendar*/ + private $vCalendar1a; + /** @var VCalendar*/ + private $vCalendar1b; + /** @var VCalendar*/ + private $vCalendar2; + /** @var VCalendar*/ + private $vCalendar3; + /** @var DateTime DateTime object that will be returned by DateTime() or DateTime('now') */ + public static $datetimeNow; + protected function setUp(): void { $this->urlGenerator = $this->createMock(URLGenerator::class); $this->config = $this->createMock(IConfig::class); @@ -51,6 +65,7 @@ class IMipServiceTest extends TestCase { $this->random = $this->createMock(ISecureRandom::class); $this->l10nFactory = $this->createMock(L10NFactory::class); $this->l10n = $this->createMock(LazyL10N::class); + $this->timeFactory = $this->createMock(ITimeFactory::class); $this->l10nFactory->expects(self::once()) ->method('findGenericLanguage') ->willReturn('en'); @@ -63,8 +78,81 @@ class IMipServiceTest extends TestCase { $this->config, $this->db, $this->random, - $this->l10nFactory + $this->l10nFactory, + $this->timeFactory ); + + // construct calendar with a 1 hour event and same start/end time zones + $this->vCalendar1a = new VCalendar(); + $vEvent = $this->vCalendar1a->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']); + $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Toronto']); + $vEvent->add('SUMMARY', 'Testing Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + // construct calendar with a 1 hour event and different start/end time zones + $this->vCalendar1b = new VCalendar(); + $vEvent = $this->vCalendar1b->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701T080000', ['TZID' => 'America/Toronto']); + $vEvent->add('DTEND', '20240701T090000', ['TZID' => 'America/Vancouver']); + $vEvent->add('SUMMARY', 'Testing Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + // construct calendar with a full day event + $this->vCalendar2 = new VCalendar(); + // time zone component + $vTimeZone = $this->vCalendar2->add('VTIMEZONE'); + $vTimeZone->add('TZID', 'America/Toronto'); + // event component + $vEvent = $this->vCalendar2->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701'); + $vEvent->add('DTEND', '20240702'); + $vEvent->add('SUMMARY', 'Testing Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); + + // construct calendar with a multi day event + $this->vCalendar3 = new VCalendar(); + // time zone component + $vTimeZone = $this->vCalendar3->add('VTIMEZONE'); + $vTimeZone->add('TZID', 'America/Toronto'); + // event component + $vEvent = $this->vCalendar3->add('VEVENT', []); + $vEvent->UID->setValue('96a0e6b1-d886-4a55-a60d-152b31401dcc'); + $vEvent->add('DTSTART', '20240701'); + $vEvent->add('DTEND', '20240706'); + $vEvent->add('SUMMARY', 'Testing Event'); + $vEvent->add('ORGANIZER', 'mailto:organizer@testing.com', ['CN' => 'Organizer']); + $vEvent->add('ATTENDEE', 'mailto:attendee1@testing.com', [ + 'CN' => 'Attendee One', + 'CUTYPE' => 'INDIVIDUAL', + 'PARTSTAT' => 'NEEDS-ACTION', + 'ROLE' => 'REQ-PARTICIPANT', + 'RSVP' => 'TRUE' + ]); } public function testGetFrom(): void { @@ -81,96 +169,93 @@ class IMipServiceTest extends TestCase { } public function testBuildBodyDataCreated(): void { - $vCalendar = new VCalendar(); - $oldVevent = null; - $newVevent = new VEvent($vCalendar, 'two', [ - 'UID' => 'uid-1234', - 'SEQUENCE' => 3, - 'LAST-MODIFIED' => 789456, - 'SUMMARY' => 'Second Breakfast', - 'DTSTART' => new \DateTime('2016-01-01 00:00:00'), - 'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00') + + // construct l10n return(s) + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM', + $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM', + $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'full'] => 'July 1, 2024' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['In a %1$s on %2$s between %3$s - %4$s', ['day', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'] ]); - + // construct time factory return(s) + $this->timeFactory->method('getDateTime')->willReturnCallback( + function ($v1, $v2) { + return match (true) { + $v1 == 'now' && $v2 == null => (new \DateTime('20240630T000000')) + }; + } + ); + /** test singleton partial day event*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // define expected output $expected = [ - 'meeting_when' => $this->service->generateWhenString($newVevent), + 'meeting_when' => $this->service->generateWhenString($eventReader), 'meeting_description' => '', - 'meeting_title' => 'Second Breakfast', + 'meeting_title' => 'Testing Event', 'meeting_location' => '', 'meeting_url' => '', 'meeting_url_html' => '', ]; - - $actual = $this->service->buildBodyData($newVevent, $oldVevent); - + // generate actual output + $actual = $this->service->buildBodyData($vCalendar->VEVENT[0], null); + // test output $this->assertEquals($expected, $actual); } public function testBuildBodyDataUpdate(): void { - $vCalendar = new VCalendar(); - $oldVevent = new VEvent($vCalendar, 'two', [ - 'UID' => 'uid-1234', - 'SEQUENCE' => 1, - 'LAST-MODIFIED' => 456789, - 'SUMMARY' => 'Elevenses', - 'DTSTART' => new \DateTime('2016-01-01 00:00:00'), - 'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00') + + // construct l10n return(s) + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM', + $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM', + $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'full'] => 'July 1, 2024' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['In a %1$s on %2$s between %3$s - %4$s', ['day', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'] ]); - $oldVevent->add('ORGANIZER', 'mailto:gandalf@wiz.ard'); - $oldVevent->add('ATTENDEE', 'mailto:' . 'frodo@hobb.it', ['RSVP' => 'TRUE', 'CN' => 'Frodo']); - $newVevent = new VEvent($vCalendar, 'two', [ - 'UID' => 'uid-1234', - 'SEQUENCE' => 3, - 'LAST-MODIFIED' => 789456, - 'SUMMARY' => 'Second Breakfast', - 'DTSTART' => new \DateTime('2016-01-01 00:00:00'), - 'RECURRENCE-ID' => new \DateTime('2016-01-01 00:00:00') - ]); - + // construct time factory return(s) + $this->timeFactory->method('getDateTime')->willReturnCallback( + function ($v1, $v2) { + return match (true) { + $v1 == 'now' && $v2 == null => (new \DateTime('20240630T000000')) + }; + } + ); + /** test singleton partial day event*/ + $vCalendarNew = clone $this->vCalendar1a; + $vCalendarOld = clone $this->vCalendar1a; + // construct event reader + $eventReaderNew = new EventReader($vCalendarNew, $vCalendarNew->VEVENT[0]->UID->getValue()); + // alter old event label/title + $vCalendarOld->VEVENT[0]->SUMMARY->setValue('Testing Singleton Event'); + // define expected output $expected = [ - 'meeting_when' => $this->service->generateWhenString($newVevent), + 'meeting_when' => $this->service->generateWhenString($eventReaderNew), 'meeting_description' => '', - 'meeting_title' => 'Second Breakfast', + 'meeting_title' => 'Testing Event', 'meeting_location' => '', 'meeting_url' => '', 'meeting_url_html' => '', - 'meeting_when_html' => $this->service->generateWhenString($newVevent), - 'meeting_title_html' => sprintf("%s
%s", 'Elevenses', 'Second Breakfast'), + 'meeting_when_html' => $this->service->generateWhenString($eventReaderNew), + 'meeting_title_html' => sprintf("%s
%s", 'Testing Singleton Event', 'Testing Event'), 'meeting_description_html' => '', 'meeting_location_html' => '' ]; - - $actual = $this->service->buildBodyData($newVevent, $oldVevent); - - $this->assertEquals($expected, $actual); - } - - public function testGenerateWhenStringHourlyEvent(): void { - $vCalendar = new VCalendar(); - $vevent = new VEvent($vCalendar, 'two', [ - 'UID' => 'uid-1234', - 'SEQUENCE' => 1, - 'LAST-MODIFIED' => 456789, - 'SUMMARY' => 'Elevenses', - 'TZID' => 'Europe/Vienna', - 'DTSTART' => (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), - 'DTEND' => (new \DateTime('2016-01-01 09:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), - ]); - - $this->l10n->expects(self::exactly(3)) - ->method('l') - ->withConsecutive( - ['weekdayName', (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'abbreviated']], - ['datetime', (new \DateTime('2016-01-01 08:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'medium|short']], - ['time', (new \DateTime('2016-01-01 09:00:00'))->setTimezone(new \DateTimeZone('Europe/Vienna')), ['width' => 'short']] - )->willReturnOnConsecutiveCalls( - 'Fr.', - '01.01. 08:00', - '09:00' - ); - - $expected = 'Fr., 01.01. 08:00 - 09:00 (Europe/Vienna)'; - $actual = $this->service->generateWhenString($vevent); + // generate actual output + $actual = $this->service->buildBodyData($vCalendarNew->VEVENT[0], $vCalendarOld->VEVENT[0]); + // test output $this->assertEquals($expected, $actual); } @@ -250,73 +335,1021 @@ class IMipServiceTest extends TestCase { $this->assertEquals(1451606400, $occurrence); } - public function testGetCurrentAttendeeRequest(): void { - // Construct ITip Message - $message = new Message(); - $message->method = 'REQUEST'; - $message->sequence = 1; - $message->sender = 'mailto:organizer@example.com'; - $message->senderName = 'The Organizer'; - $message->recipient = 'mailto:attendee@example.com'; - $message->recipientName = 'The Attendee'; - $message->significantChange = true; - $message->message = new VCalendar(); - $message->message->add('VEVENT', ['UID' => '82496785-1915-4604-a5ce-4e2091639c9a', 'SEQUENCE' => 1]); - $message->message->VEVENT->add('SUMMARY', 'Fellowship meeting'); - $message->message->VEVENT->add('DTSTART', (new \DateTime('NOW'))->modify('+1 hour')); - $message->message->VEVENT->add('DTEND', (new \DateTime('NOW'))->modify('+2 hour')); - $message->message->VEVENT->add('ORGANIZER', 'mailto:organizer@example.com', ['CN' => 'The Organizer']); - $message->message->VEVENT->add('ATTENDEE', 'mailto:attendee@example.com', ['CN' => 'The Attendee']); - // Test getCurrentAttendee - $result = $this->service->getCurrentAttendee($message); - // Evaluate Result - $this->assertEquals($message->message->VEVENT->ATTENDEE, $result); + public function testGenerateWhenStringSingular(): void { + + // construct l10n return(s) + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM', + $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM', + $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'full'] => 'July 1, 2024', + $v1 === 'date' && $v2 == (new \DateTime('20240701T000000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'full'] => 'July 1, 2024' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['In a %1$s on %2$s for the entire day', ['day', 'July 1, 2024'], 'In a day on July 1, 2024 for the entire day'], + ['In a %1$s on %2$s between %3$s - %4$s', ['day', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['In %1$s %2$s on %3$s for the entire day', [2, 'days', 'July 1, 2024'], 'In 2 days on July 1, 2024 for the entire day'], + ['In %1$s %2$s on %3$s between %4$s - %5$s', [2, 'days', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In 2 days on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['In a %1$s on %2$s for the entire day', ['week', 'July 1, 2024'], 'In a week on July 1, 2024 for the entire day'], + ['In a %1$s on %2$s between %3$s - %4$s', ['week', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a week on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['In %1$s %2$s on %3$s for the entire day', [2, 'weeks', 'July 1, 2024'], 'In 2 weeks on July 1, 2024 for the entire day'], + ['In %1$s %2$s on %3$s between %4$s - %5$s', [2, 'weeks', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In 2 weeks on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['In a %1$s on %2$s for the entire day', ['month', 'July 1, 2024'], 'In a month on July 1, 2024 for the entire day'], + ['In a %1$s on %2$s between %3$s - %4$s', ['month', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a month on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['In %1$s %2$s on %3$s for the entire day', [2, 'months', 'July 1, 2024'], 'In 2 months on July 1, 2024 for the entire day'], + ['In %1$s %2$s on %3$s between %4$s - %5$s', [2, 'months', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In 2 months on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['In a %1$s on %2$s for the entire day', ['year', 'July 1, 2024'], 'In a year on July 1, 2024 for the entire day'], + ['In a %1$s on %2$s between %3$s - %4$s', ['year', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In a year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['In %1$s %2$s on %3$s for the entire day', [2, 'years', 'July 1, 2024'], 'In 2 years on July 1, 2024 for the entire day'], + ['In %1$s %2$s on %3$s between %4$s - %5$s', [2, 'years', 'July 1, 2024', '8:00 AM', '9:00 AM (America/Toronto)'], 'In 2 years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)'] + ]); + + // construct time factory return(s) + $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls( + (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240621T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240621T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240614T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240614T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240530T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240530T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240430T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240430T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20230630T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20230630T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20220630T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20220630T170000', (new \DateTimeZone('America/Toronto')))) + ); + + /** test patrial day event in 1 day*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a day on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 1 day*/ + $vCalendar = clone $this->vCalendar2; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a day on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test patrial day event in 2 days*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 days on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 2 days*/ + $vCalendar = clone $this->vCalendar2; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 days on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test patrial day event in 1 week*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a week on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 1 week*/ + $vCalendar = clone $this->vCalendar2; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a week on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test patrial day event in 2 weeks*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 weeks on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 2 weeks*/ + $vCalendar = clone $this->vCalendar2; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 weeks on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test patrial day event in 1 month*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a month on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 1 month*/ + $vCalendar = clone $this->vCalendar2; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a month on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test patrial day event in 2 months*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 months on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 2 months*/ + $vCalendar = clone $this->vCalendar2; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 months on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test patrial day event in 1 year*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 1 year*/ + $vCalendar = clone $this->vCalendar2; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a year on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test patrial day event in 2 years*/ + $vCalendar = clone $this->vCalendar1a; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event in 2 years*/ + $vCalendar = clone $this->vCalendar2; + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 years on July 1, 2024 for the entire day', + $this->service->generateWhenString($eventReader) + ); + } - public function testGetCurrentAttendeeReply(): void { - // Construct ITip Message - $message = new Message(); - $message->method = 'REPLY'; - $message->sequence = 2; - $message->sender = 'mailto:attendee@example.com'; - $message->senderName = 'The Attendee'; - $message->recipient = 'mailto:organizer@example.com'; - $message->recipientName = 'The Organizer'; - $message->significantChange = true; - $message->message = new VCalendar(); - $message->message->add('METHOD', 'REPLY'); - $message->message->add('VEVENT', ['UID' => '82496785-1915-4604-a5ce-4e2091639c9a', 'SEQUENCE' => 2]); - $message->message->VEVENT->add('SUMMARY', 'Fellowship meeting'); - $message->message->VEVENT->add('DTSTART', (new \DateTime('NOW'))->modify('+1 hour')); - $message->message->VEVENT->add('DTEND', (new \DateTime('NOW'))->modify('+2 hour')); - $message->message->VEVENT->add('ORGANIZER', 'mailto:organizer@example.com', ['CN' => 'The Organizer']); - $message->message->VEVENT->add('ATTENDEE', 'mailto:attendee@example.com', ['CN' => 'The Attendee']); - // Test getCurrentAttendee - $result = $this->service->getCurrentAttendee($message); - // Evaluate Result - $this->assertEquals($message->message->VEVENT->ATTENDEE, $result); + public function testGenerateWhenStringRecurringDaily(): void { + + // construct l10n return maps + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM', + $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM', + $v1 === 'date' && $v2 == (new \DateTime('20240713T080000', (new \DateTimeZone('UTC')))) && $v3 == ['width' => 'long'] => 'July 13, 2024' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['Every Day for the entire day', [], 'Every Day for the entire day'], + ['Every Day for the entire day until %1$s', ['July 13, 2024'], 'Every Day for the entire day until July 13, 2024'], + ['Every Day between %1$s - %2$s', ['8:00 AM', '9:00 AM (America/Toronto)'], 'Every Day between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every Day between %1$s - %2$s until %3$s', ['8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'Every Day between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'], + ['Every %1$d Days for the entire day', [3], 'Every 3 Days for the entire day'], + ['Every %1$d Days for the entire day until %2$s', [3, 'July 13, 2024'], 'Every 3 Days for the entire day until July 13, 2024'], + ['Every %1$d Days between %2$s - %3$s', [3, '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every %1$d Days between %2$s - %3$s until %4$s', [3, '8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'], + ['Could not generate event recurrence statement', [], 'Could not generate event recurrence statement'], + ]); + + /** test partial day event with every day interval and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=1;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Day between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event with every day interval and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=1;UNTIL=20240713T080000Z'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Day between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event every 3rd day interval and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event with every 3rd day interval and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;UNTIL=20240713T080000Z'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 3 Days between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every day interval and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=1;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Day for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every day interval and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=1;UNTIL=20240713T080000Z'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Day for the entire day until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every 3rd day interval and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 3 Days for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every 3rd day interval and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=3;UNTIL=20240713T080000Z'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 3 Days for the entire day until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + } - public function testGetCurrentAttendeeMismatch(): void { - // Construct ITip Message - $message = new Message(); - $message->method = 'REQUEST'; - $message->sequence = 1; - $message->sender = 'mailto:organizer@example.com'; - $message->senderName = 'The Organizer'; - $message->recipient = 'mailto:mismatch@example.com'; - $message->recipientName = 'The Mismatch'; - $message->significantChange = true; - $message->message = new VCalendar(); - $message->message->add('VEVENT', ['UID' => '82496785-1915-4604-a5ce-4e2091639c9a', 'SEQUENCE' => 1]); - $message->message->VEVENT->add('SUMMARY', 'Fellowship meeting'); - $message->message->VEVENT->add('DTSTART', (new \DateTime('NOW'))->modify('+1 hour')); - $message->message->VEVENT->add('DTEND', (new \DateTime('NOW'))->modify('+2 hour')); - $message->message->VEVENT->add('ORGANIZER', 'mailto:organizer@example.com', ['CN' => 'The Organizer']); - $message->message->VEVENT->add('ATTENDEE', 'mailto:attendee@example.com', ['CN' => 'The Attendee']); - // Test getCurrentAttendee - $result = $this->service->getCurrentAttendee($message); - // Evaluate Result - $this->assertEquals(null, $result); + public function testGenerateWhenStringRecurringWeekly(): void { + + // construct l10n return maps + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM', + $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM', + $v1 === 'date' && $v2 == (new \DateTime('20240722T080000', (new \DateTimeZone('UTC')))) && $v3 == ['width' => 'long'] => 'July 13, 2024' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['Every Week on %1$s for the entire day', ['Monday, Wednesday, Friday'], 'Every Week on Monday, Wednesday, Friday for the entire day'], + ['Every Week on %1$s for the entire day until %2$s', ['Monday, Wednesday, Friday', 'July 13, 2024'], 'Every Week on Monday, Wednesday, Friday for the entire day until July 13, 2024'], + ['Every Week on %1$s between %2$s - %3$s', ['Monday, Wednesday, Friday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every Week on %1$s between %2$s - %3$s until %4$s', ['Monday, Wednesday, Friday', '8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'], + ['Every %1$d Weeks on %2$s for the entire day', [2, 'Monday, Wednesday, Friday'], 'Every 2 Weeks on Monday, Wednesday, Friday for the entire day'], + ['Every %1$d Weeks on %2$s for the entire day until %3$s', [2, 'Monday, Wednesday, Friday', 'July 13, 2024'], 'Every 2 Weeks on Monday, Wednesday, Friday for the entire day until July 13, 2024'], + ['Every %1$d Weeks on %2$s between %3$s - %4$s', [2, 'Monday, Wednesday, Friday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s', [2, 'Monday, Wednesday, Friday', '8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'], + ['Could not generate event recurrence statement', [], 'Could not generate event recurrence statement'], + ['Monday', [], 'Monday'], + ['Wednesday', [], 'Wednesday'], + ['Friday', [], 'Friday'], + ]); + + /** test partial day event with every week interval on Mon, Wed, Fri and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event with every week interval on Mon, Wed, Fri and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20240722T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Week on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event with every 2nd week interval on Mon, Wed, Fri and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test partial day event with every 2nd week interval on Mon, Wed, Fri and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;UNTIL=20240722T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Weeks on Monday, Wednesday, Friday between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every week interval on Mon, Wed, Fri and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Week on Monday, Wednesday, Friday for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every week interval on Mon, Wed, Fri and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20240722T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Week on Monday, Wednesday, Friday for the entire day until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every 2nd week interval on Mon, Wed, Fri and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Weeks on Monday, Wednesday, Friday for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every 2nd week interval on Mon, Wed, Fri and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;BYDAY=MO,WE,FR;INTERVAL=2;UNTIL=20240722T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Weeks on Monday, Wednesday, Friday for the entire day until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + } + + public function testGenerateWhenStringRecurringMonthly(): void { + + // construct l10n return maps + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM', + $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM', + $v1 === 'date' && $v2 == (new \DateTime('20241231T080000', (new \DateTimeZone('UTC')))) && $v3 == ['width' => 'long'] => 'December 31, 2024' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['Every Month on the %1$s for the entire day', ['1, 8'], 'Every Month on the 1, 8 for the entire day'], + ['Every Month on the %1$s for the entire day until %2$s', ['1, 8', 'December 31, 2024'], 'Every Month on the 1, 8 for the entire day until December 31, 2024'], + ['Every Month on the %1$s between %2$s - %3$s', ['1, 8', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every Month on the %1$s between %2$s - %3$s until %4$s', ['1, 8', '8:00 AM', '9:00 AM (America/Toronto)', 'December 31, 2024'], 'Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024'], + ['Every %1$d Months on the %2$s for the entire day', [2, '1, 8'], 'Every 2 Months on the 1, 8 for the entire day'], + ['Every %1$d Months on the %2$s for the entire day until %3$s', [2, '1, 8', 'December 31, 2024'], 'Every 2 Months on the 1, 8 for the entire day until December 31, 2024'], + ['Every %1$d Months on the %2$s between %3$s - %4$s', [2, '1, 8', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every %1$d Months on the %2$s between %3$s - %4$s until %5$s', [2, '1, 8', '8:00 AM', '9:00 AM (America/Toronto)', 'December 31, 2024'], 'Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024'], + ['Every Month on the %1$s for the entire day', ['First Sunday, Saturday'], 'Every Month on the First Sunday, Saturday for the entire day'], + ['Every Month on the %1$s for the entire day until %2$s', ['First Sunday, Saturday', 'December 31, 2024'], 'Every Month on the First Sunday, Saturday for the entire day until December 31, 2024'], + ['Every Month on the %1$s between %2$s - %3$s', ['First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every Month on the %1$s between %2$s - %3$s until %4$s', ['First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)', 'December 31, 2024'], 'Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024'], + ['Every %1$d Months on the %2$s for the entire day', [2, 'First Sunday, Saturday'], 'Every 2 Months on the First Sunday, Saturday for the entire day'], + ['Every %1$d Months on the %2$s for the entire day until %3$s', [2, 'First Sunday, Saturday', 'December 31, 2024'], 'Every 2 Months on the First Sunday, Saturday for the entire day until December 31, 2024'], + ['Every %1$d Months on the %2$s between %3$s - %4$s', [2, 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every %1$d Months on the %2$s between %3$s - %4$s until %5$s', [2, 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)', 'December 31, 2024'], 'Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024'], + ['Could not generate event recurrence statement', [], 'Could not generate event recurrence statement'], + ['Saturday', [], 'Saturday'], + ['Sunday', [], 'Sunday'], + ['First', [], 'First'], + ]); + + /** test absolute partial day event with every month interval on 1st, 8th and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute partial day event with every Month interval on 1st, 8th and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;UNTIL=20241231T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Month on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute partial day event with every 2nd Month interval on 1st, 8th and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute partial day event with every 2nd Month interval on 1st, 8th and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;INTERVAL=2;UNTIL=20241231T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Months on the 1, 8 between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute entire day event with every Month interval on 1st, 8th and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Month on the 1, 8 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute entire day event with every Month interval on 1st, 8th and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;UNTIL=20241231T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Month on the 1, 8 for the entire day until December 31, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute entire day event with every 2nd Month interval on 1st, 8th and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Months on the 1, 8 for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute entire day event with every 2nd Month interval on 1st, 8th and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYMONTHDAY=1,8;INTERVAL=2;UNTIL=20241231T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Months on the 1, 8 for the entire day until December 31, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test relative partial day event with every month interval on the 1st Saturday, Sunday and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test relative partial day event with every Month interval on the 1st Saturday, Sunday and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;UNTIL=20241231T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Month on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test relative partial day event with every 2nd Month interval on the 1st Saturday, Sunday and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test relative partial day event with every 2nd Month interval on the 1st Saturday, Sunday and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;UNTIL=20241231T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Months on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until December 31, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test relative entire day event with every Month interval on the 1st Saturday, Sunday and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Month on the First Sunday, Saturday for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test relative entire day event with every Month interval on the 1st Saturday, Sunday and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;UNTIL=20241231T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Month on the First Sunday, Saturday for the entire day until December 31, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test relative entire day event with every 2nd Month interval on the 1st Saturday, Sunday and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Months on the First Sunday, Saturday for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test relative entire day event with every 2nd Month interval on the 1st Saturday, Sunday and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=MONTHLY;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;UNTIL=20241231T080000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Months on the First Sunday, Saturday for the entire day until December 31, 2024', + $this->service->generateWhenString($eventReader) + ); + + } + + public function testGenerateWhenStringRecurringYearly(): void { + + // construct l10n return maps + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM', + $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM', + $v1 === 'date' && $v2 == (new \DateTime('20260731T040000', (new \DateTimeZone('UTC')))) && $v3 == ['width' => 'long'] => 'July 31, 2026' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['Every Year in %1$s on the %2$s for the entire day', ['July', '1st'], 'Every Year in July on the 1st for the entire day'], + ['Every Year in %1$s on the %2$s for the entire day until %3$s', ['July', '1st', 'July 31, 2026'], 'Every Year in July on the 1st for the entire day until July 31, 2026'], + ['Every Year in %1$s on the %2$s between %3$s - %4$s', ['July', '1st', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s', ['July', '1st', '8:00 AM', '9:00 AM (America/Toronto)', 'July 31, 2026'], 'Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026'], + ['Every %1$d Years in %2$s on the %3$s for the entire day', [2, 'July', '1st'], 'Every 2 Years in July on the 1st for the entire day'], + ['Every %1$d Years in %2$s on the %3$s for the entire day until %4$s', [2, 'July', '1st', 'July 31, 2026'], 'Every 2 Years in July on the 1st for the entire day until July 31, 2026'], + ['Every %1$d Years in %2$s on the %3$s between %4$s - %5$s', [2, 'July', '1st', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s', [2, 'July', '1st', '8:00 AM', '9:00 AM (America/Toronto)', 'July 31, 2026'], 'Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026'], + ['Every Year in %1$s on the %2$s for the entire day', ['July', 'First Sunday, Saturday'], 'Every Year in July on the First Sunday, Saturday for the entire day'], + ['Every Year in %1$s on the %2$s for the entire day until %3$s', ['July', 'First Sunday, Saturday', 'July 31, 2026'], 'Every Year in July on the First Sunday, Saturday for the entire day until July 31, 2026'], + ['Every Year in %1$s on the %2$s between %3$s - %4$s', ['July', 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s', ['July', 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)', 'July 31, 2026'], 'Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026'], + ['Every %1$d Years in %2$s on the %3$s for the entire day', [2, 'July', 'First Sunday, Saturday'], 'Every 2 Years in July on the First Sunday, Saturday for the entire day'], + ['Every %1$d Years in %2$s on the %3$s for the entire day until %4$s', [2, 'July', 'First Sunday, Saturday', 'July 31, 2026'], 'Every 2 Years in July on the First Sunday, Saturday for the entire day until July 31, 2026'], + ['Every %1$d Years in %2$s on the %3$s between %4$s - %5$s', [2, 'July', 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)'], 'Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)'], + ['Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s', [2, 'July', 'First Sunday, Saturday', '8:00 AM', '9:00 AM (America/Toronto)', 'July 31, 2026'], 'Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026'], + ['Could not generate event recurrence statement', [], 'Could not generate event recurrence statement'], + ['July', [], 'July'], + ['Saturday', [], 'Saturday'], + ['Sunday', [], 'Sunday'], + ['First', [], 'First'], + ]); + + /** test absolute partial day event with every year interval on July 1 and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute partial day event with every year interval on July 1 and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;UNTIL=20260731T040000Z'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Year in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute partial day event with every 2nd year interval on July 1 and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute partial day event with every 2nd year interval on July 1 and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;INTERVAL=2;UNTIL=20260731T040000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Years in July on the 1st between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute entire day event with every year interval on July 1 and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Year in July on the 1st for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute entire day event with every year interval on July 1 and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;UNTIL=20260731T040000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Year in July on the 1st for the entire day until July 31, 2026', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute entire day event with every 2nd year interval on July 1 and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Years in July on the 1st for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test absolute entire day event with every 2nd year interval on July 1 and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;INTERVAL=2;UNTIL=20260731T040000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Years in July on the 1st for the entire day until July 31, 2026', + $this->service->generateWhenString($eventReader) + ); + + /** test relative partial day event with every year interval on the 1st Saturday, Sunday in July and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test relative partial day event with every year interval on the 1st Saturday, Sunday in July and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;UNTIL=20260731T040000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Year in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026', + $this->service->generateWhenString($eventReader) + ); + + /** test relative partial day event with every 2nd year interval on the 1st Saturday, Sunday in July and no conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto)', + $this->service->generateWhenString($eventReader) + ); + + /** test relative partial day event with every 2nd year interval on the 1st Saturday, Sunday in July and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;UNTIL=20260731T040000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Years in July on the First Sunday, Saturday between 8:00 AM - 9:00 AM (America/Toronto) until July 31, 2026', + $this->service->generateWhenString($eventReader) + ); + + /** test relative entire day event with every year interval on the 1st Saturday, Sunday in July and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Year in July on the First Sunday, Saturday for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test relative entire day event with every year interval on the 1st Saturday, Sunday in July and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;UNTIL=20260731T040000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every Year in July on the First Sunday, Saturday for the entire day until July 31, 2026', + $this->service->generateWhenString($eventReader) + ); + + /** test relative entire day event with every 2nd year interval on the 1st Saturday, Sunday in July and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Years in July on the First Sunday, Saturday for the entire day', + $this->service->generateWhenString($eventReader) + ); + + /** test relative entire day event with every 2nd year interval on the 1st Saturday, Sunday in July and conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=YEARLY;BYMONTH=7;BYDAY=SU,SA;BYSETPOS=1;INTERVAL=2;UNTIL=20260731T040000Z;'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'Every 2 Years in July on the First Sunday, Saturday for the entire day until July 31, 2026', + $this->service->generateWhenString($eventReader) + ); + + } + + public function testGenerateWhenStringRecurringFixed(): void { + + // construct l10n return maps + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'time' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '8:00 AM', + $v1 === 'time' && $v2 == (new \DateTime('20240701T090000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'short'] => '9:00 AM', + $v1 === 'date' && $v2 == (new \DateTime('20240713T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 13, 2024' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['On specific dates for the entire day until %1$s', ['July 13, 2024'], 'On specific dates for the entire day until July 13, 2024'], + ['On specific dates between %1$s - %2$s until %3$s', ['8:00 AM', '9:00 AM (America/Toronto)', 'July 13, 2024'], 'On specific dates between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024'], + ]); + + /** test partial day event with every day interval and conclusion*/ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RDATE', '20240703T080000,20240709T080000,20240713T080000'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'On specific dates between 8:00 AM - 9:00 AM (America/Toronto) until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + + /** test entire day event with every day interval and no conclusion*/ + $vCalendar = clone $this->vCalendar2; + $vCalendar->VEVENT[0]->add('RDATE', '20240703T080000,20240709T080000,20240713T080000'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'On specific dates for the entire day until July 13, 2024', + $this->service->generateWhenString($eventReader) + ); + + } + + public function testGenerateOccurringString(): void { + + // construct l10n return(s) + $this->l10n->method('l')->willReturnCallback( + function ($v1, $v2, $v3) { + return match (true) { + $v1 === 'date' && $v2 == (new \DateTime('20240701T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 1, 2024', + $v1 === 'date' && $v2 == (new \DateTime('20240703T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 3, 2024', + $v1 === 'date' && $v2 == (new \DateTime('20240705T080000', (new \DateTimeZone('America/Toronto')))) && $v3 == ['width' => 'long'] => 'July 5, 2024' + }; + } + ); + $this->l10n->method('t')->willReturnMap([ + ['In a %1$s on %2$s', ['day', 'July 1, 2024'], 'In a day on July 1, 2024'], + ['In a %1$s on %2$s then on %3$s', ['day', 'July 1, 2024', 'July 3, 2024'], 'In a day on July 1, 2024 then on July 3, 2024'], + ['In a %1$s on %2$s then on %3$s and %4$s', ['day', 'July 1, 2024', 'July 3, 2024', 'July 5, 2024'], 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024'], + ['In %1$s %2$s on %3$s', [2, 'days', 'July 1, 2024'], 'In 2 days on July 1, 2024'], + ['In %1$s %2$s on %3$s then on %4$s', [2, 'days', 'July 1, 2024', 'July 3, 2024'], 'In 2 days on July 1, 2024 then on July 3, 2024'], + ['In %1$s %2$s on %3$s then on %4$s and %5$s', [2, 'days', 'July 1, 2024', 'July 3, 2024', 'July 5, 2024'], 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024'], + ]); + + // construct time factory return(s) + $this->timeFactory->method('getDateTime')->willReturnOnConsecutiveCalls( + (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240629T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + (new \DateTime('20240628T170000', (new \DateTimeZone('America/Toronto')))), + ); + + /** test patrial day recurring event in 1 day with single occurance remaining */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=1'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a day on July 1, 2024', + $this->service->generateOccurringString($eventReader) + ); + + /** test patrial day recurring event in 1 day with two occurances remaining */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=2'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a day on July 1, 2024 then on July 3, 2024', + $this->service->generateOccurringString($eventReader) + ); + + /** test patrial day recurring event in 1 day with three occurances remaining */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=3'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In a day on July 1, 2024 then on July 3, 2024 and July 5, 2024', + $this->service->generateOccurringString($eventReader) + ); + + /** test patrial day recurring event in 2 days with single occurance remaining */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=1'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 days on July 1, 2024', + $this->service->generateOccurringString($eventReader) + ); + + /** test patrial day recurring event in 2 days with two occurances remaining */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=2'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 days on July 1, 2024 then on July 3, 2024', + $this->service->generateOccurringString($eventReader) + ); + + /** test patrial day recurring event in 2 days with three occurances remaining */ + $vCalendar = clone $this->vCalendar1a; + $vCalendar->VEVENT[0]->add('RRULE', 'FREQ=DAILY;INTERVAL=2;COUNT=3'); + // construct event reader + $eventReader = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue()); + // test output + $this->assertEquals( + 'In 2 days on July 1, 2024 then on July 3, 2024 and July 5, 2024', + $this->service->generateOccurringString($eventReader) + ); + } + } diff --git a/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php b/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php index 9a077e35076..7264119f8c6 100644 --- a/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php +++ b/apps/dav/tests/unit/Files/Sharing/FilesDropPluginTest.php @@ -7,6 +7,8 @@ namespace OCA\DAV\Tests\Files\Sharing; use OC\Files\View; use OCA\DAV\Files\Sharing\FilesDropPlugin; +use OCP\Share\IAttributes; +use OCP\Share\IShare; use Sabre\DAV\Exception\MethodNotAllowed; use Sabre\DAV\Server; use Sabre\HTTP\RequestInterface; @@ -18,6 +20,9 @@ class FilesDropPluginTest extends TestCase { /** @var View|\PHPUnit\Framework\MockObject\MockObject */ private $view; + /** @var IShare|\PHPUnit\Framework\MockObject\MockObject */ + private $share; + /** @var Server|\PHPUnit\Framework\MockObject\MockObject */ private $server; @@ -34,6 +39,7 @@ class FilesDropPluginTest extends TestCase { parent::setUp(); $this->view = $this->createMock(View::class); + $this->share = $this->createMock(IShare::class); $this->server = $this->createMock(Server::class); $this->plugin = new FilesDropPlugin(); @@ -42,6 +48,11 @@ class FilesDropPluginTest extends TestCase { $this->response->expects($this->never()) ->method($this->anything()); + + $attributes = $this->createMock(IAttributes::class); + $this->share->expects($this->any()) + ->method('getAttributes') + ->willReturn($attributes); } public function testInitialize(): void { @@ -69,6 +80,7 @@ class FilesDropPluginTest extends TestCase { public function testValid(): void { $this->plugin->enable(); $this->plugin->setView($this->view); + $this->plugin->setShare($this->share); $this->request->method('getMethod') ->willReturn('PUT'); @@ -93,6 +105,7 @@ class FilesDropPluginTest extends TestCase { public function testFileAlreadyExistsValid(): void { $this->plugin->enable(); $this->plugin->setView($this->view); + $this->plugin->setShare($this->share); $this->request->method('getMethod') ->willReturn('PUT'); @@ -122,6 +135,7 @@ class FilesDropPluginTest extends TestCase { public function testNoMKCOL(): void { $this->plugin->enable(); $this->plugin->setView($this->view); + $this->plugin->setShare($this->share); $this->request->method('getMethod') ->willReturn('MKCOL'); @@ -134,6 +148,7 @@ class FilesDropPluginTest extends TestCase { public function testNoSubdirPut(): void { $this->plugin->enable(); $this->plugin->setView($this->view); + $this->plugin->setShare($this->share); $this->request->method('getMethod') ->willReturn('PUT'); diff --git a/apps/federatedfilesharing/l10n/pt_PT.js b/apps/federatedfilesharing/l10n/pt_PT.js index b75ab6d81e0..b2c987030a0 100644 --- a/apps/federatedfilesharing/l10n/pt_PT.js +++ b/apps/federatedfilesharing/l10n/pt_PT.js @@ -9,8 +9,8 @@ OC.L10N.register( "File is already shared with %s" : "O ficheiro já foi partilhado com %s", "Could not find share" : "Não foi possível encontrar partilha", "Federated sharing" : "Partilha Federada", - "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Recebeu {partilha} como uma partilha remota de {utilizador} (em nome de {behalf})", - "You received {share} as a remote share from {user}" : "Recebeu {partilha} como uma partilha remota de {utilizador}", + "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Recebeu {share} como uma partilha remota de {user} (em nome de {behalf})", + "You received {share} as a remote share from {user}" : "Recebeu {share} como uma partilha remota de {user}", "Accept" : "Aceitar", "Decline" : "Recusar", "Federated Cloud Sharing" : "Partilha de Nuvem Federada", diff --git a/apps/federatedfilesharing/l10n/pt_PT.json b/apps/federatedfilesharing/l10n/pt_PT.json index 5a411d6d14b..5b32141d8b8 100644 --- a/apps/federatedfilesharing/l10n/pt_PT.json +++ b/apps/federatedfilesharing/l10n/pt_PT.json @@ -7,8 +7,8 @@ "File is already shared with %s" : "O ficheiro já foi partilhado com %s", "Could not find share" : "Não foi possível encontrar partilha", "Federated sharing" : "Partilha Federada", - "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Recebeu {partilha} como uma partilha remota de {utilizador} (em nome de {behalf})", - "You received {share} as a remote share from {user}" : "Recebeu {partilha} como uma partilha remota de {utilizador}", + "You received {share} as a remote share from {user} (on behalf of {behalf})" : "Recebeu {share} como uma partilha remota de {user} (em nome de {behalf})", + "You received {share} as a remote share from {user}" : "Recebeu {share} como uma partilha remota de {user}", "Accept" : "Aceitar", "Decline" : "Recusar", "Federated Cloud Sharing" : "Partilha de Nuvem Federada", diff --git a/apps/files/appinfo/info.xml b/apps/files/appinfo/info.xml index 4a920b499ce..f3da2057f65 100644 --- a/apps/files/appinfo/info.xml +++ b/apps/files/appinfo/info.xml @@ -51,6 +51,10 @@ OCA\Files\Command\Object\Put + + OCA\Files\Settings\PersonalSettings + + OCA\Files\Activity\Settings\FavoriteAction @@ -77,8 +81,4 @@ - - OCA\Files\Settings\PersonalSettings - - diff --git a/apps/files/composer/composer/autoload_classmap.php b/apps/files/composer/composer/autoload_classmap.php index f7880847ac0..68cdabb3dcd 100644 --- a/apps/files/composer/composer/autoload_classmap.php +++ b/apps/files/composer/composer/autoload_classmap.php @@ -58,6 +58,9 @@ return array( 'OCA\\Files\\Event\\LoadSidebar' => $baseDir . '/../lib/Event/LoadSidebar.php', 'OCA\\Files\\Exception\\TransferOwnershipException' => $baseDir . '/../lib/Exception/TransferOwnershipException.php', 'OCA\\Files\\Helper' => $baseDir . '/../lib/Helper.php', + 'OCA\\Files\\Listener\\DeclarativeSettingsGetValueEventListener' => $baseDir . '/../lib/Listener/DeclarativeSettingsGetValueEventListener.php', + 'OCA\\Files\\Listener\\DeclarativeSettingsRegisterFormEventListener' => $baseDir . '/../lib/Listener/DeclarativeSettingsRegisterFormEventListener.php', + 'OCA\\Files\\Listener\\DeclarativeSettingsSetValueEventListener' => $baseDir . '/../lib/Listener/DeclarativeSettingsSetValueEventListener.php', 'OCA\\Files\\Listener\\LoadSearchPluginsListener' => $baseDir . '/../lib/Listener/LoadSearchPluginsListener.php', 'OCA\\Files\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php', 'OCA\\Files\\Listener\\RenderReferenceEventListener' => $baseDir . '/../lib/Listener/RenderReferenceEventListener.php', @@ -70,6 +73,7 @@ return array( 'OCA\\Files\\Service\\DirectEditingService' => $baseDir . '/../lib/Service/DirectEditingService.php', 'OCA\\Files\\Service\\LivePhotosService' => $baseDir . '/../lib/Service/LivePhotosService.php', 'OCA\\Files\\Service\\OwnershipTransferService' => $baseDir . '/../lib/Service/OwnershipTransferService.php', + 'OCA\\Files\\Service\\SettingsService' => $baseDir . '/../lib/Service/SettingsService.php', 'OCA\\Files\\Service\\TagService' => $baseDir . '/../lib/Service/TagService.php', 'OCA\\Files\\Service\\UserConfig' => $baseDir . '/../lib/Service/UserConfig.php', 'OCA\\Files\\Service\\ViewConfig' => $baseDir . '/../lib/Service/ViewConfig.php', diff --git a/apps/files/composer/composer/autoload_static.php b/apps/files/composer/composer/autoload_static.php index 9ba311f2776..ca88e773e4a 100644 --- a/apps/files/composer/composer/autoload_static.php +++ b/apps/files/composer/composer/autoload_static.php @@ -73,6 +73,9 @@ class ComposerStaticInitFiles 'OCA\\Files\\Event\\LoadSidebar' => __DIR__ . '/..' . '/../lib/Event/LoadSidebar.php', 'OCA\\Files\\Exception\\TransferOwnershipException' => __DIR__ . '/..' . '/../lib/Exception/TransferOwnershipException.php', 'OCA\\Files\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php', + 'OCA\\Files\\Listener\\DeclarativeSettingsGetValueEventListener' => __DIR__ . '/..' . '/../lib/Listener/DeclarativeSettingsGetValueEventListener.php', + 'OCA\\Files\\Listener\\DeclarativeSettingsRegisterFormEventListener' => __DIR__ . '/..' . '/../lib/Listener/DeclarativeSettingsRegisterFormEventListener.php', + 'OCA\\Files\\Listener\\DeclarativeSettingsSetValueEventListener' => __DIR__ . '/..' . '/../lib/Listener/DeclarativeSettingsSetValueEventListener.php', 'OCA\\Files\\Listener\\LoadSearchPluginsListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSearchPluginsListener.php', 'OCA\\Files\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php', 'OCA\\Files\\Listener\\RenderReferenceEventListener' => __DIR__ . '/..' . '/../lib/Listener/RenderReferenceEventListener.php', @@ -85,6 +88,7 @@ class ComposerStaticInitFiles 'OCA\\Files\\Service\\DirectEditingService' => __DIR__ . '/..' . '/../lib/Service/DirectEditingService.php', 'OCA\\Files\\Service\\LivePhotosService' => __DIR__ . '/..' . '/../lib/Service/LivePhotosService.php', 'OCA\\Files\\Service\\OwnershipTransferService' => __DIR__ . '/..' . '/../lib/Service/OwnershipTransferService.php', + 'OCA\\Files\\Service\\SettingsService' => __DIR__ . '/..' . '/../lib/Service/SettingsService.php', 'OCA\\Files\\Service\\TagService' => __DIR__ . '/..' . '/../lib/Service/TagService.php', 'OCA\\Files\\Service\\UserConfig' => __DIR__ . '/..' . '/../lib/Service/UserConfig.php', 'OCA\\Files\\Service\\ViewConfig' => __DIR__ . '/..' . '/../lib/Service/ViewConfig.php', diff --git a/apps/files/l10n/ar.js b/apps/files/l10n/ar.js index 59656d85898..37e7e8d0537 100644 --- a/apps/files/l10n/ar.js +++ b/apps/files/l10n/ar.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "تم تغيير ملف أو مجلد", "A favorite file or folder has been changed" : "ملف في المفضلة تم تم تغييره", "Upload (max. %s)" : "الرفع ( حد اقصى. %s ) ", + "Files compatibility" : "توافقية الملفات", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "السماح بتقييد أسماء الملفات لضمان إمكانية مزامنة الملفات مع جميع العملاء. بشكل افتراضي، يُسمح بجميع أسماء الملفات الصالحة على POSIX (مثل Linux أو macOS).", + "Enforce Windows compatibility" : "فرض التوافق مع وندوز", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "سيؤدي هذا إلى حظر أسماء الملفات غير الصالحة على أنظمة Windows؛ مثل استخدام الأسماء المحجوزة أو الأحرف الخاصة. لكن هذا لن يفرض توافق حساسية الحالة.", "Accept" : "قبول", "Reject" : "رفض", "Incoming ownership transfer from {user}" : "تم تحويل ملكية الملف إليك من قبل {user}", diff --git a/apps/files/l10n/ar.json b/apps/files/l10n/ar.json index a8097c43e5f..6d48f589cf6 100644 --- a/apps/files/l10n/ar.json +++ b/apps/files/l10n/ar.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "تم تغيير ملف أو مجلد", "A favorite file or folder has been changed" : "ملف في المفضلة تم تم تغييره", "Upload (max. %s)" : "الرفع ( حد اقصى. %s ) ", + "Files compatibility" : "توافقية الملفات", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "السماح بتقييد أسماء الملفات لضمان إمكانية مزامنة الملفات مع جميع العملاء. بشكل افتراضي، يُسمح بجميع أسماء الملفات الصالحة على POSIX (مثل Linux أو macOS).", + "Enforce Windows compatibility" : "فرض التوافق مع وندوز", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "سيؤدي هذا إلى حظر أسماء الملفات غير الصالحة على أنظمة Windows؛ مثل استخدام الأسماء المحجوزة أو الأحرف الخاصة. لكن هذا لن يفرض توافق حساسية الحالة.", "Accept" : "قبول", "Reject" : "رفض", "Incoming ownership transfer from {user}" : "تم تحويل ملكية الملف إليك من قبل {user}", diff --git a/apps/files/l10n/ast.js b/apps/files/l10n/ast.js index 82e81d6b966..023a3b81ef4 100644 --- a/apps/files/l10n/ast.js +++ b/apps/files/l10n/ast.js @@ -161,6 +161,8 @@ OC.L10N.register( "Reject" : "Refugar", "Incoming ownership transfer from {user}" : "Recibióse una tresferencia de propiedá de: {user}", "Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "¿Quies aceptar «{path}»?\n\nNota: el procesu de tresferencia pue tardar hasta 1 hora tres aceptalu", + "Ownership transfer denied" : "Negóse la tresferencia de la propiedá", + "Your ownership transfer of {path} was denied by {user}." : "{user} negó la to tresferencia de la propiedá de: {path}", "Ownership transfer failed" : "El procesu de tresferencia falló", "Your ownership transfer of {path} to {user} failed." : "El procesu de tresferencia de «{path}» a «{user}» falló", "The ownership transfer of {path} from {user} failed." : "El procesu de tresferencia de «{path}» dende «{user}» falló", @@ -184,6 +186,7 @@ OC.L10N.register( "Folder name" : "Nome de la carpeta", "This node is unavailable" : "Esti noyu nun ta disponible", "Download file {name}" : "Baxar el ficheru «{name}»", + "Invalid file name" : "El nome del ficheru ye inválidu", "\"{name}\" is not an allowed filetype." : "«{name}» nun ye un tipu de ficheru permíu", "{newName} already exists." : "«{newName}» yá esiste.", "\"{char}\" is not allowed inside a file name." : "El caráuter «{char}» nun ta permitíu nel nome del ficheru.", @@ -197,6 +200,7 @@ OC.L10N.register( "Toggle selection for all files and folders" : "Alternar la seleición de tolos ficheros y toles carpetes", "\"{displayName}\" failed on some elements " : "«{displauName}» falló con dalgún elementu", "\"{displayName}\" batch action executed successfully" : "L'aición per llotes «{displayName}» executóse correutamente", + "{count} selected" : "{count} na seleición", "List of files and folders." : "Una llista de ficheros y carpetes.", "Column headers with buttons are sortable." : "Les testeres de les columnes con botones puen ordenase.", "This list is not fully rendered for performance reasons. The files will be rendered as you navigate through the list." : "Esta llista nun ta completa por motivos de rindimientu. Los ficheros van apaecer a midida que navegues pela llista.", @@ -232,6 +236,7 @@ OC.L10N.register( "Shared" : "Compartío", "Switch to list view" : "Cambiar a la vista de llista", "Switch to grid view" : "Cambiar a la vista de rexáu", + "Upload was cancelled by user" : "L'usuariu anuló la xuba", "Error during upload: {message}" : "Hebo un error demientres la xuba: {messages}", "Error during upload, status code {status}" : "Hebo un error demientres la xuba. Cödigu d'estáu: {status}", "Unknown error during upload" : "Hebo un error desconocíu demientres la xuba", diff --git a/apps/files/l10n/ast.json b/apps/files/l10n/ast.json index 0190347e4af..6a69a0d5657 100644 --- a/apps/files/l10n/ast.json +++ b/apps/files/l10n/ast.json @@ -159,6 +159,8 @@ "Reject" : "Refugar", "Incoming ownership transfer from {user}" : "Recibióse una tresferencia de propiedá de: {user}", "Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "¿Quies aceptar «{path}»?\n\nNota: el procesu de tresferencia pue tardar hasta 1 hora tres aceptalu", + "Ownership transfer denied" : "Negóse la tresferencia de la propiedá", + "Your ownership transfer of {path} was denied by {user}." : "{user} negó la to tresferencia de la propiedá de: {path}", "Ownership transfer failed" : "El procesu de tresferencia falló", "Your ownership transfer of {path} to {user} failed." : "El procesu de tresferencia de «{path}» a «{user}» falló", "The ownership transfer of {path} from {user} failed." : "El procesu de tresferencia de «{path}» dende «{user}» falló", @@ -182,6 +184,7 @@ "Folder name" : "Nome de la carpeta", "This node is unavailable" : "Esti noyu nun ta disponible", "Download file {name}" : "Baxar el ficheru «{name}»", + "Invalid file name" : "El nome del ficheru ye inválidu", "\"{name}\" is not an allowed filetype." : "«{name}» nun ye un tipu de ficheru permíu", "{newName} already exists." : "«{newName}» yá esiste.", "\"{char}\" is not allowed inside a file name." : "El caráuter «{char}» nun ta permitíu nel nome del ficheru.", @@ -195,6 +198,7 @@ "Toggle selection for all files and folders" : "Alternar la seleición de tolos ficheros y toles carpetes", "\"{displayName}\" failed on some elements " : "«{displauName}» falló con dalgún elementu", "\"{displayName}\" batch action executed successfully" : "L'aición per llotes «{displayName}» executóse correutamente", + "{count} selected" : "{count} na seleición", "List of files and folders." : "Una llista de ficheros y carpetes.", "Column headers with buttons are sortable." : "Les testeres de les columnes con botones puen ordenase.", "This list is not fully rendered for performance reasons. The files will be rendered as you navigate through the list." : "Esta llista nun ta completa por motivos de rindimientu. Los ficheros van apaecer a midida que navegues pela llista.", @@ -230,6 +234,7 @@ "Shared" : "Compartío", "Switch to list view" : "Cambiar a la vista de llista", "Switch to grid view" : "Cambiar a la vista de rexáu", + "Upload was cancelled by user" : "L'usuariu anuló la xuba", "Error during upload: {message}" : "Hebo un error demientres la xuba: {messages}", "Error during upload, status code {status}" : "Hebo un error demientres la xuba. Cödigu d'estáu: {status}", "Unknown error during upload" : "Hebo un error desconocíu demientres la xuba", diff --git a/apps/files/l10n/da.js b/apps/files/l10n/da.js index 65ff025ee7d..5a94a1bf5ac 100644 --- a/apps/files/l10n/da.js +++ b/apps/files/l10n/da.js @@ -53,7 +53,7 @@ OC.L10N.register( "This operation is forbidden" : "Denne operation er forbudt", "This directory is unavailable, please check the logs or contact the administrator" : "Denne mappe er utilgængelig, tjek venligst loggene eller kontakt administratoren", "Storage is temporarily not available" : "Lagerplads er midlertidigt ikke tilgængeligt", - "Could not move \"{file}\", target exists" : "Kunne ikke flytte \"{file}\" - der findes allerede en fil med dette navn", + "Could not move \"{file}\", target exists" : "Kunne ikke flytte \"{file}\" - filen findes allerede", "Could not move \"{file}\"" : "Kunne ikke flytte \"{file}\"", "copy" : "kopiér", "Could not copy \"{file}\", target exists" : "Kunne ikke kopiere \"{file}\" - der findes allerede en fil med dette navn", @@ -229,7 +229,7 @@ OC.L10N.register( "Choose {file}" : "Vælg {file}", "Loading current folder" : "Indlæser aktuelle mappe", "No files in here" : "Her er ingen filer", - "Upload some content or sync with your devices!" : "Overfør indhold eller synkronisér med dine enheder!", + "Upload some content or sync with your devices!" : "Upload indhold eller synkronisér med dine enheder!", "Go to the previous folder" : "Gå til forrige mappe", "Go back" : "Gå tilbage", "Share" : "Del", diff --git a/apps/files/l10n/da.json b/apps/files/l10n/da.json index 838c1b76edd..28c27b88691 100644 --- a/apps/files/l10n/da.json +++ b/apps/files/l10n/da.json @@ -51,7 +51,7 @@ "This operation is forbidden" : "Denne operation er forbudt", "This directory is unavailable, please check the logs or contact the administrator" : "Denne mappe er utilgængelig, tjek venligst loggene eller kontakt administratoren", "Storage is temporarily not available" : "Lagerplads er midlertidigt ikke tilgængeligt", - "Could not move \"{file}\", target exists" : "Kunne ikke flytte \"{file}\" - der findes allerede en fil med dette navn", + "Could not move \"{file}\", target exists" : "Kunne ikke flytte \"{file}\" - filen findes allerede", "Could not move \"{file}\"" : "Kunne ikke flytte \"{file}\"", "copy" : "kopiér", "Could not copy \"{file}\", target exists" : "Kunne ikke kopiere \"{file}\" - der findes allerede en fil med dette navn", @@ -227,7 +227,7 @@ "Choose {file}" : "Vælg {file}", "Loading current folder" : "Indlæser aktuelle mappe", "No files in here" : "Her er ingen filer", - "Upload some content or sync with your devices!" : "Overfør indhold eller synkronisér med dine enheder!", + "Upload some content or sync with your devices!" : "Upload indhold eller synkronisér med dine enheder!", "Go to the previous folder" : "Gå til forrige mappe", "Go back" : "Gå tilbage", "Share" : "Del", diff --git a/apps/files/l10n/de_DE.js b/apps/files/l10n/de_DE.js index 5ce50eaa33a..f5fcf8287c7 100644 --- a/apps/files/l10n/de_DE.js +++ b/apps/files/l10n/de_DE.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "Eine Datei oder ein Ordner wurde geändert", "A favorite file or folder has been changed" : "Eine favorisierte Datei oder ein Ordner wurde geändert", "Upload (max. %s)" : "Hochladen (max. %s)", + "Files compatibility" : "Dateikompatibilität", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Ermöglicht die Einschränkung von Dateinamen, um sicherzustellen, dass Dateien mit allen Clients synchronisiert werden können. Standardmäßig sind alle unter POSIX (z. B. Linux oder macOS) gültigen Dateinamen zulässig.", + "Enforce Windows compatibility" : "Windows-Kompatibilität erzwingen", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Dadurch werden Dateinamen blockiert, die auf Windows-Systemen unzulässig, z. B. reservierte Namen oder Sonderzeichen. Die Kompatibilität der Groß-/Kleinschreibung wird dadurch jedoch nicht erzwungen.", "Accept" : "Akzeptieren", "Reject" : "Ablehnen", "Incoming ownership transfer from {user}" : "Eingehende Besitzübertragung von {user}", diff --git a/apps/files/l10n/de_DE.json b/apps/files/l10n/de_DE.json index 0f05d3a6c33..148d37a9144 100644 --- a/apps/files/l10n/de_DE.json +++ b/apps/files/l10n/de_DE.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "Eine Datei oder ein Ordner wurde geändert", "A favorite file or folder has been changed" : "Eine favorisierte Datei oder ein Ordner wurde geändert", "Upload (max. %s)" : "Hochladen (max. %s)", + "Files compatibility" : "Dateikompatibilität", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Ermöglicht die Einschränkung von Dateinamen, um sicherzustellen, dass Dateien mit allen Clients synchronisiert werden können. Standardmäßig sind alle unter POSIX (z. B. Linux oder macOS) gültigen Dateinamen zulässig.", + "Enforce Windows compatibility" : "Windows-Kompatibilität erzwingen", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Dadurch werden Dateinamen blockiert, die auf Windows-Systemen unzulässig, z. B. reservierte Namen oder Sonderzeichen. Die Kompatibilität der Groß-/Kleinschreibung wird dadurch jedoch nicht erzwungen.", "Accept" : "Akzeptieren", "Reject" : "Ablehnen", "Incoming ownership transfer from {user}" : "Eingehende Besitzübertragung von {user}", diff --git a/apps/files/l10n/en_GB.js b/apps/files/l10n/en_GB.js index 452e5522580..85f81513f00 100644 --- a/apps/files/l10n/en_GB.js +++ b/apps/files/l10n/en_GB.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "A file or folder has been changed", "A favorite file or folder has been changed" : "A favourite file or folder has been changed", "Upload (max. %s)" : "Upload (max. %s)", + "Files compatibility" : "Files compatibility", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed.", + "Enforce Windows compatibility" : "Enforce Windows compatibility", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity.", "Accept" : "Accept", "Reject" : "Reject", "Incoming ownership transfer from {user}" : "Incoming ownership transfer from {user}", diff --git a/apps/files/l10n/en_GB.json b/apps/files/l10n/en_GB.json index dd25c7c1790..e60e631d098 100644 --- a/apps/files/l10n/en_GB.json +++ b/apps/files/l10n/en_GB.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "A file or folder has been changed", "A favorite file or folder has been changed" : "A favourite file or folder has been changed", "Upload (max. %s)" : "Upload (max. %s)", + "Files compatibility" : "Files compatibility", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed.", + "Enforce Windows compatibility" : "Enforce Windows compatibility", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity.", "Accept" : "Accept", "Reject" : "Reject", "Incoming ownership transfer from {user}" : "Incoming ownership transfer from {user}", diff --git a/apps/files/l10n/es_MX.js b/apps/files/l10n/es_MX.js index 9ad8c4d6ced..5ed189991a3 100644 --- a/apps/files/l10n/es_MX.js +++ b/apps/files/l10n/es_MX.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "Un archivo o carpeta ha sido cambiado", "A favorite file or folder has been changed" : "Un archivo o carpeta favorito ha sido cambiado", "Upload (max. %s)" : "Cargar (max. %s)", + "Files compatibility" : "Compatibilidad de archivos", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Permitir restringir los nombres de archivos para asegurar que los archivos se puedan sincronizar con todos los clientes. Por defecto, se permiten todos los nombres de archivos válidos en POSIX (por ejemplo, Linux o macOS).", + "Enforce Windows compatibility" : "Imponer la compatibilidad de Windows", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Esto bloqueará los nombres de archivos inválidos en sistemas Windows, tales como usar nombres reservados o caracteres especiales. Pero no impondrá la compatibilidad del uso de mayúsculas y minúsculas.", "Accept" : "Aceptar", "Reject" : "Rechazar", "Incoming ownership transfer from {user}" : "Solicitud de transferencia de propiedad entrante de {user}", diff --git a/apps/files/l10n/es_MX.json b/apps/files/l10n/es_MX.json index 55fb7978b5f..d92831dec3d 100644 --- a/apps/files/l10n/es_MX.json +++ b/apps/files/l10n/es_MX.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "Un archivo o carpeta ha sido cambiado", "A favorite file or folder has been changed" : "Un archivo o carpeta favorito ha sido cambiado", "Upload (max. %s)" : "Cargar (max. %s)", + "Files compatibility" : "Compatibilidad de archivos", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Permitir restringir los nombres de archivos para asegurar que los archivos se puedan sincronizar con todos los clientes. Por defecto, se permiten todos los nombres de archivos válidos en POSIX (por ejemplo, Linux o macOS).", + "Enforce Windows compatibility" : "Imponer la compatibilidad de Windows", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Esto bloqueará los nombres de archivos inválidos en sistemas Windows, tales como usar nombres reservados o caracteres especiales. Pero no impondrá la compatibilidad del uso de mayúsculas y minúsculas.", "Accept" : "Aceptar", "Reject" : "Rechazar", "Incoming ownership transfer from {user}" : "Solicitud de transferencia de propiedad entrante de {user}", diff --git a/apps/files/l10n/ga.js b/apps/files/l10n/ga.js index 1cbe668b99d..b95e2a24e9a 100644 --- a/apps/files/l10n/ga.js +++ b/apps/files/l10n/ga.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "Athraíodhcomhad nó fillteán", "A favorite file or folder has been changed" : "Athraíodhcomhad nó fillteán is fearr leat", "Upload (max. %s)" : "Uaslódáil (%s ar a mhéad)", + "Files compatibility" : "Comhoiriúnacht comhaid", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Ceadaigh comhaid a shrianadh lena chinntiú gur féidir comhaid a shioncronú le gach cliant. De réir réamhshocraithe ceadaítear gach comhadainm atá bailí ar POSIX (m.sh. Linux nó macOS).", + "Enforce Windows compatibility" : "Comhoiriúnacht Windows a fhorfheidhmiú", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Cuirfidh sé seo bac ar ainmneacha comhaid nach bhfuil bailí ar chórais Windows, ar nós ainmneacha forchoimeádta nó carachtair speisialta a úsáid. Ach ní chuirfidh sé seo i bhfeidhm comhoiriúnacht íogaireacht cáis.", "Accept" : "Glac", "Reject" : "Diúltaigh", "Incoming ownership transfer from {user}" : "Aistriú úinéireachta isteach ó {user}", diff --git a/apps/files/l10n/ga.json b/apps/files/l10n/ga.json index 6dce210b293..05f66c92f4a 100644 --- a/apps/files/l10n/ga.json +++ b/apps/files/l10n/ga.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "Athraíodhcomhad nó fillteán", "A favorite file or folder has been changed" : "Athraíodhcomhad nó fillteán is fearr leat", "Upload (max. %s)" : "Uaslódáil (%s ar a mhéad)", + "Files compatibility" : "Comhoiriúnacht comhaid", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Ceadaigh comhaid a shrianadh lena chinntiú gur féidir comhaid a shioncronú le gach cliant. De réir réamhshocraithe ceadaítear gach comhadainm atá bailí ar POSIX (m.sh. Linux nó macOS).", + "Enforce Windows compatibility" : "Comhoiriúnacht Windows a fhorfheidhmiú", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Cuirfidh sé seo bac ar ainmneacha comhaid nach bhfuil bailí ar chórais Windows, ar nós ainmneacha forchoimeádta nó carachtair speisialta a úsáid. Ach ní chuirfidh sé seo i bhfeidhm comhoiriúnacht íogaireacht cáis.", "Accept" : "Glac", "Reject" : "Diúltaigh", "Incoming ownership transfer from {user}" : "Aistriú úinéireachta isteach ó {user}", diff --git a/apps/files/l10n/gl.js b/apps/files/l10n/gl.js index a3732b3efbd..258d0b23334 100644 --- a/apps/files/l10n/gl.js +++ b/apps/files/l10n/gl.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "Cambiouse un ficheiro ou cartafol", "A favorite file or folder has been changed" : "Cambiouse un ficheiro ou cartafol favorito", "Upload (max. %s)" : "Envío (máx. %s)", + "Files compatibility" : "Compatibilidade de ficheiros", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Permitir restrinxir os nomes de ficheiros para garantir que os ficheiros se poidan sincronizar con todos os clientes. De xeito predeterminado, permítense todos os nomes de ficheiro válidos en POSIX (p. ex., Linux ou macOS).", + "Enforce Windows compatibility" : "Forzar a compatibilidade con Windows", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Isto bloqueará os nomes de ficheiros non válidos en sistemas Windows, coma o uso de nomes reservados ou caracteres especiais. Porén, isto non forzará á compatibilidade da distinción entre maiúsculas e minúsculas.", "Accept" : "Aceptar", "Reject" : "Rexeitar", "Incoming ownership transfer from {user}" : "Transferencia da propiedade entrante de {user}", diff --git a/apps/files/l10n/gl.json b/apps/files/l10n/gl.json index 54a00520bdf..d6f9cbed32a 100644 --- a/apps/files/l10n/gl.json +++ b/apps/files/l10n/gl.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "Cambiouse un ficheiro ou cartafol", "A favorite file or folder has been changed" : "Cambiouse un ficheiro ou cartafol favorito", "Upload (max. %s)" : "Envío (máx. %s)", + "Files compatibility" : "Compatibilidade de ficheiros", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Permitir restrinxir os nomes de ficheiros para garantir que os ficheiros se poidan sincronizar con todos os clientes. De xeito predeterminado, permítense todos os nomes de ficheiro válidos en POSIX (p. ex., Linux ou macOS).", + "Enforce Windows compatibility" : "Forzar a compatibilidade con Windows", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Isto bloqueará os nomes de ficheiros non válidos en sistemas Windows, coma o uso de nomes reservados ou caracteres especiais. Porén, isto non forzará á compatibilidade da distinción entre maiúsculas e minúsculas.", "Accept" : "Aceptar", "Reject" : "Rexeitar", "Incoming ownership transfer from {user}" : "Transferencia da propiedade entrante de {user}", diff --git a/apps/files/l10n/it.js b/apps/files/l10n/it.js index f1f1b00e079..1df6693d214 100644 --- a/apps/files/l10n/it.js +++ b/apps/files/l10n/it.js @@ -161,6 +161,8 @@ OC.L10N.register( "Reject" : "Rifiuta", "Incoming ownership transfer from {user}" : "Trasferimento di proprietà in ingresso da {user}", "Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Vuoi accettare {path}?\n\nNota: il processo di trasferimento dopo l'accettazione potrebbe richiedere fino a un'ora.", + "Ownership transfer denied" : "Trasferimento di proprietà negato", + "Your ownership transfer of {path} was denied by {user}." : "Il tuo trasferimento di proprietà di {path} è stato negato da {user}.", "Ownership transfer failed" : "Trasferimento di proprietà non riuscito", "Your ownership transfer of {path} to {user} failed." : "Il tuo trasferimento di proprietà di {path} a {user} non è riuscito.", "The ownership transfer of {path} from {user} failed." : "Il trasferimento di proprietà di {path} da {user} non è riuscito.", @@ -235,6 +237,7 @@ OC.L10N.register( "Shared" : "Condiviso", "Switch to list view" : "Passa alla vista elenco", "Switch to grid view" : "Passa alla vista griglia", + "Upload was cancelled by user" : "Caricamento annullato dall'utente", "Error during upload: {message}" : "Errore durante il caricamento: {message}", "Error during upload, status code {status}" : "Errore durante il caricamento, codice di stato {status}", "Unknown error during upload" : "Errore sconosciuto durante il caricamento", diff --git a/apps/files/l10n/it.json b/apps/files/l10n/it.json index 4a2ec801c64..16b15f61df6 100644 --- a/apps/files/l10n/it.json +++ b/apps/files/l10n/it.json @@ -159,6 +159,8 @@ "Reject" : "Rifiuta", "Incoming ownership transfer from {user}" : "Trasferimento di proprietà in ingresso da {user}", "Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Vuoi accettare {path}?\n\nNota: il processo di trasferimento dopo l'accettazione potrebbe richiedere fino a un'ora.", + "Ownership transfer denied" : "Trasferimento di proprietà negato", + "Your ownership transfer of {path} was denied by {user}." : "Il tuo trasferimento di proprietà di {path} è stato negato da {user}.", "Ownership transfer failed" : "Trasferimento di proprietà non riuscito", "Your ownership transfer of {path} to {user} failed." : "Il tuo trasferimento di proprietà di {path} a {user} non è riuscito.", "The ownership transfer of {path} from {user} failed." : "Il trasferimento di proprietà di {path} da {user} non è riuscito.", @@ -233,6 +235,7 @@ "Shared" : "Condiviso", "Switch to list view" : "Passa alla vista elenco", "Switch to grid view" : "Passa alla vista griglia", + "Upload was cancelled by user" : "Caricamento annullato dall'utente", "Error during upload: {message}" : "Errore durante il caricamento: {message}", "Error during upload, status code {status}" : "Errore durante il caricamento, codice di stato {status}", "Unknown error during upload" : "Errore sconosciuto durante il caricamento", diff --git a/apps/files/l10n/nb.js b/apps/files/l10n/nb.js index af80d835f2c..8f59ee71639 100644 --- a/apps/files/l10n/nb.js +++ b/apps/files/l10n/nb.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "En fil eller mappe ble endret", "A favorite file or folder has been changed" : "En favoritt-fil eller mappe har blitt endret", "Upload (max. %s)" : "Opplasting (maks %s)", + "Files compatibility" : "Kompatibilitet med filer", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Tillat å begrense filnavn for å sikre at filer kan synkroniseres med alle klienter. Som standard er alle filnavn gyldige på POSIX (f.eks. Linux eller macOS) tillatt.", + "Enforce Windows compatibility" : "Håndhev Windows-kompatibilitet", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Dette vil blokkere filnavn som ikke er gyldige på Windows-systemer, for eksempel å bruke reserverte navn eller spesialtegn. Men dette vil ikke håndheve kompatibiliteten til store og små bokstaver.", "Accept" : "Aksepter", "Reject" : "Avvis", "Incoming ownership transfer from {user}" : "Ny eierskapsoverføring fra {user}", diff --git a/apps/files/l10n/nb.json b/apps/files/l10n/nb.json index 6a49c09d4ac..d793c92aeb4 100644 --- a/apps/files/l10n/nb.json +++ b/apps/files/l10n/nb.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "En fil eller mappe ble endret", "A favorite file or folder has been changed" : "En favoritt-fil eller mappe har blitt endret", "Upload (max. %s)" : "Opplasting (maks %s)", + "Files compatibility" : "Kompatibilitet med filer", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Tillat å begrense filnavn for å sikre at filer kan synkroniseres med alle klienter. Som standard er alle filnavn gyldige på POSIX (f.eks. Linux eller macOS) tillatt.", + "Enforce Windows compatibility" : "Håndhev Windows-kompatibilitet", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Dette vil blokkere filnavn som ikke er gyldige på Windows-systemer, for eksempel å bruke reserverte navn eller spesialtegn. Men dette vil ikke håndheve kompatibiliteten til store og små bokstaver.", "Accept" : "Aksepter", "Reject" : "Avvis", "Incoming ownership transfer from {user}" : "Ny eierskapsoverføring fra {user}", diff --git a/apps/files/l10n/ru.js b/apps/files/l10n/ru.js index 447e2f03b52..1545adf32ef 100644 --- a/apps/files/l10n/ru.js +++ b/apps/files/l10n/ru.js @@ -157,10 +157,16 @@ OC.L10N.register( "A file or folder has been changed" : "Изменён файл или каталог", "A favorite file or folder has been changed" : "Изменён файл или папка отмеченные как избранное", "Upload (max. %s)" : "Загрузка (максимум %s)", + "Files compatibility" : "Совместимость файлов", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Разрешить ограничения на имена файлов для обеспечения возможности их синхронизации со всеми клиентами. По умолчанию разрешены все имена файлов, допустимые в POSIX (например, в Linux или macOS).", + "Enforce Windows compatibility" : "Обеспечить совместимость с Windows", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Это позволит блокировать имена файлов, недопустимые в системах Windows, например, использующие зарезервированные имена или специальные символы. Однако это не обеспечит совместимость в части чувствительности к регистру.", "Accept" : "Принять", "Reject" : "Отклонить", "Incoming ownership transfer from {user}" : "Запрос передачи владения от пользователя {user}", "Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Принять владение {path}?\n\nПримечание: процесс переноса может занять до одного часа.", + "Ownership transfer denied" : "Передача владения отклонена", + "Your ownership transfer of {path} was denied by {user}." : "Передача владения {path} отклонена {user}.", "Ownership transfer failed" : "Не удалось передать владение", "Your ownership transfer of {path} to {user} failed." : "Вам не удалось передать владение «{path}» пользователю {user}.", "The ownership transfer of {path} from {user} failed." : "Пользователю {user} не удалось передать владение «{path}».", @@ -168,6 +174,7 @@ OC.L10N.register( "Your ownership transfer of {path} to {user} has completed." : "Завершена передача владения «{path}» от вас пользователю {user}.", "The ownership transfer of {path} from {user} has completed." : "Завершена передача владения «{path}» от пользователя {user}.", "in %s" : "в %s", + "Transferred from %1$s on %2$s" : "Передано от %1$s %2$s", "File Management" : "Управление файлами", "Current directory path" : "Текущий путь к каталогу", "Reload current directory" : "Обновить текущий каталог", @@ -254,7 +261,7 @@ OC.L10N.register( "WebDAV URL" : "Ссылка WebDAV", "Copy to clipboard" : "Копировать в буфер", "Use this address to access your Files via WebDAV" : "Используйте этот адрес для подключения WebDAV", - "If you have enabled 2FA, you must create and use a new app password by clicking here." : "Если вы используете двухфакторную аутентификацию, то нажмите здесь чтобы создать пароль приложения.", + "If you have enabled 2FA, you must create and use a new app password by clicking here." : "Если вы включили двухфакторную аутентификацию, то нажмите здесь, чтобы создать пароль приложения.", "Clipboard is not available" : "Буфер обмена недоступен", "WebDAV URL copied to clipboard" : "Ссылка CalDAV скопирована в буфер обмена", "Unable to change the favourite state of the file" : "Не удалось изменить состояние «избранный» этого файла.", diff --git a/apps/files/l10n/ru.json b/apps/files/l10n/ru.json index 7b78a97096a..bba6bda3303 100644 --- a/apps/files/l10n/ru.json +++ b/apps/files/l10n/ru.json @@ -155,10 +155,16 @@ "A file or folder has been changed" : "Изменён файл или каталог", "A favorite file or folder has been changed" : "Изменён файл или папка отмеченные как избранное", "Upload (max. %s)" : "Загрузка (максимум %s)", + "Files compatibility" : "Совместимость файлов", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Разрешить ограничения на имена файлов для обеспечения возможности их синхронизации со всеми клиентами. По умолчанию разрешены все имена файлов, допустимые в POSIX (например, в Linux или macOS).", + "Enforce Windows compatibility" : "Обеспечить совместимость с Windows", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Это позволит блокировать имена файлов, недопустимые в системах Windows, например, использующие зарезервированные имена или специальные символы. Однако это не обеспечит совместимость в части чувствительности к регистру.", "Accept" : "Принять", "Reject" : "Отклонить", "Incoming ownership transfer from {user}" : "Запрос передачи владения от пользователя {user}", "Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Принять владение {path}?\n\nПримечание: процесс переноса может занять до одного часа.", + "Ownership transfer denied" : "Передача владения отклонена", + "Your ownership transfer of {path} was denied by {user}." : "Передача владения {path} отклонена {user}.", "Ownership transfer failed" : "Не удалось передать владение", "Your ownership transfer of {path} to {user} failed." : "Вам не удалось передать владение «{path}» пользователю {user}.", "The ownership transfer of {path} from {user} failed." : "Пользователю {user} не удалось передать владение «{path}».", @@ -166,6 +172,7 @@ "Your ownership transfer of {path} to {user} has completed." : "Завершена передача владения «{path}» от вас пользователю {user}.", "The ownership transfer of {path} from {user} has completed." : "Завершена передача владения «{path}» от пользователя {user}.", "in %s" : "в %s", + "Transferred from %1$s on %2$s" : "Передано от %1$s %2$s", "File Management" : "Управление файлами", "Current directory path" : "Текущий путь к каталогу", "Reload current directory" : "Обновить текущий каталог", @@ -252,7 +259,7 @@ "WebDAV URL" : "Ссылка WebDAV", "Copy to clipboard" : "Копировать в буфер", "Use this address to access your Files via WebDAV" : "Используйте этот адрес для подключения WebDAV", - "If you have enabled 2FA, you must create and use a new app password by clicking here." : "Если вы используете двухфакторную аутентификацию, то нажмите здесь чтобы создать пароль приложения.", + "If you have enabled 2FA, you must create and use a new app password by clicking here." : "Если вы включили двухфакторную аутентификацию, то нажмите здесь, чтобы создать пароль приложения.", "Clipboard is not available" : "Буфер обмена недоступен", "WebDAV URL copied to clipboard" : "Ссылка CalDAV скопирована в буфер обмена", "Unable to change the favourite state of the file" : "Не удалось изменить состояние «избранный» этого файла.", diff --git a/apps/files/l10n/sl.js b/apps/files/l10n/sl.js index c788159328a..658695bac33 100644 --- a/apps/files/l10n/sl.js +++ b/apps/files/l10n/sl.js @@ -272,6 +272,7 @@ OC.L10N.register( "Templates" : "Predloge", "New template folder" : "Nova mapa predlog", "Some files could not be moved" : "Nekaterih datotek ni mogoče premakniti", + "Files copied successfully" : "Datoteke so uspešno kopirane", "Files moved successfully" : "Datoteke so uspešno premaknjene", "Upload cancelled" : "Pošiljanje je bilo preklicano", "_{folderCount} folder_::_{folderCount} folders_" : ["{folderCount} mapa","{folderCount} mapi","{folderCount} mape","{folderCount} map"], diff --git a/apps/files/l10n/sl.json b/apps/files/l10n/sl.json index 6b092d8427d..aae81446dac 100644 --- a/apps/files/l10n/sl.json +++ b/apps/files/l10n/sl.json @@ -270,6 +270,7 @@ "Templates" : "Predloge", "New template folder" : "Nova mapa predlog", "Some files could not be moved" : "Nekaterih datotek ni mogoče premakniti", + "Files copied successfully" : "Datoteke so uspešno kopirane", "Files moved successfully" : "Datoteke so uspešno premaknjene", "Upload cancelled" : "Pošiljanje je bilo preklicano", "_{folderCount} folder_::_{folderCount} folders_" : ["{folderCount} mapa","{folderCount} mapi","{folderCount} mape","{folderCount} map"], diff --git a/apps/files/l10n/sv.js b/apps/files/l10n/sv.js index 9ed04ab24a8..a66e60f86f9 100644 --- a/apps/files/l10n/sv.js +++ b/apps/files/l10n/sv.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "En ny fil eller mapp har blivit ändrad", "A favorite file or folder has been changed" : "En favorit-fil eller mapp har blivit ändrad", "Upload (max. %s)" : "Ladda upp (högst %s)", + "Files compatibility" : "Filkompatibilitet", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Tillåt att begränsa filnamn för att säkerställa att filer kan synkroniseras med alla klienter. Som standard är alla filnamn som är giltiga på POSIX (t.ex. Linux eller macOS) tillåtna.", + "Enforce Windows compatibility" : "Tvinga Windows-kompatibilitet", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Detta kommer att blockera filnamn som inte är giltiga på Windows-system, som att använda reserverade namn eller specialtecken. Men detta kommer inte att framtvinga kompatibiliteten för skiftlägeskänslighet.", "Accept" : "Acceptera", "Reject" : "Avvisa", "Incoming ownership transfer from {user}" : "Inkommande ägaröverföring från {user}", diff --git a/apps/files/l10n/sv.json b/apps/files/l10n/sv.json index 15abb05b4db..bb0c389d7d2 100644 --- a/apps/files/l10n/sv.json +++ b/apps/files/l10n/sv.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "En ny fil eller mapp har blivit ändrad", "A favorite file or folder has been changed" : "En favorit-fil eller mapp har blivit ändrad", "Upload (max. %s)" : "Ladda upp (högst %s)", + "Files compatibility" : "Filkompatibilitet", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "Tillåt att begränsa filnamn för att säkerställa att filer kan synkroniseras med alla klienter. Som standard är alla filnamn som är giltiga på POSIX (t.ex. Linux eller macOS) tillåtna.", + "Enforce Windows compatibility" : "Tvinga Windows-kompatibilitet", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "Detta kommer att blockera filnamn som inte är giltiga på Windows-system, som att använda reserverade namn eller specialtecken. Men detta kommer inte att framtvinga kompatibiliteten för skiftlägeskänslighet.", "Accept" : "Acceptera", "Reject" : "Avvisa", "Incoming ownership transfer from {user}" : "Inkommande ägaröverföring från {user}", diff --git a/apps/files/l10n/zh_HK.js b/apps/files/l10n/zh_HK.js index f5d4b9fadea..3f5d013cf8a 100644 --- a/apps/files/l10n/zh_HK.js +++ b/apps/files/l10n/zh_HK.js @@ -157,6 +157,10 @@ OC.L10N.register( "A file or folder has been changed" : "檔案或資料夾有所更改", "A favorite file or folder has been changed" : "收藏的檔案或資料夾有所更改", "Upload (max. %s)" : "上傳(上限 %s)", + "Files compatibility" : "檔案兼容性", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "允許限製檔案名稱以確保檔案可以與所有客戶端同步。默認情況下,允許 POSIX(例如 Linux 或 macOS)上有效的所有檔案名稱。", + "Enforce Windows compatibility" : "實施 Windows 兼容性", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "這將阻止在 Windows 系統上無效的檔案名,例如使用保留名稱或特殊字元。但這不會強制區分大小寫的兼容性。", "Accept" : "接受", "Reject" : "拒絕", "Incoming ownership transfer from {user}" : "來自 {user} 的擁有權轉移", diff --git a/apps/files/l10n/zh_HK.json b/apps/files/l10n/zh_HK.json index ce2583d1fbb..62779dcb373 100644 --- a/apps/files/l10n/zh_HK.json +++ b/apps/files/l10n/zh_HK.json @@ -155,6 +155,10 @@ "A file or folder has been changed" : "檔案或資料夾有所更改", "A favorite file or folder has been changed" : "收藏的檔案或資料夾有所更改", "Upload (max. %s)" : "上傳(上限 %s)", + "Files compatibility" : "檔案兼容性", + "Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed." : "允許限製檔案名稱以確保檔案可以與所有客戶端同步。默認情況下,允許 POSIX(例如 Linux 或 macOS)上有效的所有檔案名稱。", + "Enforce Windows compatibility" : "實施 Windows 兼容性", + "This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity." : "這將阻止在 Windows 系統上無效的檔案名,例如使用保留名稱或特殊字元。但這不會強制區分大小寫的兼容性。", "Accept" : "接受", "Reject" : "拒絕", "Incoming ownership transfer from {user}" : "來自 {user} 的擁有權轉移", diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php index 5f57b2e2f34..b4fd04c9fbc 100644 --- a/apps/files/lib/AppInfo/Application.php +++ b/apps/files/lib/AppInfo/Application.php @@ -17,6 +17,9 @@ use OCA\Files\Controller\ApiController; use OCA\Files\DirectEditingCapabilities; use OCA\Files\Event\LoadSearchPlugins; use OCA\Files\Event\LoadSidebar; +use OCA\Files\Listener\DeclarativeSettingsGetValueEventListener; +use OCA\Files\Listener\DeclarativeSettingsRegisterFormEventListener; +use OCA\Files\Listener\DeclarativeSettingsSetValueEventListener; use OCA\Files\Listener\LoadSearchPluginsListener; use OCA\Files\Listener\LoadSidebarListener; use OCA\Files\Listener\RenderReferenceEventListener; @@ -46,6 +49,9 @@ use OCP\ISearch; use OCP\IServerContainer; use OCP\ITagManager; use OCP\IUserSession; +use OCP\Settings\Events\DeclarativeSettingsGetValueEvent; +use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent; +use OCP\Settings\Events\DeclarativeSettingsSetValueEvent; use OCP\Share\IManager as IShareManager; use OCP\Util; use Psr\Container\ContainerInterface; @@ -109,6 +115,9 @@ class Application extends App implements IBootstrap { $context->registerEventListener(BeforeNodeCopiedEvent::class, SyncLivePhotosListener::class); $context->registerEventListener(NodeCopiedEvent::class, SyncLivePhotosListener::class); $context->registerEventListener(LoadSearchPlugins::class, LoadSearchPluginsListener::class); + $context->registerEventListener(DeclarativeSettingsRegisterFormEvent::class, DeclarativeSettingsRegisterFormEventListener::class); + $context->registerEventListener(DeclarativeSettingsGetValueEvent::class, DeclarativeSettingsGetValueEventListener::class); + $context->registerEventListener(DeclarativeSettingsSetValueEvent::class, DeclarativeSettingsSetValueEventListener::class); $context->registerSearchProvider(FilesSearchProvider::class); diff --git a/apps/files/lib/Listener/DeclarativeSettingsGetValueEventListener.php b/apps/files/lib/Listener/DeclarativeSettingsGetValueEventListener.php new file mode 100644 index 00000000000..b1d0ee3a395 --- /dev/null +++ b/apps/files/lib/Listener/DeclarativeSettingsGetValueEventListener.php @@ -0,0 +1,39 @@ + */ +class DeclarativeSettingsGetValueEventListener implements IEventListener { + + public function __construct( + private SettingsService $service, + ) { + } + + public function handle(Event $event): void { + if (!($event instanceof DeclarativeSettingsGetValueEvent)) { + return; + } + + if ($event->getApp() !== Application::APP_ID) { + return; + } + + $event->setValue( + match($event->getFieldId()) { + 'windows_support' => $this->service->hasFilesWindowsSupport(), + } + ); + } +} diff --git a/apps/files/lib/Listener/DeclarativeSettingsRegisterFormEventListener.php b/apps/files/lib/Listener/DeclarativeSettingsRegisterFormEventListener.php new file mode 100644 index 00000000000..51832e89ecb --- /dev/null +++ b/apps/files/lib/Listener/DeclarativeSettingsRegisterFormEventListener.php @@ -0,0 +1,50 @@ + */ +class DeclarativeSettingsRegisterFormEventListener implements IEventListener { + + public function __construct( + private IL10N $l, + ) { + } + + public function handle(Event $event): void { + if (!($event instanceof DeclarativeSettingsRegisterFormEvent)) { + return; + } + + $event->registerSchema(Application::APP_ID, [ + 'id' => 'files-filename-support', + 'priority' => 10, + 'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, + 'section_id' => 'server', + 'storage_type' => DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL, + 'title' => $this->l->t('Files compatibility'), + 'description' => $this->l->t('Allow to restrict filenames to ensure files can be synced with all clients. By default all filenames valid on POSIX (e.g. Linux or macOS) are allowed.'), + + 'fields' => [ + [ + 'id' => 'windows_support', + 'title' => $this->l->t('Enforce Windows compatibility'), + 'description' => $this->l->t('This will block filenames not valid on Windows systems, like using reserved names or special characters. But this will not enforce compatibility of case sensitivity.'), + 'type' => DeclarativeSettingsTypes::CHECKBOX, + 'default' => false, + ], + ], + ]); + } +} diff --git a/apps/files/lib/Listener/DeclarativeSettingsSetValueEventListener.php b/apps/files/lib/Listener/DeclarativeSettingsSetValueEventListener.php new file mode 100644 index 00000000000..43d01563c26 --- /dev/null +++ b/apps/files/lib/Listener/DeclarativeSettingsSetValueEventListener.php @@ -0,0 +1,40 @@ + */ +class DeclarativeSettingsSetValueEventListener implements IEventListener { + + public function __construct( + private SettingsService $service, + ) { + } + + public function handle(Event $event): void { + if (!($event instanceof DeclarativeSettingsSetValueEvent)) { + return; + } + + if ($event->getApp() !== Application::APP_ID) { + return; + } + + switch ($event->getFieldId()) { + case 'windows_support': + $this->service->setFilesWindowsSupport((bool) $event->getValue()); + $event->stopPropagation(); + break; + } + } +} diff --git a/apps/files/lib/Service/SettingsService.php b/apps/files/lib/Service/SettingsService.php new file mode 100644 index 00000000000..d07e907a5f6 --- /dev/null +++ b/apps/files/lib/Service/SettingsService.php @@ -0,0 +1,63 @@ +', ':', + '"', '|', '?', + '*', + ]; + + public function __construct( + private IConfig $config, + private FilenameValidator $filenameValidator, + private LoggerInterface $logger, + ) { + } + + public function hasFilesWindowsSupport(): bool { + return empty(array_diff(self::WINDOWS_BASENAMES, $this->filenameValidator->getForbiddenBasenames())) + && empty(array_diff(self::WINDOWS_CHARACTERS, $this->filenameValidator->getForbiddenCharacters())) + && empty(array_diff(self::WINDOWS_EXTENSION, $this->filenameValidator->getForbiddenExtensions())); + } + + public function setFilesWindowsSupport(bool $enabled = true): void { + if ($enabled) { + $basenames = array_unique(array_merge(self::WINDOWS_BASENAMES, $this->filenameValidator->getForbiddenBasenames())); + $characters = array_unique(array_merge(self::WINDOWS_CHARACTERS, $this->filenameValidator->getForbiddenCharacters())); + $extensions = array_unique(array_merge(self::WINDOWS_EXTENSION, $this->filenameValidator->getForbiddenExtensions())); + } else { + $basenames = array_unique(array_values(array_diff($this->filenameValidator->getForbiddenBasenames(), self::WINDOWS_BASENAMES))); + $characters = array_unique(array_values(array_diff($this->filenameValidator->getForbiddenCharacters(), self::WINDOWS_CHARACTERS))); + $extensions = array_unique(array_values(array_diff($this->filenameValidator->getForbiddenExtensions(), self::WINDOWS_EXTENSION))); + } + $values = [ + 'forbidden_filename_basenames' => empty($basenames) ? null : $basenames, + 'forbidden_filename_characters' => empty($characters) ? null : $characters, + 'forbidden_filename_extensions' => empty($extensions) ? null : $extensions, + ]; + $this->config->setSystemValues($values); + } +} diff --git a/apps/files/lib/Settings/PersonalSettings.php b/apps/files/lib/Settings/PersonalSettings.php index c70a7171c94..484e4bde2b8 100644 --- a/apps/files/lib/Settings/PersonalSettings.php +++ b/apps/files/lib/Settings/PersonalSettings.php @@ -14,6 +14,7 @@ use OCP\Settings\ISettings; class PersonalSettings implements ISettings { public function getForm(): TemplateResponse { + \OCP\Util::addScript(Application::APP_ID, 'settings-personal'); return new TemplateResponse(Application::APP_ID, 'settings-personal'); } diff --git a/apps/files/src/components/NewNodeDialog.vue b/apps/files/src/components/NewNodeDialog.vue index 1ac65421dfe..d73e363e39f 100644 --- a/apps/files/src/components/NewNodeDialog.vue +++ b/apps/files/src/components/NewNodeDialog.vue @@ -3,13 +3,15 @@ - SPDX-License-Identifier: AGPL-3.0-or-later -->