@@ -41,7 +41,7 @@
diff --git a/frontend/src/components/prompts/Rename.vue b/frontend/src/components/prompts/Rename.vue
index f18ed7a089..4e1bb095bc 100644
--- a/frontend/src/components/prompts/Rename.vue
+++ b/frontend/src/components/prompts/Rename.vue
@@ -6,7 +6,7 @@
- {{ $t("prompts.renameMessage") }} {{ oldName() }}{{ oldName }}:
{{ $t("buttons.rename") }}
@@ -56,7 +57,7 @@ export default {
};
},
created() {
- this.name = this.oldName();
+ this.name = this.oldName;
},
inject: ["$showError"],
computed: {
@@ -67,25 +68,28 @@ export default {
"isListing",
]),
...mapWritableState(useFileStore, ["reload", "preselect"]),
- },
- methods: {
- ...mapActions(useLayoutStore, ["closeHovers"]),
- cancel: function () {
- this.closeHovers();
- },
- oldName: function () {
+ oldName() {
if (!this.isListing) {
return this.req.name;
}
if (this.selectedCount === 0 || this.selectedCount > 1) {
// This shouldn't happen.
- return;
+ return "";
}
return this.req.items[this.selected[0]].name;
},
+ },
+ methods: {
+ ...mapActions(useLayoutStore, ["closeHovers"]),
+ cancel: function () {
+ this.closeHovers();
+ },
submit: async function () {
+ if (this.name === "" || this.name === this.oldName) {
+ return;
+ }
let oldLink = "";
let newLink = "";
diff --git a/frontend/src/components/prompts/ReplaceRename.vue b/frontend/src/components/prompts/ReplaceRename.vue
deleted file mode 100644
index 1d49d735bd..0000000000
--- a/frontend/src/components/prompts/ReplaceRename.vue
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
{{ $t("prompts.replace") }}
-
-
-
-
{{ $t("prompts.replaceMessage") }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/src/components/prompts/ResolveConflict.vue b/frontend/src/components/prompts/ResolveConflict.vue
new file mode 100644
index 0000000000..e7bf9c7462
--- /dev/null
+++ b/frontend/src/components/prompts/ResolveConflict.vue
@@ -0,0 +1,307 @@
+
+
+
+
+ {{
+ personalized
+ ? $t("prompts.resolveConflict")
+ : $t("prompts.replaceOrSkip")
+ }}
+
+
+
+
+
+
+ {{ $t("prompts.singleConflictResolve") }}
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+ {{ $t("prompts.rename") }}
+
+
+ {{ $t("prompts.forbiddenError") }}
+
+
+
+ {{ $t("prompts.override") }}
+
+
+ {{ $t("prompts.skip") }}
+
+
+
+
+
+
+ {{ humanTime(item.origin.lastModified) }}
+
+
+ {{ humanSize(item.origin.size) }}
+
+
+
+
+
+
+
+ {{ humanTime(item.dest.lastModified) }}
+
+
+ {{ humanSize(item.dest.size) }}
+
+
+
+
+
+
+
+
+
+ {{ $t("prompts.fastConflictResolve", { count: conflict.length }) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/prompts/Upload.vue b/frontend/src/components/prompts/Upload.vue
index 75f7951f26..19b1fbb175 100644
--- a/frontend/src/components/prompts/Upload.vue
+++ b/frontend/src/components/prompts/Upload.vue
@@ -69,18 +69,29 @@ const uploadInput = (event: Event) => {
const path = route.path.endsWith("/") ? route.path : route.path + "/";
const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
- if (conflict) {
+ if (conflict.length > 0) {
layoutStore.showHover({
- prompt: "replace",
- action: (event: Event) => {
- event.preventDefault();
- layoutStore.closeHovers();
- upload.handleFiles(uploadFiles, path, false);
+ prompt: "resolve-conflict",
+ props: {
+ conflict: conflict,
+ isUploadAction: true,
},
- confirm: (event: Event) => {
+ confirm: (event: Event, result: Array
) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(uploadFiles, path, true);
+ for (let i = result.length - 1; i >= 0; i--) {
+ const item = result[i];
+ if (item.checked.length == 2) {
+ continue;
+ } else if (item.checked.length == 1 && item.checked[0] == "origin") {
+ uploadFiles[item.index].overwrite = true;
+ } else {
+ uploadFiles.splice(item.index, 1);
+ }
+ }
+ if (uploadFiles.length > 0) {
+ upload.handleFiles(uploadFiles, path);
+ }
},
});
diff --git a/frontend/src/components/settings/Languages.vue b/frontend/src/components/settings/Languages.vue
index 3df6028e61..6a6033587b 100644
--- a/frontend/src/components/settings/Languages.vue
+++ b/frontend/src/components/settings/Languages.vue
@@ -34,9 +34,10 @@ export default {
no: "Norsk",
nl: "Nederlands (Nederland)",
"nl-be": "Nederlands (België)",
+ lv: "Latviešu",
pl: "Polski",
"pt-br": "Português (Brasil)",
- pt: "Português (Portugal)",
+ "pt-pt": "Português (Portugal)",
ro: "Romanian",
ru: "Русский",
sk: "Slovenčina",
diff --git a/frontend/src/css/base.css b/frontend/src/css/base.css
index f0b8ef0cee..cdb3319bf8 100644
--- a/frontend/src/css/base.css
+++ b/frontend/src/css/base.css
@@ -182,10 +182,11 @@ html[dir="rtl"] .breadcrumbs a {
background: var(--textSecondary) !important;
}
-.vfm-modal {
- z-index: 9999999 !important;
-}
-
body > div[style*="z-index: 9990"] {
z-index: 10000 !important;
}
+
+#modal-background .button:focus {
+ outline: 1px solid #2195f32d;
+ outline-offset: 1px;
+}
diff --git a/frontend/src/css/styles.css b/frontend/src/css/styles.css
index 5ac7d8d516..bab7cd192d 100644
--- a/frontend/src/css/styles.css
+++ b/frontend/src/css/styles.css
@@ -1,6 +1,5 @@
@import "normalize.css/normalize.css";
@import "vue-toastification/dist/index.css";
-@import "vue-final-modal/style.css";
@import "./_variables.css";
@import "./_buttons.css";
@import "./_inputs.css";
diff --git a/frontend/src/i18n/ar.json b/frontend/src/i18n/ar.json
index cf600a381b..cadd540283 100644
--- a/frontend/src/i18n/ar.json
+++ b/frontend/src/i18n/ar.json
@@ -48,7 +48,11 @@
"saveChanges": "حفظ التغييرات",
"editAsText": "تعديل على شكل نص",
"increaseFontSize": "زيادة حجم الخط",
- "decreaseFontSize": "تصغير حجم الخط"
+ "decreaseFontSize": "تصغير حجم الخط",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "تحميل الملف",
@@ -161,7 +165,19 @@
"uploadMessage": "إختر الملفات التي تريد رفعها.",
"optionalPassword": "كلمة مرور إختيارية",
"resolution": "الدقة",
- "discardEditorChanges": "هل تريد بالتأكيد إلغاء التغييرات؟"
+ "discardEditorChanges": "هل تريد بالتأكيد إلغاء التغييرات؟",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "الصور",
diff --git a/frontend/src/i18n/bg.json b/frontend/src/i18n/bg.json
index db4ece315a..2cba2b983f 100644
--- a/frontend/src/i18n/bg.json
+++ b/frontend/src/i18n/bg.json
@@ -48,7 +48,11 @@
"saveChanges": "Запиши промените",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Свали файл",
@@ -161,7 +165,19 @@
"uploadMessage": "Изберете опция за качване.",
"optionalPassword": "Опционална парола",
"resolution": "Резолюция",
- "discardEditorChanges": "Сигурни ли сте, че искате да откажете направените промени?"
+ "discardEditorChanges": "Сигурни ли сте, че искате да откажете направените промени?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Изображения",
diff --git a/frontend/src/i18n/ca.json b/frontend/src/i18n/ca.json
index da6dfcc99a..4ce9faa0b3 100644
--- a/frontend/src/i18n/ca.json
+++ b/frontend/src/i18n/ca.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Descarregar fitxer",
@@ -161,7 +165,19 @@
"uploadMessage": "Seleccioneu una opció per pujar.",
"optionalPassword": "Contrasenya opcional",
"resolution": "Resolució",
- "discardEditorChanges": "Esteu segur que voleu descartar els canvis que heu fet?"
+ "discardEditorChanges": "Esteu segur que voleu descartar els canvis que heu fet?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Imatges",
diff --git a/frontend/src/i18n/cs.json b/frontend/src/i18n/cs.json
index 560e015c91..e354475f83 100644
--- a/frontend/src/i18n/cs.json
+++ b/frontend/src/i18n/cs.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Stáhnout soubor",
@@ -161,7 +165,19 @@
"uploadMessage": "Vyberte možnost pro nahrání.",
"optionalPassword": "Volitelné heslo",
"resolution": "Rozlišení",
- "discardEditorChanges": "Opravdu chcete zrušit provedené změny?"
+ "discardEditorChanges": "Opravdu chcete zrušit provedené změny?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Obrázky",
diff --git a/frontend/src/i18n/de.json b/frontend/src/i18n/de.json
index 0cd29ba839..a09e2bdb51 100644
--- a/frontend/src/i18n/de.json
+++ b/frontend/src/i18n/de.json
@@ -42,13 +42,17 @@
"update": "Aktualisieren",
"upload": "Hochladen",
"openFile": "Datei öffnen",
- "openDirect": "View raw",
+ "openDirect": "Original anzeigen",
"discardChanges": "Verwerfen",
"stopSearch": "Suche beenden",
"saveChanges": "Änderungen speichern",
"editAsText": "Als Text bearbeiten",
"increaseFontSize": "Schrift vergrößern",
- "decreaseFontSize": "Schrift verkleinern"
+ "decreaseFontSize": "Schrift verkleinern",
+ "overrideAll": "Alle Dateien im Zielordner ersetzen",
+ "skipAll": "Alle in Konflikt stehenden Dateien überspringen",
+ "renameAll": "Alle Dateien umbenennen (Kopie erstellen)",
+ "singleDecision": "Bei jeder Datei mit Konflikt entscheiden"
},
"download": {
"downloadFile": "Datei herunterladen",
@@ -161,7 +165,19 @@
"uploadMessage": "Wähle eine Upload-Option.",
"optionalPassword": "Optionales Passwort",
"resolution": "Auflösung",
- "discardEditorChanges": "Möchtest du deine Änderungen wirklich verwerfen?"
+ "discardEditorChanges": "Möchtest du deine Änderungen wirklich verwerfen?",
+ "replaceOrSkip": "Dateien ersetzen oder überspringen",
+ "resolveConflict": "Welche Dateien möchtest du behalten?",
+ "singleConflictResolve": "Wenn du beide Versionen auswählst, wird dem Namen der kopierten Datei eine Nummer hinzugefügt.",
+ "fastConflictResolve": "Der Zielordner enthält {count} Dateien mit demselben Namen.",
+ "uploadingFiles": "Dateien werden hochgeladen",
+ "filesInOrigin": "Dateien im Ursprungsordner",
+ "filesInDest": "Dateien im Zielordner",
+ "override": "Überschreiben",
+ "skip": "Überspringen",
+ "forbiddenError": "Zugriff verweigert",
+ "currentPassword": "Dein Passwort",
+ "currentPasswordMessage": "Gib dein Passwort ein, um diese Aktion zu bestätigen."
},
"search": {
"images": "Bilder",
diff --git a/frontend/src/i18n/el.json b/frontend/src/i18n/el.json
index ab0e0914f5..90853ab7da 100644
--- a/frontend/src/i18n/el.json
+++ b/frontend/src/i18n/el.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Λήψη αρχείου",
@@ -161,7 +165,19 @@
"uploadMessage": "Επιλέξτε μια επιλογή για τη μεταφόρτωση.",
"optionalPassword": "Προαιρετικός κωδικός πρόσβασης",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Εικόνες",
diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json
index 0410f7f860..8f3223fff4 100644
--- a/frontend/src/i18n/en.json
+++ b/frontend/src/i18n/en.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Download File",
@@ -161,7 +165,19 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Images",
diff --git a/frontend/src/i18n/es.json b/frontend/src/i18n/es.json
index 94b77c490c..92847e62be 100644
--- a/frontend/src/i18n/es.json
+++ b/frontend/src/i18n/es.json
@@ -48,7 +48,11 @@
"saveChanges": "Guardar cambios",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Descargar fichero",
@@ -161,7 +165,19 @@
"uploadMessage": "Seleccione una opción para subir.",
"optionalPassword": "Contraseña opcional",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Imágenes",
diff --git a/frontend/src/i18n/fa.json b/frontend/src/i18n/fa.json
index 53fef115dd..a40addba4b 100644
--- a/frontend/src/i18n/fa.json
+++ b/frontend/src/i18n/fa.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "دانلود فایل",
@@ -161,7 +165,19 @@
"uploadMessage": "یک گزینه برای آپلود انتخاب کنید.",
"optionalPassword": "رمز عبور اختیاری",
"resolution": "وضوح تصویر",
- "discardEditorChanges": "آیا مطمئن هستید که میخواهید تغییراتی را که ایجاد کردهاید، لغو کنید؟"
+ "discardEditorChanges": "آیا مطمئن هستید که میخواهید تغییراتی را که ایجاد کردهاید، لغو کنید؟",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "تصاویر",
diff --git a/frontend/src/i18n/fr.json b/frontend/src/i18n/fr.json
index 3f9a36e889..7a5e6070c4 100644
--- a/frontend/src/i18n/fr.json
+++ b/frontend/src/i18n/fr.json
@@ -48,7 +48,11 @@
"saveChanges": "Enregistrer changements",
"editAsText": "Editer comme Texte",
"increaseFontSize": "Augmenter taille police",
- "decreaseFontSize": "Réduire taille police"
+ "decreaseFontSize": "Réduire taille police",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Télécharger le fichier",
@@ -161,7 +165,19 @@
"uploadMessage": "Sélectionnez une option d'import.",
"optionalPassword": "Mot de passe optionnel",
"resolution": "Résolution",
- "discardEditorChanges": "Êtes-vous sûr de vouloir annuler les modifications apportées ?"
+ "discardEditorChanges": "Êtes-vous sûr de vouloir annuler les modifications apportées ?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Images",
diff --git a/frontend/src/i18n/he.json b/frontend/src/i18n/he.json
index a9aed87d45..1b7a7b0bc2 100644
--- a/frontend/src/i18n/he.json
+++ b/frontend/src/i18n/he.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "הורד קובץ",
@@ -161,7 +165,19 @@
"uploadMessage": "בחר אפשרות העלאה.",
"optionalPassword": "סיסמא אופציונלית",
"resolution": "Resolution",
- "discardEditorChanges": "האם אתה בטוח שברצונך לבטל את השינויים שביצעת?"
+ "discardEditorChanges": "האם אתה בטוח שברצונך לבטל את השינויים שביצעת?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "תמונות",
diff --git a/frontend/src/i18n/hr.json b/frontend/src/i18n/hr.json
index df1fb6da7c..9626a0c756 100644
--- a/frontend/src/i18n/hr.json
+++ b/frontend/src/i18n/hr.json
@@ -48,7 +48,11 @@
"saveChanges": "Spremi promjene",
"editAsText": "Uredi kao tekst",
"increaseFontSize": "Povećaj veličinu fonta",
- "decreaseFontSize": "Smanji veličinu fonta"
+ "decreaseFontSize": "Smanji veličinu fonta",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Preuzmi Datoteku",
@@ -161,7 +165,19 @@
"uploadMessage": "Odaberite opciju za prijenos.",
"optionalPassword": "Opcionalna lozinka",
"resolution": "Rezolucija",
- "discardEditorChanges": "Jeste li sigurni da želite odbaciti promjene koje ste napravili?"
+ "discardEditorChanges": "Jeste li sigurni da želite odbaciti promjene koje ste napravili?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Slike",
diff --git a/frontend/src/i18n/hu.json b/frontend/src/i18n/hu.json
index 38732646ae..4df490b8bc 100644
--- a/frontend/src/i18n/hu.json
+++ b/frontend/src/i18n/hu.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Fájl letöltése",
@@ -161,7 +165,19 @@
"uploadMessage": "Válasszon egy feltöltési módot.",
"optionalPassword": "Választható jelszó",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Képek",
diff --git a/frontend/src/i18n/index.ts b/frontend/src/i18n/index.ts
index 9fa7155f85..44b8e17783 100644
--- a/frontend/src/i18n/index.ts
+++ b/frontend/src/i18n/index.ts
@@ -3,6 +3,7 @@ import { createI18n } from "vue-i18n";
import("dayjs/locale/ar");
import("dayjs/locale/bg");
+import("dayjs/locale/ca");
import("dayjs/locale/cs");
import("dayjs/locale/de");
import("dayjs/locale/el");
@@ -16,6 +17,7 @@ import("dayjs/locale/is");
import("dayjs/locale/it");
import("dayjs/locale/ja");
import("dayjs/locale/ko");
+import("dayjs/locale/lv");
import("dayjs/locale/nb");
import("dayjs/locale/nl");
import("dayjs/locale/nl-be");
@@ -41,6 +43,18 @@ export function detectLocale() {
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language
let locale = navigator.language.toLowerCase();
switch (true) {
+ case /^ar\b/.test(locale):
+ locale = "ar";
+ break;
+ case /^bg\b/.test(locale):
+ locale = "bg";
+ break;
+ case /^cs\b/.test(locale):
+ locale = "cs";
+ break;
+ case /^lv\b/.test(locale):
+ locale = "lv";
+ break;
case /^he\b/.test(locale):
locale = "he";
break;
@@ -50,9 +64,6 @@ export function detectLocale() {
case /^hu\b/.test(locale):
locale = "hu";
break;
- case /^ar\b/.test(locale):
- locale = "ar";
- break;
case /^el.*/i.test(locale):
locale = "el";
break;
@@ -74,8 +85,9 @@ export function detectLocale() {
case /^pt-br\b/.test(locale):
locale = "pt-br";
break;
+ case /^pt-pt\b/.test(locale):
case /^pt\b/.test(locale):
- locale = "pt";
+ locale = "pt-pt";
break;
case /^ja\b/.test(locale):
locale = "ja";
@@ -128,9 +140,7 @@ export function detectLocale() {
case /^no\b/.test(locale):
locale = "no";
break;
- case /^bg\b/.test(locale):
- locale = "bg";
- break;
+
default:
locale = "en";
}
diff --git a/frontend/src/i18n/is.json b/frontend/src/i18n/is.json
index 6b7d8abbd5..40f8fd6de6 100644
--- a/frontend/src/i18n/is.json
+++ b/frontend/src/i18n/is.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Sækja skjal",
@@ -161,7 +165,19 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Myndir",
diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json
index a17eb7461e..a363bd0680 100644
--- a/frontend/src/i18n/it.json
+++ b/frontend/src/i18n/it.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Scarica file",
@@ -161,7 +165,19 @@
"uploadMessage": "Seleziona un'opzione per il caricamento.",
"optionalPassword": "Password opzionale",
"resolution": "Risoluzione",
- "discardEditorChanges": "Sei sicuro di voler scartare le modifiche apportate?"
+ "discardEditorChanges": "Sei sicuro di voler scartare le modifiche apportate?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Immagini",
diff --git a/frontend/src/i18n/ja.json b/frontend/src/i18n/ja.json
index 853fe8d8ab..79c29ac8bc 100644
--- a/frontend/src/i18n/ja.json
+++ b/frontend/src/i18n/ja.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "ファイルのダウンロード",
@@ -161,7 +165,19 @@
"uploadMessage": "アップロードするオプションを選択してください。",
"optionalPassword": "パスワード(オプション)",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "画像",
diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json
index 9c1cd76491..1ca34ed38b 100644
--- a/frontend/src/i18n/ko.json
+++ b/frontend/src/i18n/ko.json
@@ -42,13 +42,17 @@
"update": "업데이트",
"upload": "업로드",
"openFile": "파일 열기",
- "openDirect": "View raw",
+ "openDirect": "원본 보기",
"discardChanges": "변경 사항 취소",
"stopSearch": "검색 중단",
"saveChanges": "변경사항 저장",
"editAsText": "텍스트로 편집",
"increaseFontSize": "글꼴 크기 증가",
- "decreaseFontSize": "글꼴 크기 감소"
+ "decreaseFontSize": "글꼴 크기 감소",
+ "overrideAll": "대상 폴더의 모든 파일을 대체",
+ "skipAll": "충돌하는 모든 파일을 건너뛰기",
+ "renameAll": "모든 파일의 이름 변경 (복사본 생성)",
+ "singleDecision": "충돌하는 각 파일을 확인"
},
"download": {
"downloadFile": "파일 다운로드",
@@ -161,7 +165,19 @@
"uploadMessage": "업로드 옵션을 선택하세요.",
"optionalPassword": "비밀번호 (선택)",
"resolution": "해상도",
- "discardEditorChanges": "변경 사항을 취소하시겠습니까?"
+ "discardEditorChanges": "변경 사항을 취소하시겠습니까?",
+ "replaceOrSkip": "파일 대체 또는 건너뛰기",
+ "resolveConflict": "어떤 파일을 유지하시겠습니까?",
+ "singleConflictResolve": "모든 버전을 선택하면 복사한 파일의 이름에 번호를 추가합니다.",
+ "fastConflictResolve": "대상 폴더에 같은 이름을 가진 파일이 {count}개 있습니다.",
+ "uploadingFiles": "파일 업로드 중",
+ "filesInOrigin": "원본 파일",
+ "filesInDest": "대상 경로의 파일",
+ "override": "덮어쓰기",
+ "skip": "건너뛰기",
+ "forbiddenError": "권한 오류",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "이미지",
diff --git a/frontend/src/i18n/lv.json b/frontend/src/i18n/lv.json
index 2d55756691..72cc0a5dd3 100644
--- a/frontend/src/i18n/lv.json
+++ b/frontend/src/i18n/lv.json
@@ -48,7 +48,11 @@
"saveChanges": "Saglabāt izmaiņas",
"editAsText": "Rediģēt kā tekstu",
"increaseFontSize": "Palieliniet fonta lielumu",
- "decreaseFontSize": "Samaziniet fonta lielumu"
+ "decreaseFontSize": "Samaziniet fonta lielumu",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Lejupielādēt failu",
@@ -161,7 +165,19 @@
"uploadMessage": "Atlasiet augšupielādes opciju.",
"optionalPassword": "Izvēles parole",
"resolution": "Izšķirtspēja",
- "discardEditorChanges": "Vai tiešām vēlaties atmest veiktās izmaiņas?"
+ "discardEditorChanges": "Vai tiešām vēlaties atmest veiktās izmaiņas?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Attēli",
diff --git a/frontend/src/i18n/lv_LV.json b/frontend/src/i18n/lv_LV.json
deleted file mode 100644
index 67fbdb8e0e..0000000000
--- a/frontend/src/i18n/lv_LV.json
+++ /dev/null
@@ -1,290 +0,0 @@
-{
- "buttons": {
- "cancel": "Atcelt",
- "clear": "Tīrs",
- "close": "Aizvērt",
- "continue": "Turpināt",
- "copy": "Kopēt",
- "copyFile": "Kopēt failu",
- "copyToClipboard": "Kopēt starpliktuvē",
- "copyDownloadLinkToClipboard": "Kopēt lejupielādes saiti starpliktuvē",
- "create": "Izveidot",
- "delete": "Dzēst",
- "download": "Lejupielādēt",
- "file": "Fails",
- "folder": "Mape",
- "fullScreen": "Pārslēgt pilnekrāna režīmu",
- "hideDotfiles": "Slēpt punktfailus",
- "info": "Informācija",
- "more": "Vairāk",
- "move": "Pārvietot",
- "moveFile": "Pārvietot failu",
- "new": "Jauns",
- "next": "Nākamais",
- "ok": "Labi",
- "permalink": "Iegūt pastāvīgo saiti",
- "previous": "Iepriekšējais",
- "preview": "Priekšskatījums",
- "publish": "Publicēt",
- "rename": "Pārdēvēt",
- "replace": "Aizstāt",
- "reportIssue": "Ziņot par problēmu",
- "save": "Saglabāt",
- "schedule": "Grafiks",
- "search": "Meklēt",
- "select": "Izvēlieties",
- "selectMultiple": "Izvēlieties vairākus",
- "share": "Dalīties",
- "shell": "Pārslēgt apvalku",
- "submit": "Iesniegt",
- "switchView": "Pārslēgt skatu",
- "toggleSidebar": "Pārslēgt sānjoslu",
- "update": "Atjaunināt",
- "upload": "Augšupielādēt",
- "openFile": "Atvērt failu",
- "openDirect": "View raw",
- "discardChanges": "Izmest",
- "stopSearch": "Beigt meklēšanu",
- "saveChanges": "Saglabāt izmaiņas",
- "editAsText": "Rediģēt kā tekstu",
- "increaseFontSize": "Palieliniet fonta lielumu",
- "decreaseFontSize": "Samaziniet fonta lielumu"
- },
- "download": {
- "downloadFile": "Lejupielādēt failu",
- "downloadFolder": "Lejupielādēt mapi",
- "downloadSelected": "Lejupielādēt atlasīto"
- },
- "upload": {
- "abortUpload": "Vai tiešām vēlaties pārtraukt?"
- },
- "errors": {
- "forbidden": "Jums nav atļaujas piekļūt šim.",
- "internal": "Kaut kas tiešām nogāja greizi.",
- "notFound": "Šo atrašanās vietu nevar sasniegt.",
- "connection": "Ar serveri nevar sazināties."
- },
- "files": {
- "body": "Ķermenis",
- "closePreview": "Aizvērt priekšskatījumu",
- "files": "Faili",
- "folders": "Mapes",
- "home": "Sākums",
- "lastModified": "Pēdējoreiz modificēts",
- "loading": "Notiek ielāde...",
- "lonely": "Šeit ir tukša vieta...",
- "metadata": "Metadati",
- "multipleSelectionEnabled": "Vairākas atlases ir iespējotas",
- "name": "Vārds",
- "size": "Izmērs",
- "sortByLastModified": "Kārtot pēc pēdējās modifikācijas",
- "sortByName": "Kārtot pēc nosaukuma",
- "sortBySize": "Kārtot pēc izmēra",
- "noPreview": "Šim failam nav pieejams priekšskatījums.",
- "csvTooLarge": "CSV fails ir pārāk liels priekšskatīšanai (>5 MB). Lūdzu, lejupielādējiet to, lai skatītu",
- "csvLoadFailed": "Neizdevās ielādēt CSV failu.",
- "showingRows": "Rāda {count} rindu(as)",
- "columnSeparator": "Kolonnu atdalītājs",
- "csvSeparators": {
- "comma": "Komats (,)",
- "semicolon": "Semikols (;)",
- "both": "Gan (,) gan (;)"
- },
- "fileEncoding": "File Encoding"
- },
- "help": {
- "click": "atlasiet failu vai direktoriju",
- "ctrl": {
- "click": "atlasīt vairākus failus vai direktorijus",
- "f": "atver meklēšanu",
- "s": "saglabājiet failu vai lejupielādējiet direktoriju, kurā atrodaties"
- },
- "del": "dzēst atlasītos vienumus",
- "doubleClick": "atvērt failu vai direktoriju",
- "esc": "notīrīt atlasi un/vai aizvērt uzvedni",
- "f1": "šo informāciju",
- "f2": "pārdēvēt failu",
- "help": "Palīdzība"
- },
- "login": {
- "createAnAccount": "Izveidot kontu",
- "loginInstead": "Jau ir konts",
- "password": "Parole",
- "passwordConfirm": "Paroles apstiprināšana",
- "passwordsDontMatch": "Paroles nesakrīt",
- "signup": "Reģistrēšanās",
- "submit": "Pieteikties",
- "username": "Lietotājvārds",
- "usernameTaken": "Lietotājvārds jau aizņemts",
- "wrongCredentials": "Nepareizi akreditācijas dati",
- "passwordTooShort": "Parolei jābūt vismaz {min} rakstzīmju garai",
- "logout_reasons": {
- "inactivity": "Jūs esat atteicies no sistēmas neaktivitātes dēļ."
- }
- },
- "permanent": "Pastāvīgs",
- "prompts": {
- "copy": "Kopēt",
- "copyMessage": "Izvēlieties atrašanās vietu, uz kuru kopēt failus:",
- "currentlyNavigating": "Pašlaik navigācija:",
- "deleteMessageMultiple": "Vai tiešām vēlaties dzēst {count} failu(s)?",
- "deleteMessageSingle": "Vai tiešām vēlaties dzēst šo failu/mapi?",
- "deleteMessageShare": "Vai tiešām vēlaties dzēst šo koplietojumu({path})?",
- "deleteUser": "Vai tiešām vēlaties dzēst šo lietotāju?",
- "deleteTitle": "Dzēst failus",
- "displayName": "Displeja nosaukums:",
- "download": "Lejupielādēt failus",
- "downloadMessage": "Izvēlieties formātu, kuru vēlaties lejupielādēt.",
- "error": "Kaut kas nogāja greizi",
- "fileInfo": "Informācija par failu",
- "filesSelected": "{count} atlasīti faili",
- "lastModified": "Pēdējās izmaiņas",
- "move": "Pārvietot",
- "moveMessage": "Izvēlieties jaunu mājvietu failam(iem)/mapei(ēm):",
- "newArchetype": "Izveidojiet jaunu ierakstu, pamatojoties uz arhtipu. Jūsu fails tiks izveidots satura mapē.",
- "newDir": "Jauna direktorija",
- "newDirMessage": "Nosaukums savai jaunajai direktorijai.",
- "newFile": "Jauns fails",
- "newFileMessage": "Nosauciet savu jauno failu.",
- "numberDirs": "Katalogu skaits",
- "numberFiles": "Failu skaits",
- "rename": "Pārdēvēt",
- "renameMessage": "Ievietojiet jaunu nosaukumu",
- "replace": "Aizstāt",
- "replaceMessage": "Vienam no failiem, kurus mēģināt augšupielādēt, ir konfliktējošs nosaukums. Vai vēlaties izlaist šo failu un turpināt augšupielādi vai aizstāt esošo?\n",
- "schedule": "Grafiks",
- "scheduleMessage": "Izvēlieties datumu un laiku, lai ieplānotu šī ieraksta publicēšanu.",
- "show": "Rādīt",
- "size": "Izmērs",
- "upload": "Augšupielādēt",
- "uploadFiles": "Notiek {files} failu augšupielāde...",
- "uploadMessage": "Atlasiet augšupielādes opciju.",
- "optionalPassword": "Izvēles parole",
- "resolution": "Izšķirtspēja",
- "discardEditorChanges": "Vai tiešām vēlaties atmest veiktās izmaiņas?"
- },
- "search": {
- "images": "Attēli",
- "music": "Mūzika",
- "pdf": "PDF",
- "pressToSearch": "Nospiediet taustiņu Enter, lai meklētu...",
- "search": "Meklē...",
- "typeToSearch": "Ierakstiet, lai meklētu...",
- "types": "Veidi",
- "video": "Video"
- },
- "settings": {
- "aceEditorTheme": "Ace redaktora tēma",
- "admin": "Admin",
- "administrator": "Administrator",
- "allowCommands": "Izpildīt komandas",
- "allowEdit": "Rediģēt, pārdēvēt un dzēst failus vai direktorijus",
- "allowNew": "Izveidojiet jaunus failus un direktorijus",
- "allowPublish": "Publicēt jaunus ierakstus un lapas",
- "allowSignup": "Atļaut lietotājiem reģistrēties",
- "hideLoginButton": "Paslēpt pieteikšanās pogu publiskajās lapās",
- "avoidChanges": "(atstājiet tukšu, lai izvairītos no izmaiņām)",
- "branding": "Zīmols",
- "brandingDirectoryPath": "Zīmola direktorijas ceļš",
- "brandingHelp": "Jūs varat pielāgot sava failu pārlūka instances izskatu un darbību, mainot tās nosaukumu, aizstājot logotipu, pievienojot pielāgotus stilus un pat atspējojot ārējās saites uz GitHub.\nLai iegūtu plašāku informāciju par pielāgotu zīmola veidošanu, lūdzu, skatiet {0}.",
- "changePassword": "Mainīt paroli",
- "commandRunner": "Komandu skrējējs",
- "commandRunnerHelp": "Šeit varat iestatīt komandas, kas tiek izpildītas nosauktajos notikumos. Katrā rindā jāraksta pa vienai. Būs pieejami vides mainīgie {0} un {1}, kas ir {0} relatīvi pret {1}. Lai iegūtu plašāku informāciju par šo funkciju un pieejamajiem vides mainīgajiem, lūdzu, izlasiet {2}.",
- "commandsUpdated": "Komandas atjauninātas!",
- "createUserDir": "Automātiski izveidot lietotāja mājas direktoriju, pievienojot jaunu lietotāju",
- "minimumPasswordLength": "Minimālais paroles garums",
- "tusUploads": "Sadalītas augšupielādes",
- "tusUploadsHelp": "Failu pārlūks atbalsta failu augšupielādi fragmentos, ļaujot izveidot efektīvu, uzticamu, atsākamu un fragmentos sadalītu failu augšupielādi pat neuzticamos tīklos.",
- "tusUploadsChunkSize": "Norāda pieprasījuma maksimālo izmēru (mazākiem augšupielādes apjomiem tiks izmantota tieša augšupielāde). Varat ievadīt vienkāršu veselu skaitli, kas apzīmē baitu izmēru, vai virkni, piemēram, 10 MB, 1 GB utt.",
- "tusUploadsRetryCount": "Atkārtotu mēģinājumu skaits, kas jāveic, ja fragmenta augšupielāde neizdodas.",
- "userHomeBasePath": "Lietotāja mājas direktoriju bāzes ceļš",
- "userScopeGenerationPlaceholder": "Darbības joma tiks ģenerēta automātiski",
- "createUserHomeDirectory": "Izveidojiet lietotāja mājas direktoriju",
- "customStylesheet": "Pielāgota stila lapa",
- "defaultUserDescription": "Šie ir noklusējuma iestatījumi jaunajiem lietotājiem.",
- "disableExternalLinks": "Atspējot ārējās saites (izņemot dokumentāciju)",
- "disableUsedDiskPercentage": "Atspējot izmantotā diska procentuālās daļas grafiku",
- "documentation": "dokumentācija",
- "examples": "Piemēri",
- "executeOnShell": "Izpildīt uz čaulas",
- "executeOnShellDescription": "Pēc noklusējuma failu pārlūks izpilda komandas, tieši izsaucot to bināros failus. Ja vēlaties tās palaist čaulā (piemēram, Bash vai PowerShell), varat to definēt šeit ar nepieciešamajiem argumentiem un karodziņiem. Ja tas ir iestatīts, izpildītā komanda tiks pievienota kā arguments. Tas attiecas gan uz lietotāja komandām, gan notikumu piesaistes rīkiem.",
- "globalRules": "Šis ir globāls atļaušanas un aizliegšanas noteikumu kopums. Tie attiecas uz katru lietotāju. Katra lietotāja iestatījumos varat definēt konkrētus noteikumus, lai tos ignorētu.",
- "globalSettings": "Globālie iestatījumi",
- "hideDotfiles": "Slēpt punktfailus",
- "insertPath": "Ievietojiet ceļu",
- "insertRegex": "Ievietojiet regex izteiksmi",
- "instanceName": "Gadījuma nosaukums",
- "language": "Valoda",
- "lockPassword": "Neļaut lietotājam mainīt paroli",
- "newPassword": "Jūsu jaunā parole",
- "newPasswordConfirm": "Apstipriniet savu jauno paroli",
- "newUser": "Jauns lietotājs",
- "password": "Parole",
- "passwordUpdated": "Parole atjaunināta!",
- "path": "Ceļš",
- "perm": {
- "create": "Izveidojiet failus un direktorijus",
- "delete": "Dzēst failus un direktorijus",
- "download": "Lejupielādēt",
- "execute": "Izpildīt komandas",
- "modify": "Rediģēt failus",
- "rename": "Pārdēvēt vai pārvietot failus un direktorijus",
- "share": "Kopīgojiet failus"
- },
- "permissions": "Atļaujas",
- "permissionsHelp": "Varat iestatīt lietotāju kā administratoru vai izvēlēties atļaujas individuāli. Ja atlasīsiet “Administrators”, visas pārējās opcijas tiks automātiski atzīmētas. Lietotāju pārvaldība joprojām ir administratora privilēģija.\n",
- "profileSettings": "Profila iestatījumi",
- "redirectAfterCopyMove": "Pārvirzīt uz galapunktu pēc kopēšanas/pārvietošanas",
- "ruleExample1": "neļauj piekļūt jebkuram dotfile failam (piemēram, .git, .gitignore) katrā mapē.\n",
- "ruleExample2": "bloķē piekļuvi failam ar nosaukumu Caddyfile darbības jomas saknē.",
- "rules": "Noteikumi",
- "rulesHelp": "Šeit varat definēt atļaušanas un aizliegšanas noteikumu kopu šim konkrētajam lietotājam. Bloķētie faili netiks rādīti sarakstos, un lietotājs tiem nevarēs piekļūt. Mēs atbalstām regulārās izteiksmes un ceļus attiecībā pret lietotāja darbības jomu.\n",
- "scope": "Darbības joma",
- "setDateFormat": "Iestatiet precīzu datuma formātu",
- "settingsUpdated": "Iestatījumi atjaunināti!",
- "shareDuration": "Kopīgošanas ilgums",
- "shareManagement": "Kopīgošanas pārvaldība",
- "shareDeleted": "Kopīgojums izdzēsts!",
- "singleClick": "Failu un direktoriju atvēršanai izmantojiet vienus klikšķi",
- "themes": {
- "default": "Sistēmas noklusējums",
- "dark": "Tumša",
- "light": "Gaiša",
- "title": "Tēma"
- },
- "user": "Lietotājs",
- "userCommands": "Komandas",
- "userCommandsHelp": "Ar atstarpi atdalīts saraksts ar šim lietotājam pieejamajām komandām. Piemērs:\n",
- "userCreated": "Lietotājs izveidots!",
- "userDefaults": "Lietotāja noklusējuma iestatījumi",
- "userDeleted": "Lietotājs izdzēsts!",
- "userManagement": "Lietotāju pārvaldība",
- "userUpdated": "Lietotājs atjaunināts!",
- "username": "Lietotājvārds",
- "users": "Lietotāji",
- "currentPassword": "Esošā Parole"
- },
- "sidebar": {
- "help": "Palīdzība",
- "hugoNew": "Hugo Jauns",
- "login": "Pieteikties",
- "logout": "Atteikties",
- "myFiles": "Mani faili",
- "newFile": "Jauns fails",
- "newFolder": "Jauna mape",
- "preview": "Priekšskatījums",
- "settings": "Iestatījumi",
- "signup": "Reģistrēties",
- "siteSettings": "Vietnes iestatījumi"
- },
- "success": {
- "linkCopied": "Saite nokopēta!"
- },
- "time": {
- "days": "Dienas",
- "hours": "Stundas",
- "minutes": "Minūtes",
- "seconds": "Sekundes",
- "unit": "Laika vienība"
- }
-}
diff --git a/frontend/src/i18n/nl-be.json b/frontend/src/i18n/nl-be.json
index d9f76406c7..f9fb8fd8b8 100644
--- a/frontend/src/i18n/nl-be.json
+++ b/frontend/src/i18n/nl-be.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Bestand downloaden",
@@ -161,7 +165,19 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Afbeeldingen",
diff --git a/frontend/src/i18n/nl.json b/frontend/src/i18n/nl.json
index 70e9b2446c..331eb3063f 100644
--- a/frontend/src/i18n/nl.json
+++ b/frontend/src/i18n/nl.json
@@ -42,13 +42,17 @@
"update": "Bijwerken",
"upload": "Uploaden",
"openFile": "Bestand openen",
- "openDirect": "View raw",
+ "openDirect": "Raw weergeven",
"discardChanges": "Weggooien",
"stopSearch": "Stoppen met zoeken",
"saveChanges": "Wijzigingen opslaan",
"editAsText": "Als tekst bewerken",
"increaseFontSize": "Lettertype vergroten",
- "decreaseFontSize": "Lettertype verkleinen"
+ "decreaseFontSize": "Lettertype verkleinen",
+ "overrideAll": "Alle bestanden in doelmap vervangen",
+ "skipAll": "Alle conflicterende bestanden overslaan",
+ "renameAll": "Alle bestanden hernoemen (een kopie maken)",
+ "singleDecision": "Voor elk conflicterend bestand besluiten"
},
"download": {
"downloadFile": "Bestand downloaden",
@@ -161,7 +165,19 @@
"uploadMessage": "Kies een optie bij de upload.",
"optionalPassword": "Optioneel wachtwoord",
"resolution": "Resolutie",
- "discardEditorChanges": "Weet u zeker dat u de door u aangebrachte wijzigingen wilt weggooien?"
+ "discardEditorChanges": "Weet u zeker dat u de door u aangebrachte wijzigingen wilt weggooien?",
+ "replaceOrSkip": "Bestanden vervangen of overslaan",
+ "resolveConflict": "Welke bestanden wilt u behouden?",
+ "singleConflictResolve": "Als u beide versies selecteert, wordt er een nummer toegevoegd aan de naam van het gekopieerde bestand.",
+ "fastConflictResolve": "De doelmap daar bevat {count} bestanden met dezelfde naam.",
+ "uploadingFiles": "Bestanden uploaden",
+ "filesInOrigin": "Bestanden in origineel",
+ "filesInDest": "Bestanden in bestemming",
+ "override": "Overschrijven",
+ "skip": "Overslaan",
+ "forbiddenError": "Verboden Fout",
+ "currentPassword": "Uw wachtwoord",
+ "currentPasswordMessage": "Voer uw wachtwoord in om deze actie te valideren."
},
"search": {
"images": "Afbeeldingen",
diff --git a/frontend/src/i18n/no.json b/frontend/src/i18n/no.json
index 4c9fb225ee..cd77273984 100644
--- a/frontend/src/i18n/no.json
+++ b/frontend/src/i18n/no.json
@@ -48,7 +48,11 @@
"saveChanges": "Lagre Endringane ",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Nedlast filen",
@@ -161,7 +165,19 @@
"uploadMessage": "Velg et alternativ for opplasting.",
"optionalPassword": "Valgfritt passord",
"resolution": "Oppløysning",
- "discardEditorChanges": "Er du sikker på at du vil forkaste endringene du har gjort?"
+ "discardEditorChanges": "Er du sikker på at du vil forkaste endringene du har gjort?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Bilde",
diff --git a/frontend/src/i18n/pl.json b/frontend/src/i18n/pl.json
index 9f9d3a29d7..f613dd5173 100644
--- a/frontend/src/i18n/pl.json
+++ b/frontend/src/i18n/pl.json
@@ -42,13 +42,17 @@
"update": "Aktualizuj",
"upload": "Wyślij",
"openFile": "Otwórz plik",
- "openDirect": "View raw",
+ "openDirect": "Otwórz bezpośrednio",
"discardChanges": "Odrzuć",
"stopSearch": "Zatrzymaj wyszukiwanie",
"saveChanges": "Zapisz zmiany",
"editAsText": "Edytuj jako tekst",
"increaseFontSize": "Zwiększ rozmiar czcionki",
- "decreaseFontSize": "Zmniejsz rozmiar czcionki"
+ "decreaseFontSize": "Zmniejsz rozmiar czcionki",
+ "overrideAll": "Zastąp wszystkie pliki w folderze docelowym",
+ "skipAll": "Pomiń wszystkie pliki powodujące konflikty",
+ "renameAll": "Zmień nazwy wszystkich plików (utwórz kopię)",
+ "singleDecision": "Podejmij decyzję dla każdego pliku powodującego konflikt"
},
"download": {
"downloadFile": "Pobierz plik",
@@ -161,7 +165,19 @@
"uploadMessage": "Wybierz opcję przesyłania.",
"optionalPassword": "Opcjonalne hasło",
"resolution": "Rozdzielczość",
- "discardEditorChanges": "Czy na pewno chcesz odrzucić wprowadzone zmiany?"
+ "discardEditorChanges": "Czy na pewno chcesz odrzucić wprowadzone zmiany?",
+ "replaceOrSkip": "Zastąp lub pomiń pliki",
+ "resolveConflict": "Które pliki chcesz zachować?",
+ "singleConflictResolve": "Jeśli wybierzesz obie wersje, do nazwy kopiowanego pliku zostanie dodany numer.",
+ "fastConflictResolve": "W folderze docelowym liczba plików o tej samej nazwie to {count}.",
+ "uploadingFiles": "Wysyłanie plików",
+ "filesInOrigin": "Pliki w miejscu pochodzenia",
+ "filesInDest": "Pliki w miejscu docelowym",
+ "override": "Zastąp",
+ "skip": "Pomiń",
+ "forbiddenError": "Błąd zabronionego dostępu",
+ "currentPassword": "Twoje hasło",
+ "currentPasswordMessage": "Wpisz swoje hasło, aby zatwierdzić tę czynność."
},
"search": {
"images": "Obrazy",
diff --git a/frontend/src/i18n/pt-br.json b/frontend/src/i18n/pt-br.json
index 5f36c337ea..6b9c90048e 100644
--- a/frontend/src/i18n/pt-br.json
+++ b/frontend/src/i18n/pt-br.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Baixar arquivo",
@@ -161,7 +165,19 @@
"uploadMessage": "Selecione uma opção para enviar.",
"optionalPassword": "Senha opcional",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Imagens",
diff --git a/frontend/src/i18n/pt-pt.json b/frontend/src/i18n/pt-pt.json
new file mode 100644
index 0000000000..f7b8e52446
--- /dev/null
+++ b/frontend/src/i18n/pt-pt.json
@@ -0,0 +1,306 @@
+{
+ "buttons": {
+ "cancel": "Cancelar",
+ "clear": "Limpar",
+ "close": "Fechar",
+ "continue": "Continuar",
+ "copy": "Copiar",
+ "copyFile": "Copiar ficheiro",
+ "copyToClipboard": "Copiar para a área de transferência",
+ "copyDownloadLinkToClipboard": "Copiar link do download para a área de transferência",
+ "create": "Criar",
+ "delete": "Eliminar",
+ "download": "Descarregar",
+ "file": "Ficheiro",
+ "folder": "Pasta",
+ "fullScreen": "Alternar ecrã inteiro",
+ "hideDotfiles": "Ocultar ficheiros começados por ponto",
+ "info": "Info",
+ "more": "Mais",
+ "move": "Mover",
+ "moveFile": "Mover ficheiro",
+ "new": "Novo",
+ "next": "Seguinte",
+ "ok": "OK",
+ "permalink": "Obter link permanente",
+ "previous": "Anterior",
+ "preview": "Pré-visualizar",
+ "publish": "Publicar",
+ "rename": "Mudar o nome",
+ "replace": "Substituir",
+ "reportIssue": "Reportar problema",
+ "save": "Guardar",
+ "schedule": "Agendar",
+ "search": "Pesquisar",
+ "select": "Seleccionar",
+ "selectMultiple": "Seleccionar vários",
+ "share": "Partilhar",
+ "shell": "Alternar shell",
+ "submit": "Enviar",
+ "switchView": "Alterar vista",
+ "toggleSidebar": "Alternar barra lateral",
+ "update": "Actualizar",
+ "upload": "Enviar",
+ "openFile": "Abrir ficheiro",
+ "openDirect": "Ver raw",
+ "discardChanges": "Descartar",
+ "stopSearch": "Parar a procura",
+ "saveChanges": "Guardar alterações",
+ "editAsText": "Editar como Texto",
+ "increaseFontSize": "Aumentar o tamanho da letra",
+ "decreaseFontSize": "Diminuir o tamanho da letra",
+ "overrideAll": "Substituir todos os ficheiros na pasta de destino",
+ "skipAll": "Ignorar todos os ficheiros em conflito",
+ "renameAll": "Mudar o nome a todos os ficheiros (criar uma cópia)",
+ "singleDecision": "Decidir para cada ficheiro em conflito"
+ },
+ "download": {
+ "downloadFile": "Descarregar Ficheiro",
+ "downloadFolder": "Descarregar Pasta",
+ "downloadSelected": "Descarregar Seleccionados"
+ },
+ "upload": {
+ "abortUpload": "Tem a certeza que quer abortar?"
+ },
+ "errors": {
+ "forbidden": "Não tem permissão para aceder a isto.",
+ "internal": "Algo correu mal.",
+ "notFound": "Esta localização não pôde ser alcançada.",
+ "connection": "Este servidor não pôde ser alcançado."
+ },
+ "files": {
+ "body": "Corpo",
+ "closePreview": "Fechar pré-visualização",
+ "files": "Ficheiros",
+ "folders": "Pastas",
+ "home": "Início",
+ "lastModified": "Última modificação",
+ "loading": "A carregar...",
+ "lonely": "Sinto-me sózinho...",
+ "metadata": "Metadados",
+ "multipleSelectionEnabled": "Selecção múltipla activada",
+ "name": "Nome",
+ "size": "Tamanho",
+ "sortByLastModified": "Ordenar pela última modificação",
+ "sortByName": "Ordenar pelo nome",
+ "sortBySize": "Ordenar pelo tamanho",
+ "noPreview": "Pré-visualização não disponível para este ficheiro.",
+ "csvTooLarge": "O ficheiro CSV é demasiado grande para pré-visualizar (>5MB). Por favor, descarregue-o para visualizá-lo.",
+ "csvLoadFailed": "Falha ao carregar o ficheiro CSV.",
+ "showingRows": "A mostrar {count} linha(s)",
+ "columnSeparator": "Separador de Coluna",
+ "csvSeparators": {
+ "comma": "Vírgula (,)",
+ "semicolon": "Ponto e vírgula (;)",
+ "both": "Ambos (,) e (;)"
+ },
+ "fileEncoding": "Codificação do Ficheiro"
+ },
+ "help": {
+ "click": "seleccionar ficheiro ou pasta",
+ "ctrl": {
+ "click": "seleccionar vários ficheiros e pastas",
+ "f": "opens search",
+ "s": "guarda um ficheiro ou descarrega a pasta onde estiver"
+ },
+ "del": "elimina os itens seleccionados",
+ "doubleClick": "abre um ficheiro ou pasta",
+ "esc": "limpa a selecção e/ou fecha o pedido",
+ "f1": "esta informação",
+ "f2": "muda o nome ao ficheiro",
+ "help": "Ajuda"
+ },
+ "login": {
+ "createAnAccount": "Criar uma conta",
+ "loginInstead": "Já tenho uma conta",
+ "password": "Palavra-passe",
+ "passwordConfirm": "Confirmação da Palavra-passe",
+ "passwordsDontMatch": "As palavras-passe não coincidem",
+ "signup": "Registar",
+ "submit": "Entrar",
+ "username": "Nome de utilizador",
+ "usernameTaken": "O nome de utilizador já existe",
+ "wrongCredentials": "Credenciais erradas",
+ "passwordTooShort": "A palavra-passe tem de ter pelo menos {min} caracteres",
+ "logout_reasons": {
+ "inactivity": "Foi terminada a sessão por inactividade."
+ }
+ },
+ "permanent": "Permanente",
+ "prompts": {
+ "copy": "Copiar",
+ "copyMessage": "Escolha a localização para copiar os ficheiros:",
+ "currentlyNavigating": "Actualmente a navegar em:",
+ "deleteMessageMultiple": "Tem a certeza que quer eliminar {count} ficheiro(s)?",
+ "deleteMessageSingle": "Tem a certeza que quer eliminar este ficheiro/pasta?",
+ "deleteMessageShare": "Tem a certeza que quer eliminar esta partilha ({path})?",
+ "deleteUser": "Tem a certeza que quer eliminar este utilizador?",
+ "deleteTitle": "Eliminar ficheiros",
+ "displayName": "Nome a mostrar:",
+ "download": "Descarregar ficheiros",
+ "downloadMessage": "Escolha o formato que pretende descarregar.",
+ "error": "Algo correu mal.",
+ "fileInfo": "Informação do Ficheiro",
+ "filesSelected": "{count} ficheiro(s) seleccionado(s)",
+ "lastModified": "última modificação",
+ "move": "Mover",
+ "moveMessage": "Escolha uma nova casa para o(s) seu(s) ficheiro(s)/pasta(s):",
+ "newArchetype": "Escolha um novo post baseado no archetype. O seu ficheiro irá criado no conteúdo da pasta.",
+ "newDir": "Nova pasta",
+ "newDirMessage": "Nomeie a sua nova pasta.",
+ "newFile": "Novo ficheiro",
+ "newFileMessage": "Nomeie o seu novo ficheiro.",
+ "numberDirs": "Número de pastas",
+ "numberFiles": "Número de ficheiros",
+ "rename": "Mudar o nome",
+ "renameMessage": "Introduza um novo nome para",
+ "replace": "Substituir",
+ "replaceMessage": "Um dos ficheiros que está a tentar enviar tem um nome em conflito. Quer ignorar este ficheiro e continuar a enviar ou substituir o existente?\none?\n",
+ "schedule": "Agendar",
+ "scheduleMessage": "Escolha a data e hora para agendar a autenticação desta publicação.",
+ "show": "Mostrar",
+ "size": "Tamanho",
+ "upload": "Enviar",
+ "uploadFiles": "A enviar {files} ficheiros...",
+ "uploadMessage": "Seleccione uma opção para enviar.",
+ "optionalPassword": "Palavra-passe opcional",
+ "resolution": "Resolução",
+ "discardEditorChanges": "Tem a certeza que quer descartar as alterações que fez?",
+ "replaceOrSkip": "Substituir ou ignorar ficheiros",
+ "resolveConflict": "Que ficheiros quer manter?",
+ "singleConflictResolve": "Se seleccionar ambas as versões, um número será adicionar ao nome do ficheiro copiado.",
+ "fastConflictResolve": "Na pasta de destino há {count} ficheiros com o mesmo nome.",
+ "uploadingFiles": "A enviar ficheiros",
+ "filesInOrigin": "Ficheiros na origem",
+ "filesInDest": "Ficheiros no destino",
+ "override": "Substituir",
+ "skip": "Ignorar",
+ "forbiddenError": "Erro de Proibido",
+ "currentPassword": "A sua palavra-passe",
+ "currentPasswordMessage": "Insira a sua palavra-passe para validar esta acção."
+ },
+ "search": {
+ "images": "Imagens",
+ "music": "Música",
+ "pdf": "PDF",
+ "pressToSearch": "Prima Enter para procurar...",
+ "search": "Procurar...",
+ "typeToSearch": "Digite para procurar...",
+ "types": "Tipos",
+ "video": "Vídeo"
+ },
+ "settings": {
+ "aceEditorTheme": "Editor de temas audaz",
+ "admin": "Admin",
+ "administrator": "Administrador",
+ "allowCommands": "Executar comandos",
+ "allowEdit": "Editar, mudar o nome e eliminar ficheiros ou pastas",
+ "allowNew": "Criar novos ficheiros e pastas",
+ "allowPublish": "Publicar novas publicações e páginas",
+ "allowSignup": "Permitir que utilizadores se registem",
+ "hideLoginButton": "Ocultar o botão de início de sessão nas páginas públicas",
+ "avoidChanges": "(deixe em branco para evitar alterações)",
+ "branding": "Branding",
+ "brandingDirectoryPath": "Caminho da pasta da marca",
+ "brandingHelp": "Pode personalizar a aparência da instânciado seu File Browser\nao alterar o seu nome, alterar o logótipo, adicionar estilos personalizados e até mesmo desactivar links externos para o Github.\nPara mais informação acerca de personalização de marca, por favor, veja {0}.",
+ "changePassword": "Alterar Palavra-passe",
+ "commandRunner": "Executador de comandos",
+ "commandRunnerHelp": "Aqui pode definir comandos que são executados nos eventos nomeados. Tem de escrever um por linha. A variável de ambiente {0} e {1} irá estar disponível, sendo {0} relativo a {1}.\nPara mais informação acerca desta funcionalidade e variáveis de ambiente disponíveis, por favor, leia o {2}.",
+ "commandsUpdated": "Comandos actualizados!",
+ "createUserDir": "Criar automaticamente a pasta da casa do utilizador quando adicionar um novo utilizador",
+ "minimumPasswordLength": "Comprimento mínimo da palavra-passe",
+ "tusUploads": "Envios aos Bocados",
+ "tusUploadsHelp": "O File Browser suporta envio de ficheiros aos bocados, permitindo a criação de envios eficiente, de confiança e retomáveis de ficheiros aos bocados mesmo em redes instáveis.",
+ "tusUploadsChunkSize": "Indica o tamanho máximo do pedido (envios directos serão utilizadas para envios pequenos). Pode introduzir um valor inteiro para tamanhos de byte ou uma cadeia como 10MB, 1GB, etc.",
+ "tusUploadsRetryCount": "Número de tentativas a realizar se um bocado falha ao ser enviado.",
+ "userHomeBasePath": "O caminho base para a pasta da casa do utilizador",
+ "userScopeGenerationPlaceholder": "O escopo será gerado automaticamente",
+ "createUserHomeDirectory": "Criar pasta da casa do utilizador",
+ "customStylesheet": "Folha de estilo Personalizada",
+ "defaultUserDescription": "Estes são as definições por defeito para novos utilizadores",
+ "disableExternalLinks": "Eliminar links externos (excepto documentação)",
+ "disableUsedDiskPercentage": "Desactivar gráfico de percentagem de uso de disco",
+ "documentation": "documentação\ndocumentation",
+ "examples": "Exemplos",
+ "executeOnShell": "Executar na shell",
+ "executeOnShellDescription": "Por defeito, o File Browser executa os comandos ao chamar os seus binários\ndirectamenta. Se quiser executá-los mesmo na shell (como o Bash ou PoweShell), pode defini-lo aqui com os argumentos pedidos e flags. Se definido, o comando que executar será acrescentado como um argumento. Isto aplica-se a ambos comandos de utilizador e hooks de eventos.",
+ "globalRules": "Esta é um conjunto global de regras de permissão e negação. Elas aplicam-se a cada utilizador. Pode definir regras especificas em cada definições de utilizador para contornar estas.",
+ "globalSettings": "Definições Globais",
+ "hideDotfiles": "Ocultar ficheiros começados por ponto",
+ "insertPath": "Introduza o caminho",
+ "insertRegex": "Introduza expressão regex",
+ "instanceName": "Nome da instância",
+ "language": "Idioma",
+ "lockPassword": "Impedir o utilizador de alterar a palavra-passe",
+ "newPassword": "A sua nova palavra-passe",
+ "newPasswordConfirm": "Confirmar a sua palavra-passe",
+ "newUser": "Novo Utilizador",
+ "password": "Palavra-passe",
+ "passwordUpdated": "Palavras-passe não coincidem!",
+ "path": "Caminho",
+ "perm": {
+ "create": "Criar ficheiros e pastas",
+ "delete": "Eliminar ficheiros e pastas",
+ "download": "Descarregar",
+ "execute": "Executar comandos",
+ "modify": "Editar ficheiros",
+ "rename": "Mudar o nome ou mover ficheiros e pastas",
+ "share": "Ficheiros partilhados"
+ },
+ "permissions": "Permissões",
+ "permissionsHelp": "Pode definir um utilizador um administrador ou escolher as permissões individualmente. Se escolher \"Administrador\", todas as outras opções serão automaticamente marcadas. A gestão de utilizadores continua a ser um privilégio de um administrador.\n",
+ "profileSettings": "Definições de Perfil",
+ "redirectAfterCopyMove": "Redireccionar para o destino depois de copiar/mover",
+ "ruleExample1": "impede o acesso a qualquer ficheiro começado por ponto (como .git ou .gitignore) em cada pasta.\n",
+ "ruleExample2": "bloqueia o acesso ao ficheiro chamado Caddyfile na raíz de um escopo.",
+ "rules": "Regras",
+ "rulesHelp": "Aqui pode definir um conjunto de regras de permissão e negação para este utilizador especifico. Os ficheiros bloqueados não serão mostrados nas listas e não são acessíveis ao utilizador. Suportamos regex e caminhos relativos ao escopo do utilizador.\n",
+ "scope": "Escopo",
+ "setDateFormat": "Definir formato exacto da data",
+ "settingsUpdated": "Definições actualizadas!",
+ "shareDuration": "Duração da Partilha",
+ "shareManagement": "Gestão de Partilhas",
+ "shareDeleted": "Partilha eliminada!",
+ "singleClick": "Utilizar cliques únicos para abrir ficheiros e pastas",
+ "themes": {
+ "default": "Predefinição do sistema",
+ "dark": "Escuro",
+ "light": "Claro",
+ "title": "Tema"
+ },
+ "user": "Utilizador",
+ "userCommands": "Comandos",
+ "userCommandsHelp": "Uma lista separada por espaços com os comandos disponíveis para este utilizador. Exemplo:\n",
+ "userCreated": "Utilizador criado!",
+ "userDefaults": "Definições de utilizador por defeito",
+ "userDeleted": "Utilizador eliminado!",
+ "userManagement": "Gestão de Utilizadores",
+ "userUpdated": "Utilizador actualizado!",
+ "username": "Nome de utilizador",
+ "users": "Utilizadores",
+ "currentPassword": "A Sua Palavra-passe Actual"
+ },
+ "sidebar": {
+ "help": "Ajuda",
+ "hugoNew": "Hugo New",
+ "login": "Iniciar sessão",
+ "logout": "Sair",
+ "myFiles": "Os meus ficheiros",
+ "newFile": "Novo ficheiro",
+ "newFolder": "Nova pasta",
+ "preview": "Pré-visualizar",
+ "settings": "Definições",
+ "signup": "Registar",
+ "siteSettings": "Definições do Site"
+ },
+ "success": {
+ "linkCopied": "Link copiado!"
+ },
+ "time": {
+ "days": "Dias",
+ "hours": "Horas",
+ "minutes": "Minutos",
+ "seconds": "Segundos",
+ "unit": "Unidade de Tempo"
+ }
+}
diff --git a/frontend/src/i18n/pt.json b/frontend/src/i18n/pt.json
index 0e50052255..ef5a4cf734 100644
--- a/frontend/src/i18n/pt.json
+++ b/frontend/src/i18n/pt.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Descarregar ficheiro",
@@ -161,7 +165,19 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Imagens",
diff --git a/frontend/src/i18n/ro.json b/frontend/src/i18n/ro.json
index 5495e884d8..052025455d 100644
--- a/frontend/src/i18n/ro.json
+++ b/frontend/src/i18n/ro.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Descarcă fișier",
@@ -161,7 +165,19 @@
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Imagini",
diff --git a/frontend/src/i18n/ru.json b/frontend/src/i18n/ru.json
index 05514e4a64..4ff2658786 100644
--- a/frontend/src/i18n/ru.json
+++ b/frontend/src/i18n/ru.json
@@ -48,7 +48,11 @@
"saveChanges": "Сохранить",
"editAsText": "Редактировать как текст",
"increaseFontSize": "Увеличить размер шрифта",
- "decreaseFontSize": "Уменьшить размер шрифта"
+ "decreaseFontSize": "Уменьшить размер шрифта",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Скачать файл",
@@ -161,7 +165,19 @@
"uploadMessage": "Выберите вариант для загрузки.",
"optionalPassword": "Необязательный пароль",
"resolution": "Разрешение",
- "discardEditorChanges": "Вы действительно желаете отменить ваши правки?"
+ "discardEditorChanges": "Вы действительно желаете отменить ваши правки?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Изображения",
diff --git a/frontend/src/i18n/sk.json b/frontend/src/i18n/sk.json
index 225a4f748e..c43b0816d0 100644
--- a/frontend/src/i18n/sk.json
+++ b/frontend/src/i18n/sk.json
@@ -48,7 +48,11 @@
"saveChanges": "Uložiť zmeny",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Stiahnuť súbor",
@@ -161,7 +165,19 @@
"uploadMessage": "Zvoľte možnosť nahrávania.",
"optionalPassword": "Voliteľné heslo",
"resolution": "Rozlíšenie",
- "discardEditorChanges": "Naozaj chcete zahodiť vykonané zmeny?"
+ "discardEditorChanges": "Naozaj chcete zahodiť vykonané zmeny?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Obrázky",
diff --git a/frontend/src/i18n/sv-se.json b/frontend/src/i18n/sv-se.json
index 5542c7159f..5102f9b066 100644
--- a/frontend/src/i18n/sv-se.json
+++ b/frontend/src/i18n/sv-se.json
@@ -48,7 +48,11 @@
"saveChanges": "Spara ändringar",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Ladda ner fil",
@@ -161,7 +165,19 @@
"uploadMessage": "Välj ett alternativ att ladda upp.",
"optionalPassword": "Valfritt lösenord",
"resolution": "Upplösning",
- "discardEditorChanges": "Är du säker på att du vill förkasta ändringarna du gjort?"
+ "discardEditorChanges": "Är du säker på att du vill förkasta ändringarna du gjort?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Bilder",
diff --git a/frontend/src/i18n/tr.json b/frontend/src/i18n/tr.json
index 5ff72853e6..e0608217c4 100644
--- a/frontend/src/i18n/tr.json
+++ b/frontend/src/i18n/tr.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Dosyayı indir",
@@ -161,7 +165,19 @@
"uploadMessage": "Yüklemek için bir seçenek belirleyin.",
"optionalPassword": "İsteğe bağlı şifre",
"resolution": "Resolution",
- "discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
+ "discardEditorChanges": "Are you sure you wish to discard the changes you've made?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Görseller",
diff --git a/frontend/src/i18n/uk.json b/frontend/src/i18n/uk.json
index ccaf9a41f0..0eea735704 100644
--- a/frontend/src/i18n/uk.json
+++ b/frontend/src/i18n/uk.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Завантажити файл",
@@ -161,7 +165,19 @@
"uploadMessage": "Виберіть варіант для вивантаження.",
"optionalPassword": "Необов'язковий пароль",
"resolution": "Розширення",
- "discardEditorChanges": "Чи дійсно ви хочете скасувати поточні зміни?"
+ "discardEditorChanges": "Чи дійсно ви хочете скасувати поточні зміни?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Зображення",
diff --git a/frontend/src/i18n/vi.json b/frontend/src/i18n/vi.json
index ef3aeab580..3b84ab4625 100644
--- a/frontend/src/i18n/vi.json
+++ b/frontend/src/i18n/vi.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "Tải xuống tệp tin",
@@ -161,7 +165,19 @@
"uploadMessage": "Chọn một tùy chọn để tải lên.",
"optionalPassword": "Mật khẩu tùy chọn",
"resolution": "Độ phân giải",
- "discardEditorChanges": "Bạn có chắc chắn muốn hủy bỏ các thay đổi đã thực hiện không?"
+ "discardEditorChanges": "Bạn có chắc chắn muốn hủy bỏ các thay đổi đã thực hiện không?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "Hình ảnh",
diff --git a/frontend/src/i18n/zh-cn.json b/frontend/src/i18n/zh-cn.json
index 4a16eef972..9d136737a1 100644
--- a/frontend/src/i18n/zh-cn.json
+++ b/frontend/src/i18n/zh-cn.json
@@ -48,7 +48,11 @@
"saveChanges": "保存更改",
"editAsText": "以文本形式编辑",
"increaseFontSize": "增大字体大小",
- "decreaseFontSize": "减小字体大小"
+ "decreaseFontSize": "减小字体大小",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "下载文件",
@@ -161,7 +165,19 @@
"uploadMessage": "选择上传选项。",
"optionalPassword": "密码(选填,不填即无密码)",
"resolution": "分辨率",
- "discardEditorChanges": "你确定要放弃所做的更改吗?"
+ "discardEditorChanges": "你确定要放弃所做的更改吗?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "图像",
diff --git a/frontend/src/i18n/zh-tw.json b/frontend/src/i18n/zh-tw.json
index 61f264f38e..edced1fb4a 100644
--- a/frontend/src/i18n/zh-tw.json
+++ b/frontend/src/i18n/zh-tw.json
@@ -48,7 +48,11 @@
"saveChanges": "Save changes",
"editAsText": "Edit as Text",
"increaseFontSize": "Increase font size",
- "decreaseFontSize": "Decrease font size"
+ "decreaseFontSize": "Decrease font size",
+ "overrideAll": "Replace all files in destination folder",
+ "skipAll": "Skip all conflicting files",
+ "renameAll": "Rename all files (create a copy)",
+ "singleDecision": "Decide for each conflicting file"
},
"download": {
"downloadFile": "下載檔案",
@@ -161,7 +165,19 @@
"uploadMessage": "選擇上傳項。",
"optionalPassword": "密碼(選填,不填即無密碼)",
"resolution": "解析度",
- "discardEditorChanges": "你確定要放棄所做的變更嗎?"
+ "discardEditorChanges": "你確定要放棄所做的變更嗎?",
+ "replaceOrSkip": "Replace or skip files",
+ "resolveConflict": "Which files do you want to keep?",
+ "singleConflictResolve": "If you select both versions, a number will be added to the name of the copied file.",
+ "fastConflictResolve": "The destination folder there are {count} files with same name.",
+ "uploadingFiles": "Uploading files",
+ "filesInOrigin": "Files in origin",
+ "filesInDest": "Files in destination",
+ "override": "Overwrite",
+ "skip": "Skip",
+ "forbiddenError": "Forbidden Error",
+ "currentPassword": "Your password",
+ "currentPasswordMessage": "Enter your password to validate this action."
},
"search": {
"images": "影像",
diff --git a/frontend/src/main.ts b/frontend/src/main.ts
index 42f4420564..f6b7ac78c5 100644
--- a/frontend/src/main.ts
+++ b/frontend/src/main.ts
@@ -2,7 +2,6 @@ import { disableExternal } from "@/utils/constants";
import { createApp } from "vue";
import VueNumberInput from "@chenfengyuan/vue-number-input";
import VueLazyload from "vue-lazyload";
-import { createVfm } from "vue-final-modal";
import Toast, { POSITION, useToast } from "vue-toastification";
import type {
ToastOptions,
@@ -27,7 +26,6 @@ dayjs.extend(relativeTime);
dayjs.extend(duration);
const pinia = createPinia(router);
-const vfm = createVfm();
const app = createApp(App);
@@ -39,7 +37,6 @@ app.use(Toast, {
newestOnTop: true,
} satisfies PluginOptions);
-app.use(vfm);
app.use(i18n);
app.use(pinia);
app.use(router);
diff --git a/frontend/src/stores/layout.ts b/frontend/src/stores/layout.ts
index 372fca06e8..fbd6d99f6a 100644
--- a/frontend/src/stores/layout.ts
+++ b/frontend/src/stores/layout.ts
@@ -76,7 +76,7 @@ export const useLayoutStore = defineStore("layout", {
});
},
closeHovers() {
- this.prompts.shift()?.close?.();
+ this.prompts.pop()?.close?.();
},
// easily reset state using `$reset`
clearLayout() {
diff --git a/frontend/src/types/file.d.ts b/frontend/src/types/file.d.ts
index 6b9b6372cd..e6511b3919 100644
--- a/frontend/src/types/file.d.ts
+++ b/frontend/src/types/file.d.ts
@@ -52,6 +52,8 @@ type DownloadFormat =
interface ClipItem {
from: string;
name: string;
+ size?: number;
+ modified?: string;
}
interface BreadCrumb {
@@ -59,6 +61,19 @@ interface BreadCrumb {
url: string;
}
+interface ConflictingItem {
+ lastModified: number | string | undefined;
+ size: number | undefined;
+}
+
+interface ConflictingResource {
+ index: number;
+ name: string;
+ origin: ConflictingItem;
+ dest: ConflictingItem;
+ checked: Array<"origin" | "dest">;
+}
+
interface CsvData {
headers: string[];
rows: string[][];
diff --git a/frontend/src/types/global.d.ts b/frontend/src/types/global.d.ts
index 5475c908fd..287388f0ec 100644
--- a/frontend/src/types/global.d.ts
+++ b/frontend/src/types/global.d.ts
@@ -10,4 +10,8 @@ declare global {
// TODO: no idea what the exact type is
__vue__: any;
}
+
+ interface HTMLElement {
+ clickOutsideEvent?: (event: Event) => void;
+ }
}
diff --git a/frontend/src/types/upload.d.ts b/frontend/src/types/upload.d.ts
index 4bad9e0650..5e5716acb1 100644
--- a/frontend/src/types/upload.d.ts
+++ b/frontend/src/types/upload.d.ts
@@ -17,6 +17,7 @@ interface UploadEntry {
isDir: boolean;
fullPath?: string;
file?: File;
+ overwrite?: boolean;
}
type UploadList = UploadEntry[];
diff --git a/frontend/src/utils/encodings.ts b/frontend/src/utils/encodings.ts
index 80f1e21975..9be1017a4e 100644
--- a/frontend/src/utils/encodings.ts
+++ b/frontend/src/utils/encodings.ts
@@ -1,4 +1,5 @@
export const availableEncodings = [
+ // encodings
"utf-8",
"ibm866",
"iso-8859-2",
@@ -37,6 +38,178 @@ export const availableEncodings = [
"euc-kr",
"utf-16be",
"utf-16le",
+ // label encodings
+ "unicode-1-1-utf-8",
+ "utf8",
+ "866",
+ "cp866",
+ "csibm866",
+ "csisolatin2",
+ "iso-ir-101",
+ "iso8859-2",
+ "iso88592",
+ "iso_8859-2",
+ "iso_8859-2:1987",
+ "l2",
+ "latin2",
+ "csisolatin3",
+ "iso-ir-109",
+ "iso8859-3",
+ "iso88593",
+ "iso_8859-3",
+ "iso_8859-3:1988",
+ "l3",
+ "latin3",
+ "csisolatin4",
+ "iso-ir-110",
+ "iso8859-4",
+ "iso88594",
+ "iso_8859-4",
+ "iso_8859-4:1988",
+ "l4",
+ "latin4",
+ "csisolatincyrillic",
+ "cyrillic",
+ "iso-ir-144",
+ "iso88595",
+ "iso_8859-5",
+ "iso_8859-5:1988",
+ "arabic",
+ "asmo-708",
+ "csiso88596e",
+ "csiso88596i",
+ "csisolatinarabic",
+ "ecma-114",
+ "iso-8859-6-e",
+ "iso-8859-6-i",
+ "iso-ir-127",
+ "iso8859-6",
+ "iso88596",
+ "iso_8859-6",
+ "iso_8859-6:1987",
+ "csisolatingreek",
+ "ecma-118",
+ "elot_928",
+ "greek",
+ "greek8",
+ "iso-ir-126",
+ "iso8859-7",
+ "iso88597",
+ "iso_8859-7",
+ "iso_8859-7:1987",
+ "sun_eu_greek",
+ "csiso88598e",
+ "csisolatinhebrew",
+ "hebrew",
+ "iso-8859-8-e",
+ "iso-ir-138",
+ "iso8859-8",
+ "iso88598",
+ "iso_8859-8",
+ "iso_8859-8:1988",
+ "visual",
+ "csiso88598i",
+ "logical",
+ "csisolatin6",
+ "iso-ir-157",
+ "iso8859-10",
+ "iso885910",
+ "l6",
+ "latin6",
+ "iso8859-13",
+ "iso885913",
+ "iso8859-14",
+ "iso885914",
+ "csisolatin9",
+ "iso8859-15",
+ "iso885915",
+ "l9",
+ "latin9",
+ "cskoi8r",
+ "koi",
+ "koi8",
+ "koi8_r",
+ "csmacintosh",
+ "mac",
+ "x-mac-roman",
+ "dos-874",
+ "iso-8859-11",
+ "iso8859-11",
+ "iso885911",
+ "tis-620",
+ "cp1250",
+ "x-cp1250",
+ "cp1251",
+ "x-cp1251",
+ "ansi_x3.4-1968",
+ "ascii",
+ "cp1252",
+ "cp819",
+ "csisolatin1",
+ "ibm819",
+ "iso-8859-1",
+ "iso-ir-100",
+ "iso8859-1",
+ "iso88591",
+ "iso_8859-1",
+ "iso_8859-1:1987",
+ "l1",
+ "latin1",
+ "us-ascii",
+ "x-cp1252",
+ "cp1253",
+ "x-cp1253",
+ "cp1254",
+ "csisolatin5",
+ "iso-8859-9",
+ "iso-ir-148",
+ "iso8859-9",
+ "iso88599",
+ "iso_8859-9",
+ "iso_8859-9:1989",
+ "l5",
+ "latin5",
+ "x-cp1254",
+ "cp1255",
+ "x-cp1255",
+ "cp1256",
+ "x-cp1256",
+ "cp1257",
+ "x-cp1257",
+ "cp1258",
+ "x-cp1258",
+ "x-mac-ukrainian",
+ "chinese",
+ "csgb2312",
+ "csiso58gb231280",
+ "gb2312",
+ "gb_2312",
+ "gb_2312-80",
+ "iso-ir-58",
+ "x-gbk",
+ "big5-hkscs",
+ "cn-big5",
+ "csbig5",
+ "x-x-big5",
+ "cseucpkdfmtjapanese",
+ "x-euc-jp",
+ "csiso2022jp",
+ "csshiftjis",
+ "ms_kanji",
+ "shift-jis",
+ "sjis",
+ "windows-31j",
+ "x-sjis",
+ "cseuckr",
+ "csksc56011987",
+ "iso-ir-149",
+ "korean",
+ "ks_c_5601-1987",
+ "ks_c_5601-1989",
+ "ksc5601",
+ "ksc_5601",
+ "windows-949",
+ "utf-16",
];
export function decode(content: ArrayBuffer, encoding: string): string {
diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts
index d7f0bd9b7f..faca153923 100644
--- a/frontend/src/utils/index.ts
+++ b/frontend/src/utils/index.ts
@@ -4,3 +4,25 @@ import { partial } from "filesize";
* Formats filesize as KiB/MiB/...
*/
export const filesize = partial({ base: 2 });
+
+export const vClickOutside = {
+ created(el: HTMLElement, binding: any) {
+ el.clickOutsideEvent = (event: Event) => {
+ const target = event.target;
+
+ if (target instanceof Node) {
+ if (!el.contains(target)) {
+ binding.value(event);
+ }
+ }
+ };
+
+ document.addEventListener("click", el.clickOutsideEvent);
+ },
+
+ unmounted(el: HTMLElement) {
+ if (el.clickOutsideEvent) {
+ document.removeEventListener("click", el.clickOutsideEvent);
+ }
+ },
+};
diff --git a/frontend/src/utils/upload.ts b/frontend/src/utils/upload.ts
index e951cb43cb..3b68919223 100644
--- a/frontend/src/utils/upload.ts
+++ b/frontend/src/utils/upload.ts
@@ -3,31 +3,58 @@ import { useUploadStore } from "@/stores/upload";
import url from "@/utils/url";
export function checkConflict(
- files: UploadList,
+ files: UploadList | Array,
dest: ResourceItem[]
-): boolean {
+): ConflictingResource[] {
if (typeof dest === "undefined" || dest === null) {
dest = [];
}
+ const conflictingFiles: ConflictingResource[] = [];
const folder_upload = files[0].fullPath !== undefined;
- const names = new Set();
+ function getFile(name: string): ResourceItem | null {
+ for (const item of dest) {
+ if (item.name == name) return item;
+ }
+
+ return null;
+ }
+
for (let i = 0; i < files.length; i++) {
const file = files[i];
- let name = file.name;
+ const name = file.name;
- if (folder_upload) {
+ if (folder_upload && file.isDir) {
const dirs = file.fullPath?.split("/");
+ // For folder uploads, destination listing is flat and only contains
+ // top-level entries. Treating every nested file as a conflict when the
+ // parent folder exists blocks the whole upload (see #5798), so skip
+ // preflight conflict detection for nested files.
if (dirs && dirs.length > 1) {
- name = dirs[0];
+ continue;
}
}
- names.add(name);
+ const item = getFile(name);
+ if (item != null) {
+ conflictingFiles.push({
+ index: i,
+ name: item.path,
+ origin: {
+ lastModified: file.modified || file.file?.lastModified,
+ size: file.size,
+ },
+ dest: {
+ lastModified: item.modified,
+ size: item.size,
+ },
+ checked: ["origin"],
+ });
+ }
}
- return dest.some((d) => names.has(d.name));
+ return conflictingFiles;
}
export function scanFiles(dt: DataTransfer): Promise {
@@ -146,6 +173,12 @@ export function handleFiles(
const type = file.isDir ? "dir" : detectType((file.file as File).type);
- uploadStore.upload(path, file.name, file.file ?? null, overwrite, type);
+ uploadStore.upload(
+ path,
+ file.name,
+ file.file ?? null,
+ file.overwrite || overwrite,
+ type
+ );
}
}
diff --git a/frontend/src/views/files/Editor.vue b/frontend/src/views/files/Editor.vue
index dbde609e29..2b2852d37b 100644
--- a/frontend/src/views/files/Editor.vue
+++ b/frontend/src/views/files/Editor.vue
@@ -121,7 +121,7 @@ const isMarkdownFile =
fileStore.req?.name.endsWith(".markdown");
const katexOptions = {
output: "mathml" as const,
- throwOnError: false
+ throwOnError: false,
};
marked.use(markedKatex(katexOptions));
@@ -233,6 +233,11 @@ const initEditor = (fileContent: string) => {
editor.value.setFontSize(fontSize.value);
editor.value.focus();
+
+ const selection = editor.value?.getSelection();
+ selection.on("changeSelection", function () {
+ isSelectionEmpty.value = selection.isEmpty();
+ });
};
const keyEvent = (event: KeyboardEvent) => {
@@ -296,6 +301,7 @@ const close = () => {
prompt: "discardEditorChanges",
confirm: (event: Event) => {
event.preventDefault();
+ editor.value?.session.getUndoManager().reset();
finishClose();
},
saveAction: async () => {
diff --git a/frontend/src/views/files/FileListing.vue b/frontend/src/views/files/FileListing.vue
index 0a86b359ee..0ad8bd8cc2 100644
--- a/frontend/src/views/files/FileListing.vue
+++ b/frontend/src/views/files/FileListing.vue
@@ -480,7 +480,10 @@ const headerButtons = computed(() => {
shell: authStore.user?.perm.execute && enableExec,
delete: fileStore.selectedCount > 0 && authStore.user?.perm.delete,
rename: fileStore.selectedCount === 1 && authStore.user?.perm.rename,
- share: fileStore.selectedCount === 1 && authStore.user?.perm.share,
+ share:
+ fileStore.selectedCount === 1 &&
+ authStore.user?.perm.share &&
+ authStore.user?.perm.download,
move: fileStore.selectedCount > 0 && authStore.user?.perm.rename,
copy: fileStore.selectedCount > 0 && authStore.user?.perm.create,
};
@@ -628,6 +631,8 @@ const copyCut = (event: Event | KeyboardEvent): void => {
items.push({
from: fileStore.req.items[i].url,
name: fileStore.req.items[i].name,
+ size: fileStore.req.items[i].size,
+ modified: fileStore.req.items[i].modified,
});
}
@@ -651,7 +656,15 @@ const paste = (event: Event) => {
for (const item of clipboardStore.items) {
const from = item.from.endsWith("/") ? item.from.slice(0, -1) : item.from;
const to = route.path + encodeURIComponent(item.name);
- items.push({ from, to, name: item.name });
+ items.push({
+ from,
+ to,
+ name: item.name,
+ size: item.size,
+ modified: item.modified,
+ overwrite: false,
+ rename: clipboardStore.path == route.path,
+ });
}
if (items.length === 0) {
@@ -660,7 +673,7 @@ const paste = (event: Event) => {
const preselect = removePrefix(route.path) + items[0].name;
- let action = (overwrite: boolean, rename: boolean) => {
+ let action = (overwrite?: boolean, rename?: boolean) => {
api
.copy(items, overwrite, rename)
.then(() => {
@@ -683,34 +696,37 @@ const paste = (event: Event) => {
};
}
- if (clipboardStore.path == route.path) {
- action(false, true);
-
- return;
- }
-
const conflict = upload.checkConflict(items, fileStore.req!.items);
- let overwrite = false;
- let rename = false;
-
- if (conflict) {
+ if (conflict.length > 0) {
layoutStore.showHover({
- prompt: "replace-rename",
- confirm: (event: Event, option: string) => {
- overwrite = option == "overwrite";
- rename = option == "rename";
-
+ prompt: "resolve-conflict",
+ props: {
+ conflict: conflict,
+ },
+ confirm: (event: Event, result: Array) => {
event.preventDefault();
layoutStore.closeHovers();
- action(overwrite, rename);
+ for (let i = result.length - 1; i >= 0; i--) {
+ const item = result[i];
+ if (item.checked.length == 2) {
+ items[item.index].rename = true;
+ } else if (item.checked.length == 1 && item.checked[0] == "origin") {
+ items[item.index].overwrite = true;
+ } else {
+ items.splice(item.index, 1);
+ }
+ }
+ if (items.length > 0) {
+ action();
+ }
},
});
return;
}
- action(overwrite, rename);
+ action(false, false);
};
const columnsResize = () => {
@@ -806,20 +822,30 @@ const drop = async (event: DragEvent) => {
const preselect = removePrefix(path) + (files[0].fullPath || files[0].name);
- if (conflict) {
+ if (conflict.length > 0) {
layoutStore.showHover({
- prompt: "replace",
- action: (event: Event) => {
- event.preventDefault();
- layoutStore.closeHovers();
- upload.handleFiles(files, path, false);
- fileStore.preselect = preselect;
+ prompt: "resolve-conflict",
+ props: {
+ conflict: conflict,
+ isUploadAction: true,
},
- confirm: (event: Event) => {
+ confirm: (event: Event, result: Array) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(files, path, true);
- fileStore.preselect = preselect;
+ for (let i = result.length - 1; i >= 0; i--) {
+ const item = result[i];
+ if (item.checked.length == 2) {
+ continue;
+ } else if (item.checked.length == 1 && item.checked[0] == "origin") {
+ files[item.index].overwrite = true;
+ } else {
+ files.splice(item.index, 1);
+ }
+ }
+ if (files.length > 0) {
+ upload.handleFiles(files, path, true);
+ fileStore.preselect = preselect;
+ }
},
});
@@ -852,18 +878,29 @@ const uploadInput = (event: Event) => {
const path = route.path.endsWith("/") ? route.path : route.path + "/";
const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
- if (conflict) {
+ if (conflict.length > 0) {
layoutStore.showHover({
- prompt: "replace",
- action: (event: Event) => {
- event.preventDefault();
- layoutStore.closeHovers();
- upload.handleFiles(uploadFiles, path, false);
+ prompt: "resolve-conflict",
+ props: {
+ conflict: conflict,
+ isUploadAction: true,
},
- confirm: (event: Event) => {
+ confirm: (event: Event, result: Array) => {
event.preventDefault();
layoutStore.closeHovers();
- upload.handleFiles(uploadFiles, path, true);
+ for (let i = result.length - 1; i >= 0; i--) {
+ const item = result[i];
+ if (item.checked.length == 2) {
+ continue;
+ } else if (item.checked.length == 1 && item.checked[0] == "origin") {
+ uploadFiles[item.index].overwrite = true;
+ } else {
+ uploadFiles.splice(item.index, 1);
+ }
+ }
+ if (uploadFiles.length > 0) {
+ upload.handleFiles(uploadFiles, path, true);
+ }
},
});
diff --git a/frontend/src/views/files/Preview.vue b/frontend/src/views/files/Preview.vue
index 9a67de2d7c..2a60e7df30 100644
--- a/frontend/src/views/files/Preview.vue
+++ b/frontend/src/views/files/Preview.vue
@@ -311,7 +311,11 @@ const isPdf = computed(() => fileStore.req?.extension.toLowerCase() == ".pdf");
const isEpub = computed(
() => fileStore.req?.extension.toLowerCase() == ".epub"
);
-const isCsv = computed(() => fileStore.req?.extension.toLowerCase() == ".csv");
+const isCsv = computed(
+ () =>
+ fileStore.req?.extension.toLowerCase() == ".csv" &&
+ fileStore.req.size <= CSV_MAX_SIZE
+);
const isResizeEnabled = computed(() => resizePreview);
diff --git a/frontend/src/views/settings/User.vue b/frontend/src/views/settings/User.vue
index 77786e2a99..63e0d2a2df 100644
--- a/frontend/src/views/settings/User.vue
+++ b/frontend/src/views/settings/User.vue
@@ -15,19 +15,6 @@
:isDefault="false"
:isNew="isNew"
/>
-
-
-
-
-
@@ -72,12 +59,12 @@ import { useRoute, useRouter } from "vue-router";
import { useI18n } from "vue-i18n";
import { StatusError } from "@/api/utils";
import { authMethod } from "@/utils/constants";
+import { logout } from "@/utils/auth";
const error = ref();
const originalUser = ref();
const user = ref();
const createUserDir = ref(false);
-const currentPassword = ref("");
const isCurrentPasswordRequired = ref(false);
const $showError = inject("$showError")!;
@@ -134,17 +121,35 @@ const fetchData = async () => {
}
};
-const deletePrompt = () =>
- layoutStore.showHover({ prompt: "deleteUser", confirm: deleteUser });
+const deletePrompt = () => {
+ if (isCurrentPasswordRequired.value) {
+ layoutStore.showHover({
+ prompt: "current-password",
+ confirm: (event: Event, currentPassword: string) => {
+ event.preventDefault();
+ layoutStore.closeHovers();
+ deleteUser(currentPassword);
+ },
+ });
+ } else {
+ layoutStore.showHover({
+ prompt: "deleteUser",
+ confirm: () => deleteUser(""),
+ });
+ }
+};
-const deleteUser = async (e: Event) => {
- e.preventDefault();
+const deleteUser = async (currentPassword: string) => {
if (!user.value) {
return false;
}
try {
- await api.remove(user.value.id, currentPassword.value);
- router.push({ path: "/settings/users" });
+ await api.remove(user.value.id, currentPassword);
+ if (user.value.id == authStore.user?.id) {
+ logout();
+ } else {
+ router.push({ path: "/settings/users" });
+ }
$showSuccess(t("settings.userDeleted"));
} catch (err) {
if (err instanceof StatusError) {
@@ -157,8 +162,25 @@ const deleteUser = async (e: Event) => {
return true;
};
-const save = async (event: Event) => {
+const save = (event: Event) => {
event.preventDefault();
+ if (isCurrentPasswordRequired.value) {
+ layoutStore.showHover({
+ prompt: "current-password",
+ confirm: (event: Event, currentPassword: string) => {
+ event.preventDefault();
+ layoutStore.closeHovers();
+ send(currentPassword);
+ },
+ });
+ } else {
+ send("");
+ }
+
+ return true;
+};
+
+const send = async (currentPassword: string) => {
if (!user.value) {
return false;
}
@@ -170,11 +192,11 @@ const save = async (event: Event) => {
...user.value,
};
- const loc = await api.create(newUser, currentPassword.value);
+ const loc = await api.create(newUser, currentPassword);
router.push({ path: loc || "/settings/users" });
$showSuccess(t("settings.userCreated"));
} else {
- await api.update(user.value, ["all"], currentPassword.value);
+ await api.update(user.value, ["all"], currentPassword);
if (user.value.id === authStore.user?.id) {
authStore.updateUser(user.value);
@@ -185,7 +207,5 @@ const save = async (event: Event) => {
} catch (e: any) {
$showError(e);
}
-
- return true;
};
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 583b2e3829..081591773d 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -14,7 +14,7 @@ const plugins = [
// defaults already drop IE support
targets: ["defaults"],
}),
- compression({ include: /\.js$/i, deleteOriginalAssets: true }),
+ compression({ include: /\.js$/, deleteOriginalAssets: false }),
];
const resolve = {
diff --git a/go.mod b/go.mod
index 8e0f0f1025..e354852959 100644
--- a/go.mod
+++ b/go.mod
@@ -1,10 +1,10 @@
module github.com/filebrowser/filebrowser/v2
-go 1.25
+go 1.25.0
require (
github.com/asdine/storm/v3 v3.2.1
- github.com/asticode/go-astisub v0.38.0
+ github.com/asticode/go-astisub v0.39.0
github.com/disintegration/imaging v1.6.2
github.com/dsoprea/go-exif/v3 v3.0.1
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568
@@ -16,18 +16,19 @@ require (
github.com/marusama/semaphore/v2 v2.5.0
github.com/mholt/archives v0.1.5
github.com/mitchellh/go-homedir v1.1.0
- github.com/redis/go-redis/v9 v9.17.3
- github.com/samber/lo v1.52.0
- github.com/shirou/gopsutil/v4 v4.26.1
+ github.com/redis/go-redis/v9 v9.18.0
+ github.com/samber/lo v1.53.0
+ github.com/shirou/gopsutil/v4 v4.26.2
github.com/spf13/afero v1.15.0
github.com/spf13/cobra v1.10.2
github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.11.1
github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce
- golang.org/x/crypto v0.48.0
- golang.org/x/image v0.36.0
- golang.org/x/text v0.34.0
+ go.etcd.io/bbolt v1.4.3
+ golang.org/x/crypto v0.49.0
+ golang.org/x/image v0.37.0
+ golang.org/x/text v0.35.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
)
@@ -47,7 +48,7 @@ require (
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
- github.com/ebitengine/purego v0.9.1 // indirect
+ github.com/ebitengine/purego v0.10.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
@@ -73,12 +74,12 @@ require (
github.com/subosito/gotenv v1.6.0 // indirect
github.com/ulikunitz/xz v0.5.15 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
- go.etcd.io/bbolt v1.4.3 // indirect
+ go.uber.org/atomic v1.11.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
- golang.org/x/net v0.49.0 // indirect
- golang.org/x/sync v0.19.0 // indirect
- golang.org/x/sys v0.41.0 // indirect
+ golang.org/x/net v0.51.0 // indirect
+ golang.org/x/sync v0.20.0 // indirect
+ golang.org/x/sys v0.42.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
diff --git a/go.sum b/go.sum
index 262a280c87..07a252baeb 100644
--- a/go.sum
+++ b/go.sum
@@ -31,8 +31,8 @@ github.com/asticode/go-astikit v0.20.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xbl
github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0=
github.com/asticode/go-astikit v0.56.0 h1:DmD2p7YnvxiPdF0h+dRmos3bsejNEXbycENsY5JfBqw=
github.com/asticode/go-astikit v0.56.0/go.mod h1:fV43j20UZYfXzP9oBn33udkvCvDvCDhzjVqoLFuuYZE=
-github.com/asticode/go-astisub v0.38.0 h1:Qh3IO8Cotn0wwok5maid7xqsIJTwn2DtABT1UajKJaI=
-github.com/asticode/go-astisub v0.38.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8=
+github.com/asticode/go-astisub v0.39.0 h1:j1/rFLRUH0TT2CW9YCtBek9lRdMp96oxaZm6vbgE96M=
+github.com/asticode/go-astisub v0.39.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8=
github.com/asticode/go-astits v1.8.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ=
github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c=
github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI=
@@ -83,8 +83,8 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003142440-7a1927d49d9d/go.mod h1:LV
github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw=
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8=
-github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
-github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
+github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ISU=
+github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
@@ -166,7 +166,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
+github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -202,8 +205,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/redis/go-redis/v9 v9.17.3 h1:fN29NdNrE17KttK5Ndf20buqfDZwGNgoUr9qjl1DQx4=
-github.com/redis/go-redis/v9 v9.17.3/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
+github.com/redis/go-redis/v9 v9.18.0 h1:pMkxYPkEbMPwRdenAzUNyFNrDgHx9U+DrBabWNfSRQs=
+github.com/redis/go-redis/v9 v9.18.0/go.mod h1:k3ufPphLU5YXwNTUcCRXGxUoF1fqxnhFQmscfkCoDA0=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
@@ -212,10 +215,10 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
-github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
-github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
-github.com/shirou/gopsutil/v4 v4.26.1 h1:TOkEyriIXk2HX9d4isZJtbjXbEjf5qyKPAzbzY0JWSo=
-github.com/shirou/gopsutil/v4 v4.26.1/go.mod h1:medLI9/UNAb0dOI9Q3/7yWSqKkj00u+1tgY8nvv41pc=
+github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM=
+github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
+github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI=
+github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik=
github.com/sorairolake/lzip-go v0.3.8/go.mod h1:JcBqGMV0frlxwrsE9sMWXDjqn3EeVf0/54YPsw66qkU=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
@@ -257,6 +260,8 @@ github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3i
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
+github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
@@ -264,6 +269,8 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
+go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
@@ -276,8 +283,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
-golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
+golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
+golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -289,8 +296,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/image v0.36.0 h1:Iknbfm1afbgtwPTmHnS2gTM/6PPZfH+z2EFuOkSbqwc=
-golang.org/x/image v0.36.0/go.mod h1:YsWD2TyyGKiIX1kZlu9QfKIsQ4nAAK9bdgdrIsE7xy4=
+golang.org/x/image v0.37.0 h1:ZiRjArKI8GwxZOoEtUfhrBtaCN+4b/7709dlT6SSnQA=
+golang.org/x/image v0.37.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -329,8 +336,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
-golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
+golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
+golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -343,8 +350,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
-golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
+golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
+golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -370,8 +377,8 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
-golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
+golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -382,8 +389,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
-golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
+golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
+golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/http/auth.go b/http/auth.go
index 4eceeafe31..d975beae9d 100644
--- a/http/auth.go
+++ b/http/auth.go
@@ -167,6 +167,10 @@ var signupHandler = func(_ http.ResponseWriter, r *http.Request, d *data) (int,
d.settings.Defaults.Apply(user)
+ // Users signed up via the signup handler should never become admins, even
+ // if that is the default permission.
+ user.Perm.Admin = false
+
pwd, err := users.ValidateAndHashPwd(info.Password, d.settings.MinimumPasswordLength)
if err != nil {
return http.StatusBadRequest, err
diff --git a/http/public.go b/http/public.go
index 6dcdaff1a5..596a03c972 100644
--- a/http/public.go
+++ b/http/public.go
@@ -56,7 +56,7 @@ var withHashFile = func(fn handleFunc) handleFunc {
filePath := ""
if file.IsDir {
- basePath = filepath.Dir(basePath)
+ basePath = filepath.Clean(link.Path)
filePath = ifPath
}
diff --git a/http/resource.go b/http/resource.go
index 7066f35a63..3f78cb0c0e 100644
--- a/http/resource.go
+++ b/http/resource.go
@@ -43,7 +43,7 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
return renderJSON(w, r, file)
} else if encoding == "true" {
if file.Type != "text" {
- return http.StatusUnsupportedMediaType, fmt.Errorf("file is not a text file")
+ return renderJSON(w, r, file)
}
f, err := d.user.Fs.Open(r.URL.Path)
@@ -212,6 +212,8 @@ func resourcePatchHandler(fileCache FileCache) handleFunc {
dst := r.URL.Query().Get("destination")
action := r.URL.Query().Get("action")
dst, err := url.QueryUnescape(dst)
+ dst = path.Clean("/" + dst)
+ src = path.Clean("/" + src)
if !d.Check(src) || !d.Check(dst) {
return http.StatusForbidden, nil
}
diff --git a/http/share.go b/http/share.go
index 509a7b21e2..35125dba40 100644
--- a/http/share.go
+++ b/http/share.go
@@ -20,7 +20,7 @@ import (
func withPermShare(fn handleFunc) handleFunc {
return withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
- if !d.user.Perm.Share {
+ if !d.user.Perm.Share || !d.user.Perm.Download {
return http.StatusForbidden, nil
}
diff --git a/http/tus_handlers.go b/http/tus_handlers.go
index b659d47965..0b7bcbb48f 100644
--- a/http/tus_handlers.go
+++ b/http/tus_handlers.go
@@ -5,10 +5,10 @@ import (
"fmt"
"io"
"net/http"
- "net/url"
"os"
"path/filepath"
"strconv"
+ "strings"
"time"
"github.com/spf13/afero"
@@ -112,12 +112,12 @@ func tusPostHandler(cache UploadCache) handleFunc {
// Enables the user to utilize the PATCH endpoint for uploading file data
cache.Register(file.RealPath(), uploadLength)
- path, err := url.JoinPath("/", d.server.BaseURL, "/api/tus", r.URL.Path)
- if err != nil {
- return http.StatusBadRequest, fmt.Errorf("invalid path: %w", err)
+ basePath := "/" + strings.Trim(strings.TrimSpace(d.server.BaseURL), "/")
+ if basePath == "/" {
+ basePath = ""
}
- w.Header().Set("Location", path)
+ w.Header().Set("Location", basePath+"/api/tus"+r.URL.EscapedPath())
return http.StatusCreated, nil
})
}
@@ -240,7 +240,7 @@ func tusPatchHandler(cache UploadCache) handleFunc {
func tusDeleteHandler(cache UploadCache) handleFunc {
return withUser(func(_ http.ResponseWriter, r *http.Request, d *data) (int, error) {
- if r.URL.Path == "/" || !d.user.Perm.Create {
+ if r.URL.Path == "/" || !d.user.Perm.Delete {
return http.StatusForbidden, nil
}
diff --git a/http/utils.go b/http/utils.go
index c76cecf420..dc51ccb681 100644
--- a/http/utils.go
+++ b/http/utils.go
@@ -60,6 +60,15 @@ func stripPrefix(prefix string, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
p := strings.TrimPrefix(r.URL.Path, prefix)
rp := strings.TrimPrefix(r.URL.RawPath, prefix)
+
+ // If the path is exactly the prefix (no trailing slash), redirect to
+ // the prefix with a trailing slash so the router receives "/" instead
+ // of "", which would otherwise cause a redirect to the site root.
+ if p == "" {
+ http.Redirect(w, r, prefix+"/", http.StatusMovedPermanently)
+ return
+ }
+
r2 := new(http.Request)
*r2 = *r
r2.URL = new(url.URL)
diff --git a/storage/bolt/users.go b/storage/bolt/users.go
index 974c0a48aa..6686d941b0 100644
--- a/storage/bolt/users.go
+++ b/storage/bolt/users.go
@@ -6,6 +6,7 @@ import (
"reflect"
"github.com/asdine/storm/v3"
+ bolt "go.etcd.io/bbolt"
fberrors "github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/users"
@@ -93,3 +94,29 @@ func (st usersBackend) DeleteByUsername(username string) error {
return st.db.DeleteStruct(user)
}
+
+func (st usersBackend) CountAdmins() (int, error) {
+ count := 0
+
+ err := st.db.Bolt.View(func(tx *bolt.Tx) error {
+ bucket := tx.Bucket([]byte(reflect.TypeOf(users.User{}).Name()))
+ if bucket == nil {
+ return nil
+ }
+
+ c := bucket.Cursor()
+ for _, v := c.First(); v != nil; _, v = c.Next() {
+ var u users.User
+ if err := st.db.Codec().Unmarshal(v, &u); err != nil {
+ return err
+ }
+ if u.Perm.Admin {
+ count++
+ }
+ }
+
+ return nil
+ })
+
+ return count, err
+}
diff --git a/transifex.yml b/transifex.yml
index 8a12912b6d..3ab4a61a31 100644
--- a/transifex.yml
+++ b/transifex.yml
@@ -9,7 +9,9 @@ settings:
language_mapping:
sv_SE: sv-se
pt_BR: pt-br
+ pt_PT: pt-pt
zh_CN: zh-cn
zh_HK: zh-hk
zh_TW: zh-tw
nl_BE: nl-be
+ lv_LV: lv-lv
diff --git a/users/storage.go b/users/storage.go
index 43c65fe4f5..33cfc9c4ae 100644
--- a/users/storage.go
+++ b/users/storage.go
@@ -15,6 +15,7 @@ type StorageBackend interface {
Update(u *User, fields ...string) error
DeleteByID(uint) error
DeleteByUsername(string) error
+ CountAdmins() (int, error)
}
type Store interface {
@@ -108,14 +109,20 @@ func (s *Storage) Delete(id interface{}) error {
if err != nil {
return err
}
- if user.ID == 1 {
+ if s.IsUniqueAdmin(user) {
return fberrors.ErrRootUserDeletion
}
+
return s.back.DeleteByUsername(id)
case uint:
- if id == 1 {
+ user, err := s.back.GetBy(id)
+ if err != nil {
+ return err
+ }
+ if s.IsUniqueAdmin(user) {
return fberrors.ErrRootUserDeletion
}
+
return s.back.DeleteByID(id)
default:
return fberrors.ErrInvalidDataType
@@ -131,3 +138,15 @@ func (s *Storage) LastUpdate(id uint) int64 {
}
return 0
}
+
+func (s *Storage) IsUniqueAdmin(user *User) bool {
+ if !user.Perm.Admin {
+ return false
+ }
+
+ count, err := s.back.CountAdmins()
+ if err != nil {
+ return true
+ }
+ return count <= 1
+}
diff --git a/www/docs/authentication.md b/www/docs/authentication.md
index 75270f8cc7..4308b01c12 100644
--- a/www/docs/authentication.md
+++ b/www/docs/authentication.md
@@ -38,7 +38,7 @@ Where `X-My-Header` is the HTTP header provided by your proxy with the username.
> [!WARNING]
>
-> File Browser will blindly trust the provided header. If the proxy can be bypassed, an attacker could simply attach the header and get admin access.
+> File Browser will blindly trust the provided header. If the proxy can be bypassed, an attacker could simply attach the header and get admin access. Please ensure that File Browser is not accessible from untrusted networks, and that the proxy is correctly configured to strip/overwrite the header from client requests.
## Hook Authentication