Compare commits

...

60 Commits

Author SHA1 Message Date
Salvatore Martire e5b982afef fixup! feat: improve ZipFolderPlugin behaviour for different cases
Signed-off-by: Salvatore Martire <4652631+salmart-dev@users.noreply.github.com>
2026-03-30 19:27:07 +02:00
Salvatore Martire 16eaea217d fixup! feat: improve ZipFolderPlugin behaviour for different cases
Signed-off-by: Salvatore Martire <4652631+salmart-dev@users.noreply.github.com>
2026-03-30 18:41:27 +02:00
Salvatore Martire ccc00aab36 fixup! feat: improve ZipFolderPlugin behaviour for different cases
Signed-off-by: Salvatore Martire <4652631+salmart-dev@users.noreply.github.com>
2026-03-30 15:39:01 +02:00
Salvatore Martire b251a118a7 feat: improve ZipFolderPlugin behaviour for different cases
Signed-off-by: Salvatore Martire <4652631+salmart-dev@users.noreply.github.com>
2026-03-27 15:07:17 +01:00
Kostiantyn Miakshyn d1567c918c feat(files_sharing): Improve user experience when user attempts to download folder with non-downloadable files
Signed-off-by: Kostiantyn Miakshyn <molodchick@gmail.com>
2026-03-27 15:07:17 +01:00
Nextcloud bot f8cc0adefb fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2026-03-27 00:29:10 +00:00
Robin Appelman d1fd735698 Merge pull request #57374 from nextcloud/rename-dav-permissions
fix: allow renaming files with just update permissions
2026-03-26 22:12:28 +01:00
nextcloud-command 8f7b0b4264 chore(assets): Recompile assets
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
2026-03-26 18:18:56 +01:00
Robin Appelman c08592de28 fix: properly expose rename permissions over dav
Signed-off-by: Robin Appelman <robin@icewind.nl>
2026-03-26 18:18:55 +01:00
Robin Appelman 005b2b04e8 fix: update rename permissions check in files ui
Signed-off-by: Robin Appelman <robin@icewind.nl>
2026-03-26 17:10:03 +01:00
Robin Appelman 63a4778744 fix: allow renaming files with just update permissions
Signed-off-by: Robin Appelman <robin@icewind.nl>
2026-03-26 17:10:01 +01:00
Côme Chilliet ca245b4cc6 Merge pull request #58896 from nextcloud/fix/fix-tags-user-event
fix: Fix user in Tags class, do not depend upon session
2026-03-26 17:06:27 +01:00
Louis 309d12abe1 Merge pull request #58990 from mosi-kha/fix/group-displayname-event-oldvalue
fix(group): pass previous display name in GroupChangedEvent
2026-03-26 16:07:50 +01:00
Kate 7e9e1269a0 Merge pull request #59218 from nextcloud/feat/audit-log-ai-config-changes 2026-03-26 12:22:37 +01:00
Marcel Klehr 861f9bdb31 fix(settings): Check all values first, then apply them
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
2026-03-26 11:32:42 +01:00
Marcel Klehr a375265111 fix(settings): Throw JSON errors and return 400 status if JSON encode fails
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
2026-03-26 11:03:31 +01:00
Marcel Klehr 7fe3d1c6a0 feat(settings): Log AI config changes to audit log
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
2026-03-26 10:50:01 +01:00
Kate 0cf140e903 Merge pull request #58761 from nextcloud/feat/1700/limit-recent-files 2026-03-26 09:05:14 +01:00
github-actions[bot] 3d27f8d288 Merge pull request #59207 from nextcloud/dependabot/npm_and_yarn/multi-bf05dc1ecf
chore(deps): Bump picomatch
2026-03-26 02:18:48 +00:00
Nextcloud bot 52dac4be2b fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2026-03-26 00:19:23 +00:00
dependabot[bot] 252e24b83d chore(deps): Bump picomatch
Bumps  and [picomatch](https://github.com/micromatch/picomatch). These dependencies needed to be updated together.

Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

Updates `picomatch` from 2.3.1 to 2.3.2
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/4.0.3...4.0.4)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-25 22:31:46 +00:00
Ferdinand Thiessen 2ae66ff888 Merge pull request #59043 from nextcloud/jtr/chore-trashbin-drop-abortOperation-usage
chore(trashbin): deprecate abortOperation on BeforeNodeRestoredEvent / switch to AbortedEventException
2026-03-25 18:14:59 +01:00
Cristian Scheid 6594d54476 feat(recent-search): pass recent_limit config value to getRecentSearch function
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
2026-03-25 13:53:26 -03:00
Joas Schilling 9b125a7605 Merge pull request #59179 from nextcloud/automated/noid/master-update-code-signing-crl
[master] fix(security): Update code signing revocation list
2026-03-25 07:35:57 +01:00
nextcloud-command eb06a5628f fix(security): Update code signing revocation list
Signed-off-by: GitHub <noreply@github.com>
2026-03-25 03:12:18 +00:00
Nextcloud bot 2a5e57d2f4 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2026-03-25 00:19:21 +00:00
Cristian Scheid 9b605de474 refactor(recent-files): move recent limit to app-scoped config
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
2026-03-24 20:44:22 -03:00
Cristian Scheid 48ce8c3fa1 refactor(recent-files): remove user config from frontend files
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
2026-03-24 15:38:53 -03:00
Cristian Scheid 3925176b49 refactor(files-settings): remove recent file settings section
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
2026-03-24 15:15:34 -03:00
Cristian Scheid 981978d960 feat(recent-files): handle invalid config when only min or max are set for recent files limit
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
2026-03-24 15:15:34 -03:00
Cristian Scheid 282e6b707a feat(file-info): encapsulate logic to get last activity in getLastActivity function
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
2026-03-24 15:15:34 -03:00
Cristian Scheid 5bcac61c73 refactor(recent-search): use order by fields to determine extended cache join and cast config limit to number
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
2026-03-24 15:15:34 -03:00
Cristian Scheid 8225ab726f feat(recent-files): add nc:last_activity property to allow sorting by max between upload_time and mtime
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
2026-03-24 15:15:34 -03:00
Cristian Scheid 62f3ea390e feat(recent-files): add recent_files_limit config on files settings
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
2026-03-24 15:15:34 -03:00
John Molakvoæ d677a3a5e2 Merge pull request #59089 from nextcloud/fix/expand-theming-capabilities 2026-03-24 17:45:07 +01:00
skjnldsv 04d9f79985 chore: openapi conf update
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
2026-03-24 15:24:18 +01:00
John Molakvoæ 8fa69c1c29 fix(theming): deprecation message
Co-authored-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: John Molakvoæ <skjnldsv@users.noreply.github.com>
2026-03-24 15:24:18 +01:00
skjnldsv f2c73ebffd fix(theming): deprecate OCA.Theming and move to capabilities
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
2026-03-24 15:24:18 +01:00
Côme Chilliet 5a7d38b22c Merge pull request #59159 from nextcloud/fix/remove-static-vars-batch
Remove static vars, first batch
2026-03-24 14:20:10 +01:00
Nextcloud bot e4c2a1d218 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2026-03-24 00:19:16 +00:00
Côme Chilliet e367c5a928 chore: update psalm baseline
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:48:31 +01:00
Côme Chilliet 5c935429ef fix: Remove a static var usage in encryption application
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:48:31 +01:00
Côme Chilliet c88a1d3961 fix: Remove static vars usage in user_ldap
There are still some left, harder to remove.

Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:48:31 +01:00
Côme Chilliet 9b84a0ec19 fix: Remove unused static var and method in files application
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:48:30 +01:00
Côme Chilliet b256928385 fix: Remove use of static vars in dav application
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:48:30 +01:00
Côme Chilliet 6b49aa792b chore: Remove types from const properties for PHP 8.2 compatibility
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:36:01 +01:00
Côme Chilliet cd2d09de64 fix: Remove static vars from core classes
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:34:54 +01:00
Côme Chilliet 2c068f3683 fix: Remove static vars from applications
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:34:20 +01:00
Côme Chilliet 1398c598cf fix: Remove static vars from user_ldap
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:34:01 +01:00
Côme Chilliet 614afec231 fix: Remove static var in AppManager
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:33:29 +01:00
Côme Chilliet 3fcb3a962d fix: Remove useless static property in OCP\Util
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:33:15 +01:00
Côme Chilliet 5961eba6a1 fix: Remove static var in NaturalSort
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-23 16:19:59 +01:00
Josh 8bd63c5fe2 chore(Trashbin): hello lint
Signed-off-by: Josh <josh.t.richards@gmail.com>
2026-03-21 11:50:28 -04:00
Josh e53c124ecc chore(trashbin): drop unused use statements from SyncLivePhotosListener
Signed-off-by: Josh <josh.t.richards@gmail.com>
2026-03-21 11:50:28 -04:00
Josh 5f658d9eae chore(Trashbin): add AbortedEventException use
Signed-off-by: Josh <josh.t.richards@gmail.com>
2026-03-21 11:50:28 -04:00
Josh bd0784e056 refactor(Trashbin): switch to AbortedEventException usage in restore
Signed-off-by: Josh <josh.t.richards@gmail.com>
2026-03-21 11:50:28 -04:00
Josh 23569000a8 chore(trashbin): switch SyncLivePhotosListener to AbortedEventException
Signed-off-by: Josh <josh.t.richards@gmail.com>
2026-03-21 11:50:28 -04:00
Josh 4b2a77b1ff chore(trashbin): refactor deprecated abortOperation to use AbortedEventException
Signed-off-by: Josh <josh.t.richards@gmail.com>
2026-03-21 11:50:28 -04:00
mostafa 3d6d38a2fb fix(group): pass previous display name in GroupChangedEvent
Signed-off-by: mostafa <mostafakhaki00@gmail.com>
2026-03-17 09:16:30 +00:00
Côme Chilliet cc99dd8fd9 fix: Fix user in Tags class, do not depend upon session
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
2026-03-13 15:13:40 +01:00
147 changed files with 3774 additions and 502 deletions
+9 -1
View File
@@ -10,20 +10,28 @@ OC.L10N.register(
"{author} commented on {file}" : "{author} pakomentavo {file}",
"<strong>Comments</strong> for files" : "Failų <strong>komentarai</strong>",
"Files" : "Failai",
"You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "Buvote paminėtas „{file}“, komentare, kuris buvo parašytas iš paskyros, kuri vėliau buvo ištrinta.",
"{user} mentioned you in a comment on \"{file}\"" : "{user} minėjo jus \"{file}\" komentare",
"Files app plugin to add comments to files" : "Failų programėlės įskiepis, skirtas prie failų pridėti komentarus",
"Edit comment" : "Taisyti komentarą",
"Delete comment" : "Ištrinti komentarą",
"Cancel edit" : "Atsisakyti taisymo",
"New comment" : "Naujas komentaras",
"Write a comment …" : "Rašyti komentarą ...",
"Post comment" : "Paskelbti komentarą",
"@ for mentions, : for emoji, / for smart picker" : "@ paminėjimams, : jaustukams, / išmaniajam rinkikliui",
"Could not reload comments" : "Nepavyko įkelti komentarų iš naujo",
"Failed to mark comments as read" : "Nepavyko pažymėti komentarų kaip perskaitytų",
"Unable to load the comments list" : "Nepavyko įkelti komentarų sąrašo",
"No comments yet, start the conversation!" : "Komentarų kol kas nėra, pradėkite pokalbį!",
"No more messages" : "Daugiau jokių pranešimų",
"Retry" : "Bandyti dar kartą",
"_1 new comment_::_{unread} new comments_" : ["1 neskaitytas komentaras","{unread} neskaityti komentarai","{unread} neskaitytų komentarų","{unread} neskaitytas komentaras"],
"Comment" : "Komentaras",
"An error occurred while trying to edit the comment" : "Bandant taisyti komentarą, įvyko klaida",
"Comment deleted" : "Komentaras ištrintas",
"An error occurred while trying to delete the comment" : "Bandant ištrinti komentarą, įvyko klaida",
"An error occurred while trying to create the comment" : "Bandant sukurti komentarą, įvyko klaida"
"An error occurred while trying to create the comment" : "Bandant sukurti komentarą, įvyko klaida",
"Write a comment …" : "Rašyti komentarą..."
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
+9 -1
View File
@@ -8,20 +8,28 @@
"{author} commented on {file}" : "{author} pakomentavo {file}",
"<strong>Comments</strong> for files" : "Failų <strong>komentarai</strong>",
"Files" : "Failai",
"You were mentioned on \"{file}\", in a comment by an account that has since been deleted" : "Buvote paminėtas „{file}“, komentare, kuris buvo parašytas iš paskyros, kuri vėliau buvo ištrinta.",
"{user} mentioned you in a comment on \"{file}\"" : "{user} minėjo jus \"{file}\" komentare",
"Files app plugin to add comments to files" : "Failų programėlės įskiepis, skirtas prie failų pridėti komentarus",
"Edit comment" : "Taisyti komentarą",
"Delete comment" : "Ištrinti komentarą",
"Cancel edit" : "Atsisakyti taisymo",
"New comment" : "Naujas komentaras",
"Write a comment …" : "Rašyti komentarą ...",
"Post comment" : "Paskelbti komentarą",
"@ for mentions, : for emoji, / for smart picker" : "@ paminėjimams, : jaustukams, / išmaniajam rinkikliui",
"Could not reload comments" : "Nepavyko įkelti komentarų iš naujo",
"Failed to mark comments as read" : "Nepavyko pažymėti komentarų kaip perskaitytų",
"Unable to load the comments list" : "Nepavyko įkelti komentarų sąrašo",
"No comments yet, start the conversation!" : "Komentarų kol kas nėra, pradėkite pokalbį!",
"No more messages" : "Daugiau jokių pranešimų",
"Retry" : "Bandyti dar kartą",
"_1 new comment_::_{unread} new comments_" : ["1 neskaitytas komentaras","{unread} neskaityti komentarai","{unread} neskaitytų komentarų","{unread} neskaitytas komentaras"],
"Comment" : "Komentaras",
"An error occurred while trying to edit the comment" : "Bandant taisyti komentarą, įvyko klaida",
"Comment deleted" : "Komentaras ištrintas",
"An error occurred while trying to delete the comment" : "Bandant ištrinti komentarą, įvyko klaida",
"An error occurred while trying to create the comment" : "Bandant sukurti komentarą, įvyko klaida"
"An error occurred while trying to create the comment" : "Bandant sukurti komentarą, įvyko klaida",
"Write a comment …" : "Rašyti komentarą..."
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
}
+3 -1
View File
@@ -2,6 +2,8 @@ OC.L10N.register(
"contactsinteraction",
{
"Recently contacted" : "Paskiausiai susisiekta",
"Contacts Interaction" : "Sąveika su adresatais"
"Contacts Interaction" : "Sąveika su adresatais",
"Manages interaction between accounts and contacts" : "Tvarko sąveiką tarp paskyrų ir kontaktų",
"Collect data about accounts and contacts interactions and provide an address book for the data" : "Rinkti duomenis apie klientų ir kontaktų sąveiką ir pateikti adresų knygą duomenims"
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
+3 -1
View File
@@ -1,5 +1,7 @@
{ "translations": {
"Recently contacted" : "Paskiausiai susisiekta",
"Contacts Interaction" : "Sąveika su adresatais"
"Contacts Interaction" : "Sąveika su adresatais",
"Manages interaction between accounts and contacts" : "Tvarko sąveiką tarp paskyrų ir kontaktų",
"Collect data about accounts and contacts interactions and provide an address book for the data" : "Rinkti duomenis apie klientų ir kontaktų sąveiką ir pateikti adresų knygą duomenims"
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
}
+2
View File
@@ -3,6 +3,7 @@ OC.L10N.register(
{
"Dashboard" : "Skydelis",
"Dashboard app" : "Skydelio programėlė",
"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." : "Pradėkite dieną informuotai\n\n„Nextcloud“ ataskaitų sritis yra jūsų dienos atspirties taškas, kuriame pateikiama artėjančių susitikimų, skubių el. laiškų, pokalbių žinučių, gaunamų bilietų, naujausių tviterio žinučių ir daug daugiau apžvalga! Žmonės gali pridėti norimus valdiklius ir pakeisti foną pagal savo skonį.",
"Weather" : "Orai",
"Status" : "Būsena",
"Good morning" : "Labas rytas",
@@ -19,6 +20,7 @@ OC.L10N.register(
"Edit widgets" : "Taisyti valdiklius",
"Get more widgets from the App Store" : "Parsisiųsti įskiepių iš App Store",
"Weather service" : "Orų tarnyba",
"For your privacy, the weather data is requested by your {productName} server on your behalf so the weather service receives no personal information." : "Dėl jūsų privatumo, {productName} serveris jūsų vardu užklausė orų duomenis, todėl orų tarnyba negauna jokios asmeninės informacijos.",
"Weather data from Met.no" : "Orų duomenys iš Met.no",
"geocoding with Nominatim" : "geografinis kodavimas naudojant Nominatim",
"elevation data from OpenTopoData" : "aukščio duomenys iš OpenTopoData"
+2
View File
@@ -1,6 +1,7 @@
{ "translations": {
"Dashboard" : "Skydelis",
"Dashboard app" : "Skydelio programėlė",
"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." : "Pradėkite dieną informuotai\n\n„Nextcloud“ ataskaitų sritis yra jūsų dienos atspirties taškas, kuriame pateikiama artėjančių susitikimų, skubių el. laiškų, pokalbių žinučių, gaunamų bilietų, naujausių tviterio žinučių ir daug daugiau apžvalga! Žmonės gali pridėti norimus valdiklius ir pakeisti foną pagal savo skonį.",
"Weather" : "Orai",
"Status" : "Būsena",
"Good morning" : "Labas rytas",
@@ -17,6 +18,7 @@
"Edit widgets" : "Taisyti valdiklius",
"Get more widgets from the App Store" : "Parsisiųsti įskiepių iš App Store",
"Weather service" : "Orų tarnyba",
"For your privacy, the weather data is requested by your {productName} server on your behalf so the weather service receives no personal information." : "Dėl jūsų privatumo, {productName} serveris jūsų vardu užklausė orų duomenis, todėl orų tarnyba negauna jokios asmeninės informacijos.",
"Weather data from Met.no" : "Orų duomenys iš Met.no",
"geocoding with Nominatim" : "geografinis kodavimas naudojant Nominatim",
"elevation data from OpenTopoData" : "aukščio duomenys iš OpenTopoData"
@@ -216,6 +216,7 @@ return array(
'OCA\\DAV\\Connector\\Sabre\\Auth' => $baseDir . '/../lib/Connector/Sabre/Auth.php',
'OCA\\DAV\\Connector\\Sabre\\BearerAuth' => $baseDir . '/../lib/Connector/Sabre/BearerAuth.php',
'OCA\\DAV\\Connector\\Sabre\\BlockLegacyClientPlugin' => $baseDir . '/../lib/Connector/Sabre/BlockLegacyClientPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\ByteCounterFilter' => $baseDir . '/../lib/Connector/Sabre/ByteCounterFilter.php',
'OCA\\DAV\\Connector\\Sabre\\CachingTree' => $baseDir . '/../lib/Connector/Sabre/CachingTree.php',
'OCA\\DAV\\Connector\\Sabre\\ChecksumList' => $baseDir . '/../lib/Connector/Sabre/ChecksumList.php',
'OCA\\DAV\\Connector\\Sabre\\ChecksumUpdatePlugin' => $baseDir . '/../lib/Connector/Sabre/ChecksumUpdatePlugin.php',
@@ -254,6 +255,7 @@ return array(
'OCA\\DAV\\Connector\\Sabre\\ShareTypeList' => $baseDir . '/../lib/Connector/Sabre/ShareTypeList.php',
'OCA\\DAV\\Connector\\Sabre\\ShareeList' => $baseDir . '/../lib/Connector/Sabre/ShareeList.php',
'OCA\\DAV\\Connector\\Sabre\\SharesPlugin' => $baseDir . '/../lib/Connector/Sabre/SharesPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\StreamByteCounter' => $baseDir . '/../lib/Connector/Sabre/StreamByteCounter.php',
'OCA\\DAV\\Connector\\Sabre\\TagList' => $baseDir . '/../lib/Connector/Sabre/TagList.php',
'OCA\\DAV\\Connector\\Sabre\\TagsPlugin' => $baseDir . '/../lib/Connector/Sabre/TagsPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\UserIdHeaderPlugin' => $baseDir . '/../lib/Connector/Sabre/UserIdHeaderPlugin.php',
@@ -231,6 +231,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Connector\\Sabre\\Auth' => __DIR__ . '/..' . '/../lib/Connector/Sabre/Auth.php',
'OCA\\DAV\\Connector\\Sabre\\BearerAuth' => __DIR__ . '/..' . '/../lib/Connector/Sabre/BearerAuth.php',
'OCA\\DAV\\Connector\\Sabre\\BlockLegacyClientPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/BlockLegacyClientPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\ByteCounterFilter' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ByteCounterFilter.php',
'OCA\\DAV\\Connector\\Sabre\\CachingTree' => __DIR__ . '/..' . '/../lib/Connector/Sabre/CachingTree.php',
'OCA\\DAV\\Connector\\Sabre\\ChecksumList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ChecksumList.php',
'OCA\\DAV\\Connector\\Sabre\\ChecksumUpdatePlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ChecksumUpdatePlugin.php',
@@ -269,6 +270,7 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Connector\\Sabre\\ShareTypeList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ShareTypeList.php',
'OCA\\DAV\\Connector\\Sabre\\ShareeList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ShareeList.php',
'OCA\\DAV\\Connector\\Sabre\\SharesPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/SharesPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\StreamByteCounter' => __DIR__ . '/..' . '/../lib/Connector/Sabre/StreamByteCounter.php',
'OCA\\DAV\\Connector\\Sabre\\TagList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/TagList.php',
'OCA\\DAV\\Connector\\Sabre\\TagsPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/TagsPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\UserIdHeaderPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/UserIdHeaderPlugin.php',
+345
View File
@@ -0,0 +1,345 @@
OC.L10N.register(
"dav",
{
"Calendar" : "Kalendorius",
"Tasks" : "Užduotys",
"Personal" : "Asmeniniai",
"{actor} created calendar {calendar}" : "{actor} sukūrė kalendorių {calendar}",
"You created calendar {calendar}" : "Jūs sukūrėte kalendorių {calendar}",
"{actor} deleted calendar {calendar}" : "{actor} ištrynė kalendorių {calendar}",
"You deleted calendar {calendar}" : "Jūs ištrynėte kalendorių {calendar}",
"{actor} updated calendar {calendar}" : "{actor} atnaujino kalendorių {calendar}",
"You updated calendar {calendar}" : "Jūs atnaujinote kalendorių {calendar}",
"{actor} restored calendar {calendar}" : "{actor} atkūrė kalendorių {calendar}",
"You restored calendar {calendar}" : "Jūs atkūrėte kalendorių {calendar}",
"You shared calendar {calendar} as public link" : "Jūs pradėjote bendrinti kalendorių {calendar} kaip viešąją nuorodą",
"You removed public link for calendar {calendar}" : "Jūs pašalinote viešąją nuorodą kalendoriui {calendar}",
"{actor} shared calendar {calendar} with you" : "{actor} pradėjo bendrinti su jumis kalendorių {calendar}",
"You shared calendar {calendar} with {user}" : "Jūs pradėjote bendrinti kalendorių {calendar} su {user}",
"{actor} shared calendar {calendar} with {user}" : "{actor} pradėjo bendrinti kalendorių {calendar} su {user}",
"{actor} unshared calendar {calendar} from you" : "{actor} nustojo bendrinti su jumis kalendorių {calendar}",
"You unshared calendar {calendar} from {user}" : "Jūs nustojote bendrinti kalendorių {calendar} su {user}",
"{actor} unshared calendar {calendar} from {user}" : "{actor} nustojo bendrinti kalendorių {calendar} su {user}",
"{actor} unshared calendar {calendar} from themselves" : "{actor} nustojo bendrinti su savimi kalendorių {calendar}",
"You shared calendar {calendar} with group {group}" : "Jūs pradėjote bendrinti kalendorių {calendar} su grupe {group}",
"{actor} shared calendar {calendar} with group {group}" : "{actor} pradėjo bendrinti kalendorių {calendar} su grupe {group}",
"You unshared calendar {calendar} from group {group}" : "Jūs nustojote bendrinti kalendorių {calendar} su grupe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} nustojo bendrinti kalendorių {calendar} su grupe {group}",
"Untitled event" : "Įvykis be pavadinimo",
"{actor} created event {event} in calendar {calendar}" : "{actor} kalendoriuje {calendar} sukūrė įvykį {event}",
"You created event {event} in calendar {calendar}" : "Jūs kalendoriuje {calendar} sukūrėte įvykį {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} ištrynė įvykį {event} iš kalendoriaus {calendar}",
"You deleted event {event} from calendar {calendar}" : "Jūs ištrynėte įvykį {event} iš kalendoriaus {calendar}",
"{actor} updated event {event} in calendar {calendar}" : "{actor} kalendoriuje {calendar} atnaujino įvykį {event}",
"You updated event {event} in calendar {calendar}" : "Jūs kalendoriuje {calendar} atnaujinote įvykį {event}",
"{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} perkėlė {event} įvykį iš {sourceCalendar} kalendoriaus į {targetCalendar} kalendorių",
"You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "Jūs perkėlėte {event} įvykį iš {sourceCalendar} kalendroriaus į {targetCalendar} kalendorių",
"{actor} restored event {event} of calendar {calendar}" : "{actor} kalendoriuje {calendar} atkūrė įvykį {event}",
"You restored event {event} of calendar {calendar}" : "Jūs kalendoriuje {calendar} atkūrėte įvykį {event}",
"Busy" : "Užimtas laikas",
"{actor} created to-do {todo} in list {calendar}" : "{actor} sukūrė {todo} darbų sąraše {calendar}",
"You created to-do {todo} in list {calendar}" : "Jūs sukūrėte {todo} darbų sąraše {calendar}",
"{actor} deleted to-do {todo} from list {calendar}" : "{actor} pašalino {todo} darbą iš sąrašo {calendar}",
"You deleted to-do {todo} from list {calendar}" : "Jūs ištrynėte {todo} darbus iš sąrašo {calendar}",
"{actor} updated to-do {todo} in list {calendar}" : "{actor} atnaujino {todo} darbą sąraše {calendar}",
"You updated to-do {todo} in list {calendar}" : "Jūs atnaujinote {todo} darbą sąraše {calendar}",
"{actor} solved to-do {todo} in list {calendar}" : "{actor} užbaigė {todo} darbą iš sąrašo {calendar}",
"You solved to-do {todo} in list {calendar}" : "Jūs užbaigėte {todo} darbą iš sąrašo {calendar}",
"{actor} reopened to-do {todo} in list {calendar}" : "{actor} vėl pradėjo {todo} darbą iš sąrašo {calendar}",
"You reopened to-do {todo} in list {calendar}" : "Jūs vėl pradėjote {todo} darbą iš sąrašo {calendar}",
"{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "{actor} perkėlė {todo} darbą iš {sourceCalendar} sąrašo į {targetCalendar}",
"You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "Jūs perkėlėte {todo} darbą iš {sourceCalendar} sąrašo į {targetCalendar}",
"Calendar, contacts and tasks" : "Kalendorius, adresatai ir užduotys",
"A <strong>calendar</strong> was modified" : "<strong>Kalendorius</strong> buvo modifikuotas",
"A calendar <strong>event</strong> was modified" : "Kalendoriaus <strong>įvykis</strong> buvo modifikuotas",
"A calendar <strong>to-do</strong> was modified" : "Kalendoriaus <strong>darbų sąrašas</strong> buvo atnaujintas",
"Contact birthdays" : "Adresatų gimtadieniai",
"Death of %s" : "%s pabaiga",
"Untitled calendar" : "Kalendorius be pavadinimo",
"Calendar:" : "Kalendorius:",
"Date:" : "Data:",
"Where:" : "Kur:",
"Description:" : "Aprašas:",
"_%n year_::_%n years_" : ["%n metai","%n metai","%n metų","%n metai"],
"_%n month_::_%n months_" : ["%n mėnesis","%n mėnesiai","%n mėnesių","%n mėnesis"],
"_%n day_::_%n days_" : ["%n diena","%n dienos","%n dienų","%n diena"],
"_%n hour_::_%n hours_" : ["%n valanda","%n valandos","%n valandų","%n valanda"],
"_%n minute_::_%n minutes_" : ["%n minutė","%n minutės","%n minučių","%n minutė"],
"%s (in %s)" : "%s (po %s)",
"%s (%s ago)" : "%s (prieš %s)",
"Calendar: %s" : "Kalendorius: %s",
"Date: %s" : "Data: %s",
"Description: %s" : "Aprašas: %s",
"Where: %s" : "Kur: %s",
"%1$s via %2$s" : "%1$s per %2$s",
"In the past on %1$s for the entire day" : "Anksčiau %1$s visą dieną",
"_In %n minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["Per %n minutę %1$s visai dienai","Per %n minutes %1$s visai dienai","Per %n minučių %1$s visai dienai","Per %n minučių %1$s visai dienai"],
"_In %n hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Per %n valandą %1$s visai dienai","Per %n valandas %1$s visai dienai","Per %n valandų %1$s visai dienai","Per %n valandų %1$s visai dienai"],
"_In %n day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Per %n dieną %1$s visai dienai","Per %n dienas %1$s visai dienai","Per %n dienų %1$s visai dienai","Per %n dienų %1$s visai dienai"],
"_In %n week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Per %n savaitę %1$s visai dienai","Per %n savaites %1$s visai dienai","Per %n savaičių %1$s visai dienai","Per %n savaičių %1$s visai dienai"],
"_In %n month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["Per %n mėnesį %1$s visai dienai","Per %n mėnesius %1$s visai dienai","Per %n mėnesių %1$s visai dienai","Per %n mėnesių %1$s visai dienai"],
"_In %n year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["Per %n metus %1$s visai dienai","Per %n metus %1$s visai dienai","Per %n metų %1$s visai dienai","Per %n metų %1$s visai dienai"],
"In the past on %1$s between %2$s - %3$s" : "Anksčiau %1$s tarp %2$s - %3$s",
"_In %n minute on %1$s between %2$s - %3$s_::_In %n minutes on %1$s between %2$s - %3$s_" : ["Per %n minutę %1$s tarp %2$s - %3$s","Per %n minutes %1$s tarp %2$s - %3$s","Per %n minučių %1$s tarp %2$s - %3$s","Per %n minučių %1$s tarp %2$s - %3$s"],
"_In %n hour on %1$s between %2$s - %3$s_::_In %n hours on %1$s between %2$s - %3$s_" : ["Per %n valandą %1$s tarp %2$s - %3$s","Per %n valandas %1$s tarp %2$s - %3$s","Per %n valandų %1$s tarp %2$s - %3$s","Per %n valandų %1$s tarp %2$s - %3$s"],
"_In %n day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["Per %n dieną %1$s tarp %2$s - %3$s","Per %n dienas %1$s tarp %2$s - %3$s","Per %n dienų %1$s tarp %2$s - %3$s","Per %n dienų %1$s tarp %2$s - %3$s"],
"_In %n week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["Per %n savaitę %1$s tarp %2$s - %3$s","Per %n savaites %1$s tarp %2$s - %3$s","Per %n savaičių %1$s tarp %2$s - %3$s","Per %n savaičių %1$s tarp %2$s - %3$s"],
"_In %n month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["Per %n mėnesį %1$s tarp %2$s ir %3$s","Per %n mėnesius %1$s tarp %2$s - %3$s","Per %n mėnesių %1$s tarp %2$s - %3$s","Per %n mėnesių %1$s tarp %2$s - %3$s"],
"_In %n year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["Per %n metus %1$s tarp %2$s - %3$s","Per %n metus %1$s tarp %2$s - %3$s","Per %n metų %1$s tarp %2$s - %3$s","Per %n metų %1$s tarp %2$s - %3$s"],
"Could not generate when statement" : "Nepavyko sugeneruoti kada sakinio",
"Every Day for the entire day" : "Kiekvieną dieną visą dieną",
"Every Day for the entire day until %1$s" : "Kiekvieną dieną visą dieną iki %1$s",
"Every Day between %1$s - %2$s" : "Kiekvieną dieną tarp %1$s - %2$s",
"Every Day between %1$s - %2$s until %3$s" : "Kiekvieną dieną tarp %1$s - %2$s iki %3$s",
"Every %1$d Days for the entire day" : "Kiekvieną %1$d dieną visą dieną",
"Every %1$d Days for the entire day until %2$s" : "Kiekvieną %1$d dieną visą dieną iki %2$s",
"Every %1$d Days between %2$s - %3$s" : "Kiekvieną %1$d dieną tarp %2$s - %3$s",
"Every %1$d Days between %2$s - %3$s until %4$s" : "Kiekvieną %1$d dieną tarp %2$s - %3$s iki %4$s",
"Could not generate event recurrence statement" : "Nepavyko sugeneruoti įvykio pasikartojimo sakinio",
"Every Week on %1$s for the entire day" : "Kiekvieną savaitę %1$s visą dieną",
"Every Week on %1$s for the entire day until %2$s" : "Kiekvieną savaitę %1$s visą dieną iki %2$s",
"Every Week on %1$s between %2$s - %3$s" : "Kiekvieną savaitę %1$s tarp %2$s - %3$s",
"Every Week on %1$s between %2$s - %3$s until %4$s" : "Kiekvieną savaitę %1$s tarp %2$s - %3$s iki %4$s",
"Every %1$d Weeks on %2$s for the entire day" : "Kiekvieną %1$d savaitę %2$s visą dieną",
"Every %1$d Weeks on %2$s for the entire day until %3$s" : "Kiekvieną %1$d savaitę %2$s visą dieną iki %3$s",
"Every %1$d Weeks on %2$s between %3$s - %4$s" : "Kiekvieną %1$d savaitę %2$s tarp %3$s - %4$s",
"Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Kiekvieną %1$d savaitę %2$s tarp %3$s - %4$s iki %5$s",
"Every Month on the %1$s for the entire day" : "Kiekvieną mėnesį %1$s visą dieną",
"Every Month on the %1$s for the entire day until %2$s" : "Kiekvieną mėnesį %1$s visą dieną iki %2$s",
"Every Month on the %1$s between %2$s - %3$s" : "Kiekvieną mėnesį %1$s tarp %2$s - %3$s",
"Every Month on the %1$s between %2$s - %3$s until %4$s" : "Kiekvieną mėnesį %1$s tarp %2$s - %3$s iki %4$s",
"Every %1$d Months on the %2$s for the entire day" : "Kiekvieną %1$d mėnesį %2$s visą dieną",
"Every %1$d Months on the %2$s for the entire day until %3$s" : "Kiekvieną %1$d mėnesį %2$s visą dieną iki %3$s",
"Every %1$d Months on the %2$s between %3$s - %4$s" : "Kiekvieną %1$d mėnesį %2$s tarp %3$s - %4$s",
"Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Kiekvieną %1$d mėnesį %2$s tarp %3$s - %4$s iki %5$s",
"Every Year in %1$s on the %2$s for the entire day" : "Kiekvienais metais %1$s , %2$s visą dieną",
"Every Year in %1$s on the %2$s for the entire day until %3$s" : "Kiekvienais metais %1$s , %2$s visą dieną iki %3$s",
"Every Year in %1$s on the %2$s between %3$s - %4$s" : "Kiekvienais metais %1$s , %2$s tarp %3$s - %4$s",
"Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Kiekvienais metais %1$s , %2$s tarp %3$s - %4$s iki %5$s",
"Every %1$d Years in %2$s on the %3$s for the entire day" : "Kiekvienais %1$d metais %2$s, %3$s visą dieną",
"Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Kiekvienais %1$d metais %2$s , %3$s visą dieną iki %4$s",
"Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Kiekvienais %1$d metais %2$s , %3$s tarp %4$s - %5$s",
"Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Kiekvienais %1$d metais %2$s , %3$s tarp %4$s - %5$s iki %6$s",
"On specific dates for the entire day until %1$s" : "Konkrečiomis datomis visą dieną iki %1$s",
"On specific dates between %1$s - %2$s until %3$s" : "Konkrečiomis datomis tarp %1$s - %2$s iki %3$s",
"In the past on %1$s" : "Praeityje %1$s",
"_In %n minute on %1$s_::_In %n minutes on %1$s_" : ["Per %n minutę %1$s","Per %n minutes %1$s","Per %n minučių %1$s","Per %n minučių %1$s"],
"_In %n hour on %1$s_::_In %n hours on %1$s_" : ["Per %n valandą %1$s","Per %n valandas %1$s","Per %n valandų %1$s","Per %n valandų %1$s"],
"_In %n day on %1$s_::_In %n days on %1$s_" : ["Per %n dieną %1$s","Per %n dienas %1$s","Per %n dienų %1$s","Per %n dienų %1$s"],
"_In %n week on %1$s_::_In %n weeks on %1$s_" : ["Per %n savaitę %1$s","Per %n savaites %1$s","Per %n savaičių %1$s","Per %n savaičių %1$s"],
"_In %n month on %1$s_::_In %n months on %1$s_" : ["Per %n mėnesį %1$s","Per %n mėnesius %1$s","Per %n mėnesių %1$s","Per %n mėnesių %1$s"],
"_In %n year on %1$s_::_In %n years on %1$s_" : ["Per %n metus %1$s","Per %n metus %1$s","Per %n metų %1$s","Per %n metų %1$s"],
"In the past on %1$s then on %2$s" : "Anksčiau %1$s tuomet %2$s",
"_In %n minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Per %n minutę %1$s tuomet %2$s","Per %n minutes %1$s tuomet %2$s","Per %n minučių %1$s tuomet %2$s","Per %n minučių %1$s tuomet %2$s"],
"_In %n hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Per %n valandą %1$s tuomet %2$s","Per %n valandas %1$s tuomet %2$s","Per %n valandų %1$s tuomet %2$s","Per %n valandų %1$s tuomet %2$s"],
"_In %n day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Per %n dieną %1$s tuomet %2$s","Per %n dienas %1$s tuomet %2$s","Per %n dienų %1$s tuomet %2$s","Per %n dienų %1$s tuomet %2$s"],
"_In %n week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["Per %n savaitę %1$s tuomet %2$s","Per %n savaites %1$s tuomet %2$s","Per %n savaičių %1$s tuomet %2$s","Per %n savaičių %1$s tuomet %2$s"],
"_In %n month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Per %n mėnesį %1$s tuomet %2$s","Per %n mėnesius %1$s tuomet %2$s","Per %n mėnesių %1$s tuomet %2$s","Per %n mėnesių %1$s tuomet %2$s"],
"_In %n year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["Per %n metus %1$s tuomet %2$s","Per %n metus %1$s tuomet %2$s","Per %n metų %1$s tuomet %2$s","Per %n metų %1$s tuomet %2$s"],
"In the past on %1$s then on %2$s and %3$s" : "Anksčiau %1$s tuomet %2$s ir %3$s",
"_In %n minute on %1$s then on %2$s and %3$s_::_In %n minutes on %1$s then on %2$s and %3$s_" : ["Per %n minutę %1$s tuomet %2$s ir %3$s","Per %n minutes %1$s tuomet %2$s ir %3$s","Per %n minučių %1$s tuomet %2$s ir %3$s","Per %n minučių %1$s tuomet %2$s ir %3$s"],
"_In %n hour on %1$s then on %2$s and %3$s_::_In %n hours on %1$s then on %2$s and %3$s_" : ["Per %n valandą %1$s tuomet %2$s ir %3$s","Per %n valandas %1$s tuomet %2$s ir %3$s","Per %n valandų %1$s tuomet %2$s ir %3$s","Per %n valandų %1$s tuomet %2$s ir %3$s"],
"_In %n day on %1$s then on %2$s and %3$s_::_In %n days on %1$s then on %2$s and %3$s_" : ["Per %n dieną %1$s tuomet %2$s ir %3$s","Per %n dienas %1$s tuomet %2$s ir %3$s","Per %n dienų %1$s tuomet %2$s ir %3$s","Per %n dienų %1$s tuomet %2$s ir %3$s"],
"_In %n week on %1$s then on %2$s and %3$s_::_In %n weeks on %1$s then on %2$s and %3$s_" : ["Per %n savaitę %1$s tuomet %2$s ir %3$s","Per %n savaites %1$s tuomet %2$s ir %3$s","Per %n savaičių %1$s tuomet %2$s ir %3$s","Per %n savaičių %1$s tuomet %2$s ir %3$s"],
"_In %n month on %1$s then on %2$s and %3$s_::_In %n months on %1$s then on %2$s and %3$s_" : ["Per %n mėnesį %1$s tuomet %2$s ir %3$s","Per %n mėnesius %1$s tuomet %2$s ir %3$s","Per %n mėnesių %1$s tuomet %2$s ir %3$s","Per %n mėnesių %1$s tuomet %2$s ir %3$s"],
"_In %n year on %1$s then on %2$s and %3$s_::_In %n years on %1$s then on %2$s and %3$s_" : ["Per %n metus %1$s tuomet %2$s ir %3$s","Per %n metus %1$s tuomet %2$s ir %3$s","Per %n metų %1$s tuomet %2$s ir %3$s","Per %n metų %1$s tuomet %2$s ir %3$s"],
"Could not generate next recurrence statement" : "Nepavyko sugeneruoti kito pasikartojimo sakinio",
"Cancelled: %1$s" : "Atšaukta: %1$s",
"\"%1$s\" has been canceled" : "\"%1$s\" buvo atšauktas",
"Re: %1$s" : "Dėl: %1$s",
"%1$s has accepted your invitation" : "%1$s priėmė jūsų kvietimą",
"%1$s has tentatively accepted your invitation" : "%1$s preliminariai priėmė jūsų kvietimą",
"%1$s has declined your invitation" : "%1$s atmetė jūsų kvietimą",
"%1$s has responded to your invitation" : "%1$s atsakė į jūsų kvietimą",
"Invitation updated: %1$s" : "Kvietimas atnaujintas: %1$s",
"%1$s updated the event \"%2$s\"" : "%1$s atnaujino įvykį \"%2$s\"",
"Invitation: %1$s" : "Pakvietimas: %1$s",
"%1$s would like to invite you to \"%2$s\"" : "%1$s norėtų jus pakviesti į \"%2$s\"",
"Organizer:" : "Organizatorius:",
"Attendees:" : "Kviestiniai:",
"Title:" : "Pavadinimas:",
"When:" : "Kada:",
"Location:" : "Vieta:",
"Link:" : "Nuoroda:",
"Occurring:" : "Pasitaiko:",
"Accept" : "Priimti",
"Decline" : "Atmesti",
"More options …" : "Daugiau parinkčių…",
"More options at %s" : "Daugiau parinkčių %s",
"Monday" : "Pirmadienis",
"Tuesday" : "Antradienis",
"Wednesday" : "Trečiadienis",
"Thursday" : "Ketvirtadienis",
"Friday" : "Penktadienis",
"Saturday" : "Šeštadienis",
"Sunday" : "Sekmadienis",
"January" : "Sausis",
"February" : "Vasaris",
"March" : "Kovas",
"April" : "Balandis",
"May" : "Gegužė",
"June" : "Birželis",
"July" : "Liepa",
"August" : "Rugpjūtis",
"September" : "Rugsėjis",
"October" : "Spalis",
"November" : "Lapkritis",
"December" : "Gruodis",
"First" : "Pirmas",
"Second" : "Antras",
"Third" : "Trečias",
"Fourth" : "Ketvirtas",
"Fifth" : "Penktas",
"Last" : "Paskutinis",
"Second Last" : "Antras paskutinis",
"Third Last" : "Trečias paskutinis",
"Fourth Last" : "Ketvirtasis paskutinis",
"Fifth Last" : "Penktas paskutinis",
"Contacts" : "Adresatai",
"{actor} created address book {addressbook}" : "{actor} sukūrė adresų knygą {addressbook}",
"You created address book {addressbook}" : "Jūs sukūrėte adresų knygą {addressbook}",
"{actor} deleted address book {addressbook}" : "{actor} ištrynė adresų knygą {addressbook}",
"You deleted address book {addressbook}" : "Jūs ištrynėte adresų knygą {addressbook}",
"{actor} updated address book {addressbook}" : "{actor} atnaujino adresų knygą {addressbook}",
"You updated address book {addressbook}" : "Jūs atnaujinote adresų knygą {addressbook}",
"{actor} shared address book {addressbook} with you" : "{actor} pasidalino su jumis {addressbook} adresų knyga",
"You shared address book {addressbook} with {user}" : "Jūs pasidalinote {addressbook} adresų knyga su {user}",
"{actor} shared address book {addressbook} with {user}" : "{actor} pasidalino {addressbook} adresų knyga su {user}",
"{actor} unshared address book {addressbook} from you" : "{actor} atšaukė su jumis bendrinamą {addressbook} adresų knygą",
"You unshared address book {addressbook} from {user}" : "Jūs atšaukėte bendrinamą {addressbook} adresų knygą su {user}",
"{actor} unshared address book {addressbook} from {user}" : "{actor} atšaukė {addressbook} bendrinamą adresų knygą su {user}",
"{actor} unshared address book {addressbook} from themselves" : "{actor} atšaukė savo paties bendrinamą {addressbook} adresų knygą",
"You shared address book {addressbook} with group {group}" : "Jūs bendrinote {addressbook} adresų knygą su {group} grupe",
"{actor} shared address book {addressbook} with group {group}" : "{actor} bendrino {addressbook} adresų knygą su {group} grupe",
"You unshared address book {addressbook} from group {group}" : "Jūs atšaukėte bendrinamą {addressbook}adresų knygą su {group} grupe",
"{actor} unshared address book {addressbook} from group {group}" : "{actor} atšaukė bendrinamą {addressbook} adresų knygą su {group} grupe",
"{actor} created contact {card} in address book {addressbook}" : "{actor} sukūrė {card} kontaktą {addressbook} adresų knygoje",
"You created contact {card} in address book {addressbook}" : "Jūs sukūrėte {card} kontaktą {addressbook} adresų knygoje",
"{actor} deleted contact {card} from address book {addressbook}" : "{actor} ištrynė {card} kontaktų iš {addressbook} adresų knygos",
"You deleted contact {card} from address book {addressbook}" : "Jūs ištrynėte {card} kontaktą iš {addressbook} adresų knygos",
"{actor} updated contact {card} in address book {addressbook}" : "{actor} atnaujino {card} kontaktą {addressbook} adresų knygoje",
"You updated contact {card} in address book {addressbook}" : "Jūs atnaujinote {card} kontaktą {addressbook} adresų knygoje",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>kontaktas</strong> arba <strong>adresų knyga</strong> buvo atnaujinta",
"System address book disabled" : "Sistemos adresų knyga išjungta",
"The system contacts address book has been automatically disabled during upgrade. This means that the address book will no longer be available to users in the contacts app or other clients. The system contacts address book was disabled because the amount of contacts in the address book exceeded the maximum recommended number of contacts. This limit is set to prevent performance issues. You can re-enable the system address book with the following command {command}" : "Sistemos kontaktų adresų knyga buvo automatiškai išjungta atnaujinimo metu. Tai reiškia, kad adresų knyga nebebus pasiekiama vartotojams kontaktų programėlėje ar kituose klientuose. Sistemos kontaktų adresų knyga buvo išjungta, nes joje esančių kontaktų skaičius viršijo maksimalų rekomenduojamą kontaktų skaičių. Šis apribojimas nustatytas siekiant išvengti našumo problemų. Sistemos adresų knygą galite iš naujo įjungti naudodami šią komandą {command}.",
"Accounts" : "Paskyros",
"System address book which holds all accounts" : "Sistemos adresų knyga, kurioje saugomos visos paskyros",
"File is not updatable: %1$s" : "Failo atnaujinamas negalimas: %1$s",
"Failed to get storage for file" : "Nepavyko gauti failo saugyklos vietos",
"Could not write to final file, canceled by hook" : "Nepavyko įrašyti į galutinį failą, atšaukta naudojant interceptorių",
"Could not write file contents" : "Nepavyko įrašyti failo turinio",
"_%n byte_::_%n bytes_" : ["%n baitas","%n baitai","%n baitų","%n baitų"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Klaida kopijuojant failą į paskirties vietą (nukopijuota: %1$s, numatomas failo dydis: %2$s)",
"Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Tikėtasi %1$s failo dydžio, bet nuskaityta (iš „Nextcloud“ kliento) ir įrašyta (į „Nextcloud“ saugyklą) %2$s. Gali būti tinklo problema siuntėjo pusėje arba problema rašant į saugyklą serverio pusėje.",
"Could not rename part file to final file, canceled by hook" : "Nepavyko pervadinti dalinio failo į galutinį failą, atšaukta naudojant interceptorių",
"Could not rename part file to final file" : "Nepavyko pervadinti dalinio failo į galutinį failą",
"Failed to check file size: %1$s" : "Nepavyko patikrinti failo dydžio: %1$s",
"Could not open file: %1$s (%2$d), file does seem to exist" : "Nepavyko atidaryti failo: %1$s (%2$d), atrodo, kad failas egzistuoja",
"Could not open file: %1$s (%2$d), file doesn't seem to exist" : "Nepavyko atidaryti failo: %1$s (%2$d), atrodo, kad failo nėra",
"Failed to get size for : %1$s" : "Nepavyko gauti %1$s dydžio",
"Encryption not ready: %1$s" : "Šifravimas neparuoštas: %1$s",
"Failed to open file: %1$s" : "Nepavyko atverti failo: %1$s",
"Failed to unlink: %1$s" : "Nepavyko atsieti: %1$s",
"Failed to write file contents: %1$s" : "Nepavyko įrašyti failo turinio: %1$s",
"File not found: %1$s" : "Failas nerastas: %1$s",
"Invalid target path" : "Netinkamas tikslinis kelias",
"System is in maintenance mode." : "Sistema yra techninės priežiūros veiksenoje.",
"Upgrade needed" : "Reikalingas naujinimas",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Norint naudoti CalDAV ir CardDAV su iOS/macOS, jūsų %s turi būti sukonfigūruota taip, kad naudotų HTTPS.",
"Configures a CalDAV account" : "Konfigūruoja CalDAV paskyrą",
"Configures a CardDAV account" : "Konfigūruoja CardDAV paskyrą",
"Events" : "Įvykiai",
"Untitled task" : "Užduotis be pavadinimo",
"Completed on %s" : "Pabaigta %s",
"Due on %s by %s" : "Laukiamas %s iki %s",
"Due on %s" : "Laukiamas %s",
"This is an example contact" : "Tai yra kontakto pavyzdys",
"Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Sveiki atvykę į „Nextcloud“ kalendorių!\n\nTai pavyzdinis įrašas išbandykite planavimo lankstumą su „Nextcloud“ kalendoriumi, atlikdami bet kokius norimus pakeitimus!\n\nSu „Nextcloud“ kalendoriumi galite:\n- Nesunkiai kurti, redaguoti ir valdyti įvykius.\n- Kurti kelis kalendorius ir bendrinti juos su komandos nariais, draugais ar šeima.\n- Patikrinti prieinamumą ir rodyti savo užimtumo laiką kitiems.\n- Sklandžiai integruotis su programėlėmis ir įrenginiais per „CalDAV“.\n- Tinkinti savo patirtį: planuoti pasikartojančius įvykius, koreguoti pranešimus ir kitus nustatymus.",
"Example event - open me!" : "Pavyzdinis įvykis atverk mane!",
"System Address Book" : "Sistemos adresų knyga",
"The system address book contains contact information for all users in your instance." : "Sistemos adresų knygoje yra visų jūsų turimų vartotojų kontaktinė informacija.",
"Enable System Address Book" : "Įjungti sistemos adresų knygą",
"DAV system address book" : "DAV sistemos adresų knyga",
"No outstanding DAV system address book sync." : "Nėra jokių nepatvirtintų DAV sistemos adresų knygos sinchronizavimo.",
"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\"." : "DAV sistemos adresų knygos sinchronizavimas dar nebuvo paleistas, nes jūsų egzemplioriuje yra daugiau nei 1000 vartotojų arba įvyko klaida. Paleiskite jį rankiniu būdu, iškviečiant „occ dav:sync-system-addressbook“.",
"DAV system address book size" : "DAV sistemos adresų knygos dydis",
"The system address book is disabled" : "Sistemos adresų knyga išjungta",
"The system address book is enabled, but contains more than the configured limit of %d contacts" : "Sistemos adresų knyga įjungta ir joje yra daugiau kontaktų nei nustatyta riba, t.y. %d kontaktų",
"The system address book is enabled and contains less than the configured limit of %d contacts" : "Sistemos adresų knyga įjungta ir joje yra mažiau kontaktų nei nustatyta riba, t.y. %d kontaktų",
"WebDAV endpoint" : "WebDAV galutinis taškas",
"Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Nepavyko patikrinti, ar jūsų žiniatinklio serveris tinkamai nustatytas leisti failų sinchronizavimą per WebDAV. Patikrinkite rankiniu būdu.",
"Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Jūsų svetainės serveris nėra tinkamai sukonfiguruotas, Failų sinchronizavimas negalimas, nes neveikia WebDAV interfeisas.",
"Your web server is properly set up to allow file synchronization over WebDAV." : "Jūsų žiniatinklio serveris tinkamai sukonfigūruotas, kad būtų galima sinchronizuoti failus per WebDAV.",
"Calendars including events, details and attendees" : "Kalendoriai su įvykiais, informacija ir dalyviais",
"Migrated calendar (%1$s)" : "Perkeltas kalendorius (%1$s)",
"Contacts and groups" : "Adresatai ir grupės",
"WebDAV" : "WebDAV",
"Absence saved" : "Išsaugotas nebuvimas",
"Failed to save your absence settings" : "Nepavyko išsaugoti jūsų nebuvimo nustatymų",
"Absence cleared" : "Nebuvimas pašalintas",
"Failed to clear your absence settings" : "Nepavyko išvalyti nedalyvavimo nustatymų",
"First day" : "Pirma diena",
"Last day (inclusive)" : "Paskutinė diena (imtinai)",
"Out of office replacement (optional)" : "Nebuvimo biure pakeitimas (neprivaloma)",
"Name of the replacement" : "Pakeitimo pavadinimas",
"Short absence status" : "Trumpo nebuvimo būsena",
"Long absence Message" : "Ilgo nebuvimo žinutė",
"Save" : "Įrašyti",
"Disable absence" : "Išjungti nebuvimą",
"Failed to load availability" : "Nepavyko įkelti prieinamumo",
"Saved availability" : "Išsaugotas pasiekiamumas",
"Failed to save availability" : "Nepavyko išsaugoti pasiekiamumo",
"to" : "iki",
"Delete slot" : "Ištrinti laiko tarpą",
"No working hours set" : "Nenustatyta jokių darbo valandų",
"Add slot" : "Pridėti laiko tarpą",
"Weekdays" : "Šiokiadieniai",
"Pick a start time for {dayName}" : "Pasirinkite {dayName} pradžios laiką",
"Pick a end time for {dayName}" : "Pasirinkite {dayName} pabaigos laiką",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatiškai nustatyti naudotojo būseną į „Netrukdyti“, kai jis nėra pasiekiamas, kad būtų nutildyti visi pranešimai.",
"Cancel" : "Atsisakyti",
"Import" : "Importuoti",
"Error while saving settings" : "Klaida įrašant nustatymus",
"Contact reset successfully" : "Kontaktas sėkmingai nustatytas iš naujo",
"Error while resetting contact" : "Iš naujo nustatant kontaktą įvyko klaida",
"Contact imported successfully" : "Kontaktas sėkmingai importuotas",
"Error while importing contact" : "Importuojant kontaktą įvyko klaida",
"Import contact" : "Importuoti kontaktą",
"Reset to default" : "Atstatyti į numatytąjį",
"Import contacts" : "Importuoti kontaktus",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importuojant naują .vcf failą, esamas numatytasis kontaktas bus ištrintas ir pakeistas nauju. Ar norite tęsti?",
"Failed to save example event creation setting" : "Nepavyko išsaugoti pavyzdinio įvykio kūrimo nustatymo",
"Failed to upload the example event" : "Nepavyko įkelti pavyzdinio įvykio",
"Custom example event was saved successfully" : "Pasirinktinis pavyzdinis įvykis sėkmingai išsaugotas",
"Failed to delete the custom example event" : "Nepavyko ištrinti pasirinktinio pavyzdžio įvykio",
"Custom example event was deleted successfully" : "Pasirinktinis pavyzdinis įvykis sėkmingai ištrintas",
"Import calendar event" : "Importuoti kalendoriaus įvykį",
"Uploading a new event will overwrite the existing one." : "Įkėlus naują įvykį, esamas bus perrašytas.",
"Upload event" : "Įkelti įvykį",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Taip pat įsidiekite {calendarappstoreopen}Kalendoriaus programėlę{linkclose} arba sinchronizavimui {calendardocopen}prijunkite savo darbalaukį ir mobilųjį ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Įsitikinkite, kad tinkamai nusistatėte {emailopen}el. pašto serverį{linkclose}.",
"Calendar server" : "Kalendoriaus serveris",
"Send invitations to attendees" : "Siųsti pakvietimus kviestiniams",
"Automatically generate a birthday calendar" : "Automatiškai sukurti gimtadienių kalendorių",
"Birthday calendars will be generated by a background job." : "Gimtadienių kalendoriai bus sukurti foninės užduoties.",
"Hence they will not be available immediately after enabling but will show up after some time." : "Tai reiškia, kad jie nebus matomi iš karto įjungus, o pasirodys tik po kurio laiko.",
"Send notifications for events" : "Siųsti įvykių pranešimus",
"Notifications are sent via background jobs, so these must occur often enough." : "Pranešimai yra siunčiami per fonines užduotis, todėl jos privalo būti vykdomos gana dažnai.",
"Send reminder notifications to calendar sharees as well" : "Siųskite priminimus ir tiems, kurie bendrina kalendorių",
"Reminders are always sent to organizers and attendees." : "Priminimai visada siunčiami organizatoriams ir dalyviams.",
"Enable notifications for events via push" : "Įjungti pranešimus apie įvykius per tiesioginius pranešimus",
"Example content" : "Turinio pavyzdys",
"Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Pavyzdinis turinys skirtas „Nextcloud“ funkcijoms demonstruoti. Numatytasis turinys pateikiamas kartu su „Nextcloud“ ir gali būti pakeistas pasirinktiniu turiniu.",
"Availability" : "Pasiekiamumas",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Jei sukonfigūruosite savo darbo valandas, kiti žmonės, rezervuodami susitikimą, matys, kada esate išvykę.",
"Absence" : "Nebuvimas",
"Configure your next absence period." : "Konfigūruokite kitą nebuvimo laikotarpį.",
"There was an error updating your attendance status." : "Atnaujinant lankomumo būseną įvyko klaida.",
"Please contact the organizer directly." : "Prašome susisiekti su organizatoriumi tiesiogiai.",
"Are you accepting the invitation?" : "Ar priimate pakvietimą?",
"Tentative" : "Preliminarus",
"Your attendance was updated successfully." : "Jūsų lankomumas sėkmingai atnaujintas.",
"No results." : "Jokių rezultatų.",
"Start typing." : "Start typing."
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
+343
View File
@@ -0,0 +1,343 @@
{ "translations": {
"Calendar" : "Kalendorius",
"Tasks" : "Užduotys",
"Personal" : "Asmeniniai",
"{actor} created calendar {calendar}" : "{actor} sukūrė kalendorių {calendar}",
"You created calendar {calendar}" : "Jūs sukūrėte kalendorių {calendar}",
"{actor} deleted calendar {calendar}" : "{actor} ištrynė kalendorių {calendar}",
"You deleted calendar {calendar}" : "Jūs ištrynėte kalendorių {calendar}",
"{actor} updated calendar {calendar}" : "{actor} atnaujino kalendorių {calendar}",
"You updated calendar {calendar}" : "Jūs atnaujinote kalendorių {calendar}",
"{actor} restored calendar {calendar}" : "{actor} atkūrė kalendorių {calendar}",
"You restored calendar {calendar}" : "Jūs atkūrėte kalendorių {calendar}",
"You shared calendar {calendar} as public link" : "Jūs pradėjote bendrinti kalendorių {calendar} kaip viešąją nuorodą",
"You removed public link for calendar {calendar}" : "Jūs pašalinote viešąją nuorodą kalendoriui {calendar}",
"{actor} shared calendar {calendar} with you" : "{actor} pradėjo bendrinti su jumis kalendorių {calendar}",
"You shared calendar {calendar} with {user}" : "Jūs pradėjote bendrinti kalendorių {calendar} su {user}",
"{actor} shared calendar {calendar} with {user}" : "{actor} pradėjo bendrinti kalendorių {calendar} su {user}",
"{actor} unshared calendar {calendar} from you" : "{actor} nustojo bendrinti su jumis kalendorių {calendar}",
"You unshared calendar {calendar} from {user}" : "Jūs nustojote bendrinti kalendorių {calendar} su {user}",
"{actor} unshared calendar {calendar} from {user}" : "{actor} nustojo bendrinti kalendorių {calendar} su {user}",
"{actor} unshared calendar {calendar} from themselves" : "{actor} nustojo bendrinti su savimi kalendorių {calendar}",
"You shared calendar {calendar} with group {group}" : "Jūs pradėjote bendrinti kalendorių {calendar} su grupe {group}",
"{actor} shared calendar {calendar} with group {group}" : "{actor} pradėjo bendrinti kalendorių {calendar} su grupe {group}",
"You unshared calendar {calendar} from group {group}" : "Jūs nustojote bendrinti kalendorių {calendar} su grupe {group}",
"{actor} unshared calendar {calendar} from group {group}" : "{actor} nustojo bendrinti kalendorių {calendar} su grupe {group}",
"Untitled event" : "Įvykis be pavadinimo",
"{actor} created event {event} in calendar {calendar}" : "{actor} kalendoriuje {calendar} sukūrė įvykį {event}",
"You created event {event} in calendar {calendar}" : "Jūs kalendoriuje {calendar} sukūrėte įvykį {event}",
"{actor} deleted event {event} from calendar {calendar}" : "{actor} ištrynė įvykį {event} iš kalendoriaus {calendar}",
"You deleted event {event} from calendar {calendar}" : "Jūs ištrynėte įvykį {event} iš kalendoriaus {calendar}",
"{actor} updated event {event} in calendar {calendar}" : "{actor} kalendoriuje {calendar} atnaujino įvykį {event}",
"You updated event {event} in calendar {calendar}" : "Jūs kalendoriuje {calendar} atnaujinote įvykį {event}",
"{actor} moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "{actor} perkėlė {event} įvykį iš {sourceCalendar} kalendoriaus į {targetCalendar} kalendorių",
"You moved event {event} from calendar {sourceCalendar} to calendar {targetCalendar}" : "Jūs perkėlėte {event} įvykį iš {sourceCalendar} kalendroriaus į {targetCalendar} kalendorių",
"{actor} restored event {event} of calendar {calendar}" : "{actor} kalendoriuje {calendar} atkūrė įvykį {event}",
"You restored event {event} of calendar {calendar}" : "Jūs kalendoriuje {calendar} atkūrėte įvykį {event}",
"Busy" : "Užimtas laikas",
"{actor} created to-do {todo} in list {calendar}" : "{actor} sukūrė {todo} darbų sąraše {calendar}",
"You created to-do {todo} in list {calendar}" : "Jūs sukūrėte {todo} darbų sąraše {calendar}",
"{actor} deleted to-do {todo} from list {calendar}" : "{actor} pašalino {todo} darbą iš sąrašo {calendar}",
"You deleted to-do {todo} from list {calendar}" : "Jūs ištrynėte {todo} darbus iš sąrašo {calendar}",
"{actor} updated to-do {todo} in list {calendar}" : "{actor} atnaujino {todo} darbą sąraše {calendar}",
"You updated to-do {todo} in list {calendar}" : "Jūs atnaujinote {todo} darbą sąraše {calendar}",
"{actor} solved to-do {todo} in list {calendar}" : "{actor} užbaigė {todo} darbą iš sąrašo {calendar}",
"You solved to-do {todo} in list {calendar}" : "Jūs užbaigėte {todo} darbą iš sąrašo {calendar}",
"{actor} reopened to-do {todo} in list {calendar}" : "{actor} vėl pradėjo {todo} darbą iš sąrašo {calendar}",
"You reopened to-do {todo} in list {calendar}" : "Jūs vėl pradėjote {todo} darbą iš sąrašo {calendar}",
"{actor} moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "{actor} perkėlė {todo} darbą iš {sourceCalendar} sąrašo į {targetCalendar}",
"You moved to-do {todo} from list {sourceCalendar} to list {targetCalendar}" : "Jūs perkėlėte {todo} darbą iš {sourceCalendar} sąrašo į {targetCalendar}",
"Calendar, contacts and tasks" : "Kalendorius, adresatai ir užduotys",
"A <strong>calendar</strong> was modified" : "<strong>Kalendorius</strong> buvo modifikuotas",
"A calendar <strong>event</strong> was modified" : "Kalendoriaus <strong>įvykis</strong> buvo modifikuotas",
"A calendar <strong>to-do</strong> was modified" : "Kalendoriaus <strong>darbų sąrašas</strong> buvo atnaujintas",
"Contact birthdays" : "Adresatų gimtadieniai",
"Death of %s" : "%s pabaiga",
"Untitled calendar" : "Kalendorius be pavadinimo",
"Calendar:" : "Kalendorius:",
"Date:" : "Data:",
"Where:" : "Kur:",
"Description:" : "Aprašas:",
"_%n year_::_%n years_" : ["%n metai","%n metai","%n metų","%n metai"],
"_%n month_::_%n months_" : ["%n mėnesis","%n mėnesiai","%n mėnesių","%n mėnesis"],
"_%n day_::_%n days_" : ["%n diena","%n dienos","%n dienų","%n diena"],
"_%n hour_::_%n hours_" : ["%n valanda","%n valandos","%n valandų","%n valanda"],
"_%n minute_::_%n minutes_" : ["%n minutė","%n minutės","%n minučių","%n minutė"],
"%s (in %s)" : "%s (po %s)",
"%s (%s ago)" : "%s (prieš %s)",
"Calendar: %s" : "Kalendorius: %s",
"Date: %s" : "Data: %s",
"Description: %s" : "Aprašas: %s",
"Where: %s" : "Kur: %s",
"%1$s via %2$s" : "%1$s per %2$s",
"In the past on %1$s for the entire day" : "Anksčiau %1$s visą dieną",
"_In %n minute on %1$s for the entire day_::_In %n minutes on %1$s for the entire day_" : ["Per %n minutę %1$s visai dienai","Per %n minutes %1$s visai dienai","Per %n minučių %1$s visai dienai","Per %n minučių %1$s visai dienai"],
"_In %n hour on %1$s for the entire day_::_In %n hours on %1$s for the entire day_" : ["Per %n valandą %1$s visai dienai","Per %n valandas %1$s visai dienai","Per %n valandų %1$s visai dienai","Per %n valandų %1$s visai dienai"],
"_In %n day on %1$s for the entire day_::_In %n days on %1$s for the entire day_" : ["Per %n dieną %1$s visai dienai","Per %n dienas %1$s visai dienai","Per %n dienų %1$s visai dienai","Per %n dienų %1$s visai dienai"],
"_In %n week on %1$s for the entire day_::_In %n weeks on %1$s for the entire day_" : ["Per %n savaitę %1$s visai dienai","Per %n savaites %1$s visai dienai","Per %n savaičių %1$s visai dienai","Per %n savaičių %1$s visai dienai"],
"_In %n month on %1$s for the entire day_::_In %n months on %1$s for the entire day_" : ["Per %n mėnesį %1$s visai dienai","Per %n mėnesius %1$s visai dienai","Per %n mėnesių %1$s visai dienai","Per %n mėnesių %1$s visai dienai"],
"_In %n year on %1$s for the entire day_::_In %n years on %1$s for the entire day_" : ["Per %n metus %1$s visai dienai","Per %n metus %1$s visai dienai","Per %n metų %1$s visai dienai","Per %n metų %1$s visai dienai"],
"In the past on %1$s between %2$s - %3$s" : "Anksčiau %1$s tarp %2$s - %3$s",
"_In %n minute on %1$s between %2$s - %3$s_::_In %n minutes on %1$s between %2$s - %3$s_" : ["Per %n minutę %1$s tarp %2$s - %3$s","Per %n minutes %1$s tarp %2$s - %3$s","Per %n minučių %1$s tarp %2$s - %3$s","Per %n minučių %1$s tarp %2$s - %3$s"],
"_In %n hour on %1$s between %2$s - %3$s_::_In %n hours on %1$s between %2$s - %3$s_" : ["Per %n valandą %1$s tarp %2$s - %3$s","Per %n valandas %1$s tarp %2$s - %3$s","Per %n valandų %1$s tarp %2$s - %3$s","Per %n valandų %1$s tarp %2$s - %3$s"],
"_In %n day on %1$s between %2$s - %3$s_::_In %n days on %1$s between %2$s - %3$s_" : ["Per %n dieną %1$s tarp %2$s - %3$s","Per %n dienas %1$s tarp %2$s - %3$s","Per %n dienų %1$s tarp %2$s - %3$s","Per %n dienų %1$s tarp %2$s - %3$s"],
"_In %n week on %1$s between %2$s - %3$s_::_In %n weeks on %1$s between %2$s - %3$s_" : ["Per %n savaitę %1$s tarp %2$s - %3$s","Per %n savaites %1$s tarp %2$s - %3$s","Per %n savaičių %1$s tarp %2$s - %3$s","Per %n savaičių %1$s tarp %2$s - %3$s"],
"_In %n month on %1$s between %2$s - %3$s_::_In %n months on %1$s between %2$s - %3$s_" : ["Per %n mėnesį %1$s tarp %2$s ir %3$s","Per %n mėnesius %1$s tarp %2$s - %3$s","Per %n mėnesių %1$s tarp %2$s - %3$s","Per %n mėnesių %1$s tarp %2$s - %3$s"],
"_In %n year on %1$s between %2$s - %3$s_::_In %n years on %1$s between %2$s - %3$s_" : ["Per %n metus %1$s tarp %2$s - %3$s","Per %n metus %1$s tarp %2$s - %3$s","Per %n metų %1$s tarp %2$s - %3$s","Per %n metų %1$s tarp %2$s - %3$s"],
"Could not generate when statement" : "Nepavyko sugeneruoti kada sakinio",
"Every Day for the entire day" : "Kiekvieną dieną visą dieną",
"Every Day for the entire day until %1$s" : "Kiekvieną dieną visą dieną iki %1$s",
"Every Day between %1$s - %2$s" : "Kiekvieną dieną tarp %1$s - %2$s",
"Every Day between %1$s - %2$s until %3$s" : "Kiekvieną dieną tarp %1$s - %2$s iki %3$s",
"Every %1$d Days for the entire day" : "Kiekvieną %1$d dieną visą dieną",
"Every %1$d Days for the entire day until %2$s" : "Kiekvieną %1$d dieną visą dieną iki %2$s",
"Every %1$d Days between %2$s - %3$s" : "Kiekvieną %1$d dieną tarp %2$s - %3$s",
"Every %1$d Days between %2$s - %3$s until %4$s" : "Kiekvieną %1$d dieną tarp %2$s - %3$s iki %4$s",
"Could not generate event recurrence statement" : "Nepavyko sugeneruoti įvykio pasikartojimo sakinio",
"Every Week on %1$s for the entire day" : "Kiekvieną savaitę %1$s visą dieną",
"Every Week on %1$s for the entire day until %2$s" : "Kiekvieną savaitę %1$s visą dieną iki %2$s",
"Every Week on %1$s between %2$s - %3$s" : "Kiekvieną savaitę %1$s tarp %2$s - %3$s",
"Every Week on %1$s between %2$s - %3$s until %4$s" : "Kiekvieną savaitę %1$s tarp %2$s - %3$s iki %4$s",
"Every %1$d Weeks on %2$s for the entire day" : "Kiekvieną %1$d savaitę %2$s visą dieną",
"Every %1$d Weeks on %2$s for the entire day until %3$s" : "Kiekvieną %1$d savaitę %2$s visą dieną iki %3$s",
"Every %1$d Weeks on %2$s between %3$s - %4$s" : "Kiekvieną %1$d savaitę %2$s tarp %3$s - %4$s",
"Every %1$d Weeks on %2$s between %3$s - %4$s until %5$s" : "Kiekvieną %1$d savaitę %2$s tarp %3$s - %4$s iki %5$s",
"Every Month on the %1$s for the entire day" : "Kiekvieną mėnesį %1$s visą dieną",
"Every Month on the %1$s for the entire day until %2$s" : "Kiekvieną mėnesį %1$s visą dieną iki %2$s",
"Every Month on the %1$s between %2$s - %3$s" : "Kiekvieną mėnesį %1$s tarp %2$s - %3$s",
"Every Month on the %1$s between %2$s - %3$s until %4$s" : "Kiekvieną mėnesį %1$s tarp %2$s - %3$s iki %4$s",
"Every %1$d Months on the %2$s for the entire day" : "Kiekvieną %1$d mėnesį %2$s visą dieną",
"Every %1$d Months on the %2$s for the entire day until %3$s" : "Kiekvieną %1$d mėnesį %2$s visą dieną iki %3$s",
"Every %1$d Months on the %2$s between %3$s - %4$s" : "Kiekvieną %1$d mėnesį %2$s tarp %3$s - %4$s",
"Every %1$d Months on the %2$s between %3$s - %4$s until %5$s" : "Kiekvieną %1$d mėnesį %2$s tarp %3$s - %4$s iki %5$s",
"Every Year in %1$s on the %2$s for the entire day" : "Kiekvienais metais %1$s , %2$s visą dieną",
"Every Year in %1$s on the %2$s for the entire day until %3$s" : "Kiekvienais metais %1$s , %2$s visą dieną iki %3$s",
"Every Year in %1$s on the %2$s between %3$s - %4$s" : "Kiekvienais metais %1$s , %2$s tarp %3$s - %4$s",
"Every Year in %1$s on the %2$s between %3$s - %4$s until %5$s" : "Kiekvienais metais %1$s , %2$s tarp %3$s - %4$s iki %5$s",
"Every %1$d Years in %2$s on the %3$s for the entire day" : "Kiekvienais %1$d metais %2$s, %3$s visą dieną",
"Every %1$d Years in %2$s on the %3$s for the entire day until %4$s" : "Kiekvienais %1$d metais %2$s , %3$s visą dieną iki %4$s",
"Every %1$d Years in %2$s on the %3$s between %4$s - %5$s" : "Kiekvienais %1$d metais %2$s , %3$s tarp %4$s - %5$s",
"Every %1$d Years in %2$s on the %3$s between %4$s - %5$s until %6$s" : "Kiekvienais %1$d metais %2$s , %3$s tarp %4$s - %5$s iki %6$s",
"On specific dates for the entire day until %1$s" : "Konkrečiomis datomis visą dieną iki %1$s",
"On specific dates between %1$s - %2$s until %3$s" : "Konkrečiomis datomis tarp %1$s - %2$s iki %3$s",
"In the past on %1$s" : "Praeityje %1$s",
"_In %n minute on %1$s_::_In %n minutes on %1$s_" : ["Per %n minutę %1$s","Per %n minutes %1$s","Per %n minučių %1$s","Per %n minučių %1$s"],
"_In %n hour on %1$s_::_In %n hours on %1$s_" : ["Per %n valandą %1$s","Per %n valandas %1$s","Per %n valandų %1$s","Per %n valandų %1$s"],
"_In %n day on %1$s_::_In %n days on %1$s_" : ["Per %n dieną %1$s","Per %n dienas %1$s","Per %n dienų %1$s","Per %n dienų %1$s"],
"_In %n week on %1$s_::_In %n weeks on %1$s_" : ["Per %n savaitę %1$s","Per %n savaites %1$s","Per %n savaičių %1$s","Per %n savaičių %1$s"],
"_In %n month on %1$s_::_In %n months on %1$s_" : ["Per %n mėnesį %1$s","Per %n mėnesius %1$s","Per %n mėnesių %1$s","Per %n mėnesių %1$s"],
"_In %n year on %1$s_::_In %n years on %1$s_" : ["Per %n metus %1$s","Per %n metus %1$s","Per %n metų %1$s","Per %n metų %1$s"],
"In the past on %1$s then on %2$s" : "Anksčiau %1$s tuomet %2$s",
"_In %n minute on %1$s then on %2$s_::_In %n minutes on %1$s then on %2$s_" : ["Per %n minutę %1$s tuomet %2$s","Per %n minutes %1$s tuomet %2$s","Per %n minučių %1$s tuomet %2$s","Per %n minučių %1$s tuomet %2$s"],
"_In %n hour on %1$s then on %2$s_::_In %n hours on %1$s then on %2$s_" : ["Per %n valandą %1$s tuomet %2$s","Per %n valandas %1$s tuomet %2$s","Per %n valandų %1$s tuomet %2$s","Per %n valandų %1$s tuomet %2$s"],
"_In %n day on %1$s then on %2$s_::_In %n days on %1$s then on %2$s_" : ["Per %n dieną %1$s tuomet %2$s","Per %n dienas %1$s tuomet %2$s","Per %n dienų %1$s tuomet %2$s","Per %n dienų %1$s tuomet %2$s"],
"_In %n week on %1$s then on %2$s_::_In %n weeks on %1$s then on %2$s_" : ["Per %n savaitę %1$s tuomet %2$s","Per %n savaites %1$s tuomet %2$s","Per %n savaičių %1$s tuomet %2$s","Per %n savaičių %1$s tuomet %2$s"],
"_In %n month on %1$s then on %2$s_::_In %n months on %1$s then on %2$s_" : ["Per %n mėnesį %1$s tuomet %2$s","Per %n mėnesius %1$s tuomet %2$s","Per %n mėnesių %1$s tuomet %2$s","Per %n mėnesių %1$s tuomet %2$s"],
"_In %n year on %1$s then on %2$s_::_In %n years on %1$s then on %2$s_" : ["Per %n metus %1$s tuomet %2$s","Per %n metus %1$s tuomet %2$s","Per %n metų %1$s tuomet %2$s","Per %n metų %1$s tuomet %2$s"],
"In the past on %1$s then on %2$s and %3$s" : "Anksčiau %1$s tuomet %2$s ir %3$s",
"_In %n minute on %1$s then on %2$s and %3$s_::_In %n minutes on %1$s then on %2$s and %3$s_" : ["Per %n minutę %1$s tuomet %2$s ir %3$s","Per %n minutes %1$s tuomet %2$s ir %3$s","Per %n minučių %1$s tuomet %2$s ir %3$s","Per %n minučių %1$s tuomet %2$s ir %3$s"],
"_In %n hour on %1$s then on %2$s and %3$s_::_In %n hours on %1$s then on %2$s and %3$s_" : ["Per %n valandą %1$s tuomet %2$s ir %3$s","Per %n valandas %1$s tuomet %2$s ir %3$s","Per %n valandų %1$s tuomet %2$s ir %3$s","Per %n valandų %1$s tuomet %2$s ir %3$s"],
"_In %n day on %1$s then on %2$s and %3$s_::_In %n days on %1$s then on %2$s and %3$s_" : ["Per %n dieną %1$s tuomet %2$s ir %3$s","Per %n dienas %1$s tuomet %2$s ir %3$s","Per %n dienų %1$s tuomet %2$s ir %3$s","Per %n dienų %1$s tuomet %2$s ir %3$s"],
"_In %n week on %1$s then on %2$s and %3$s_::_In %n weeks on %1$s then on %2$s and %3$s_" : ["Per %n savaitę %1$s tuomet %2$s ir %3$s","Per %n savaites %1$s tuomet %2$s ir %3$s","Per %n savaičių %1$s tuomet %2$s ir %3$s","Per %n savaičių %1$s tuomet %2$s ir %3$s"],
"_In %n month on %1$s then on %2$s and %3$s_::_In %n months on %1$s then on %2$s and %3$s_" : ["Per %n mėnesį %1$s tuomet %2$s ir %3$s","Per %n mėnesius %1$s tuomet %2$s ir %3$s","Per %n mėnesių %1$s tuomet %2$s ir %3$s","Per %n mėnesių %1$s tuomet %2$s ir %3$s"],
"_In %n year on %1$s then on %2$s and %3$s_::_In %n years on %1$s then on %2$s and %3$s_" : ["Per %n metus %1$s tuomet %2$s ir %3$s","Per %n metus %1$s tuomet %2$s ir %3$s","Per %n metų %1$s tuomet %2$s ir %3$s","Per %n metų %1$s tuomet %2$s ir %3$s"],
"Could not generate next recurrence statement" : "Nepavyko sugeneruoti kito pasikartojimo sakinio",
"Cancelled: %1$s" : "Atšaukta: %1$s",
"\"%1$s\" has been canceled" : "\"%1$s\" buvo atšauktas",
"Re: %1$s" : "Dėl: %1$s",
"%1$s has accepted your invitation" : "%1$s priėmė jūsų kvietimą",
"%1$s has tentatively accepted your invitation" : "%1$s preliminariai priėmė jūsų kvietimą",
"%1$s has declined your invitation" : "%1$s atmetė jūsų kvietimą",
"%1$s has responded to your invitation" : "%1$s atsakė į jūsų kvietimą",
"Invitation updated: %1$s" : "Kvietimas atnaujintas: %1$s",
"%1$s updated the event \"%2$s\"" : "%1$s atnaujino įvykį \"%2$s\"",
"Invitation: %1$s" : "Pakvietimas: %1$s",
"%1$s would like to invite you to \"%2$s\"" : "%1$s norėtų jus pakviesti į \"%2$s\"",
"Organizer:" : "Organizatorius:",
"Attendees:" : "Kviestiniai:",
"Title:" : "Pavadinimas:",
"When:" : "Kada:",
"Location:" : "Vieta:",
"Link:" : "Nuoroda:",
"Occurring:" : "Pasitaiko:",
"Accept" : "Priimti",
"Decline" : "Atmesti",
"More options …" : "Daugiau parinkčių…",
"More options at %s" : "Daugiau parinkčių %s",
"Monday" : "Pirmadienis",
"Tuesday" : "Antradienis",
"Wednesday" : "Trečiadienis",
"Thursday" : "Ketvirtadienis",
"Friday" : "Penktadienis",
"Saturday" : "Šeštadienis",
"Sunday" : "Sekmadienis",
"January" : "Sausis",
"February" : "Vasaris",
"March" : "Kovas",
"April" : "Balandis",
"May" : "Gegužė",
"June" : "Birželis",
"July" : "Liepa",
"August" : "Rugpjūtis",
"September" : "Rugsėjis",
"October" : "Spalis",
"November" : "Lapkritis",
"December" : "Gruodis",
"First" : "Pirmas",
"Second" : "Antras",
"Third" : "Trečias",
"Fourth" : "Ketvirtas",
"Fifth" : "Penktas",
"Last" : "Paskutinis",
"Second Last" : "Antras paskutinis",
"Third Last" : "Trečias paskutinis",
"Fourth Last" : "Ketvirtasis paskutinis",
"Fifth Last" : "Penktas paskutinis",
"Contacts" : "Adresatai",
"{actor} created address book {addressbook}" : "{actor} sukūrė adresų knygą {addressbook}",
"You created address book {addressbook}" : "Jūs sukūrėte adresų knygą {addressbook}",
"{actor} deleted address book {addressbook}" : "{actor} ištrynė adresų knygą {addressbook}",
"You deleted address book {addressbook}" : "Jūs ištrynėte adresų knygą {addressbook}",
"{actor} updated address book {addressbook}" : "{actor} atnaujino adresų knygą {addressbook}",
"You updated address book {addressbook}" : "Jūs atnaujinote adresų knygą {addressbook}",
"{actor} shared address book {addressbook} with you" : "{actor} pasidalino su jumis {addressbook} adresų knyga",
"You shared address book {addressbook} with {user}" : "Jūs pasidalinote {addressbook} adresų knyga su {user}",
"{actor} shared address book {addressbook} with {user}" : "{actor} pasidalino {addressbook} adresų knyga su {user}",
"{actor} unshared address book {addressbook} from you" : "{actor} atšaukė su jumis bendrinamą {addressbook} adresų knygą",
"You unshared address book {addressbook} from {user}" : "Jūs atšaukėte bendrinamą {addressbook} adresų knygą su {user}",
"{actor} unshared address book {addressbook} from {user}" : "{actor} atšaukė {addressbook} bendrinamą adresų knygą su {user}",
"{actor} unshared address book {addressbook} from themselves" : "{actor} atšaukė savo paties bendrinamą {addressbook} adresų knygą",
"You shared address book {addressbook} with group {group}" : "Jūs bendrinote {addressbook} adresų knygą su {group} grupe",
"{actor} shared address book {addressbook} with group {group}" : "{actor} bendrino {addressbook} adresų knygą su {group} grupe",
"You unshared address book {addressbook} from group {group}" : "Jūs atšaukėte bendrinamą {addressbook}adresų knygą su {group} grupe",
"{actor} unshared address book {addressbook} from group {group}" : "{actor} atšaukė bendrinamą {addressbook} adresų knygą su {group} grupe",
"{actor} created contact {card} in address book {addressbook}" : "{actor} sukūrė {card} kontaktą {addressbook} adresų knygoje",
"You created contact {card} in address book {addressbook}" : "Jūs sukūrėte {card} kontaktą {addressbook} adresų knygoje",
"{actor} deleted contact {card} from address book {addressbook}" : "{actor} ištrynė {card} kontaktų iš {addressbook} adresų knygos",
"You deleted contact {card} from address book {addressbook}" : "Jūs ištrynėte {card} kontaktą iš {addressbook} adresų knygos",
"{actor} updated contact {card} in address book {addressbook}" : "{actor} atnaujino {card} kontaktą {addressbook} adresų knygoje",
"You updated contact {card} in address book {addressbook}" : "Jūs atnaujinote {card} kontaktą {addressbook} adresų knygoje",
"A <strong>contact</strong> or <strong>address book</strong> was modified" : "<strong>kontaktas</strong> arba <strong>adresų knyga</strong> buvo atnaujinta",
"System address book disabled" : "Sistemos adresų knyga išjungta",
"The system contacts address book has been automatically disabled during upgrade. This means that the address book will no longer be available to users in the contacts app or other clients. The system contacts address book was disabled because the amount of contacts in the address book exceeded the maximum recommended number of contacts. This limit is set to prevent performance issues. You can re-enable the system address book with the following command {command}" : "Sistemos kontaktų adresų knyga buvo automatiškai išjungta atnaujinimo metu. Tai reiškia, kad adresų knyga nebebus pasiekiama vartotojams kontaktų programėlėje ar kituose klientuose. Sistemos kontaktų adresų knyga buvo išjungta, nes joje esančių kontaktų skaičius viršijo maksimalų rekomenduojamą kontaktų skaičių. Šis apribojimas nustatytas siekiant išvengti našumo problemų. Sistemos adresų knygą galite iš naujo įjungti naudodami šią komandą {command}.",
"Accounts" : "Paskyros",
"System address book which holds all accounts" : "Sistemos adresų knyga, kurioje saugomos visos paskyros",
"File is not updatable: %1$s" : "Failo atnaujinamas negalimas: %1$s",
"Failed to get storage for file" : "Nepavyko gauti failo saugyklos vietos",
"Could not write to final file, canceled by hook" : "Nepavyko įrašyti į galutinį failą, atšaukta naudojant interceptorių",
"Could not write file contents" : "Nepavyko įrašyti failo turinio",
"_%n byte_::_%n bytes_" : ["%n baitas","%n baitai","%n baitų","%n baitų"],
"Error while copying file to target location (copied: %1$s, expected filesize: %2$s)" : "Klaida kopijuojant failą į paskirties vietą (nukopijuota: %1$s, numatomas failo dydis: %2$s)",
"Expected filesize of %1$s but read (from Nextcloud client) and wrote (to Nextcloud storage) %2$s. Could either be a network problem on the sending side or a problem writing to the storage on the server side." : "Tikėtasi %1$s failo dydžio, bet nuskaityta (iš „Nextcloud“ kliento) ir įrašyta (į „Nextcloud“ saugyklą) %2$s. Gali būti tinklo problema siuntėjo pusėje arba problema rašant į saugyklą serverio pusėje.",
"Could not rename part file to final file, canceled by hook" : "Nepavyko pervadinti dalinio failo į galutinį failą, atšaukta naudojant interceptorių",
"Could not rename part file to final file" : "Nepavyko pervadinti dalinio failo į galutinį failą",
"Failed to check file size: %1$s" : "Nepavyko patikrinti failo dydžio: %1$s",
"Could not open file: %1$s (%2$d), file does seem to exist" : "Nepavyko atidaryti failo: %1$s (%2$d), atrodo, kad failas egzistuoja",
"Could not open file: %1$s (%2$d), file doesn't seem to exist" : "Nepavyko atidaryti failo: %1$s (%2$d), atrodo, kad failo nėra",
"Failed to get size for : %1$s" : "Nepavyko gauti %1$s dydžio",
"Encryption not ready: %1$s" : "Šifravimas neparuoštas: %1$s",
"Failed to open file: %1$s" : "Nepavyko atverti failo: %1$s",
"Failed to unlink: %1$s" : "Nepavyko atsieti: %1$s",
"Failed to write file contents: %1$s" : "Nepavyko įrašyti failo turinio: %1$s",
"File not found: %1$s" : "Failas nerastas: %1$s",
"Invalid target path" : "Netinkamas tikslinis kelias",
"System is in maintenance mode." : "Sistema yra techninės priežiūros veiksenoje.",
"Upgrade needed" : "Reikalingas naujinimas",
"Your %s needs to be configured to use HTTPS in order to use CalDAV and CardDAV with iOS/macOS." : "Norint naudoti CalDAV ir CardDAV su iOS/macOS, jūsų %s turi būti sukonfigūruota taip, kad naudotų HTTPS.",
"Configures a CalDAV account" : "Konfigūruoja CalDAV paskyrą",
"Configures a CardDAV account" : "Konfigūruoja CardDAV paskyrą",
"Events" : "Įvykiai",
"Untitled task" : "Užduotis be pavadinimo",
"Completed on %s" : "Pabaigta %s",
"Due on %s by %s" : "Laukiamas %s iki %s",
"Due on %s" : "Laukiamas %s",
"This is an example contact" : "Tai yra kontakto pavyzdys",
"Welcome to Nextcloud Calendar!\n\nThis is a sample event - explore the flexibility of planning with Nextcloud Calendar by making any edits you want!\n\nWith Nextcloud Calendar, you can:\n- Create, edit, and manage events effortlessly.\n- Create multiple calendars and share them with teammates, friends, or family.\n- Check availability and display your busy times to others.\n- Seamlessly integrate with apps and devices via CalDAV.\n- Customize your experience: schedule recurring events, adjust notifications and other settings." : "Sveiki atvykę į „Nextcloud“ kalendorių!\n\nTai pavyzdinis įrašas išbandykite planavimo lankstumą su „Nextcloud“ kalendoriumi, atlikdami bet kokius norimus pakeitimus!\n\nSu „Nextcloud“ kalendoriumi galite:\n- Nesunkiai kurti, redaguoti ir valdyti įvykius.\n- Kurti kelis kalendorius ir bendrinti juos su komandos nariais, draugais ar šeima.\n- Patikrinti prieinamumą ir rodyti savo užimtumo laiką kitiems.\n- Sklandžiai integruotis su programėlėmis ir įrenginiais per „CalDAV“.\n- Tinkinti savo patirtį: planuoti pasikartojančius įvykius, koreguoti pranešimus ir kitus nustatymus.",
"Example event - open me!" : "Pavyzdinis įvykis atverk mane!",
"System Address Book" : "Sistemos adresų knyga",
"The system address book contains contact information for all users in your instance." : "Sistemos adresų knygoje yra visų jūsų turimų vartotojų kontaktinė informacija.",
"Enable System Address Book" : "Įjungti sistemos adresų knygą",
"DAV system address book" : "DAV sistemos adresų knyga",
"No outstanding DAV system address book sync." : "Nėra jokių nepatvirtintų DAV sistemos adresų knygos sinchronizavimo.",
"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\"." : "DAV sistemos adresų knygos sinchronizavimas dar nebuvo paleistas, nes jūsų egzemplioriuje yra daugiau nei 1000 vartotojų arba įvyko klaida. Paleiskite jį rankiniu būdu, iškviečiant „occ dav:sync-system-addressbook“.",
"DAV system address book size" : "DAV sistemos adresų knygos dydis",
"The system address book is disabled" : "Sistemos adresų knyga išjungta",
"The system address book is enabled, but contains more than the configured limit of %d contacts" : "Sistemos adresų knyga įjungta ir joje yra daugiau kontaktų nei nustatyta riba, t.y. %d kontaktų",
"The system address book is enabled and contains less than the configured limit of %d contacts" : "Sistemos adresų knyga įjungta ir joje yra mažiau kontaktų nei nustatyta riba, t.y. %d kontaktų",
"WebDAV endpoint" : "WebDAV galutinis taškas",
"Could not check that your web server is properly set up to allow file synchronization over WebDAV. Please check manually." : "Nepavyko patikrinti, ar jūsų žiniatinklio serveris tinkamai nustatytas leisti failų sinchronizavimą per WebDAV. Patikrinkite rankiniu būdu.",
"Your web server is not yet properly set up to allow file synchronization, because the WebDAV interface seems to be broken." : "Jūsų svetainės serveris nėra tinkamai sukonfiguruotas, Failų sinchronizavimas negalimas, nes neveikia WebDAV interfeisas.",
"Your web server is properly set up to allow file synchronization over WebDAV." : "Jūsų žiniatinklio serveris tinkamai sukonfigūruotas, kad būtų galima sinchronizuoti failus per WebDAV.",
"Calendars including events, details and attendees" : "Kalendoriai su įvykiais, informacija ir dalyviais",
"Migrated calendar (%1$s)" : "Perkeltas kalendorius (%1$s)",
"Contacts and groups" : "Adresatai ir grupės",
"WebDAV" : "WebDAV",
"Absence saved" : "Išsaugotas nebuvimas",
"Failed to save your absence settings" : "Nepavyko išsaugoti jūsų nebuvimo nustatymų",
"Absence cleared" : "Nebuvimas pašalintas",
"Failed to clear your absence settings" : "Nepavyko išvalyti nedalyvavimo nustatymų",
"First day" : "Pirma diena",
"Last day (inclusive)" : "Paskutinė diena (imtinai)",
"Out of office replacement (optional)" : "Nebuvimo biure pakeitimas (neprivaloma)",
"Name of the replacement" : "Pakeitimo pavadinimas",
"Short absence status" : "Trumpo nebuvimo būsena",
"Long absence Message" : "Ilgo nebuvimo žinutė",
"Save" : "Įrašyti",
"Disable absence" : "Išjungti nebuvimą",
"Failed to load availability" : "Nepavyko įkelti prieinamumo",
"Saved availability" : "Išsaugotas pasiekiamumas",
"Failed to save availability" : "Nepavyko išsaugoti pasiekiamumo",
"to" : "iki",
"Delete slot" : "Ištrinti laiko tarpą",
"No working hours set" : "Nenustatyta jokių darbo valandų",
"Add slot" : "Pridėti laiko tarpą",
"Weekdays" : "Šiokiadieniai",
"Pick a start time for {dayName}" : "Pasirinkite {dayName} pradžios laiką",
"Pick a end time for {dayName}" : "Pasirinkite {dayName} pabaigos laiką",
"Automatically set user status to \"Do not disturb\" outside of availability to mute all notifications." : "Automatiškai nustatyti naudotojo būseną į „Netrukdyti“, kai jis nėra pasiekiamas, kad būtų nutildyti visi pranešimai.",
"Cancel" : "Atsisakyti",
"Import" : "Importuoti",
"Error while saving settings" : "Klaida įrašant nustatymus",
"Contact reset successfully" : "Kontaktas sėkmingai nustatytas iš naujo",
"Error while resetting contact" : "Iš naujo nustatant kontaktą įvyko klaida",
"Contact imported successfully" : "Kontaktas sėkmingai importuotas",
"Error while importing contact" : "Importuojant kontaktą įvyko klaida",
"Import contact" : "Importuoti kontaktą",
"Reset to default" : "Atstatyti į numatytąjį",
"Import contacts" : "Importuoti kontaktus",
"Importing a new .vcf file will delete the existing default contact and replace it with the new one. Do you want to continue?" : "Importuojant naują .vcf failą, esamas numatytasis kontaktas bus ištrintas ir pakeistas nauju. Ar norite tęsti?",
"Failed to save example event creation setting" : "Nepavyko išsaugoti pavyzdinio įvykio kūrimo nustatymo",
"Failed to upload the example event" : "Nepavyko įkelti pavyzdinio įvykio",
"Custom example event was saved successfully" : "Pasirinktinis pavyzdinis įvykis sėkmingai išsaugotas",
"Failed to delete the custom example event" : "Nepavyko ištrinti pasirinktinio pavyzdžio įvykio",
"Custom example event was deleted successfully" : "Pasirinktinis pavyzdinis įvykis sėkmingai ištrintas",
"Import calendar event" : "Importuoti kalendoriaus įvykį",
"Uploading a new event will overwrite the existing one." : "Įkėlus naują įvykį, esamas bus perrašytas.",
"Upload event" : "Įkelti įvykį",
"Also install the {calendarappstoreopen}Calendar app{linkclose}, or {calendardocopen}connect your desktop & mobile for syncing ↗{linkclose}." : "Taip pat įsidiekite {calendarappstoreopen}Kalendoriaus programėlę{linkclose} arba sinchronizavimui {calendardocopen}prijunkite savo darbalaukį ir mobilųjį ↗{linkclose}.",
"Please make sure to properly set up {emailopen}the email server{linkclose}." : "Įsitikinkite, kad tinkamai nusistatėte {emailopen}el. pašto serverį{linkclose}.",
"Calendar server" : "Kalendoriaus serveris",
"Send invitations to attendees" : "Siųsti pakvietimus kviestiniams",
"Automatically generate a birthday calendar" : "Automatiškai sukurti gimtadienių kalendorių",
"Birthday calendars will be generated by a background job." : "Gimtadienių kalendoriai bus sukurti foninės užduoties.",
"Hence they will not be available immediately after enabling but will show up after some time." : "Tai reiškia, kad jie nebus matomi iš karto įjungus, o pasirodys tik po kurio laiko.",
"Send notifications for events" : "Siųsti įvykių pranešimus",
"Notifications are sent via background jobs, so these must occur often enough." : "Pranešimai yra siunčiami per fonines užduotis, todėl jos privalo būti vykdomos gana dažnai.",
"Send reminder notifications to calendar sharees as well" : "Siųskite priminimus ir tiems, kurie bendrina kalendorių",
"Reminders are always sent to organizers and attendees." : "Priminimai visada siunčiami organizatoriams ir dalyviams.",
"Enable notifications for events via push" : "Įjungti pranešimus apie įvykius per tiesioginius pranešimus",
"Example content" : "Turinio pavyzdys",
"Example content serves to showcase the features of Nextcloud. Default content is shipped with Nextcloud, and can be replaced by custom content." : "Pavyzdinis turinys skirtas „Nextcloud“ funkcijoms demonstruoti. Numatytasis turinys pateikiamas kartu su „Nextcloud“ ir gali būti pakeistas pasirinktiniu turiniu.",
"Availability" : "Pasiekiamumas",
"If you configure your working hours, other people will see when you are out of office when they book a meeting." : "Jei sukonfigūruosite savo darbo valandas, kiti žmonės, rezervuodami susitikimą, matys, kada esate išvykę.",
"Absence" : "Nebuvimas",
"Configure your next absence period." : "Konfigūruokite kitą nebuvimo laikotarpį.",
"There was an error updating your attendance status." : "Atnaujinant lankomumo būseną įvyko klaida.",
"Please contact the organizer directly." : "Prašome susisiekti su organizatoriumi tiesiogiai.",
"Are you accepting the invitation?" : "Ar priimate pakvietimą?",
"Tentative" : "Preliminarus",
"Your attendance was updated successfully." : "Jūsų lankomumas sėkmingai atnaujintas.",
"No results." : "Jokių rezultatų.",
"Start typing." : "Start typing."
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
}
+1 -1
View File
@@ -76,7 +76,7 @@ class BulkUploadPlugin extends ServerPlugin {
'error' => false,
'etag' => $node->getETag(),
'fileid' => DavUtil::getDavFileId($node->getId()),
'permissions' => DavUtil::getDavPermissions($node),
'permissions' => DavUtil::getDavPermissions($node, $node->getParent()),
];
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), ['path' => $headers['x-file-path']]);
+3 -3
View File
@@ -190,7 +190,7 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
];
/** @var array parameters to index */
public static array $indexParameters = [
private const INDEXED_PARAMETERS = [
'ATTENDEE' => ['CN'],
'ORGANIZER' => ['CN'],
];
@@ -3386,9 +3386,9 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
$query->executeStatement();
}
if (array_key_exists($property->name, self::$indexParameters)) {
if (array_key_exists($property->name, self::INDEXED_PARAMETERS)) {
$parameters = $property->parameters();
$indexedParametersForProperty = self::$indexParameters[$property->name];
$indexedParametersForProperty = self::INDEXED_PARAMETERS[$property->name];
foreach ($parameters as $key => $value) {
if (in_array($key, $indexedParametersForProperty)) {
+2 -1
View File
@@ -20,7 +20,7 @@ class Capabilities implements ICapability {
}
/**
* @return array{dav: array{chunking: string, public_shares_chunking: bool, search_supports_creation_time: bool, search_supports_upload_time: bool, bulkupload?: string, absence-supported?: bool, absence-replacement?: bool}}
* @return array{dav: array{chunking: string, public_shares_chunking: bool, search_supports_creation_time: bool, search_supports_upload_time: bool, search_supports_last_activity: bool, bulkupload?: string, absence-supported?: bool, absence-replacement?: bool}}
*/
public function getCapabilities() {
$capabilities = [
@@ -29,6 +29,7 @@ class Capabilities implements ICapability {
'public_shares_chunking' => true,
'search_supports_creation_time' => true,
'search_supports_upload_time' => true,
'search_supports_last_activity' => true,
]
];
if ($this->config->getSystemValueBool('bulkupload.enabled', true)) {
+2 -2
View File
@@ -42,7 +42,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
private string $dbCardsPropertiesTable = 'cards_properties';
/** @var array properties to index */
public static array $indexProperties = [
private const INDEXED_PROPERTIES = [
'BDAY', 'UID', 'N', 'FN', 'TITLE', 'ROLE', 'NOTE', 'NICKNAME',
'ORG', 'CATEGORIES', 'EMAIL', 'TEL', 'IMPP', 'ADR', 'URL', 'GEO',
'CLOUD', 'X-SOCIALPROFILE'];
@@ -1384,7 +1384,7 @@ class CardDavBackend implements BackendInterface, SyncSupport {
);
foreach ($vCard->children() as $property) {
if (!in_array($property->name, self::$indexProperties)) {
if (!in_array($property->name, self::INDEXED_PROPERTIES)) {
continue;
}
$preferred = 0;
@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Connector\Sabre;
/**
* A stream filter to track how many bytes have been streamed from a stream.
*/
class ByteCounterFilter extends \php_user_filter {
/** @psalm-suppress NonInvariantPropertyType PHP crashes without string type */
public string $filtername = 'ByteCounter';
public function filter($in, $out, &$consumed, bool $closing): int {
$counter = $this->params['counter'] ?? null;
while ($bucket = stream_bucket_make_writeable($in)) {
$length = $bucket->datalen;
$consumed += $length;
if ($counter instanceof StreamByteCounter) {
$counter->bytes += $length;
}
stream_bucket_append($out, $bucket);
}
return PSFS_PASS_ON;
}
}
+18 -4
View File
@@ -68,6 +68,7 @@ class FilesPlugin extends ServerPlugin {
public const METADATA_ETAG_PROPERTYNAME = '{http://nextcloud.org/ns}metadata_etag';
public const UPLOAD_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}upload_time';
public const CREATION_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}creation_time';
public const LAST_ACTIVITY_PROPERTYNAME = '{http://nextcloud.org/ns}last_activity';
public const SHARE_NOTE = '{http://nextcloud.org/ns}note';
public const SHARE_HIDE_DOWNLOAD_PROPERTYNAME = '{http://nextcloud.org/ns}hide-download';
public const SUBFOLDER_COUNT_PROPERTYNAME = '{http://nextcloud.org/ns}contained-folder-count';
@@ -202,10 +203,19 @@ class FilesPlugin extends ServerPlugin {
// First check copyable (move only needs additional delete permission)
$this->checkCopy($source, $target);
// The source needs to be deletable for moving
$sourceNodeFileInfo = $sourceNode->getFileInfo();
if (!$sourceNodeFileInfo->isDeletable()) {
throw new Forbidden($source . ' cannot be deleted');
[$sourceDir] = \Sabre\Uri\split($source);
[$destinationDir, ] = \Sabre\Uri\split($target);
if ($sourceDir === $destinationDir) {
if (!$sourceNode->canRename()) {
throw new Forbidden($source . ' cannot be renamed');
}
} else {
// The source needs to be deletable for moving
$sourceNodeFileInfo = $sourceNode->getFileInfo();
if (!$sourceNodeFileInfo->isDeletable()) {
throw new Forbidden($source . ' cannot be deleted');
}
}
// The source is not allowed to be the parent of the target
@@ -437,6 +447,10 @@ class FilesPlugin extends ServerPlugin {
return $node->getFileInfo()->getCreationTime();
});
$propFind->handle(self::LAST_ACTIVITY_PROPERTYNAME, function () use ($node) {
return $node->getFileInfo()->getLastActivity();
});
foreach ($node->getFileInfo()->getMetadata() as $metadataKey => $metadataValue) {
$propFind->handle(self::FILE_METADATA_PREFIX . $metadataKey, $metadataValue);
}
+10 -5
View File
@@ -112,6 +112,13 @@ abstract class Node implements INode {
return $this->path;
}
/**
* Check if this node can be renamed
*/
public function canRename(): bool {
return DavUtil::canRename($this->node, $this->node->getParent());
}
/**
* Renames the node
*
@@ -123,10 +130,8 @@ abstract class Node implements INode {
* @throws LockedException
*/
public function setName($name): void {
// rename is only allowed if the delete privilege is granted
// (basically rename is a copy with delete of the original node)
if (!$this->info->isDeletable() && !($this->info->getMountPoint() instanceof MoveableMount && $this->info->getInternalPath() === '')) {
throw new Forbidden();
if (!$this->canRename()) {
throw new Forbidden('');
}
/** @var string $parentPath */
@@ -320,7 +325,7 @@ abstract class Node implements INode {
}
public function getDavPermissions(): string {
return DavUtil::getDavPermissions($this->info);
return DavUtil::getDavPermissions($this->info, $this->node->getParent());
}
/**
@@ -110,6 +110,8 @@ class ServerFactory {
$this->logger,
$this->eventDispatcher,
\OCP\Server::get(IDateTimeZone::class),
$this->config,
$this->l10n,
));
// Some WebDAV clients do require Class 2 WebDAV support (locking), since
@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Connector\Sabre;
/**
* Class to use in combination with ByteCounterFilter to keep track of how much
* has been read from a stream.
*
* @see ByteCounterFilter
*/
class StreamByteCounter {
public float|int $bytes = 0;
}
+128 -22
View File
@@ -15,7 +15,9 @@ use OCP\Files\Events\BeforeZipCreatedEvent;
use OCP\Files\File as NcFile;
use OCP\Files\Folder as NcFolder;
use OCP\Files\Node as NcNode;
use OCP\IConfig;
use OCP\IDateTimeZone;
use OCP\IL10N;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
@@ -37,13 +39,22 @@ class ZipFolderPlugin extends ServerPlugin {
* Reference to main server object
*/
private ?Server $server = null;
private bool $reportMissingFiles;
private array $missingInfo = [];
public function __construct(
private Tree $tree,
private LoggerInterface $logger,
private IEventDispatcher $eventDispatcher,
private IDateTimeZone $timezoneFactory,
private IConfig $config,
private IL10N $l10n,
) {
$this->reportMissingFiles = $this->config->getSystemValueBool('archive_report_missing_files', false);
if ($this->reportMissingFiles) {
stream_filter_register('count.bytes', ByteCounterFilter::class);
}
}
/**
@@ -63,27 +74,78 @@ class ZipFolderPlugin extends ServerPlugin {
/**
* Adding a node to the archive streamer.
* This will recursively add new nodes to the stream if the node is a directory.
* @return ?string an error message if an error occurred and reporting is enabled, null otherwise
*/
protected function streamNode(Streamer $streamer, NcNode $node, string $rootPath): void {
protected function streamNode(Streamer $streamer, NcNode $node, string $rootPath): ?string {
// Remove the root path from the filename to make it relative to the requested folder
$filename = str_replace($rootPath, '', $node->getPath());
$mtime = $node->getMTime();
if ($node instanceof NcFile) {
$resource = $node->fopen('rb');
if ($resource === false) {
$this->logger->info('Cannot read file for zip stream', ['filePath' => $node->getPath()]);
throw new \Sabre\DAV\Exception\ServiceUnavailable('Requested file can currently not be accessed.');
}
$streamer->addFileFromStream($resource, $filename, $node->getSize(), $mtime);
} elseif ($node instanceof NcFolder) {
if ($node instanceof NcFolder) {
$streamer->addEmptyDir($filename, $mtime);
$content = $node->getDirectoryListing();
foreach ($content as $subNode) {
$this->streamNode($streamer, $subNode, $rootPath);
}
return null;
}
if ($node instanceof NcFile) {
$nodeSize = $node->getSize();
try {
$stream = $node->fopen('rb');
} catch (\Exception $e) {
// opening failed, log the failure as reason for the missing file
if ($this->reportMissingFiles) {
$exceptionClass = get_class($e);
return $this->l10n->t('Error while opening the file: %s', [$exceptionClass]);
}
throw $e;
}
if ($this->reportMissingFiles) {
if ($stream === false) {
return $this->l10n->t('File could not be opened (fopen). Please check the server logs for more information.');
}
$byteCounter = new StreamByteCounter();
$wrapped = stream_filter_append($stream, 'count.bytes', STREAM_FILTER_READ, ['counter' => $byteCounter]);
if ($wrapped === false) {
return $this->l10n->t('Unable to check file for consistency check');
}
}
$fileAddedToStream = $streamer->addFileFromStream($stream, $filename, $nodeSize, $mtime);
if ($this->reportMissingFiles) {
if (!$fileAddedToStream) {
return $this->l10n->t('The archive was already finalized');
}
return $this->logStreamErrors($stream, $filename, $nodeSize, $byteCounter->bytes);
}
}
return null;
}
/**
* Checks whether $stream was fully streamed or if there were other issues
* with the stream, logging the error if necessary.
*
*/
private function logStreamErrors(mixed $stream, string $path, float|int $expectedFileSize, float|int $readFileSize): ?string {
$streamMetadata = stream_get_meta_data($stream);
if (!is_resource($stream) || get_resource_type($stream) !== 'stream') {
return $this->l10n->t('Resource is not a stream or is closed.');
}
if ($streamMetadata['timed_out'] ?? false) {
return $this->l10n->t('Timeout while reading from stream.');
}
if (!($streamMetadata['eof'] ?? true) || $readFileSize != $expectedFileSize) {
return $this->l10n->t('Read %d out of %d bytes from storage. This means the connection may have been closed due to a network/storage error.', [$expectedFileSize, $readFileSize]);
}
return null;
}
/**
@@ -137,7 +199,7 @@ class ZipFolderPlugin extends ServerPlugin {
}
$folder = $node->getNode();
$event = new BeforeZipCreatedEvent($folder, $files);
$event = new BeforeZipCreatedEvent($folder, $files, $this->reportMissingFiles);
$this->eventDispatcher->dispatchTyped($event);
if ((!$event->isSuccessful()) || $event->getErrorMessage() !== null) {
$errorMessage = $event->getErrorMessage();
@@ -150,12 +212,16 @@ class ZipFolderPlugin extends ServerPlugin {
throw new Forbidden($errorMessage);
}
// At this point either the event handlers did not block the download
// or they support the new mechanism that filters out nodes that are not
// downloadable, in either case we can use the new API to set the iterator
$content = empty($files) ? $folder->getDirectoryListing() : [];
foreach ($files as $path) {
$child = $node->getChild($path);
assert($child instanceof Node);
$content[] = $child->getNode();
}
$event->setNodesIterable($this->getIterableFromNodes($content));
$archiveName = $folder->getName();
if (count(explode('/', trim($folder->getPath(), '/'), 3)) === 2) {
@@ -169,31 +235,71 @@ class ZipFolderPlugin extends ServerPlugin {
$rootPath = dirname($folder->getPath());
}
$streamer = new Streamer($tarRequest, -1, count($content), $this->timezoneFactory);
// numberOfFiles is irrelevant as size=-1 forces the use of zip64 already
$streamer = new Streamer($tarRequest, -1, 0, $this->timezoneFactory);
$streamer->sendHeaders($archiveName);
// For full folder downloads we also add the folder itself to the archive
if (empty($files)) {
$streamer->addEmptyDir($archiveName);
}
foreach ($content as $node) {
$this->streamNode($streamer, $node, $rootPath);
foreach ($event->getNodes($rootPath) as $path => [$node, $reason]) {
$filename = str_replace($rootPath, '', $path);
if ($node === null) {
if ($this->reportMissingFiles) {
$this->missingInfo[$filename] = $reason;
}
continue;
}
$streamError = $this->streamNode($streamer, $node, $rootPath);
if ($this->reportMissingFiles && $streamError !== null) {
$this->missingInfo[$filename] = $streamError;
}
}
if ($this->reportMissingFiles && !empty($this->missingInfo)) {
$json = json_encode($this->missingInfo, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
$stream = fopen('php://temp', 'r+');
fwrite($stream, $json);
rewind($stream);
$streamer->addFileFromStream($stream, 'missing_files.json', (float)strlen($json), false);
}
$streamer->finalize();
return false;
}
/**
* Tell sabre/dav not to trigger it's own response sending logic as the handleDownload will have already send the response
* Given a set of nodes, produces a list of all nodes contained in them
* recursively.
*
* @param NcNode[] $nodes
* @return iterable<NcNode>
*/
private function getIterableFromNodes(array $nodes): iterable {
foreach ($nodes as $node) {
yield $node;
if ($node instanceof NcFolder) {
foreach ($node->getDirectoryListing() as $child) {
yield from $this->getIterableFromNodes([$child]);
}
}
}
}
/**
* Tell sabre/dav not to trigger its own response sending logic as the handleDownload will have already send the response
*
* @return false|null
*/
public function afterDownload(Request $request, Response $response): ?bool {
$node = $this->tree->getNodeForPath($request->getPath());
if (!($node instanceof Directory)) {
if ($node instanceof Directory) {
// only handle directories
return null;
} else {
return false;
}
return null;
}
}
+5
View File
@@ -88,6 +88,7 @@ class FileSearchBackend implements ISearchBackend {
new SearchPropertyDefinition('{DAV:}getlastmodified', true, true, true, SearchPropertyDefinition::DATATYPE_DATETIME),
new SearchPropertyDefinition('{DAV:}creationdate', true, true, true, SearchPropertyDefinition::DATATYPE_DATETIME),
new SearchPropertyDefinition('{http://nextcloud.org/ns}upload_time', true, true, true, SearchPropertyDefinition::DATATYPE_DATETIME),
new SearchPropertyDefinition('{http://nextcloud.org/ns}last_activity', true, false, true, SearchPropertyDefinition::DATATYPE_DATETIME),
new SearchPropertyDefinition(FilesPlugin::SIZE_PROPERTYNAME, true, true, true, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
new SearchPropertyDefinition(TagsPlugin::FAVORITE_PROPERTYNAME, true, true, true, SearchPropertyDefinition::DATATYPE_BOOLEAN),
new SearchPropertyDefinition(FilesPlugin::INTERNAL_FILEID_PROPERTYNAME, true, true, false, SearchPropertyDefinition::DATATYPE_NONNEGATIVE_INTEGER),
@@ -304,6 +305,8 @@ class FileSearchBackend implements ISearchBackend {
return $node->getNode()->getCreationTime();
case '{http://nextcloud.org/ns}upload_time':
return $node->getNode()->getUploadTime();
case '{http://nextcloud.org/ns}last_activity':
return $node->getNode()->getLastActivity();
case FilesPlugin::SIZE_PROPERTYNAME:
return $node->getSize();
case FilesPlugin::INTERNAL_FILEID_PROPERTYNAME:
@@ -332,6 +335,8 @@ class FileSearchBackend implements ISearchBackend {
$direction = $order->order === Order::ASC ? ISearchOrder::DIRECTION_ASCENDING : ISearchOrder::DIRECTION_DESCENDING;
if (str_starts_with($order->property->name, FilesPlugin::FILE_METADATA_PREFIX)) {
return new SearchOrder($direction, substr($order->property->name, strlen(FilesPlugin::FILE_METADATA_PREFIX)), IMetadataQuery::EXTRA);
} elseif ($order->property->name === FilesPlugin::LAST_ACTIVITY_PROPERTYNAME) {
return new SearchOrder($direction, 'last_activity');
} else {
return new SearchOrder($direction, $this->mapPropertyNameToColumn($order->property));
}
@@ -23,14 +23,14 @@ use Sabre\VObject\Component\VCard;
use Sabre\VObject\Reader;
class ContactsSearchProvider implements IFilteringProvider {
private static array $searchPropertiesRestricted = [
private const SEARCH_PROPERTIES_RESTRICTED = [
'N',
'FN',
'NICKNAME',
'EMAIL',
];
private static array $searchProperties = [
private const SEARCH_PROPERTIES = [
'N',
'FN',
'NICKNAME',
@@ -87,7 +87,7 @@ class ContactsSearchProvider implements IFilteringProvider {
$searchResults = $this->backend->searchPrincipalUri(
$principalUri,
$query->getFilter('term')?->get() ?? '',
$query->getFilter('title-only')?->get() ? self::$searchPropertiesRestricted : self::$searchProperties,
$query->getFilter('title-only')?->get() ? self::SEARCH_PROPERTIES_RESTRICTED : self::SEARCH_PROPERTIES,
[
'limit' => $query->getLimit(),
'offset' => $query->getCursor(),
+10 -10
View File
@@ -32,7 +32,7 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
/**
* @var string[]
*/
private static $searchProperties = [
private const SEARCH_PROPERTIES = [
'SUMMARY',
'LOCATION',
'DESCRIPTION',
@@ -42,9 +42,9 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
];
/**
* @var string[]
* @var array<string, string[]>
*/
private static $searchParameters = [
private const SEARCH_PARAMETERS = [
'ATTENDEE' => ['CN'],
'ORGANIZER' => ['CN'],
];
@@ -52,7 +52,7 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
/**
* @var string
*/
private static $componentType = 'VEVENT';
private const COMPONENT_TYPE = 'VEVENT';
/**
* @inheritDoc
@@ -102,9 +102,9 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
$searchResults = $this->backend->searchPrincipalUri(
$principalUri,
$term,
[self::$componentType],
self::$searchProperties,
self::$searchParameters,
[self::COMPONENT_TYPE],
self::SEARCH_PROPERTIES,
self::SEARCH_PARAMETERS,
[
'limit' => $query->getLimit(),
'offset' => $query->getCursor(),
@@ -122,9 +122,9 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
$attendeeSearchResults = $this->backend->searchPrincipalUri(
$principalUri,
$personDisplayName,
[self::$componentType],
[self::COMPONENT_TYPE],
['ATTENDEE'],
self::$searchParameters,
self::SEARCH_PARAMETERS,
[
'limit' => $query->getLimit(),
'offset' => $query->getCursor(),
@@ -148,7 +148,7 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
}
}
$formattedResults = \array_map(function (array $eventRow) use ($calendarsById, $subscriptionsById): SearchResultEntry {
$component = $this->getPrimaryComponent($eventRow['calendardata'], self::$componentType);
$component = $this->getPrimaryComponent($eventRow['calendardata'], self::COMPONENT_TYPE);
$title = (string)($component->SUMMARY ?? $this->l10n->t('Untitled event'));
if ($eventRow['calendartype'] === CalDavBackend::CALENDAR_TYPE_CALENDAR) {
+7 -7
View File
@@ -24,7 +24,7 @@ class TasksSearchProvider extends ACalendarSearchProvider {
/**
* @var string[]
*/
private static $searchProperties = [
private const SEARCH_PROPERTIES = [
'SUMMARY',
'DESCRIPTION',
'CATEGORIES',
@@ -33,12 +33,12 @@ class TasksSearchProvider extends ACalendarSearchProvider {
/**
* @var string[]
*/
private static $searchParameters = [];
private const SEARCH_PARAMETERS = [];
/**
* @var string
*/
private static $componentType = 'VTODO';
private const COMPONENT_TYPE = 'VTODO';
/**
* @inheritDoc
@@ -83,9 +83,9 @@ class TasksSearchProvider extends ACalendarSearchProvider {
$searchResults = $this->backend->searchPrincipalUri(
$principalUri,
$query->getFilter('term')?->get() ?? '',
[self::$componentType],
self::$searchProperties,
self::$searchParameters,
[self::COMPONENT_TYPE],
self::SEARCH_PROPERTIES,
self::SEARCH_PARAMETERS,
[
'limit' => $query->getLimit(),
'offset' => $query->getCursor(),
@@ -94,7 +94,7 @@ class TasksSearchProvider extends ACalendarSearchProvider {
]
);
$formattedResults = \array_map(function (array $taskRow) use ($calendarsById, $subscriptionsById):SearchResultEntry {
$component = $this->getPrimaryComponent($taskRow['calendardata'], self::$componentType);
$component = $this->getPrimaryComponent($taskRow['calendardata'], self::COMPONENT_TYPE);
$title = (string)($component->SUMMARY ?? $this->l10n->t('Untitled task'));
if ($taskRow['calendartype'] === CalDavBackend::CALENDAR_TYPE_CALENDAR) {
+4
View File
@@ -94,6 +94,7 @@ use OCP\ISession;
use OCP\ITagManager;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Mail\IEmailValidator;
use OCP\Mail\IMailer;
use OCP\Profiler\IProfiler;
@@ -243,6 +244,7 @@ class Server {
\OCP\Server::get(IUserSession::class)
));
$config = \OCP\Server::get(IConfig::class);
// performance improvement plugins
$this->server->addPlugin(new CopyEtagHeaderPlugin());
$this->server->addPlugin(new RequestIdHeaderPlugin(\OCP\Server::get(IRequest::class)));
@@ -255,6 +257,8 @@ class Server {
$logger,
$eventDispatcher,
\OCP\Server::get(IDateTimeZone::class),
$config,
\OCP\Server::get(IFactory::class)->get('dav'),
));
$this->server->addPlugin(\OCP\Server::get(PaginatePlugin::class));
$this->server->addPlugin(new PropFindPreloadNotifyPlugin());
+5 -1
View File
@@ -32,7 +32,8 @@
"chunking",
"public_shares_chunking",
"search_supports_creation_time",
"search_supports_upload_time"
"search_supports_upload_time",
"search_supports_last_activity"
],
"properties": {
"chunking": {
@@ -47,6 +48,9 @@
"search_supports_upload_time": {
"type": "boolean"
},
"search_supports_last_activity": {
"type": "boolean"
},
"bulkupload": {
"type": "string"
},
+3
View File
@@ -33,6 +33,7 @@ class CapabilitiesTest extends TestCase {
'public_shares_chunking' => true,
'search_supports_creation_time' => true,
'search_supports_upload_time' => true,
'search_supports_last_activity' => true,
],
];
$this->assertSame($expected, $capabilities->getCapabilities());
@@ -55,6 +56,7 @@ class CapabilitiesTest extends TestCase {
'public_shares_chunking' => true,
'search_supports_creation_time' => true,
'search_supports_upload_time' => true,
'search_supports_last_activity' => true,
'bulkupload' => '1.0',
],
];
@@ -78,6 +80,7 @@ class CapabilitiesTest extends TestCase {
'public_shares_chunking' => true,
'search_supports_creation_time' => true,
'search_supports_upload_time' => true,
'search_supports_last_activity' => true,
'absence-supported' => true,
'absence-replacement' => true,
],
@@ -42,7 +42,7 @@ class NodeTest extends \Test\TestCase {
[Constants::PERMISSION_ALL, 'file', true, Constants::PERMISSION_ALL, true, '' , 'SRMGDNVW'],
[Constants::PERMISSION_ALL, 'file', true, Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE, true, '' , 'SRMGDNV'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE, 'file', true, Constants::PERMISSION_ALL, false, 'test', 'SGDNVW'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGD'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_UPDATE, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGDN'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_DELETE, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGNVW'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_CREATE, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RGDNVW'],
[Constants::PERMISSION_ALL - Constants::PERMISSION_READ, 'file', false, Constants::PERMISSION_ALL, false, 'test', 'RDNVW'],
@@ -0,0 +1,317 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\DAV\Tests\unit\Connector\Sabre;
use Exception;
use OCA\DAV\Connector\Sabre\Directory;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCA\DAV\Connector\Sabre\Node;
use OCA\DAV\Connector\Sabre\ZipFolderPlugin;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Events\BeforeZipCreatedEvent;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\Node as OCPNode;
use OCP\IConfig;
use OCP\IDateTimeZone;
use OCP\IL10N;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Sabre\DAV\Tree;
use Sabre\HTTP\Request;
use Sabre\HTTP\Response;
use Test\TestCase;
class ZipFolderPluginTest extends TestCase {
private Tree&MockObject $tree;
private LoggerInterface&MockObject $logger;
private IEventDispatcher&MockObject $eventDispatcher;
private IDateTimeZone&MockObject $timezoneFactory;
private IConfig&MockObject $config;
private Response&MockObject $response;
private IL10N&MockObject $l10n;
protected function setUp(): void {
parent::setUp();
$this->tree = $this->createMock(Tree::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->timezoneFactory = $this->createMock(IDateTimeZone::class);
$this->config = $this->createMock(IConfig::class);
$this->response = $this->createMock(Response::class);
$this->l10n = $this->createMock(IL10N::class);
$this->l10n->method('t')->willReturnCallback(static fn (string $text, array $parameters = []): string => vsprintf($text, $parameters));
}
public static function dataDownloadingABlockedFolderShouldFail(): array {
return [
'missing files reporting feature off' => [ false ],
'missing files reporting feature on' => [ true ],
];
}
/*
* Tests that the plugin throws a Forbidden exception when the user is trying
* to download a collection they have no access to.
*/
#[DataProvider(methodName: 'dataDownloadingABlockedFolderShouldFail')]
public function testDownloadingABlockedFolderShouldFail(bool $reportMissingFiles): void {
$plugin = $this->createPlugin($reportMissingFiles);
$folderPath = '/user/files/folder';
$folder = $this->createFolderNode($folderPath, []);
$directory = $this->createDirectoryNode($folder);
$this->tree->expects($this->once())
->method('getNodeForPath')
->with($folderPath)
->willReturn($directory);
$errorMessage = 'Blocked by ACL';
$this->eventDispatcher->expects($this->once())
->method('dispatchTyped')
->willReturnCallback(function (BeforeZipCreatedEvent $event) use ($reportMissingFiles, $errorMessage): BeforeZipCreatedEvent {
$this->assertSame([], $event->getFiles());
$this->assertEquals($reportMissingFiles, $event->allowPartialArchive);
$event->setSuccessful(false);
$event->setErrorMessage($errorMessage);
return $event;
});
$this->expectException(Forbidden::class);
$this->expectExceptionMessage($errorMessage);
$directory->expects($this->never())->method('getChild');
$folder->expects($this->never())->method('getDirectoryListing');
$plugin->handleDownload($this->createRequest($folderPath), $this->response);
}
public static function dataDownloadingAFolderShouldFailWhenItemsAreBlocked(): array {
return [
'no files filtering' => [ [] ],
'files filtering' => [ ['allowed.txt', 'blocked.txt'] ],
];
}
/*
* Tests that when `archive_report_missing_files` is disabled, downloading
* a directory which contains a non-downloadable item stops the entire
* download.
*/
#[DataProvider(methodName: 'dataDownloadingAFolderShouldFailWhenItemsAreBlocked')]
public function testDownloadingAFolderShouldFailWhenItemsAreBlocked(array $filesFilter): void {
$plugin = $this->createPlugin(false);
$folderPath = '/user/files/folder';
$allowedFile = $this->createFile("{$folderPath}/allowed.txt", 'allowed');
$blockedFile = $this->createFile("{$folderPath}/blocked.txt", 'secret');
$files = [$allowedFile, $blockedFile];
$childNodes = [
'allowed.txt' => $this->createNode($allowedFile),
'blocked.txt' => $this->createNode($blockedFile),
];
$folder = $this->createFolderNode($folderPath, $files);
$directory = $this->createDirectoryNode($folder, $childNodes);
$this->tree->expects($this->once())
->method('getNodeForPath')
->with($folderPath)
->willReturn($directory);
$errorMessage = 'Blocked by ACL';
$this->eventDispatcher->expects($this->once())
->method('dispatchTyped')
->willReturnCallback(function (BeforeZipCreatedEvent $event) use ($errorMessage, $filesFilter): BeforeZipCreatedEvent {
$this->assertSame($filesFilter, $event->getFiles());
$this->assertFalse($event->allowPartialArchive);
$event->setSuccessful(false);
$event->setErrorMessage($errorMessage);
return $event;
});
$this->expectException(Forbidden::class);
$this->expectExceptionMessage($errorMessage);
$plugin->handleDownload($this->createRequest($folderPath, $filesFilter), $this->response);
}
public static function dataDownloadingAFolderWithMissingFilesReportingShouldSucceed(): array {
return [
// files are reporting as missing either because they are download-blocked or because some error happened
'full directory download' => [
'children' => ['allowed.txt' => 'allowed', 'blocked.txt' => 'blocked', 'error.txt' => new \RuntimeException('read error')],
'filesFilter' => [],
'downloadBlocked' => [ 'blocked.txt' ],
'expectedMissingFiles' => [ 'blocked.txt' => 'blocked', 'error.txt' => 'Error while opening the file: RuntimeException' ],
],
// files filtered out should not be reported as missing
'filtering some files' => [
'children' => [ 'allowed.txt' => 'allowed', 'blocked.txt' => 'blocked', 'error.txt' => new \RuntimeException('read error') ],
'filesFilter' => ['allowed.txt', 'blocked.txt'],
'downloadBlocked' => ['blocked.txt'],
'expectedMissingFiles' => [ 'blocked.txt' => 'blocked' ],
],
];
}
/*
* Tests that when files in a directory cannot be downloaded and the
* `archive_report_missing_files` is enabled, an entry is added to the
* `missing_files.json` file.
*/
#[DataProvider(methodName: 'dataDownloadingAFolderWithMissingFilesReportingShouldSucceed')]
public function testDownloadingAFolderWithMissingFilesReportingShouldSucceed(array $children, array $filesFilter, array $downloadBlocked, array $expectedMissingFiles): void {
$plugin = $this->createPlugin(true);
$folderPath = '/user/files/folder';
$childFiles = [];
$childNodes = [];
foreach ($children as $childName => $content) {
$childFile = $this->createFile("{$folderPath}/{$childName}", $content);
$childFiles[$childName] = $childFile;
$childNodes[$childName] = $this->createNode($childFile);
}
$folder = $this->createFolderNode($folderPath, array_values($childFiles));
$directory = $this->createDirectoryNode($folder, $childNodes);
$this->tree->expects($this->once())
->method('getNodeForPath')
->with($folderPath)
->willReturn($directory);
$this->eventDispatcher->expects($this->once())
->method('dispatchTyped')
->willReturnCallback(function (BeforeZipCreatedEvent $event) use ($downloadBlocked, $filesFilter): BeforeZipCreatedEvent {
$this->assertSame($filesFilter, $event->getFiles());
$this->assertTrue($event->allowPartialArchive);
$event->addNodeFilter(static function ($node) use ($downloadBlocked): array {
if (in_array($node->getName(), $downloadBlocked)) {
return [false, 'blocked'];
}
return [true, null];
});
return $event;
});
ob_start();
$request = $this->createRequest($folderPath, $filesFilter);
$continueHandling = $plugin->handleDownload($request, $this->response);
$output = $this->getActualOutputForAssertion();
$this->assertStringContainsString('missing_files.json', $output, "$output does not contain missin_files.json");
foreach ($expectedMissingFiles as $file => $error) {
$stringToMatch = sprintf('%s": "%s"', $file, $error);
$this->assertStringContainsString($stringToMatch, $output, "$output does not contain $stringToMatch");
}
// assert that the handling should be stopped
$this->assertFalse($continueHandling);
}
private function createPlugin(bool $reportMissingFiles): ZipFolderPlugin {
$this->config->method('getSystemValueBool')
->with('archive_report_missing_files', false)
->willReturn($reportMissingFiles);
return new ZipFolderPlugin(
$this->tree,
$this->logger,
$this->eventDispatcher,
$this->timezoneFactory,
$this->config,
$this->l10n,
);
}
/**
* @param list<string> $filesFilter
* @throws \JsonException
*/
private function createRequest(string $resource, array $filesFilter = []): Request&MockObject {
$query = [];
if ($filesFilter !== []) {
$query['files'] = json_encode($filesFilter, JSON_THROW_ON_ERROR);
}
$request = $this->createMock(Request::class);
$request->method('getPath')->willReturn($resource);
$request->method('getQueryParameters')->willReturn($query);
// file filtering can be done via header or QS parameters. Use only one.
$request->method('getHeaderAsArray')->willReturnMap([
['Accept', ['application/zip']],
['X-NC-Files', []],
]);
return $request;
}
/**
* @param list<File> $children
* @param array<string, Node&MockObject> $childNodes
*/
private function createDirectoryNode(Folder $folder, array $childNodes = []): Directory&MockObject {
$directory = $this->createMock(Directory::class);
$directory->method('getNode')->willReturn($folder);
$directory->method('getChild')->willReturnCallback(static fn (string $name, ...$_): Node => $childNodes[$name]);
return $directory;
}
/**
* @param list<OCPNode> $children
*/
private function createFolderNode(string $path, array $children): Folder&MockObject {
$folder = $this->createMock(Folder::class);
$folder->method('getPath')->willReturn($path);
$folder->method('getName')->willReturn(basename($path));
$folder->method('getDirectoryListing')->willReturn($children);
return $folder;
}
private function createNode(File $node): Node&MockObject {
$child = $this->createMock(Node::class);
$child->method('getNode')->willReturn($node);
$child->method('getPath')->willReturn($node->getPath());
return $child;
}
private function createFile(string $path, string|Exception $contents): File&MockObject {
$length = is_string($contents) ? strlen($contents) : 0;
$file = $this->createMock(File::class);
$file->method('getPath')->willReturn($path);
$file->method('getName')->willReturn(basename($path));
$file->method('getSize')->willReturn($length);
$file->method('getMTime')->willReturn(123);
$file->method('fopen')->with('rb')->willReturnCallback(static function () use ($contents) {
if (!is_string($contents)) {
throw $contents;
}
$stream = fopen('php://temp', 'r+');
fwrite($stream, $contents);
rewind($stream);
return $stream;
});
return $file;
}
}
+1
View File
@@ -41,6 +41,7 @@ OC.L10N.register(
"Enable recovery key" : "Activer la clé de récupération",
"The recovery key is an additional encryption key used to encrypt files. It is used to recover files from an account if the password is forgotten." : "La clé de récupération est une clé de chiffrement supplémentaire utilisée pour chiffrer les fichiers. Elle est utilisée pour récupérer les fichiers d'un compte si le mot de passe a été oublié.",
"Recovery key password" : "Mot de passe de la clé de récupération",
"Passwords fields do not match" : "Les deux mots de passe ne correspondent pas",
"Repeat recovery key password" : "Répétez le mot de passe de la clé de récupération",
"Old recovery key password" : "Ancien mot de passe de la clé de récupération",
"New recovery key password" : "Nouveau mot de passe de la clé de récupération",
+1
View File
@@ -39,6 +39,7 @@
"Enable recovery key" : "Activer la clé de récupération",
"The recovery key is an additional encryption key used to encrypt files. It is used to recover files from an account if the password is forgotten." : "La clé de récupération est une clé de chiffrement supplémentaire utilisée pour chiffrer les fichiers. Elle est utilisée pour récupérer les fichiers d'un compte si le mot de passe a été oublié.",
"Recovery key password" : "Mot de passe de la clé de récupération",
"Passwords fields do not match" : "Les deux mots de passe ne correspondent pas",
"Repeat recovery key password" : "Répétez le mot de passe de la clé de récupération",
"Old recovery key password" : "Ancien mot de passe de la clé de récupération",
"New recovery key password" : "Nouveau mot de passe de la clé de récupération",
@@ -21,9 +21,8 @@ use OCP\IUserSession;
use Psr\Log\LoggerInterface;
class PassphraseService {
/** @var array<string, bool> */
private static array $passwordResetUsers = [];
private array $passwordResetUsers = [];
public function __construct(
private Util $util,
@@ -39,9 +38,9 @@ class PassphraseService {
public function setProcessingReset(string $uid, bool $processing = true): void {
if ($processing) {
self::$passwordResetUsers[$uid] = true;
$this->passwordResetUsers[$uid] = true;
} else {
unset(self::$passwordResetUsers[$uid]);
unset($this->passwordResetUsers[$uid]);
}
}
@@ -51,7 +50,7 @@ class PassphraseService {
public function setPassphraseForUser(string $userId, string $password, ?string $recoveryPassword = null): bool {
// if we are in the process to resetting a user password, we have nothing
// to do here
if (isset(self::$passwordResetUsers[$userId])) {
if (isset($this->passwordResetUsers[$userId])) {
return true;
}
+1 -1
View File
@@ -64,7 +64,7 @@ OC.L10N.register(
"Cancel" : "Abbrechen",
"Add remote share" : "Externe Freigabe hinzufügen",
"Remote share" : "Externe Freigabe",
"Do you want to add the remote share {name} from {owner}@{remote}?" : "Möchten Sie die externe Freigabe {name} von {owner}@{remote} hinzufügen?",
"Do you want to add the remote share {name} from {owner}@{remote}?" : "Soll die externe Freigabe {name} von {owner}@{remote} hinzufügt werden?",
"Remote share password" : "Passwort für die externe Freigabe",
"Incoming share could not be processed" : "Eingehende Freigabe konnte nicht verarbeitet werden",
"X (formerly Twitter)" : "X (früher Twitter)",
+1 -1
View File
@@ -62,7 +62,7 @@
"Cancel" : "Abbrechen",
"Add remote share" : "Externe Freigabe hinzufügen",
"Remote share" : "Externe Freigabe",
"Do you want to add the remote share {name} from {owner}@{remote}?" : "Möchten Sie die externe Freigabe {name} von {owner}@{remote} hinzufügen?",
"Do you want to add the remote share {name} from {owner}@{remote}?" : "Soll die externe Freigabe {name} von {owner}@{remote} hinzufügt werden?",
"Remote share password" : "Passwort für die externe Freigabe",
"Incoming share could not be processed" : "Eingehende Freigabe konnte nicht verarbeitet werden",
"X (formerly Twitter)" : "X (früher Twitter)",
+73
View File
@@ -0,0 +1,73 @@
OC.L10N.register(
"federatedfilesharing",
{
"Invalid Federated Cloud ID" : "Neteisingas federacinės debesijos ID",
"Server to server sharing is not enabled on this server" : "Dalinimasis tarp serverių yra neleidžiamas šiame serveryje",
"Couldn't establish a federated share." : "Nepavyko užmegzti federacinio viešinio.",
"Couldn't establish a federated share, maybe the password was wrong." : "Nepavyko užmegzti federacinio viešinio, galbūt, neteisingas slaptažodis.",
"Federated Share request sent, you will receive an invitation. Check your notifications." : "Federacinio viešinio užklausa išsiųsta, jūs gausite pakvietimą. Tikrinkite savo pranešimus.",
"Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "Nepavyko užmegzti federacinio viešinio, atrodo, kad serveris su kuriuo ketinama jungtis į federaciją yra per senas (Nextcloud <= 9).",
"It is not allowed to send federated group shares from this server." : "Iš šio serverio neleidžiama siųsti federacinių grupės viešinių.",
"Sharing %1$s failed, because this item is already shared with the account %2$s" : "%1$s bendrinimas nepavyko, nes šis elementas jau bendrinamas su %2$s paskyra",
"Not allowed to create a federated share to the same account" : "Draudžiama kurti federacinį bendrinamą išteklių ta pačia paskyra",
"Federated shares require read permissions" : "Federaciniams bendrinamiesiems elementams reikalingi leidimai skaityti",
"File is already shared with %s" : "Failas jau yra bendrinamas su %s",
"Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate." : "%1$s bendrinimas nepavyko, %2$s nepavyko rasti, galbūt serveris šiuo metu nepasiekiamas arba naudoja automatiškai pasirašytą sertifikatą.",
"Could not find share" : "Nepavyko rasti viešinio",
"Federated sharing" : "Federacinis bendrinimas",
"You received {share} as a remote share from {user} (on behalf of {behalf})" : "Jūs gavote {share} kaip nuotolinį viešinį iš {user} ({behalf} vardu)",
"You received {share} as a remote share from {user}" : "Jūs gavote {share} kaip nuotolinį viešinį iš {user}",
"Accept" : "Priimti",
"Decline" : "Atmesti",
"Federated Cloud Sharing" : "Bendrinimas federacinėje debesijoje",
"Sharing" : "Duomenų bendrinimas",
"Federated file sharing" : "Federacinis failų bendrinimas",
"Provide federated file sharing across servers" : "Užtikrinti federacinį failų bendrinimą tarp serverių",
"Confirm data upload to lookup server" : "Patvirtinkite duomenų įkėlimą į paieškos serverį",
"When enabled, all account properties (e.g. email address) with scope visibility set to \"published\", will be automatically synced and transmitted to an external system and made available in a public, global address book." : "Kai įjungta, visos paskyros ypatybės (pvz., el. pašto adresas), kurių matomumo apimtis nustatyta kaip „publikuota“, bus automatiškai sinchronizuojamos ir perduotos išorinei sistemai bei padaromos prieinamos viešojoje, globalioje adresų knygoje.",
"Enable data upload" : "Įgalinti duomenų įkėlimą",
"Disable upload" : "Išjungti įkėlimą",
"Confirm querying lookup server" : "Patvirtinkite užklausos paieškos serverį",
"When enabled, the search input when creating shares will be sent to an external system that provides a public and global address book." : "Kai įgalinta, paieškos įvestis kuriant bendrinamus failus bus siunčiama į išorinę sistemą, kurioje yra vieša ir globali adresų knyga.",
"This is used to retrieve the federated cloud ID to make federated sharing easier." : "Tai naudojama norint gauti federacinio debesies ID, kad būtų lengviau bendrinti federacinį serverį.",
"Moreover, email addresses of users might be sent to that system in order to verify them." : "Be to, į tą sistemą gali būti siunčiami vartotojų el. pašto adresai, siekiant juos patikrinti.",
"Enable querying" : "Įgalinti užklausą",
"Disable querying" : "Išjungti užklausą",
"Unable to update federated files sharing config" : "Nepavyko atnaujinti federacinių failų bendrinimo konfigūracijos",
"Adjust how people can share between servers. This includes shares between people on this server as well if they are using federated sharing." : "Koreguokite, kaip naudotojai gali bendrinti tarp serverių. Tai apima ir bendrinimą tarp šio serverio naudotojų, jei jie naudoja federacinį bendrinimą.",
"Allow people on this server to send shares to other servers (this option also allows WebDAV access to public shares)" : "Leisti šio serverio naudotojams siųsti bendrinamus failus į kitus serverius (ši parinktis taip pat suteikia „WebDAV“ prieigą prie viešai bendrinamų failų)",
"Allow people on this server to receive shares from other servers" : "Leisti šio serverio naudotojams gauti bendrinamus failus iš kitų serverių",
"Allow people on this server to send shares to groups on other servers" : "Leisti šio serverio naudotojams siųsti bendrinamus failus grupėms kituose serveriuose",
"Allow people on this server to receive group shares from other servers" : "Leisti šio serverio naudotojams gauti grupės bendrinimus iš kitų serverių",
"The lookup server is only available for global scale." : "Paieškos serveris galimas tik globaliu mastu.",
"Search global and public address book for people" : "Ieškoti žmonių globalioje ir viešojoje adresų knygoje",
"Allow people to publish their data to a global and public address book" : "Leisti žmonėms publikuoti savo duomenis globalioje ir viešojoje adresų knygoje",
"Trusted federation" : "Patikima federacija",
"Automatically accept shares from trusted federated accounts and groups by default" : "Automatiškai priimti bendrinimus iš patikimų federacinių paskyrų ir grupių pagal numatytuosius nustatymus",
"Share with me through my #Nextcloud Federated Cloud ID, see {url}" : "Pasidalinkite su manimi per mano #Nextcloud Federated Cloud ID, žr. {url}",
"Share with me through my #Nextcloud Federated Cloud ID" : "Bendrinti su manimi per mano #Nextcloud federacinės debesijos ID",
"Share with me via Nextcloud" : "Bendrinkite su manimi per „Nextcloud“",
"Cloud ID copied" : "Cloud ID nukopijuotas",
"Copy" : "Kopijuoti",
"Clipboard not available. Please copy the cloud ID manually." : "Iškarpinė neprieinama. Nukopijuokite debesijos ID rankiniu būdu.",
"Copied!" : "Nukopijuota!",
"Federated Cloud" : "Federacinė debesija",
"You can share with anyone who uses a {productName} server or other Open Cloud Mesh (OCM) compatible servers and services! Just put their Federated Cloud ID in the share dialog. It looks like person@cloud.example.com" : "Galite bendrinti su visais, kas naudoja {productName} serverį ar kitus su „Open Cloud Mesh“ (OCM) suderinamus serverius ir paslaugas! Tiesiog bendrinimo dialogo lange įveskite jų „Federated Cloud“ ID. Jis atrodo taip: person@cloud.example.com",
"Your Federated Cloud ID" : "Jūsų „Federated Cloud“ ID",
"Share it so your friends can share files with you:" : "Pasidalinkite juo, kad jūsų draugai galėtų bendrinti failus kartu su jumis:",
"Bluesky" : "\"Bluesky\"",
"Facebook" : "„Facebook“",
"Mastodon" : "„Mastodon“",
"Add to your website" : "Pridėkite prie savo svetainės",
"Share with me via {productName}" : "Pasidalinkite su manimi per {productName}",
"HTML Code:" : "HTML kodas:",
"Cancel" : "Atsisakyti",
"Add remote share" : "Pridėti nuotolinį viešinį",
"Remote share" : "Nuotolinis viešinys",
"Do you want to add the remote share {name} from {owner}@{remote}?" : "Ar norite pridėti nuotolinį viešinį {name} iš {owner}@{remote}?",
"Remote share password" : "Nuotolinio viešinio slaptažodis",
"Incoming share could not be processed" : "Gaunamo bendrinimo apdoroti nepavyko",
"X (formerly Twitter)" : "X (anksčiau „Twitter“)",
"formerly Twitter" : "anksčiau „Twitter“"
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
+71
View File
@@ -0,0 +1,71 @@
{ "translations": {
"Invalid Federated Cloud ID" : "Neteisingas federacinės debesijos ID",
"Server to server sharing is not enabled on this server" : "Dalinimasis tarp serverių yra neleidžiamas šiame serveryje",
"Couldn't establish a federated share." : "Nepavyko užmegzti federacinio viešinio.",
"Couldn't establish a federated share, maybe the password was wrong." : "Nepavyko užmegzti federacinio viešinio, galbūt, neteisingas slaptažodis.",
"Federated Share request sent, you will receive an invitation. Check your notifications." : "Federacinio viešinio užklausa išsiųsta, jūs gausite pakvietimą. Tikrinkite savo pranešimus.",
"Couldn't establish a federated share, it looks like the server to federate with is too old (Nextcloud <= 9)." : "Nepavyko užmegzti federacinio viešinio, atrodo, kad serveris su kuriuo ketinama jungtis į federaciją yra per senas (Nextcloud <= 9).",
"It is not allowed to send federated group shares from this server." : "Iš šio serverio neleidžiama siųsti federacinių grupės viešinių.",
"Sharing %1$s failed, because this item is already shared with the account %2$s" : "%1$s bendrinimas nepavyko, nes šis elementas jau bendrinamas su %2$s paskyra",
"Not allowed to create a federated share to the same account" : "Draudžiama kurti federacinį bendrinamą išteklių ta pačia paskyra",
"Federated shares require read permissions" : "Federaciniams bendrinamiesiems elementams reikalingi leidimai skaityti",
"File is already shared with %s" : "Failas jau yra bendrinamas su %s",
"Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate." : "%1$s bendrinimas nepavyko, %2$s nepavyko rasti, galbūt serveris šiuo metu nepasiekiamas arba naudoja automatiškai pasirašytą sertifikatą.",
"Could not find share" : "Nepavyko rasti viešinio",
"Federated sharing" : "Federacinis bendrinimas",
"You received {share} as a remote share from {user} (on behalf of {behalf})" : "Jūs gavote {share} kaip nuotolinį viešinį iš {user} ({behalf} vardu)",
"You received {share} as a remote share from {user}" : "Jūs gavote {share} kaip nuotolinį viešinį iš {user}",
"Accept" : "Priimti",
"Decline" : "Atmesti",
"Federated Cloud Sharing" : "Bendrinimas federacinėje debesijoje",
"Sharing" : "Duomenų bendrinimas",
"Federated file sharing" : "Federacinis failų bendrinimas",
"Provide federated file sharing across servers" : "Užtikrinti federacinį failų bendrinimą tarp serverių",
"Confirm data upload to lookup server" : "Patvirtinkite duomenų įkėlimą į paieškos serverį",
"When enabled, all account properties (e.g. email address) with scope visibility set to \"published\", will be automatically synced and transmitted to an external system and made available in a public, global address book." : "Kai įjungta, visos paskyros ypatybės (pvz., el. pašto adresas), kurių matomumo apimtis nustatyta kaip „publikuota“, bus automatiškai sinchronizuojamos ir perduotos išorinei sistemai bei padaromos prieinamos viešojoje, globalioje adresų knygoje.",
"Enable data upload" : "Įgalinti duomenų įkėlimą",
"Disable upload" : "Išjungti įkėlimą",
"Confirm querying lookup server" : "Patvirtinkite užklausos paieškos serverį",
"When enabled, the search input when creating shares will be sent to an external system that provides a public and global address book." : "Kai įgalinta, paieškos įvestis kuriant bendrinamus failus bus siunčiama į išorinę sistemą, kurioje yra vieša ir globali adresų knyga.",
"This is used to retrieve the federated cloud ID to make federated sharing easier." : "Tai naudojama norint gauti federacinio debesies ID, kad būtų lengviau bendrinti federacinį serverį.",
"Moreover, email addresses of users might be sent to that system in order to verify them." : "Be to, į tą sistemą gali būti siunčiami vartotojų el. pašto adresai, siekiant juos patikrinti.",
"Enable querying" : "Įgalinti užklausą",
"Disable querying" : "Išjungti užklausą",
"Unable to update federated files sharing config" : "Nepavyko atnaujinti federacinių failų bendrinimo konfigūracijos",
"Adjust how people can share between servers. This includes shares between people on this server as well if they are using federated sharing." : "Koreguokite, kaip naudotojai gali bendrinti tarp serverių. Tai apima ir bendrinimą tarp šio serverio naudotojų, jei jie naudoja federacinį bendrinimą.",
"Allow people on this server to send shares to other servers (this option also allows WebDAV access to public shares)" : "Leisti šio serverio naudotojams siųsti bendrinamus failus į kitus serverius (ši parinktis taip pat suteikia „WebDAV“ prieigą prie viešai bendrinamų failų)",
"Allow people on this server to receive shares from other servers" : "Leisti šio serverio naudotojams gauti bendrinamus failus iš kitų serverių",
"Allow people on this server to send shares to groups on other servers" : "Leisti šio serverio naudotojams siųsti bendrinamus failus grupėms kituose serveriuose",
"Allow people on this server to receive group shares from other servers" : "Leisti šio serverio naudotojams gauti grupės bendrinimus iš kitų serverių",
"The lookup server is only available for global scale." : "Paieškos serveris galimas tik globaliu mastu.",
"Search global and public address book for people" : "Ieškoti žmonių globalioje ir viešojoje adresų knygoje",
"Allow people to publish their data to a global and public address book" : "Leisti žmonėms publikuoti savo duomenis globalioje ir viešojoje adresų knygoje",
"Trusted federation" : "Patikima federacija",
"Automatically accept shares from trusted federated accounts and groups by default" : "Automatiškai priimti bendrinimus iš patikimų federacinių paskyrų ir grupių pagal numatytuosius nustatymus",
"Share with me through my #Nextcloud Federated Cloud ID, see {url}" : "Pasidalinkite su manimi per mano #Nextcloud Federated Cloud ID, žr. {url}",
"Share with me through my #Nextcloud Federated Cloud ID" : "Bendrinti su manimi per mano #Nextcloud federacinės debesijos ID",
"Share with me via Nextcloud" : "Bendrinkite su manimi per „Nextcloud“",
"Cloud ID copied" : "Cloud ID nukopijuotas",
"Copy" : "Kopijuoti",
"Clipboard not available. Please copy the cloud ID manually." : "Iškarpinė neprieinama. Nukopijuokite debesijos ID rankiniu būdu.",
"Copied!" : "Nukopijuota!",
"Federated Cloud" : "Federacinė debesija",
"You can share with anyone who uses a {productName} server or other Open Cloud Mesh (OCM) compatible servers and services! Just put their Federated Cloud ID in the share dialog. It looks like person@cloud.example.com" : "Galite bendrinti su visais, kas naudoja {productName} serverį ar kitus su „Open Cloud Mesh“ (OCM) suderinamus serverius ir paslaugas! Tiesiog bendrinimo dialogo lange įveskite jų „Federated Cloud“ ID. Jis atrodo taip: person@cloud.example.com",
"Your Federated Cloud ID" : "Jūsų „Federated Cloud“ ID",
"Share it so your friends can share files with you:" : "Pasidalinkite juo, kad jūsų draugai galėtų bendrinti failus kartu su jumis:",
"Bluesky" : "\"Bluesky\"",
"Facebook" : "„Facebook“",
"Mastodon" : "„Mastodon“",
"Add to your website" : "Pridėkite prie savo svetainės",
"Share with me via {productName}" : "Pasidalinkite su manimi per {productName}",
"HTML Code:" : "HTML kodas:",
"Cancel" : "Atsisakyti",
"Add remote share" : "Pridėti nuotolinį viešinį",
"Remote share" : "Nuotolinis viešinys",
"Do you want to add the remote share {name} from {owner}@{remote}?" : "Ar norite pridėti nuotolinį viešinį {name} iš {owner}@{remote}?",
"Remote share password" : "Nuotolinio viešinio slaptažodis",
"Incoming share could not be processed" : "Gaunamo bendrinimo apdoroti nepavyko",
"X (formerly Twitter)" : "X (anksčiau „Twitter“)",
"formerly Twitter" : "anksčiau „Twitter“"
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
}
+33
View File
@@ -0,0 +1,33 @@
OC.L10N.register(
"federation",
{
"Added to the list of trusted servers" : "Pridėtas į patikimų serverių sąrašą",
"No server found with ID: %s" : "Nerasta jokio serverio, kurio ID: %s",
"Could not remove server" : "Nepavyko pašalinti serverio",
"Server is already in the list of trusted servers." : "Serveris jau yra patikimų serverių sąraše.",
"No server to federate with found" : "Nerasta jokio serverio, su kuriuo jungtis į federaciją",
"Could not add server" : "Nepavyko pridėti serverio",
"Trusted servers" : "Patikimi serveriai",
"Federation" : "Federacija",
"Federation allows you to connect with other trusted servers to exchange the account directory." : "Federacija leidžia prisijungti prie kitų patikimų serverių, kad būtų galima keistis paskyros katalogu.",
"Federation allows you to connect with other trusted servers to exchange the account directory. For example this will be used to auto-complete external accounts for federated sharing." : "Federacija leidžia prisijungti prie kitų patikimų serverių, kad būtų galima keistis paskyros katalogu.",
"Could not add trusted server. Please try again later." : "Nepavyko pridėti patikimo serverio. Bandykite dar kartą vėliau.",
"Add trusted server" : "Pridėti patikimą serverį",
"Server url" : "Serverio url",
"Add" : "Pridėti",
"Server ok" : "Serveris tvarkoje",
"User list was exchanged at least once successfully with the remote server." : "Vartotojų sąrašas buvo bent kartą sėkmingai pakeistas su nuotoliniu serveriu.",
"Server pending" : "Laukiama serverio",
"Waiting for shared secret or initial user list exchange." : "Laukiama bendrinamo slapto rakto arba pradinio naudotojų sąrašo pasikeitimo.",
"Server access revoked" : "Prieiga prie serverio atšaukta",
"Server failure" : "Serverio gedimas",
"Connection to the remote server failed or the remote server is misconfigured." : "Ryšys su nuotoliniu serveriu nepavyko arba nuotolinis serveris yra neteisingai sukonfigūruotas.",
"Failed to delete trusted server. Please try again later." : "Nepavyko pašalinti patikimo serverio. Bandykite dar kartą vėliau.",
"Delete" : "Ištrinti",
"Federation allows you to connect with other trusted servers to exchange the account directory. For example this will be used to auto-complete external accounts for federated sharing. It is not necessary to add a server as trusted server in order to create a federated share." : "Federacija leidžia prisijungti prie kitų patikimų serverių, kad būtų galima keistis paskyrų katalogu. Pavyzdžiui, tai bus naudojama automatiškai užpildyti išorines paskyras, skirtas federuotam bendrinimui. Norint sukurti federuotą bendrinimą, nebūtina pridėti serverio kaip patikimo serverio.",
"Each server must validate the other. This process may require a few cron cycles." : "Kiekvienas serveris turi patvirtinti kitą. Šiam procesui gali prireikti kelių „cron“ ciklų.",
"External documentation for Federated Cloud Sharing" : "Išorinė dokumentacija apie Federacinį Debesies Bendrinimą",
"+ Add trusted server" : "+ Pridėti patikimą serverį",
"Trusted server" : "Patikimas serveris"
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
+31
View File
@@ -0,0 +1,31 @@
{ "translations": {
"Added to the list of trusted servers" : "Pridėtas į patikimų serverių sąrašą",
"No server found with ID: %s" : "Nerasta jokio serverio, kurio ID: %s",
"Could not remove server" : "Nepavyko pašalinti serverio",
"Server is already in the list of trusted servers." : "Serveris jau yra patikimų serverių sąraše.",
"No server to federate with found" : "Nerasta jokio serverio, su kuriuo jungtis į federaciją",
"Could not add server" : "Nepavyko pridėti serverio",
"Trusted servers" : "Patikimi serveriai",
"Federation" : "Federacija",
"Federation allows you to connect with other trusted servers to exchange the account directory." : "Federacija leidžia prisijungti prie kitų patikimų serverių, kad būtų galima keistis paskyros katalogu.",
"Federation allows you to connect with other trusted servers to exchange the account directory. For example this will be used to auto-complete external accounts for federated sharing." : "Federacija leidžia prisijungti prie kitų patikimų serverių, kad būtų galima keistis paskyros katalogu.",
"Could not add trusted server. Please try again later." : "Nepavyko pridėti patikimo serverio. Bandykite dar kartą vėliau.",
"Add trusted server" : "Pridėti patikimą serverį",
"Server url" : "Serverio url",
"Add" : "Pridėti",
"Server ok" : "Serveris tvarkoje",
"User list was exchanged at least once successfully with the remote server." : "Vartotojų sąrašas buvo bent kartą sėkmingai pakeistas su nuotoliniu serveriu.",
"Server pending" : "Laukiama serverio",
"Waiting for shared secret or initial user list exchange." : "Laukiama bendrinamo slapto rakto arba pradinio naudotojų sąrašo pasikeitimo.",
"Server access revoked" : "Prieiga prie serverio atšaukta",
"Server failure" : "Serverio gedimas",
"Connection to the remote server failed or the remote server is misconfigured." : "Ryšys su nuotoliniu serveriu nepavyko arba nuotolinis serveris yra neteisingai sukonfigūruotas.",
"Failed to delete trusted server. Please try again later." : "Nepavyko pašalinti patikimo serverio. Bandykite dar kartą vėliau.",
"Delete" : "Ištrinti",
"Federation allows you to connect with other trusted servers to exchange the account directory. For example this will be used to auto-complete external accounts for federated sharing. It is not necessary to add a server as trusted server in order to create a federated share." : "Federacija leidžia prisijungti prie kitų patikimų serverių, kad būtų galima keistis paskyrų katalogu. Pavyzdžiui, tai bus naudojama automatiškai užpildyti išorines paskyras, skirtas federuotam bendrinimui. Norint sukurti federuotą bendrinimą, nebūtina pridėti serverio kaip patikimo serverio.",
"Each server must validate the other. This process may require a few cron cycles." : "Kiekvienas serveris turi patvirtinti kitą. Šiam procesui gali prireikti kelių „cron“ ciklų.",
"External documentation for Federated Cloud Sharing" : "Išorinė dokumentacija apie Federacinį Debesies Bendrinimą",
"+ Add trusted server" : "+ Pridėti patikimą serverį",
"Trusted server" : "Patikimas serveris"
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
}
+1 -1
View File
@@ -400,7 +400,7 @@ OC.L10N.register(
"Clear filter" : "Filter zurücksetzen",
"Open file sidebar" : "Datei-Seitenleiste öffnen",
"Search everywhere …" : "Überall suchen …",
"Search here …" : "Hier suchen …",
"Search here …" : "Hier suchen …",
"Preparing …" : "Bereite vor …",
"Submitting fields …" : "Felder werden übermittelt …",
"Shared by link" : "Über einen Link geteilt",
+1 -1
View File
@@ -398,7 +398,7 @@
"Clear filter" : "Filter zurücksetzen",
"Open file sidebar" : "Datei-Seitenleiste öffnen",
"Search everywhere …" : "Überall suchen …",
"Search here …" : "Hier suchen …",
"Search here …" : "Hier suchen …",
"Preparing …" : "Bereite vor …",
"Submitting fields …" : "Felder werden übermittelt …",
"Shared by link" : "Über einen Link geteilt",
+194 -10
View File
@@ -43,38 +43,65 @@ OC.L10N.register(
"Files" : "Failai",
"A file or folder has been <strong>changed</strong>" : "Buvo <strong>pakeistas</strong> failas ar aplankas",
"A favorite file or folder has been <strong>changed</strong>" : "Buvo <strong>pakeistas</strong> mėgstamas failas ar aplankas",
"Failed to authorize" : "Nepavyko autorizuoti",
"Invalid folder path" : "Neteisingas aplanko kelias",
"Folder not found" : "Aplankas nerastas",
"The file cannot be found" : "Failas negali būti surastas",
"The destination path does not exist: %1$s" : "Paskirties kelio nėra: %1$s",
"You do not have permission to create a file at the specified location" : "Jūs neturite leidimo sukurti failą nurodytoje vietoje",
"The file could not be converted." : "Nepavyko konvertuoti failo.",
"Could not get relative path to converted file" : "Nepavyko gauti santykinio kelio į konvertuotą failą",
"Limit must be a positive integer." : "Limito riba turi būti teigiamas sveikasis skaičius.",
"The replacement character may only be a single character." : "Pakaitinis simbolis gali būti tik vienas simbolis.",
"Filename sanitization already started." : "Failų pavadinimų valymas jau pradėtas.",
"No filename sanitization in progress." : "Failų pavadinimų valymas nevykdomas.",
"Favorite files" : "Mėgstamiausi failai",
"No favorites" : "Nėra mėgstamiausių",
"More favorites" : "Daugiau mėgstamiausių",
"Accept" : "Priimti",
"Reject" : "Atmesti",
"Incoming ownership transfer from {user}" : "Gaunamasis nuosavybės perdavimas nuo {user}",
"Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Ar norite priimti {path}?\n\nPastaba: Priėmus, perdavimo procesas gali užtrukti iki 1 valandos.",
"Ownership transfer denied" : "Nuosavybės perdavimas atmestas",
"Your ownership transfer of {path} was denied by {user}." : "Jūsų nuosavybės {path} perdavimas buvo atmestas {user}.",
"Ownership transfer failed" : "Nuosavybės perdavimas nepavyko",
"Your ownership transfer of {path} to {user} failed." : "Nepavyko perduoti jūsų {path} nuosavybės naudotojui {user}.",
"The ownership transfer of {path} from {user} failed." : "{path} nuosavybės perdavimas iš naudotojo {user} nepavyko.",
"Ownership transfer done" : "Nuosavybės perdavimas atliktas",
"Your ownership transfer of {path} to {user} has completed." : "Jūsų {path} nuosavybės perdavimas naudotojui {user} užbaigtas.",
"The ownership transfer of {path} from {user} has completed." : "{path} nuosavybės perdavimas iš naudotojo {user} užbaigtas.",
"in %s" : "per %s",
"in %s" : "pо %s",
"Transferred from %1$s on %2$s" : "Perkelta iš %1$s į %2$s",
"File Management" : "Failų tvarkymas",
"Home" : "Pagrindinis",
"Target folder does not exist any more" : "Paskirties aplanko daugiau nebėra",
"Reload current directory" : "Įkelti dabartinį katalogą iš naujo",
"Go to the \"{dir}\" directory" : "Eikite į \"{dir}\" katalogą",
"Current directory path" : "Dabartinis katalogo kelias",
"Share" : "Bendrinti",
"Drag and drop files here to upload" : "Tempkite failus čia norėdami išsiųsti",
"Reload content" : "Įkelti turinį iš naujo",
"Your have used your space quota and cannot upload files anymore" : "Jūs išnaudojote leidžiamą duomenų kiekį ir daugiau nebegalite išsiųsti failų",
"You do not have permission to upload or create files here." : "Jūs neturite leidimo čia įkelti ar kurti failų.",
"Drag and drop files here to upload" : "Tempkite čia failus norėdami juos išsiųsti",
"Favorite" : "Mėgstamas",
"Back" : "Atgal",
"Toggle selection for file \"{displayName}\"" : "Perjungti failo „{displayName}“ pasirinkimą",
"Toggle selection for folder \"{displayName}\"" : "Perjungti aplanko „{displayName}“ pasirinkimą",
"File is loading" : "Failas yra įkeliamas",
"Folder is loading" : "Aplankas yra įkeliamas",
"Filename" : "Failo pavadinimas",
"Folder name" : "Aplanko pavadinimas",
"This node is unavailable" : "Šis mazgas neprieinamas",
"Another entry with the same name already exists." : "Kitas įrašas tuo pačiu pavadinimu jau yra.",
"Invalid filename." : "Neteisingas failo pavadinimas.",
"Rename file" : "Pervadinti failą",
"Recently created" : "Neseniai sukurta",
"Folder" : "Aplankas",
"Unknown file type" : "Nežinomas failo tipas",
"{ext} image" : "{ext} paveikslėlis",
"{ext} video" : "{ext} vaizdo įrašas",
"{ext} audio" : "{ext} garso įrašas",
"{ext} text" : "{ext} tekstas",
"Pending" : "Laukiantis",
"Unknown date" : "Nežinoma data",
"Active filters" : "Aktyvūs filtrai",
@@ -82,6 +109,11 @@ OC.L10N.register(
"Today" : "Šiandien",
"Last 7 days" : "Paskutinės 7 dienos",
"Last 30 days" : "Paskutinės 30 dienų",
"This year ({year})" : "Šie metai ({year})",
"Last year ({year})" : "Praėję metai ({year})",
"Custom range" : "Pasirinktinis diapazonas",
"Custom date range" : "Pasirinktinis datų diapazonas",
"Search everywhere" : "Ieškoti visur",
"Documents" : "Dokumentai",
"Spreadsheets" : "Skaičiuoklės",
"Presentations" : "Pateiktys",
@@ -91,26 +123,64 @@ OC.L10N.register(
"Images" : "Paveikslai",
"Videos" : "Vaizdo įrašai",
"Filters" : "Filtrai",
"Back to filters" : "Atgal į filtrus",
"Appearance" : "Išvaizda",
"Show hidden files" : "Rodyti paslėptus failus",
"Show file type column" : "Rodyti failo tipo stulpelį",
"Show file extensions" : "Rodyti failų plėtinius",
"Crop image previews" : "Apkirpti paveikslėlių peržiūras",
"General" : "Bendra",
"Sort favorites first" : "Pirmiausia rūšiuoti mėgstamiausius",
"Sort folders before files" : "Rūšiuoti aplankus prieš failus",
"Enable folder tree view" : "Įjungti aplankų medžio rodinį",
"Default view" : "Numatytasis rodinys",
"All files" : "Visi failai",
"Personal files" : "Asmeniniai failai",
"Additional settings" : "Papildomi nustatymai",
"Actions" : "Veiksmai",
"File actions" : "Veiksmai su failais",
"Selection" : "Pasirinkimas",
"Select all files" : "Pasirinkti visus failus",
"Deselect all" : "Panaikinti pasirinkimą",
"Navigation" : "Navigacija",
"Select or deselect" : "Pasirinkti arba panaikinti pasirinkimą",
"Select a range" : "Pasirinkite diapazoną",
"Navigation" : "Naršymas",
"Go to parent folder" : "Eiti į viršesnį aplanką",
"Go to file above" : "Eiti į aukščiau esantį failą",
"Go to file below" : "Eiti į žemiau esantį failą",
"Go left in grid" : "Eiti į kairę tinklelyje",
"Go right in grid" : "Eiti į dešinę tinklelyje",
"View" : "Rodyti",
"Toggle grid view" : "Rodyti tinkleliu",
"Toggle grid view" : "Perjungti tinklelio rodinį",
"Show those shortcuts" : "Rodyti tuos sparčiuosius klavišus",
"Warnings" : "Įspėjimai",
"Warn before changing a file extension" : "Įspėti prieš keičiant failo prievardį",
"Warn before deleting a file" : "Įspėti prieš ištrinant failą",
"WebDAV URL" : "WebDAV URL",
"Create an app password" : "Sukurkite programėlės slaptažodį",
"Required for WebDAV authentication because Two-Factor Authentication is enabled for this account." : "Būtina „WebDAV“ autentifikavimui, nes šiai paskyrai įjungtas dviejų veiksnių autentifikavimas.",
"How to access files using WebDAV" : "Kaip pasiekti failus naudojant WebDAV",
"Total rows summary" : "Bendras eilučių skaičius",
"Toggle selection for all files and folders" : "Perjungti visų failų ir aplankų pasirinkimą",
"Name" : "Pavadinimas",
"File type" : "Failo tipas",
"Size" : "Dydis",
"Modified" : "Pakeistas",
"{displayName}: failed on some elements" : "{displayName}: kai kurių elementų klaida",
"{displayName}: done" : "{displayName}: padaryta",
"{displayName}: failed" : "{displayName}: nepavyko",
"(selected)" : "(pasirinktas)",
"List of files and folders." : "Failų ir aplankų sąrašas.",
"You have used your space quota and cannot upload files anymore." : "Išnaudojote savo vietos kvotą ir daugiau negalite įkelti failų.",
"Column headers with buttons are sortable." : "Stulpelių antraštes su mygtukais galima rūšiuoti.",
"This list is not fully rendered for performance reasons. The files will be rendered as you navigate through the list." : "Šis sąrašas nėra pilnai sugeneruotas dėl našumo priežasčių. Failai bus sugeneruoti jums naršant sąraše.",
"File not found" : "Failas nerastas",
"_{count} selected_::_{count} selected_" : ["{count} pasirinktas","{count} pasirinkti","{count} pasirinkti","{count} pasirinkti"],
"Views" : "Rodiniai",
"Search everywhere …" : "Ieškoti visur…",
"Search here …" : "Ieškoti čia…",
"Search scope options" : "Paieškos apimties parinktys",
"Search here" : "Ieškoti čia",
"Owner" : "Savininkas",
"{usedQuotaByte} used" : "Naudojama {usedQuotaByte}",
"{used} of {quota} used" : "panaudota {used} iš {quota}",
@@ -118,11 +188,32 @@ OC.L10N.register(
"Could not refresh storage stats" : "Nepavyko iš naujo įkelti saugyklos statistikos",
"Your storage is full, files can not be updated or synced anymore!" : "Jūsų saugykla pilna, failai daugiau nebegali būti atnaujinti arba sinchronizuojami!",
"Storage information" : "Informacija apie saugyklą",
"Storage quota" : "Saugyklos kvota",
"New folder" : "Naujas aplankas",
"Create new folder" : "Sukurti naują aplanką",
"This name is already in use." : "Šis pavadinimas jau yra naudojamas.",
"Create" : "Sukurti",
"Files starting with a dot are hidden by default" : "Failai, prasidedantys tašku, pagal numatytuosius nustatymus yra paslėpti",
"Failed to start filename sanitization." : "Nepavyko pradėti failų pavadinimų valymo.",
"Failed to refresh filename sanitization status." : "Nepavyko atnaujinti failo pavadinimo išvalymo būsenos.",
"Filename sanitization in progress." : "Vykdomas failų pavadinimų valymas.",
"Currently {processedUsers} of {totalUsers} accounts are already processed." : "Šiuo metu {processedUsers} naudotojų paskyros iš {totalUsers} egzistuojančių jau apdorotos.",
"Preparing …" : "Ruošiama…",
"Refresh" : "Įkelti iš naujo",
"All files have been santized for Windows filename support." : "Visi failai buvo patvirtinti, kad atitiktų „Windows“ failų pavadinimų reikalavimus.",
"Some files could not be sanitized, please check your logs." : "Kai kurių failų nepavyko išvalyti, patikrinkite savo registrų įrašų žurnalus.",
"Sanitization errors" : "Valymo klaidos",
"Not sanitized filenames" : "Neišvalyti failų vardai",
"Windows filename support has been enabled." : "Įjungtas „Windows“ failų vardų palaikymas.",
"While this blocks users from creating new files with unsupported filenames, existing files are not yet renamed and thus still may break sync on Windows." : "Nors tai neleidžia vartotojams kurti naujų failų su nepalaikomais failų pavadinimais, esami failai dar nėra pervadinti, todėl vis tiek gali sutrikdyti sinchronizavimą sistemoje „Windows“.",
"You can trigger a rename of files with invalid filenames, this will be done in the background and may take some time." : "Galite pervadinti failus su neteisingais pavadinimais. Tai bus atliekama fone ir gali užtrukti.",
"Please note that this may cause high workload on the sync clients." : "Atminkite, kad tai gali sukelti didelį sinchronizavimo klientų darbo krūvį.",
"Limit" : "Limitas",
"This allows to configure how many users should be processed in one background job run." : "Tai leidžia konfigūruoti, kiek vartotojų turėtų būti apdorojama vieno foninio darbo vykdymo metu.",
"Sanitize filenames" : "Išvalyti failų pavadinimus",
"(starting)" : "(pradedama)",
"Fill template fields" : "Užpildykite šablono laukus",
"Submitting fields …" : "Pateikiami laukai  ...",
"Submit" : "Pateikti",
"Choose a file or folder to transfer" : "Pasirinkite norimą perduoti failą ar aplanką",
"Transfer" : "Perduoti",
@@ -130,104 +221,197 @@ OC.L10N.register(
"Invalid path selected" : "Pasirinktas neteisingas kelias",
"Unknown error" : "Nežinoma klaida",
"Ownership transfer request sent" : "Nuosavybės perdavimo užklausa išsiųsta",
"Cannot transfer ownership of a file or folder you do not own" : "Negalima perduoti jums nepriklausančio failo ar aplanko nuosavybės teisės",
"Transfer ownership of a file or folder" : "Perduoti failo ar aplanko nuosavybę",
"Choose file or folder to transfer" : "Pasirinkti norimą perduoti failą ar aplanką",
"Change" : "Keisti",
"New owner" : "Naujasis savininkas",
"Keep {old}" : "Palikti {old}",
"Keep without extension" : "Palikti be prievardžio",
"Use {new}" : "Naudoti {new}",
"Remove extension" : "Pašalinti prievardį",
"Change file extension" : "Keisti failo prievardį",
"Changing the file extension from \"{old}\" to \"{new}\" may render the file unreadable." : "Pakeitus failo plėtinį iš „{old}“ į „{new}“, failas gali tapti neįskaitomas.",
"Removing the file extension \"{old}\" may render the file unreadable." : "Pašalinus failo plėtinį „{old}“, failas gali tapti neįskaitomas.",
"Adding the file extension \"{new}\" may render the file unreadable." : "Pridėjus failo plėtinį „{new}“, failas gali tapti neįskaitomas.",
"Do not show this dialog again." : "Daugiau neberodyti šio dialogo.",
"Rename file to hidden" : "Pervadinti failą į paslėptą",
"Prefixing a filename with a dot may render the file hidden." : "Failo pavadinimo pradžioje įrašius tašką, failas gali būti paslėptas.",
"Are you sure you want to rename the file to \"{filename}\"?" : "Ar tikrai norite pervardyti failą į „{filename}“?",
"Cancel" : "Atsisakyti",
"Rename" : "Pervadinti",
"Select file or folder to link to" : "Pasirinkite failą arba aplanką, į kurį norite susieti",
"Choose {file}" : "Pasirinkti{file}",
"Files settings" : "Failų nustatymai",
"Switch to list view" : "Perjungti į sąrašo rodinį",
"Switch to grid view" : "Perjungti į tinklelio rodinį",
"The file could not be found" : "Failas nerastas",
"Upload was cancelled by user" : "Įkelimas buvo atšauktas vartotojo",
"The file could not be found" : "Nepavyko rasti failo",
"Upload was cancelled by user" : "Naudotojas atsisakė failo išsiuntimo",
"Not enough free space" : "Trūksta laisvos vietos",
"Operation is blocked by access control" : "Operacija yra užblokuota prieigos valdymo",
"Error during upload: {message}" : "Įkėlimo klaida: {message}",
"Error during upload, status code {status}" : "Įkėlimo klaida, būsenos kodas - {status}",
"Unknown error during upload" : "Įkėlimo metu įvyko nežinoma klaida",
"File list is reloading" : "Failų sąrašas įkeliamas iš naujo",
"Loading current folder" : "Įkeliamas dabartinis aplankas",
"Retry" : "Bandyti dar kartą",
"No files in here" : "Čia failų nėra",
"Upload some content or sync with your devices!" : "Įkelkite failus arba sinchronizuokite su savo įrenginiais!",
"Go back" : "Grįžti",
"Loading …" : "Įkeliama …",
"Loading …" : "Įkeliama…",
"Your files" : "Jūsų failai",
"Open in files" : "Atidaryti failuose",
"File cannot be accessed" : "Nepavyksta gauti prieigos prie failo",
"The file could not be found or you do not have permissions to view it. Ask the sender to share it." : "Nepavyko surasti failo arba jūs neturite leidimo jo peržiūrėti. Paprašykite siuntėjo, kad pradėtų jį su jumis bendrinti.",
"No search results for “{query}”" : "Nėra paieškos rezultatų pagal užklausą „{query}“",
"Search for files" : "Ieškoti failų",
"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." : "Leisti apriboti failų pavadinimus, siekiant užtikrinti, kad failus būtų galima sinchronizuoti su visais klientais. Pagal numatytuosius nustatymus leidžiami visi failų vardai, galiojantys POSIX (pvz., Linux arba macOS).",
"After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner." : "Įjungus su „Windows“ suderinamus failų pavadinimus, esamų failų nebegalima modifikuoti, tačiau jų savininkas gali juos pervadinti galiojančiais naujais pavadinimais.",
"Failed to toggle Windows filename support" : "Nepavyko įjungti „Windows“ failų vardų palaikymo",
"Files compatibility" : "Failų suderinamumas",
"Enforce Windows compatibility" : "Užtikrinti suderinamumą su „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." : "Tai blokuos „Windows“ sistemose negaliojančius failų pavadinimus, pvz., rezervuotus pavadinimus ar specialiuosius simbolius. Tačiau tai neužtikrins didžiųjų ir mažųjų raidžių skyrimo suderinamumo.",
"Blank" : "Tuščia",
"Unable to create new file from template" : "Nepavyko sukurti naujo failo iš šablono",
"Pick a template for {name}" : "Pasirinkite šabloną, skirtą {name}",
"Create a new file with the selected template" : "Sukurti naują failą naudojant pasirinktą šabloną",
"Creating file" : "Sukuriamas failas",
"Save as {displayName}" : "Įrašyti kaip {displayName}",
"Save as …" : "Įrašyti kaip…",
"Converting files …" : "Failų konvertavimas  ...",
"Failed to convert files: {message}" : "Nepavyko konvertuoti failų: {message}",
"All files failed to be converted" : "Nepavyko konvertuoti visų failų",
"One file could not be converted: {message}" : "Vieno failo nepavyko konvertuoti: {message}",
"_%n file could not be converted_::_%n files could not be converted_" : ["%n failas negali būti konvertuotas","%n failai negali būti konvertuoti","%n failų negali būti konvertuota","%n failų negali būti konvertuota"],
"_%n file converted_::_%n files converted_" : ["%n failas konvertuotas","%n failai konvertuoti","%n failų konvertuota","%n failų konvertuota"],
"Files converted" : "Failai konvertuoti",
"Failed to convert files" : "Nepavyko konvertuoti failų",
"Converting file …" : "Failai konvertuojami  ...",
"File successfully converted" : "Failas sėkmingai konvertuotas",
"Failed to convert file: {message}" : "Nepavyko konvertuoti failo: {message}",
"Failed to convert file" : "Nepavyko konvertuoti failo",
"Delete" : "Ištrinti",
"Leave this share" : "Palikti bendrinimą",
"Leave these shares" : "Palikti bendrinimus",
"Disconnect storage" : "Atjungti saugyklą",
"Delete permanently" : "Ištrinti negrįžtamai",
"Disconnect storages" : "Atjungti saugyklas",
"Delete permanently" : "Ištrinti visam laikui",
"Delete and unshare" : "Ištrinti ir nebebendrinti",
"Delete file" : "Ištrinti failą",
"Delete files" : "Ištrinti failus",
"Delete folder" : "Ištrinti aplanką",
"Delete folders" : "Ištrinti aplankus",
"_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["Ketinate visam laikui ištrinti {count} elementą","Ketinate visam laikui ištrinti {count} elementus","Ketinate visam laikui ištrinti {count} elementų","Ketinate visam laikui ištrinti {count} elementų"],
"_You are about to delete {count} item_::_You are about to delete {count} items_" : ["Jūs ketinate ištrinti {count} elementą","Jūs ketinate ištrinti {count} elementus","Jūs ketinate ištrinti {count} elementų","Jūs ketinate ištrinti {count} elementą"],
"Confirm deletion" : "Patvirtinti ištrynimą",
"Download" : "Atsisiųsti",
"The requested file is not available." : "Prašomo failo nėra.",
"The requested files are not available." : "Prašomų failų nėra.",
"Add to favorites" : "Pridėti į mėgstamus",
"Remove from favorites" : "Šalinti iš mėgstamų",
"Add or remove favorite" : "Pridėti arba pašalinti mėgstamiausią",
"Move" : "Perkelti",
"Copy" : "Kopijuoti",
"Move or copy" : "Perkelti ar kopijuoti",
"Destination is not a folder" : "Paskirties vieta nėra aplankas",
"This file/folder is already in that directory" : "Šis failas / aplankas jau yra tame kataloge",
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Negalite perkelti failo / aplanko ant jo paties arba į jo paties poaplankį",
"A file or folder with that name already exists in this folder" : "Failas arba aplankas tokiu pavadinimu jau yra šiame aplanke",
"The files are locked" : "Failai yra užrakinti",
"The file does not exist anymore" : "Failo daugiau nebėra",
"Moving \"{source}\" to \"{destination}\" …" : "Perkeliama \"{source}\" į \"{destination}\"  ...",
"Moving {count} files to \"{destination}\" …" : "{count} failai perkeliami į \"{destination}\"  ...",
"Copying \"{source}\" to \"{destination}\" …" : "Kopijuojama iš \"{source}\" į \"{destination}\"  ...",
"Copying {count} files to \"{destination}\" …" : "{count} failai kopijuojami į \"{destination}\"  ...",
"Choose destination" : "Pasirinkite paskirties vietą",
"Copy to {target}" : "Kopijuoti į {target}",
"Move to {target}" : "Perkelti į {target}",
"Move or copy operation failed" : "Perkėlimo ar kopijavimo operacija patyrė nesėkmę",
"Open folder" : "Atverti aplanką",
"Open folder {displayName}" : "Atverti aplanką {displayName}",
"Open in Files" : "Atidaryti programėlėje Files",
"Open locally" : "Atidaryti vietoje",
"Failed to redirect to client" : "Nepavyko peradresuoti į klientą",
"Open file locally" : "Atidaryti failą vietoje",
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Failas dabar turėtų atsidaryti jūsų įrenginyje. Jei ne, patikrinkite, ar įdiegta darbalaukio programėlė.",
"Retry and close" : "Bandyti dar kartą ir užverti",
"Open online" : "Atidaryti internete",
"Details" : "Išsamiau",
"Open the details sidebar" : "Atidaryti išsamios informacijos šoninę juostą",
"Unfavorite" : "Pašalinti iš mėgstamiausių",
"View in folder" : "Rodyti aplanke",
"Type" : "Tipas",
"Created new folder \"{name}\"" : "Sukurtas naujas aplankas „{name}“",
"Unable to initialize the templates directory" : "Nepavyko inicijuoti šablonų katalogo",
"Create templates folder" : "Sukurti šablonų aplanką",
"Templates" : "Šablonai",
"New template folder" : "Naujas šablonų aplankas",
"In folder" : "Aplanke",
"Pick folder to search in" : "Pasirinkite aplanką, kuriame norite ieškoti",
"Search in all files" : "Ieškoti visuose failuose",
"Search in folder: {folder}" : "Ieškoti aplanke: {folder}",
"One of the dropped files could not be processed" : "Vieno iš atmestų failų apdoroti nepavyko",
"Your browser does not support the Filesystem API. Directories will not be uploaded" : "Jūsų naršyklė nepalaiko failų sistemos API. Katalogai nebus įkelti.",
"No files to upload" : "Nėra failų, kuriuos būtų galima įkelti",
"Unable to create the directory {directory}" : "Nepavyko sukurti katalogo {directory}",
"Some files could not be uploaded" : "Kai kurių failų nepavyko išsiųsti",
"Files uploaded successfully" : "Failai sėkmingai išsiųsti",
"No files to process" : "Nėra failų, kuriuos reikėtų apdoroti",
"Files copied successfully" : "Failai sėkmingai nukopijuoti",
"Files moved successfully" : "Failai sėkmingai perkelti",
"Some files could not be copied" : "Kai kurių failų nepavyko nukopijuoti",
"Some files could not be moved" : "Kai kurių failų nepavyko perkelti",
"Could not rename \"{oldName}\", it does not exist any more" : "Nepavyko pervadinti failo „{oldName}“, jo daugiau nebėra",
"Conflicts resolution skipped" : "Konfliktų sprendimas praleistas",
"Upload cancelled" : "Įkėlimas atšauktas",
"Could not rename \"{oldName}\", it does not exist any more" : "Nepavyko pervadinti „{oldName}“, jo daugiau nebėra",
"The name \"{newName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Pavadinimas „{newName}“ jau naudojamas aplanke „{dir}“. Pasirinkite kitokį pavadinimą.",
"Could not rename \"{oldName}\"" : "Nepavyko pervadinti „{oldName}“",
"This operation is forbidden" : "Ši operacija yra uždrausta",
"This folder is unavailable, please try again later or contact the administration" : "Šis aplankas neprieinamas, bandykite dar kartą vėliau arba susisiekite su administratoriumi",
"Storage is temporarily not available" : "Saugykla yra laikinai neprieinama",
"Unexpected error: {error}" : "Netikėta klaida: {error}",
"_%n file_::_%n files_" : ["%n failas","%n failai","%n failų","%n failas"],
"_%n folder_::_%n folders_" : ["%n aplankas","%n aplankai","%n aplankų","%n aplankas"],
"_%n hidden_::_%n hidden_" : ["%n paslėptas","%n paslėpti","%n paslėptų","%n paslėptas"],
"Filename must not be empty." : "Failo pavadinimas negali būti tuščias.",
"\"{char}\" is not allowed inside a filename." : "\"{char}\" simbolis failo pavadinime neleidžiamas",
"\"{segment}\" is a reserved name and not allowed for filenames." : "„{segment}“ yra rezervuotas pavadinimas ir neleidžiamas naudoti failo pavadinimuose.",
"\"{extension}\" is not an allowed filetype." : "„{extension}“ nėra leidžiamas failo tipas.",
"Filenames must not end with \"{extension}\"." : "Failų pavadinimai negali baigtis „{extension}“.",
"List of favorite files and folders." : "Mėgstamiausių failų ir aplankų sąrašas.",
"No favorites yet" : "Kol kas nėra mėgstamų",
"Files and folders you mark as favorite will show up here" : "Čia bus rodomi failai ir aplankai, kuriuos pažymėsite kaip mėgstamus",
"List of your files and folders." : "Jūsų failų ir aplankų sąrašas.",
"Folder tree" : "Aplankų medis",
"List of your files and folders that are not shared." : "Jūsų nebendrinamų failų ir aplankų sąrašas.",
"No personal files found" : "Nerasta jokių asmeninių failų",
"Files that are not shared will show up here." : "Čia bus rodomi nebendrinami failai.",
"Recent" : "Paskiausiai naudoti",
"List of recently modified files and folders." : "Paskiausiai modifikuotų failų ir aplankų sąrašas.",
"No recently modified files" : "Nėra jokių paskiausiai modifikuotų failų",
"Files and folders you recently modified will show up here." : "Čia bus rodomi neseniai modifikuoti failai ir aplankai.",
"Search" : "Paieška",
"Search results within your files." : "Paieškos rezultatai jūsų failuose.",
"No entries found in this folder" : "Nerasta įrašų šiame aplanke",
"Select all" : "Pažymėti viską",
"Upload too large" : "Įkėlimui failas per didelis",
"The files you are trying to upload exceed the maximum size for file uploads on this server." : "Bandomų įkelti failų dydis viršija maksimalų, šiame serveryje leidžiamų įkelti failų dydį.",
"Renamed \"{oldName}\" to \"{newName}\"" : "„{oldName}“ pervadintas į „{newName}“",
"Clear filter" : "Išvalyti filtrą",
"Open file sidebar" : "Atverti failų šoninę juostą",
"Search everywhere …" : "Ieškoti visur…",
"Search here …" : "Ieškoti čia…",
"Preparing …" : "Ruošiama...",
"Submitting fields …" : "Pateikiami laukai...",
"Shared by link" : "Bendrinama pagal nuorodą",
"Shared" : "Bendrinama",
"You" : "Jūs",
"Shared multiple times with different people" : "Dalijimasis kelis kartus su skirtingais žmonėmis",
"Unable to change the favorite state of the file" : "Nepavyko pakeisti failo mėgstamiausios būsenos",
"Error while loading the file data" : "Klaida įkeliant failo duomenis",
"Tags" : "Žymos",
"Save as …" : "Įrašyti kaip…"
"Save as …" : "Įrašyti kaip…",
"Converting files …" : "Failų konvertavimas…",
"Converting file …" : "Failo konvertavimas…"
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
+194 -10
View File
@@ -41,38 +41,65 @@
"Files" : "Failai",
"A file or folder has been <strong>changed</strong>" : "Buvo <strong>pakeistas</strong> failas ar aplankas",
"A favorite file or folder has been <strong>changed</strong>" : "Buvo <strong>pakeistas</strong> mėgstamas failas ar aplankas",
"Failed to authorize" : "Nepavyko autorizuoti",
"Invalid folder path" : "Neteisingas aplanko kelias",
"Folder not found" : "Aplankas nerastas",
"The file cannot be found" : "Failas negali būti surastas",
"The destination path does not exist: %1$s" : "Paskirties kelio nėra: %1$s",
"You do not have permission to create a file at the specified location" : "Jūs neturite leidimo sukurti failą nurodytoje vietoje",
"The file could not be converted." : "Nepavyko konvertuoti failo.",
"Could not get relative path to converted file" : "Nepavyko gauti santykinio kelio į konvertuotą failą",
"Limit must be a positive integer." : "Limito riba turi būti teigiamas sveikasis skaičius.",
"The replacement character may only be a single character." : "Pakaitinis simbolis gali būti tik vienas simbolis.",
"Filename sanitization already started." : "Failų pavadinimų valymas jau pradėtas.",
"No filename sanitization in progress." : "Failų pavadinimų valymas nevykdomas.",
"Favorite files" : "Mėgstamiausi failai",
"No favorites" : "Nėra mėgstamiausių",
"More favorites" : "Daugiau mėgstamiausių",
"Accept" : "Priimti",
"Reject" : "Atmesti",
"Incoming ownership transfer from {user}" : "Gaunamasis nuosavybės perdavimas nuo {user}",
"Do you want to accept {path}?\n\nNote: The transfer process after accepting may take up to 1 hour." : "Ar norite priimti {path}?\n\nPastaba: Priėmus, perdavimo procesas gali užtrukti iki 1 valandos.",
"Ownership transfer denied" : "Nuosavybės perdavimas atmestas",
"Your ownership transfer of {path} was denied by {user}." : "Jūsų nuosavybės {path} perdavimas buvo atmestas {user}.",
"Ownership transfer failed" : "Nuosavybės perdavimas nepavyko",
"Your ownership transfer of {path} to {user} failed." : "Nepavyko perduoti jūsų {path} nuosavybės naudotojui {user}.",
"The ownership transfer of {path} from {user} failed." : "{path} nuosavybės perdavimas iš naudotojo {user} nepavyko.",
"Ownership transfer done" : "Nuosavybės perdavimas atliktas",
"Your ownership transfer of {path} to {user} has completed." : "Jūsų {path} nuosavybės perdavimas naudotojui {user} užbaigtas.",
"The ownership transfer of {path} from {user} has completed." : "{path} nuosavybės perdavimas iš naudotojo {user} užbaigtas.",
"in %s" : "per %s",
"in %s" : "pо %s",
"Transferred from %1$s on %2$s" : "Perkelta iš %1$s į %2$s",
"File Management" : "Failų tvarkymas",
"Home" : "Pagrindinis",
"Target folder does not exist any more" : "Paskirties aplanko daugiau nebėra",
"Reload current directory" : "Įkelti dabartinį katalogą iš naujo",
"Go to the \"{dir}\" directory" : "Eikite į \"{dir}\" katalogą",
"Current directory path" : "Dabartinis katalogo kelias",
"Share" : "Bendrinti",
"Drag and drop files here to upload" : "Tempkite failus čia norėdami išsiųsti",
"Reload content" : "Įkelti turinį iš naujo",
"Your have used your space quota and cannot upload files anymore" : "Jūs išnaudojote leidžiamą duomenų kiekį ir daugiau nebegalite išsiųsti failų",
"You do not have permission to upload or create files here." : "Jūs neturite leidimo čia įkelti ar kurti failų.",
"Drag and drop files here to upload" : "Tempkite čia failus norėdami juos išsiųsti",
"Favorite" : "Mėgstamas",
"Back" : "Atgal",
"Toggle selection for file \"{displayName}\"" : "Perjungti failo „{displayName}“ pasirinkimą",
"Toggle selection for folder \"{displayName}\"" : "Perjungti aplanko „{displayName}“ pasirinkimą",
"File is loading" : "Failas yra įkeliamas",
"Folder is loading" : "Aplankas yra įkeliamas",
"Filename" : "Failo pavadinimas",
"Folder name" : "Aplanko pavadinimas",
"This node is unavailable" : "Šis mazgas neprieinamas",
"Another entry with the same name already exists." : "Kitas įrašas tuo pačiu pavadinimu jau yra.",
"Invalid filename." : "Neteisingas failo pavadinimas.",
"Rename file" : "Pervadinti failą",
"Recently created" : "Neseniai sukurta",
"Folder" : "Aplankas",
"Unknown file type" : "Nežinomas failo tipas",
"{ext} image" : "{ext} paveikslėlis",
"{ext} video" : "{ext} vaizdo įrašas",
"{ext} audio" : "{ext} garso įrašas",
"{ext} text" : "{ext} tekstas",
"Pending" : "Laukiantis",
"Unknown date" : "Nežinoma data",
"Active filters" : "Aktyvūs filtrai",
@@ -80,6 +107,11 @@
"Today" : "Šiandien",
"Last 7 days" : "Paskutinės 7 dienos",
"Last 30 days" : "Paskutinės 30 dienų",
"This year ({year})" : "Šie metai ({year})",
"Last year ({year})" : "Praėję metai ({year})",
"Custom range" : "Pasirinktinis diapazonas",
"Custom date range" : "Pasirinktinis datų diapazonas",
"Search everywhere" : "Ieškoti visur",
"Documents" : "Dokumentai",
"Spreadsheets" : "Skaičiuoklės",
"Presentations" : "Pateiktys",
@@ -89,26 +121,64 @@
"Images" : "Paveikslai",
"Videos" : "Vaizdo įrašai",
"Filters" : "Filtrai",
"Back to filters" : "Atgal į filtrus",
"Appearance" : "Išvaizda",
"Show hidden files" : "Rodyti paslėptus failus",
"Show file type column" : "Rodyti failo tipo stulpelį",
"Show file extensions" : "Rodyti failų plėtinius",
"Crop image previews" : "Apkirpti paveikslėlių peržiūras",
"General" : "Bendra",
"Sort favorites first" : "Pirmiausia rūšiuoti mėgstamiausius",
"Sort folders before files" : "Rūšiuoti aplankus prieš failus",
"Enable folder tree view" : "Įjungti aplankų medžio rodinį",
"Default view" : "Numatytasis rodinys",
"All files" : "Visi failai",
"Personal files" : "Asmeniniai failai",
"Additional settings" : "Papildomi nustatymai",
"Actions" : "Veiksmai",
"File actions" : "Veiksmai su failais",
"Selection" : "Pasirinkimas",
"Select all files" : "Pasirinkti visus failus",
"Deselect all" : "Panaikinti pasirinkimą",
"Navigation" : "Navigacija",
"Select or deselect" : "Pasirinkti arba panaikinti pasirinkimą",
"Select a range" : "Pasirinkite diapazoną",
"Navigation" : "Naršymas",
"Go to parent folder" : "Eiti į viršesnį aplanką",
"Go to file above" : "Eiti į aukščiau esantį failą",
"Go to file below" : "Eiti į žemiau esantį failą",
"Go left in grid" : "Eiti į kairę tinklelyje",
"Go right in grid" : "Eiti į dešinę tinklelyje",
"View" : "Rodyti",
"Toggle grid view" : "Rodyti tinkleliu",
"Toggle grid view" : "Perjungti tinklelio rodinį",
"Show those shortcuts" : "Rodyti tuos sparčiuosius klavišus",
"Warnings" : "Įspėjimai",
"Warn before changing a file extension" : "Įspėti prieš keičiant failo prievardį",
"Warn before deleting a file" : "Įspėti prieš ištrinant failą",
"WebDAV URL" : "WebDAV URL",
"Create an app password" : "Sukurkite programėlės slaptažodį",
"Required for WebDAV authentication because Two-Factor Authentication is enabled for this account." : "Būtina „WebDAV“ autentifikavimui, nes šiai paskyrai įjungtas dviejų veiksnių autentifikavimas.",
"How to access files using WebDAV" : "Kaip pasiekti failus naudojant WebDAV",
"Total rows summary" : "Bendras eilučių skaičius",
"Toggle selection for all files and folders" : "Perjungti visų failų ir aplankų pasirinkimą",
"Name" : "Pavadinimas",
"File type" : "Failo tipas",
"Size" : "Dydis",
"Modified" : "Pakeistas",
"{displayName}: failed on some elements" : "{displayName}: kai kurių elementų klaida",
"{displayName}: done" : "{displayName}: padaryta",
"{displayName}: failed" : "{displayName}: nepavyko",
"(selected)" : "(pasirinktas)",
"List of files and folders." : "Failų ir aplankų sąrašas.",
"You have used your space quota and cannot upload files anymore." : "Išnaudojote savo vietos kvotą ir daugiau negalite įkelti failų.",
"Column headers with buttons are sortable." : "Stulpelių antraštes su mygtukais galima rūšiuoti.",
"This list is not fully rendered for performance reasons. The files will be rendered as you navigate through the list." : "Šis sąrašas nėra pilnai sugeneruotas dėl našumo priežasčių. Failai bus sugeneruoti jums naršant sąraše.",
"File not found" : "Failas nerastas",
"_{count} selected_::_{count} selected_" : ["{count} pasirinktas","{count} pasirinkti","{count} pasirinkti","{count} pasirinkti"],
"Views" : "Rodiniai",
"Search everywhere …" : "Ieškoti visur…",
"Search here …" : "Ieškoti čia…",
"Search scope options" : "Paieškos apimties parinktys",
"Search here" : "Ieškoti čia",
"Owner" : "Savininkas",
"{usedQuotaByte} used" : "Naudojama {usedQuotaByte}",
"{used} of {quota} used" : "panaudota {used} iš {quota}",
@@ -116,11 +186,32 @@
"Could not refresh storage stats" : "Nepavyko iš naujo įkelti saugyklos statistikos",
"Your storage is full, files can not be updated or synced anymore!" : "Jūsų saugykla pilna, failai daugiau nebegali būti atnaujinti arba sinchronizuojami!",
"Storage information" : "Informacija apie saugyklą",
"Storage quota" : "Saugyklos kvota",
"New folder" : "Naujas aplankas",
"Create new folder" : "Sukurti naują aplanką",
"This name is already in use." : "Šis pavadinimas jau yra naudojamas.",
"Create" : "Sukurti",
"Files starting with a dot are hidden by default" : "Failai, prasidedantys tašku, pagal numatytuosius nustatymus yra paslėpti",
"Failed to start filename sanitization." : "Nepavyko pradėti failų pavadinimų valymo.",
"Failed to refresh filename sanitization status." : "Nepavyko atnaujinti failo pavadinimo išvalymo būsenos.",
"Filename sanitization in progress." : "Vykdomas failų pavadinimų valymas.",
"Currently {processedUsers} of {totalUsers} accounts are already processed." : "Šiuo metu {processedUsers} naudotojų paskyros iš {totalUsers} egzistuojančių jau apdorotos.",
"Preparing …" : "Ruošiama…",
"Refresh" : "Įkelti iš naujo",
"All files have been santized for Windows filename support." : "Visi failai buvo patvirtinti, kad atitiktų „Windows“ failų pavadinimų reikalavimus.",
"Some files could not be sanitized, please check your logs." : "Kai kurių failų nepavyko išvalyti, patikrinkite savo registrų įrašų žurnalus.",
"Sanitization errors" : "Valymo klaidos",
"Not sanitized filenames" : "Neišvalyti failų vardai",
"Windows filename support has been enabled." : "Įjungtas „Windows“ failų vardų palaikymas.",
"While this blocks users from creating new files with unsupported filenames, existing files are not yet renamed and thus still may break sync on Windows." : "Nors tai neleidžia vartotojams kurti naujų failų su nepalaikomais failų pavadinimais, esami failai dar nėra pervadinti, todėl vis tiek gali sutrikdyti sinchronizavimą sistemoje „Windows“.",
"You can trigger a rename of files with invalid filenames, this will be done in the background and may take some time." : "Galite pervadinti failus su neteisingais pavadinimais. Tai bus atliekama fone ir gali užtrukti.",
"Please note that this may cause high workload on the sync clients." : "Atminkite, kad tai gali sukelti didelį sinchronizavimo klientų darbo krūvį.",
"Limit" : "Limitas",
"This allows to configure how many users should be processed in one background job run." : "Tai leidžia konfigūruoti, kiek vartotojų turėtų būti apdorojama vieno foninio darbo vykdymo metu.",
"Sanitize filenames" : "Išvalyti failų pavadinimus",
"(starting)" : "(pradedama)",
"Fill template fields" : "Užpildykite šablono laukus",
"Submitting fields …" : "Pateikiami laukai  ...",
"Submit" : "Pateikti",
"Choose a file or folder to transfer" : "Pasirinkite norimą perduoti failą ar aplanką",
"Transfer" : "Perduoti",
@@ -128,104 +219,197 @@
"Invalid path selected" : "Pasirinktas neteisingas kelias",
"Unknown error" : "Nežinoma klaida",
"Ownership transfer request sent" : "Nuosavybės perdavimo užklausa išsiųsta",
"Cannot transfer ownership of a file or folder you do not own" : "Negalima perduoti jums nepriklausančio failo ar aplanko nuosavybės teisės",
"Transfer ownership of a file or folder" : "Perduoti failo ar aplanko nuosavybę",
"Choose file or folder to transfer" : "Pasirinkti norimą perduoti failą ar aplanką",
"Change" : "Keisti",
"New owner" : "Naujasis savininkas",
"Keep {old}" : "Palikti {old}",
"Keep without extension" : "Palikti be prievardžio",
"Use {new}" : "Naudoti {new}",
"Remove extension" : "Pašalinti prievardį",
"Change file extension" : "Keisti failo prievardį",
"Changing the file extension from \"{old}\" to \"{new}\" may render the file unreadable." : "Pakeitus failo plėtinį iš „{old}“ į „{new}“, failas gali tapti neįskaitomas.",
"Removing the file extension \"{old}\" may render the file unreadable." : "Pašalinus failo plėtinį „{old}“, failas gali tapti neįskaitomas.",
"Adding the file extension \"{new}\" may render the file unreadable." : "Pridėjus failo plėtinį „{new}“, failas gali tapti neįskaitomas.",
"Do not show this dialog again." : "Daugiau neberodyti šio dialogo.",
"Rename file to hidden" : "Pervadinti failą į paslėptą",
"Prefixing a filename with a dot may render the file hidden." : "Failo pavadinimo pradžioje įrašius tašką, failas gali būti paslėptas.",
"Are you sure you want to rename the file to \"{filename}\"?" : "Ar tikrai norite pervardyti failą į „{filename}“?",
"Cancel" : "Atsisakyti",
"Rename" : "Pervadinti",
"Select file or folder to link to" : "Pasirinkite failą arba aplanką, į kurį norite susieti",
"Choose {file}" : "Pasirinkti{file}",
"Files settings" : "Failų nustatymai",
"Switch to list view" : "Perjungti į sąrašo rodinį",
"Switch to grid view" : "Perjungti į tinklelio rodinį",
"The file could not be found" : "Failas nerastas",
"Upload was cancelled by user" : "Įkelimas buvo atšauktas vartotojo",
"The file could not be found" : "Nepavyko rasti failo",
"Upload was cancelled by user" : "Naudotojas atsisakė failo išsiuntimo",
"Not enough free space" : "Trūksta laisvos vietos",
"Operation is blocked by access control" : "Operacija yra užblokuota prieigos valdymo",
"Error during upload: {message}" : "Įkėlimo klaida: {message}",
"Error during upload, status code {status}" : "Įkėlimo klaida, būsenos kodas - {status}",
"Unknown error during upload" : "Įkėlimo metu įvyko nežinoma klaida",
"File list is reloading" : "Failų sąrašas įkeliamas iš naujo",
"Loading current folder" : "Įkeliamas dabartinis aplankas",
"Retry" : "Bandyti dar kartą",
"No files in here" : "Čia failų nėra",
"Upload some content or sync with your devices!" : "Įkelkite failus arba sinchronizuokite su savo įrenginiais!",
"Go back" : "Grįžti",
"Loading …" : "Įkeliama …",
"Loading …" : "Įkeliama…",
"Your files" : "Jūsų failai",
"Open in files" : "Atidaryti failuose",
"File cannot be accessed" : "Nepavyksta gauti prieigos prie failo",
"The file could not be found or you do not have permissions to view it. Ask the sender to share it." : "Nepavyko surasti failo arba jūs neturite leidimo jo peržiūrėti. Paprašykite siuntėjo, kad pradėtų jį su jumis bendrinti.",
"No search results for “{query}”" : "Nėra paieškos rezultatų pagal užklausą „{query}“",
"Search for files" : "Ieškoti failų",
"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." : "Leisti apriboti failų pavadinimus, siekiant užtikrinti, kad failus būtų galima sinchronizuoti su visais klientais. Pagal numatytuosius nustatymus leidžiami visi failų vardai, galiojantys POSIX (pvz., Linux arba macOS).",
"After enabling the Windows compatible filenames, existing files cannot be modified anymore but can be renamed to valid new names by their owner." : "Įjungus su „Windows“ suderinamus failų pavadinimus, esamų failų nebegalima modifikuoti, tačiau jų savininkas gali juos pervadinti galiojančiais naujais pavadinimais.",
"Failed to toggle Windows filename support" : "Nepavyko įjungti „Windows“ failų vardų palaikymo",
"Files compatibility" : "Failų suderinamumas",
"Enforce Windows compatibility" : "Užtikrinti suderinamumą su „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." : "Tai blokuos „Windows“ sistemose negaliojančius failų pavadinimus, pvz., rezervuotus pavadinimus ar specialiuosius simbolius. Tačiau tai neužtikrins didžiųjų ir mažųjų raidžių skyrimo suderinamumo.",
"Blank" : "Tuščia",
"Unable to create new file from template" : "Nepavyko sukurti naujo failo iš šablono",
"Pick a template for {name}" : "Pasirinkite šabloną, skirtą {name}",
"Create a new file with the selected template" : "Sukurti naują failą naudojant pasirinktą šabloną",
"Creating file" : "Sukuriamas failas",
"Save as {displayName}" : "Įrašyti kaip {displayName}",
"Save as …" : "Įrašyti kaip…",
"Converting files …" : "Failų konvertavimas  ...",
"Failed to convert files: {message}" : "Nepavyko konvertuoti failų: {message}",
"All files failed to be converted" : "Nepavyko konvertuoti visų failų",
"One file could not be converted: {message}" : "Vieno failo nepavyko konvertuoti: {message}",
"_%n file could not be converted_::_%n files could not be converted_" : ["%n failas negali būti konvertuotas","%n failai negali būti konvertuoti","%n failų negali būti konvertuota","%n failų negali būti konvertuota"],
"_%n file converted_::_%n files converted_" : ["%n failas konvertuotas","%n failai konvertuoti","%n failų konvertuota","%n failų konvertuota"],
"Files converted" : "Failai konvertuoti",
"Failed to convert files" : "Nepavyko konvertuoti failų",
"Converting file …" : "Failai konvertuojami  ...",
"File successfully converted" : "Failas sėkmingai konvertuotas",
"Failed to convert file: {message}" : "Nepavyko konvertuoti failo: {message}",
"Failed to convert file" : "Nepavyko konvertuoti failo",
"Delete" : "Ištrinti",
"Leave this share" : "Palikti bendrinimą",
"Leave these shares" : "Palikti bendrinimus",
"Disconnect storage" : "Atjungti saugyklą",
"Delete permanently" : "Ištrinti negrįžtamai",
"Disconnect storages" : "Atjungti saugyklas",
"Delete permanently" : "Ištrinti visam laikui",
"Delete and unshare" : "Ištrinti ir nebebendrinti",
"Delete file" : "Ištrinti failą",
"Delete files" : "Ištrinti failus",
"Delete folder" : "Ištrinti aplanką",
"Delete folders" : "Ištrinti aplankus",
"_You are about to permanently delete {count} item_::_You are about to permanently delete {count} items_" : ["Ketinate visam laikui ištrinti {count} elementą","Ketinate visam laikui ištrinti {count} elementus","Ketinate visam laikui ištrinti {count} elementų","Ketinate visam laikui ištrinti {count} elementų"],
"_You are about to delete {count} item_::_You are about to delete {count} items_" : ["Jūs ketinate ištrinti {count} elementą","Jūs ketinate ištrinti {count} elementus","Jūs ketinate ištrinti {count} elementų","Jūs ketinate ištrinti {count} elementą"],
"Confirm deletion" : "Patvirtinti ištrynimą",
"Download" : "Atsisiųsti",
"The requested file is not available." : "Prašomo failo nėra.",
"The requested files are not available." : "Prašomų failų nėra.",
"Add to favorites" : "Pridėti į mėgstamus",
"Remove from favorites" : "Šalinti iš mėgstamų",
"Add or remove favorite" : "Pridėti arba pašalinti mėgstamiausią",
"Move" : "Perkelti",
"Copy" : "Kopijuoti",
"Move or copy" : "Perkelti ar kopijuoti",
"Destination is not a folder" : "Paskirties vieta nėra aplankas",
"This file/folder is already in that directory" : "Šis failas / aplankas jau yra tame kataloge",
"You cannot move a file/folder onto itself or into a subfolder of itself" : "Negalite perkelti failo / aplanko ant jo paties arba į jo paties poaplankį",
"A file or folder with that name already exists in this folder" : "Failas arba aplankas tokiu pavadinimu jau yra šiame aplanke",
"The files are locked" : "Failai yra užrakinti",
"The file does not exist anymore" : "Failo daugiau nebėra",
"Moving \"{source}\" to \"{destination}\" …" : "Perkeliama \"{source}\" į \"{destination}\"  ...",
"Moving {count} files to \"{destination}\" …" : "{count} failai perkeliami į \"{destination}\"  ...",
"Copying \"{source}\" to \"{destination}\" …" : "Kopijuojama iš \"{source}\" į \"{destination}\"  ...",
"Copying {count} files to \"{destination}\" …" : "{count} failai kopijuojami į \"{destination}\"  ...",
"Choose destination" : "Pasirinkite paskirties vietą",
"Copy to {target}" : "Kopijuoti į {target}",
"Move to {target}" : "Perkelti į {target}",
"Move or copy operation failed" : "Perkėlimo ar kopijavimo operacija patyrė nesėkmę",
"Open folder" : "Atverti aplanką",
"Open folder {displayName}" : "Atverti aplanką {displayName}",
"Open in Files" : "Atidaryti programėlėje Files",
"Open locally" : "Atidaryti vietoje",
"Failed to redirect to client" : "Nepavyko peradresuoti į klientą",
"Open file locally" : "Atidaryti failą vietoje",
"The file should now open on your device. If it doesn't, please check that you have the desktop app installed." : "Failas dabar turėtų atsidaryti jūsų įrenginyje. Jei ne, patikrinkite, ar įdiegta darbalaukio programėlė.",
"Retry and close" : "Bandyti dar kartą ir užverti",
"Open online" : "Atidaryti internete",
"Details" : "Išsamiau",
"Open the details sidebar" : "Atidaryti išsamios informacijos šoninę juostą",
"Unfavorite" : "Pašalinti iš mėgstamiausių",
"View in folder" : "Rodyti aplanke",
"Type" : "Tipas",
"Created new folder \"{name}\"" : "Sukurtas naujas aplankas „{name}“",
"Unable to initialize the templates directory" : "Nepavyko inicijuoti šablonų katalogo",
"Create templates folder" : "Sukurti šablonų aplanką",
"Templates" : "Šablonai",
"New template folder" : "Naujas šablonų aplankas",
"In folder" : "Aplanke",
"Pick folder to search in" : "Pasirinkite aplanką, kuriame norite ieškoti",
"Search in all files" : "Ieškoti visuose failuose",
"Search in folder: {folder}" : "Ieškoti aplanke: {folder}",
"One of the dropped files could not be processed" : "Vieno iš atmestų failų apdoroti nepavyko",
"Your browser does not support the Filesystem API. Directories will not be uploaded" : "Jūsų naršyklė nepalaiko failų sistemos API. Katalogai nebus įkelti.",
"No files to upload" : "Nėra failų, kuriuos būtų galima įkelti",
"Unable to create the directory {directory}" : "Nepavyko sukurti katalogo {directory}",
"Some files could not be uploaded" : "Kai kurių failų nepavyko išsiųsti",
"Files uploaded successfully" : "Failai sėkmingai išsiųsti",
"No files to process" : "Nėra failų, kuriuos reikėtų apdoroti",
"Files copied successfully" : "Failai sėkmingai nukopijuoti",
"Files moved successfully" : "Failai sėkmingai perkelti",
"Some files could not be copied" : "Kai kurių failų nepavyko nukopijuoti",
"Some files could not be moved" : "Kai kurių failų nepavyko perkelti",
"Could not rename \"{oldName}\", it does not exist any more" : "Nepavyko pervadinti failo „{oldName}“, jo daugiau nebėra",
"Conflicts resolution skipped" : "Konfliktų sprendimas praleistas",
"Upload cancelled" : "Įkėlimas atšauktas",
"Could not rename \"{oldName}\", it does not exist any more" : "Nepavyko pervadinti „{oldName}“, jo daugiau nebėra",
"The name \"{newName}\" is already used in the folder \"{dir}\". Please choose a different name." : "Pavadinimas „{newName}“ jau naudojamas aplanke „{dir}“. Pasirinkite kitokį pavadinimą.",
"Could not rename \"{oldName}\"" : "Nepavyko pervadinti „{oldName}“",
"This operation is forbidden" : "Ši operacija yra uždrausta",
"This folder is unavailable, please try again later or contact the administration" : "Šis aplankas neprieinamas, bandykite dar kartą vėliau arba susisiekite su administratoriumi",
"Storage is temporarily not available" : "Saugykla yra laikinai neprieinama",
"Unexpected error: {error}" : "Netikėta klaida: {error}",
"_%n file_::_%n files_" : ["%n failas","%n failai","%n failų","%n failas"],
"_%n folder_::_%n folders_" : ["%n aplankas","%n aplankai","%n aplankų","%n aplankas"],
"_%n hidden_::_%n hidden_" : ["%n paslėptas","%n paslėpti","%n paslėptų","%n paslėptas"],
"Filename must not be empty." : "Failo pavadinimas negali būti tuščias.",
"\"{char}\" is not allowed inside a filename." : "\"{char}\" simbolis failo pavadinime neleidžiamas",
"\"{segment}\" is a reserved name and not allowed for filenames." : "„{segment}“ yra rezervuotas pavadinimas ir neleidžiamas naudoti failo pavadinimuose.",
"\"{extension}\" is not an allowed filetype." : "„{extension}“ nėra leidžiamas failo tipas.",
"Filenames must not end with \"{extension}\"." : "Failų pavadinimai negali baigtis „{extension}“.",
"List of favorite files and folders." : "Mėgstamiausių failų ir aplankų sąrašas.",
"No favorites yet" : "Kol kas nėra mėgstamų",
"Files and folders you mark as favorite will show up here" : "Čia bus rodomi failai ir aplankai, kuriuos pažymėsite kaip mėgstamus",
"List of your files and folders." : "Jūsų failų ir aplankų sąrašas.",
"Folder tree" : "Aplankų medis",
"List of your files and folders that are not shared." : "Jūsų nebendrinamų failų ir aplankų sąrašas.",
"No personal files found" : "Nerasta jokių asmeninių failų",
"Files that are not shared will show up here." : "Čia bus rodomi nebendrinami failai.",
"Recent" : "Paskiausiai naudoti",
"List of recently modified files and folders." : "Paskiausiai modifikuotų failų ir aplankų sąrašas.",
"No recently modified files" : "Nėra jokių paskiausiai modifikuotų failų",
"Files and folders you recently modified will show up here." : "Čia bus rodomi neseniai modifikuoti failai ir aplankai.",
"Search" : "Paieška",
"Search results within your files." : "Paieškos rezultatai jūsų failuose.",
"No entries found in this folder" : "Nerasta įrašų šiame aplanke",
"Select all" : "Pažymėti viską",
"Upload too large" : "Įkėlimui failas per didelis",
"The files you are trying to upload exceed the maximum size for file uploads on this server." : "Bandomų įkelti failų dydis viršija maksimalų, šiame serveryje leidžiamų įkelti failų dydį.",
"Renamed \"{oldName}\" to \"{newName}\"" : "„{oldName}“ pervadintas į „{newName}“",
"Clear filter" : "Išvalyti filtrą",
"Open file sidebar" : "Atverti failų šoninę juostą",
"Search everywhere …" : "Ieškoti visur…",
"Search here …" : "Ieškoti čia…",
"Preparing …" : "Ruošiama...",
"Submitting fields …" : "Pateikiami laukai...",
"Shared by link" : "Bendrinama pagal nuorodą",
"Shared" : "Bendrinama",
"You" : "Jūs",
"Shared multiple times with different people" : "Dalijimasis kelis kartus su skirtingais žmonėmis",
"Unable to change the favorite state of the file" : "Nepavyko pakeisti failo mėgstamiausios būsenos",
"Error while loading the file data" : "Klaida įkeliant failo duomenis",
"Tags" : "Žymos",
"Save as …" : "Įrašyti kaip…"
"Save as …" : "Įrašyti kaip…",
"Converting files …" : "Failų konvertavimas…",
"Converting file …" : "Failo konvertavimas…"
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
}
+1
View File
@@ -95,6 +95,7 @@ OC.L10N.register(
"Another entry with the same name already exists." : "Друг запис со исто име веќе постои.",
"Invalid filename." : "Невалидно име.",
"Rename file" : "Преименувај датотека",
"Recently created" : "Неодамна креирани",
"Folder" : "Папка",
"Unknown file type" : "Непознат тип на датотека",
"{ext} image" : "{ext} слика",
+1
View File
@@ -93,6 +93,7 @@
"Another entry with the same name already exists." : "Друг запис со исто име веќе постои.",
"Invalid filename." : "Невалидно име.",
"Rename file" : "Преименувај датотека",
"Recently created" : "Неодамна креирани",
"Folder" : "Папка",
"Unknown file type" : "Непознат тип на датотека",
"{ext} image" : "{ext} слика",
+1 -1
View File
@@ -46,7 +46,7 @@ OC.L10N.register(
"Failed to authorize" : "Autorizácia zlyhala",
"Invalid folder path" : "Neplatná cesta k priečinku",
"Folder not found" : "Priečinok nebol nájdený",
"The file cannot be found" : "Súbor sa nepodarilo nájisť",
"The file cannot be found" : "Súbor sa nepodarilo nájsť",
"The destination path does not exist: %1$s" : "Cieľová cesta neexistuje: %1$s",
"You do not have permission to create a file at the specified location" : "Nemáte oprávnenie vytvoriť súbor v zadanom umiestnení",
"The file could not be converted." : "Súbor nemohol byť skonvertovaný.",
+1 -1
View File
@@ -44,7 +44,7 @@
"Failed to authorize" : "Autorizácia zlyhala",
"Invalid folder path" : "Neplatná cesta k priečinku",
"Folder not found" : "Priečinok nebol nájdený",
"The file cannot be found" : "Súbor sa nepodarilo nájisť",
"The file cannot be found" : "Súbor sa nepodarilo nájsť",
"The destination path does not exist: %1$s" : "Cieľová cesta neexistuje: %1$s",
"You do not have permission to create a file at the specified location" : "Nemáte oprávnenie vytvoriť súbor v zadanom umiestnení",
"The file could not be converted." : "Súbor nemohol byť skonvertovaný.",
-34
View File
@@ -7,43 +7,9 @@
*/
namespace OCA\Files;
use OC\NavigationManager;
use OCA\Files\Service\ChunkedUploadConfig;
use OCP\App\IAppManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IGroupManager;
use OCP\INavigationManager;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Server;
use Psr\Log\LoggerInterface;
class App {
private static ?INavigationManager $navigationManager = null;
/**
* Returns the app's navigation manager
*/
public static function getNavigationManager(): INavigationManager {
// TODO: move this into a service in the Application class
if (self::$navigationManager === null) {
self::$navigationManager = new NavigationManager(
Server::get(IAppManager::class),
Server::get(IUrlGenerator::class),
Server::get(IFactory::class),
Server::get(IUserSession::class),
Server::get(IGroupManager::class),
Server::get(IConfig::class),
Server::get(LoggerInterface::class),
Server::get(IEventDispatcher::class),
);
self::$navigationManager->clear(false);
}
return self::$navigationManager;
}
public static function extendJsConfig($settings): void {
$appConfig = json_decode($settings['array']['oc_appconfig'], true);
+8
View File
@@ -22,6 +22,7 @@ use OCP\Config\ValueType;
*/
class ConfigLexicon implements ILexicon {
public const OVERWRITES_HOME_FOLDERS = 'overwrites_home_folders';
public const RECENT_LIMIT = 'recent_limit';
public function getStrictness(): Strictness {
return Strictness::IGNORE;
@@ -37,6 +38,13 @@ class ConfigLexicon implements ILexicon {
lazy: false,
note: 'It will be populated with app IDs of mount providers that overwrite home folders. Currently, only files_external and groupfolders.',
),
new Entry(
self::RECENT_LIMIT,
ValueType::INT,
defaultRaw: 100,
definition: 'Maximum number of files to display on recent files view',
lazy: false,
),
];
}
@@ -10,6 +10,7 @@ namespace OCA\Files\Controller;
use OC\Files\FilenameValidator;
use OC\Files\Filesystem;
use OCA\Files\AppInfo\Application;
use OCA\Files\ConfigLexicon;
use OCA\Files\Event\LoadAdditionalScriptsEvent;
use OCA\Files\Event\LoadSearchPlugins;
use OCA\Files\Event\LoadSidebar;
@@ -25,6 +26,7 @@ use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Services\IInitialState;
use OCP\Authentication\TwoFactorAuth\IRegistry;
use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent as ResourcesLoadAdditionalScriptsEvent;
@@ -62,6 +64,7 @@ class ViewController extends Controller {
private ViewConfig $viewConfig,
private FilenameValidator $filenameValidator,
private IRegistry $twoFactorRegistry,
private IAppConfig $appConfig,
) {
parent::__construct($appName, $request);
}
@@ -174,6 +177,7 @@ class ViewController extends Controller {
$this->initialState->provideInitialState('storageStats', $storageInfo);
$this->initialState->provideInitialState('config', $this->userConfig->getConfigs());
$this->initialState->provideInitialState('viewConfigs', $this->viewConfig->getConfigs());
$this->initialState->provideInitialState('recent_limit', $this->appConfig->getAppValueInt(ConfigLexicon::RECENT_LIMIT, 100));
// File sorting user config
$filesSortingConfig = json_decode($this->config->getUserValue($userId, 'files', 'files_sorting_configs', '{}'), true);
+9 -4
View File
@@ -37,10 +37,15 @@ export const action: IFileAction = {
: filesStore.getNode(dirname(node.source))
const parentPermissions = parentNode?.permissions || Permission.NONE
// Only enable if the node have the delete permission
// and if the parent folder allows creating files
return Boolean(node.permissions & Permission.DELETE)
&& Boolean(parentPermissions & Permission.CREATE)
// Enable if the node has update permissions or the node
// has delete permission and the parent folder allows creating files
return (
(
Boolean(node.permissions & Permission.DELETE)
&& Boolean(parentPermissions & Permission.CREATE)
)
|| Boolean(node.permissions & Permission.UPDATE)
)
},
async exec({ nodes }) {
+3 -1
View File
@@ -8,12 +8,14 @@ import type { ResponseDataDetailed, SearchResult } from 'webdav'
import { getCurrentUser } from '@nextcloud/auth'
import { Folder, Permission } from '@nextcloud/files'
import { getRecentSearch, getRemoteURL, getRootPath, resultToNode } from '@nextcloud/files/dav'
import { loadState } from '@nextcloud/initial-state'
import logger from '../logger.ts'
import { getPinia } from '../store/index.ts'
import { useUserConfigStore } from '../store/userconfig.ts'
import { client } from './WebdavClient.ts'
const lastTwoWeeksTimestamp = Math.round((Date.now() / 1000) - (60 * 60 * 24 * 14))
const recentLimit = loadState<number>('files', 'recent_limit', 100)
/**
* Get recently changed nodes
@@ -41,7 +43,7 @@ export async function getContents(path = '/', options: { signal: AbortSignal }):
const contentsResponse = await client.search('/', {
signal: options.signal,
details: true,
data: getRecentSearch(lastTwoWeeksTimestamp),
data: getRecentSearch(lastTwoWeeksTimestamp, recentLimit),
}) as ResponseDataDetailed<SearchResult>
const contents = contentsResponse.data.results
@@ -18,6 +18,7 @@ use OCP\App\IAppManager;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\RedirectResponse;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IAppConfig;
use OCP\AppFramework\Services\IInitialState;
use OCP\Authentication\TwoFactorAuth\IRegistry;
use OCP\Diagnostics\IEventLogger;
@@ -48,6 +49,7 @@ use Test\TestCase;
class ViewControllerTest extends TestCase {
private ContainerInterface&MockObject $container;
private IAppManager&MockObject $appManager;
private IAppConfig&MockObject $appConfig;
private ICacheFactory&MockObject $cacheFactory;
private IConfig&MockObject $config;
private IEventDispatcher $eventDispatcher;
@@ -71,6 +73,7 @@ class ViewControllerTest extends TestCase {
protected function setUp(): void {
parent::setUp();
$this->appManager = $this->createMock(IAppManager::class);
$this->appConfig = $this->createMock(IAppConfig::class);
$this->config = $this->createMock(IConfig::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->initialState = $this->createMock(IInitialState::class);
@@ -142,6 +145,7 @@ class ViewControllerTest extends TestCase {
$this->viewConfig,
$filenameValidator,
$this->twoFactorRegistry,
$this->appConfig,
])
->onlyMethods([
'getStorageInfo',
@@ -298,11 +302,11 @@ class ViewControllerTest extends TestCase {
'backup_codes' => true,
]);
$invokedCountProvideInitialState = $this->exactly(9);
$invokedCountProvideInitialState = $this->exactly(10);
$this->initialState->expects($invokedCountProvideInitialState)
->method('provideInitialState')
->willReturnCallback(function ($key, $data) use ($invokedCountProvideInitialState): void {
if ($invokedCountProvideInitialState->numberOfInvocations() === 9) {
if ($invokedCountProvideInitialState->numberOfInvocations() === 10) {
$this->assertEquals('isTwoFactorEnabled', $key);
$this->assertTrue($data);
}
+6
View File
@@ -83,12 +83,15 @@ OC.L10N.register(
"External storage support" : "Support de stockage externe",
"Adds basic external storage support" : "Ajoute la prise en charge de base du stockage externe",
"This application enables administrators to configure connections to external storage providers, such as FTP servers, S3 or SWIFT object stores, other Nextcloud servers, WebDAV servers, and more. Administration can choose which types of storage to enable and can mount these storage locations for an account, a group, or the entire system. Users will see a new folder appear in their root Nextcloud directory, which they can access and use like any other Nextcloud folder. External storage also allows people to share files stored in these external locations. In these cases, the credentials for the owner of the file are used when the recipient requests the file from external storage, thereby ensuring that the recipient can access the shared file.\n\nExternal storage can be configured using the GUI or at the command line. This second option provides the administration with more flexibility for configuring bulk external storage mounts and setting mount priorities. More information is available in the external storage GUI documentation and the external storage Configuration File documentation." : "Cette application permet aux administrateurs de configurer des connexions à des stockage externes, tels que des serveurs FTP, des stockages d'objets S3 ou SWIFT, d'autres serveurs Nextcloud, des serveurs WebDAV, etc. L'administrateur peut choisir les types de stockage à activer et peut monter ces emplacements de stockage pour un compte, un groupe ou l'ensemble du système. Les utilisateurs verront apparaître un nouveau dossier dans leur répertoire racine Nextcloud, auquel ils pourront accéder et utiliser comme n'importe quel autre dossier Nextcloud. Le stockage externe permet également aux personnes de partager des fichiers stockés dans ces emplacements externes. Dans ce cas, les informations d'identification du propriétaire du fichier sont utilisées lorsque le destinataire demande le fichier à partir du stockage externe, garantissant ainsi que le destinataire peut accéder au fichier partagé.\n\nLe stockage externe peut être configuré à l'aide de l'interface graphique ou via l'interface en ligne de commande. Cette deuxième option offre à l'administration une plus grande flexibilité pour configurer les montages de stockage externes en masse et définir les priorités de montage. D'autres informations sont disponibles dans la documentation de l'interface graphique de stockage externe et la documentation du fichier de configuration de stockage externe.",
"Edit storage" : "Modifier le stockage",
"Add storage" : "Ajouter un stockage",
"Folder name" : "Nom du dossier",
"Authentication" : "Authentification",
"Cancel" : "Annuler",
"Edit" : "Modifier",
"Create" : "Créer",
"Restrict to" : "Restreindre à",
"Storage configuration" : "Configuration du stockage",
"Never" : "Jamais",
"Once every direct access" : "Une fois par accès direct",
"Always" : "Toujours",
@@ -99,6 +102,7 @@ OC.L10N.register(
"Compatibility with Mac NFD encoding (slow)" : "Compatibilité avec l'encodage Mac NFD (lent)",
"External storages" : "Stockages externes",
"Status" : "Statut",
"Restricted to" : "Restreint à",
"Actions" : "Actions",
"Checking …" : "Vérification  ...",
"Recheck status" : "Vérifier à nouveau le statut",
@@ -118,6 +122,7 @@ OC.L10N.register(
"Enter the storage password" : "Entrez le mot de passe du stockage",
"{module} is not installed." : "{module} nest pas installé",
"Dependant backends" : "Backends dépendants",
"Add external storage" : "Ajouter un stockage externe",
"Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Les identifiants globaux peuvent être utilisés pour s'authentifier auprès de multiples stockages externes qui ont les mêmes identifiants.",
"Saving …" : "Enregistrement  …",
"Save" : "Enregistrer",
@@ -133,6 +138,7 @@ OC.L10N.register(
"Open in Files" : "Ouvrir dans Fichiers",
"External mount error" : "Erreur montage externe",
"There was an error with this external storage. Do you want to review this mount point config in the settings page?" : "Une erreur est survenue avec ce stockage externe. Voulez-vous vérifier la configuration de ce point de montage dans la page des paramètres ?",
"Open settings" : "Ouvrir les paramètres",
"Ignore" : "Ignorer",
"List of external storage." : "Liste des périphériques de stockage externes.",
"There is no external storage configured. You can configure them in your Personal settings." : "Aucun stockage externe n'est configuré. Vous pouvez le configurer dans vos Paramètres personnels.",
+6
View File
@@ -81,12 +81,15 @@
"External storage support" : "Support de stockage externe",
"Adds basic external storage support" : "Ajoute la prise en charge de base du stockage externe",
"This application enables administrators to configure connections to external storage providers, such as FTP servers, S3 or SWIFT object stores, other Nextcloud servers, WebDAV servers, and more. Administration can choose which types of storage to enable and can mount these storage locations for an account, a group, or the entire system. Users will see a new folder appear in their root Nextcloud directory, which they can access and use like any other Nextcloud folder. External storage also allows people to share files stored in these external locations. In these cases, the credentials for the owner of the file are used when the recipient requests the file from external storage, thereby ensuring that the recipient can access the shared file.\n\nExternal storage can be configured using the GUI or at the command line. This second option provides the administration with more flexibility for configuring bulk external storage mounts and setting mount priorities. More information is available in the external storage GUI documentation and the external storage Configuration File documentation." : "Cette application permet aux administrateurs de configurer des connexions à des stockage externes, tels que des serveurs FTP, des stockages d'objets S3 ou SWIFT, d'autres serveurs Nextcloud, des serveurs WebDAV, etc. L'administrateur peut choisir les types de stockage à activer et peut monter ces emplacements de stockage pour un compte, un groupe ou l'ensemble du système. Les utilisateurs verront apparaître un nouveau dossier dans leur répertoire racine Nextcloud, auquel ils pourront accéder et utiliser comme n'importe quel autre dossier Nextcloud. Le stockage externe permet également aux personnes de partager des fichiers stockés dans ces emplacements externes. Dans ce cas, les informations d'identification du propriétaire du fichier sont utilisées lorsque le destinataire demande le fichier à partir du stockage externe, garantissant ainsi que le destinataire peut accéder au fichier partagé.\n\nLe stockage externe peut être configuré à l'aide de l'interface graphique ou via l'interface en ligne de commande. Cette deuxième option offre à l'administration une plus grande flexibilité pour configurer les montages de stockage externes en masse et définir les priorités de montage. D'autres informations sont disponibles dans la documentation de l'interface graphique de stockage externe et la documentation du fichier de configuration de stockage externe.",
"Edit storage" : "Modifier le stockage",
"Add storage" : "Ajouter un stockage",
"Folder name" : "Nom du dossier",
"Authentication" : "Authentification",
"Cancel" : "Annuler",
"Edit" : "Modifier",
"Create" : "Créer",
"Restrict to" : "Restreindre à",
"Storage configuration" : "Configuration du stockage",
"Never" : "Jamais",
"Once every direct access" : "Une fois par accès direct",
"Always" : "Toujours",
@@ -97,6 +100,7 @@
"Compatibility with Mac NFD encoding (slow)" : "Compatibilité avec l'encodage Mac NFD (lent)",
"External storages" : "Stockages externes",
"Status" : "Statut",
"Restricted to" : "Restreint à",
"Actions" : "Actions",
"Checking …" : "Vérification  ...",
"Recheck status" : "Vérifier à nouveau le statut",
@@ -116,6 +120,7 @@
"Enter the storage password" : "Entrez le mot de passe du stockage",
"{module} is not installed." : "{module} nest pas installé",
"Dependant backends" : "Backends dépendants",
"Add external storage" : "Ajouter un stockage externe",
"Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Les identifiants globaux peuvent être utilisés pour s'authentifier auprès de multiples stockages externes qui ont les mêmes identifiants.",
"Saving …" : "Enregistrement  …",
"Save" : "Enregistrer",
@@ -131,6 +136,7 @@
"Open in Files" : "Ouvrir dans Fichiers",
"External mount error" : "Erreur montage externe",
"There was an error with this external storage. Do you want to review this mount point config in the settings page?" : "Une erreur est survenue avec ce stockage externe. Voulez-vous vérifier la configuration de ce point de montage dans la page des paramètres ?",
"Open settings" : "Ouvrir les paramètres",
"Ignore" : "Ignorer",
"List of external storage." : "Liste des périphériques de stockage externes.",
"There is no external storage configured. You can configure them in your Personal settings." : "Aucun stockage externe n'est configuré. Vous pouvez le configurer dans vos Paramètres personnels.",
+82
View File
@@ -1,15 +1,20 @@
OC.L10N.register(
"files_external",
{
"You are not logged in" : "Nesate prisijungęs",
"Permission denied" : "Leidimas atmestas",
"Forbidden to manage local mounts" : "Draudžiama valdyti vietinius prijungimus",
"Storage with ID \"%d\" not found" : "Nerasta saugykla su identifikacijos numeriu \"%d\"",
"Invalid backend or authentication mechanism class" : "Netinkama programinio kodo klasė realizuoja prisijungimo mechanizmą",
"Invalid mount point" : "Neteisingas prijungimo taškas",
"Objectstore forbidden" : "Objektų saugykla yra neprieinama",
"Invalid storage backend \"%s\"" : "Neteisinga saugyklos „%s“ posistemė",
"Not permitted to use backend \"%s\"" : "Neleidžiama naudoti vidinės pusės „%s“",
"Not permitted to use authentication mechanism \"%s\"" : "Neleidžiama naudoti tapatybės nustatymo mechanizmo „%s“",
"Unsatisfied backend parameters" : " Netinkami posistemės parametrai",
"Unsatisfied authentication mechanism parameters" : "Netinkami parametrai perduoti į prisijungimo mechanizmą",
"Insufficient data: %s" : "Trūksta duomenų: %s",
"Storage with ID \"%d\" is not editable by non-admins" : "Ne administratoriai negali redaguoti saugyklos su ID „%d“ ",
"Access key" : "Prieigos raktas",
"Secret key" : "Slaptasis raktas",
"Builtin" : "Įtaisytasis",
@@ -25,18 +30,29 @@ OC.L10N.register(
"API key" : "API raktas",
"Global credentials" : "Visuotiniai prisijungimo duomenys",
"Log-in credentials, save in database" : "Prisijungimo duomenys, saugoti duomenų bazėje",
"Login and password" : "Prisijungimas ir slaptažodis",
"Log-in credentials, save in session" : "Prisijungimo duomenys, saugoti sesijoje",
"Global credentials, manually entered" : "Prisijungimas ir slaptažodis",
"Manually entered, store in database" : "Įvesta rankiniu būdu, saugoma duomenų bazėje",
"RSA public key" : "RSA viešasis raktas",
"Public key" : "Viešasis raktas",
"RSA private key" : "RSA privatusis raktas",
"Private key" : "Privatusis raktas",
"Kerberos default realm, defaults to \"WORKGROUP\"" : "Numatytoji „Kerberos“ sritis, numatytoji reikšmė yra „WORKGROUP“",
"Kerberos ticket Apache mode" : "Kerberos bilieto Apache režimas",
"Kerberos ticket" : "Kerberos bilietas",
"S3 Storage" : "S3 saugykla",
"Bucket" : "Amazon S3 saugykla",
"Hostname" : "Domeno vardas",
"Port" : "Prievadas",
"Proxy" : "Įgaliotasis serveris",
"Region" : "Regionas",
"Storage Class" : "Saugyklos klasė",
"Enable SSL" : "Įjungti SSL",
"Enable Path Style" : "Amazon S3 kelias",
"Legacy (v2) authentication" : "\"Legacy\" (v2) autentifikacija",
"Enable multipart copy" : "Įgalinti kelių dalių kopijavimą",
"Use presigned S3 url" : "Naudoti iš anksto pasirašytą S3 URL",
"SSE-C encryption key" : "SSE-C šifravimo raktas",
"WebDAV" : "WebDAV",
"URL" : "URL",
@@ -54,20 +70,34 @@ OC.L10N.register(
"SMB/CIFS" : "SMB/CIFS",
"Share" : "Bendrinti",
"Show hidden files" : "Rodyti paslėptus failus",
"Case sensitive file system" : "Didžiųjų ir mažųjų raidžių failų sistema",
"Disabling it will allow to use a case insensitive file system, but comes with a performance penalty" : "Išjungus bus galima naudoti didžiųjų ir mažųjų raidžių neįtakojamą failų sistemą, tačiau tai sumažins našumą.",
"Verify ACL access when listing files" : "Patikrinkite ACL prieigą, kai rodomi failai",
"Check the ACL's of each file or folder inside a directory to filter out items where the account has no read permissions, comes with a performance penalty" : "Patikrinkite kiekvieno failo ar aplanko, esančio kataloge, ACL, kad pašalintumėte elementus, kurių paskyra neturi skaitymo teisių, nes tai gali sumažinti našumą.",
"Timeout" : "Pasibaigė laikas",
"SMB/CIFS using OC login" : "SMB/CIFS naudojant OC prisijungimą",
"Login as share" : "Prisijungti kaip bendrinti",
"OpenStack Object Storage" : "„OpenStack“ objektų saugykla",
"Service name" : "Paslaugos vardas",
"Request timeout (seconds)" : "Prisijungimo laikas (sekundėmis)",
"External storage" : "Išorinė saugykla",
"External storage support" : "Išorinės saugyklos priežiūra",
"Adds basic external storage support" : "Pridedama pagrindinė išorinės atminties palaikymo funkcija",
"This application enables administrators to configure connections to external storage providers, such as FTP servers, S3 or SWIFT object stores, other Nextcloud servers, WebDAV servers, and more. Administration can choose which types of storage to enable and can mount these storage locations for an account, a group, or the entire system. Users will see a new folder appear in their root Nextcloud directory, which they can access and use like any other Nextcloud folder. External storage also allows people to share files stored in these external locations. In these cases, the credentials for the owner of the file are used when the recipient requests the file from external storage, thereby ensuring that the recipient can access the shared file.\n\nExternal storage can be configured using the GUI or at the command line. This second option provides the administration with more flexibility for configuring bulk external storage mounts and setting mount priorities. More information is available in the external storage GUI documentation and the external storage Configuration File documentation." : "Ši programa leidžia administratoriams konfigūruoti ryšius su išorinių saugyklų teikėjais, tokiais kaip FTP serveriai, S3 arba SWIFT objektų saugyklos, kiti „Nextcloud“ serveriai, „WebDAV“ serveriai ir kt. Administratorius gali pasirinkti, kokius saugyklų tipus įjungti, ir gali prijungti šias saugyklų vietas paskyrai, grupei arba visai sistemai. Vartotojai pamatys naują aplanką, atsirastą jų šakniniame „Nextcloud“ kataloge, kurį jie galės pasiekti ir naudoti kaip bet kurį kitą „Nextcloud“ aplanką. Išorinė saugykla taip pat leidžia naudotojams bendrinti failus, saugomus šiose išorinėse vietose. Tokiais atvejais, kai gavėjas prašo failo iš išorinės saugyklos, naudojami failo savininko prisijungimo duomenys, taip užtikrinant, kad gavėjas gali pasiekti bendrinamą failą.\n\nIšorinę saugyklą galima konfigūruoti naudojant grafinę sąsają arba komandinėje eilutėje. Ši antroji parinktis suteikia administratoriui daugiau lankstumo konfigūruojant masinį išorinių saugyklų prijungimą ir nustatant prijungimo prioritetus. Daugiau informacijos rasite išorinės saugyklos grafinės sąsajos dokumentacijoje ir išorinės saugyklos konfigūracijos failo dokumentacijoje.",
"Edit storage" : "Redaguoti saugyklą",
"Add storage" : "Pridėti saugyklą",
"Folder name" : "Aplanko pavadinimas",
"Authentication" : "Prisijungimas",
"Cancel" : "Atsisakyti",
"Edit" : "Taisyti",
"Create" : "Sukurti",
"Restrict to" : "Apsiriboti",
"Storage configuration" : "Saugyklos konfigūracija",
"Never" : "Niekada",
"Once every direct access" : "Kartą per tiesioginę peržiūrą",
"Always" : "Visada",
"Mount options" : "Prijungimo parinktys",
"Check filesystem changes" : "Patikrinkite failų sistemos pakeitimus",
"Read only" : "Tik skaitymui",
"Enable previews" : "Leisti peržiūras",
"Enable sharing" : "Leisti bendrinti",
@@ -75,18 +105,58 @@ OC.L10N.register(
"Compatibility with Mac NFD encoding (slow)" : "Suderinamumas su Mac NFD koduote (lėtai)",
"External storages" : "Išorinės saugyklos",
"Status" : "Būsena",
"Restricted to" : "Apribota iki",
"Actions" : "Veiksmai",
"Checking …" : "Tikrinama  ...",
"Recheck status" : "Dar kartą patikrinkite būseną",
"Delete" : "Ištrinti",
"System provided storage" : "Sistema suteikė saugyklą",
"Saved" : "Įrašyta",
"Error while saving" : "Išsaugant įvyko klaida",
"Saved allowed backends" : "Išsaugotos leidžiamos posistemės",
"Failed to save allowed backends" : "Nepavyko išsaugoti leidžiamų posistemių",
"Advanced options for external storage mounts" : "Išplėstinės išorinių saugyklų prijungimo parinktys",
"Allow people to mount external storage" : "Leisti naudotojams prijungti išorinę saugyklą",
"External storage backends people are allowed to mount" : "Išorinių saugyklų posistemės, kurias naudotojams leidžiama prijungti",
"Error generating key pair" : "Klaida generuojant raktų porą",
"Key size" : "Rakto dydis",
"Generate keys" : "Generuoti raktus",
"Confirm" : "Patvirtinti",
"Storage credentials" : "Saugyklos kredencialai",
"To access the storage, you need to provide the authentication credentials." : "Norėdami pasiekti saugyklą, turite pateikti autentifikavimo duomenis.",
"Enter the storage login" : "Įveskite saugyklos prisijungimo vardą",
"Enter the storage password" : "Įveskite saugyklos slaptažodį",
"External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices." : "Išorinė atmintis leidžia prijungti išorines saugojimo paslaugas ir įrenginius kaip antrinius „Nextcloud“ saugojimo įrenginius.",
"You may also allow people to mount their own external storage services." : "Taip pat galite leisti naudotojams prijungti savo išorines saugyklos paslaugas.",
"The cURL support in PHP is not enabled or installed." : " cURL palaikymas naudojant PHP yra neįgalintas arba neįdiegtas.",
"The FTP support in PHP is not enabled or installed." : "FTP palaikymas naudojant PHP nėra įjungtas arba įdiegtas.",
"{module} is not installed." : "{module} modulis nėra įdiegtas",
"Dependant backends" : "Priklausomos posistemės",
"No external storage configured or you do not have the permission to configure them" : "Nėra sukonfigūruota išorinė saugykla arba neturite leidimo jos konfigūruoti",
"Add external storage" : "Pridėkite išorinę saugyklą",
"Global credentials saved" : "Globalūs prisijungimo duomenys išsaugoti",
"Could not save global credentials" : "Nepavyko išsaugoti globalių prisijungimo duomenų",
"Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globalūs prisijungimo duomenys gali būti naudojami autentifikavimui naudojant kelias išorines saugyklas, turinčias tuos pačius prisijungimo duomenis.",
"Saving …" : "Įrašoma…",
"Save" : "Įrašyti",
"Unable to update this external storage config. {statusMessage}" : "Nepavyko atnaujinti šios išorinės saugyklos konfigūracijos. {statusMessage}",
"New configuration successfully saved" : "Nauja konfigūracija sėkmingai įrašyta",
"Enter missing credentials" : "Įveskite trūkstamus prisijungimo duomenis",
"Credentials successfully set" : "Prisijungimo duomenys sėkmingai nustatyti",
"Error while setting credentials: {error}" : "Klaida nustatant prisijungimo duomenis: {error}",
"Checking storage …" : "Tikrinama saugykla  ...",
"There was an error with this external storage." : "Šioje išorinėje saugykloje įvyko klaida.",
"We were unable to check the external storage {basename}" : "Nepavyko patikrinti išorinės saugyklos {basename}",
"Examine this faulty external storage configuration" : "Patikrinkite šią klaidingą išorinės saugyklos konfigūraciją",
"Open in Files" : "Atidaryti programėlėje Files",
"External mount error" : "Išorinio prijungimo klaida",
"There was an error with this external storage. Do you want to review this mount point config in the settings page?" : "Įvyko klaida su šia išorine saugykla. Ar norite peržiūrėti šią prijungimo taško konfigūraciją nustatymų puslapyje?",
"Open settings" : "Atidarykite nustatymus",
"Ignore" : "Nepaisyti",
"List of external storage." : "Išorinių saugyklų sąrašas.",
"There is no external storage configured. You can configure them in your Personal settings." : "Nėra sukonfigūruotos išorinės saugyklos. Jas galite sukonfigūruoti asmeniniuose nustatymuose.",
"There is no external storage configured and you don't have the permission to configure them." : "Nėra sukonfigūruotos išorinės saugyklos ir jūs neturite leidimo jų konfigūruoti.",
"No external storage" : "Nėra išorinės atminties",
"Storage type" : "Saugyklos tipas",
"Unknown" : "Nežinoma",
"Scope" : "Leidimas",
@@ -94,6 +164,8 @@ OC.L10N.register(
"System" : "Sistema",
"Connected" : "Prisijungta",
"Error" : "Klaida",
"Indeterminate" : "Neapibrėžta",
"Incomplete configuration" : "Nebaigta konfigūracija",
"Unauthorized" : "Nesankcionuota",
"Network error" : "Tinklo klaida",
"Grant access" : "Suteikti prieigą",
@@ -105,17 +177,27 @@ OC.L10N.register(
"The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "cURL palaikymas yra neįjungtas arba neįdiegtas į PHP. %s prijungimas neįmanomas. Paprašykite sistemos administratoriaus pagalbos.",
"The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "FTP palaikymas yra neįjungtas arba neįdiegtas į PHP. %s prijungimas neįmanomas. Paprašykite sistemos administratoriaus pagalbos.",
"\"%1$s\" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it." : "\"%1$s\" nėra įdiegtas. %2$s prijungimas yra neįmanomas. Paprašykite savo sistemos administratoriaus, kad jį įdiegtų.",
"Checking storage …" : "Tikrinama saugykla...",
"Type to select account or group." : "Įveskite tekstą, kad pasirinktumėte paskyrą arba grupę.",
"(Group)" : "(Grupė)",
"Check for changes" : "Patikrinti ar nėra pakeitimų",
"Disconnect" : "Atsijungti",
"Unknown backend: {backendName}" : "Nežinoma posistemė: {backendName}",
"Admin defined" : "Administratorius apibrėžtas",
"Automatic status checking is disabled due to the large number of configured storages, click to check status" : "Automatinis būsenos tikrinimas išjungtas dėl didelio sukonfigūruotų saugyklų skaičiaus, spustelėkite, kad patikrintumėte būseną",
"Are you sure you want to disconnect this external storage?" : "Ar tikrai norite atjungti šią išorinę saugyklą?",
"It will make the storage unavailable in {instanceName} and will lead to a deletion of these files and folders on any sync client that is currently connected but will not delete any files and folders on the external storage itself." : "Tai padarys saugyklą nepasiekiama {instanceName} ir šie failai bei aplankai bus ištrinti bet kuriame šiuo metu prijungtame sinchronizavimo kliente, tačiau nebus ištrinti jokie failai ir aplankai pačioje išorinėje saugykloje.",
"Delete storage?" : "Ištrinti saugyklą?",
"Click to recheck the configuration" : "Spustelėkite norėdami iš naujo patikrinti konfigūraciją",
"Saving …" : "Įrašoma …",
"Failed to save global credentials" : "Nepavyko išsaugoti globalių prisijungimo duomenų",
"Failed to save global credentials: {message}" : "Nepavyko išsaugoti globalių prisijungimo duomenų: {message}",
"No external storage configured or you don't have the permission to configure them" : "Nėra sukonfigūruota jokia išorinė saugykla arba jūs neturite leidimo jų konfigūruoti",
"Open documentation" : "Atverti dokumentaciją",
"External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices. You may also allow people to mount their own external storage services." : "Išorinė saugykla leidžia prijungti išorinių saugyklų paslaugas ir įrenginius kaip antrinius „Nextcloud“ saugojimo įrenginius. Taip pat galite leisti naudotojams prijungti savo išorines saugojimo paslaugas.",
"Configuration" : "Konfigūracija",
"Available for" : "Prieinamas",
"All people" : "Visi naudotojai",
"Advanced settings" : "Išplėstiniai nustatymai"
},
"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);");
+82
View File
@@ -1,13 +1,18 @@
{ "translations": {
"You are not logged in" : "Nesate prisijungęs",
"Permission denied" : "Leidimas atmestas",
"Forbidden to manage local mounts" : "Draudžiama valdyti vietinius prijungimus",
"Storage with ID \"%d\" not found" : "Nerasta saugykla su identifikacijos numeriu \"%d\"",
"Invalid backend or authentication mechanism class" : "Netinkama programinio kodo klasė realizuoja prisijungimo mechanizmą",
"Invalid mount point" : "Neteisingas prijungimo taškas",
"Objectstore forbidden" : "Objektų saugykla yra neprieinama",
"Invalid storage backend \"%s\"" : "Neteisinga saugyklos „%s“ posistemė",
"Not permitted to use backend \"%s\"" : "Neleidžiama naudoti vidinės pusės „%s“",
"Not permitted to use authentication mechanism \"%s\"" : "Neleidžiama naudoti tapatybės nustatymo mechanizmo „%s“",
"Unsatisfied backend parameters" : " Netinkami posistemės parametrai",
"Unsatisfied authentication mechanism parameters" : "Netinkami parametrai perduoti į prisijungimo mechanizmą",
"Insufficient data: %s" : "Trūksta duomenų: %s",
"Storage with ID \"%d\" is not editable by non-admins" : "Ne administratoriai negali redaguoti saugyklos su ID „%d“ ",
"Access key" : "Prieigos raktas",
"Secret key" : "Slaptasis raktas",
"Builtin" : "Įtaisytasis",
@@ -23,18 +28,29 @@
"API key" : "API raktas",
"Global credentials" : "Visuotiniai prisijungimo duomenys",
"Log-in credentials, save in database" : "Prisijungimo duomenys, saugoti duomenų bazėje",
"Login and password" : "Prisijungimas ir slaptažodis",
"Log-in credentials, save in session" : "Prisijungimo duomenys, saugoti sesijoje",
"Global credentials, manually entered" : "Prisijungimas ir slaptažodis",
"Manually entered, store in database" : "Įvesta rankiniu būdu, saugoma duomenų bazėje",
"RSA public key" : "RSA viešasis raktas",
"Public key" : "Viešasis raktas",
"RSA private key" : "RSA privatusis raktas",
"Private key" : "Privatusis raktas",
"Kerberos default realm, defaults to \"WORKGROUP\"" : "Numatytoji „Kerberos“ sritis, numatytoji reikšmė yra „WORKGROUP“",
"Kerberos ticket Apache mode" : "Kerberos bilieto Apache režimas",
"Kerberos ticket" : "Kerberos bilietas",
"S3 Storage" : "S3 saugykla",
"Bucket" : "Amazon S3 saugykla",
"Hostname" : "Domeno vardas",
"Port" : "Prievadas",
"Proxy" : "Įgaliotasis serveris",
"Region" : "Regionas",
"Storage Class" : "Saugyklos klasė",
"Enable SSL" : "Įjungti SSL",
"Enable Path Style" : "Amazon S3 kelias",
"Legacy (v2) authentication" : "\"Legacy\" (v2) autentifikacija",
"Enable multipart copy" : "Įgalinti kelių dalių kopijavimą",
"Use presigned S3 url" : "Naudoti iš anksto pasirašytą S3 URL",
"SSE-C encryption key" : "SSE-C šifravimo raktas",
"WebDAV" : "WebDAV",
"URL" : "URL",
@@ -52,20 +68,34 @@
"SMB/CIFS" : "SMB/CIFS",
"Share" : "Bendrinti",
"Show hidden files" : "Rodyti paslėptus failus",
"Case sensitive file system" : "Didžiųjų ir mažųjų raidžių failų sistema",
"Disabling it will allow to use a case insensitive file system, but comes with a performance penalty" : "Išjungus bus galima naudoti didžiųjų ir mažųjų raidžių neįtakojamą failų sistemą, tačiau tai sumažins našumą.",
"Verify ACL access when listing files" : "Patikrinkite ACL prieigą, kai rodomi failai",
"Check the ACL's of each file or folder inside a directory to filter out items where the account has no read permissions, comes with a performance penalty" : "Patikrinkite kiekvieno failo ar aplanko, esančio kataloge, ACL, kad pašalintumėte elementus, kurių paskyra neturi skaitymo teisių, nes tai gali sumažinti našumą.",
"Timeout" : "Pasibaigė laikas",
"SMB/CIFS using OC login" : "SMB/CIFS naudojant OC prisijungimą",
"Login as share" : "Prisijungti kaip bendrinti",
"OpenStack Object Storage" : "„OpenStack“ objektų saugykla",
"Service name" : "Paslaugos vardas",
"Request timeout (seconds)" : "Prisijungimo laikas (sekundėmis)",
"External storage" : "Išorinė saugykla",
"External storage support" : "Išorinės saugyklos priežiūra",
"Adds basic external storage support" : "Pridedama pagrindinė išorinės atminties palaikymo funkcija",
"This application enables administrators to configure connections to external storage providers, such as FTP servers, S3 or SWIFT object stores, other Nextcloud servers, WebDAV servers, and more. Administration can choose which types of storage to enable and can mount these storage locations for an account, a group, or the entire system. Users will see a new folder appear in their root Nextcloud directory, which they can access and use like any other Nextcloud folder. External storage also allows people to share files stored in these external locations. In these cases, the credentials for the owner of the file are used when the recipient requests the file from external storage, thereby ensuring that the recipient can access the shared file.\n\nExternal storage can be configured using the GUI or at the command line. This second option provides the administration with more flexibility for configuring bulk external storage mounts and setting mount priorities. More information is available in the external storage GUI documentation and the external storage Configuration File documentation." : "Ši programa leidžia administratoriams konfigūruoti ryšius su išorinių saugyklų teikėjais, tokiais kaip FTP serveriai, S3 arba SWIFT objektų saugyklos, kiti „Nextcloud“ serveriai, „WebDAV“ serveriai ir kt. Administratorius gali pasirinkti, kokius saugyklų tipus įjungti, ir gali prijungti šias saugyklų vietas paskyrai, grupei arba visai sistemai. Vartotojai pamatys naują aplanką, atsirastą jų šakniniame „Nextcloud“ kataloge, kurį jie galės pasiekti ir naudoti kaip bet kurį kitą „Nextcloud“ aplanką. Išorinė saugykla taip pat leidžia naudotojams bendrinti failus, saugomus šiose išorinėse vietose. Tokiais atvejais, kai gavėjas prašo failo iš išorinės saugyklos, naudojami failo savininko prisijungimo duomenys, taip užtikrinant, kad gavėjas gali pasiekti bendrinamą failą.\n\nIšorinę saugyklą galima konfigūruoti naudojant grafinę sąsają arba komandinėje eilutėje. Ši antroji parinktis suteikia administratoriui daugiau lankstumo konfigūruojant masinį išorinių saugyklų prijungimą ir nustatant prijungimo prioritetus. Daugiau informacijos rasite išorinės saugyklos grafinės sąsajos dokumentacijoje ir išorinės saugyklos konfigūracijos failo dokumentacijoje.",
"Edit storage" : "Redaguoti saugyklą",
"Add storage" : "Pridėti saugyklą",
"Folder name" : "Aplanko pavadinimas",
"Authentication" : "Prisijungimas",
"Cancel" : "Atsisakyti",
"Edit" : "Taisyti",
"Create" : "Sukurti",
"Restrict to" : "Apsiriboti",
"Storage configuration" : "Saugyklos konfigūracija",
"Never" : "Niekada",
"Once every direct access" : "Kartą per tiesioginę peržiūrą",
"Always" : "Visada",
"Mount options" : "Prijungimo parinktys",
"Check filesystem changes" : "Patikrinkite failų sistemos pakeitimus",
"Read only" : "Tik skaitymui",
"Enable previews" : "Leisti peržiūras",
"Enable sharing" : "Leisti bendrinti",
@@ -73,18 +103,58 @@
"Compatibility with Mac NFD encoding (slow)" : "Suderinamumas su Mac NFD koduote (lėtai)",
"External storages" : "Išorinės saugyklos",
"Status" : "Būsena",
"Restricted to" : "Apribota iki",
"Actions" : "Veiksmai",
"Checking …" : "Tikrinama  ...",
"Recheck status" : "Dar kartą patikrinkite būseną",
"Delete" : "Ištrinti",
"System provided storage" : "Sistema suteikė saugyklą",
"Saved" : "Įrašyta",
"Error while saving" : "Išsaugant įvyko klaida",
"Saved allowed backends" : "Išsaugotos leidžiamos posistemės",
"Failed to save allowed backends" : "Nepavyko išsaugoti leidžiamų posistemių",
"Advanced options for external storage mounts" : "Išplėstinės išorinių saugyklų prijungimo parinktys",
"Allow people to mount external storage" : "Leisti naudotojams prijungti išorinę saugyklą",
"External storage backends people are allowed to mount" : "Išorinių saugyklų posistemės, kurias naudotojams leidžiama prijungti",
"Error generating key pair" : "Klaida generuojant raktų porą",
"Key size" : "Rakto dydis",
"Generate keys" : "Generuoti raktus",
"Confirm" : "Patvirtinti",
"Storage credentials" : "Saugyklos kredencialai",
"To access the storage, you need to provide the authentication credentials." : "Norėdami pasiekti saugyklą, turite pateikti autentifikavimo duomenis.",
"Enter the storage login" : "Įveskite saugyklos prisijungimo vardą",
"Enter the storage password" : "Įveskite saugyklos slaptažodį",
"External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices." : "Išorinė atmintis leidžia prijungti išorines saugojimo paslaugas ir įrenginius kaip antrinius „Nextcloud“ saugojimo įrenginius.",
"You may also allow people to mount their own external storage services." : "Taip pat galite leisti naudotojams prijungti savo išorines saugyklos paslaugas.",
"The cURL support in PHP is not enabled or installed." : " cURL palaikymas naudojant PHP yra neįgalintas arba neįdiegtas.",
"The FTP support in PHP is not enabled or installed." : "FTP palaikymas naudojant PHP nėra įjungtas arba įdiegtas.",
"{module} is not installed." : "{module} modulis nėra įdiegtas",
"Dependant backends" : "Priklausomos posistemės",
"No external storage configured or you do not have the permission to configure them" : "Nėra sukonfigūruota išorinė saugykla arba neturite leidimo jos konfigūruoti",
"Add external storage" : "Pridėkite išorinę saugyklą",
"Global credentials saved" : "Globalūs prisijungimo duomenys išsaugoti",
"Could not save global credentials" : "Nepavyko išsaugoti globalių prisijungimo duomenų",
"Global credentials can be used to authenticate with multiple external storages that have the same credentials." : "Globalūs prisijungimo duomenys gali būti naudojami autentifikavimui naudojant kelias išorines saugyklas, turinčias tuos pačius prisijungimo duomenis.",
"Saving …" : "Įrašoma…",
"Save" : "Įrašyti",
"Unable to update this external storage config. {statusMessage}" : "Nepavyko atnaujinti šios išorinės saugyklos konfigūracijos. {statusMessage}",
"New configuration successfully saved" : "Nauja konfigūracija sėkmingai įrašyta",
"Enter missing credentials" : "Įveskite trūkstamus prisijungimo duomenis",
"Credentials successfully set" : "Prisijungimo duomenys sėkmingai nustatyti",
"Error while setting credentials: {error}" : "Klaida nustatant prisijungimo duomenis: {error}",
"Checking storage …" : "Tikrinama saugykla  ...",
"There was an error with this external storage." : "Šioje išorinėje saugykloje įvyko klaida.",
"We were unable to check the external storage {basename}" : "Nepavyko patikrinti išorinės saugyklos {basename}",
"Examine this faulty external storage configuration" : "Patikrinkite šią klaidingą išorinės saugyklos konfigūraciją",
"Open in Files" : "Atidaryti programėlėje Files",
"External mount error" : "Išorinio prijungimo klaida",
"There was an error with this external storage. Do you want to review this mount point config in the settings page?" : "Įvyko klaida su šia išorine saugykla. Ar norite peržiūrėti šią prijungimo taško konfigūraciją nustatymų puslapyje?",
"Open settings" : "Atidarykite nustatymus",
"Ignore" : "Nepaisyti",
"List of external storage." : "Išorinių saugyklų sąrašas.",
"There is no external storage configured. You can configure them in your Personal settings." : "Nėra sukonfigūruotos išorinės saugyklos. Jas galite sukonfigūruoti asmeniniuose nustatymuose.",
"There is no external storage configured and you don't have the permission to configure them." : "Nėra sukonfigūruotos išorinės saugyklos ir jūs neturite leidimo jų konfigūruoti.",
"No external storage" : "Nėra išorinės atminties",
"Storage type" : "Saugyklos tipas",
"Unknown" : "Nežinoma",
"Scope" : "Leidimas",
@@ -92,6 +162,8 @@
"System" : "Sistema",
"Connected" : "Prisijungta",
"Error" : "Klaida",
"Indeterminate" : "Neapibrėžta",
"Incomplete configuration" : "Nebaigta konfigūracija",
"Unauthorized" : "Nesankcionuota",
"Network error" : "Tinklo klaida",
"Grant access" : "Suteikti prieigą",
@@ -103,17 +175,27 @@
"The cURL support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "cURL palaikymas yra neįjungtas arba neįdiegtas į PHP. %s prijungimas neįmanomas. Paprašykite sistemos administratoriaus pagalbos.",
"The FTP support in PHP is not enabled or installed. Mounting of %s is not possible. Please ask your system administrator to install it." : "FTP palaikymas yra neįjungtas arba neįdiegtas į PHP. %s prijungimas neįmanomas. Paprašykite sistemos administratoriaus pagalbos.",
"\"%1$s\" is not installed. Mounting of %2$s is not possible. Please ask your system administrator to install it." : "\"%1$s\" nėra įdiegtas. %2$s prijungimas yra neįmanomas. Paprašykite savo sistemos administratoriaus, kad jį įdiegtų.",
"Checking storage …" : "Tikrinama saugykla...",
"Type to select account or group." : "Įveskite tekstą, kad pasirinktumėte paskyrą arba grupę.",
"(Group)" : "(Grupė)",
"Check for changes" : "Patikrinti ar nėra pakeitimų",
"Disconnect" : "Atsijungti",
"Unknown backend: {backendName}" : "Nežinoma posistemė: {backendName}",
"Admin defined" : "Administratorius apibrėžtas",
"Automatic status checking is disabled due to the large number of configured storages, click to check status" : "Automatinis būsenos tikrinimas išjungtas dėl didelio sukonfigūruotų saugyklų skaičiaus, spustelėkite, kad patikrintumėte būseną",
"Are you sure you want to disconnect this external storage?" : "Ar tikrai norite atjungti šią išorinę saugyklą?",
"It will make the storage unavailable in {instanceName} and will lead to a deletion of these files and folders on any sync client that is currently connected but will not delete any files and folders on the external storage itself." : "Tai padarys saugyklą nepasiekiama {instanceName} ir šie failai bei aplankai bus ištrinti bet kuriame šiuo metu prijungtame sinchronizavimo kliente, tačiau nebus ištrinti jokie failai ir aplankai pačioje išorinėje saugykloje.",
"Delete storage?" : "Ištrinti saugyklą?",
"Click to recheck the configuration" : "Spustelėkite norėdami iš naujo patikrinti konfigūraciją",
"Saving …" : "Įrašoma …",
"Failed to save global credentials" : "Nepavyko išsaugoti globalių prisijungimo duomenų",
"Failed to save global credentials: {message}" : "Nepavyko išsaugoti globalių prisijungimo duomenų: {message}",
"No external storage configured or you don't have the permission to configure them" : "Nėra sukonfigūruota jokia išorinė saugykla arba jūs neturite leidimo jų konfigūruoti",
"Open documentation" : "Atverti dokumentaciją",
"External storage enables you to mount external storage services and devices as secondary Nextcloud storage devices. You may also allow people to mount their own external storage services." : "Išorinė saugykla leidžia prijungti išorinių saugyklų paslaugas ir įrenginius kaip antrinius „Nextcloud“ saugojimo įrenginius. Taip pat galite leisti naudotojams prijungti savo išorines saugojimo paslaugas.",
"Configuration" : "Konfigūracija",
"Available for" : "Prieinamas",
"All people" : "Visi naudotojai",
"Advanced settings" : "Išplėstiniai nustatymai"
},"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"
}
+3 -3
View File
@@ -403,8 +403,8 @@ OC.L10N.register(
"Back to %s" : "Zurück zu %s",
"Add to your Nextcloud" : "Zu deiner Nextcloud hinzufügen",
"Sharing %s failed because the back end does not support ScienceMesh shares" : "Freigabe von %s fehlgeschlagen, da das Backend keine ScienceMesh-Freigaben unterstützt",
"Name or email …" : "Name oder E-Mail-Adresse …",
"Name, email, or Federated Cloud ID …" : "Name, E-Mail-Adresse oder Federated-Cloud-ID …",
"Searching …" : "Suche …"
"Name or email …" : "Name oder E-Mail-Adresse …",
"Name, email, or Federated Cloud ID …" : "Name, E-Mail-Adresse oder Federated-Cloud-ID …",
"Searching …" : "Suche …"
},
"nplurals=2; plural=(n != 1);");
+3 -3
View File
@@ -401,8 +401,8 @@
"Back to %s" : "Zurück zu %s",
"Add to your Nextcloud" : "Zu deiner Nextcloud hinzufügen",
"Sharing %s failed because the back end does not support ScienceMesh shares" : "Freigabe von %s fehlgeschlagen, da das Backend keine ScienceMesh-Freigaben unterstützt",
"Name or email …" : "Name oder E-Mail-Adresse …",
"Name, email, or Federated Cloud ID …" : "Name, E-Mail-Adresse oder Federated-Cloud-ID …",
"Searching …" : "Suche …"
"Name or email …" : "Name oder E-Mail-Adresse …",
"Name, email, or Federated Cloud ID …" : "Name, E-Mail-Adresse oder Federated-Cloud-ID …",
"Searching …" : "Suche …"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
+3 -3
View File
@@ -403,8 +403,8 @@ OC.L10N.register(
"Back to %s" : "Zurück zu %s",
"Add to your Nextcloud" : "Zu Ihrer Nextcloud hinzufügen",
"Sharing %s failed because the back end does not support ScienceMesh shares" : "Freigabe von %s fehlgeschlagen, da das Backend keine ScienceMesh-Freigaben unterstützt",
"Name or email …" : "Name oder E-Mail-Adresse …",
"Name, email, or Federated Cloud ID …" : "Name, E-Mail-Adresse oder Federated-Cloud-ID …",
"Searching …" : "Suche …"
"Name or email …" : "Name oder E-Mail-Adresse …",
"Name, email, or Federated Cloud ID …" : "Name, E-Mail-Adresse oder Federated-Cloud-ID …",
"Searching …" : "Suche …"
},
"nplurals=2; plural=(n != 1);");
+3 -3
View File
@@ -401,8 +401,8 @@
"Back to %s" : "Zurück zu %s",
"Add to your Nextcloud" : "Zu Ihrer Nextcloud hinzufügen",
"Sharing %s failed because the back end does not support ScienceMesh shares" : "Freigabe von %s fehlgeschlagen, da das Backend keine ScienceMesh-Freigaben unterstützt",
"Name or email …" : "Name oder E-Mail-Adresse …",
"Name, email, or Federated Cloud ID …" : "Name, E-Mail-Adresse oder Federated-Cloud-ID …",
"Searching …" : "Suche …"
"Name or email …" : "Name oder E-Mail-Adresse …",
"Name, email, or Federated Cloud ID …" : "Name, E-Mail-Adresse oder Federated-Cloud-ID …",
"Searching …" : "Suche …"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}
+7
View File
@@ -166,7 +166,9 @@ OC.L10N.register(
"Can edit" : "Gali taisyti",
"Custom permissions" : "Tinkinti leidimai",
"Resharing is not allowed" : "Bendrinimas iš naujo yra neleidžiamas",
"Searching …" : "Ieškoma",
"No elements found." : "Nerasta jokių elementų.",
"Search everywhere" : "Ieškoti visur",
"Guest" : "Svečias",
"Group" : "Grupė",
"Email" : "El. paštas",
@@ -201,6 +203,7 @@ OC.L10N.register(
"Expiration date (enforced)" : "Galiojimo pabaigos data (nustatyta)",
"Set expiration date" : "Nustatyti galiojimo pabaigos datą",
"Hide download" : "Slėpti atsisiuntimą",
"Allow download and sync" : "Leisti atsisiųsti ir sinchronizuoti",
"Note to recipient" : "Pastaba gavėjui",
"Enter a note for the share recipient" : "Įrašykite pranešimą bendrinimo gavėjui",
"Delete share" : "Ištrinti viešinį",
@@ -214,9 +217,13 @@ OC.L10N.register(
"Expires {relativetime}" : "Galioja iki {relativetime}",
"this share just expired." : "šis viešinys ką tik nustojo galioti.",
"Shared with you by {owner}" : "{owner} pasidalino su jumis",
"Internal shares" : "Vidiniai bendrinimai",
"External shares" : "Išoriniai bendrinimai",
"Link to a file" : "Nuoroda į failą",
"Open in Files" : "Atidaryti programėlėje Files",
"Shared" : "Bendrinama",
"Shared by {ownerDisplayName}" : "Bendrina {ownerDisplayName}",
"Shared multiple times with different people" : "Dalijimasis kelis kartus su skirtingais žmonėmis",
"Shared with others" : "Bendrinama su kitais",
"People" : "Žmonės",
"Create file request" : "Sukurtį viešinį failų įkėlimui",
+7
View File
@@ -164,7 +164,9 @@
"Can edit" : "Gali taisyti",
"Custom permissions" : "Tinkinti leidimai",
"Resharing is not allowed" : "Bendrinimas iš naujo yra neleidžiamas",
"Searching …" : "Ieškoma",
"No elements found." : "Nerasta jokių elementų.",
"Search everywhere" : "Ieškoti visur",
"Guest" : "Svečias",
"Group" : "Grupė",
"Email" : "El. paštas",
@@ -199,6 +201,7 @@
"Expiration date (enforced)" : "Galiojimo pabaigos data (nustatyta)",
"Set expiration date" : "Nustatyti galiojimo pabaigos datą",
"Hide download" : "Slėpti atsisiuntimą",
"Allow download and sync" : "Leisti atsisiųsti ir sinchronizuoti",
"Note to recipient" : "Pastaba gavėjui",
"Enter a note for the share recipient" : "Įrašykite pranešimą bendrinimo gavėjui",
"Delete share" : "Ištrinti viešinį",
@@ -212,9 +215,13 @@
"Expires {relativetime}" : "Galioja iki {relativetime}",
"this share just expired." : "šis viešinys ką tik nustojo galioti.",
"Shared with you by {owner}" : "{owner} pasidalino su jumis",
"Internal shares" : "Vidiniai bendrinimai",
"External shares" : "Išoriniai bendrinimai",
"Link to a file" : "Nuoroda į failą",
"Open in Files" : "Atidaryti programėlėje Files",
"Shared" : "Bendrinama",
"Shared by {ownerDisplayName}" : "Bendrina {ownerDisplayName}",
"Shared multiple times with different people" : "Dalijimasis kelis kartus su skirtingais žmonėmis",
"Shared with others" : "Bendrinama su kitais",
"People" : "Žmonės",
"Create file request" : "Sukurtį viešinį failų įkėlimui",
@@ -24,6 +24,7 @@ class BeforeDirectFileDownloadListener implements IEventListener {
public function __construct(
private IUserSession $userSession,
private IRootFolder $rootFolder,
private ViewOnly $viewOnly,
) {
}
@@ -32,17 +33,17 @@ class BeforeDirectFileDownloadListener implements IEventListener {
return;
}
$pathsToCheck = [$event->getPath()];
// Check only for user/group shares. Don't restrict e.g. share links
$user = $this->userSession->getUser();
if ($user) {
$viewOnlyHandler = new ViewOnly(
$this->rootFolder->getUserFolder($user->getUID())
);
if (!$viewOnlyHandler->check($pathsToCheck)) {
$event->setSuccessful(false);
$event->setErrorMessage('Access to this resource or one of its sub-items has been denied.');
}
// Check only for user/group shares. Don't restrict e.g. share links
if (!$user) {
return;
}
$userFolder = $this->rootFolder->getUserFolder($user->getUID());
$node = $userFolder->get($event->getPath());
if (!$this->viewOnly->isDownloadable($node)) {
$event->setSuccessful(false);
$event->setErrorMessage('Access to this resource has been denied.');
}
}
}
@@ -14,6 +14,7 @@ use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Files\Events\BeforeZipCreatedEvent;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\IUserSession;
/**
@@ -37,28 +38,53 @@ class BeforeZipCreatedListener implements IEventListener {
$files = $event->getFiles();
if (empty($files)) {
$pathsToCheck = [$dir];
$pathsToCheck = [];
} else {
$pathsToCheck = [];
foreach ($files as $file) {
$pathsToCheck[] = $dir . '/' . $file;
$pathsToCheck[] = $file;
}
}
// Check only for user/group shares. Don't restrict e.g. share links
$user = $this->userSession->getUser();
if ($user) {
$viewOnlyHandler = new ViewOnly(
$this->rootFolder->getUserFolder($user->getUID())
);
if (!$viewOnlyHandler->check($pathsToCheck)) {
$event->setErrorMessage('Access to this resource or one of its sub-items has been denied.');
$event->setSuccessful(false);
} else {
$event->setSuccessful(true);
}
} else {
$folder = $event->getFolder();
if ($user === null && $folder === null) {
// there is no way to know if the file is downloadable or not, allow it
$event->setSuccessful(true);
return;
}
// in link-shares there may be no user, in that case we check that the share folder is downloadable
$userFolder = $user ? $this->rootFolder->getUserFolder($user->getUID()) : null;
$folderToCheck = $folder;
if ($userFolder !== null) {
// if we have a user, use their user folder
$folderToCheck = $userFolder->getPath() === $dir ? $userFolder : $userFolder->get($dir);
}
$viewOnlyHandler = new ViewOnly($folderToCheck);
$isRootDownloadable = $viewOnlyHandler->isDownloadable($folderToCheck);
if (!$isRootDownloadable) {
$message = $event->allowPartialArchive ? 'Access to this resource and its children has been denied.' : 'Access to this resource or one of its sub-items has been denied.';
$event->setErrorMessage($message);
$event->setSuccessful(false);
return;
}
if ($event->allowPartialArchive) {
$event->setSuccessful(true);
$event->addNodeFilter(fn (Node $node): array => [
$viewOnlyHandler->isDownloadable($node),
'Download is disabled for this resource'
]);
} elseif ($viewOnlyHandler->check($pathsToCheck)) {
// keep the old behaviour
$event->setSuccessful(true);
} else {
$event->setErrorMessage('Access to this resource or one of its sub-items has been denied.');
$event->setSuccessful(false);
}
}
}
+22 -10
View File
@@ -19,22 +19,30 @@ use OCP\Files\NotFoundException;
class ViewOnly {
public function __construct(
private Folder $userFolder,
private ?Folder $folder,
) {
}
/**
* @param string[] $pathsToCheck paths to check, relative to the user folder
* @param string[] $pathsToCheck paths to check, relative to the given folder
* @return bool
*/
public function check(array $pathsToCheck): bool {
if ($this->folder === null) {
throw new \LogicException('Folder is not set but this check requires it.');
}
if (empty($pathsToCheck)) {
return $this->dirRecursiveCheck($this->folder);
}
// If any of elements cannot be downloaded, prevent whole download
foreach ($pathsToCheck as $file) {
try {
$info = $this->userFolder->get($file);
$info = $this->folder->get($file);
if ($info instanceof File) {
// access to filecache is expensive in the loop
if (!$this->checkFileInfo($info)) {
if (!$this->isDownloadable($info)) {
return false;
}
} elseif ($info instanceof Folder) {
@@ -43,7 +51,7 @@ class ViewOnly {
return false;
}
}
} catch (NotFoundException $e) {
} catch (NotFoundException) {
continue;
}
}
@@ -56,14 +64,14 @@ class ViewOnly {
* @throws NotFoundException
*/
private function dirRecursiveCheck(Folder $dirInfo): bool {
if (!$this->checkFileInfo($dirInfo)) {
if (!$this->isDownloadable($dirInfo)) {
return false;
}
// If any of elements cannot be downloaded, prevent whole download
$files = $dirInfo->getDirectoryListing();
foreach ($files as $file) {
if ($file instanceof File) {
if (!$this->checkFileInfo($file)) {
if (!$this->isDownloadable($file)) {
return false;
}
} elseif ($file instanceof Folder) {
@@ -77,11 +85,15 @@ class ViewOnly {
/**
* @param Node $fileInfo
* @return bool
* @throws NotFoundException
*/
private function checkFileInfo(Node $fileInfo): bool {
public function isDownloadable(Node $fileInfo): bool {
// Restrict view-only to nodes which are shared
$storage = $fileInfo->getStorage();
try {
$storage = $fileInfo->getStorage();
} catch (NotFoundException) {
return true;
}
if (!$storage->instanceOfStorage(SharedStorage::class)) {
return true;
}
+26 -6
View File
@@ -13,6 +13,7 @@ use OCA\Files_Sharing\AppInfo\Application;
use OCA\Files_Sharing\Listener\BeforeDirectFileDownloadListener;
use OCA\Files_Sharing\Listener\BeforeZipCreatedListener;
use OCA\Files_Sharing\SharedStorage;
use OCA\Files_Sharing\ViewOnly;
use OCP\Files\Events\BeforeDirectFileDownloadEvent;
use OCP\Files\Events\BeforeZipCreatedEvent;
use OCP\Files\File;
@@ -80,6 +81,7 @@ class ApplicationTest extends TestCase {
$userFolder = $this->createMock(Folder::class);
$userFolder->method('get')->willReturn($file);
$userFolder->method('getPath')->willReturn($path);
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('test');
@@ -91,7 +93,8 @@ class ApplicationTest extends TestCase {
$event = new BeforeDirectFileDownloadEvent($path);
$listener = new BeforeDirectFileDownloadListener(
$this->userSession,
$this->rootFolder
$this->rootFolder,
new ViewOnly($userFolder),
);
$listener->handle($event);
@@ -137,6 +140,7 @@ class ApplicationTest extends TestCase {
$secureSharedStorage->method('getShare')->willReturn($secureReceiverFileShare);
$folder = $this->createMock(Folder::class);
$folder->method('getPath')->willReturn($dir);
if ($folderStorage === 'nonSharedStorage') {
$folder->method('getStorage')->willReturn($nonSharedStorage);
} elseif ($folderStorage === 'secureSharedStorage') {
@@ -160,6 +164,21 @@ class ApplicationTest extends TestCase {
$directoryListing
);
$folder->method('getDirectoryListing')->willReturn($directoryListing);
$callCount = 0;
$folder->method('get')->willReturnCallback(function (string $path) use (&$callCount, $directoryListing) {
if (isset($directoryListing[$callCount])) {
return $directoryListing[$callCount++];
}
throw new \Exception('Unknown path ' . $path);
});
}
// If the folder contains any secure-shared files, make it appear as a secure-shared folder
// so that ViewOnly::isDownloadable() will return false
$containsSecureSharedFiles = in_array('secureSharedStorage', $directoryListing);
if ($containsSecureSharedFiles && $folderStorage === 'nonSharedStorage') {
$folder->method('getStorage')->willReturn($secureSharedStorage);
}
$rootFolder = $this->createMock(Folder::class);
@@ -167,7 +186,7 @@ class ApplicationTest extends TestCase {
$rootFolder->method('getDirectoryListing')->willReturn([$folder]);
$userFolder = $this->createMock(Folder::class);
$userFolder->method('get')->willReturn($rootFolder);
$userFolder->method('get')->willReturn($folder);
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('test');
@@ -176,11 +195,12 @@ class ApplicationTest extends TestCase {
$this->rootFolder->method('getUserFolder')->with('test')->willReturn($userFolder);
// Simulate zip download of folder folder
$event = new BeforeZipCreatedEvent($dir, $files);
// Simulate zip download of folder
$event = new BeforeZipCreatedEvent($folder, $files);
$listener = new BeforeZipCreatedListener(
$this->userSession,
$this->rootFolder
$this->rootFolder,
);
$listener->handle($event);
@@ -195,7 +215,7 @@ class ApplicationTest extends TestCase {
$event = new BeforeZipCreatedEvent('/test', ['test.txt']);
$listener = new BeforeZipCreatedListener(
$this->userSession,
$this->rootFolder
$this->rootFolder,
);
$listener->handle($event);
@@ -0,0 +1,263 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Sharing\Tests\unit\Listener;
use OCA\Files_Sharing\Listener\BeforeZipCreatedListener;
use OCA\Files_Sharing\SharedStorage;
use OCP\Files\Events\BeforeZipCreatedEvent;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IAttributes;
use OCP\Share\IShare;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use Test\TestCase;
class BeforeZipCreatedListenerTest extends TestCase {
private IUserSession&MockObject $userSession;
private IRootFolder&MockObject $rootFolder;
private Folder&MockObject $userFolder;
private BeforeZipCreatedListener $listener;
protected function setUp(): void {
parent::setUp();
$this->userSession = $this->createMock(IUserSession::class);
$this->rootFolder = $this->createMock(IRootFolder::class);
$this->userFolder = $this->createMock(Folder::class);
$this->listener = new BeforeZipCreatedListener($this->userSession, $this->rootFolder);
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user');
$this->userSession->method('getUser')->willReturn($user);
$this->rootFolder->method('getUserFolder')->with('user')->willReturn($this->userFolder);
}
public static function dataHandle(): array {
$rootFromFolder = '/folder';
return [
'partial archive disabled, no filtering, 1 blocked file => should fail event' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => true,
'files' => ['blocked.txt' => false],
'filesFilter' => [],
'allowPartialArchive' => false,
'expectedSuccess' => false,
'expectedMessage' => 'Access to this resource or one of its sub-items has been denied.',
'expectedNodeList' => [],
],
'partial archive disabled, no filtering, 1 blocked 1 non-blocked file => should fail event' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => true,
'files' => ['blocked.txt' => false, 'allowed.txt' => true],
'filesFilter' => [],
'allowPartialArchive' => false,
'expectedSuccess' => false,
'expectedMessage' => 'Access to this resource or one of its sub-items has been denied.',
'expectedNodeList' => [],
],
'partial archive enabled, no filtering, 1 blocked file => should not fail event' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => true,
'files' => ['blocked.txt' => false],
'filesFilter' => [],
'allowPartialArchive' => true,
'expectedSuccess' => true,
'expectedMessage' => null,
'expectedNodeList' => ['blocked.txt' => [null, 'Download is disabled for this resource']],
],
'partial archive enabled, no filtering, 1 blocked 1 non-blocked file => should not fail event' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => true,
'files' => ['blocked.txt' => false, 'allowed.txt' => true],
'filesFilter' => [],
'allowPartialArchive' => true,
'expectedSuccess' => true,
'expectedMessage' => null,
'expectedNodeList' => ['blocked.txt' => [null, 'Download is disabled for this resource'], 'allowed.txt' => null],
],
'partial archive disabled, with filtering, 1 blocked 2 non-blocked files => should fail event' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => true,
'files' => ['blocked.txt' => false, 'allowed.txt' => true, 'notinfilter.txt' => true],
'filesFilter' => ['blocked.txt', 'allowed.txt'],
'allowPartialArchive' => false,
'expectedSuccess' => false,
'expectedMessage' => 'Access to this resource or one of its sub-items has been denied.',
'expectedNodeList' => [],
],
'partial archive enabled, with filtering, 1 blocked 2 non-blocked files => should not fail event' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => true,
'files' => ['blocked.txt' => false, 'allowed.txt' => true, 'notinfilter.txt' => true],
'filesFilter' => ['blocked.txt', 'allowed.txt'],
'allowPartialArchive' => true,
'expectedSuccess' => true,
'expectedMessage' => null,
'expectedNodeList' => ['blocked.txt' => [null, 'Download is disabled for this resource'], 'allowed.txt' => null],
],
'partial archive disabled, with filtering on non-blocked file, 1 blocked 1 non-blocked file => should succeed event' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => true,
'files' => ['allowed.txt' => true, 'notinfilter.txt' => false],
'filesFilter' => ['allowed.txt'],
'allowPartialArchive' => false,
'expectedSuccess' => true,
'expectedMessage' => null,
'expectedNodeList' => ['allowed.txt' => null],
],
'partial archive enabled, with filtering on non-blocked file, 1 downloadable 1 non-blocked file => should succeed event' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => true,
'files' => ['allowed.txt' => true, 'notinfilter.txt' => false],
'filesFilter' => ['allowed.txt'],
'allowPartialArchive' => true,
'expectedSuccess' => true,
'expectedMessage' => null,
'expectedNodeList' => ['allowed.txt' => null],
],
'partial archive disabled, root (containing) folder not downloadable, with filtering' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => false,
'files' => ['allowed.txt' => true, 'notinfilter.txt' => false],
'filesFilter' => ['allowed.txt'],
'allowPartialArchive' => false,
'expectedSuccess' => false,
'expectedMessage' => 'Access to this resource or one of its sub-items has been denied.',
'expectedNodeList' => [],
],
'partial archive enabled, root (containing) folder not downloadable, with filtering' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => false,
'files' => ['allowed.txt' => true, 'notinfilter.txt' => false],
'filesFilter' => ['allowed.txt'],
'allowPartialArchive' => true,
'expectedSuccess' => false,
'expectedMessage' => 'Access to this resource and its children has been denied.',
'expectedNodeList' => [],
],
'partial archive disabled, root (containing) folder not downloadable, no filtering' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => false,
'files' => ['allowed.txt' => true, 'notinfilter.txt' => false],
'filesFilter' => [],
'allowPartialArchive' => false,
'expectedSuccess' => false,
'expectedMessage' => 'Access to this resource or one of its sub-items has been denied.',
'expectedNodeList' => [],
],
'partial archive enabled, root (containing) folder not downloadable, no filtering' => [
'folderPath' => $rootFromFolder,
'rootDownloadable' => false,
'files' => ['allowed.txt' => true, 'notinfilter.txt' => false],
'filesFilter' => [],
'allowPartialArchive' => true,
'expectedSuccess' => false,
'expectedMessage' => 'Access to this resource and its children has been denied.',
'expectedNodeList' => [],
],
];
}
#[DataProvider(methodName: 'dataHandle')]
public function testHandle(
string $folderPath,
bool $rootDownloadable,
array $files,
array $filesFilter,
bool $allowPartialArchive,
bool $expectedSuccess,
?string $expectedMessage,
array $expectedNodeList,
): void {
$fileNodes = [];
$fileNodesByName = [];
$folderPathFromUserRoot = "/user/files{$folderPath}";
foreach ($files as $relativePath => $downloadable) {
$pathWithFolder = "{$folderPathFromUserRoot}/{$relativePath}";
$file = $this->createSharedFile($downloadable, $pathWithFolder);
$fileNodesByName[$relativePath] = $file;
$fileNodes[] = $file;
}
$folder = $this->createSharedFolder($rootDownloadable, $folderPathFromUserRoot, $fileNodes);
$this->userFolder->method('get')->willReturn($folder);
$folder->method('get')->willReturnCallback(function (string $path) use ($folderPath, $fileNodesByName, $folder) {
$path = str_replace($folderPath . '/', '', $path);
return match (true) {
isset($fileNodesByName[$path]) => $fileNodesByName[$path],
default => throw new \RuntimeException("Mock node not set for {$path}"),
};
});
$event = new BeforeZipCreatedEvent($folder, $filesFilter, $allowPartialArchive);
$this->listener->handle($event);
$this->assertEquals($expectedSuccess, $event->isSuccessful());
$this->assertSame($expectedMessage, $event->getErrorMessage());
$event->setNodesIterable($fileNodes);
$actualNodes = iterator_to_array($event->getNodes($folderPathFromUserRoot));
$this->assertCount(count($expectedNodeList), $actualNodes);
foreach ($expectedNodeList as $relativePath => $expectedValue) {
$path = "$relativePath";
if ($expectedValue === null) {
// cannot reference the node in the data provider, add it here
$node = $fileNodesByName[$path] ?? null;
$this->assertNotNull($node, 'Node mock must be present for the test to be correct.');
$expectedValue = [$node, null];
}
$this->assertEquals($expectedValue, $actualNodes[$path] ?? []);
}
}
private function createSharedFile(bool $downloadable, string $path): File&MockObject {
$file = $this->createMock(File::class);
$file->method('getStorage')->willReturn($this->createSharedStorage($downloadable));
$file->method('getPath')->willReturn($path);
$file->method('getName')->willReturn(basename($path));
return $file;
}
/**
* @param list<Node> $children
*/
private function createSharedFolder(bool $downloadable, string $path, array $children = []): Folder&MockObject {
$folder = $this->createMock(Folder::class);
$folder->method('getStorage')->willReturn($this->createSharedStorage($downloadable));
$folder->method('getDirectoryListing')->willReturn($children);
$folder->method('getPath')->willReturn($path);
$folder->method('getName')->willReturn(basename($path));
return $folder;
}
private function createSharedStorage(bool $downloadable): SharedStorage&MockObject {
$attributes = $this->createMock(IAttributes::class);
$attributes->method('getAttribute')->with('permissions', 'download')->willReturn($downloadable);
$share = $this->createMock(IShare::class);
$share->method('getAttributes')->willReturn($attributes);
$storage = $this->getMockBuilder(SharedStorage::class)
->disableOriginalConstructor()
->onlyMethods(['instanceOfStorage', 'getShare'])
->getMock();
$storage->method('instanceOfStorage')->with(SharedStorage::class)->willReturn(true);
$storage->method('getShare')->willReturn($share);
return $storage;
}
}
@@ -8,7 +8,7 @@ declare(strict_types=1);
*/
namespace OCA\Files_Trashbin\Events;
use Exception;
use OCP\Exceptions\AbortedEventException;
use OCP\Files\Events\Node\AbstractNodesEvent;
use OCP\Files\Node;
@@ -25,15 +25,10 @@ class BeforeNodeRestoredEvent extends AbstractNodesEvent {
}
/**
* @return never
* @since 28.0.0
* @deprecated 29.0.0 - use OCP\Exceptions\AbortedEventException instead
*/
public function abortOperation(?\Throwable $ex = null) {
$this->stopPropagation();
$this->run = false;
if ($ex !== null) {
throw $ex;
} else {
throw new Exception('Operation aborted');
}
throw new AbortedEventException($ex?->getMessage() ?? 'Operation aborted');
}
}
@@ -14,10 +14,9 @@ use OCA\Files_Trashbin\Trash\ITrashItem;
use OCA\Files_Trashbin\Trash\ITrashManager;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Exceptions\AbortedEventException;
use OCP\Files\Folder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IUserSession;
/**
@@ -76,7 +75,7 @@ class SyncLivePhotosListener implements IEventListener {
unset($this->pendingRestores[$peerFile->getId()]);
return;
} else {
$event->abortOperation(new NotPermittedException('Cannot restore the video part of a live photo'));
throw new AbortedEventException('Cannot restore the video part of a live photo');
}
} else {
$user = $this->userSession?->getUser();
@@ -94,14 +93,14 @@ class SyncLivePhotosListener implements IEventListener {
$trashItem = $this->getTrashItem($trashRoot, $peerFile->getInternalPath());
if ($trashItem === null) {
$event->abortOperation(new NotFoundException("Couldn't find peer file in trashbin"));
throw new AbortedEventException('Could not find peer file in trashbin');
}
$this->pendingRestores[$sourceFile->getId()] = true;
try {
$this->trashManager->restoreItem($trashItem);
} catch (\Throwable $ex) {
$event->abortOperation($ex);
throw new AbortedEventException($ex->getMessage());
}
}
}
@@ -154,6 +154,10 @@ class TrashItem implements ITrashItem {
return $this->fileInfo->getUploadTime();
}
public function getLastActivity(): int {
return $this->fileInfo->getLastActivity();
}
public function getParentId(): int {
return $this->fileInfo->getParentId();
}
+6 -1
View File
@@ -29,6 +29,7 @@ use OCP\Config\IUserConfig;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\EventDispatcher\IEventListener;
use OCP\Exceptions\AbortedEventException;
use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
use OCP\Files\File;
use OCP\Files\Folder;
@@ -515,7 +516,11 @@ class Trashbin implements IEventListener {
$run = true;
$event = new BeforeNodeRestoredEvent($sourceNode, $targetNode, $run);
$dispatcher = Server::get(IEventDispatcher::class);
$dispatcher->dispatchTyped($event);
try {
$dispatcher->dispatchTyped($event);
} catch (AbortedEventException) {
$run = false;
}
if (!$run) {
return false;
+1
View File
@@ -2,6 +2,7 @@ OC.L10N.register(
"profile",
{
"Profile" : "Profilis",
"Searching …" : "Ieškoma",
"Not found" : "Nerasta",
"You have not added any info yet" : "Jūs kol kas nesate pridėję jokios informacijos",
"{user} has not added any info yet" : "Naudotojas {user} kol kas nėra pridėjęs jokios informacijos",
+1
View File
@@ -1,5 +1,6 @@
{ "translations": {
"Profile" : "Profilis",
"Searching …" : "Ieškoma",
"Not found" : "Nerasta",
"You have not added any info yet" : "Jūs kol kas nesate pridėję jokios informacijos",
"{user} has not added any info yet" : "Naudotojas {user} kol kas nėra pridėjęs jokios informacijos",
+3 -3
View File
@@ -775,12 +775,12 @@ OC.L10N.register(
"Resend welcome email" : "Willkommens-E-Mail erneut senden",
"In case of lost device or exiting the organization, this can remotely wipe the {productName} data from all devices associated with {userid}. Only works if the devices are connected to the internet." : "Im Falle des Verlusts des Gerätes oder des Verlassens der Organisation können mit dieser Funktion sämtliche {productName}-Daten von allen Geräten, die mit {userid} verbunden sind, gelöscht werden. Funktioniert nur, wenn das Gerät mit dem Internet verbunden ist.",
"Remote wipe of devices" : "Fernlöschung von Geräten",
"Wipe {userid}'s devices" : "Lösche {userid}'s Geräte",
"Wiped {userid}'s devices" : "{userid}'s Geräte bereinigt",
"Wipe {userid}'s devices" : "Lösche {userid}s Geräte",
"Wiped {userid}'s devices" : "{userid}s Geräte bereinigt",
"Failed to load groups with details" : "Gruppen mit Details konnten nicht geladen werden",
"Failed to load sub admin groups with details" : "Unteradministrations-Gruppen mit Details konnten nicht geladen werden",
"Failed to update line manager" : "Manager konnte nicht aktualisiert werden",
"Fully delete {userid}'s account including all their personal files, app data, etc." : "Das Konto von {userid} vollständig löschen inklusive aller persönlichen Dateien, App-Daten, usw.",
"Fully delete {userid}'s account including all their personal files, app data, etc." : "Das Konto von {userid} vollständig löschen, inklusive aller persönlichen Dateien, App-Daten, usw.",
"Account deletion" : "Kontenlöschung",
"Delete {userid}'s account" : "Konto von {userid} löschen",
"Display name was successfully changed" : "Der Anzeigename wurde geändert",
+3 -3
View File
@@ -773,12 +773,12 @@
"Resend welcome email" : "Willkommens-E-Mail erneut senden",
"In case of lost device or exiting the organization, this can remotely wipe the {productName} data from all devices associated with {userid}. Only works if the devices are connected to the internet." : "Im Falle des Verlusts des Gerätes oder des Verlassens der Organisation können mit dieser Funktion sämtliche {productName}-Daten von allen Geräten, die mit {userid} verbunden sind, gelöscht werden. Funktioniert nur, wenn das Gerät mit dem Internet verbunden ist.",
"Remote wipe of devices" : "Fernlöschung von Geräten",
"Wipe {userid}'s devices" : "Lösche {userid}'s Geräte",
"Wiped {userid}'s devices" : "{userid}'s Geräte bereinigt",
"Wipe {userid}'s devices" : "Lösche {userid}s Geräte",
"Wiped {userid}'s devices" : "{userid}s Geräte bereinigt",
"Failed to load groups with details" : "Gruppen mit Details konnten nicht geladen werden",
"Failed to load sub admin groups with details" : "Unteradministrations-Gruppen mit Details konnten nicht geladen werden",
"Failed to update line manager" : "Manager konnte nicht aktualisiert werden",
"Fully delete {userid}'s account including all their personal files, app data, etc." : "Das Konto von {userid} vollständig löschen inklusive aller persönlichen Dateien, App-Daten, usw.",
"Fully delete {userid}'s account including all their personal files, app data, etc." : "Das Konto von {userid} vollständig löschen, inklusive aller persönlichen Dateien, App-Daten, usw.",
"Account deletion" : "Kontenlöschung",
"Delete {userid}'s account" : "Konto von {userid} löschen",
"Display name was successfully changed" : "Der Anzeigename wurde geändert",
+1 -1
View File
@@ -780,7 +780,7 @@ OC.L10N.register(
"Failed to load groups with details" : "Gruppen mit Details konnten nicht geladen werden",
"Failed to load sub admin groups with details" : "Unteradministrations-Gruppen mit Details konnten nicht geladen werden",
"Failed to update line manager" : "Manager konnte nicht aktualisiert werden",
"Fully delete {userid}'s account including all their personal files, app data, etc." : "Lösche {userid}s Konto vollständig inklusive aller persönlichen Dateien, App-Daten, usw.",
"Fully delete {userid}'s account including all their personal files, app data, etc." : "Das Konto von {userid} vollständig löschen, inklusive aller persönlichen Dateien, App-Daten, usw.",
"Account deletion" : "Kontenlöschung",
"Delete {userid}'s account" : "Konto von {userid} löschen",
"Display name was successfully changed" : "Der Anzeigename wurde geändert",
+1 -1
View File
@@ -778,7 +778,7 @@
"Failed to load groups with details" : "Gruppen mit Details konnten nicht geladen werden",
"Failed to load sub admin groups with details" : "Unteradministrations-Gruppen mit Details konnten nicht geladen werden",
"Failed to update line manager" : "Manager konnte nicht aktualisiert werden",
"Fully delete {userid}'s account including all their personal files, app data, etc." : "Lösche {userid}s Konto vollständig inklusive aller persönlichen Dateien, App-Daten, usw.",
"Fully delete {userid}'s account including all their personal files, app data, etc." : "Das Konto von {userid} vollständig löschen, inklusive aller persönlichen Dateien, App-Daten, usw.",
"Account deletion" : "Kontenlöschung",
"Delete {userid}'s account" : "Konto von {userid} löschen",
"Display name was successfully changed" : "Der Anzeigename wurde geändert",
+3
View File
@@ -327,6 +327,7 @@ OC.L10N.register(
"Language" : "Kalba",
"Set default language" : "Nustatyti numatytąją kalbą",
"Add new account" : "Pridėti naują paskyrą",
"Total rows summary" : "Bendras eilučių skaičius",
"Avatar" : "Avataras",
"Account name" : "Paskyros pavadinimas",
"Group admin for" : "Grupės administratorius",
@@ -408,6 +409,8 @@ OC.L10N.register(
"Organisation" : "Organizacija",
"Phone number" : "Telefono numeris",
"Role" : "Vaidmuo",
"X (formerly Twitter)" : "X (anksčiau „Twitter“)",
"Bluesky" : "\"Bluesky\"",
"Website" : "Svetainė",
"Profile visibility" : "Profilio matomumas",
"Locale" : "Lokalė",
+3
View File
@@ -325,6 +325,7 @@
"Language" : "Kalba",
"Set default language" : "Nustatyti numatytąją kalbą",
"Add new account" : "Pridėti naują paskyrą",
"Total rows summary" : "Bendras eilučių skaičius",
"Avatar" : "Avataras",
"Account name" : "Paskyros pavadinimas",
"Group admin for" : "Grupės administratorius",
@@ -406,6 +407,8 @@
"Organisation" : "Organizacija",
"Phone number" : "Telefono numeris",
"Role" : "Vaidmuo",
"X (formerly Twitter)" : "X (anksčiau „Twitter“)",
"Bluesky" : "\"Bluesky\"",
"Website" : "Svetainė",
"Profile visibility" : "Profilio matomumas",
"Locale" : "Lokalė",
@@ -10,23 +10,28 @@ namespace OCA\Settings\Controller;
use OCA\Settings\Settings\Admin\ArtificialIntelligence;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
use OCP\AppFramework\Http\DataResponse;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IAppConfig;
use OCP\IRequest;
use OCP\Log\Audit\CriticalActionPerformedEvent;
class AISettingsController extends Controller {
public function __construct(
$appName,
IRequest $request,
private string $userId,
private IAppConfig $appConfig,
private IEventDispatcher $eventDispatcher,
) {
parent::__construct($appName, $request);
}
/**
* Sets the email settings
* Sets the AI settings
*
* @param array $settings
* @return DataResponse
@@ -38,7 +43,23 @@ class AISettingsController extends Controller {
if (!isset($settings[$key])) {
continue;
}
$this->appConfig->setValueString('core', $key, json_encode($settings[$key]), lazy: in_array($key, \OC\TaskProcessing\Manager::LAZY_CONFIG_KEYS, true));
try {
$settings[$key] = json_encode($settings[$key], flags: \JSON_THROW_ON_ERROR);
} catch (\JsonException) {
return new DataResponse(['error' => "Setting value for '$key' must be JSON-compatible"], Http::STATUS_BAD_REQUEST);
}
}
foreach ($keys as $key) {
if (!isset($settings[$key])) {
continue;
}
$changed = $this->appConfig->setValueString('core', $key, $settings[$key], lazy: in_array($key, \OC\TaskProcessing\Manager::LAZY_CONFIG_KEYS, true));
if ($changed) {
$this->eventDispatcher->dispatchTyped(new CriticalActionPerformedEvent(
'AI configuration was changed by user %s: %s was set to %s',
[$this->userId, $key, $settings[$key]]
));
}
}
return new DataResponse();
+1
View File
@@ -14,6 +14,7 @@ OC.L10N.register(
"Password to access {file} was sent to {email}" : "Slaptažodis, skirtas prieigai prie {file}, buvo išsiųstas į {email}",
"Password to access {file} was sent to you" : "Jums buvo išsiųstas slaptažodis, skirtas prieigai prie {file}",
"Share by mail" : "Bendrinimas el. paštu",
"Sharing %1$s failed, because this item is already shared with the account %2$s" : "%1$s bendrinimas nepavyko, nes šis elementas jau bendrinamas su %2$s paskyra",
"Failed to send share by email" : "Nepavyko pasidalinti el. paštu",
"Note:" : "Pastaba:",
"Open %s" : "Atverti %s",
+1
View File
@@ -12,6 +12,7 @@
"Password to access {file} was sent to {email}" : "Slaptažodis, skirtas prieigai prie {file}, buvo išsiųstas į {email}",
"Password to access {file} was sent to you" : "Jums buvo išsiųstas slaptažodis, skirtas prieigai prie {file}",
"Share by mail" : "Bendrinimas el. paštu",
"Sharing %1$s failed, because this item is already shared with the account %2$s" : "%1$s bendrinimas nepavyko, nes šis elementas jau bendrinamas su %2$s paskyra",
"Failed to send share by email" : "Nepavyko pasidalinti el. paštu",
"Note:" : "Pastaba:",
"Open %s" : "Atverti %s",
+1 -1
View File
@@ -40,7 +40,7 @@ OC.L10N.register(
"<strong>System tags</strong> for a file have been modified" : "<strong>System-Schlagwort</strong> für eine Datei wurde geändert",
"Files" : "Dateien",
"Tags" : "Schlagworte",
"All tagged %s …" : "Alle Schlagwort %s hinzugefügt …",
"All tagged %s …" : "Alle Schlagworte %s hinzugefügt …",
"tagged %s" : "Schlagwort %s hinzugefügt",
"Collaborative tags" : "Kollaborative Schlagworte",
"Collaborative tagging functionality which shares tags among people." : "Gemeinschaftliche Schlagwort-Funktionalität, welche Schlagworte unter den Benutzern teilt.",
+1 -1
View File
@@ -38,7 +38,7 @@
"<strong>System tags</strong> for a file have been modified" : "<strong>System-Schlagwort</strong> für eine Datei wurde geändert",
"Files" : "Dateien",
"Tags" : "Schlagworte",
"All tagged %s …" : "Alle Schlagwort %s hinzugefügt …",
"All tagged %s …" : "Alle Schlagworte %s hinzugefügt …",
"tagged %s" : "Schlagwort %s hinzugefügt",
"Collaborative tags" : "Kollaborative Schlagworte",
"Collaborative tagging functionality which shares tags among people." : "Gemeinschaftliche Schlagwort-Funktionalität, welche Schlagworte unter den Benutzern teilt.",
+1
View File
@@ -69,6 +69,7 @@ OC.L10N.register(
"Search or create collaborative tags" : "Ieškoti ar sukurti bendradarbiavimo žymas",
"System tag management" : "Sistemos žymų valdymas",
"Collaborative tags are available for all users. Restricted tags are visible to users but cannot be assigned by them. Invisible tags are for internal use, since users cannot see or assign them." : "Bendradarbiavimo žymos yra prieinamos visiems naudotojams. Apribotos žymos yra matomos naudotojams, tačiau naudotojai negali jų priskirinėti. Nematomos žymos yra vidiniam naudojimui, nes naudotojai negali jų nei matyti, nei priskirinėti.",
"Open in Files" : "Atidaryti programėlėje Files",
"No tags found" : "Nerasta jokių žymų",
"Tags you have created will show up here." : "Čia bus rodomos jūsų sukurtos žymos.",
"Failed to load tag" : "Nepavyko įkelti žymos",
+1
View File
@@ -67,6 +67,7 @@
"Search or create collaborative tags" : "Ieškoti ar sukurti bendradarbiavimo žymas",
"System tag management" : "Sistemos žymų valdymas",
"Collaborative tags are available for all users. Restricted tags are visible to users but cannot be assigned by them. Invisible tags are for internal use, since users cannot see or assign them." : "Bendradarbiavimo žymos yra prieinamos visiems naudotojams. Apribotos žymos yra matomos naudotojams, tačiau naudotojai negali jų priskirinėti. Nematomos žymos yra vidiniam naudojimui, nes naudotojai negali jų nei matyti, nei priskirinėti.",
"Open in Files" : "Atidaryti programėlėje Files",
"No tags found" : "Nerasta jokių žymų",
"Tags you have created will show up here." : "Čia bus rodomos jūsų sukurtos žymos.",
"Failed to load tag" : "Nepavyko įkelti žymos",
+26 -10
View File
@@ -8,8 +8,10 @@ namespace OCA\Theming;
use OCA\Theming\AppInfo\Application;
use OCA\Theming\Service\BackgroundService;
use OCA\Theming\Service\ThemesService;
use OCP\Capabilities\IPublicCapability;
use OCP\IConfig;
use OCP\Config\IUserConfig;
use OCP\IAppConfig;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
@@ -21,18 +23,14 @@ use OCP\IUserSession;
*/
class Capabilities implements IPublicCapability {
/**
* @param ThemingDefaults $theming
* @param Util $util
* @param IURLGenerator $url
* @param IConfig $config
*/
public function __construct(
protected ThemingDefaults $theming,
protected Util $util,
protected IURLGenerator $url,
protected IConfig $config,
protected IAppConfig $appConfig,
protected IUserConfig $userConfig,
protected IUserSession $userSession,
protected ThemesService $themesService,
) {
}
@@ -44,6 +42,8 @@ class Capabilities implements IPublicCapability {
* name: string,
* productName: string,
* url: string,
* imprintUrl: string,
* privacyUrl: string,
* slogan: string,
* color: string,
* color-text: string,
@@ -57,6 +57,13 @@ class Capabilities implements IPublicCapability {
* background-default: bool,
* logoheader: string,
* favicon: string,
* primaryColor: string,
* backgroundColor: string,
* defaultPrimaryColor: string,
* defaultBackgroundColor: string,
* inverted: bool,
* cacheBuster: string,
* enabledThemes: list<string>,
* },
* }
*/
@@ -64,7 +71,7 @@ class Capabilities implements IPublicCapability {
$color = $this->theming->getDefaultColorPrimary();
$colorText = $this->util->invertTextColor($color) ? '#000000' : '#ffffff';
$backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime', '');
$backgroundLogo = $this->appConfig->getValueString('theming', 'backgroundMime', '');
$backgroundColor = $this->theming->getColorBackground();
$backgroundText = $this->theming->getTextColorBackground();
$backgroundPlain = $backgroundLogo === 'backgroundColor' || ($backgroundLogo === '' && $backgroundColor !== BackgroundService::DEFAULT_COLOR);
@@ -80,7 +87,7 @@ class Capabilities implements IPublicCapability {
$color = $this->theming->getColorPrimary();
$colorText = $this->theming->getTextColorPrimary();
$backgroundImage = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT);
$backgroundImage = $this->userConfig->getValueString($user->getUID(), Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT);
if ($backgroundImage === BackgroundService::BACKGROUND_CUSTOM) {
$backgroundPlain = false;
$background = $this->url->linkToRouteAbsolute('theming.userTheme.getBackground');
@@ -98,6 +105,8 @@ class Capabilities implements IPublicCapability {
'name' => $this->theming->getName(),
'productName' => $this->theming->getProductName(),
'url' => $this->theming->getBaseUrl(),
'imprintUrl' => $this->theming->getImprintUrl(),
'privacyUrl' => $this->theming->getPrivacyUrl(),
'slogan' => $this->theming->getSlogan(),
'color' => $color,
'color-text' => $colorText,
@@ -111,6 +120,13 @@ class Capabilities implements IPublicCapability {
'background-default' => !$this->util->isBackgroundThemed(),
'logoheader' => $this->url->getAbsoluteURL($this->theming->getLogo()),
'favicon' => $this->url->getAbsoluteURL($this->theming->getLogo()),
'primaryColor' => $color,
'backgroundColor' => $backgroundColor,
'defaultPrimaryColor' => $this->theming->getDefaultColorPrimary(),
'defaultBackgroundColor' => $this->theming->getDefaultColorBackground(),
'inverted' => $this->util->invertTextColor($color),
'cacheBuster' => $this->util->getCacheBuster(),
'enabledThemes' => $this->themesService->getEnabledThemes(),
],
];
}
+3 -4
View File
@@ -11,6 +11,9 @@ namespace OCA\Theming\Service;
use OCA\Theming\ThemingDefaults;
use OCA\Theming\Util;
/**
* @deprecated since Nextcloud 34 all properties are now exposed via Capabilities
*/
class JSDataService implements \JsonSerializable {
public function __construct(
@@ -40,10 +43,6 @@ class JSDataService implements \JsonSerializable {
'cacheBuster' => $this->util->getCacheBuster(),
'enabledThemes' => $this->themesService->getEnabledThemes(),
// deprecated use primaryColor
'color' => $this->themingDefaults->getColorPrimary(),
'' => 'color is deprecated since Nextcloud 29, use primaryColor instead'
];
}
}
+3 -2
View File
@@ -151,9 +151,9 @@ class ThemesService {
/**
* Get the list of all enabled themes IDs for the current user.
*
* @return string[]
* @return list<string>
*/
public function getEnabledThemes(): array {
public function getEnabledThemes() {
$enforcedTheme = $this->config->getSystemValueString('enforce_theme', '');
$user = $this->userSession->getUser();
if ($user === null) {
@@ -163,6 +163,7 @@ class ThemesService {
return [];
}
/** @var list<string> */
$enabledThemes = json_decode($this->config->getUserValue($user->getUID(), Application::APP_ID, 'enabled-themes', '["default"]'));
if ($enforcedTheme !== '') {
return array_merge([$enforcedTheme], $enabledThemes);
+1 -1
View File
@@ -84,7 +84,7 @@ class ThemingDefaults extends \OC_Defaults {
return strip_tags($this->appConfig->getAppValueString(ConfigLexicon::INSTANCE_NAME, $this->entity));
}
public function getProductName() {
public function getProductName(): string {
return strip_tags($this->appConfig->getAppValueString(ConfigLexicon::PRODUCT_NAME, $this->productName));
}
+40 -1
View File
@@ -81,6 +81,8 @@
"name",
"productName",
"url",
"imprintUrl",
"privacyUrl",
"slogan",
"color",
"color-text",
@@ -93,7 +95,14 @@
"background-plain",
"background-default",
"logoheader",
"favicon"
"favicon",
"primaryColor",
"backgroundColor",
"defaultPrimaryColor",
"defaultBackgroundColor",
"inverted",
"cacheBuster",
"enabledThemes"
],
"properties": {
"name": {
@@ -105,6 +114,12 @@
"url": {
"type": "string"
},
"imprintUrl": {
"type": "string"
},
"privacyUrl": {
"type": "string"
},
"slogan": {
"type": "string"
},
@@ -143,6 +158,30 @@
},
"favicon": {
"type": "string"
},
"primaryColor": {
"type": "string"
},
"backgroundColor": {
"type": "string"
},
"defaultPrimaryColor": {
"type": "string"
},
"defaultBackgroundColor": {
"type": "string"
},
"inverted": {
"type": "boolean"
},
"cacheBuster": {
"type": "string"
},
"enabledThemes": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
+159 -14
View File
@@ -9,12 +9,17 @@ namespace OCA\Theming\Tests;
use OCA\Theming\Capabilities;
use OCA\Theming\ImageManager;
use OCA\Theming\Service\BackgroundService;
use OCA\Theming\Service\ThemesService;
use OCA\Theming\ThemingDefaults;
use OCA\Theming\Util;
use OCP\App\IAppManager;
use OCP\Config\IUserConfig;
use OCP\Files\IAppData;
use OCP\IAppConfig;
use OCP\IConfig;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserSession;
use OCP\ServerVersion;
use PHPUnit\Framework\MockObject\MockObject;
@@ -28,9 +33,11 @@ use Test\TestCase;
class CapabilitiesTest extends TestCase {
protected ThemingDefaults&MockObject $theming;
protected IURLGenerator&MockObject $url;
protected IConfig&MockObject $config;
protected IAppConfig&MockObject $appConfig;
protected IUserConfig&MockObject $userConfig;
protected Util&MockObject $util;
protected IUserSession $userSession;
protected IUserSession&MockObject $userSession;
protected ThemesService&MockObject $themesService;
protected Capabilities $capabilities;
protected function setUp(): void {
@@ -38,24 +45,30 @@ class CapabilitiesTest extends TestCase {
$this->theming = $this->createMock(ThemingDefaults::class);
$this->url = $this->createMock(IURLGenerator::class);
$this->config = $this->createMock(IConfig::class);
$this->appConfig = $this->createMock(IAppConfig::class);
$this->userConfig = $this->createMock(IUserConfig::class);
$this->util = $this->createMock(Util::class);
$this->userSession = $this->createMock(IUserSession::class);
$this->themesService = $this->createMock(ThemesService::class);
$this->capabilities = new Capabilities(
$this->theming,
$this->util,
$this->url,
$this->config,
$this->appConfig,
$this->userConfig,
$this->userSession,
$this->themesService,
);
}
public static function dataGetCapabilities(): array {
return [
['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', '#fff', '#000', 'http://absolute/', true, [
['name', 'url', 'slogan', '#FFFFFF', '#000000', 'logo', 'background', '#fff', '#000', 'http://absolute/', true, 'https://imprint.example.com/', 'https://privacy.example.com/', '#0082c9', [
'name' => 'name',
'productName' => 'name',
'url' => 'url',
'imprintUrl' => 'https://imprint.example.com/',
'privacyUrl' => 'https://privacy.example.com/',
'slogan' => 'slogan',
'color' => '#FFFFFF',
'color-text' => '#000000',
@@ -69,11 +82,20 @@ class CapabilitiesTest extends TestCase {
'background-default' => false,
'logoheader' => 'http://absolute/logo',
'favicon' => 'http://absolute/logo',
'primaryColor' => '#FFFFFF',
'backgroundColor' => '#fff',
'defaultPrimaryColor' => '#FFFFFF',
'defaultBackgroundColor' => '#0082c9',
'inverted' => true,
'cacheBuster' => 'v1',
'enabledThemes' => ['default'],
]],
['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', '#fff', '#000', 'http://localhost/', false, [
['name1', 'url2', 'slogan3', '#01e4a0', '#ffffff', 'logo5', 'background6', '#fff', '#000', 'http://localhost/', false, '', '', '#0082c9', [
'name' => 'name1',
'productName' => 'name1',
'url' => 'url2',
'imprintUrl' => '',
'privacyUrl' => '',
'slogan' => 'slogan3',
'color' => '#01e4a0',
'color-text' => '#ffffff',
@@ -87,11 +109,20 @@ class CapabilitiesTest extends TestCase {
'background-default' => true,
'logoheader' => 'http://localhost/logo5',
'favicon' => 'http://localhost/logo5',
'primaryColor' => '#01e4a0',
'backgroundColor' => '#fff',
'defaultPrimaryColor' => '#01e4a0',
'defaultBackgroundColor' => '#0082c9',
'inverted' => false,
'cacheBuster' => 'v1',
'enabledThemes' => ['default'],
]],
['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', true, [
['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', true, '', '', '#0082c9', [
'name' => 'name1',
'productName' => 'name1',
'url' => 'url2',
'imprintUrl' => '',
'privacyUrl' => '',
'slogan' => 'slogan3',
'color' => '#000000',
'color-text' => '#ffffff',
@@ -105,11 +136,20 @@ class CapabilitiesTest extends TestCase {
'background-default' => false,
'logoheader' => 'http://localhost/logo5',
'favicon' => 'http://localhost/logo5',
'primaryColor' => '#000000',
'backgroundColor' => '#000000',
'defaultPrimaryColor' => '#000000',
'defaultBackgroundColor' => '#0082c9',
'inverted' => false,
'cacheBuster' => 'v1',
'enabledThemes' => ['default'],
]],
['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', false, [
['name1', 'url2', 'slogan3', '#000000', '#ffffff', 'logo5', 'backgroundColor', '#000000', '#ffffff', 'http://localhost/', false, '', '', '#0082c9', [
'name' => 'name1',
'productName' => 'name1',
'url' => 'url2',
'imprintUrl' => '',
'privacyUrl' => '',
'slogan' => 'slogan3',
'color' => '#000000',
'color-text' => '#ffffff',
@@ -123,17 +163,25 @@ class CapabilitiesTest extends TestCase {
'background-default' => true,
'logoheader' => 'http://localhost/logo5',
'favicon' => 'http://localhost/logo5',
'primaryColor' => '#000000',
'backgroundColor' => '#000000',
'defaultPrimaryColor' => '#000000',
'defaultBackgroundColor' => '#0082c9',
'inverted' => false,
'cacheBuster' => 'v1',
'enabledThemes' => ['default'],
]],
];
}
/**
* @param non-empty-array<string, string> $expected
* @param array<string, mixed> $expected
*/
#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataGetCapabilities')]
public function testGetCapabilities(string $name, string $url, string $slogan, string $color, string $textColor, string $logo, string $background, string $backgroundColor, string $backgroundTextColor, string $baseUrl, bool $backgroundThemed, array $expected): void {
$this->config->expects($this->once())
->method('getAppValue')
public function testGetCapabilities(string $name, string $url, string $slogan, string $color, string $textColor, string $logo, string $background, string $backgroundColor, string $backgroundTextColor, string $baseUrl, bool $backgroundThemed, string $imprintUrl, string $privacyUrl, string $defaultBackgroundColor, array $expected): void {
$this->appConfig->expects($this->once())
->method('getValueString')
->with('theming', 'backgroundMime', '')
->willReturn($background);
$this->theming->expects($this->once())
->method('getName')
@@ -144,6 +192,12 @@ class CapabilitiesTest extends TestCase {
$this->theming->expects($this->once())
->method('getBaseUrl')
->willReturn($url);
$this->theming->expects($this->once())
->method('getImprintUrl')
->willReturn($imprintUrl);
$this->theming->expects($this->once())
->method('getPrivacyUrl')
->willReturn($privacyUrl);
$this->theming->expects($this->once())
->method('getSlogan')
->willReturn($slogan);
@@ -153,6 +207,9 @@ class CapabilitiesTest extends TestCase {
$this->theming->expects($this->once())
->method('getTextColorBackground')
->willReturn($backgroundTextColor);
$this->theming->expects($this->once())
->method('getDefaultColorBackground')
->willReturn($defaultBackgroundColor);
$this->theming->expects($this->atLeast(1))
->method('getDefaultColorPrimary')
->willReturn($color);
@@ -160,20 +217,25 @@ class CapabilitiesTest extends TestCase {
->method('getLogo')
->willReturn($logo);
$util = new Util($this->createMock(ServerVersion::class), $this->config, $this->createMock(IAppManager::class), $this->createMock(IAppData::class), $this->createMock(ImageManager::class));
$util = new Util($this->createMock(ServerVersion::class), $this->createMock(IConfig::class), $this->createMock(IAppManager::class), $this->createMock(IAppData::class), $this->createMock(ImageManager::class));
$this->util->expects($this->exactly(3))
->method('elementColor')
->with($color)
->willReturnCallback(static function (string $color, ?bool $brightBackground = null) use ($util) {
return $util->elementColor($color, $brightBackground);
});
$this->util->expects($this->any())
->method('invertTextColor')
->willReturnCallback(fn () => $textColor === '#000000');
$this->util->expects($this->once())
->method('isBackgroundThemed')
->willReturn($backgroundThemed);
$this->util->expects($this->once())
->method('getCacheBuster')
->willReturn('v1');
$this->themesService->expects($this->once())
->method('getEnabledThemes')
->willReturn(['default']);
if ($background !== 'backgroundColor') {
$this->theming->expects($this->once())
@@ -194,4 +256,87 @@ class CapabilitiesTest extends TestCase {
$this->assertEquals(['theming' => $expected], $this->capabilities->getCapabilities());
}
public static function dataGetCapabilitiesWithUser(): array {
return [
'default background' => [
BackgroundService::BACKGROUND_DEFAULT,
false,
'http://localhost/background',
],
'custom background' => [
BackgroundService::BACKGROUND_CUSTOM,
false,
'http://localhost/route',
],
'shipped background' => [
'jo-myoung-hee-fluid.webp',
false,
'http://localhost/img',
],
'solid color background' => [
'solid',
true,
BackgroundService::DEFAULT_COLOR,
],
];
}
#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataGetCapabilitiesWithUser')]
public function testGetCapabilitiesWithUser(string $backgroundImage, bool $expectedBackgroundPlain, string $expectedBackground): void {
$user = $this->createMock(IUser::class);
$user->method('getUID')->willReturn('user1');
$this->userSession->method('getUser')->willReturn($user);
$userColor = '#00679e';
$defaultColor = '#0082c9';
$this->theming->method('getDefaultColorPrimary')->willReturn($defaultColor);
$this->theming->method('getColorPrimary')->willReturn($userColor);
$this->theming->method('getTextColorPrimary')->willReturn('#ffffff');
$this->theming->method('getName')->willReturn('Name');
$this->theming->method('getProductName')->willReturn('Name');
$this->theming->method('getBaseUrl')->willReturn('http://example.com/');
$this->theming->method('getImprintUrl')->willReturn('');
$this->theming->method('getPrivacyUrl')->willReturn('');
$this->theming->method('getSlogan')->willReturn('Slogan');
$this->theming->method('getColorBackground')->willReturn(BackgroundService::DEFAULT_COLOR);
$this->theming->method('getTextColorBackground')->willReturn('#ffffff');
$this->theming->method('getDefaultColorBackground')->willReturn('#0082c9');
$this->theming->method('getLogo')->willReturn('/logo');
$this->theming->method('getBackground')->willReturn('/background');
$this->appConfig->method('getValueString')->willReturn('');
$this->userConfig->method('getValueString')->willReturn($backgroundImage);
$this->util->method('invertTextColor')->willReturn(false);
$this->util->method('elementColor')->willReturn($userColor);
$this->util->method('isBackgroundThemed')->willReturn(false);
$this->util->method('getCacheBuster')->willReturn('v1');
$this->themesService->method('getEnabledThemes')->willReturn(['default']);
$this->url->method('getAbsoluteURL')->willReturnCallback(fn (string $url) => 'http://localhost' . $url);
$this->url->method('linkToRouteAbsolute')->willReturn('http://localhost/route');
$this->url->method('linkTo')->willReturn('http://localhost/img');
$result = $this->capabilities->getCapabilities();
$theming = $result['theming'];
// For logged-in users, color/primaryColor reflect getColorPrimary(), not getDefaultColorPrimary()
$this->assertSame($userColor, $theming['color']);
$this->assertSame($userColor, $theming['primaryColor']);
// color-text comes from getTextColorPrimary() directly, not invertTextColor()
$this->assertSame('#ffffff', $theming['color-text']);
// inverted uses invertTextColor() with the user's active color
$this->assertSame(false, $theming['inverted']);
// defaultPrimaryColor always reflects the admin-configured default
$this->assertSame($defaultColor, $theming['defaultPrimaryColor']);
// Background varies by user's background_image setting
$this->assertSame($expectedBackgroundPlain, $theming['background-plain']);
$this->assertSame($expectedBackground, $theming['background']);
// New fields are always present
$this->assertSame('v1', $theming['cacheBuster']);
$this->assertSame(['default'], $theming['enabledThemes']);
}
}
@@ -17,7 +17,7 @@ use OCP\Security\IHasher;
use OCP\Security\ISecureRandom;
class BackupCodeStorage {
private static $CODE_LENGTH = 16;
private const CODE_LENGTH = 16;
public function __construct(
private BackupCodeMapper $mapper,
@@ -40,7 +40,7 @@ class BackupCodeStorage {
$uid = $user->getUID();
foreach (range(1, min([$number, 20])) as $i) {
$code = $this->random->generate(self::$CODE_LENGTH, ISecureRandom::CHAR_HUMAN_READABLE);
$code = $this->random->generate(self::CODE_LENGTH, ISecureRandom::CHAR_HUMAN_READABLE);
$dbCode = new BackupCode();
$dbCode->setUserId($uid);
+2
View File
@@ -3,6 +3,7 @@ OC.L10N.register(
{
"Channel updated" : "Canal de mise à jour modifié",
"Web updater is disabled" : "La mise à jour par l'interface Web est désactivée ",
"Configuration is read-only" : "La configuration est en lecture seule",
"App updated" : "Application mise à jour",
"See what's new" : "Quoi de neuf",
"{app} updated to version {version}" : "{app} a été mise à jour vers la version {version}",
@@ -24,6 +25,7 @@ OC.L10N.register(
"Please make sure your config.php does not set <samp>appstoreenabled</samp> to false." : "Veuillez vous assurer que le paramètre <samp>appstoreenabled</samp> n'est pas défini à false dans votre config.php.",
"Could not connect to the App Store or no updates have been returned at all. Search manually for updates or make sure your server has access to the internet and can connect to the App Store." : "Impossible de se connecter au magasin d'applications ou aucune mise à jour n'est disponible. Recherchez manuellement les mises à jour ou assurez-vous que votre serveur a accès à Internet et peut se connecter au magasin d'applications.",
"<strong>All</strong> apps have a compatible version for this {productName} version available." : "<strong>Toutes</strong> les applications ont une version compatible avec cette version de {productName}.",
"_<strong>%n</strong> app has no compatible version for this {productName} version available._::_<strong>%n</strong> apps have no compatible version for this {productName} version available._" : ["Lapplication <strong>%n</strong> na pas de version compatible pour cette version de {productName}.","Les applications <strong>%n</strong> nont pas de version compatible pour cette version de {productName}.","Les applications <strong>%n</strong> nont pas de version compatible pour cette version de {productName}."],
"Enterprise" : "Entreprise",
"Stable" : "Stable",
"The most recent stable version. It is suited for regular use and will always update to the latest major version." : "La version stable la plus récente. Elle est adaptée pour une utilisation régulière et sera toujours mise à jour vers la dernière version majeure.",
+2
View File
@@ -1,6 +1,7 @@
{ "translations": {
"Channel updated" : "Canal de mise à jour modifié",
"Web updater is disabled" : "La mise à jour par l'interface Web est désactivée ",
"Configuration is read-only" : "La configuration est en lecture seule",
"App updated" : "Application mise à jour",
"See what's new" : "Quoi de neuf",
"{app} updated to version {version}" : "{app} a été mise à jour vers la version {version}",
@@ -22,6 +23,7 @@
"Please make sure your config.php does not set <samp>appstoreenabled</samp> to false." : "Veuillez vous assurer que le paramètre <samp>appstoreenabled</samp> n'est pas défini à false dans votre config.php.",
"Could not connect to the App Store or no updates have been returned at all. Search manually for updates or make sure your server has access to the internet and can connect to the App Store." : "Impossible de se connecter au magasin d'applications ou aucune mise à jour n'est disponible. Recherchez manuellement les mises à jour ou assurez-vous que votre serveur a accès à Internet et peut se connecter au magasin d'applications.",
"<strong>All</strong> apps have a compatible version for this {productName} version available." : "<strong>Toutes</strong> les applications ont une version compatible avec cette version de {productName}.",
"_<strong>%n</strong> app has no compatible version for this {productName} version available._::_<strong>%n</strong> apps have no compatible version for this {productName} version available._" : ["Lapplication <strong>%n</strong> na pas de version compatible pour cette version de {productName}.","Les applications <strong>%n</strong> nont pas de version compatible pour cette version de {productName}.","Les applications <strong>%n</strong> nont pas de version compatible pour cette version de {productName}."],
"Enterprise" : "Entreprise",
"Stable" : "Stable",
"The most recent stable version. It is suited for regular use and will always update to the latest major version." : "La version stable la plus récente. Elle est adaptée pour une utilisation régulière et sera toujours mise à jour vers la dernière version majeure.",
+2
View File
@@ -157,6 +157,7 @@ OC.L10N.register(
"The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin." : "Les classes d'objets fréquentes pour les utilisateurs sont : organizationalPerson, person, user et inetOrgPerson. Si vous n'êtes pas sûr de la classe à utiliser, demandez à l'administrateur de l'annuaire.",
"The filter specifies which LDAP users shall have access to the {instanceName} instance." : "Le filtre spécifie quels utilisateurs LDAP auront accès à l'instance {instanceName}.",
"Verify settings and count users" : "Vérifier les paramètres et compter les utilisateurs",
"User count: {usersCount}" : "Nombre d'utilisateurs : {usersCount}",
"Test Configuration" : "Tester la configuration",
"Help" : "Aide",
"Server" : "Serveur",
@@ -170,6 +171,7 @@ OC.L10N.register(
"Usernames are used to store and assign metadata. In order to precisely identify and recognize users, each LDAP user will have an internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." : "Les noms d'utilisateurs sont utilisés pour le stockage et l'assignation de (meta) données. Pour identifier et reconnaître précisément les utilisateurs, chaque utilisateur LDAP aura un nom interne spécifique. Cela requiert l'association d'un nom d'utilisateur NextCloud à un nom d'utilisateur LDAP. Le nom d'utilisateur créé est associé à l'attribut UUID de l'utilisateur LDAP. Par ailleurs, le DN est mémorisé en cache pour limiter les interactions LDAP mais il n'est pas utilisé pour l'identification. Si le DN est modifié, ces modifications seront retrouvées. Seul le nom interne à NextCloud est utilisé au sein du produit. Supprimer les associations créera des orphelins et l'action affectera toutes les configurations LDAP. NE JAMAIS SUPPRIMER LES ASSOCIATIONS EN ENVIRONNEMENT DE PRODUCTION, mais uniquement sur des environnements de tests et d'expérimentations.",
"Clear Username-LDAP User Mapping" : "Supprimer l'association utilisateur interne-utilisateur LDAP",
"Clear Groupname-LDAP Group Mapping" : "Supprimer l'association nom de groupe-groupe LDAP",
"Please renew your password" : "Merci de modifier votre mot de passe",
"An internal error occurred." : "Une erreur interne est survenue.",
"Please try again or contact your administrator." : "Veuillez réessayer ou contactez votre administrateur.",
"Wrong password." : "Mot de passe incorrect.",
+2
View File
@@ -155,6 +155,7 @@
"The most common object classes for users are organizationalPerson, person, user, and inetOrgPerson. If you are not sure which object class to select, please consult your directory admin." : "Les classes d'objets fréquentes pour les utilisateurs sont : organizationalPerson, person, user et inetOrgPerson. Si vous n'êtes pas sûr de la classe à utiliser, demandez à l'administrateur de l'annuaire.",
"The filter specifies which LDAP users shall have access to the {instanceName} instance." : "Le filtre spécifie quels utilisateurs LDAP auront accès à l'instance {instanceName}.",
"Verify settings and count users" : "Vérifier les paramètres et compter les utilisateurs",
"User count: {usersCount}" : "Nombre d'utilisateurs : {usersCount}",
"Test Configuration" : "Tester la configuration",
"Help" : "Aide",
"Server" : "Serveur",
@@ -168,6 +169,7 @@
"Usernames are used to store and assign metadata. In order to precisely identify and recognize users, each LDAP user will have an internal username. This requires a mapping from username to LDAP user. The created username is mapped to the UUID of the LDAP user. Additionally the DN is cached as well to reduce LDAP interaction, but it is not used for identification. If the DN changes, the changes will be found. The internal username is used all over. Clearing the mappings will have leftovers everywhere. Clearing the mappings is not configuration sensitive, it affects all LDAP configurations! Never clear the mappings in a production environment, only in a testing or experimental stage." : "Les noms d'utilisateurs sont utilisés pour le stockage et l'assignation de (meta) données. Pour identifier et reconnaître précisément les utilisateurs, chaque utilisateur LDAP aura un nom interne spécifique. Cela requiert l'association d'un nom d'utilisateur NextCloud à un nom d'utilisateur LDAP. Le nom d'utilisateur créé est associé à l'attribut UUID de l'utilisateur LDAP. Par ailleurs, le DN est mémorisé en cache pour limiter les interactions LDAP mais il n'est pas utilisé pour l'identification. Si le DN est modifié, ces modifications seront retrouvées. Seul le nom interne à NextCloud est utilisé au sein du produit. Supprimer les associations créera des orphelins et l'action affectera toutes les configurations LDAP. NE JAMAIS SUPPRIMER LES ASSOCIATIONS EN ENVIRONNEMENT DE PRODUCTION, mais uniquement sur des environnements de tests et d'expérimentations.",
"Clear Username-LDAP User Mapping" : "Supprimer l'association utilisateur interne-utilisateur LDAP",
"Clear Groupname-LDAP Group Mapping" : "Supprimer l'association nom de groupe-groupe LDAP",
"Please renew your password" : "Merci de modifier votre mot de passe",
"An internal error occurred." : "Une erreur interne est survenue.",
"Please try again or contact your administrator." : "Veuillez réessayer ou contactez votre administrateur.",
"Wrong password." : "Mot de passe incorrect.",
+2 -7
View File
@@ -444,13 +444,9 @@ class Configuration {
}
protected function getValue(string $varName): string {
static $defaults;
if (is_null($defaults)) {
$defaults = $this->getDefaults();
}
return Server::get(IConfig::class)->getAppValue('user_ldap',
$this->configPrefix . $varName,
$defaults[$varName]);
$this->getDefaults()[$varName]);
}
/**
@@ -571,7 +567,7 @@ class Configuration {
*/
public function getConfigTranslationArray(): array {
//TODO: merge them into one representation
static $array = [
return [
'ldap_host' => 'ldapHost',
'ldap_port' => 'ldapPort',
'ldap_backup_host' => 'ldapBackupHost',
@@ -644,7 +640,6 @@ class Configuration {
'ldap_attr_anniversarydate' => 'ldapAttributeAnniversaryDate',
'ldap_attr_pronouns' => 'ldapAttributePronouns',
];
return $array;
}
/**
+5 -8
View File
@@ -1,10 +1,13 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\User_LDAP\Mapping;
use OCP\HintException;
@@ -12,7 +15,6 @@ use OCP\IAppConfig;
use OCP\ICacheFactory;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\Server;
use OCP\Support\Subscription\IAssertion;
/**
@@ -30,6 +32,7 @@ class UserMapping extends AbstractMapping {
IAppConfig $config,
bool $isCLI,
private IAssertion $assertion,
private IRequest $request,
) {
parent::__construct($dbc, $cacheFactory, $config, $isCLI);
}
@@ -41,13 +44,7 @@ class UserMapping extends AbstractMapping {
try {
$this->assertion->createUserIsLegit();
} catch (HintException $e) {
static $isProvisioningApi = null;
if ($isProvisioningApi === null) {
$request = Server::get(IRequest::class);
$isProvisioningApi = \preg_match(self::PROV_API_REGEX, $request->getRequestUri()) === 1;
}
if ($isProvisioningApi) {
if (\preg_match(self::PROV_API_REGEX, $this->request->getRequestUri()) === 1) {
// only throw when prov API is being used, since functionality
// should not break for end users (e.g. when sharing).
// On direct API usage, e.g. on users page, this is desired.
+13 -16
View File
@@ -16,7 +16,7 @@ use OCP\Util;
use Psr\Log\LoggerInterface;
class Wizard extends LDAPUtility {
protected static ?IL10N $l = null;
private IL10N $l;
protected ?\LDAP\Connection $cr = null;
protected WizardResult $result;
protected LoggerInterface $logger;
@@ -40,9 +40,7 @@ class Wizard extends LDAPUtility {
protected Access $access,
) {
parent::__construct($ldap);
if (is_null(static::$l)) {
static::$l = Server::get(IL10NFactory::class)->get('user_ldap');
}
$this->l = Server::get(IL10NFactory::class)->get('user_ldap');
$this->result = new WizardResult();
$this->logger = Server::get(LoggerInterface::class);
}
@@ -94,7 +92,7 @@ class Wizard extends LDAPUtility {
$filter = $this->configuration->ldapGroupFilter;
if (empty($filter)) {
$output = self::$l->n('%n group found', '%n groups found', 0);
$output = $this->l->n('%n group found', '%n groups found', 0);
$this->result->addChange('ldap_group_count', $output);
return $this->result;
}
@@ -110,9 +108,9 @@ class Wizard extends LDAPUtility {
}
if ($groupsTotal > 1000) {
$output = self::$l->t('> 1000 groups found');
$output = $this->l->t('> 1000 groups found');
} else {
$output = self::$l->n(
$output = $this->l->n(
'%n group found',
'%n groups found',
$groupsTotal
@@ -130,9 +128,9 @@ class Wizard extends LDAPUtility {
$usersTotal = $this->countEntries($filter, 'users');
if ($usersTotal > 1000) {
$output = self::$l->t('> 1000 users found');
$output = $this->l->t('> 1000 users found');
} else {
$output = self::$l->n(
$output = $this->l->n(
'%n user found',
'%n users found',
$usersTotal
@@ -216,7 +214,7 @@ class Wizard extends LDAPUtility {
}
}
throw new \Exception(self::$l->t('Could not detect user display name attribute. Please specify it yourself in advanced LDAP settings.'));
throw new \Exception($this->l->t('Could not detect user display name attribute. Please specify it yourself in advanced LDAP settings.'));
}
/**
@@ -431,7 +429,7 @@ class Wizard extends LDAPUtility {
natsort($groupNames);
$this->result->addOptions($dbKey, array_values($groupNames));
} else {
throw new \Exception(self::$l->t('Could not find the desired feature'));
throw new \Exception($this->l->t('Could not find the desired feature'));
}
$setFeatures = $this->configuration->$confKey;
@@ -1024,7 +1022,7 @@ class Wizard extends LDAPUtility {
$host = $this->configuration->ldapHost;
$hostInfo = parse_url((string)$host);
if (!is_string($host) || !$hostInfo) {
throw new \Exception(self::$l->t('Invalid Host'));
throw new \Exception($this->l->t('Invalid Host'));
}
$this->logger->debug(
'Wiz: Attempting to connect',
@@ -1032,7 +1030,7 @@ class Wizard extends LDAPUtility {
);
$cr = $this->ldap->connect($host, (string)$port);
if (!$this->ldap->isResource($cr)) {
throw new \Exception(self::$l->t('Invalid Host'));
throw new \Exception($this->l->t('Invalid Host'));
}
/** @var \LDAP\Connection $cr */
@@ -1219,7 +1217,7 @@ class Wizard extends LDAPUtility {
//sorting in the web UI. Therefore: array_values
$this->result->addOptions($dbkey, array_values($availableFeatures));
} else {
throw new \Exception(self::$l->t('Could not find the desired feature'));
throw new \Exception($this->l->t('Could not find the desired feature'));
}
$setFeatures = $this->configuration->$confkey;
@@ -1307,7 +1305,7 @@ class Wizard extends LDAPUtility {
* @return array<array{port:int,tls:bool}>
*/
private function getDefaultLdapPortSettings(): array {
static $settings = [
return [
['port' => 7636, 'tls' => false],
['port' => 636, 'tls' => false],
['port' => 7389, 'tls' => true],
@@ -1315,7 +1313,6 @@ class Wizard extends LDAPUtility {
['port' => 7389, 'tls' => false],
['port' => 389, 'tls' => false],
];
return $settings;
}
/**

Some files were not shown because too many files have changed in this diff Show More