Compare commits

...

129 Commits

Author SHA1 Message Date
Henrique Dias
8ef8f2c098 chore(release): 2.35.0 2025-06-30 17:03:16 +02:00
Henrique Dias
3b3df83d64 docs: add warning to command runner 2025-06-30 17:01:02 +02:00
Henrique Dias
38d0366acf fix: update documentation links 2025-06-30 17:01:02 +02:00
Henrique Dias
4403cd3572 fix: shell value must be joined by blank space 2025-06-30 17:01:02 +02:00
Foxy Hunter
8d7522049c feat: Long press selects item in single click mode 2025-06-30 16:14:09 +02:00
Henrique Dias
7b43cfb1dc docs: improve fail2ban filter 2025-06-29 17:24:17 +02:00
Henrique Dias
d644744417 docs: add fail2ban instructions 2025-06-29 16:34:50 +02:00
Henrique Dias
d1a73a8b18 chore(release): 2.34.2 2025-06-29 16:12:09 +02:00
Henrique Dias
2b5d6cbb99 fix: mitigate unprotected shares 2025-06-29 16:06:20 +02:00
Henrique Dias
364f391017 docs: cleanup installation 2025-06-29 15:53:02 +02:00
Henrique Dias
c13861e13c docs: clarify admin password 2025-06-29 15:36:58 +02:00
Henrique Dias
e6b750add5 chore: make more fields in bug report mandatory 2025-06-29 15:06:18 +02:00
Henrique Dias
70d59ec03e chore(release): 2.34.1 2025-06-29 11:28:57 +02:00
Henrique Dias
bf37f88c32 fix: passthrough the minimum password length (#5236) 2025-06-29 11:28:32 +02:00
Foxy Hunter
7354eb6cf9 fix: exclude to-be-moved folder from move dialog (#5235) 2025-06-29 11:23:06 +02:00
Henrique Dias
10684e5390 docs: bring the maintenance warning higher in the page 2025-06-29 10:13:39 +02:00
Henrique Dias
58fe817349 docs: add link to contributing and license in readme 2025-06-29 10:13:01 +02:00
Henrique Dias
d8472e767b chore(release): 2.34.0 2025-06-29 09:54:35 +02:00
Henrique Dias
8700cb30ff chore: reuse docker flags 2025-06-29 09:51:44 +02:00
manx98
93c4b2e03c fix: abort ongoing requests when changing pages (#3927) 2025-06-29 09:38:03 +02:00
Henrique Dias
2d1a82b73f docs: improvements to building and docs (#5234) 2025-06-29 09:28:39 +02:00
dependabot[bot]
5a07291306 build(deps): bump brace-expansion from 1.1.11 to 1.1.12 in /tools (#5228)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-29 09:20:44 +02:00
transifex-integration[bot]
09f679fae4 feat: Translate frontend/src/i18n/en.json in fa (#5233)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-06-29 09:17:05 +02:00
Oleg Lobanov
9e273cd947 Revert "docs: change cloudflare environment (#5231)" (#5232)
This reverts commit 77d266bc00.
2025-06-28 22:38:51 +02:00
Oleg Lobanov
77d266bc00 docs: change cloudflare environment (#5231) 2025-06-28 22:30:37 +02:00
Oleg Lobanov
8861933cf8 build: publish docs to cloudflare pages (#5230) 2025-06-28 22:20:26 +02:00
transifex-integration[bot]
a5ea2a266b feat: update translations for project File Browser (#5226)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-06-28 19:56:56 +02:00
Oleg Lobanov
f5e531c8ae build: add an arm64 target for the site image (#5229) 2025-06-28 19:47:55 +02:00
Oleg Lobanov
6072540c3e docs: migrate to MkDocs for site generation (#5227) 2025-06-28 19:34:34 +02:00
Henrique Dias
464b644adf fix: add configurable minimum password length (#5225) 2025-06-28 10:07:34 +02:00
Henrique Dias
089255997a fix: do not expose the name of the root directory (#5224) 2025-06-28 08:40:07 +02:00
dependabot[bot]
5331969163 build(deps): bump github.com/go-viper/mapstructure/v2 in /tools
Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/go-viper/mapstructure/releases)
- [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: github.com/go-viper/mapstructure/v2
  dependency-version: 2.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-27 21:52:15 +02:00
dependabot[bot]
f32f27383d build(deps): bump github.com/go-viper/mapstructure/v2
Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/go-viper/mapstructure/releases)
- [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: github.com/go-viper/mapstructure/v2
  dependency-version: 2.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-27 21:44:29 +02:00
Henrique Dias
0acd69c537 feat: Translate frontend/src/i18n/en.json in fa 2025-06-27 18:09:32 +02:00
Henrique Dias
ae4fb0ea25 chore: make as exception to mnd 2025-06-27 08:19:34 +02:00
Adrien Kohlbecker
8230eb7ab5 fix: Graceful shutdown 2025-06-27 08:19:34 +02:00
Henrique Dias
8b8fb3343f ci: remove goconst 2025-06-27 08:03:11 +02:00
Oleksandr Redko
1d494ff315 build: bump golangci-lint to 2.1.6 2025-06-27 07:56:15 +02:00
Henrique Dias
da03728cd7 chore(release): 2.33.10 2025-06-26 21:23:35 +02:00
Henrique Dias
e735491c57 fix: ignore linting error 2025-06-26 21:12:24 +02:00
Henrique Dias
4d830f707f fix: correctly check if command is allowed when using shell 2025-06-26 21:09:16 +02:00
Henrique Dias
f84a6db680 fix: correctly split shell 2025-06-26 21:07:45 +02:00
Henrique Dias
a430eb2e60 chore(release): 2.33.9 2025-06-26 19:45:36 +02:00
Henrique Dias
c232d41f90 fix: remove unused import 2025-06-26 19:43:20 +02:00
Henrique Dias
c1e4fd648b docs: add warning regarding the custom commands feature 2025-06-26 19:42:13 +02:00
Henrique Dias
d5b39a14fd fix: remove auth token from /api/command 2025-06-26 19:42:13 +02:00
Henrique Dias
e2e1e49130 fix: check exact match on command allow list 2025-06-26 19:42:12 +02:00
Henrique Dias
b0f92dd2d7 chore(release): 2.33.8 2025-06-25 20:53:47 +02:00
Henrique Dias
21b0827808 Merge commit from fork 2025-06-25 20:50:38 +02:00
Henrique Dias
d6d84e2b48 chore(release): 2.33.7 2025-06-25 17:47:23 +02:00
Henrique Dias
ca86f91621 Merge commit from fork 2025-06-25 17:42:39 +02:00
Henrique Dias
4bfbf33249 fix: linting issues 2025-06-25 17:37:18 +02:00
Henrique Dias
f19943a42e Merge commit from fork 2025-06-25 17:35:15 +02:00
Henrique Dias
e74c958862 fix: linting issues 2025-06-25 17:34:00 +02:00
Henrique Dias
221451a517 fix: correctly parse negative boolean flags 2025-06-25 17:24:06 +02:00
Henrique Dias
f46641b038 chore(release): 2.33.6 2025-06-24 22:00:57 +02:00
Henrique Dias
23bd8f6715 fix: remove incorrect default for password flag 2025-06-24 21:43:44 +02:00
Henrique Dias
506fc08577 chore(release): 2.33.5 2025-06-24 17:11:40 +02:00
transifex-integration[bot]
f33076462a feat: update languages for project File Browser (#5190)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-06-24 17:08:28 +02:00
Henrique Dias
6c29fabdc8 chore: remove cz_CS from transifex.yaml 2025-06-24 17:05:12 +02:00
Adam
0268506f80 fix: actually register the czech language (#5189) 2025-06-24 17:02:01 +02:00
Henrique Dias
ad864a97e9 chore(release): 2.33.4 2025-06-22 17:59:45 +02:00
transifex-integration[bot]
f714e71a35 feat: translation updates for project File Browser (#5179)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-06-22 17:59:23 +02:00
Henrique Dias
dbdbbab4d7 chore(release): 2.33.3 2025-06-22 17:57:34 +02:00
Henrique Dias
7c0c7820ef fix: keep command behavior in Dockerfile 2025-06-22 17:55:57 +02:00
Arion2000
2741616473 fix: update search hotkey in help prompt (#5178) 2025-06-22 12:45:21 +02:00
Henrique Dias
ffb858e4ef chore(release): 2.33.2 2025-06-21 10:37:30 +02:00
Henrique Dias
0ca8059d8d fix: create user dir on signup 2025-06-21 10:32:50 +02:00
Henrique Dias
8ca080422f chore(release): 2.33.1 2025-06-21 09:25:18 +02:00
Henrique Dias
cbb712484d fix: remove auth query parameter from download and preview links
macOS saves the download URL in the metadata of the downloaded file.
This means that the downloaded file contains a metadata item with the JWT
token of the user. If the user were to share this file with someone else,
they would have access to their account using the JWT in the metadata
during the validity of the JWT.

The JWT has been removed from the URLs. Since the user is logged in, there
is an authentication cookie set. A JWT in the URL is not necessary.
2025-06-21 09:21:39 +02:00
Patrick Wang
8a14018861 fix: downloadUrl of file preview (#3728) 2025-06-21 09:21:17 +02:00
Henrique Dias
a493ec90ff docs: add more docker notes 2025-06-21 08:45:53 +02:00
Henrique Dias
33113036cd docs: update security.md 2025-06-20 21:41:46 +02:00
contributor
a02b2972eb fix: search uses ctrl+shift+f instead of hijacking browser's ctrl+f (#4638) 2025-06-19 21:57:57 +02:00
Henrique Dias
e9bb3dc243 chore(release): 2.33.0 2025-06-18 21:58:42 +02:00
Henrique Dias
2e26393a02 feat: improved docker image volumes and permissions (#5160) 2025-06-18 21:53:02 +02:00
Henrique Dias
04a13f086f chore(release): 2.32.3 2025-06-17 16:47:53 +02:00
Henrique Dias
1cc539eb8a ci: fix the post install tap command 2025-06-17 16:47:34 +02:00
Henrique Dias
6ebfdcceaa chore(release): 2.32.2 2025-06-17 16:34:37 +02:00
Henrique Dias
db671c227b ci: update gorelease homebrew 2025-06-17 16:34:04 +02:00
Henrique Dias
4aee14de44 ci: add @hacdias as codeowner 2025-06-17 16:30:02 +02:00
Henrique Dias
0cca7d8dc0 docs: move most docs to main repository (#5141) 2025-06-17 11:37:15 +02:00
transifex-integration[bot]
c34c0afecf feat: updated for project File Browser (#5159)
Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-06-17 09:05:21 +02:00
Henrique Dias
56a0f9244b chore(release): 2.32.1 2025-06-16 20:18:42 +02:00
michioxd
56b80b6d9b feat: add Vietnamese translation (#3840) 2025-06-16 18:47:20 +02:00
Dev_Nergis
d9ebd65ffc feat: update translation ko.json (#3852) 2025-06-16 18:35:50 +02:00
SOMA
a882fb6c85 feat: improve pt-br translations with new keys and refinements (#4903) 2025-06-16 17:39:57 +02:00
Henrique Dias
5daae69a6d chore: revert only translated mode to transifex 2025-06-15 21:05:30 +02:00
Henrique Dias
54a1ae0fa0 chore: add only translated mode to transifex 2025-06-15 20:48:01 +02:00
Henrique Dias
b6b4fb5da7 ci: remove manual .tx config 2025-06-15 20:13:21 +02:00
Henrique Dias
6d82a27f9a ci: add transifex.yml 2025-06-15 20:13:03 +02:00
Henrique Dias
31a326606d chore: updated readme and template 2025-06-13 22:46:22 +02:00
Henrique Dias
abbf203bdd chore: updated readme and templates 2025-06-13 22:46:22 +02:00
Henrique Dias
e82e2392a4 chore: update Go dependencies 2025-06-11 18:51:01 +02:00
Henrique Dias
f4a8420bf3 docs: add maintenance warning to readme 2025-06-11 17:44:32 +02:00
Simon
71a8f5662c fix: set videojs locale (#3742)
Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
2025-06-05 15:53:29 +02:00
Henrique Dias
48f894740f chore: remove stale bot 2025-06-04 19:08:43 +02:00
Henrique Dias
b883e287a0 chore: migrate transifex settings 2025-06-04 18:58:48 +02:00
Henrique Dias
5d9f0977d6 Merge pull request #3675 from bo0tzz/fix/random-password 2025-06-04 17:39:32 +02:00
bo0tzz
c606a01a2d fix: err shadowing lint 2025-06-04 17:36:55 +02:00
bo0tzz
54b91b8ff0 fix: imports lint 2025-06-04 17:36:55 +02:00
bo0tzz
a46acba5f9 fix: generate random admin password on quick setup
This should help mitigate issues like #3646
2025-06-04 17:36:55 +02:00
Henrique Dias
1d14798653 Merge pull request #3776 from Matthaiks/pl 2025-06-04 17:35:00 +02:00
Matthaiks
6d55cc59f7 chore: Update Polish translation 2025-06-04 17:32:41 +02:00
Matthaiks
495e731ee7 Update Polish translation 2025-06-04 17:32:41 +02:00
Henrique Dias
ff1579b950 Merge pull request #3793 from Kcchouette/patch-1 2025-06-04 17:24:12 +02:00
Kcchouette
7a48fd0c3e Merge branch 'master' into patch-1 2025-05-20 11:23:27 +00:00
dependabot[bot]
cfea84fd5e build(deps): bump golang.org/x/net from 0.33.0 to 0.38.0 (#3869) 2025-05-19 12:27:04 +00:00
dependabot[bot]
0ba9505a19 build(deps): bump golang.org/x/crypto from 0.31.0 to 0.35.0 (#3865)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.31.0 to 0.35.0.
- [Commits](https://github.com/golang/crypto/compare/v0.31.0...v0.35.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.35.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 14:24:09 +02:00
dependabot[bot]
5355629fd1 build(deps-dev): bump vite from 6.0.11 to 6.1.6 in /frontend (#3886)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.11 to 6.1.6.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.1.6/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.1.6/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.1.6
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 13:49:42 +02:00
Kcchouette
f8a16a6aca Merge branch 'master' into patch-1 2025-04-19 09:22:44 +00:00
dependabot[bot]
35d1c09243 build(deps): bump vue-i18n from 11.0.1 to 11.1.2 in /frontend (#3786)
Bumps [vue-i18n](https://github.com/intlify/vue-i18n/tree/HEAD/packages/vue-i18n) from 11.0.1 to 11.1.2.
- [Release notes](https://github.com/intlify/vue-i18n/releases)
- [Changelog](https://github.com/intlify/vue-i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/intlify/vue-i18n/commits/v11.1.2/packages/vue-i18n)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-19 17:03:45 +01:00
Kcchouette
99c64c12ed Update french translation 2025-03-10 21:04:12 +00:00
Oleg Lobanov
3d6c5152fe chore(release): 2.32.0 2025-01-31 09:48:22 +01:00
Oleg Lobanov
ba797cda31 build: fix go releaser 2025-01-31 09:48:08 +01:00
Arran Hobson Sayers
5300d00d2e fix: Fix user creation on proxy auth (#3666)
* Fix user creation on proxy auth

* Refactoring

---------

Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
2025-01-30 11:28:19 +01:00
elmodor
bbdd313705 fix: disk usage refreshing (#3692)
Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
2025-01-30 10:32:05 +01:00
Eden Yemini
045064f8b8 fix: add proper healthcheck for S6 containers (#3691)
Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
2025-01-30 10:29:14 +01:00
정성민
252f0a7533 chore: update ko.json (#3688) 2025-01-30 10:24:44 +01:00
dependabot[bot]
1194cfe009 build(deps): bump golang.org/x/net from 0.23.0 to 0.33.0 (#3712)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.23.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.23.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-30 10:22:04 +01:00
kloon15
0201f9c5c4 refactor: Fix eslint warnings (#3698)
* Update dependencies and remove typescript version pinning (fixed upstream)

* Fix esling warnings (disabled any and script lang checks)
Rewrote clipboard copy (Fixes #3407)
Run prettier

---------

Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
2025-01-30 10:18:48 +01:00
Juan Bernárdez
cc331383fb chore: add translation for the "Hide dot files setting" in "es" (Spanish) language (#3704) 2025-01-30 10:16:40 +01:00
Ryan
d1c84a8412 fix: prompts disappearing on copy / move / upload (#3537)
---------

Co-authored-by: Ryan Miller <ryan.miller@infinitetactics.com>
Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
2025-01-21 00:05:59 +01:00
dependabot[bot]
e92dbb4bb8 build(deps): bump golang.org/x/crypto from 0.26.0 to 0.31.0 (#3634)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.26.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.26.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 22:07:57 +01:00
Arran Hobson Sayers
209acf2429 feat: create user on proxy authentication if user does not exist (#3569)
---------

Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
2024-12-16 22:05:13 +01:00
dependabot[bot]
25372edb5c build(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /tools (#3601)
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-12 18:02:05 +01:00
kloon15
d51a343820 build: update to node 22 and pnpm (#3616)
This commit brings the project to support node 22 which became LTS and
fixes broken builds with typescript 5.7+ until vue-tsc is updated and
replaces npm with pnpm.

- Update tsconfig for node 22
- Pin typescript to 5.6.x to not break vue-tsc
- Replace npm with pnpm (corepack recommended)
- Update Makefile and main workflow for pnpm
- Migrate to eslint 9 flat config
- Fix broken imports
- Exclude non-TS vue files for vue-tsc
2024-12-09 12:27:18 +01:00
dependabot[bot]
065959451d build(deps): bump vue-i18n from 9.10.2 to 9.14.2 in /frontend (#3618)
Bumps [vue-i18n](https://github.com/intlify/vue-i18n/tree/HEAD/packages/vue-i18n) from 9.10.2 to 9.14.2.
- [Release notes](https://github.com/intlify/vue-i18n/releases)
- [Changelog](https://github.com/intlify/vue-i18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/intlify/vue-i18n/commits/v9.14.2/packages/vue-i18n)

---
updated-dependencies:
- dependency-name: vue-i18n
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 12:54:38 +01:00
dependabot[bot]
2fdea73430 build(deps): bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 (#3574) 2024-11-05 06:49:45 +01:00
179 changed files with 109412 additions and 9516 deletions

View File

@@ -1,5 +1,7 @@
* .venv
!docker/* dist
!healthcheck.sh .idea
!docker_config.json frontend/node_modules
!filebrowser frontend/dist
filebrowser.db
docs/index.md

2
.github/CODEOWNERS vendored
View File

@@ -2,4 +2,4 @@
# Unless a later match takes precedence, @o1egl will be requested for # Unless a later match takes precedence, @o1egl will be requested for
# review when someone opens a pull request. # review when someone opens a pull request.
* @o1egl * @o1egl @hacdias

View File

@@ -1,22 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
**Description**
<!-- A clear and concise description of what the issue is about. What are you trying to do? -->
**Expected behaviour**
<!-- What did you expect to happen? -->
**What is happening instead?**
<!-- Please, give full error messages and/or log. -->
**Additional context**
<!-- Add any other context about the problem here. If applicable, add screenshots to help explain your problem. -->
**How to reproduce?**
<!-- Tell us how to reproduce this issue. How can someone who is starting from scratch reproduce this behaviour as minimally as possible? -->
**Files**
<!-- A list of relevant files for this issue. Large files can be uploaded one-by-one or in a tarball/zipfile. -->

53
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: Bug Report
description: Report a bug in FileBrowser.
labels: [bug, triage]
body:
- type: checkboxes
attributes:
label: Checklist
description: Please verify that you've followed these steps
options:
- label: This is a bug report, not a question.
required: true
- label: I have searched on the [issue tracker](https://github.com/filebrowser/filebrowser/issues?q=is%3Aissue) for my bug.
required: true
- label: I am running the latest [FileBrowser version](https://github.com/filebrowser/filebrowser/releases) or have an issue updating.
required: true
- type: textarea
id: version
attributes:
label: Version
render: Text
description: |
Enter the version of FileBrowser you are using.
validations:
required: true
- type: textarea
attributes:
label: Description
description: |
A clear and concise description of what the issue is about. What are you trying to do?
validations:
required: true
- type: textarea
attributes:
label: What did you expect to happen?
validations:
required: true
- type: textarea
attributes:
label: What actually happened?
validations:
required: true
- type: textarea
attributes:
label: Reproduction Steps
description: |
Tell us how to reproduce this issue. How can someone who is starting from scratch reproduce this behavior as minimally as possible?
validations:
required: true
- type: textarea
attributes:
label: Files
description: |
A list of relevant files for this issue. Large files can be uploaded one-by-one or in a tarball/zipfile.

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: GitHub Discussions
url: https://github.com/filebrowser/filebrowser/discussions
about: Please ask questions and discuss features here.

View File

@@ -1,16 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
<!-- Add a clear and concise description of what the problem is. E.g. *I'm always frustrated when [...]* -->
**Describe the solution you'd like**
<!-- Add a clear and concise description of what you want to happen. -->
**Describe alternatives you've considered**
<!-- Add a clear and concise description of any alternative solutions or features you've considered. -->
**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->

View File

@@ -1,19 +1,16 @@
**Description** ## Description
<!--
Please explain the changes you made here.
If the feature changes current behaviour, explain why your solution is better.
-->
:rotating_light: Before submitting your PR, please indicate which issues are either fixed or closed by this PR. See [GitHub Help: Closing issues using keywords](https://help.github.com/articles/closing-issues-via-commit-messages/). <!-- Please explain the changes you made here. -->
- [ ] DO make sure you are requesting to **pull a topic/feature/bugfix branch** (right side). Don't request your master! ## Additional Information
- [ ] DO make sure you are making a pull request against the **master branch** (left side). Also you should start *your branch* off *our master*.
- [ ] DO make sure that File Browser can be successfully built. See [builds](https://github.com/filebrowser/community/blob/master/builds.md) and [development](https://github.com/filebrowser/community/blob/master/development.md).
- [ ] AVOID breaking the continuous integration build.
**Further comments** <!-- If it is a relatively large or complex change, please add more information to explain what you did, how you did it, if you considered any alternatives, etc. -->
<!--
If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did, what alternatives you considered, etc.
:heart: Thank you! ## Checklist
-->
Before submitting your PR, please indicate which issues are either fixed or closed by this PR. See [GitHub Help: Closing issues using keywords](https://help.github.com/articles/closing-issues-via-commit-messages/).
- [ ] I am aware the project is currently in maintenance-only mode. See [README](https://github.com/filebrowser/community/blob/master/README.md)
- [ ] I am aware that translations MUST be made through [Transifex](https://app.transifex.com/file-browser/file-browser/) and that this PR is NOT a translation update
- [ ] I am making a PR against the `master` branch.
- [ ] I am sure File Browser can be successfully built. See [builds](https://github.com/filebrowser/community/blob/master/builds.md) and [development](https://github.com/filebrowser/community/blob/master/development.md).

View File

@@ -3,20 +3,25 @@ name: main
on: on:
push: push:
branches: branches:
- 'master' - "master"
tags: tags:
- 'v*' - "v*"
pull_request: pull_request:
jobs: jobs:
# linters # linters
lint-frontend: lint-frontend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
package_json_file: "frontend/package.json"
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: '18' node-version: "22.x"
cache: "pnpm"
cache-dependency-path: "frontend/pnpm-lock.yaml"
- run: make lint-frontend - run: make lint-frontend
lint-backend: lint-backend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -32,14 +37,19 @@ jobs:
steps: steps:
- run: echo "done" - run: echo "done"
# tests # tests
test-frontend: test-frontend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
package_json_file: "frontend/package.json"
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: '18' node-version: "22.x"
cache: "pnpm"
cache-dependency-path: "frontend/pnpm-lock.yaml"
- run: make test-frontend - run: make test-frontend
test-backend: test-backend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -55,7 +65,7 @@ jobs:
steps: steps:
- run: echo "done" - run: echo "done"
# release # release
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [lint, test] needs: [lint, test]
@@ -67,9 +77,14 @@ jobs:
- uses: actions/setup-go@v5 - uses: actions/setup-go@v5
with: with:
go-version: 1.23.0 go-version: 1.23.0
- uses: pnpm/action-setup@v4
with:
package_json_file: "frontend/package.json"
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: '18' node-version: "22.x"
cache: "pnpm"
cache-dependency-path: "frontend/pnpm-lock.yaml"
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx - name: Set up Docker Buildx

20
.github/workflows/site-pr.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: Build Site
on:
pull_request:
paths:
- 'www'
- '*.md'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build site
run: make site

32
.github/workflows/site-publish.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Build and Deploy Site
on:
push:
branches:
- master
jobs:
deploy:
permissions:
contents: read
deployments: write
pull-requests: write
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build site
run: make site
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy www/public --project-name=${{ secrets.CLOUDFLARE_PROJECT_NAME }}
gitHubToken: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,24 +0,0 @@
name: 'Close stale issues and PRs'
permissions:
issues: write
pull-requests: write
on:
schedule:
- cron: '30 1 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
stale-pr-message: 'This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
close-pr-message: 'This PR was closed because it has been stalled for 5 days with no activity.'
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
days-before-stale: 30
days-before-close: 5
exempt-issue-labels: 'feature ☘,enhancement ⚙,bug 🐞'
exempt-pr-labels: 'need-help,wip'
operations-per-run: 100

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@ rice-box.go
/filebrowser /filebrowser
/filebrowser.exe /filebrowser.exe
/dist /dist
.venv
.DS_Store .DS_Store
node_modules node_modules

View File

@@ -1,121 +1,132 @@
linters-settings: version: "2"
dupl:
threshold: 100
exhaustive:
default-signifies-exhaustive: false
funlen:
lines: 100
statements: 50
goconst:
min-len: 2
min-occurrences: 2
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
disabled-checks:
- dupImport # https://github.com/go-critic/go-critic/issues/845
- ifElseChain
- octalLiteral
- whyNoLint
- wrapperFunc
gocyclo:
min-complexity: 15
goimports:
local-prefixes: github.com/filebrowser/filebrowser
gomnd:
# don't include the "operation" and "assign"
checks:
- argument
- case
- condition
- return
ignored-numbers:
- '0'
- '1'
- '2'
- '3'
ignored-functions:
- strings.SplitN
govet:
enable:
- nilness
- shadow
lll:
line-length: 140
misspell:
locale: US
nolintlint:
allow-unused: false # report any unused nolint directives
require-explanation: false # require an explanation for nolint directives
require-specific: true # require nolint directives to be specific about which linter is being skipped
linters: linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon. # inverted configuration with `default: all` and `disable` is not scalable during updates of golangci-lint
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint default: none
disable-all: true
enable: enable:
- bodyclose - bodyclose
- dogsled - dogsled
- dupl - dupl
- errcheck - errcheck
- errorlint - errorlint
- exportloopref
- exhaustive - exhaustive
- funlen - funlen
- gocheckcompilerdirectives - gocheckcompilerdirectives
- gochecknoinits - gochecknoinits
- goconst
- gocritic - gocritic
- gocyclo - gocyclo
- godox - godox
- goimports
- gomnd
- goprintffuncname - goprintffuncname
- gosec - gosec
- gosimple
- govet - govet
- ineffassign - ineffassign
- lll - lll
- misspell - misspell
- mnd
- nakedret - nakedret
- nolintlint - nolintlint
- prealloc - prealloc
- revive - revive
- rowserrcheck - rowserrcheck
- staticcheck - staticcheck
- stylecheck
- testifylint - testifylint
- typecheck
- unconvert - unconvert
- unparam - unparam
- unused - unused
- whitespace - whitespace
settings:
dupl:
threshold: 100
exhaustive:
default-signifies-exhaustive: false
funlen:
lines: 100
statements: 50
gocritic:
disabled-checks:
- dupImport # https://github.com/go-critic/go-critic/issues/845
- ifElseChain
- octalLiteral
- whyNoLint
- wrapperFunc
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
gocyclo:
min-complexity: 15
govet:
enable:
- nilness
- shadow
lll:
line-length: 140
misspell:
locale: US
mnd:
# don't include the "operation" and "assign"
checks:
- argument
- case
- condition
- return
ignored-numbers:
- "0"
- "1"
- "2"
- "3"
- "0666"
- "0700"
- "0700"
ignored-functions:
- strings.SplitN
- make
nolintlint:
allow-unused: false # report any unused nolint directives
require-explanation: false # require an explanation for nolint directives
require-specific: true # require nolint directives to be specific about which linter is being skipped
staticcheck:
checks:
- "all"
- "-QF*"
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- linters:
- gochecknoinits
path: cmd/.*.go
- linters:
- dupl
- funlen
- gochecknoinits
- gocyclo
- lll
- scopelint
path: .*_test.go
- linters:
- misspell
text: "[aA]uther"
- linters:
- mnd
text: strconv.Parse
paths:
- frontend/
issues: formatters:
exclude-dirs: enable:
- frontend/ - goimports
exclude-rules: settings:
- path: cmd/.*.go goimports:
linters: local-prefixes:
- gochecknoinits - github.com/filebrowser/filebrowser
- path: .*_test.go exclusions:
linters: generated: lax
- lll paths:
- gochecknoinits - frontend/
- gocyclo
- funlen
- dupl
- scopelint
- text: "Auther"
linters:
- misspell
- text: "strconv.Parse"
linters:
- gomnd
run:
timeout: 5m

View File

@@ -19,31 +19,30 @@ builds:
- freebsd - freebsd
goarch: goarch:
- amd64 - amd64
- 386 - "386"
- arm - arm
- arm64 - arm64
- riscv64 - riscv64
goarm: goarm:
- 5 - "5"
- 6 - "6"
- 7 - "7"
ignore: ignore:
- goos: darwin - goos: darwin
goarch: 386 goarch: "386"
- goos: freebsd - goos: freebsd
goarch: arm goarch: arm
archives: archives:
- - name_template: "{{.Os}}-{{.Arch}}{{if .Arm}}v{{.Arm}}{{end}}-{{ .ProjectName }}"
name_template: "{{.Os}}-{{.Arch}}{{if .Arm}}v{{.Arm}}{{end}}-{{ .ProjectName }}" formats: ["tar.gz"]
format: tar.gz
format_overrides: format_overrides:
- goos: windows - goos: windows
format: zip formats: ["zip"]
dockers: dockers:
- # Alpine docker images
dockerfile: Dockerfile - dockerfile: Dockerfile
use: buildx use: buildx
build_flag_templates: build_flag_templates:
- "--pull" - "--pull"
@@ -59,10 +58,8 @@ dockers:
- "filebrowser/filebrowser:{{ .Tag }}-amd64" - "filebrowser/filebrowser:{{ .Tag }}-amd64"
- "filebrowser/filebrowser:v{{ .Major }}-amd64" - "filebrowser/filebrowser:v{{ .Major }}-amd64"
extra_files: extra_files:
- docker_config.json - docker
- healthcheck.sh - dockerfile: Dockerfile
-
dockerfile: Dockerfile
use: buildx use: buildx
build_flag_templates: build_flag_templates:
- "--pull" - "--pull"
@@ -78,10 +75,8 @@ dockers:
- "filebrowser/filebrowser:{{ .Tag }}-arm64" - "filebrowser/filebrowser:{{ .Tag }}-arm64"
- "filebrowser/filebrowser:v{{ .Major }}-arm64" - "filebrowser/filebrowser:v{{ .Major }}-arm64"
extra_files: extra_files:
- docker_config.json - docker
- healthcheck.sh - dockerfile: Dockerfile
-
dockerfile: Dockerfile
use: buildx use: buildx
build_flag_templates: build_flag_templates:
- "--pull" - "--pull"
@@ -93,15 +88,13 @@ dockers:
- "--platform=linux/arm/v6" - "--platform=linux/arm/v6"
goos: linux goos: linux
goarch: arm goarch: arm
goarm: '6' goarm: "6"
image_templates: image_templates:
- "filebrowser/filebrowser:{{ .Tag }}-armv6" - "filebrowser/filebrowser:{{ .Tag }}-armv6"
- "filebrowser/filebrowser:v{{ .Major }}-armv6" - "filebrowser/filebrowser:v{{ .Major }}-armv6"
extra_files: extra_files:
- docker_config.json - docker
- healthcheck.sh - dockerfile: Dockerfile
-
dockerfile: Dockerfile
use: buildx use: buildx
build_flag_templates: build_flag_templates:
- "--pull" - "--pull"
@@ -113,16 +106,15 @@ dockers:
- "--platform=linux/arm/v7" - "--platform=linux/arm/v7"
goos: linux goos: linux
goarch: arm goarch: arm
goarm: '7' goarm: "7"
image_templates: image_templates:
- "filebrowser/filebrowser:{{ .Tag }}-armv7" - "filebrowser/filebrowser:{{ .Tag }}-armv7"
- "filebrowser/filebrowser:v{{ .Major }}-armv7" - "filebrowser/filebrowser:v{{ .Major }}-armv7"
extra_files: extra_files:
- docker_config.json - docker
- healthcheck.sh
## s6 based docker images ## s6-overlay docker images
- - dockerfile: Dockerfile.s6
dockerfile: Dockerfile.s6
use: buildx use: buildx
build_flag_templates: build_flag_templates:
- "--pull" - "--pull"
@@ -138,9 +130,8 @@ dockers:
- "filebrowser/filebrowser:{{ .Tag }}-amd64-s6" - "filebrowser/filebrowser:{{ .Tag }}-amd64-s6"
- "filebrowser/filebrowser:v{{ .Major }}-amd64-s6" - "filebrowser/filebrowser:v{{ .Major }}-amd64-s6"
extra_files: extra_files:
- docker/root - docker
- - dockerfile: Dockerfile.s6.aarch64
dockerfile: Dockerfile.s6.aarch64
use: buildx use: buildx
build_flag_templates: build_flag_templates:
- "--pull" - "--pull"
@@ -156,7 +147,8 @@ dockers:
- "filebrowser/filebrowser:{{ .Tag }}-arm64-s6" - "filebrowser/filebrowser:{{ .Tag }}-arm64-s6"
- "filebrowser/filebrowser:v{{ .Major }}-arm64-s6" - "filebrowser/filebrowser:v{{ .Major }}-arm64-s6"
extra_files: extra_files:
- docker/root - docker
docker_manifests: docker_manifests:
- name_template: "filebrowser/filebrowser:latest" - name_template: "filebrowser/filebrowser:latest"
image_templates: image_templates:
@@ -173,7 +165,7 @@ docker_manifests:
- "filebrowser/filebrowser:v{{ .Major }}-amd64" - "filebrowser/filebrowser:v{{ .Major }}-amd64"
- "filebrowser/filebrowser:v{{ .Major }}-arm64" - "filebrowser/filebrowser:v{{ .Major }}-arm64"
- "filebrowser/filebrowser:v{{ .Major }}-armv7" - "filebrowser/filebrowser:v{{ .Major }}-armv7"
## s6 image manifests ## s6 image manifests
- name_template: "filebrowser/filebrowser:s6" - name_template: "filebrowser/filebrowser:s6"
image_templates: image_templates:
- "filebrowser/filebrowser:{{ .Tag }}-amd64-s6" - "filebrowser/filebrowser:{{ .Tag }}-amd64-s6"
@@ -186,15 +178,20 @@ docker_manifests:
image_templates: image_templates:
- "filebrowser/filebrowser:v{{ .Major }}-amd64-s6" - "filebrowser/filebrowser:v{{ .Major }}-amd64-s6"
- "filebrowser/filebrowser:v{{ .Major }}-arm64-s6" - "filebrowser/filebrowser:v{{ .Major }}-arm64-s6"
brews:
homebrew_casks:
- name: filebrowser - name: filebrowser
repository: repository:
owner: filebrowser owner: filebrowser
name: homebrew-tap name: homebrew-tap
directory: Formula
homepage: https://filebrowser.org
commit_author: commit_author:
name: FileBrowser Robot name: FileBrowser Robot
email: robot@filebrowser.org email: robot@filebrowser.org
homepage: https://github.com/filebrowser/filebrowser
description: File Browser is a create-your-own-cloud-kind of software where you can install it on a server, direct it to a path and then access your files through a nice web interface description: File Browser is a create-your-own-cloud-kind of software where you can install it on a server, direct it to a path and then access your files through a nice web interface
license: "MIT" hooks:
post:
install: |
if system_command("/usr/bin/xattr", args: ["-h"]).exit_status == 0
system_command "/usr/bin/xattr", args: ["-dr", "com.apple.quarantine", "#{staged_path}/filebrowser"]
end

View File

@@ -1,10 +0,0 @@
[main]
host = https://www.transifex.com
lang_map = pt_BR: pt-br, zh_CN: zh-cn, zh_HK: zh-hk, zh_TW: zh-tw, nl_BE: nl-be, sv_SE: sv-se, cz-CS: cz_cs
[file-browser.file-browser]
file_filter = frontend/src/i18n/<lang>.json
minimum_perc = 50
source_file = frontend/src/i18n/en.json
source_lang = en
type = KEYVALUEJSON

View File

@@ -2,6 +2,217 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [2.35.0](https://github.com/filebrowser/filebrowser/compare/v2.34.2...v2.35.0) (2025-06-30)
### Features
* Long press selects item in single click mode ([8d75220](https://github.com/filebrowser/filebrowser/commit/8d7522049ced83f28f0933b55772c32e3ad04627))
### Bug Fixes
* shell value must be joined by blank space ([4403cd3](https://github.com/filebrowser/filebrowser/commit/4403cd35720dbda5a8bb1013b92582accf3317bc))
* update documentation links ([38d0366](https://github.com/filebrowser/filebrowser/commit/38d0366acf88352b5a9a97c45837b0f865efae0b))
### [2.34.2](https://github.com/filebrowser/filebrowser/compare/v2.34.1...v2.34.2) (2025-06-29)
### Bug Fixes
* mitigate unprotected shares ([2b5d6cb](https://github.com/filebrowser/filebrowser/commit/2b5d6cbb996a61a769acc56af0acc12eec2d8d8f))
### [2.34.1](https://github.com/filebrowser/filebrowser/compare/v2.34.0...v2.34.1) (2025-06-29)
### Bug Fixes
* exclude to-be-moved folder from move dialog ([#5235](https://github.com/filebrowser/filebrowser/issues/5235)) ([7354eb6](https://github.com/filebrowser/filebrowser/commit/7354eb6cf966244141277c2808988855c004f908))
* passthrough the minimum password length ([#5236](https://github.com/filebrowser/filebrowser/issues/5236)) ([bf37f88](https://github.com/filebrowser/filebrowser/commit/bf37f88c32222ad9c186482bb97338a9c9b4a93c))
## [2.34.0](https://github.com/filebrowser/filebrowser/compare/v2.33.10...v2.34.0) (2025-06-29)
### Features
* Translate frontend/src/i18n/en.json in fa ([0acd69c](https://github.com/filebrowser/filebrowser/commit/0acd69c537ce2909ff62c4bb6980982524ece221))
* Translate frontend/src/i18n/en.json in fa ([#5233](https://github.com/filebrowser/filebrowser/issues/5233)) ([09f679f](https://github.com/filebrowser/filebrowser/commit/09f679fae43398f5b87d21acc9d974d4d053392f))
* update translations for project File Browser ([#5226](https://github.com/filebrowser/filebrowser/issues/5226)) ([a5ea2a2](https://github.com/filebrowser/filebrowser/commit/a5ea2a266bef619d1c4322266d1aa7d397d2c856))
### Bug Fixes
* abort ongoing requests when changing pages ([#3927](https://github.com/filebrowser/filebrowser/issues/3927)) ([93c4b2e](https://github.com/filebrowser/filebrowser/commit/93c4b2e03c5176da01a7e00a03c03ffcce279bc8))
* add configurable minimum password length ([#5225](https://github.com/filebrowser/filebrowser/issues/5225)) ([464b644](https://github.com/filebrowser/filebrowser/commit/464b644adf22a2178414a6f1e4fa286276de81d2))
* do not expose the name of the root directory ([#5224](https://github.com/filebrowser/filebrowser/issues/5224)) ([0892559](https://github.com/filebrowser/filebrowser/commit/089255997a653c284cd4249990b58bed00086c61))
* Graceful shutdown ([8230eb7](https://github.com/filebrowser/filebrowser/commit/8230eb7ab51ccbd00b03f5b9d6964fa4aae331d4))
### Reverts
* Revert "docs: change cloudflare environment (#5231)" (#5232) ([9e273cd](https://github.com/filebrowser/filebrowser/commit/9e273cd9475d57b9500034e8b341ff8b620bcab8)), closes [#5231](https://github.com/filebrowser/filebrowser/issues/5231) [#5232](https://github.com/filebrowser/filebrowser/issues/5232)
### Build
* add an arm64 target for the site image ([#5229](https://github.com/filebrowser/filebrowser/issues/5229)) ([f5e531c](https://github.com/filebrowser/filebrowser/commit/f5e531c8ae0b9b18717e184856ace0ce19beef82))
* bump golangci-lint to 2.1.6 ([1d494ff](https://github.com/filebrowser/filebrowser/commit/1d494ff3159ef939cfb4980ccde6f27df3e738b5))
* **deps:** bump brace-expansion from 1.1.11 to 1.1.12 in /tools ([#5228](https://github.com/filebrowser/filebrowser/issues/5228)) ([5a07291](https://github.com/filebrowser/filebrowser/commit/5a072913062a6b2b0e5c74a02ca7710218ed3e5e))
* **deps:** bump github.com/go-viper/mapstructure/v2 ([f32f273](https://github.com/filebrowser/filebrowser/commit/f32f27383d1fafa074f038cc873bd37b7f20ee27))
* **deps:** bump github.com/go-viper/mapstructure/v2 in /tools ([5331969](https://github.com/filebrowser/filebrowser/commit/5331969163f5ae1fd2389f665059fc9e4a98db15))
* publish docs to cloudflare pages ([#5230](https://github.com/filebrowser/filebrowser/issues/5230)) ([8861933](https://github.com/filebrowser/filebrowser/commit/8861933cf845b104e072f35e5f37d7c26097c9dc))
### [2.33.10](https://github.com/filebrowser/filebrowser/compare/v2.33.9...v2.33.10) (2025-06-26)
### Bug Fixes
* correctly check if command is allowed when using shell ([4d830f7](https://github.com/filebrowser/filebrowser/commit/4d830f707fc4314741fd431e70c2ce50cd5a3108))
* correctly split shell ([f84a6db](https://github.com/filebrowser/filebrowser/commit/f84a6db680b6df1c7c8f06f1816f7e4c9e963668))
* ignore linting error ([e735491](https://github.com/filebrowser/filebrowser/commit/e735491c57b12c3b19dd2e4b570723df78f4eb44))
### [2.33.9](https://github.com/filebrowser/filebrowser/compare/v2.33.8...v2.33.9) (2025-06-26)
### Bug Fixes
* check exact match on command allow list ([e2e1e49](https://github.com/filebrowser/filebrowser/commit/e2e1e4913085cca8917e0f69171dc28d3c6af1b6))
* remove auth token from /api/command ([d5b39a1](https://github.com/filebrowser/filebrowser/commit/d5b39a14fd3fc0d1c364116b41289484df7c27b2))
* remove unused import ([c232d41](https://github.com/filebrowser/filebrowser/commit/c232d41f903d3026ec290bbe819b6c59a933048e))
### [2.33.8](https://github.com/filebrowser/filebrowser/compare/v2.33.7...v2.33.8) (2025-06-25)
### [2.33.7](https://github.com/filebrowser/filebrowser/compare/v2.33.6...v2.33.7) (2025-06-25)
### Bug Fixes
* correctly parse negative boolean flags ([221451a](https://github.com/filebrowser/filebrowser/commit/221451a5179c8f139819a315b80d0ecb0e7220c3))
* linting issues ([4bfbf33](https://github.com/filebrowser/filebrowser/commit/4bfbf332499fc8aea5f6df6aae1efa0de918d1ae))
* linting issues ([e74c958](https://github.com/filebrowser/filebrowser/commit/e74c95886226c0ee429af1860eed21dd1f8601aa))
### [2.33.6](https://github.com/filebrowser/filebrowser/compare/v2.33.5...v2.33.6) (2025-06-24)
### Bug Fixes
* remove incorrect default for password flag ([23bd8f6](https://github.com/filebrowser/filebrowser/commit/23bd8f67155081d707d4799393d3b1e2bebeaa34))
### [2.33.5](https://github.com/filebrowser/filebrowser/compare/v2.33.4...v2.33.5) (2025-06-24)
### Features
* update languages for project File Browser ([#5190](https://github.com/filebrowser/filebrowser/issues/5190)) ([f330764](https://github.com/filebrowser/filebrowser/commit/f33076462a133935ca97fb6c7345303fe350e167))
### Bug Fixes
* actually register the czech language ([#5189](https://github.com/filebrowser/filebrowser/issues/5189)) ([0268506](https://github.com/filebrowser/filebrowser/commit/0268506f80d33d2d31e38055e12530241d27a11b))
### [2.33.4](https://github.com/filebrowser/filebrowser/compare/v2.33.3...v2.33.4) (2025-06-22)
### Features
* translation updates for project File Browser ([#5179](https://github.com/filebrowser/filebrowser/issues/5179)) ([f714e71](https://github.com/filebrowser/filebrowser/commit/f714e71a356c2301f394d651c9b6c467440508e3))
### [2.33.3](https://github.com/filebrowser/filebrowser/compare/v2.33.2...v2.33.3) (2025-06-22)
### Bug Fixes
* keep command behavior in Dockerfile ([7c0c782](https://github.com/filebrowser/filebrowser/commit/7c0c7820efbbed2f0499353cc76ecb85d00ff7c3))
* update search hotkey in help prompt ([#5178](https://github.com/filebrowser/filebrowser/issues/5178)) ([2741616](https://github.com/filebrowser/filebrowser/commit/2741616473636d40b7e9f14c9906ada08d328c3c))
### [2.33.2](https://github.com/filebrowser/filebrowser/compare/v2.33.1...v2.33.2) (2025-06-21)
### Bug Fixes
* create user dir on signup ([0ca8059](https://github.com/filebrowser/filebrowser/commit/0ca8059d8dea4fe079146471ce4f24acc96021f2))
### [2.33.1](https://github.com/filebrowser/filebrowser/compare/v2.33.0...v2.33.1) (2025-06-21)
### Bug Fixes
* downloadUrl of file preview ([#3728](https://github.com/filebrowser/filebrowser/issues/3728)) ([8a14018](https://github.com/filebrowser/filebrowser/commit/8a14018861fe581672bbd27cdc3ae5691f70a108))
* remove auth query parameter from download and preview links ([cbb7124](https://github.com/filebrowser/filebrowser/commit/cbb712484d3bdabc033acaf3b696ef4f5865813d))
* search uses ctrl+shift+f instead of hijacking browser's ctrl+f ([#4638](https://github.com/filebrowser/filebrowser/issues/4638)) ([a02b297](https://github.com/filebrowser/filebrowser/commit/a02b2972ebde2a58806ad1377bad46e748b63166))
## [2.33.0](https://github.com/filebrowser/filebrowser/compare/v2.32.3...v2.33.0) (2025-06-18)
### Features
* improved docker image volumes and permissions ([#5160](https://github.com/filebrowser/filebrowser/issues/5160)) ([2e26393](https://github.com/filebrowser/filebrowser/commit/2e26393a022df0eaa9e08727407aba8b997aa728))
### [2.32.3](https://github.com/filebrowser/filebrowser/compare/v2.32.2...v2.32.3) (2025-06-17)
### [2.32.2](https://github.com/filebrowser/filebrowser/compare/v2.32.1...v2.32.2) (2025-06-17)
### Features
* updated for project File Browser ([#5159](https://github.com/filebrowser/filebrowser/issues/5159)) ([c34c0af](https://github.com/filebrowser/filebrowser/commit/c34c0afecf3242b16ad5d5584cd90a6ad323361c))
### [2.32.1](https://github.com/filebrowser/filebrowser/compare/v2.32.0...v2.32.1) (2025-06-16)
### Features
* add Vietnamese translation ([#3840](https://github.com/filebrowser/filebrowser/issues/3840)) ([56b80b6](https://github.com/filebrowser/filebrowser/commit/56b80b6d9b4710538765ba7df5da1f03898f6b81))
* improve pt-br translations with new keys and refinements ([#4903](https://github.com/filebrowser/filebrowser/issues/4903)) ([a882fb6](https://github.com/filebrowser/filebrowser/commit/a882fb6c85ab6ccc845ed0bf3908d8e5e60ce346))
* update translation ko.json ([#3852](https://github.com/filebrowser/filebrowser/issues/3852)) ([d9ebd65](https://github.com/filebrowser/filebrowser/commit/d9ebd65ffcf9b2166fec708d51849796d12b16e0))
### Bug Fixes
* err shadowing lint ([c606a01](https://github.com/filebrowser/filebrowser/commit/c606a01a2d20932fb32ee896234d57631f8c47e4))
* generate random admin password on quick setup ([a46acba](https://github.com/filebrowser/filebrowser/commit/a46acba5f92ee044661880d6ae349e289d984328)), closes [#3646](https://github.com/filebrowser/filebrowser/issues/3646)
* imports lint ([54b91b8](https://github.com/filebrowser/filebrowser/commit/54b91b8ff0b8ee1f02f72425ab97d27a5d942fc3))
* set videojs locale ([#3742](https://github.com/filebrowser/filebrowser/issues/3742)) ([71a8f56](https://github.com/filebrowser/filebrowser/commit/71a8f5662c207e3cd4ee714a5b5a961121f510cd))
### Build
* **deps-dev:** bump vite from 6.0.11 to 6.1.6 in /frontend ([#3886](https://github.com/filebrowser/filebrowser/issues/3886)) ([5355629](https://github.com/filebrowser/filebrowser/commit/5355629fd1e7bd85ee3222fca22da899ba23ea95))
* **deps:** bump golang.org/x/crypto from 0.31.0 to 0.35.0 ([#3865](https://github.com/filebrowser/filebrowser/issues/3865)) ([0ba9505](https://github.com/filebrowser/filebrowser/commit/0ba9505a19cb369653fc9f8260dc02fcc6587629))
* **deps:** bump golang.org/x/net from 0.33.0 to 0.38.0 ([#3869](https://github.com/filebrowser/filebrowser/issues/3869)) ([cfea84f](https://github.com/filebrowser/filebrowser/commit/cfea84fd5e7ec9c1d2366293e5db12baaa4e3a81))
* **deps:** bump vue-i18n from 11.0.1 to 11.1.2 in /frontend ([#3786](https://github.com/filebrowser/filebrowser/issues/3786)) ([35d1c09](https://github.com/filebrowser/filebrowser/commit/35d1c092434b80b22c89a614a02122e9f5965b39))
## [2.32.0](https://github.com/filebrowser/filebrowser/compare/v2.31.2...v2.32.0) (2025-01-31)
### Features
* create user on proxy authentication if user does not exist ([#3569](https://github.com/filebrowser/filebrowser/issues/3569)) ([209acf2](https://github.com/filebrowser/filebrowser/commit/209acf2429b06e2e8d78218937c59fd7e7edd1be))
### Bug Fixes
* add proper healthcheck for S6 containers ([#3691](https://github.com/filebrowser/filebrowser/issues/3691)) ([045064f](https://github.com/filebrowser/filebrowser/commit/045064f8b8bf9f86058e877448085e38da8b3f2e))
* disk usage refreshing ([#3692](https://github.com/filebrowser/filebrowser/issues/3692)) ([bbdd313](https://github.com/filebrowser/filebrowser/commit/bbdd313705b8d253f0c47ad717a6e47b2f46e719))
* Fix user creation on proxy auth ([#3666](https://github.com/filebrowser/filebrowser/issues/3666)) ([5300d00](https://github.com/filebrowser/filebrowser/commit/5300d00d2e7dbb80a252aff57e100113f02506c3))
* prompts disappearing on copy / move / upload ([#3537](https://github.com/filebrowser/filebrowser/issues/3537)) ([d1c84a8](https://github.com/filebrowser/filebrowser/commit/d1c84a84123c77dede05c023b3697a432b56122c))
### Refactorings
* Fix eslint warnings ([#3698](https://github.com/filebrowser/filebrowser/issues/3698)) ([0201f9c](https://github.com/filebrowser/filebrowser/commit/0201f9c5c4dd2a4d5a3503e59cdb8045e8d3a91f)), closes [#3407](https://github.com/filebrowser/filebrowser/issues/3407)
### Build
* **deps:** bump cross-spawn from 7.0.3 to 7.0.6 in /tools ([#3601](https://github.com/filebrowser/filebrowser/issues/3601)) ([25372ed](https://github.com/filebrowser/filebrowser/commit/25372edb5c0e616e82b76b5f523633af57d347e0))
* **deps:** bump github.com/golang-jwt/jwt/v4 from 4.5.0 to 4.5.1 ([#3574](https://github.com/filebrowser/filebrowser/issues/3574)) ([2fdea73](https://github.com/filebrowser/filebrowser/commit/2fdea73430011846276a1cda52458f1d670f5ea7))
* **deps:** bump golang.org/x/crypto from 0.26.0 to 0.31.0 ([#3634](https://github.com/filebrowser/filebrowser/issues/3634)) ([e92dbb4](https://github.com/filebrowser/filebrowser/commit/e92dbb4bb8b7894264fbf0a48a641712c3b68766))
* **deps:** bump golang.org/x/net from 0.23.0 to 0.33.0 ([#3712](https://github.com/filebrowser/filebrowser/issues/3712)) ([1194cfe](https://github.com/filebrowser/filebrowser/commit/1194cfe0097a70399c1f06cf0f514b9d70fa463c))
* **deps:** bump vue-i18n from 9.10.2 to 9.14.2 in /frontend ([#3618](https://github.com/filebrowser/filebrowser/issues/3618)) ([0659594](https://github.com/filebrowser/filebrowser/commit/065959451d3ba12019c6151274aa4e6904cdca99))
* fix go releaser ([ba797cd](https://github.com/filebrowser/filebrowser/commit/ba797cda3135eddb9b7165dc5ceb932399cb54df))
* update to node 22 and pnpm ([#3616](https://github.com/filebrowser/filebrowser/issues/3616)) ([d51a343](https://github.com/filebrowser/filebrowser/commit/d51a3438201274a1b826be1b775ca1035ade20c5))
### [2.31.2](https://github.com/filebrowser/filebrowser/compare/v2.31.1...v2.31.2) (2024-10-03) ### [2.31.2](https://github.com/filebrowser/filebrowser/compare/v2.31.1...v2.31.2) (2024-10-03)

46
CODE-OF-CONDUCT.md Normal file
View File

@@ -0,0 +1,46 @@
# Code of Conduct
## Contributor Covenant Code of Conduct
### Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
### Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
### Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
### Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hacdias@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.4, available at [https://contributor-covenant.org/version/1/4](https://contributor-covenant.org/version/1/4).

91
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,91 @@
# Contributing
If you're interested in contributing to this project, this is the best place to start. Before contributing to this project, please take a bit of time to read our [Code of Conduct](code-of-conduct.md). Also, note that this project is open-source and licensed under [Apache License 2.0](LICENSE).
## Project Structure
The backend side of the application is written in [Go](https://golang.org/), while the frontend (located on a subdirectory of the same name) is written in [Vue.js](https://vuejs.org/). Due to the tight coupling required by some features, basic knowledge of both Go and Vue.js is recommended.
* Learn Go: [https://github.com/golang/go/wiki/Learn](https://github.com/golang/go/wiki/Learn)
* Learn Vue.js: [https://vuejs.org/guide/introduction.html](https://vuejs.org/guide/introduction.html)
We encourage you to use git to manage your fork. To clone the main repository, just run:
```bash
git clone https://github.com/filebrowser/filebrowser
```
## Build
### Frontend
We are using [Node.js](https://nodejs.org/en/) on the frontend to manage the build process. The steps to build it are:
```bash
# From the root of the repo, go to frontend/
cd frontend
# Install the dependencies
pnpm install
# Build the frontend
pnpm run build
```
This will install the dependencies and build the frontend so you can then embed it into the Go app. Although, if you want to play with it, you'll get bored of building it after every change you do. So, you can run the command below to watch for changes:
```bash
pnpm run dev
```
### Backend
First of all, you need to download the required dependencies. We are using the built-in `go mod` tool for dependency management. To get the modules, run:
```bash
go mod download
```
The magic of File Browser is that the static assets are bundled into the final binary. For that, we use [Go embed.FS](https://golang.org/pkg/embed/). The files from `frontend/dist` will be embedded during the build process.
To build File Browser is just like any other Go program:
```bash
go build
```
To create a development build use the "dev" tag, this way the content inside the frontend folder will not be embedded in the binary but will be reloaded at every change:
```bash
go build -tags dev
```
## Translations
Translations are managed on Transifex, which is an online website where everyone can contribute and translate strings for our project. It automatically syncs with the main language file \(in English\) and,, for you to contribute, you just need to:
1. Go to our Transifex web page: [app.transifex.com/file-browser/file-browser](https://app.transifex.com/file-browser/file-browser/)
2. Click on **Join the project** and pick your language. We'll accept you as soon as possible. If you're language is not on the list, please request it via the interface.
Translations are automatically pushed to GitHub via an integration.
## Authentication Provider
To build a new authentication provider, you need to implement the [Auther interface](https://github.com/filebrowser/filebrowser/blob/master/auth/auth.go), whose method will be called on the login page after the user has submitted their login data.
```go
// Auther is the authentication interface.
type Auther interface {
// Auth is called to authenticate a request.
Auth(r *http.Request, s *users.Storage, root string) (*users.User, error)
}
```
After implementing the interface you should:
1. Add it to [`auth` directory](https://github.com/filebrowser/filebrowser/blob/master/auth).
2. Add it to the [configuration parser](https://github.com/filebrowser/filebrowser/blob/master/cmd/config.go) for the CLI.
3. Add it to the [`authBackend.Get`](https://github.com/filebrowser/filebrowser/blob/master/storage/bolt/auth.go).
If you need to add more flags, please update the function `addConfigFlags`.

View File

@@ -1,19 +1,32 @@
FROM alpine:latest FROM alpine:3.22
RUN apk --update add ca-certificates \
mailcap \
curl \
jq
COPY healthcheck.sh /healthcheck.sh RUN apk update && \
RUN chmod +x /healthcheck.sh # Make the script executable apk --no-cache add ca-certificates mailcap curl jq tini
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \ # Make user and create necessary directories
CMD /healthcheck.sh || exit 1 ENV UID=1000
ENV GID=1000
RUN addgroup -g $GID user && \
adduser -D -u $UID -G user user && \
mkdir -p /config /database /srv && \
chown -R user:user /config /database /srv
# Copy files and set permissions
COPY filebrowser /bin/filebrowser
COPY docker/common/ /
COPY docker/alpine/ /
RUN chown -R user:user /bin/filebrowser /defaults healthcheck.sh init.sh
# Define healthcheck script
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s CMD /healthcheck.sh
# Set the user, volumes and exposed ports
USER user
VOLUME /srv /config /database
VOLUME /srv
EXPOSE 80 EXPOSE 80
COPY docker_config.json /.filebrowser.json ENTRYPOINT [ "tini", "--", "/init.sh", "filebrowser", "--config", "/config/settings.json" ]
COPY filebrowser /filebrowser
ENTRYPOINT [ "/filebrowser" ]

View File

@@ -1,16 +1,23 @@
FROM ghcr.io/linuxserver/baseimage-alpine:3.20 FROM ghcr.io/linuxserver/baseimage-alpine:3.22
RUN apk --update add ca-certificates \ RUN apk update && \
mailcap \ apk --no-cache add ca-certificates mailcap curl jq
curl
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \ # Make user and create necessary directories
CMD curl -f http://localhost/health || exit 1 RUN mkdir -p /config /database /srv && \
chown -R abc:abc /config /database /srv
# copy local files # Copy files and set permissions
COPY docker/root/ / COPY filebrowser /bin/filebrowser
COPY filebrowser /usr/bin/filebrowser COPY docker/common/ /
COPY docker/s6/ /
# ports and volumes RUN chown -R abc:abc /bin/filebrowser /defaults healthcheck.sh
# Define healthcheck script
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s CMD /healthcheck.sh
# Set the volumes and exposed ports
VOLUME /srv /config /database VOLUME /srv /config /database
EXPOSE 80 EXPOSE 80

View File

@@ -1,16 +1,23 @@
FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.20 FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.22
RUN apk --update add ca-certificates \ RUN apk update && \
mailcap \ apk --no-cache add ca-certificates mailcap curl jq
curl
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s \ # Make user and create necessary directories
CMD curl -f http://localhost/health || exit 1 RUN mkdir -p /config /database /srv && \
chown -R abc:abc /config /database /srv
# copy local files # Copy files and set permissions
COPY docker/root/ / COPY filebrowser /bin/filebrowser
COPY filebrowser /usr/bin/filebrowser COPY docker/common/ /
COPY docker/s6/ /
# ports and volumes RUN chown -R abc:abc /bin/filebrowser /defaults healthcheck.sh
# Define healthcheck script
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s CMD /healthcheck.sh
# Set the volumes and exposed ports
VOLUME /srv /config /database VOLUME /srv /config /database
EXPOSE 80 EXPOSE 80

View File

@@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2018 File Browser contributors Copyright 2018 File Browser Contributors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -3,6 +3,14 @@ include tools.mk
LDFLAGS += -X "$(MODULE)/version.Version=$(VERSION)" -X "$(MODULE)/version.CommitSHA=$(VERSION_HASH)" LDFLAGS += -X "$(MODULE)/version.Version=$(VERSION)" -X "$(MODULE)/version.CommitSHA=$(VERSION_HASH)"
SITE_DOCKER_FLAGS = \
-v $(CURDIR)/www:/docs \
-v $(CURDIR)/LICENSE:/docs/docs/LICENSE \
-v $(CURDIR)/SECURITY.md:/docs/docs/security.md \
-v $(CURDIR)/CHANGELOG.md:/docs/docs/changelog.md \
-v $(CURDIR)/CODE-OF-CONDUCT.md:/docs/docs/code-of-conduct.md \
-v $(CURDIR)/CONTRIBUTING.md:/docs/docs/contributing.md
## Build: ## Build:
.PHONY: build .PHONY: build
@@ -10,7 +18,7 @@ build: | build-frontend build-backend ## Build binary
.PHONY: build-frontend .PHONY: build-frontend
build-frontend: ## Build frontend build-frontend: ## Build frontend
$Q cd frontend && npm ci && npm run build $Q cd frontend && pnpm install --frozen-lockfile && pnpm run build
.PHONY: build-backend .PHONY: build-backend
build-backend: ## Build backend build-backend: ## Build backend
@@ -21,6 +29,7 @@ test: | test-frontend test-backend ## Run all tests
.PHONY: test-frontend .PHONY: test-frontend
test-frontend: ## Run frontend tests test-frontend: ## Run frontend tests
$Q cd frontend && pnpm install --frozen-lockfile && pnpm run typecheck
.PHONY: test-backend .PHONY: test-backend
test-backend: ## Run backend tests test-backend: ## Run backend tests
@@ -31,7 +40,7 @@ lint: lint-frontend lint-backend ## Run all linters
.PHONY: lint-frontend .PHONY: lint-frontend
lint-frontend: ## Run frontend linters lint-frontend: ## Run frontend linters
$Q cd frontend && npm ci && npm run lint $Q cd frontend && pnpm install --frozen-lockfile && pnpm run lint
.PHONY: lint-backend .PHONY: lint-backend
lint-backend: | $(golangci-lint) ## Run backend linters lint-backend: | $(golangci-lint) ## Run backend linters
@@ -52,6 +61,17 @@ clean: clean-tools ## Clean
bump-version: $(standard-version) ## Bump app version bump-version: $(standard-version) ## Bump app version
$Q ./scripts/bump_version.sh $Q ./scripts/bump_version.sh
.PHONY: site
site: ## Build site
@rm -rf www/public
docker build -f www/Dockerfile --progress=plain -t filebrowser.site www
docker run --rm $(SITE_DOCKER_FLAGS) filebrowser.site build -d "public"
.PHONY: site-serve
site-serve: ## Serve site for development
docker build -f www/Dockerfile --progress=plain -t filebrowser.site www
docker run --rm -it -p 8000:8000 $(SITE_DOCKER_FLAGS) filebrowser.site
## Help: ## Help:
help: ## Show this help help: ## Show this help
@echo '' @echo ''

View File

@@ -2,38 +2,37 @@
<img src="https://raw.githubusercontent.com/filebrowser/logo/master/banner.png" width="550"/> <img src="https://raw.githubusercontent.com/filebrowser/logo/master/banner.png" width="550"/>
</p> </p>
![Preview](https://user-images.githubusercontent.com/5447088/50716739-ebd26700-107a-11e9-9817-14230c53efd2.gif)
[![Build](https://github.com/filebrowser/filebrowser/actions/workflows/main.yaml/badge.svg)](https://github.com/filebrowser/filebrowser/actions/workflows/main.yaml) [![Build](https://github.com/filebrowser/filebrowser/actions/workflows/main.yaml/badge.svg)](https://github.com/filebrowser/filebrowser/actions/workflows/main.yaml)
[![Go Report Card](https://goreportcard.com/badge/github.com/filebrowser/filebrowser?style=flat-square)](https://goreportcard.com/report/github.com/filebrowser/filebrowser) [![Go Report Card](https://goreportcard.com/badge/github.com/filebrowser/filebrowser)](https://goreportcard.com/report/github.com/filebrowser/filebrowser)
[![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](http://godoc.org/github.com/filebrowser/filebrowser) [![Documentation](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/filebrowser/filebrowser)
[![Version](https://img.shields.io/github/release/filebrowser/filebrowser.svg?style=flat-square)](https://github.com/filebrowser/filebrowser/releases/latest) [![Version](https://img.shields.io/github/release/filebrowser/filebrowser.svg)](https://github.com/filebrowser/filebrowser/releases/latest)
[![Chat IRC](https://img.shields.io/badge/freenode-%23filebrowser-blue.svg?style=flat-square)](http://webchat.freenode.net/?channels=%23filebrowser) [![Chat IRC](https://img.shields.io/badge/freenode-%23filebrowser-blue.svg)](http://webchat.freenode.net/?channels=%23filebrowser)
filebrowser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit your files. It allows the creation of multiple users and each user can have its own directory. It can be used as a standalone app. File Browser provides a file managing interface within a specified directory and it can be used to upload, delete, preview and edit your files. It is a **create-your-own-cloud**-kind of software where you can just install it on your server, direct it to a path and access your files through a nice web interface.
## Demo ## Documentation
url: https://demo.filebrowser.org/ Documentation on how to install, configure, and contribute to this project is hosted at [filebrowser.org](https://filebrowser.org).
credentials: `demo`/`demo` ## Project Status
## Features > [!WARNING]
>
> This project is currently on **maintenance-only** mode, and is looking for new maintainers. For more information, please read the [discussion #4906](https://github.com/filebrowser/filebrowser/discussions/4906). Therefore, please note the following:
>
> - It can take a while until someone gets back to you. Please be patient.
> - [Issues][issues] are only being used to track bugs. Any unrelated issues will be converted into a [discussion][discussions].
> - No new features will be implemented until further notice. The priority is on triaging issues and merge bug fixes.
>
> If you're interested in maintaining this project, please reach out via the discussion above.
Please refer to our docs at [https://filebrowser.org/features](https://filebrowser.org/features) [issues]: https://github.com/filebrowser/filebrowser/issues
[discussions]: https://github.com/filebrowser/filebrowser/discussions
## Install
For installation instructions please refer to our docs at [https://filebrowser.org/installation](https://filebrowser.org/installation).
## Configuration
[Authentication Method](https://filebrowser.org/configuration/authentication-method) - You can change the way the user authenticates with the filebrowser server
[Command Runner](https://filebrowser.org/configuration/command-runner) - The command runner is a feature that enables you to execute any shell command you want before or after a certain event.
[Custom Branding](https://filebrowser.org/configuration/custom-branding) - You can customize your File Browser installation by change its name to any other you want, by adding a global custom style sheet and by using your own logotype if you want.
## Contributing ## Contributing
If you're interested in contributing to this project, our docs are best places to start [https://filebrowser.org/contributing](https://filebrowser.org/contributing). Contributions are always welcome. To start contributing to this project, read our [guidelines](CONTRIBUTING.md) first.
## License
[Apache License 2.0](LICENSE) © File Browser Contributors

View File

@@ -12,7 +12,9 @@ currently being supported with security updates.
## Reporting a Vulnerability ## Reporting a Vulnerability
Vulnerabilities should be reported to filebrowser@googlegroups.com - which is a private, maintainer-only group. Maintainers will attempt to respond to/confirm reports within 2-3 days, but if you believe your report to be "critical" to user safety and security, please note as such in the subject. We have tens of thousands of users using our software, and take security vulnerabilities seriously. Vulnerabilities with critical impact should be reported on the [Security](https://github.com/filebrowser/filebrowser/security) page of this repository, which is a private way of communicating vulnerabilities to maintainers. This project is in maintenance-only mode and it can take a while until someone gets back to you.
If it is not a critical vulnerability, please open an issue and we will categorize it as a security issue. By giving visibility, we can get more help from the community at fixing such issues.
When reporting an issue, where possible, please provide at least: When reporting an issue, where possible, please provide at least:
@@ -21,6 +23,4 @@ When reporting an issue, where possible, please provide at least:
* Steps to reproduce * Steps to reproduce
* Your recommended remediation(s), if any. * Your recommended remediation(s), if any.
The FileBrowser team is a volunteer-only effort, and may reach back out for clarification. The File Browser team is a volunteer-only effort, and may reach back out for clarification.
> Note: Please do not open public issues for security issues, as GitHub does not provide facility for private issues, and deleting the issue makes it hard to triage/respond back to the reporter.

View File

@@ -150,7 +150,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
} }
if u == nil { if u == nil {
pass, err := users.HashPwd(a.Cred.Password) pass, err := users.ValidateAndHashPwd(a.Cred.Password, a.Settings.MinimumPasswordLength)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -186,7 +186,7 @@ func (a *HookAuth) SaveUser() (*users.User, error) {
// update the password when it doesn't match the current // update the password when it doesn't match the current
if p { if p {
pass, err := users.HashPwd(a.Cred.Password) pass, err := users.ValidateAndHashPwd(a.Cred.Password, a.Settings.MinimumPasswordLength)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -3,7 +3,6 @@ package auth
import ( import (
"errors" "errors"
"net/http" "net/http"
"os"
fbErrors "github.com/filebrowser/filebrowser/v2/errors" fbErrors "github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
@@ -19,14 +18,48 @@ type ProxyAuth struct {
} }
// Auth authenticates the user via an HTTP header. // Auth authenticates the user via an HTTP header.
func (a ProxyAuth) Auth(r *http.Request, usr users.Store, _ *settings.Settings, srv *settings.Server) (*users.User, error) { func (a ProxyAuth) Auth(r *http.Request, usr users.Store, setting *settings.Settings, srv *settings.Server) (*users.User, error) {
username := r.Header.Get(a.Header) username := r.Header.Get(a.Header)
user, err := usr.Get(srv.Root, username) user, err := usr.Get(srv.Root, username)
if errors.Is(err, fbErrors.ErrNotExist) { if errors.Is(err, fbErrors.ErrNotExist) {
return nil, os.ErrPermission return a.createUser(usr, setting, srv, username)
}
return user, err
}
func (a ProxyAuth) createUser(usr users.Store, setting *settings.Settings, srv *settings.Server, username string) (*users.User, error) {
const randomPasswordLength = settings.DefaultMinimumPasswordLength + 10
pwd, err := users.RandomPwd(randomPasswordLength)
if err != nil {
return nil, err
} }
return user, err var hashedRandomPassword string
hashedRandomPassword, err = users.ValidateAndHashPwd(pwd, setting.MinimumPasswordLength)
if err != nil {
return nil, err
}
user := &users.User{
Username: username,
Password: hashedRandomPassword,
LockPassword: true,
}
setting.Defaults.Apply(user)
var userHome string
userHome, err = setting.MakeUserDir(user.Username, user.Scope, srv.Root)
if err != nil {
return nil, err
}
user.Scope = userHome
err = usr.Save(user)
if err != nil {
return nil, err
}
return user, nil
} }
// LoginPage tells that proxy auth doesn't require a login page. // LoginPage tells that proxy auth doesn't require a login page.

View File

@@ -32,6 +32,7 @@ func addConfigFlags(flags *pflag.FlagSet) {
addUserFlags(flags) addUserFlags(flags)
flags.BoolP("signup", "s", false, "allow users to signup") flags.BoolP("signup", "s", false, "allow users to signup")
flags.Bool("create-user-dir", false, "generate user's home directory automatically") flags.Bool("create-user-dir", false, "generate user's home directory automatically")
flags.Uint("minimum-password-length", settings.DefaultMinimumPasswordLength, "minimum password length for new users")
flags.String("shell", "", "shell command to which other commands should be appended") flags.String("shell", "", "shell command to which other commands should be appended")
flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type") flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type")
@@ -144,6 +145,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup) fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup)
fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir) fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir)
fmt.Fprintf(w, "Minimum Password Length:\t%d\n", set.MinimumPasswordLength)
fmt.Fprintf(w, "Auth method:\t%s\n", set.AuthMethod) fmt.Fprintf(w, "Auth method:\t%s\n", set.AuthMethod)
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " ")) fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " "))
fmt.Fprintln(w, "\nBranding:") fmt.Fprintln(w, "\nBranding:")

View File

@@ -56,7 +56,7 @@ The path must be for a json or yaml file.`,
checkErr(err) checkErr(err)
var rawAuther interface{} var rawAuther interface{}
if filepath.Ext(args[0]) != ".json" { //nolint:goconst if filepath.Ext(args[0]) != ".json" {
rawAuther = cleanUpInterfaceMap(file.Auther.(map[interface{}]interface{})) rawAuther = cleanUpInterfaceMap(file.Auther.(map[interface{}]interface{}))
} else { } else {
rawAuther = file.Auther rawAuther = file.Auther

View File

@@ -29,12 +29,13 @@ override the options.`,
authMethod, auther := getAuthentication(flags) authMethod, auther := getAuthentication(flags)
s := &settings.Settings{ s := &settings.Settings{
Key: generateKey(), Key: generateKey(),
Signup: mustGetBool(flags, "signup"), Signup: mustGetBool(flags, "signup"),
CreateUserDir: mustGetBool(flags, "create-user-dir"), CreateUserDir: mustGetBool(flags, "create-user-dir"),
Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")), MinimumPasswordLength: mustGetUint(flags, "minimum-password-length"),
AuthMethod: authMethod, Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")),
Defaults: defaults, AuthMethod: authMethod,
Defaults: defaults,
Branding: settings.Branding{ Branding: settings.Branding{
Name: mustGetString(flags, "branding.name"), Name: mustGetString(flags, "branding.name"),
DisableExternal: mustGetBool(flags, "branding.disableExternal"), DisableExternal: mustGetBool(flags, "branding.disableExternal"),

View File

@@ -51,6 +51,8 @@ you want to change. Other options will remain unchanged.`,
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name)) set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
case "create-user-dir": case "create-user-dir":
set.CreateUserDir = mustGetBool(flags, flag.Name) set.CreateUserDir = mustGetBool(flags, flag.Name)
case "minimum-password-length":
set.MinimumPasswordLength = mustGetUint(flags, flag.Name)
case "branding.name": case "branding.name":
set.Branding.Name = mustGetString(flags, flag.Name) set.Branding.Name = mustGetString(flags, flag.Name)
case "branding.color": case "branding.color":

View File

@@ -1,6 +1,7 @@
package cmd package cmd
import ( import (
"context"
"crypto/tls" "crypto/tls"
"errors" "errors"
"io" "io"
@@ -13,6 +14,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"syscall" "syscall"
"time"
homedir "github.com/mitchellh/go-homedir" homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/afero" "github.com/spf13/afero"
@@ -48,7 +50,7 @@ func init() {
persistent.StringP("database", "d", "./filebrowser.db", "database path") persistent.StringP("database", "d", "./filebrowser.db", "database path")
flags.Bool("noauth", false, "use the noauth auther when using quick setup") flags.Bool("noauth", false, "use the noauth auther when using quick setup")
flags.String("username", "admin", "username for the first user when using quick config") flags.String("username", "admin", "username for the first user when using quick config")
flags.String("password", "", "hashed password for the first user when using quick config (default \"admin\")") flags.String("password", "", "hashed password for the first user when using quick config")
addServerFlags(flags) addServerFlags(flags)
} }
@@ -61,14 +63,14 @@ func addServerFlags(flags *pflag.FlagSet) {
flags.StringP("key", "k", "", "tls key") flags.StringP("key", "k", "", "tls key")
flags.StringP("root", "r", ".", "root to prepend to relative paths") flags.StringP("root", "r", ".", "root to prepend to relative paths")
flags.String("socket", "", "socket to listen to (cannot be used with address, port, cert nor key flags)") flags.String("socket", "", "socket to listen to (cannot be used with address, port, cert nor key flags)")
flags.Uint32("socket-perm", 0666, "unix socket file permissions") //nolint:gomnd flags.Uint32("socket-perm", 0666, "unix socket file permissions")
flags.StringP("baseurl", "b", "", "base url") flags.StringP("baseurl", "b", "", "base url")
flags.String("cache-dir", "", "file cache directory (disabled if empty)") flags.String("cache-dir", "", "file cache directory (disabled if empty)")
flags.String("token-expiration-time", "2h", "user session timeout") flags.String("token-expiration-time", "2h", "user session timeout")
flags.Int("img-processors", 4, "image processors count") //nolint:gomnd flags.Int("img-processors", 4, "image processors count") //nolint:mnd
flags.Bool("disable-thumbnails", false, "disable image thumbnails") flags.Bool("disable-thumbnails", false, "disable image thumbnails")
flags.Bool("disable-preview-resize", false, "disable resize of image previews") flags.Bool("disable-preview-resize", false, "disable resize of image previews")
flags.Bool("disable-exec", false, "disables Command Runner feature") flags.Bool("disable-exec", true, "disables Command Runner feature")
flags.Bool("disable-type-detection-by-header", false, "disables type detection by reading file headers") flags.Bool("disable-type-detection-by-header", false, "disables type detection by reading file headers")
} }
@@ -129,7 +131,7 @@ user created with the credentials from options "username" and "password".`,
cacheDir, err := cmd.Flags().GetString("cache-dir") cacheDir, err := cmd.Flags().GetString("cache-dir")
checkErr(err) checkErr(err)
if cacheDir != "" { if cacheDir != "" {
if err := os.MkdirAll(cacheDir, 0700); err != nil { //nolint:govet,gomnd if err := os.MkdirAll(cacheDir, 0700); err != nil { //nolint:govet
log.Fatalf("can't make directory %s: %s", cacheDir, err) log.Fatalf("can't make directory %s: %s", cacheDir, err)
} }
fileCache = diskcache.New(afero.NewOsFs(), cacheDir) fileCache = diskcache.New(afero.NewOsFs(), cacheDir)
@@ -167,10 +169,6 @@ user created with the credentials from options "username" and "password".`,
checkErr(err) checkErr(err)
} }
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, os.Interrupt, syscall.SIGTERM)
go cleanupHandler(listener, sigc)
assetsFs, err := fs.Sub(frontend.Assets(), "dist") assetsFs, err := fs.Sub(frontend.Assets(), "dist")
if err != nil { if err != nil {
panic(err) panic(err)
@@ -182,18 +180,31 @@ user created with the credentials from options "username" and "password".`,
defer listener.Close() defer listener.Close()
log.Println("Listening on", listener.Addr().String()) log.Println("Listening on", listener.Addr().String())
//nolint: gosec srv := &http.Server{
if err := http.Serve(listener, handler); err != nil { Handler: handler,
log.Fatal(err) ReadHeaderTimeout: 60 * time.Second,
} }
}, pythonConfig{allowNoDB: true}),
}
func cleanupHandler(listener net.Listener, c chan os.Signal) { //nolint:interfacer go func() {
sig := <-c if err := srv.Serve(listener); !errors.Is(err, http.ErrServerClosed) {
log.Printf("Caught signal %s: shutting down.", sig) log.Fatalf("HTTP server error: %v", err)
listener.Close() }
os.Exit(0)
log.Println("Stopped serving new connections.")
}()
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, os.Interrupt, syscall.SIGTERM)
<-sigc
shutdownCtx, shutdownRelease := context.WithTimeout(context.Background(), 10*time.Second) //nolint:mnd
defer shutdownRelease()
if err := srv.Shutdown(shutdownCtx); err != nil {
log.Fatalf("HTTP shutdown error: %v", err)
}
log.Println("Graceful shutdown complete.")
}, pythonConfig{allowNoDB: true}),
} }
//nolint:gocyclo //nolint:gocyclo
@@ -201,42 +212,42 @@ func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server {
server, err := st.Settings.GetServer() server, err := st.Settings.GetServer()
checkErr(err) checkErr(err)
if val, set := getParamB(flags, "root"); set { if val, set := getStringParamB(flags, "root"); set {
server.Root = val server.Root = val
} }
if val, set := getParamB(flags, "baseurl"); set { if val, set := getStringParamB(flags, "baseurl"); set {
server.BaseURL = val server.BaseURL = val
} }
if val, set := getParamB(flags, "log"); set { if val, set := getStringParamB(flags, "log"); set {
server.Log = val server.Log = val
} }
isSocketSet := false isSocketSet := false
isAddrSet := false isAddrSet := false
if val, set := getParamB(flags, "address"); set { if val, set := getStringParamB(flags, "address"); set {
server.Address = val server.Address = val
isAddrSet = isAddrSet || set isAddrSet = isAddrSet || set
} }
if val, set := getParamB(flags, "port"); set { if val, set := getStringParamB(flags, "port"); set {
server.Port = val server.Port = val
isAddrSet = isAddrSet || set isAddrSet = isAddrSet || set
} }
if val, set := getParamB(flags, "key"); set { if val, set := getStringParamB(flags, "key"); set {
server.TLSKey = val server.TLSKey = val
isAddrSet = isAddrSet || set isAddrSet = isAddrSet || set
} }
if val, set := getParamB(flags, "cert"); set { if val, set := getStringParamB(flags, "cert"); set {
server.TLSCert = val server.TLSCert = val
isAddrSet = isAddrSet || set isAddrSet = isAddrSet || set
} }
if val, set := getParamB(flags, "socket"); set { if val, set := getStringParamB(flags, "socket"); set {
server.Socket = val server.Socket = val
isSocketSet = isSocketSet || set isSocketSet = isSocketSet || set
} }
@@ -250,33 +261,69 @@ func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server {
server.Socket = "" server.Socket = ""
} }
_, disableThumbnails := getParamB(flags, "disable-thumbnails") disableThumbnails := getBoolParam(flags, "disable-thumbnails")
server.EnableThumbnails = !disableThumbnails server.EnableThumbnails = !disableThumbnails
_, disablePreviewResize := getParamB(flags, "disable-preview-resize") disablePreviewResize := getBoolParam(flags, "disable-preview-resize")
server.ResizePreview = !disablePreviewResize server.ResizePreview = !disablePreviewResize
_, disableTypeDetectionByHeader := getParamB(flags, "disable-type-detection-by-header") disableTypeDetectionByHeader := getBoolParam(flags, "disable-type-detection-by-header")
server.TypeDetectionByHeader = !disableTypeDetectionByHeader server.TypeDetectionByHeader = !disableTypeDetectionByHeader
_, disableExec := getParamB(flags, "disable-exec") disableExec := getBoolParam(flags, "disable-exec")
server.EnableExec = !disableExec server.EnableExec = !disableExec
if val, set := getParamB(flags, "token-expiration-time"); set { if server.EnableExec {
log.Println("WARNING: Command Runner feature enabled!")
log.Println("WARNING: This feature has known security vulnerabilities and should not")
log.Println("WARNING: you fully understand the risks involved. For more information")
log.Println("WARNING: read https://github.com/filebrowser/filebrowser/issues/5199")
}
if val, set := getStringParamB(flags, "token-expiration-time"); set {
server.TokenExpirationTime = val server.TokenExpirationTime = val
} }
return server return server
} }
// getParamB returns a parameter as a string and a boolean to tell if it is different from the default // getBoolParamB returns a parameter as a string and a boolean to tell if it is different from the default
// //
// NOTE: we could simply bind the flags to viper and use IsSet. // NOTE: we could simply bind the flags to viper and use IsSet.
// Although there is a bug on Viper that always returns true on IsSet // Although there is a bug on Viper that always returns true on IsSet
// if a flag is binded. Our alternative way is to manually check // if a flag is binded. Our alternative way is to manually check
// the flag and then the value from env/config/gotten by viper. // the flag and then the value from env/config/gotten by viper.
// https://github.com/spf13/viper/pull/331 // https://github.com/spf13/viper/pull/331
func getParamB(flags *pflag.FlagSet, key string) (string, bool) { func getBoolParamB(flags *pflag.FlagSet, key string) (value, ok bool) {
value, _ = flags.GetBool(key)
// If set on Flags, use it.
if flags.Changed(key) {
return value, true
}
// If set through viper (env, config), return it.
if v.IsSet(key) {
return v.GetBool(key), true
}
// Otherwise use default value on flags.
return value, false
}
func getBoolParam(flags *pflag.FlagSet, key string) bool {
val, _ := getBoolParamB(flags, key)
return val
}
// getStringParamB returns a parameter as a string and a boolean to tell if it is different from the default
//
// NOTE: we could simply bind the flags to viper and use IsSet.
// Although there is a bug on Viper that always returns true on IsSet
// if a flag is binded. Our alternative way is to manually check
// the flag and then the value from env/config/gotten by viper.
// https://github.com/spf13/viper/pull/331
func getStringParamB(flags *pflag.FlagSet, key string) (string, bool) {
value, _ := flags.GetString(key) value, _ := flags.GetString(key)
// If set on Flags, use it. // If set on Flags, use it.
@@ -293,8 +340,8 @@ func getParamB(flags *pflag.FlagSet, key string) (string, bool) {
return value, false return value, false
} }
func getParam(flags *pflag.FlagSet, key string) string { func getStringParam(flags *pflag.FlagSet, key string) string {
val, _ := getParamB(flags, key) val, _ := getStringParamB(flags, key)
return val return val
} }
@@ -318,10 +365,11 @@ func setupLog(logMethod string) {
func quickSetup(flags *pflag.FlagSet, d pythonData) { func quickSetup(flags *pflag.FlagSet, d pythonData) {
set := &settings.Settings{ set := &settings.Settings{
Key: generateKey(), Key: generateKey(),
Signup: false, Signup: false,
CreateUserDir: false, CreateUserDir: false,
UserHomeBasePath: settings.DefaultUsersHomeBasePath, MinimumPasswordLength: settings.DefaultMinimumPasswordLength,
UserHomeBasePath: settings.DefaultUsersHomeBasePath,
Defaults: settings.UserDefaults{ Defaults: settings.UserDefaults{
Scope: ".", Scope: ".",
Locale: "en", Locale: "en",
@@ -349,7 +397,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
} }
var err error var err error
if _, noauth := getParamB(flags, "noauth"); noauth { if _, noauth := getStringParamB(flags, "noauth"); noauth {
set.AuthMethod = auth.MethodNoAuth set.AuthMethod = auth.MethodNoAuth
err = d.store.Auth.Save(&auth.NoAuth{}) err = d.store.Auth.Save(&auth.NoAuth{})
} else { } else {
@@ -362,23 +410,29 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
checkErr(err) checkErr(err)
ser := &settings.Server{ ser := &settings.Server{
BaseURL: getParam(flags, "baseurl"), BaseURL: getStringParam(flags, "baseurl"),
Port: getParam(flags, "port"), Port: getStringParam(flags, "port"),
Log: getParam(flags, "log"), Log: getStringParam(flags, "log"),
TLSKey: getParam(flags, "key"), TLSKey: getStringParam(flags, "key"),
TLSCert: getParam(flags, "cert"), TLSCert: getStringParam(flags, "cert"),
Address: getParam(flags, "address"), Address: getStringParam(flags, "address"),
Root: getParam(flags, "root"), Root: getStringParam(flags, "root"),
} }
err = d.store.Settings.SaveServer(ser) err = d.store.Settings.SaveServer(ser)
checkErr(err) checkErr(err)
username := getParam(flags, "username") username := getStringParam(flags, "username")
password := getParam(flags, "password") password := getStringParam(flags, "password")
if password == "" { if password == "" {
password, err = users.HashPwd("admin") var pwd string
pwd, err = users.RandomPwd(set.MinimumPasswordLength)
checkErr(err)
log.Println("Randomly generated password for user 'admin':", pwd)
password, err = users.ValidateAndHashPwd(pwd, set.MinimumPasswordLength)
checkErr(err) checkErr(err)
} }
@@ -414,6 +468,7 @@ func initConfig() {
v.SetEnvPrefix("FB") v.SetEnvPrefix("FB")
v.AutomaticEnv() v.AutomaticEnv()
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
if err := v.ReadInConfig(); err != nil { if err := v.ReadInConfig(); err != nil {
var configParseError v.ConfigParseError var configParseError v.ConfigParseError

View File

@@ -25,7 +25,7 @@ this version.`,
flags := cmd.Flags() flags := cmd.Flags()
oldDB := mustGetString(flags, "old.database") oldDB := mustGetString(flags, "old.database")
oldConf := mustGetString(flags, "old.config") oldConf := mustGetString(flags, "old.config")
err := importer.Import(oldDB, oldConf, getParam(flags, "database")) err := importer.Import(oldDB, oldConf, getStringParam(flags, "database"))
checkErr(err) checkErr(err)
}, },
} }

View File

@@ -21,7 +21,7 @@ var usersAddCmd = &cobra.Command{
checkErr(err) checkErr(err)
getUserDefaults(cmd.Flags(), &s.Defaults, false) getUserDefaults(cmd.Flags(), &s.Defaults, false)
password, err := users.HashPwd(args[1]) password, err := users.ValidateAndHashPwd(args[1], s.MinimumPasswordLength)
checkErr(err) checkErr(err)
user := &users.User{ user := &users.User{

View File

@@ -27,8 +27,10 @@ options you want to change.`,
password := mustGetString(flags, "password") password := mustGetString(flags, "password")
newUsername := mustGetString(flags, "username") newUsername := mustGetString(flags, "username")
s, err := d.store.Settings.Get()
checkErr(err)
var ( var (
err error
user *users.User user *users.User
) )
@@ -64,7 +66,7 @@ options you want to change.`,
} }
if password != "" { if password != "" {
user.Password, err = users.HashPwd(password) user.Password, err = users.ValidateAndHashPwd(password, s.MinimumPasswordLength)
checkErr(err) checkErr(err)
} }

View File

@@ -14,6 +14,7 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
yaml "gopkg.in/yaml.v2" yaml "gopkg.in/yaml.v2"
"github.com/filebrowser/filebrowser/v2/files"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/storage" "github.com/filebrowser/filebrowser/v2/storage"
"github.com/filebrowser/filebrowser/v2/storage/bolt" "github.com/filebrowser/filebrowser/v2/storage/bolt"
@@ -72,7 +73,7 @@ func dbExists(path string) (bool, error) {
d := filepath.Dir(path) d := filepath.Dir(path)
_, err = os.Stat(d) _, err = os.Stat(d)
if os.IsNotExist(err) { if os.IsNotExist(err) {
if err := os.MkdirAll(d, 0700); err != nil { //nolint:govet,gomnd if err := os.MkdirAll(d, 0700); err != nil { //nolint:govet
return false, err return false, err
} }
return false, nil return false, nil
@@ -86,7 +87,7 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc {
return func(cmd *cobra.Command, args []string) { return func(cmd *cobra.Command, args []string) {
data := pythonData{hadDB: true} data := pythonData{hadDB: true}
path := getParam(cmd.Flags(), "database") path := getStringParam(cmd.Flags(), "database")
absPath, err := filepath.Abs(path) absPath, err := filepath.Abs(path)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -105,7 +106,7 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc {
log.Println("Using database: " + absPath) log.Println("Using database: " + absPath)
data.hadDB = exists data.hadDB = exists
db, err := storm.Open(path) db, err := storm.Open(path, storm.BoltOptions(files.PermFile, nil))
checkErr(err) checkErr(err)
defer db.Close() defer db.Close()
data.store, err = bolt.NewStorage(db) data.store, err = bolt.NewStorage(db)
@@ -124,7 +125,7 @@ func marshal(filename string, data interface{}) error {
encoder := json.NewEncoder(fd) encoder := json.NewEncoder(fd)
encoder.SetIndent("", " ") encoder.SetIndent("", " ")
return encoder.Encode(data) return encoder.Encode(data)
case ".yml", ".yaml": //nolint:goconst case ".yml", ".yaml":
encoder := yaml.NewEncoder(fd) encoder := yaml.NewEncoder(fd)
return encoder.Encode(data) return encoder.Encode(data)
default: default:

View File

@@ -37,11 +37,11 @@ func (f *FileCache) Store(_ context.Context, key string, value []byte) error {
defer mu.Unlock() defer mu.Unlock()
fileName := f.getFileName(key) fileName := f.getFileName(key)
if err := f.fs.MkdirAll(filepath.Dir(fileName), 0700); err != nil { //nolint:gomnd if err := f.fs.MkdirAll(filepath.Dir(fileName), 0700); err != nil {
return err return err
} }
if err := afero.WriteFile(f.fs, fileName, value, 0700); err != nil { //nolint:gomnd if err := afero.WriteFile(f.fs, fileName, value, 0700); err != nil {
return err return err
} }

41
docker/alpine/init.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/sh
set -e
# Backwards compatibility for old Docker image
if [ -f "/.filebrowser.json" ]; then
ln -s /.filebrowser.json /config/settings.json
echo ""
echo "!!!!!!!!!!!!!!!!!!!!! IMPORTANT INFORMATION !!!!!!!!!!!!!!!!!!!!!"
echo "Symlinking /.filebrowser.json to /config/settings.json for backwards compatibility."
echo ""
echo "The volume mount configuration has changed in the latest release."
echo "Please rename .filebrowser.json to settings.json and mount the parent directory to /config".
echo "Read more on https://filebrowser.org/installation.html#docker"
echo ""
echo "This workaround will be removed in a future release."
echo ""
fi
# Backwards compatibility for old Docker image
if [ -f "/database.db" ]; then
ln -s /database.db /database/filebrowser.db
echo ""
echo "!!!!!!!!!!!!!!!!!!!!! IMPORTANT INFORMATION !!!!!!!!!!!!!!!!!!!!!"
echo ""
echo "The volume mount configuration has changed in the latest release."
echo "Please rename database.db to filebrowser.db and mount the parent directory to /database".
echo "Read more on https://filebrowser.org/installation.html#docker"
echo ""
echo "This workaround will be removed in a future release."
echo ""
fi
# Ensure configuration exists
if [ ! -f "/config/settings.json" ]; then
cp -a /defaults/settings.json /config/settings.json
fi
exec "$@"

9
docker/common/healthcheck.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
set -e
PORT=${FB_PORT:-$(jq -r .port /config/settings.json)}
ADDRESS=${FB_ADDRESS:-$(jq -r .address /config/settings.json)}
ADDRESS=${ADDRESS:-localhost}
curl -f http://$ADDRESS:$PORT/health || exit 1

View File

@@ -1,3 +0,0 @@
#!/usr/bin/with-contenv bash
exec s6-setuidgid abc filebrowser -c /config/settings.json -d /database/filebrowser.db;

View File

@@ -1,9 +1,6 @@
#!/usr/bin/with-contenv bash #!/usr/bin/with-contenv bash
# make folders # Ensure configuration exists
mkdir -p /database
# copy config
if [ ! -f "/config/settings.json" ]; then if [ ! -f "/config/settings.json" ]; then
cp -a /defaults/settings.json /config/settings.json cp -a /defaults/settings.json /config/settings.json
fi fi

View File

@@ -0,0 +1,3 @@
#!/usr/bin/with-contenv bash
exec s6-setuidgid abc filebrowser -c /config/settings.json;

View File

@@ -1,12 +1,16 @@
package errors package errors
import "errors" import (
"errors"
"fmt"
)
var ( var (
ErrEmptyKey = errors.New("empty key") ErrEmptyKey = errors.New("empty key")
ErrExist = errors.New("the resource already exists") ErrExist = errors.New("the resource already exists")
ErrNotExist = errors.New("the resource does not exist") ErrNotExist = errors.New("the resource does not exist")
ErrEmptyPassword = errors.New("password is empty") ErrEmptyPassword = errors.New("password is empty")
ErrEasyPassword = errors.New("password is too easy")
ErrEmptyUsername = errors.New("username is empty") ErrEmptyUsername = errors.New("username is empty")
ErrEmptyRequest = errors.New("empty request") ErrEmptyRequest = errors.New("empty request")
ErrScopeIsRelative = errors.New("scope is a relative path") ErrScopeIsRelative = errors.New("scope is a relative path")
@@ -19,3 +23,11 @@ var (
ErrSourceIsParent = errors.New("source is parent") ErrSourceIsParent = errors.New("source is parent")
ErrRootUserDeletion = errors.New("user with id 1 can't be deleted") ErrRootUserDeletion = errors.New("user with id 1 can't be deleted")
) )
type ErrShortPassword struct {
MinimumLength uint
}
func (e ErrShortPassword) Error() string {
return fmt.Sprintf("password is too short, minimum length is %d", e.MinimumLength)
}

View File

@@ -27,8 +27,8 @@ import (
"github.com/filebrowser/filebrowser/v2/rules" "github.com/filebrowser/filebrowser/v2/rules"
) )
const PermFile = 0644 const PermFile = 0640
const PermDir = 0755 const PermDir = 0750
var ( var (
reSubDirs = regexp.MustCompile("(?i)^sub(s|titles)$") reSubDirs = regexp.MustCompile("(?i)^sub(s|titles)$")
@@ -86,6 +86,11 @@ func NewFileInfo(opts *FileOptions) (*FileInfo, error) {
return nil, err return nil, err
} }
// Do not expose the name of root directory.
if file.Path == "/" {
file.Name = ""
}
if opts.Expand { if opts.Expand {
if file.IsDir { if file.IsDir {
if err := file.readListing(opts.Checker, opts.ReadHeader); err != nil { //nolint:govet if err := file.readListing(opts.Checker, opts.ReadHeader); err != nil { //nolint:govet
@@ -217,7 +222,6 @@ func (i *FileInfo) RealPath() string {
return i.Path return i.Path
} }
//nolint:goconst
func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error { func (i *FileInfo) detectType(modify, saveContent, readHeader bool) error {
if IsNamedPipe(i.Mode) { if IsNamedPipe(i.Mode) {
i.Type = "blob" i.Type = "blob"
@@ -314,7 +318,7 @@ func (i *FileInfo) readFirstBytes() []byte {
} }
defer reader.Close() defer reader.Close()
buffer := make([]byte, 512) //nolint:gomnd buffer := make([]byte, 512)
n, err := reader.Read(buffer) n, err := reader.Read(buffer)
if err != nil && !errors.Is(err, io.EOF) { if err != nil && !errors.Is(err, io.EOF) {
log.Print(err) log.Print(err)

View File

@@ -16,8 +16,6 @@ type Listing struct {
} }
// ApplySort applies the sort order using .Order and .Sort // ApplySort applies the sort order using .Order and .Sort
//
//nolint:goconst
func (l Listing) ApplySort() { func (l Listing) ApplySort() {
// Check '.Order' to know how to sort // Check '.Order' to know how to sort
if !l.Sorting.Asc { if !l.Sorting.Asc {

View File

@@ -1,27 +0,0 @@
{
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/eslint-config-typescript",
"@vue/eslint-config-prettier"
],
"rules": {
"vue/multi-word-component-names": "off",
"vue/no-mutating-props": [
"error",
{
"shallowOnly": true
}
]
// no-undef is already included in
// @vue/eslint-config-typescript
},
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
}
}

View File

@@ -1,2 +1,3 @@
# Ignore artifacts: # Ignore artifacts:
dist dist
pnpm-lock.yaml

38
frontend/eslint.config.js Normal file
View File

@@ -0,0 +1,38 @@
import pluginVue from "eslint-plugin-vue";
import vueTsEslintConfig from "@vue/eslint-config-typescript";
import prettierConfig from "@vue/eslint-config-prettier";
export default [
{
name: "app/files-to-lint",
files: ["**/*.{ts,mts,tsx,vue}"],
},
{
name: "app/files-to-ignore",
ignores: ["**/dist/**", "**/dist-ssr/**", "**/coverage/**"],
},
...pluginVue.configs["flat/essential"],
...vueTsEslintConfig(),
prettierConfig,
{
rules: {
// Note: you must disable the base rule as it can report incorrect errors
"no-unused-expressions": "off",
"@typescript-eslint/no-unused-expressions": "off",
// TODO: theres too many of these from before ts
"@typescript-eslint/no-explicit-any": "off",
// TODO: finish the ts conversion
"vue/block-lang": "off",
"vue/multi-word-component-names": "off",
"vue/no-mutating-props": [
"error",
{
shallowOnly: true,
},
],
},
},
];

View File

@@ -1,10 +0,0 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,70 +4,75 @@
"private": true, "private": true,
"type": "module", "type": "module",
"engines": { "engines": {
"npm": ">=7.0.0", "node": ">=22.0.0",
"node": ">=18.0.0" "pnpm": ">=9.0.0"
}, },
"scripts": { "scripts": {
"dev": "vite dev", "dev": "vite dev",
"build": "npm run typecheck && vite build", "build": "pnpm run typecheck && vite build",
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +", "clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
"typecheck": "vue-tsc -p ./tsconfig.json --noEmit", "typecheck": "vue-tsc -p ./tsconfig.tsc.json --noEmit",
"lint": "npm run typecheck && eslint --ext .vue,.ts src/", "lint": "eslint src/",
"lint:fix": "eslint --ext .vue,.ts --fix src/", "lint:fix": "eslint --fix src/",
"format": "prettier --write .", "format": "prettier --write .",
"test": "playwright test" "test": "playwright test"
}, },
"dependencies": { "dependencies": {
"@chenfengyuan/vue-number-input": "^2.0.1", "@chenfengyuan/vue-number-input": "^2.0.1",
"@vueuse/core": "^10.9.0", "@vueuse/core": "^12.5.0",
"@vueuse/integrations": "^10.9.0", "@vueuse/integrations": "^12.5.0",
"ace-builds": "^1.32.9", "ace-builds": "^1.37.5",
"core-js": "^3.36.1", "core-js": "^3.40.0",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"dompurify": "^3.2.6",
"epubjs": "^0.3.93",
"filesize": "^10.1.1", "filesize": "^10.1.1",
"js-base64": "^3.7.7", "js-base64": "^3.7.7",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"material-icons": "^1.13.12", "marked": "^15.0.6",
"marked": "^14.1.0", "material-icons": "^1.13.13",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"pinia": "^2.1.7", "pinia": "^2.3.1",
"pretty-bytes": "^6.1.1", "pretty-bytes": "^6.1.1",
"qrcode.vue": "^3.4.1", "qrcode.vue": "^3.4.1",
"tus-js-client": "^4.1.0", "tus-js-client": "^4.3.1",
"utif": "^3.1.0", "utif": "^3.1.0",
"video.js": "^8.10.0", "video.js": "^8.21.0",
"videojs-hotkeys": "^0.2.28", "videojs-hotkeys": "^0.2.28",
"videojs-mobile-ui": "^1.1.1", "videojs-mobile-ui": "^1.1.1",
"vue": "^3.4.21", "vue": "^3.4.21",
"vue-final-modal": "^4.5.4", "vue-final-modal": "^4.5.4",
"vue-i18n": "^9.10.2", "vue-i18n": "^11.1.2",
"vue-lazyload": "^3.0.0", "vue-lazyload": "^3.0.0",
"vue-reader": "^1.2.14", "vue-reader": "^1.2.17",
"vue-router": "^4.3.0", "vue-router": "^4.3.0",
"vue-toastification": "^2.0.0-rc.5" "vue-toastification": "^2.0.0-rc.5"
}, },
"devDependencies": { "devDependencies": {
"@intlify/unplugin-vue-i18n": "^4.0.0", "@intlify/unplugin-vue-i18n": "^6.0.3",
"@playwright/test": "^1.42.1", "@playwright/test": "^1.50.0",
"@tsconfig/node22": "^22.0.0",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/node": "^20.12.2", "@types/node": "^22.10.10",
"@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/eslint-plugin": "^8.21.0",
"@vitejs/plugin-legacy": "^5.3.2", "@vitejs/plugin-legacy": "^6.0.0",
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "^5.0.4",
"@vue/eslint-config-prettier": "^9.0.0", "@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^13.0.0", "@vue/eslint-config-typescript": "^14.3.0",
"@vue/tsconfig": "^0.7.0",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"concurrently": "^8.2.2", "concurrently": "^9.1.2",
"eslint": "^8.57.0", "eslint": "^9.19.0",
"eslint-plugin-prettier": "^5.1.3", "eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-vue": "^9.24.0", "eslint-plugin-vue": "^9.24.0",
"jsdom": "^24.0.0", "jsdom": "^26.0.0",
"postcss": "^8.4.38", "postcss": "^8.5.1",
"prettier": "^3.2.5", "prettier": "^3.4.2",
"terser": "^5.30.0", "terser": "^5.37.0",
"vite": "^5.4.6", "vite": "^6.1.6",
"vite-plugin-compression2": "^1.0.0", "vite-plugin-compression2": "^1.0.0",
"vue-tsc": "^2.0.7" "vue-tsc": "^2.2.0"
} },
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
} }

5442
frontend/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
import { removePrefix } from "./utils";
import { baseURL } from "@/utils/constants"; import { baseURL } from "@/utils/constants";
import { useAuthStore } from "@/stores/auth"; import { removePrefix } from "./utils";
const ssl = window.location.protocol === "https:"; const ssl = window.location.protocol === "https:";
const protocol = ssl ? "wss:" : "ws:"; const protocol = ssl ? "wss:" : "ws:";
@@ -11,10 +10,8 @@ export default function command(
onmessage: WebSocket["onmessage"], onmessage: WebSocket["onmessage"],
onclose: WebSocket["onclose"] onclose: WebSocket["onclose"]
) { ) {
const authStore = useAuthStore();
url = removePrefix(url); url = removePrefix(url);
url = `${protocol}//${window.location.host}${baseURL}/api/command${url}?auth=${authStore.jwt}`; url = `${protocol}//${window.location.host}${baseURL}/api/command${url}`;
const conn = new window.WebSocket(url); const conn = new window.WebSocket(url);
conn.onopen = () => conn.send(command); conn.onopen = () => conn.send(command);

View File

@@ -1,14 +1,23 @@
import { createURL, fetchURL, removePrefix } from "./utils";
import { baseURL } from "@/utils/constants";
import { useAuthStore } from "@/stores/auth"; import { useAuthStore } from "@/stores/auth";
import { useLayoutStore } from "@/stores/layout";
import { baseURL } from "@/utils/constants";
import { upload as postTus, useTus } from "./tus"; import { upload as postTus, useTus } from "./tus";
import { createURL, fetchURL, removePrefix, StatusError } from "./utils";
export async function fetch(url: string) { export async function fetch(url: string, signal?: AbortSignal) {
url = removePrefix(url); url = removePrefix(url);
const res = await fetchURL(`/api/resources${url}`, { signal });
const res = await fetchURL(`/api/resources${url}`, {}); let data: Resource;
try {
const data = (await res.json()) as Resource; data = (await res.json()) as Resource;
} catch (e) {
// Check if the error is an intentional cancellation
if (e instanceof Error && e.name === "AbortError") {
throw new StatusError("000 No connection", 0, true);
}
throw e;
}
data.url = `/files${url}`; data.url = `/files${url}`;
if (data.isDir) { if (data.isDir) {
@@ -74,11 +83,6 @@ export function download(format: any, ...files: string[]) {
url += `algo=${format}&`; url += `algo=${format}&`;
} }
const authStore = useAuthStore();
if (authStore.jwt) {
url += `auth=${authStore.jwt}&`;
}
window.open(url); window.open(url);
} }
@@ -156,6 +160,7 @@ function moveCopy(
overwrite = false, overwrite = false,
rename = false rename = false
) { ) {
const layoutStore = useLayoutStore();
const promises = []; const promises = [];
for (const item of items) { for (const item of items) {
@@ -166,7 +171,7 @@ function moveCopy(
}&destination=${to}&override=${overwrite}&rename=${rename}`; }&destination=${to}&override=${overwrite}&rename=${rename}`;
promises.push(resourceAction(url, "PATCH")); promises.push(resourceAction(url, "PATCH"));
} }
layoutStore.closeHovers();
return Promise.all(promises); return Promise.all(promises);
} }
@@ -208,10 +213,18 @@ export function getSubtitlesURL(file: ResourceItem) {
return file.subtitles?.map((d) => createURL("api/subtitle" + d, params)); return file.subtitles?.map((d) => createURL("api/subtitle" + d, params));
} }
export async function usage(url: string) { export async function usage(url: string, signal: AbortSignal) {
url = removePrefix(url); url = removePrefix(url);
const res = await fetchURL(`/api/usage${url}`, {}); const res = await fetchURL(`/api/usage${url}`, { signal });
return await res.json(); try {
return await res.json();
} catch (e) {
// Check if the error is an intentional cancellation
if (e instanceof Error && e.name == "AbortError") {
throw new StatusError("000 No connection", 0, true);
}
throw e;
}
} }

View File

@@ -71,5 +71,5 @@ export function getDownloadURL(res: Resource, inline = false) {
...(res.token && { token: res.token }), ...(res.token && { token: res.token }),
}; };
return createURL("api/public/dl/" + res.hash + res.path, params, false); return createURL("api/public/dl/" + res.hash + res.path, params);
} }

View File

@@ -41,5 +41,5 @@ export async function create(
} }
export function getShareURL(share: Share) { export function getShareURL(share: Share) {
return createURL("share/" + share.hash, {}, false); return createURL("share/" + share.hash, {});
} }

View File

@@ -25,7 +25,7 @@ export async function create(user: IUser) {
throw new StatusError(await res.text(), res.status); throw new StatusError(await res.text(), res.status);
} }
export async function update(user: IUser, which = ["all"]) { export async function update(user: Partial<IUser>, which = ["all"]) {
await fetchURL(`/api/users/${user.id}`, { await fetchURL(`/api/users/${user.id}`, {
method: "PUT", method: "PUT",
body: JSON.stringify({ body: JSON.stringify({

View File

@@ -6,7 +6,8 @@ import { encodePath } from "@/utils/url";
export class StatusError extends Error { export class StatusError extends Error {
constructor( constructor(
message: any, message: any,
public status?: number public status?: number,
public is_canceled?: boolean
) { ) {
super(message); super(message);
this.name = "StatusError"; this.name = "StatusError";
@@ -33,7 +34,11 @@ export async function fetchURL(
}, },
...rest, ...rest,
}); });
} catch { } catch (e) {
// Check if the error is an intentional cancellation
if (e instanceof Error && e.name === "AbortError") {
throw new StatusError("000 No connection", 0, true);
}
throw new StatusError("000 No connection", 0); throw new StatusError("000 No connection", 0);
} }
@@ -76,23 +81,13 @@ export function removePrefix(url: string): string {
return url; return url;
} }
export function createURL(endpoint: string, params = {}, auth = true): string { export function createURL(endpoint: string, searchParams = {}): string {
const authStore = useAuthStore();
let prefix = baseURL; let prefix = baseURL;
if (!prefix.endsWith("/")) { if (!prefix.endsWith("/")) {
prefix = prefix + "/"; prefix = prefix + "/";
} }
const url = new URL(prefix + encodePath(endpoint), origin); const url = new URL(prefix + encodePath(endpoint), origin);
url.search = new URLSearchParams(searchParams).toString();
const searchParams: SearchParams = {
...(auth && { auth: authStore.jwt }),
...params,
};
for (const key in searchParams) {
url.searchParams.set(key, searchParams[key]);
}
return url.toString(); return url.toString();
} }

View File

@@ -34,7 +34,7 @@ const props = defineProps<{
const items = computed(() => { const items = computed(() => {
const relativePath = route.path.replace(props.base, ""); const relativePath = route.path.replace(props.base, "");
let parts = relativePath.split("/"); const parts = relativePath.split("/");
if (parts[0] === "") { if (parts[0] === "") {
parts.shift(); parts.shift();
@@ -44,7 +44,7 @@ const items = computed(() => {
parts.pop(); parts.pop();
} }
let breadcrumbs: BreadCrumb[] = []; const breadcrumbs: BreadCrumb[] = [];
for (let i = 0; i < parts.length; i++) { for (let i = 0; i < parts.length; i++) {
if (i === 0) { if (i === 0) {

View File

@@ -46,7 +46,7 @@ https://raw.githubusercontent.com/dzwillia/vue-simple-progress/master/src/compon
<script> <script>
// We're leaving this untouched as you can read in the beginning // We're leaving this untouched as you can read in the beginning
var isNumber = function (n) { const isNumber = function (n) {
return !isNaN(parseFloat(n)) && isFinite(n); return !isNaN(parseFloat(n)) && isFinite(n);
}; };
@@ -107,7 +107,7 @@ export default {
}, },
computed: { computed: {
pct() { pct() {
var pct = (this.val / this.max) * 100; let pct = (this.val / this.max) * 100;
pct = pct.toFixed(2); pct = pct.toFixed(2);
return Math.min(pct, this.max); return Math.min(pct, this.max);
}, },
@@ -160,7 +160,7 @@ export default {
return isNumber(this.fontSize) ? this.fontSize : 13; return isNumber(this.fontSize) ? this.fontSize : 13;
}, },
progress_style() { progress_style() {
var style = { const style = {
background: this.bgColor, background: this.bgColor,
}; };
@@ -177,7 +177,7 @@ export default {
return style; return style;
}, },
bar_style() { bar_style() {
var style = { const style = {
background: this.barColor, background: this.barColor,
width: this.pct + "%", width: this.pct + "%",
height: this.size_px + "px", height: this.size_px + "px",
@@ -198,7 +198,7 @@ export default {
return style; return style;
}, },
text_style() { text_style() {
var style = { const style = {
color: this.textFgColor, color: this.textFgColor,
"font-size": this.text_font_size + "px", "font-size": this.text_font_size + "px",
"text-align": this.textAlign, "text-align": this.textAlign,

View File

@@ -50,7 +50,7 @@ import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout"; import { useLayoutStore } from "@/stores/layout";
import { commands } from "@/api"; import { commands } from "@/api";
import { throttle } from "lodash"; import { throttle } from "lodash-es";
import { theme } from "@/utils/constants"; import { theme } from "@/utils/constants";
export default { export default {
@@ -163,7 +163,7 @@ export default {
this.canInput = false; this.canInput = false;
event.target.innerHTML = ""; event.target.innerHTML = "";
let results = { const results = {
text: `${cmd}\n\n`, text: `${cmd}\n\n`,
}; };
@@ -180,7 +180,7 @@ export default {
}, },
() => { () => {
results.text = results.text results.text = results.text
// eslint-disable-next-line no-control-regex
.replace(/\u001b\[[0-9;]+m/g, "") // Filter ANSI color for now .replace(/\u001b\[[0-9;]+m/g, "") // Filter ANSI color for now
.trimEnd(); .trimEnd();
this.canInput = true; this.canInput = true;

View File

@@ -101,7 +101,7 @@
href="https://github.com/filebrowser/filebrowser" href="https://github.com/filebrowser/filebrowser"
>File Browser</a >File Browser</a
> >
<span> {{ ' ' }} {{ version }}</span> <span> {{ " " }} {{ version }}</span>
</span> </span>
<span> <span>
<a @click="help">{{ $t("sidebar.help") }}</a> <a @click="help">{{ $t("sidebar.help") }}</a>
@@ -129,6 +129,7 @@ import {
import { files as api } from "@/api"; import { files as api } from "@/api";
import ProgressBar from "@/components/ProgressBar.vue"; import ProgressBar from "@/components/ProgressBar.vue";
import prettyBytes from "pretty-bytes"; import prettyBytes from "pretty-bytes";
import { StatusError } from "@/api/utils.js";
const USAGE_DEFAULT = { used: "0 B", total: "0 B", usedPercentage: 0 }; const USAGE_DEFAULT = { used: "0 B", total: "0 B", usedPercentage: 0 };
@@ -136,7 +137,7 @@ export default {
name: "sidebar", name: "sidebar",
setup() { setup() {
const usage = reactive(USAGE_DEFAULT); const usage = reactive(USAGE_DEFAULT);
return { usage }; return { usage, usageAbortController: new AbortController() };
}, },
components: { components: {
ProgressBar, ProgressBar,
@@ -157,8 +158,11 @@ export default {
}, },
methods: { methods: {
...mapActions(useLayoutStore, ["closeHovers", "showHover"]), ...mapActions(useLayoutStore, ["closeHovers", "showHover"]),
abortOngoingFetchUsage() {
this.usageAbortController.abort();
},
async fetchUsage() { async fetchUsage() {
let path = this.$route.path.endsWith("/") const path = this.$route.path.endsWith("/")
? this.$route.path ? this.$route.path
: this.$route.path + "/"; : this.$route.path + "/";
let usageStats = USAGE_DEFAULT; let usageStats = USAGE_DEFAULT;
@@ -166,13 +170,18 @@ export default {
return Object.assign(this.usage, usageStats); return Object.assign(this.usage, usageStats);
} }
try { try {
let usage = await api.usage(path); this.abortOngoingFetchUsage();
this.usageAbortController = new AbortController();
const usage = await api.usage(path, this.usageAbortController.signal);
usageStats = { usageStats = {
used: prettyBytes(usage.used, { binary: true }), used: prettyBytes(usage.used, { binary: true }),
total: prettyBytes(usage.total, { binary: true }), total: prettyBytes(usage.total, { binary: true }),
usedPercentage: Math.round((usage.used / usage.total) * 100), usedPercentage: Math.round((usage.used / usage.total) * 100),
}; };
} catch (error) { } catch (error) {
if (error instanceof StatusError && error.is_canceled) {
return;
}
this.$showError(error); this.$showError(error);
} }
return Object.assign(this.usage, usageStats); return Object.assign(this.usage, usageStats);
@@ -191,9 +200,17 @@ export default {
logout: auth.logout, logout: auth.logout,
}, },
watch: { watch: {
isFiles(newValue) { $route: {
newValue && this.fetchUsage(); handler(to) {
if (to.path.includes("/files")) {
this.fetchUsage();
}
},
immediate: true,
}, },
}, },
unmounted() {
this.abortOngoingFetchUsage();
},
}; };
</script> </script>

View File

@@ -14,15 +14,15 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import throttle from "lodash/throttle"; import { throttle } from "lodash-es";
import UTIF from "utif"; import UTIF from "utif";
import { onBeforeUnmount, onMounted, ref, watch } from "vue"; import { onBeforeUnmount, onMounted, ref, watch } from "vue";
interface IProps { interface IProps {
src: string; src: string;
moveDisabledTime: number; moveDisabledTime?: number;
classList: any[]; classList?: any[];
zoomStep: number; zoomStep?: number;
} }
const props = withDefaults(defineProps<IProps>(), { const props = withDefaults(defineProps<IProps>(), {
@@ -102,10 +102,11 @@ const decodeUTIF = () => {
if (document?.location?.pathname === undefined) { if (document?.location?.pathname === undefined) {
return; return;
} }
let suff = document.location.pathname.split(".")?.pop()?.toLowerCase() ?? ""; const suff =
document.location.pathname.split(".")?.pop()?.toLowerCase() ?? "";
if (sufs.indexOf(suff) == -1) return false; if (sufs.indexOf(suff) == -1) return false;
let xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
UTIF._xhrs.push(xhr); UTIF._xhrs.push(xhr);
UTIF._imgs.push(imgex.value); UTIF._imgs.push(imgex.value);
xhr.open("GET", props.src); xhr.open("GET", props.src);
@@ -230,7 +231,7 @@ const touchMove = (event: TouchEvent) => {
if (imgex.value === null) { if (imgex.value === null) {
return; return;
} }
let step = imgex.value.width / 5; const step = imgex.value.width / 5;
if (event.targetTouches.length === 2) { if (event.targetTouches.length === 2) {
moveDisabled.value = true; moveDisabled.value = true;
if (disabledTimer.value) clearTimeout(disabledTimer.value); if (disabledTimer.value) clearTimeout(disabledTimer.value);
@@ -239,9 +240,9 @@ const touchMove = (event: TouchEvent) => {
props.moveDisabledTime props.moveDisabledTime
); );
let p1 = event.targetTouches[0]; const p1 = event.targetTouches[0];
let p2 = event.targetTouches[1]; const p2 = event.targetTouches[1];
let touchDistance = Math.sqrt( const touchDistance = Math.sqrt(
Math.pow(p2.pageX - p1.pageX, 2) + Math.pow(p2.pageY - p1.pageY, 2) Math.pow(p2.pageX - p1.pageX, 2) + Math.pow(p2.pageY - p1.pageY, 2)
); );
if (!lastTouchDistance.value) { if (!lastTouchDistance.value) {
@@ -253,8 +254,8 @@ const touchMove = (event: TouchEvent) => {
setZoom(); setZoom();
} else if (event.targetTouches.length === 1) { } else if (event.targetTouches.length === 1) {
if (moveDisabled.value) return; if (moveDisabled.value) return;
let x = event.targetTouches[0].pageX - (lastX.value ?? 0); const x = event.targetTouches[0].pageX - (lastX.value ?? 0);
let y = event.targetTouches[0].pageY - (lastY.value ?? 0); const y = event.targetTouches[0].pageY - (lastY.value ?? 0);
if (Math.abs(x) >= step && Math.abs(y) >= step) return; if (Math.abs(x) >= step && Math.abs(y) >= step) return;
lastX.value = event.targetTouches[0].pageX; lastX.value = event.targetTouches[0].pageX;
lastY.value = event.targetTouches[0].pageY; lastY.value = event.targetTouches[0].pageY;
@@ -268,8 +269,8 @@ const doMove = (x: number, y: number) => {
} }
const style = imgex.value.style; const style = imgex.value.style;
let posX = pxStringToNumber(style.left) + x; const posX = pxStringToNumber(style.left) + x;
let posY = pxStringToNumber(style.top) + y; const posY = pxStringToNumber(style.top) + y;
style.left = posX + "px"; style.left = posX + "px";
style.top = posY + "px"; style.top = posY + "px";

View File

@@ -8,6 +8,13 @@
@dragover="dragOver" @dragover="dragOver"
@drop="drop" @drop="drop"
@click="itemClick" @click="itemClick"
@mousedown="handleMouseDown"
@mouseup="handleMouseUp"
@mouseleave="handleMouseLeave"
@touchstart="handleTouchStart"
@touchend="handleTouchEnd"
@touchcancel="handleTouchCancel"
@touchmove="handleTouchMove"
:data-dir="isDir" :data-dir="isDir"
:data-type="type" :data-type="type"
:aria-label="name" :aria-label="name"
@@ -50,6 +57,12 @@ import { useRouter } from "vue-router";
const touches = ref<number>(0); const touches = ref<number>(0);
const longPressTimer = ref<number | null>(null);
const longPressTriggered = ref<boolean>(false);
const longPressDelay = ref<number>(500);
const startPosition = ref<{ x: number; y: number } | null>(null);
const moveThreshold = ref<number>(10);
const $showError = inject<IToastError>("$showError")!; const $showError = inject<IToastError>("$showError")!;
const router = useRouter(); const router = useRouter();
@@ -82,7 +95,7 @@ const isDraggable = computed(
const canDrop = computed(() => { const canDrop = computed(() => {
if (!props.isDir || props.readOnly) return false; if (!props.isDir || props.readOnly) return false;
for (let i of fileStore.selected) { for (const i of fileStore.selected) {
if (fileStore.req?.items[i].url === props.url) { if (fileStore.req?.items[i].url === props.url) {
return false; return false;
} }
@@ -156,9 +169,9 @@ const drop = async (event: Event) => {
} }
} }
let items: any[] = []; const items: any[] = [];
for (let i of fileStore.selected) { for (const i of fileStore.selected) {
if (fileStore.req) { if (fileStore.req) {
items.push({ items.push({
from: fileStore.req?.items[i].url, from: fileStore.req?.items[i].url,
@@ -172,10 +185,10 @@ const drop = async (event: Event) => {
if (el === null) { if (el === null) {
return; return;
} }
let path = el.__vue__.url; const path = el.__vue__.url;
let baseItems = (await api.fetch(path)).items; const baseItems = (await api.fetch(path)).items;
let action = (overwrite: boolean, rename: boolean) => { const action = (overwrite: boolean, rename: boolean) => {
api api
.move(items, overwrite, rename) .move(items, overwrite, rename)
.then(() => { .then(() => {
@@ -184,7 +197,7 @@ const drop = async (event: Event) => {
.catch($showError); .catch($showError);
}; };
let conflict = upload.checkConflict(items, baseItems); const conflict = upload.checkConflict(items, baseItems);
let overwrite = false; let overwrite = false;
let rename = false; let rename = false;
@@ -209,6 +222,12 @@ const drop = async (event: Event) => {
}; };
const itemClick = (event: Event | KeyboardEvent) => { const itemClick = (event: Event | KeyboardEvent) => {
// If long press was triggered, prevent normal click behavior
if (longPressTriggered.value) {
longPressTriggered.value = false;
return;
}
if ( if (
singleClick.value && singleClick.value &&
!(event as KeyboardEvent).ctrlKey && !(event as KeyboardEvent).ctrlKey &&
@@ -281,4 +300,76 @@ const getExtension = (fileName: string): string => {
} }
return fileName.substring(lastDotIndex); return fileName.substring(lastDotIndex);
}; };
// Long-press helper functions
const startLongPress = (clientX: number, clientY: number) => {
startPosition.value = { x: clientX, y: clientY };
longPressTimer.value = window.setTimeout(() => {
handleLongPress();
}, longPressDelay.value);
};
const cancelLongPress = () => {
if (longPressTimer.value !== null) {
window.clearTimeout(longPressTimer.value);
longPressTimer.value = null;
}
startPosition.value = null;
};
const handleLongPress = () => {
if (singleClick.value) {
longPressTriggered.value = true;
click(new Event("longpress"));
}
cancelLongPress();
};
const checkMovement = (clientX: number, clientY: number): boolean => {
if (!startPosition.value) return false;
const deltaX = Math.abs(clientX - startPosition.value.x);
const deltaY = Math.abs(clientY - startPosition.value.y);
return deltaX > moveThreshold.value || deltaY > moveThreshold.value;
};
// Event handlers
const handleMouseDown = (event: MouseEvent) => {
if (event.button === 0) {
startLongPress(event.clientX, event.clientY);
}
};
const handleMouseUp = () => {
cancelLongPress();
};
const handleMouseLeave = () => {
cancelLongPress();
};
const handleTouchStart = (event: TouchEvent) => {
if (event.touches.length === 1) {
const touch = event.touches[0];
startLongPress(touch.clientX, touch.clientY);
}
};
const handleTouchEnd = () => {
cancelLongPress();
};
const handleTouchCancel = () => {
cancelLongPress();
};
const handleTouchMove = (event: TouchEvent) => {
if (event.touches.length === 1 && startPosition.value) {
const touch = event.touches[0];
if (checkMovement(touch.clientX, touch.clientY)) {
cancelLongPress();
}
}
};
</script> </script>

View File

@@ -62,7 +62,8 @@ const initVideoPlayer = async () => {
const languagePack = await ( const languagePack = await (
languageImports[lang] || languageImports.en languageImports[lang] || languageImports.en
)?.(); )?.();
videojs.addLanguage("videoPlayerLocal", languagePack.default); const code = languageImports[lang] ? lang : "en";
videojs.addLanguage(code, languagePack.default);
sourceType.value = ""; sourceType.value = "";
// //
@@ -70,14 +71,19 @@ const initVideoPlayer = async () => {
const srcOpt = { sources: { src: props.source, type: sourceType.value } }; const srcOpt = { sources: { src: props.source, type: sourceType.value } };
//Supporting localized language display. //Supporting localized language display.
const langOpt = { language: "videoPlayerLocal" }; const langOpt = { language: code };
// support for playback at different speeds. // support for playback at different speeds.
const playbackRatesOpt = { playbackRates: [0.5, 1, 1.5, 2, 2.5, 3] }; const playbackRatesOpt = { playbackRates: [0.5, 1, 1.5, 2, 2.5, 3] };
let options = getOptions(props.options, langOpt, srcOpt, playbackRatesOpt); const options = getOptions(
props.options,
langOpt,
srcOpt,
playbackRatesOpt
);
player.value = videojs(videoPlayer.value!, options, () => {}); player.value = videojs(videoPlayer.value!, options, () => {});
// TODO: need to test on mobile // TODO: need to test on mobile
// @ts-ignore // @ts-expect-error no ts definition for mobileUi
player.value!.mobileUi(); player.value!.mobileUi();
} catch (error) { } catch (error) {
console.error("Error initializing video player:", error); console.error("Error initializing video player:", error);
@@ -120,7 +126,7 @@ const subLabel = (subUrl: string) => {
let url: URL; let url: URL;
try { try {
url = new URL(subUrl); url = new URL(subUrl);
} catch (_) { } catch {
// treat it as a relative url // treat it as a relative url
// we only need this for filename // we only need this for filename
url = new URL(subUrl, window.location.origin); url = new URL(subUrl, window.location.origin);

View File

@@ -82,10 +82,10 @@ export default {
...mapActions(useLayoutStore, ["showHover", "closeHovers"]), ...mapActions(useLayoutStore, ["showHover", "closeHovers"]),
copy: async function (event) { copy: async function (event) {
event.preventDefault(); event.preventDefault();
let items = []; const items = [];
// Create a new promise for each file. // Create a new promise for each file.
for (let item of this.selected) { for (const item of this.selected) {
items.push({ items.push({
from: this.req.items[item].url, from: this.req.items[item].url,
to: this.dest + encodeURIComponent(this.req.items[item].name), to: this.dest + encodeURIComponent(this.req.items[item].name),
@@ -93,7 +93,7 @@ export default {
}); });
} }
let action = async (overwrite, rename) => { const action = async (overwrite, rename) => {
buttons.loading("copy"); buttons.loading("copy");
await api await api
@@ -122,8 +122,8 @@ export default {
return; return;
} }
let dstItems = (await api.fetch(this.dest)).items; const dstItems = (await api.fetch(this.dest)).items;
let conflict = upload.checkConflict(items, dstItems); const conflict = upload.checkConflict(items, dstItems);
let overwrite = false; let overwrite = false;
let rename = false; let rename = false;

View File

@@ -74,8 +74,8 @@ export default {
return; return;
} }
let promises = []; const promises = [];
for (let index of this.selected) { for (const index of this.selected) {
promises.push(api.remove(this.req.items[index].url)); promises.push(api.remove(this.req.items[index].url));
} }

View File

@@ -43,7 +43,7 @@ export default {
submit: async function () { submit: async function () {
this.updateRequest(null); this.updateRequest(null);
let uri = url.removeLastDir(this.$route.path) + "/"; const uri = url.removeLastDir(this.$route.path) + "/";
this.$router.push({ path: uri }); this.$router.push({ path: uri });
}, },
}, },

View File

@@ -31,9 +31,16 @@ import { useFileStore } from "@/stores/file";
import url from "@/utils/url"; import url from "@/utils/url";
import { files } from "@/api"; import { files } from "@/api";
import { StatusError } from "@/api/utils.js";
export default { export default {
name: "file-list", name: "file-list",
props: {
exclude: {
type: Array,
default: () => [],
},
},
data: function () { data: function () {
return { return {
items: [], items: [],
@@ -43,6 +50,7 @@ export default {
}, },
selected: null, selected: null,
current: window.location.pathname, current: window.location.pathname,
nextAbortController: new AbortController(),
}; };
}, },
inject: ["$showError"], inject: ["$showError"],
@@ -56,7 +64,13 @@ export default {
mounted() { mounted() {
this.fillOptions(this.req); this.fillOptions(this.req);
}, },
unmounted() {
this.abortOngoingNext();
},
methods: { methods: {
abortOngoingNext() {
this.nextAbortController.abort();
},
fillOptions(req) { fillOptions(req) {
// Sets the current path and resets // Sets the current path and resets
// the current items. // the current items.
@@ -80,8 +94,9 @@ export default {
// Otherwise we add every directory to the // Otherwise we add every directory to the
// move options. // move options.
for (let item of req.items) { for (const item of req.items) {
if (!item.isDir) continue; if (!item.isDir) continue;
if (this.exclude?.includes(item.url)) continue;
this.items.push({ this.items.push({
name: item.name, name: item.name,
@@ -93,12 +108,21 @@ export default {
// Retrieves the URL of the directory the user // Retrieves the URL of the directory the user
// just clicked in and fill the options with its // just clicked in and fill the options with its
// content. // content.
let uri = event.currentTarget.dataset.url; const uri = event.currentTarget.dataset.url;
this.abortOngoingNext();
files.fetch(uri).then(this.fillOptions).catch(this.$showError); this.nextAbortController = new AbortController();
files
.fetch(uri, this.nextAbortController.signal)
.then(this.fillOptions)
.catch((e) => {
if (e instanceof StatusError && e.is_canceled) {
return;
}
this.$showError(e);
});
}, },
touchstart(event) { touchstart(event) {
let url = event.currentTarget.dataset.url; const url = event.currentTarget.dataset.url;
// In 300 milliseconds, we shall reset the count. // In 300 milliseconds, we shall reset the count.
setTimeout(() => { setTimeout(() => {

View File

@@ -11,7 +11,7 @@
<li><strong>DEL</strong> - {{ $t("help.del") }}</li> <li><strong>DEL</strong> - {{ $t("help.del") }}</li>
<li><strong>ESC</strong> - {{ $t("help.esc") }}</li> <li><strong>ESC</strong> - {{ $t("help.esc") }}</li>
<li><strong>CTRL + S</strong> - {{ $t("help.ctrl.s") }}</li> <li><strong>CTRL + S</strong> - {{ $t("help.ctrl.s") }}</li>
<li><strong>CTRL + F</strong> - {{ $t("help.ctrl.f") }}</li> <li><strong>CTRL + SHIFT + F</strong> - {{ $t("help.ctrl.f") }}</li>
<li><strong>CTRL + Click</strong> - {{ $t("help.ctrl.click") }}</li> <li><strong>CTRL + Click</strong> - {{ $t("help.ctrl.click") }}</li>
<li><strong>Click</strong> - {{ $t("help.click") }}</li> <li><strong>Click</strong> - {{ $t("help.click") }}</li>
<li><strong>Double click</strong> - {{ $t("help.doubleClick") }}</li> <li><strong>Double click</strong> - {{ $t("help.doubleClick") }}</li>

View File

@@ -124,7 +124,7 @@ export default {
let sum = 0; let sum = 0;
for (let selected of this.selected) { for (const selected of this.selected) {
sum += this.req.items[selected].size; sum += this.req.items[selected].size;
} }

View File

@@ -8,6 +8,7 @@
<file-list <file-list
ref="fileList" ref="fileList"
@update:selected="(val) => (dest = val)" @update:selected="(val) => (dest = val)"
:exclude="excludedFolders"
tabindex="1" tabindex="1"
/> />
</div> </div>
@@ -76,14 +77,19 @@ export default {
computed: { computed: {
...mapState(useFileStore, ["req", "selected"]), ...mapState(useFileStore, ["req", "selected"]),
...mapState(useAuthStore, ["user"]), ...mapState(useAuthStore, ["user"]),
excludedFolders() {
return this.selected
.filter((idx) => this.req.items[idx].isDir)
.map((idx) => this.req.items[idx].url);
},
}, },
methods: { methods: {
...mapActions(useLayoutStore, ["showHover", "closeHovers"]), ...mapActions(useLayoutStore, ["showHover", "closeHovers"]),
move: async function (event) { move: async function (event) {
event.preventDefault(); event.preventDefault();
let items = []; const items = [];
for (let item of this.selected) { for (const item of this.selected) {
items.push({ items.push({
from: this.req.items[item].url, from: this.req.items[item].url,
to: this.dest + encodeURIComponent(this.req.items[item].name), to: this.dest + encodeURIComponent(this.req.items[item].name),
@@ -91,7 +97,7 @@ export default {
}); });
} }
let action = async (overwrite, rename) => { const action = async (overwrite, rename) => {
buttons.loading("move"); buttons.loading("move");
await api await api
@@ -106,8 +112,8 @@ export default {
}); });
}; };
let dstItems = (await api.fetch(this.dest)).items; const dstItems = (await api.fetch(this.dest)).items;
let conflict = upload.checkConflict(items, dstItems); const conflict = upload.checkConflict(items, dstItems);
let overwrite = false; let overwrite = false;
let rename = false; let rename = false;

View File

@@ -3,7 +3,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from "vue"; import { watch } from "vue";
import { ModalsContainer, useModal } from "vue-final-modal"; import { ModalsContainer, useModal } from "vue-final-modal";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { useLayoutStore } from "@/stores/layout"; import { useLayoutStore } from "@/stores/layout";
@@ -30,8 +30,6 @@ const layoutStore = useLayoutStore();
const { currentPromptName } = storeToRefs(layoutStore); const { currentPromptName } = storeToRefs(layoutStore);
const closeModal = ref<() => Promise<string>>();
const components = new Map<string, any>([ const components = new Map<string, any>([
["info", Info], ["info", Info],
["help", Help], ["help", Help],
@@ -52,11 +50,6 @@ const components = new Map<string, any>([
]); ]);
watch(currentPromptName, (newValue) => { watch(currentPromptName, (newValue) => {
if (closeModal.value) {
closeModal.value();
closeModal.value = undefined;
}
const modal = components.get(newValue!); const modal = components.get(newValue!);
if (!modal) return; if (!modal) return;
@@ -67,7 +60,7 @@ watch(currentPromptName, (newValue) => {
}, },
}); });
closeModal.value = close; layoutStore.setCloseOnPrompt(close, newValue!);
open(); open();
}); });

View File

@@ -32,16 +32,6 @@
<i class="material-icons">content_paste</i> <i class="material-icons">content_paste</i>
</button> </button>
</td> </td>
<td class="small" v-if="hasDownloadLink()">
<button
class="action copy-clipboard"
:aria-label="$t('buttons.copyDownloadLinkToClipboard')"
:title="$t('buttons.copyDownloadLinkToClipboard')"
@click="copyToClipboard(buildDownloadLink(link))"
>
<i class="material-icons">content_paste_go</i>
</button>
</td>
<td class="small"> <td class="small">
<button <button
class="action" class="action"
@@ -142,7 +132,7 @@
<script> <script>
import { mapActions, mapState } from "pinia"; import { mapActions, mapState } from "pinia";
import { useFileStore } from "@/stores/file"; import { useFileStore } from "@/stores/file";
import { share as api, pub as pub_api } from "@/api"; import { share as api } from "@/api";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { useLayoutStore } from "@/stores/layout"; import { useLayoutStore } from "@/stores/layout";
import { copy } from "@/utils/clipboard"; import { copy } from "@/utils/clipboard";
@@ -196,13 +186,23 @@ export default {
methods: { methods: {
...mapActions(useLayoutStore, ["closeHovers"]), ...mapActions(useLayoutStore, ["closeHovers"]),
copyToClipboard: function (text) { copyToClipboard: function (text) {
copy(text).then( copy({ text }).then(
() => { () => {
// clipboard successfully set // clipboard successfully set
this.$showSuccess(this.$t("success.linkCopied")); this.$showSuccess(this.$t("success.linkCopied"));
}, },
() => { () => {
// clipboard write failed // clipboard write failed
copy({ text }, { permission: true }).then(
() => {
// clipboard successfully set
this.$showSuccess(this.$t("success.linkCopied"));
},
(e) => {
// clipboard write failed
this.$showError(e);
}
);
} }
); );
}, },
@@ -247,14 +247,6 @@ export default {
buildLink(share) { buildLink(share) {
return api.getShareURL(share); return api.getShareURL(share);
}, },
hasDownloadLink() {
return (
this.selected.length === 1 && !this.req.items[this.selected[0]].isDir
);
},
buildDownloadLink(share) {
return pub_api.getDownloadURL(share);
},
sort() { sort() {
this.links = this.links.sort((a, b) => { this.links = this.links.sort((a, b) => {
if (a.expire === 0) return -1; if (a.expire === 0) return -1;

View File

@@ -48,12 +48,10 @@ const layoutStore = useLayoutStore();
// TODO: this is a copy of the same function in FileListing.vue // TODO: this is a copy of the same function in FileListing.vue
const uploadInput = (event: Event) => { const uploadInput = (event: Event) => {
layoutStore.closeHovers(); const files = (event.currentTarget as HTMLInputElement)?.files;
let files = (event.currentTarget as HTMLInputElement)?.files;
if (files === null) return; if (files === null) return;
let folder_upload = !!files[0].webkitRelativePath; const folder_upload = !!files[0].webkitRelativePath;
const uploadFiles: UploadList = []; const uploadFiles: UploadList = [];
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
@@ -68,8 +66,8 @@ const uploadInput = (event: Event) => {
}); });
} }
let path = route.path.endsWith("/") ? route.path : route.path + "/"; const path = route.path.endsWith("/") ? route.path : route.path + "/";
let conflict = upload.checkConflict(uploadFiles, fileStore.req!.items); const conflict = upload.checkConflict(uploadFiles, fileStore.req!.items);
if (conflict) { if (conflict) {
layoutStore.showHover({ layoutStore.showHover({

View File

@@ -13,12 +13,13 @@ export default {
name: "languages", name: "languages",
props: ["locale"], props: ["locale"],
data() { data() {
let dataObj = {}; const dataObj = {};
const locales = { const locales = {
he: "עברית", he: "עברית",
hu: "Magyar", hu: "Magyar",
ar: "العربية", ar: "العربية",
ca: "Català", ca: "Català",
cs: "Čeština",
de: "Deutsch", de: "Deutsch",
el: "Ελληνικά", el: "Ελληνικά",
en: "English", en: "English",
@@ -38,6 +39,7 @@ export default {
"sv-se": "Swedish (Sweden)", "sv-se": "Swedish (Sweden)",
tr: "Türkçe", tr: "Türkçe",
uk: "Українська", uk: "Українська",
vi: "Tiếng Việt",
"zh-cn": "中文 (简体)", "zh-cn": "中文 (简体)",
"zh-tw": "中文 (繁體)", "zh-tw": "中文 (繁體)",
}; };

View File

@@ -39,7 +39,7 @@ export default {
methods: { methods: {
remove(event, index) { remove(event, index) {
event.preventDefault(); event.preventDefault();
let rules = [...this.rules]; const rules = [...this.rules];
rules.splice(index, 1); rules.splice(index, 1);
this.$emit("update:rules", [...rules]); this.$emit("update:rules", [...rules]);
}, },

View File

@@ -7,7 +7,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { SelectHTMLAttributes } from "vue"; import type { SelectHTMLAttributes } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const { t } = useI18n(); const { t } = useI18n();
@@ -17,7 +17,6 @@ defineProps<{
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(e: "update:theme", val: string | null): void; (e: "update:theme", val: string | null): void;
}>(); }>();

View File

@@ -116,7 +116,7 @@ watch(createUserDirData, () => {
if (props.user?.scope) { if (props.user?.scope) {
props.user.scope = createUserDirData.value props.user.scope = createUserDirData.value
? "" ? ""
: originalUserScope.value ?? ""; : (originalUserScope.value ?? "");
} }
}); });
</script> </script>

View File

@@ -63,8 +63,8 @@
local("Roboto"), local("Roboto"),
local("Roboto-Regular"), local("Roboto-Regular"),
url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2"); url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2");
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
U+A720-A7FF; U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
@@ -142,8 +142,8 @@
local("Roboto Medium"), local("Roboto Medium"),
local("Roboto-Medium"), local("Roboto-Medium"),
url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2"); url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2");
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
U+A720-A7FF; U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {
@@ -221,8 +221,8 @@
local("Roboto Bold"), local("Roboto Bold"),
local("Roboto-Bold"), local("Roboto-Bold"),
url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2"); url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2");
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
U+A720-A7FF; U+2C60-2C7F, U+A720-A7FF;
} }
@font-face { @font-face {

View File

@@ -24,6 +24,7 @@
"ok": "موافق", "ok": "موافق",
"permalink": "الحصول على رابط دائم", "permalink": "الحصول على رابط دائم",
"previous": "السابق", "previous": "السابق",
"preview": "Preview",
"publish": "نشر", "publish": "نشر",
"rename": "إعادة تسمية", "rename": "إعادة تسمية",
"replace": "استبدال", "replace": "استبدال",
@@ -169,6 +170,7 @@
"commandRunnerHelp": "هنا بإمكانك تعيين اﻷوامر التي سيتم تنفيذها في اﻷحداث المسماة. يجب كتابة أمر واحد في كل سطر. ستكون المتغيرات البيئية (env) {0} و {1} متاحة، حيث {0} نسبي لـ {1}. لمزيد من المعلومات حول هذه الميزة و المتغيرات البيئية المتاحة، يرجى قراءة {2}.", "commandRunnerHelp": "هنا بإمكانك تعيين اﻷوامر التي سيتم تنفيذها في اﻷحداث المسماة. يجب كتابة أمر واحد في كل سطر. ستكون المتغيرات البيئية (env) {0} و {1} متاحة، حيث {0} نسبي لـ {1}. لمزيد من المعلومات حول هذه الميزة و المتغيرات البيئية المتاحة، يرجى قراءة {2}.",
"commandsUpdated": "تم تحديث اﻷوامر", "commandsUpdated": "تم تحديث اﻷوامر",
"createUserDir": "إنشاء مجلد المستخدم (home) تلقائياً عند إنشاء مستخدم جديد", "createUserDir": "إنشاء مجلد المستخدم (home) تلقائياً عند إنشاء مستخدم جديد",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "التحميلات المتقطعة", "tusUploads": "التحميلات المتقطعة",
"tusUploadsHelp": "يدعم متصفح الملفات تحميل الملفات المتقطعة، مما يسمح بتحميلات الملفات بشكل فعال و موثوق و قابلة للمتابغة و متقطعة حتى على الشبكات غير الموثوقة.", "tusUploadsHelp": "يدعم متصفح الملفات تحميل الملفات المتقطعة، مما يسمح بتحميلات الملفات بشكل فعال و موثوق و قابلة للمتابغة و متقطعة حتى على الشبكات غير الموثوقة.",
"tusUploadsChunkSize": "يشير إلى الحد اﻷقصى لحجم الطلب (سيتم استخدام التحميل المباشر للتحميلات صغيرة الخحم). يمكنك إدخال عدد صحيح عادي يدل على الحجم بوحدة البايت أو نمظ مثل10MB, 1GB, إلخ.", "tusUploadsChunkSize": "يشير إلى الحد اﻷقصى لحجم الطلب (سيتم استخدام التحميل المباشر للتحميلات صغيرة الخحم). يمكنك إدخال عدد صحيح عادي يدل على الحجم بوحدة البايت أو نمظ مثل10MB, 1GB, إلخ.",

View File

@@ -24,6 +24,7 @@
"ok": "D'acord", "ok": "D'acord",
"permalink": "Enllaç permanent", "permalink": "Enllaç permanent",
"previous": "Anterior", "previous": "Anterior",
"preview": "Preview",
"publish": "Publicar", "publish": "Publicar",
"rename": "Reanomenar", "rename": "Reanomenar",
"replace": "Substituir", "replace": "Substituir",
@@ -169,6 +170,7 @@
"commandRunnerHelp": "Aquí pots establir les comandes que s'executen en els esdeveniments anomenats. Has d'escriure'n una per línia. Les variables d'entorn {0} i {1} estaran disponibles, sent {0} relativa a {1}. Per a més informació sobre aquesta característica i les variables d'entorn disponibles, si us plau llegeix el {2}.", "commandRunnerHelp": "Aquí pots establir les comandes que s'executen en els esdeveniments anomenats. Has d'escriure'n una per línia. Les variables d'entorn {0} i {1} estaran disponibles, sent {0} relativa a {1}. Per a més informació sobre aquesta característica i les variables d'entorn disponibles, si us plau llegeix el {2}.",
"commandsUpdated": "Comandes actualitzades!", "commandsUpdated": "Comandes actualitzades!",
"createUserDir": "Crea automàticament una carpeta d'inici quan s'afegeix un usuari", "createUserDir": "Crea automàticament una carpeta d'inici quan s'afegeix un usuari",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Càrregues a trossos", "tusUploads": "Càrregues a trossos",
"tusUploadsHelp": "El File Browser suporta càrregues de fitxers a trossos, permetent la creació de càrregues de fitxers eficients, fiables, reanudables i a trossos fins i tot en xarxes poc fiables.", "tusUploadsHelp": "El File Browser suporta càrregues de fitxers a trossos, permetent la creació de càrregues de fitxers eficients, fiables, reanudables i a trossos fins i tot en xarxes poc fiables.",
"tusUploadsChunkSize": "Indica la mida màxima d'una sol·licitud (s'utilitzaran càrregues directes per a càrregues més petites). Podeu introduir un enter pla que indiqui la mida en bytes o una cadena com 10MB, 1GB, etc.", "tusUploadsChunkSize": "Indica la mida màxima d'una sol·licitud (s'utilitzaran càrregues directes per a càrregues més petites). Podeu introduir un enter pla que indiqui la mida en bytes o una cadena com 10MB, 1GB, etc.",

View File

@@ -24,6 +24,7 @@
"ok": "OK", "ok": "OK",
"permalink": "Získat trvalý odkaz", "permalink": "Získat trvalý odkaz",
"previous": "Předchozí", "previous": "Předchozí",
"preview": "Preview",
"publish": "Publikovat", "publish": "Publikovat",
"rename": "Přejmenovat", "rename": "Přejmenovat",
"replace": "Nahradit", "replace": "Nahradit",
@@ -169,6 +170,7 @@
"commandRunnerHelp": "Zde můžete nastavit příkazy, které se spustí při určených událostech. Každý příkaz musí být na samostatném řádku. Budou k dispozici proměnné prostředí {0} a {1}, přičemž {0} se vztahuje na {1}. Pro více informací o této funkci a dostupných proměnných prostředí si přečtěte {2}.", "commandRunnerHelp": "Zde můžete nastavit příkazy, které se spustí při určených událostech. Každý příkaz musí být na samostatném řádku. Budou k dispozici proměnné prostředí {0} a {1}, přičemž {0} se vztahuje na {1}. Pro více informací o této funkci a dostupných proměnných prostředí si přečtěte {2}.",
"commandsUpdated": "Příkazy aktualizovány!", "commandsUpdated": "Příkazy aktualizovány!",
"createUserDir": "Automaticky vytvořit domovskou složku uživatele při přidání nového uživatele", "createUserDir": "Automaticky vytvořit domovskou složku uživatele při přidání nového uživatele",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Nahrávání po částech", "tusUploads": "Nahrávání po částech",
"tusUploadsHelp": "File Browser podporuje nahrávání souborů po částech, což umožňuje vytváření efektivních, spolehlivých, obnovitelných a rozdělených nahrávek souborů i na nespolehlivých sítích.", "tusUploadsHelp": "File Browser podporuje nahrávání souborů po částech, což umožňuje vytváření efektivních, spolehlivých, obnovitelných a rozdělených nahrávek souborů i na nespolehlivých sítích.",
"tusUploadsChunkSize": "Maximální velikost požadavku (přímé nahrávání bude použito pro menší nahrávky). Můžete zadat prosté číslo označující velikost v bajtech nebo řetězec jako 10MB, 1GB atd.", "tusUploadsChunkSize": "Maximální velikost požadavku (přímé nahrávání bude použito pro menší nahrávky). Můžete zadat prosté číslo označující velikost v bajtech nebo řetězec jako 10MB, 1GB atd.",

View File

@@ -3,14 +3,17 @@
"cancel": "Abbrechen", "cancel": "Abbrechen",
"clear": "Schließen", "clear": "Schließen",
"close": "Schließen", "close": "Schließen",
"continue": "Fortfahren",
"copy": "Kopieren", "copy": "Kopieren",
"copyFile": "Kopiere Datei", "copyFile": "Kopiere Datei",
"copyToClipboard": "In Zwischenablage kopieren", "copyToClipboard": "In Zwischenablage kopieren",
"copyDownloadLinkToClipboard": "Download-Link in die Zwischenablage kopieren",
"create": "Neu", "create": "Neu",
"delete": "Löschen", "delete": "Löschen",
"download": "Herunterladen", "download": "Herunterladen",
"file": "Datei", "file": "Datei",
"folder": "Ordner", "folder": "Ordner",
"fullScreen": "Vollbildmodus umschalten",
"hideDotfiles": "Versteckte Dateien ausblenden", "hideDotfiles": "Versteckte Dateien ausblenden",
"info": "Info", "info": "Info",
"more": "mehr", "more": "mehr",
@@ -21,6 +24,7 @@
"ok": "OK", "ok": "OK",
"permalink": "permanenten Verweis anzeigen", "permalink": "permanenten Verweis anzeigen",
"previous": "vorherige", "previous": "vorherige",
"preview": "Vorschau",
"publish": "Veröffentlichen", "publish": "Veröffentlichen",
"rename": "umbenennen", "rename": "umbenennen",
"replace": "Ersetzen", "replace": "Ersetzen",
@@ -37,13 +41,17 @@
"toggleSidebar": "Seitenleiste anzeigen", "toggleSidebar": "Seitenleiste anzeigen",
"update": "Update", "update": "Update",
"upload": "Upload", "upload": "Upload",
"openFile": "Datei öffnen" "openFile": "Datei öffnen",
"discardChanges": "Verwerfen"
}, },
"download": { "download": {
"downloadFile": "Download Datei", "downloadFile": "Download Datei",
"downloadFolder": "Download Ordner", "downloadFolder": "Download Ordner",
"downloadSelected": "Auswahl herunterladen" "downloadSelected": "Auswahl herunterladen"
}, },
"upload": {
"abortUpload": "Sind Sie sicher, dass Sie den Vorgang abbrechen möchten?"
},
"errors": { "errors": {
"forbidden": "Sie haben keine Berechtigung dies abzurufen.", "forbidden": "Sie haben keine Berechtigung dies abzurufen.",
"internal": "Etwas ist schiefgelaufen.", "internal": "Etwas ist schiefgelaufen.",
@@ -102,6 +110,7 @@
"deleteMessageMultiple": "Sind Sie sicher, dass Sie {count} Datei(en) löschen möchten?", "deleteMessageMultiple": "Sind Sie sicher, dass Sie {count} Datei(en) löschen möchten?",
"deleteMessageSingle": "Sind Sie sicher, dass Sie diesen Ordner/diese Datei löschen möchten?", "deleteMessageSingle": "Sind Sie sicher, dass Sie diesen Ordner/diese Datei löschen möchten?",
"deleteMessageShare": "Sind Sie sicher, dass Sie diese Freigabe löschen möchten ({path})?", "deleteMessageShare": "Sind Sie sicher, dass Sie diese Freigabe löschen möchten ({path})?",
"deleteUser": "Sind Sie sicher, dass Sie diesen Benutzer löschen möchten?",
"deleteTitle": "Lösche Dateien", "deleteTitle": "Lösche Dateien",
"displayName": "Anzeigename:", "displayName": "Anzeigename:",
"download": "Lade Dateien", "download": "Lade Dateien",
@@ -130,7 +139,9 @@
"upload": "Upload", "upload": "Upload",
"uploadFiles": "Upload von {files} Dateien...", "uploadFiles": "Upload von {files} Dateien...",
"uploadMessage": "Wählen Sie eine Upload-Methode", "uploadMessage": "Wählen Sie eine Upload-Methode",
"optionalPassword": "Optionales Passwort" "optionalPassword": "Optionales Passwort",
"resolution": "Auflösung",
"discardEditorChanges": "Möchten Sie die vorgenommenen Änderungen wirklich verwerfen?"
}, },
"search": { "search": {
"images": "Bilder", "images": "Bilder",
@@ -159,10 +170,14 @@
"commandRunnerHelp": "Hier könne Sie Befehle eintragen, welche bei den benannten Aktionen ausgeführt werden. Sie müssen pro Zeile jeweils einen Befehl eingeben. Die Umgebungsvariable {0} und {1} sind verfügbar, wobei {0} relative zu {1} ist. Für mehr Informationen über diese Funktion und die verfügbaren Umgebungsvariablen lesen Sie bitte die {2}.", "commandRunnerHelp": "Hier könne Sie Befehle eintragen, welche bei den benannten Aktionen ausgeführt werden. Sie müssen pro Zeile jeweils einen Befehl eingeben. Die Umgebungsvariable {0} und {1} sind verfügbar, wobei {0} relative zu {1} ist. Für mehr Informationen über diese Funktion und die verfügbaren Umgebungsvariablen lesen Sie bitte die {2}.",
"commandsUpdated": "Befehle aktualisiert!", "commandsUpdated": "Befehle aktualisiert!",
"createUserDir": "Automatisches Erstellen des Home-Verzeichnisses beim Anlegen neuer Benutzer", "createUserDir": "Automatisches Erstellen des Home-Verzeichnisses beim Anlegen neuer Benutzer",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Gestückelter Upload", "tusUploads": "Gestückelter Upload",
"tusUploadsHelp": "File Browser unterstützt das Hochladen von gestückelten Dateien und ermöglicht so einen effizienten, zuverlässigen, fortsetzbaren und gestückelten Datei-Upload auch in unzuverlässigen Netzwerken.", "tusUploadsHelp": "File Browser unterstützt das Hochladen von gestückelten Dateien und ermöglicht so einen effizienten, zuverlässigen, fortsetzbaren und gestückelten Datei-Upload auch in unzuverlässigen Netzwerken.",
"tusUploadsChunkSize": "Gibt die maximale Größe pro Anfrage an (direkte Uploads werden für kleinere Uploads verwendet). Bitte geben Sie eine Byte-Angabe oder eine Zeichenfolge wie 10 MB, 1 GB usw. an", "tusUploadsChunkSize": "Gibt die maximale Größe pro Anfrage an (direkte Uploads werden für kleinere Uploads verwendet). Bitte geben Sie eine Byte-Angabe oder eine Zeichenfolge wie 10 MB, 1 GB usw. an",
"tusUploadsRetryCount": "Anzahl der Wiederholungsversuche, wenn das Hochladen eines Stückes fehlschlägt.", "tusUploadsRetryCount": "Anzahl der Wiederholungsversuche, wenn das Hochladen eines Stückes fehlschlägt.",
"userHomeBasePath": "Basispfad für Benutzer-Home-Verzeichnisse",
"userScopeGenerationPlaceholder": "Scope wird automatisch generiert",
"createUserHomeDirectory": "Benutzer-Home-Verzeichnis erstellen",
"customStylesheet": "Individuelles Stylesheet", "customStylesheet": "Individuelles Stylesheet",
"defaultUserDescription": "Das sind die Standardeinstellung für Benutzer", "defaultUserDescription": "Das sind die Standardeinstellung für Benutzer",
"disableExternalLinks": "Externe Links deaktivieren (außer Dokumentation)", "disableExternalLinks": "Externe Links deaktivieren (außer Dokumentation)",
@@ -209,6 +224,7 @@
"shareDeleted": "Freigabe gelöscht!", "shareDeleted": "Freigabe gelöscht!",
"singleClick": "Einfacher Klick zum Öffnen von Dateien und Ordnern", "singleClick": "Einfacher Klick zum Öffnen von Dateien und Ordnern",
"themes": { "themes": {
"default": "Systemstandard",
"dark": "Dunkel", "dark": "Dunkel",
"light": "Hell", "light": "Hell",
"title": "Erscheinungsbild" "title": "Erscheinungsbild"

View File

@@ -3,6 +3,7 @@
"cancel": "Ακύρωση", "cancel": "Ακύρωση",
"clear": "Καθαρισμός", "clear": "Καθαρισμός",
"close": "Κλείσιμο", "close": "Κλείσιμο",
"continue": "Continue",
"copy": "Αντιγραφή", "copy": "Αντιγραφή",
"copyFile": "Αντιγραφή αρχείου", "copyFile": "Αντιγραφή αρχείου",
"copyToClipboard": "Αντιγραφή στο πρόχειρο", "copyToClipboard": "Αντιγραφή στο πρόχειρο",
@@ -12,6 +13,7 @@
"download": "Λήψη", "download": "Λήψη",
"file": "Αρχείο", "file": "Αρχείο",
"folder": "Φάκελος", "folder": "Φάκελος",
"fullScreen": "Toggle full screen",
"hideDotfiles": "Απόκρυψη κρυφών αρχείων", "hideDotfiles": "Απόκρυψη κρυφών αρχείων",
"info": "Πληροφορίες", "info": "Πληροφορίες",
"more": "Περισσότερα", "more": "Περισσότερα",
@@ -22,6 +24,7 @@
"ok": "Εντάξει", "ok": "Εντάξει",
"permalink": "Λήψη μόνιμου συνδέσμου", "permalink": "Λήψη μόνιμου συνδέσμου",
"previous": "Προηγούμενο", "previous": "Προηγούμενο",
"preview": "Preview",
"publish": "Δημοσίευση", "publish": "Δημοσίευση",
"rename": "Μετονομασία", "rename": "Μετονομασία",
"replace": "Αντικατάσταση", "replace": "Αντικατάσταση",
@@ -32,12 +35,14 @@
"select": "Επιλογή", "select": "Επιλογή",
"selectMultiple": "Επιλογή πολλαπλών", "selectMultiple": "Επιλογή πολλαπλών",
"share": "Κοινοποίηση", "share": "Κοινοποίηση",
"shell": "Toggle shell",
"submit": "Υποβολή", "submit": "Υποβολή",
"switchView": "Εναλλαγή προβολής", "switchView": "Εναλλαγή προβολής",
"toggleSidebar": "(Απ-)ενεργοποίησης της πλευρικής μπάρας", "toggleSidebar": "(Απ-)ενεργοποίησης της πλευρικής μπάρας",
"update": "Ενημέρωση", "update": "Ενημέρωση",
"upload": "Μεταφόρτωση", "upload": "Μεταφόρτωση",
"openFile": "Άνοιγμα αρχείου" "openFile": "Άνοιγμα αρχείου",
"discardChanges": "Discard"
}, },
"download": { "download": {
"downloadFile": "Λήψη αρχείου", "downloadFile": "Λήψη αρχείου",
@@ -101,9 +106,11 @@
"prompts": { "prompts": {
"copy": "Αντιγραφή", "copy": "Αντιγραφή",
"copyMessage": "Επιλέξτε τοποθεσία για αντιγραφή των αρχείων σας:", "copyMessage": "Επιλέξτε τοποθεσία για αντιγραφή των αρχείων σας:",
"currentlyNavigating": "Currently navigating on:",
"deleteMessageMultiple": "Είστε σίγουροι ότι θέλετε να διαγράψετε {count} αρχεία;", "deleteMessageMultiple": "Είστε σίγουροι ότι θέλετε να διαγράψετε {count} αρχεία;",
"deleteMessageSingle": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το αρχείο/φάκελο;", "deleteMessageSingle": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το αρχείο/φάκελο;",
"deleteMessageShare": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτή την κοινοποίηση ({path});", "deleteMessageShare": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτή την κοινοποίηση ({path});",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "Διαγραφή αρχείων", "deleteTitle": "Διαγραφή αρχείων",
"displayName": "Εμφάνιση ονόματος:", "displayName": "Εμφάνιση ονόματος:",
"download": "Λήψη αρχείων", "download": "Λήψη αρχείων",
@@ -132,7 +139,9 @@
"upload": "Μεταφόρτωση", "upload": "Μεταφόρτωση",
"uploadFiles": "Μεταφόρτωση {files} αρχείων…", "uploadFiles": "Μεταφόρτωση {files} αρχείων…",
"uploadMessage": "Επιλέξτε μια επιλογή για τη μεταφόρτωση.", "uploadMessage": "Επιλέξτε μια επιλογή για τη μεταφόρτωση.",
"optionalPassword": "Προαιρετικός κωδικός πρόσβασης" "optionalPassword": "Προαιρετικός κωδικός πρόσβασης",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
}, },
"search": { "search": {
"images": "Εικόνες", "images": "Εικόνες",
@@ -161,6 +170,7 @@
"commandRunnerHelp": "Εδώ μπορείτε να ορίσετε εντολές που εκτελούνται στα ονομασμένα γεγονότα και δραστηριότητες. Πρέπει να γράψετε μία εντολή ανά γραμμή. Οι μεταβλητές περιβάλλοντος {0} και {1} θα είναι διαθέσιμες, και θα είναι {0} σχετικές με το {1}. Για περισσότερες πληροφορίες σχετικά με αυτή τη λειτουργία και τις διαθέσιμες μεταβλητές περιβάλλοντος, παρακαλώ διαβάστε το {2}.", "commandRunnerHelp": "Εδώ μπορείτε να ορίσετε εντολές που εκτελούνται στα ονομασμένα γεγονότα και δραστηριότητες. Πρέπει να γράψετε μία εντολή ανά γραμμή. Οι μεταβλητές περιβάλλοντος {0} και {1} θα είναι διαθέσιμες, και θα είναι {0} σχετικές με το {1}. Για περισσότερες πληροφορίες σχετικά με αυτή τη λειτουργία και τις διαθέσιμες μεταβλητές περιβάλλοντος, παρακαλώ διαβάστε το {2}.",
"commandsUpdated": "Οι εντολές ενημερώθηκαν!", "commandsUpdated": "Οι εντολές ενημερώθηκαν!",
"createUserDir": "Αυτόματη δημιουργία φακέλου χρήστη κατά την προσθήκη νέου χρήστη", "createUserDir": "Αυτόματη δημιουργία φακέλου χρήστη κατά την προσθήκη νέου χρήστη",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Τμηματικές μεταφορές αρχείων", "tusUploads": "Τμηματικές μεταφορές αρχείων",
"tusUploadsHelp": "Η εφαρμογή File Browser υποστηρίζει τμηματικές μεταφορτώσεις αρχείων, επιτρέποντας την αποδοτική, αξιόπιστη και συνεχιζόμενη μεταφόρτωση αρχείων ακόμα και σε ασταθείς συνδέσεις δικτύου.", "tusUploadsHelp": "Η εφαρμογή File Browser υποστηρίζει τμηματικές μεταφορτώσεις αρχείων, επιτρέποντας την αποδοτική, αξιόπιστη και συνεχιζόμενη μεταφόρτωση αρχείων ακόμα και σε ασταθείς συνδέσεις δικτύου.",
"tusUploadsChunkSize": "Υποδεικνύει το μέγιστο μέγεθος ενός αιτήματος μεταφόρτωσης (για μικρότερες μεταφορές αρχείων θα χρησιμοποιηθούν απευθείας και όχι τμηματικές μεταφορτώσεις). Μπορείτε να εισάγετε έναν ακέραιο αριθμό που υποδηλώνει το μέγεθος σε bytes, ή κείμενο με αριθμό και μονάδα μέτρησης μεγέθους δεδομένων, όπως 10MB, 1GB κλπ.", "tusUploadsChunkSize": "Υποδεικνύει το μέγιστο μέγεθος ενός αιτήματος μεταφόρτωσης (για μικρότερες μεταφορές αρχείων θα χρησιμοποιηθούν απευθείας και όχι τμηματικές μεταφορτώσεις). Μπορείτε να εισάγετε έναν ακέραιο αριθμό που υποδηλώνει το μέγεθος σε bytes, ή κείμενο με αριθμό και μονάδα μέτρησης μεγέθους δεδομένων, όπως 10MB, 1GB κλπ.",
@@ -214,6 +224,7 @@
"shareDeleted": "Η κοινοποίηση διαγράφηκε!", "shareDeleted": "Η κοινοποίηση διαγράφηκε!",
"singleClick": "Χρήση μονού κλικ για να ανοίξετε αρχεία και φακέλους", "singleClick": "Χρήση μονού κλικ για να ανοίξετε αρχεία και φακέλους",
"themes": { "themes": {
"default": "System default",
"dark": "Σκοτεινό", "dark": "Σκοτεινό",
"light": "Φωτεινό", "light": "Φωτεινό",
"title": "Μοτίβο" "title": "Μοτίβο"

View File

@@ -170,6 +170,7 @@
"commandRunnerHelp": "Here you can set commands that are executed in the named events. You must write one per line. The environment variables {0} and {1} will be available, being {0} relative to {1}. For more information about this feature and the available environment variables, please read the {2}.", "commandRunnerHelp": "Here you can set commands that are executed in the named events. You must write one per line. The environment variables {0} and {1} will be available, being {0} relative to {1}. For more information about this feature and the available environment variables, please read the {2}.",
"commandsUpdated": "Commands updated!", "commandsUpdated": "Commands updated!",
"createUserDir": "Auto create user home dir while adding new user", "createUserDir": "Auto create user home dir while adding new user",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Chunked Uploads", "tusUploads": "Chunked Uploads",
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.", "tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.", "tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",

View File

@@ -7,11 +7,13 @@
"copy": "Copiar", "copy": "Copiar",
"copyFile": "Copiar archivo", "copyFile": "Copiar archivo",
"copyToClipboard": "Copiar al portapapeles", "copyToClipboard": "Copiar al portapapeles",
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
"create": "Crear", "create": "Crear",
"delete": "Borrar", "delete": "Borrar",
"download": "Descargar", "download": "Descargar",
"file": "Archivo", "file": "Archivo",
"folder": "Carpeta", "folder": "Carpeta",
"fullScreen": "Toggle full screen",
"hideDotfiles": "Ocultar archivos empezados por punto", "hideDotfiles": "Ocultar archivos empezados por punto",
"info": "Info", "info": "Info",
"more": "Más", "more": "Más",
@@ -22,6 +24,7 @@
"ok": "OK", "ok": "OK",
"permalink": "Link permanente", "permalink": "Link permanente",
"previous": "Anterior", "previous": "Anterior",
"preview": "Preview",
"publish": "Publicar", "publish": "Publicar",
"rename": "Renombrar", "rename": "Renombrar",
"replace": "Reemplazar", "replace": "Reemplazar",
@@ -38,13 +41,17 @@
"toggleSidebar": "Mostrar/Ocultar menú", "toggleSidebar": "Mostrar/Ocultar menú",
"update": "Actualizar", "update": "Actualizar",
"upload": "Subir", "upload": "Subir",
"openFile": "Abrir archivo" "openFile": "Abrir archivo",
"discardChanges": "Discard"
}, },
"download": { "download": {
"downloadFile": "Descargar fichero", "downloadFile": "Descargar fichero",
"downloadFolder": "Descargar directorio", "downloadFolder": "Descargar directorio",
"downloadSelected": "Descargar seleccionados" "downloadSelected": "Descargar seleccionados"
}, },
"upload": {
"abortUpload": "Are you sure you wish to abort?"
},
"errors": { "errors": {
"forbidden": "No tienes los permisos necesarios para acceder.", "forbidden": "No tienes los permisos necesarios para acceder.",
"internal": "La verdad es que algo ha ido mal.", "internal": "La verdad es que algo ha ido mal.",
@@ -103,6 +110,7 @@
"deleteMessageMultiple": "¿Estás seguro que quieres eliminar {count} archivo(s)?", "deleteMessageMultiple": "¿Estás seguro que quieres eliminar {count} archivo(s)?",
"deleteMessageSingle": "¿Estás seguro que quieres eliminar este archivo/carpeta?", "deleteMessageSingle": "¿Estás seguro que quieres eliminar este archivo/carpeta?",
"deleteMessageShare": "¿Está seguro de que quiere eliminar este recurso compartido({path})?", "deleteMessageShare": "¿Está seguro de que quiere eliminar este recurso compartido({path})?",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "Borrar archivos", "deleteTitle": "Borrar archivos",
"displayName": "Nombre:", "displayName": "Nombre:",
"download": "Descargar archivos", "download": "Descargar archivos",
@@ -131,7 +139,9 @@
"upload": "Subir", "upload": "Subir",
"uploadFiles": "Subiendo {files} archivos...", "uploadFiles": "Subiendo {files} archivos...",
"uploadMessage": "Seleccione una opción para subir.", "uploadMessage": "Seleccione una opción para subir.",
"optionalPassword": "Contraseña opcional" "optionalPassword": "Contraseña opcional",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
}, },
"search": { "search": {
"images": "Imágenes", "images": "Imágenes",
@@ -160,6 +170,11 @@
"commandRunnerHelp": "Aquí puede establecer los comandos que se ejecutan en los eventos nombrados. Debe escribir uno por línea. Las variables de entorno {0} y {1} estarán disponibles, siendo {0} relativa a {1}. Para más información sobre esta característica y las variables de entorno disponibles, por favor lea el {2}.", "commandRunnerHelp": "Aquí puede establecer los comandos que se ejecutan en los eventos nombrados. Debe escribir uno por línea. Las variables de entorno {0} y {1} estarán disponibles, siendo {0} relativa a {1}. Para más información sobre esta característica y las variables de entorno disponibles, por favor lea el {2}.",
"commandsUpdated": "¡Comandos actualizados!", "commandsUpdated": "¡Comandos actualizados!",
"createUserDir": "Crea automaticamente una carpeta de inicio cuando se agrega un usuario", "createUserDir": "Crea automaticamente una carpeta de inicio cuando se agrega un usuario",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Chunked Uploads",
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
"userHomeBasePath": "Ruta base para los directorios personales de los usuarios", "userHomeBasePath": "Ruta base para los directorios personales de los usuarios",
"userScopeGenerationPlaceholder": "El ámbito se generará automáticamente", "userScopeGenerationPlaceholder": "El ámbito se generará automáticamente",
"createUserHomeDirectory": "Crear el directorio principal del usuario", "createUserHomeDirectory": "Crear el directorio principal del usuario",
@@ -173,7 +188,7 @@
"executeOnShellDescription": "Por defecto, FileBrowser ejecuta los comandos llamando directamente a sus binarios. Si quieres ejecutarlos en un shell en su lugar (como Bash o PowerShell), puedes definirlo aquí con los argumentos y banderas (flags) necesarios. Si se define, el comando que se ejecuta se añadirá como argumento. Esto se aplica tanto a los comandos de usuario como a los ganchos de eventos.", "executeOnShellDescription": "Por defecto, FileBrowser ejecuta los comandos llamando directamente a sus binarios. Si quieres ejecutarlos en un shell en su lugar (como Bash o PowerShell), puedes definirlo aquí con los argumentos y banderas (flags) necesarios. Si se define, el comando que se ejecuta se añadirá como argumento. Esto se aplica tanto a los comandos de usuario como a los ganchos de eventos.",
"globalRules": "Se trata de un conjunto global de reglas de permiso y rechazo. Se aplican a todos los usuarios. Puedes definir reglas específicas en la configuración de cada usuario para anular estas.", "globalRules": "Se trata de un conjunto global de reglas de permiso y rechazo. Se aplican a todos los usuarios. Puedes definir reglas específicas en la configuración de cada usuario para anular estas.",
"globalSettings": "Ajustes globales", "globalSettings": "Ajustes globales",
"hideDotfiles": "", "hideDotfiles": "Ocultar archivos empezados por punto",
"insertPath": "Introduce la ruta", "insertPath": "Introduce la ruta",
"insertRegex": "Introducir expresión regular", "insertRegex": "Introducir expresión regular",
"instanceName": "Nombre de la instancia", "instanceName": "Nombre de la instancia",
@@ -209,6 +224,7 @@
"shareDeleted": "¡Recurso compartido eliminado!", "shareDeleted": "¡Recurso compartido eliminado!",
"singleClick": "Utilice un solo clic para abrir archivos y directorios", "singleClick": "Utilice un solo clic para abrir archivos y directorios",
"themes": { "themes": {
"default": "System default",
"dark": "Oscuro", "dark": "Oscuro",
"light": "Claro", "light": "Claro",
"title": "Tema" "title": "Tema"

266
frontend/src/i18n/fa.json Normal file
View File

@@ -0,0 +1,266 @@
{
"buttons": {
"cancel": "لغو",
"clear": "پاک کردن",
"close": "بستن",
"continue": "ادامه",
"copy": "کپی",
"copyFile": "کپی فایل",
"copyToClipboard": "کپی به حافظه",
"copyDownloadLinkToClipboard": "کپی آدرس به حافظه",
"create": "ایجاد",
"delete": "حذف",
"download": "دانلود",
"file": "فایل",
"folder": "پوشه",
"fullScreen": "تمام صفحه ",
"hideDotfiles": "مخفی کردن دات فایلها",
"info": "اطلاعات",
"more": "بیشتر",
"move": "انتقال",
"moveFile": "انتقال فایل",
"new": "جدید",
"next": "بعدی",
"ok": "تایید",
"permalink": "دریافت لینک دائمی",
"previous": "قبلی",
"preview": "نمایش",
"publish": "انتشار",
"rename": "تغییر نام",
"replace": "جایگزین",
"reportIssue": "گزارش مشکل",
"save": "ذخیره",
"schedule": "زمان بندی",
"search": "جستجو",
"select": "انتخاب",
"selectMultiple": "انتخاب چندتایی",
"share": "اشتراک گذاری",
"shell": "تغییر پوسته",
"submit": "ثبت",
"switchView": "تغییر نمایش",
"toggleSidebar": "تغییر نوارکناری",
"update": "به روز سانی",
"upload": "آپلود",
"openFile": "باز کردن فایل",
"discardChanges": "لغو کردن"
},
"download": {
"downloadFile": "دانلود فایل",
"downloadFolder": "دانلود پوشه",
"downloadSelected": "دانلود انتخاب شده ها"
},
"upload": {
"abortUpload": "آیا مطمئن هستید که میخواهید لغو کنید؟"
},
"errors": {
"forbidden": "شما مجوز دسترسی به این را ندارید.",
"internal": "اشتباهی اتفاق افتاده است",
"notFound": "این محل قابل دسترسی نیست",
"connection": "سرور قابل دسترسی نیست"
},
"files": {
"body": "بدنه",
"closePreview": "بستن نمایش",
"files": "فایل ها",
"folders": "پوشه ها",
"home": "صفحه اصلی",
"lastModified": "آخرین ویرایش",
"loading": "در حال بارگذاری...",
"lonely": "It feels lonely here...",
"metadata": "فراداده",
"multipleSelectionEnabled": "فعال بودن چند گزینه ای",
"name": "نام",
"size": "اندازه",
"sortByLastModified": "مرتب سازی آخرین ویرایش",
"sortByName": "مرتب سازی نام",
"sortBySize": "مرتب سازی اندازه",
"noPreview": "این فایل قابل نمایش نیست"
},
"help": {
"click": "انتخاب فایل یا پوشه",
"ctrl": {
"click": "انتخاب چند فایل یا پوشه",
"f": "باز کردن جستجو",
"s": "ذخیره یک فایل یا دانلود پوشه جاری"
},
"del": "حذف گزینه انتخابی ",
"doubleClick": "باز کردن فایل یا پوشه",
"esc": "لغو انتخاب و/یا بستن پیغام",
"f1": "این اطلاعات",
"f2": "تغییر نام فایل",
"help": "راهنما"
},
"login": {
"createAnAccount": "ایجاد کاربر",
"loginInstead": "کاربر تکراری",
"password": "رمز عبور",
"passwordConfirm": "تایید رمز",
"passwordsDontMatch": "عدم تطابق رمزها",
"signup": "ثبت نام",
"submit": "ورود",
"username": "نام کاربری",
"usernameTaken": "نام کاربری تکراری",
"wrongCredentials": "خطا در اعتبارسنجی"
},
"permanent": "دائمی",
"prompts": {
"copy": "کپی",
"copyMessage": "انتخاب محل برای کپی فایل به آنجا ",
"currentlyNavigating": "در حال پیمایش",
"deleteMessageMultiple": "آیا مطمئنید که می‌خواهید {count} فایل را حذف کنید؟",
"deleteMessageSingle": "آیا مطمئنید که میخواهید فایل/پوشه را حذف کنید؟",
"deleteMessageShare": "آیا مطمئن هستید که می‌خواهید این اشتراک‌گذاری ({path}) را حذف کنید؟",
"deleteUser": "آیا مطمئنید که میخواهید این کاربر را حذف کنید؟",
"deleteTitle": "حذف فایل ها",
"displayName": "نمایش نام:",
"download": "دانلود فایل ها",
"downloadMessage": "نوع فایلی که میخواهید دانلود کنید را انتخاب کنید ",
"error": "اشتباهی رخ داده",
"fileInfo": "اطلاعات فایل ",
"filesSelected": "{count} فایل انتخاب شد.",
"lastModified": "آخرین ویرایش",
"move": "انتقال",
"moveMessage": "محل جدیدی برای فایل(ها)/پوشه(های) خود انتخاب کنید:",
"newArchetype": "یک پست جدید بر اساس یک آرکتایپ ایجاد کنید. فایل شما در پوشه محتوا ایجاد خواهد شد.",
"newDir": "پوشه جدید",
"newDirMessage": "نام پوشه جدید",
"newFile": "فایل جدید",
"newFileMessage": "نام فایل جدید",
"numberDirs": "تعداد پوشه ها",
"numberFiles": "تعداد فایل ها",
"rename": "تغییر نام",
"renameMessage": "ورود نام جدید برای",
"replace": "جایگزین کردن",
"replaceMessage": "یکی از فایل‌هایی که می‌خواهید آپلود کنید، نام متفاوتی دارد. آیا می‌خواهید از این فایل صرف نظر کنید و به آپلود ادامه دهید یا فایل موجود را جایگزین کنید؟",
"schedule": "زمان بندی",
"scheduleMessage": "تاریخ و زمانی را برای برنامه‌ریزی انتشار این پست انتخاب کنید",
"show": "نمایش",
"size": "اندازه",
"upload": "آپلود",
"uploadFiles": "در حال آپلود {files} فایل‌ها...",
"uploadMessage": "یک گزینه برای آپلود انتخاب کنید.",
"optionalPassword": "رمز عبور اختیاری",
"resolution": "وضوح تصویر",
"discardEditorChanges": "آیا مطمئن هستید که می‌خواهید تغییراتی را که ایجاد کرده‌اید، لغو کنید؟"
},
"search": {
"images": "تصاویر",
"music": "موسیقی",
"pdf": "پی دی اف",
"pressToSearch": "برای جستجو enter را بزنید...",
"search": "جستجو...",
"typeToSearch": "تایپ برای جستجو",
"types": "انواع",
"video": "ویدئو "
},
"settings": {
"admin": "Admin",
"administrator": "Administrator",
"allowCommands": "اجرای دستورات",
"allowEdit": "ویرایش، تغییر نام، و حذف فایل ها و پوشه ها",
"allowNew": "ایجاد فایلها و پوشه های جدید",
"allowPublish": "انتشار پست ها و صفحات جدید",
"allowSignup": "اجاره دادن به کاربران برای ثبت نام",
"avoidChanges": "(خالی بگذارید تا تغییر ایجاد نشود)",
"branding": "برندسازی",
"brandingDirectoryPath": "مسیر پوشه برند",
"brandingHelp": "شما می‌توانید ظاهر و حس نمونه‌ی مرورگر فایل خود را با تغییر نام، جایگزینی لوگو، اضافه کردن سبک‌های سفارشی و حتی غیرفعال کردن لینک‌های خارجی به گیت‌هاب، سفارشی کنید.\nبرای اطلاعات بیشتر در مورد برندسازی سفارشی، لطفاً به {0} مراجعه کنید.",
"changePassword": "تعبیر رمز",
"commandRunner": "اجرا کننده دستورات",
"commandRunnerHelp": "در اینجا می‌توانید دستوراتی را که در رویدادهای نامگذاری شده اجرا می‌شوند، تنظیم کنید. باید در هر خط یکی را بنویسید. متغیرهای محیطی {0} و {1} در دسترس خواهند بود و {0} نسبت به {1} هستند. برای اطلاعات بیشتر در مورد این ویژگی و متغیرهای محیطی موجود، لطفاً {2} را مطالعه کنید.",
"commandsUpdated": "دستورات ویرایش شد!",
"createUserDir": "ایجاد خودکار پوشه برای هر کاربر هنگام اضافه کردن کاربر جدید",
"minimumPasswordLength": "حداقل طول رمز عبور",
"tusUploads": "آپلودهای بخش بخش شده",
"tusUploadsHelp": "مرورگر فایل از آپلود فایل بخش بخش شده پشتیبانی می‌کند و امکان ایجاد آپلودهای فایل کارآمد، قابل اعتماد، قابل از سرگیری و بخش بخش شده را حتی در شبکه‌های غیرقابل اعتماد فراهم می‌کند.",
"tusUploadsChunkSize": "حداکثر اندازه یک درخواست را نشان می‌دهد (برای آپلودهای کوچک‌تر از آپلود مستقیم استفاده می‌شود). می‌توانید یک عدد صحیح ساده که نشان‌دهنده اندازه بایت است یا یک رشته مانند ۱۰ مگابایت، ۱ گیگابایت و غیره وارد کنید.",
"tusUploadsRetryCount": "تعداد تلاش‌های مجدد برای انجام در صورت عدم موفقیت در آپلود یک قطعه داده.",
"userHomeBasePath": "مسیر پایه برای پوشه های کاربر",
"userScopeGenerationPlaceholder": "محدوده به صورت خودکار تولید خواهد شد",
"createUserHomeDirectory": "ایجاد پوشه ناحیه کاربری",
"customStylesheet": "Stylesheet سفارشی",
"defaultUserDescription": "این تنظیمات پیش‌فرض برای کاربران جدید است.",
"disableExternalLinks": "غیرفعال کردن لینک‌های خارجی (به جز مستندات)",
"disableUsedDiskPercentage": "نمودار درصد دیسک استفاده شده را غیرفعال کنید",
"documentation": "مستندسازی",
"examples": "مثال ها",
"executeOnShell": "اجرا روی shell",
"executeOnShellDescription": "به طور پیش‌فرض، مرورگر فایل، دستورات را با فراخوانی مستقیم فایل‌های باینری آنها اجرا می‌کند. اگر می‌خواهید آنها را روی یک پوسته (مانند Bash یا PowerShell) اجرا کنید، می‌توانید آن را در اینجا با آرگومان‌ها و پرچم‌های مورد نیاز تعریف کنید. در صورت تنظیم، دستوری که اجرا می‌کنید به عنوان یک آرگومان پیوست می‌شود. این موضوع هم در مورد دستورات کاربر و هم در مورد هوک ها صدق می‌کند.",
"globalRules": "این یک مجموعه جهانی از قوانین مجاز و غیرمجاز است. آنها برای هر کاربر اعمال می‌شوند. شما می‌توانید قوانین خاصی را در تنظیمات هر کاربر تعریف کنید تا این قوانین را لغو کنید.",
"globalSettings": "تنظیمات سراسری",
"hideDotfiles": "مخفی کردن دات فایل ها",
"insertPath": "وارد کردن مسیر",
"insertRegex": "وارد کردن عبارات باقاعده",
"instanceName": "نام نمونه",
"language": "زبان",
"lockPassword": "جلوگیری از تغییر رمز توسط کاربر",
"newPassword": "رمز جدید شما",
"newPasswordConfirm": "تایید رمز جدید شما",
"newUser": "کاربر جدید ",
"password": " رمز عبور",
"passwordUpdated": "رمز عبور ویرایش شد!",
"path": "مسیر",
"perm": {
"create": "استاد فایل ها و پوشه ها",
"delete": "حذف فایل ها و پوشه ها",
"download": "دانلود",
"execute": "اجرای دستورات",
"modify": "ویرایش فایل ها",
"rename": "تغییر نام یا انتقال فایل ها و پوشه ها",
"share": "به اشتراک گذاری فایل ها"
},
"permissions": "دسترسی ها",
"permissionsHelp": "شما می‌توانید کاربر را به عنوان مدیر تنظیم کنید یا دسترسی‌ها را به صورت جداگانه انتخاب کنید. اگر \"مدیر\" را انتخاب کنید، تمام گزینه‌های دیگر به طور خودکار اعمال می‌شوند. مدیریت کاربران همچنان از اختیارات مدیر است.",
"profileSettings": "تنظیمات ناحیه کاربری",
"ruleExample1": "از دسترسی به هرگونه فایل نقطه‌ای (مانند .git، .gitignore) در هر پوشه جلوگیری می‌کند.",
"ruleExample2": "دسترسی به فایلی به نام Caddyfile را در ریشه دامنه مسدود می‌کند.",
"rules": "قواعد",
"rulesHelp": "در اینجا می‌توانید مجموعه‌ای از قوانین مجاز و غیرمجاز را برای این کاربر خاص تعریف کنید. فایل‌های مسدود شده در لیست‌ها نمایش داده نمی‌شوند و کاربر به آنها دسترسی نخواهد داشت. ما از regex و مسیرهای مربوط به محدوده کاربر پشتیبانی می‌کنیم.",
"scope": "محدوده",
"setDateFormat": "تنظیم قالب دقیق تاریخ",
"settingsUpdated": "تنظیمات به روز شد!",
"shareDuration": "زمان به اشتراک گذاری",
"shareManagement": "مدیریت به اشتراک گذاری",
"shareDeleted": "به اشتراک گذاری حذف شد!",
"singleClick": "استفاده از یک کلیک برای باز کردن فایل ها و پوشه ها",
"themes": {
"default": "تنظیمات پیش فرض سیستم",
"dark": "تاریک ",
"light": "روشن",
"title": "تم یا زمینه"
},
"user": "کاربر",
"userCommands": "دستورات",
"userCommandsHelp": "فهرستی از دستورات موجود برای این کاربر که با فاصله از هم جدا شده‌اند. مثال:",
"userCreated": "کاربر ایجاد شد",
"userDefaults": "تنظیمات پیش فرض کاربر",
"userDeleted": "کاربر حذف شد",
"userManagement": "مدیریت کاربران",
"userUpdated": "کاربر به روز شد!",
"username": "نام کاربری",
"users": "کاربران"
},
"sidebar": {
"help": "راهنما",
"hugoNew": "Hugo New",
"login": "ورود",
"logout": "خروج از حساب",
"myFiles": "فایل های من",
"newFile": "فایل جدید",
"newFolder": "پوشه جدید",
"preview": "نمایش",
"settings": "تنظیمات",
"signup": "ثبت نام",
"siteSettings": "تنظیمات سایت "
},
"success": {
"linkCopied": "لینک کپی شد!"
},
"time": {
"days": "روزها",
"hours": "ساعت",
"minutes": "دقیقه",
"seconds": "ثانیه",
"unit": "واحد زمان"
}
}

View File

@@ -14,7 +14,7 @@
"file": "Fichier", "file": "Fichier",
"folder": "Dossier", "folder": "Dossier",
"fullScreen": "Plein écran", "fullScreen": "Plein écran",
"hideDotfiles": "Masquer les dotfiles", "hideDotfiles": "Masquer les fichiers cachés",
"info": "Info", "info": "Info",
"more": "Plus", "more": "Plus",
"move": "Déplacer", "move": "Déplacer",
@@ -22,15 +22,16 @@
"new": "Nouveau", "new": "Nouveau",
"next": "Suivant", "next": "Suivant",
"ok": "OK", "ok": "OK",
"permalink": "Obtenir un lien permanent", "permalink": "Obtenir le lien permanent",
"previous": "Précédent", "previous": "Précédent",
"preview": "Prévisualiser",
"publish": "Publier", "publish": "Publier",
"rename": "Renommer", "rename": "Renommer",
"replace": "Remplacer", "replace": "Remplacer",
"reportIssue": "Rapport d'erreur", "reportIssue": "Signaler un problème",
"save": "Enregistrer", "save": "Enregistrer",
"schedule": "Fixer la date", "schedule": "Planifier",
"search": "Chercher", "search": "Rechercher",
"select": "Sélectionner", "select": "Sélectionner",
"selectMultiple": "Sélection multiple", "selectMultiple": "Sélection multiple",
"share": "Partager", "share": "Partager",
@@ -40,18 +41,22 @@
"toggleSidebar": "Afficher/Masquer la barre latérale", "toggleSidebar": "Afficher/Masquer la barre latérale",
"update": "Mettre à jour", "update": "Mettre à jour",
"upload": "Importer", "upload": "Importer",
"openFile": "Ouvrir le fichier" "openFile": "Ouvrir le fichier",
"discardChanges": "Annuler"
}, },
"download": { "download": {
"downloadFile": "Télécharger le fichier", "downloadFile": "Télécharger le fichier",
"downloadFolder": "Télécharger le dossier", "downloadFolder": "Télécharger le dossier",
"downloadSelected": "Télécharger la selection" "downloadSelected": "Télécharger la sélection"
},
"upload": {
"abortUpload": "Êtes-vous sûr de vouloir annuler ?"
}, },
"errors": { "errors": {
"forbidden": "Vous n'avez pas la permission d'accéder à cela.", "forbidden": "Vous n'avez pas la permission d'accéder à cela.",
"internal": "Aïe ! Quelque chose s'est mal passé.", "internal": "Aïe ! Quelque chose s'est mal passé.",
"notFound": "Impossible d'accéder à cet emplacement.", "notFound": "Impossible d'accéder à cet emplacement.",
"connection": "Le serveur n'est pas accessible." "connection": "Le serveur est injoignable."
}, },
"files": { "files": {
"body": "Corps", "body": "Corps",
@@ -61,15 +66,15 @@
"home": "Accueil", "home": "Accueil",
"lastModified": "Dernière modification", "lastModified": "Dernière modification",
"loading": "Chargement...", "loading": "Chargement...",
"lonely": "Il semble qu'il n'y ait rien par ici...", "lonely": "C'est un peu désert ici...",
"metadata": "Metadonnées", "metadata": "Métadonnées",
"multipleSelectionEnabled": "Sélection multiple activée", "multipleSelectionEnabled": "Sélection multiple activée",
"name": "Nom", "name": "Nom",
"size": "Taille", "size": "Taille",
"sortByLastModified": "Trier par date de dernière modification", "sortByLastModified": "Trier par date de modification",
"sortByName": "Trier par nom", "sortByName": "Trier par nom",
"sortBySize": "Trier par taille", "sortBySize": "Trier par taille",
"noPreview": "Il n'y a pas de prévisualisation pour ce fichier." "noPreview": "L'aperçu n'est pas disponible pour ce fichier."
}, },
"help": { "help": {
"click": "Sélectionner un élément", "click": "Sélectionner un élément",
@@ -105,6 +110,7 @@
"deleteMessageMultiple": "Êtes-vous sûr de vouloir supprimer ces {count} élément(s) ?", "deleteMessageMultiple": "Êtes-vous sûr de vouloir supprimer ces {count} élément(s) ?",
"deleteMessageSingle": "Êtes-vous sûr de vouloir supprimer cet élément ?", "deleteMessageSingle": "Êtes-vous sûr de vouloir supprimer cet élément ?",
"deleteMessageShare": "Êtes-vous sûr de vouloir supprimer ce partage ({path}) ?", "deleteMessageShare": "Êtes-vous sûr de vouloir supprimer ce partage ({path}) ?",
"deleteUser": "Êtes-vous sûr de vouloir supprimer cet utilisateur ?",
"deleteTitle": "Supprimer", "deleteTitle": "Supprimer",
"displayName": "Nom :", "displayName": "Nom :",
"download": "Télécharger", "download": "Télécharger",
@@ -125,31 +131,33 @@
"rename": "Renommer", "rename": "Renommer",
"renameMessage": "Nouveau nom pour", "renameMessage": "Nouveau nom pour",
"replace": "Remplacer", "replace": "Remplacer",
"replaceMessage": "Un des fichiers que vous êtes en train d'importer a le même nom qu'un autre déjà présent. Voulez-vous remplacer le fichier actuel par le nouveau ?\n", "replaceMessage": "L'un des fichiers que vous êtes en train d'importer a le même nom qu'un autre déjà présent. Voulez-vous remplacer le fichier actuel par le nouveau ?\n",
"schedule": "Fixer la date", "schedule": "Planifier",
"scheduleMessage": "Choisissez une date pour planifier la publication de ce post", "scheduleMessage": "Choisissez une date pour planifier la publication de ce post",
"show": "Montrer", "show": "Montrer",
"size": "Taille", "size": "Taille",
"upload": "Importer", "upload": "Importer",
"uploadFiles": "Importation de {files} fichiers...", "uploadFiles": "Importation de {files} fichiers...",
"uploadMessage": "Séléctionnez une option d'import.", "uploadMessage": "Sélectionnez une option d'import.",
"optionalPassword": "Mot de passe optionnel" "optionalPassword": "Mot de passe optionnel",
"resolution": "Résolution",
"discardEditorChanges": "Êtes-vous sûr de vouloir annuler les modifications apportées ?"
}, },
"search": { "search": {
"images": "Images", "images": "Images",
"music": "Musique", "music": "Musique",
"pdf": "PDF", "pdf": "PDF",
"pressToSearch": "Appuyez du entrée pour chercher...", "pressToSearch": "Appuyez sur Entrée pour rechercher...",
"search": "Recherche en cours...", "search": "Recherche en cours...",
"typeToSearch": "Écrivez pour chercher...", "typeToSearch": "Écrivez pour rechercher...",
"types": "Types", "types": "Types",
"video": "Video" "video": "Vidéo"
}, },
"settings": { "settings": {
"admin": "Admin", "admin": "Admin",
"administrator": "Administrateur", "administrator": "Administrateur",
"allowCommands": "Exécuter des commandes", "allowCommands": "Exécuter des commandes",
"allowEdit": "Editer, renommer et supprimer des fichiers ou des dossiers", "allowEdit": "Éditer, renommer et supprimer des fichiers ou des dossiers",
"allowNew": "Créer de nouveaux fichiers et dossiers", "allowNew": "Créer de nouveaux fichiers et dossiers",
"allowPublish": "Publier de nouveaux posts et pages", "allowPublish": "Publier de nouveaux posts et pages",
"allowSignup": "Autoriser les utilisateurs à s'inscrire", "allowSignup": "Autoriser les utilisateurs à s'inscrire",
@@ -158,32 +166,40 @@
"brandingDirectoryPath": "Chemin du dossier d'image de marque", "brandingDirectoryPath": "Chemin du dossier d'image de marque",
"brandingHelp": "Vous pouvez personnaliser l'apparence de votre instance de File Browser en changeant son nom, en remplaçant le logo, en ajoutant des styles personnalisés et même en désactivant les liens externes vers GitHub.\nPour plus d'informations sur la personnalisation de l'image de marque, veuillez consulter la {0}.", "brandingHelp": "Vous pouvez personnaliser l'apparence de votre instance de File Browser en changeant son nom, en remplaçant le logo, en ajoutant des styles personnalisés et même en désactivant les liens externes vers GitHub.\nPour plus d'informations sur la personnalisation de l'image de marque, veuillez consulter la {0}.",
"changePassword": "Modifier le mot de passe", "changePassword": "Modifier le mot de passe",
"commandRunner": "Command runner", "commandRunner": "Exécuteur de commandes",
"commandRunnerHelp": "Ici, vous pouvez définir les commandes qui sont exécutées pour les événements nommés précédemments. Vous devez en écrire une par ligne. Les variables d'environnement {0} et {1} seront disponibles, {0} étant relatif à {1}. Pour plus d'informations sur cette fonctionnalité et les variables d'environnement disponibles, veuillez lire la {2}.", "commandRunnerHelp": "Ici, vous pouvez définir les commandes qui seront exécutées lors des événements nommés précédemments. Vous devez en écrire une par ligne. Les variables d'environnement {0} et {1} seront disponibles, {0} étant relatif à {1}. Pour plus d'informations sur cette fonctionnalité et les variables d'environnement disponibles, veuillez lire la {2}.",
"commandsUpdated": "Commandes mises à jour !", "commandsUpdated": "Commandes mises à jour !",
"createUserDir": "Créer automatiquement un dossier pour l'utilisateur", "createUserDir": "Créer automatiquement un dossier pour l'utilisateur",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Uploads segmentés",
"tusUploadsHelp": "File Browser prend en charge les uploads segmentés afin de permettre une gestion efficace, fiable et reprenable sur des réseaux instables.",
"tusUploadsChunkSize": "Taille maximale autorisée par segment (les uploads directs seront utilisés pour les fichiers plus petits). Vous pouvez entrer un entier en octets ou une chaîne telle que 10MB, 1GB, etc.",
"tusUploadsRetryCount": "Nombre de tentatives en cas d'échec d'un segment.",
"userHomeBasePath": "Chemin de base pour les répertoires personnels des utilisateurs",
"userScopeGenerationPlaceholder": "Le périmètre sera généré automatiquement",
"createUserHomeDirectory": "Créer le répertoire personnel de l'utilisateur",
"customStylesheet": "Feuille de style personnalisée", "customStylesheet": "Feuille de style personnalisée",
"defaultUserDescription": "Paramètres par défaut pour les nouveaux utilisateurs.", "defaultUserDescription": "Paramètres par défaut pour les nouveaux utilisateurs.",
"disableExternalLinks": "Désactiver les liens externes (sauf la documentation)", "disableExternalLinks": "Désactiver les liens externes (sauf la documentation)",
"disableUsedDiskPercentage": "Disable used disk percentage graph", "disableUsedDiskPercentage": "Désactiver le graphique de pourcentage d'utilisation du disque",
"documentation": "documentation", "documentation": "documentation",
"examples": "Exemples", "examples": "Exemples",
"executeOnShell": "Exécuter dans le shell", "executeOnShell": "Exécuter dans le shell",
"executeOnShellDescription": "Par défaut, File Browser exécute les commandes en appelant directement leurs binaires. Si vous voulez les exécuter sur un shell à la place (comme Bash ou PowerShell), vous pouvez le définir ici avec les arguments et les drapeaux requis. S'il est défini, la commande que vous exécutez sera ajoutée en tant qu'argument. Cela s'applique à la fois aux commandes utilisateur et aux crochets d'événements.", "executeOnShellDescription": "Par défaut, File Browser exécute les commandes en appelant directement leurs binaires. Si vous voulez les exécuter sur un shell à la place (comme Bash ou PowerShell), vous pouvez le définir ici avec les arguments et les drapeaux requis. S'il est défini, la commande que vous exécutez sera ajoutée en tant qu'argument. Cela s'applique à la fois aux commandes utilisateur et aux crochets d'événements.",
"globalRules": "Il s'agit d'un ensemble global de règles d'autorisation et d'interdiction. Elles s'appliquent à tous les utilisateurs. Vous pouvez définir des règles spécifiques sur les paramètres de chaque utilisateur pour remplacer celles-ci.", "globalRules": "Il s'agit d'un ensemble global de règles d'autorisation et d'interdiction. Elles s'appliquent à tous les utilisateurs. Vous pouvez définir des règles spécifiques sur les paramètres de chaque utilisateur pour remplacer celles-ci.",
"globalSettings": "Paramètres généraux", "globalSettings": "Paramètres globaux",
"hideDotfiles": "Cacher les fichiers de configuration utilisateur (dotfiles)", "hideDotfiles": "Cacher les fichiers de configuration utilisateur (dotfiles)",
"insertPath": "Insérez le chemin", "insertPath": "Insérer le chemin",
"insertRegex": "Insérez l'expression régulière", "insertRegex": "Insérer une expression régulière",
"instanceName": "Nom de l'instance", "instanceName": "Nom de l'instance",
"language": "Langue", "language": "Langue",
"lockPassword": "Empêcher l'utilisateur de changer son mot de passe", "lockPassword": "Empêcher l'utilisateur de changer son mot de passe",
"newPassword": "Votre nouveau mot de passe", "newPassword": "Votre nouveau mot de passe",
"newPasswordConfirm": "Confirmation du nouveau mot de passe", "newPasswordConfirm": "Confirmation du nouveau mot de passe",
"newUser": "Nouvel Utilisateur", "newUser": "Nouvel utilisateur",
"password": "Mot de passe", "password": "Mot de passe",
"passwordUpdated": "Mot de passe mis à jour !", "passwordUpdated": "Mot de passe mis à jour !",
"path": "", "path": "Chemin",
"perm": { "perm": {
"create": "Créer des fichiers et des dossiers", "create": "Créer des fichiers et des dossiers",
"delete": "Supprimer des fichiers et des dossiers", "delete": "Supprimer des fichiers et des dossiers",
@@ -208,15 +224,16 @@
"shareDeleted": "Partage supprimé !", "shareDeleted": "Partage supprimé !",
"singleClick": "Utiliser un simple clic pour ouvrir les fichiers et les dossiers", "singleClick": "Utiliser un simple clic pour ouvrir les fichiers et les dossiers",
"themes": { "themes": {
"default": "System default",
"dark": "Sombre", "dark": "Sombre",
"light": "Lumineux", "light": "Clair",
"title": "Thème" "title": "Thème"
}, },
"user": "Utilisateur", "user": "Utilisateur",
"userCommands": "Commandes", "userCommands": "Commandes",
"userCommandsHelp": "Une liste séparée par des espaces des commandes permises pour l'utilisateur. Exemple :", "userCommandsHelp": "Une liste séparée par des espaces des commandes permises pour l'utilisateur. Exemple :\n",
"userCreated": "Utilisateur créé !", "userCreated": "Utilisateur créé !",
"userDefaults": "User default settings", "userDefaults": "Paramètres par défaut de l'utilisateur",
"userDeleted": "Utilisateur supprimé !", "userDeleted": "Utilisateur supprimé !",
"userManagement": "Gestion des utilisateurs", "userManagement": "Gestion des utilisateurs",
"userUpdated": "Utilisateur mis à jour !", "userUpdated": "Utilisateur mis à jour !",
@@ -237,7 +254,7 @@
"siteSettings": "Paramètres du site" "siteSettings": "Paramètres du site"
}, },
"success": { "success": {
"linkCopied": "Lien copié!" "linkCopied": "Lien copié !"
}, },
"time": { "time": {
"days": "Jours", "days": "Jours",

View File

@@ -3,6 +3,7 @@
"cancel": "ביטול", "cancel": "ביטול",
"clear": "נקה", "clear": "נקה",
"close": "סגירה", "close": "סגירה",
"continue": "המשך",
"copy": "העתקה", "copy": "העתקה",
"copyFile": "העתק קובץ", "copyFile": "העתק קובץ",
"copyToClipboard": "העתק ללוח", "copyToClipboard": "העתק ללוח",
@@ -12,6 +13,7 @@
"download": "הורדה", "download": "הורדה",
"file": "קובץ", "file": "קובץ",
"folder": "תיקייה", "folder": "תיקייה",
"fullScreen": "Toggle full screen",
"hideDotfiles": "הסתר קבצים/תיקיות ששמם מתחיל בנקודה", "hideDotfiles": "הסתר קבצים/תיקיות ששמם מתחיל בנקודה",
"info": "מידע", "info": "מידע",
"more": "עוד", "more": "עוד",
@@ -22,6 +24,7 @@
"ok": "אישור", "ok": "אישור",
"permalink": "יצירת קישור קבוע", "permalink": "יצירת קישור קבוע",
"previous": "הקודם", "previous": "הקודם",
"preview": "Preview",
"publish": "פרסום", "publish": "פרסום",
"rename": "שינוי שם", "rename": "שינוי שם",
"replace": "החלפה", "replace": "החלפה",
@@ -39,7 +42,6 @@
"update": "עדכון", "update": "עדכון",
"upload": "העלאה", "upload": "העלאה",
"openFile": "פתח קובץ", "openFile": "פתח קובץ",
"continue": "המשך",
"discardChanges": "זריקת השינויים" "discardChanges": "זריקת השינויים"
}, },
"download": { "download": {
@@ -58,7 +60,6 @@
}, },
"files": { "files": {
"body": "גוף", "body": "גוף",
"clear": "ניקוי",
"closePreview": "סגירת תצוגה מקדימה", "closePreview": "סגירת תצוגה מקדימה",
"files": "קבצים", "files": "קבצים",
"folders": "תיקיות", "folders": "תיקיות",
@@ -109,6 +110,7 @@
"deleteMessageMultiple": "האם אתה בטוח שברצונך למחוק {count} קבצים?", "deleteMessageMultiple": "האם אתה בטוח שברצונך למחוק {count} קבצים?",
"deleteMessageSingle": "האם אתה בטוח שברצונך למחוק את הקובץ/התיקייה?", "deleteMessageSingle": "האם אתה בטוח שברצונך למחוק את הקובץ/התיקייה?",
"deleteMessageShare": "האם אתה בטוח שברצונך למחוק את השיתוף הזה ({path})?", "deleteMessageShare": "האם אתה בטוח שברצונך למחוק את השיתוף הזה ({path})?",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "מחיקת קבצים", "deleteTitle": "מחיקת קבצים",
"displayName": "שם:", "displayName": "שם:",
"download": "הורדת קבצים", "download": "הורדת קבצים",
@@ -138,6 +140,7 @@
"uploadFiles": "מעלה {files} קבצים...", "uploadFiles": "מעלה {files} קבצים...",
"uploadMessage": "בחר אפשרות העלאה.", "uploadMessage": "בחר אפשרות העלאה.",
"optionalPassword": "סיסמא אופציונלית", "optionalPassword": "סיסמא אופציונלית",
"resolution": "Resolution",
"discardEditorChanges": "האם אתה בטוח שברצונך לבטל את השינויים שביצעת?" "discardEditorChanges": "האם אתה בטוח שברצונך לבטל את השינויים שביצעת?"
}, },
"search": { "search": {
@@ -167,6 +170,11 @@
"commandRunnerHelp": "אתה יכול להגדיר פקודות שיבוצעו באירועים שונים. עליך לכתוב אחד בכל שורה. משתני הסביבה {0} ו-{1} יהיו זמינים, בהיותם {0} ביחס ל-{1}. למידע נוסף על תכונה זו ועל משתני הסביבה הזמינים, עיין ב {2}.", "commandRunnerHelp": "אתה יכול להגדיר פקודות שיבוצעו באירועים שונים. עליך לכתוב אחד בכל שורה. משתני הסביבה {0} ו-{1} יהיו זמינים, בהיותם {0} ביחס ל-{1}. למידע נוסף על תכונה זו ועל משתני הסביבה הזמינים, עיין ב {2}.",
"commandsUpdated": "הפקודות עודכנו!", "commandsUpdated": "הפקודות עודכנו!",
"createUserDir": "צור אוטומטית תיקיית בית בעת הוספת משתמש חדש", "createUserDir": "צור אוטומטית תיקיית בית בעת הוספת משתמש חדש",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Chunked Uploads",
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
"userHomeBasePath": "נתיב ראשי לתיקיות הבית של משתמשים", "userHomeBasePath": "נתיב ראשי לתיקיות הבית של משתמשים",
"userScopeGenerationPlaceholder": "ההיקף יווצר אוטומטית", "userScopeGenerationPlaceholder": "ההיקף יווצר אוטומטית",
"createUserHomeDirectory": "צור תיקיית בית למשתמש", "createUserHomeDirectory": "צור תיקיית בית למשתמש",
@@ -216,6 +224,7 @@
"shareDeleted": "השיתוף נמחק!", "shareDeleted": "השיתוף נמחק!",
"singleClick": "השתמש בלחיצה בודדת כדי לפתוח קובץ/תיקייה", "singleClick": "השתמש בלחיצה בודדת כדי לפתוח קובץ/תיקייה",
"themes": { "themes": {
"default": "System default",
"dark": "כהה", "dark": "כהה",
"light": "בהיר", "light": "בהיר",
"title": "ערכת נושא" "title": "ערכת נושא"

View File

@@ -3,14 +3,17 @@
"cancel": "Mégse", "cancel": "Mégse",
"clear": "Törlése", "clear": "Törlése",
"close": "Bezárás", "close": "Bezárás",
"continue": "Continue",
"copy": "Másolás", "copy": "Másolás",
"copyFile": "Fájl másolása", "copyFile": "Fájl másolása",
"copyToClipboard": "Másolás vágólapra", "copyToClipboard": "Másolás vágólapra",
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
"create": "Létrehozás", "create": "Létrehozás",
"delete": "Törlése", "delete": "Törlése",
"download": "Letöltés", "download": "Letöltés",
"file": "Fájl", "file": "Fájl",
"folder": "Mappa", "folder": "Mappa",
"fullScreen": "Toggle full screen",
"hideDotfiles": "Rejtett fájlok elrejtése", "hideDotfiles": "Rejtett fájlok elrejtése",
"info": "Infó", "info": "Infó",
"more": "További", "more": "További",
@@ -21,6 +24,7 @@
"ok": "OK", "ok": "OK",
"permalink": "Állandó link lekérése", "permalink": "Állandó link lekérése",
"previous": "Előző", "previous": "Előző",
"preview": "Preview",
"publish": "Publikálása", "publish": "Publikálása",
"rename": "Átnevezés", "rename": "Átnevezés",
"replace": "Csere", "replace": "Csere",
@@ -37,13 +41,17 @@
"toggleSidebar": "Oldalsáv átváltása", "toggleSidebar": "Oldalsáv átváltása",
"update": "Frissítés", "update": "Frissítés",
"upload": "Feltöltés", "upload": "Feltöltés",
"openFile": "Fájl megnyitása" "openFile": "Fájl megnyitása",
"discardChanges": "Discard"
}, },
"download": { "download": {
"downloadFile": "Fájl letöltése", "downloadFile": "Fájl letöltése",
"downloadFolder": "Mappa letöltése", "downloadFolder": "Mappa letöltése",
"downloadSelected": "Kijelölés letöltése" "downloadSelected": "Kijelölés letöltése"
}, },
"upload": {
"abortUpload": "Are you sure you wish to abort?"
},
"errors": { "errors": {
"forbidden": "Nincs jogosultsága a hozzáféréshez.", "forbidden": "Nincs jogosultsága a hozzáféréshez.",
"internal": "Valami nagyon elromlott.", "internal": "Valami nagyon elromlott.",
@@ -102,6 +110,7 @@
"deleteMessageMultiple": "Biztosan törölni szeretne {count} fájlt?", "deleteMessageMultiple": "Biztosan törölni szeretne {count} fájlt?",
"deleteMessageSingle": "Biztosan törölni szeretné ezt a fájl vagy mappát?", "deleteMessageSingle": "Biztosan törölni szeretné ezt a fájl vagy mappát?",
"deleteMessageShare": "Biztosan törölni szeretné ezt a megosztást ({path})?", "deleteMessageShare": "Biztosan törölni szeretné ezt a megosztást ({path})?",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "Fájlok törlése", "deleteTitle": "Fájlok törlése",
"displayName": "Megjelenített név:", "displayName": "Megjelenített név:",
"download": "Fájlok letöltése", "download": "Fájlok letöltése",
@@ -130,7 +139,9 @@
"upload": "Feltöltés", "upload": "Feltöltés",
"uploadFiles": "{files} fájl feltöltése…", "uploadFiles": "{files} fájl feltöltése…",
"uploadMessage": "Válasszon egy feltöltési módot.", "uploadMessage": "Válasszon egy feltöltési módot.",
"optionalPassword": "Választható jelszó" "optionalPassword": "Választható jelszó",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
}, },
"search": { "search": {
"images": "Képek", "images": "Képek",
@@ -159,12 +170,18 @@
"commandRunnerHelp": "Beállíthatja azokat a parancsokat, amelyek a megnevezett események során végrehajtásra kerülnek. Soronként egyet kell megadni. A {0} és a {1} környezeti változók lesznek elérhetőek, ahol a {0} relatív a {1}-hez. A funkcióról és a rendelkezésre álló környezeti változókról további információ: {2}.", "commandRunnerHelp": "Beállíthatja azokat a parancsokat, amelyek a megnevezett események során végrehajtásra kerülnek. Soronként egyet kell megadni. A {0} és a {1} környezeti változók lesznek elérhetőek, ahol a {0} relatív a {1}-hez. A funkcióról és a rendelkezésre álló környezeti változókról további információ: {2}.",
"commandsUpdated": "Parancsok frissítve!", "commandsUpdated": "Parancsok frissítve!",
"createUserDir": "Felhasználók saját mappáinak automatikus létrehozása új felhasználók hozzáadásakor", "createUserDir": "Felhasználók saját mappáinak automatikus létrehozása új felhasználók hozzáadásakor",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Chunked Uploads",
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
"userHomeBasePath": "Alap elérési útvonal a felhasználók saját mappáihoz", "userHomeBasePath": "Alap elérési útvonal a felhasználók saját mappáihoz",
"userScopeGenerationPlaceholder": "A környezet automatikus lesz létrehozva", "userScopeGenerationPlaceholder": "A környezet automatikus lesz létrehozva",
"createUserHomeDirectory": "Felhasználói saját mappák létrehozása", "createUserHomeDirectory": "Felhasználói saját mappák létrehozása",
"customStylesheet": "Egyéni stíluslap", "customStylesheet": "Egyéni stíluslap",
"defaultUserDescription": "Ezek az alapértelmezett beállítások az új felhasználók számára.", "defaultUserDescription": "Ezek az alapértelmezett beállítások az új felhasználók számára.",
"disableExternalLinks": "Külső linkek letiltása (kivéve a dokumentáció)", "disableExternalLinks": "Külső linkek letiltása (kivéve a dokumentáció)",
"disableUsedDiskPercentage": "Disable used disk percentage graph",
"documentation": "dokumentáció", "documentation": "dokumentáció",
"examples": "Példák", "examples": "Példák",
"executeOnShell": "Futtatás parancsértelmezőben", "executeOnShell": "Futtatás parancsértelmezőben",
@@ -207,6 +224,7 @@
"shareDeleted": "Megosztás törölve!", "shareDeleted": "Megosztás törölve!",
"singleClick": "Fájlok és könyvtárak megnyitása egyetlen kattintással", "singleClick": "Fájlok és könyvtárak megnyitása egyetlen kattintással",
"themes": { "themes": {
"default": "System default",
"dark": "Sötét", "dark": "Sötét",
"light": "Világos", "light": "Világos",
"title": "Téma" "title": "Téma"

View File

@@ -23,8 +23,10 @@ import("dayjs/locale/sk");
import("dayjs/locale/sv"); import("dayjs/locale/sv");
import("dayjs/locale/tr"); import("dayjs/locale/tr");
import("dayjs/locale/uk"); import("dayjs/locale/uk");
import("dayjs/locale/vi");
import("dayjs/locale/zh-cn"); import("dayjs/locale/zh-cn");
import("dayjs/locale/zh-tw"); import("dayjs/locale/zh-tw");
import("dayjs/locale/cs");
// All i18n resources specified in the plugin `include` option can be loaded // All i18n resources specified in the plugin `include` option can be loaded
// at once using the import syntax // at once using the import syntax
@@ -103,6 +105,9 @@ export function detectLocale() {
case /^uk\b/.test(locale): case /^uk\b/.test(locale):
locale = "uk"; locale = "uk";
break; break;
case /^vi\b/.test(locale):
locale = "vi";
break;
case /^sv-se\b/.test(locale): case /^sv-se\b/.test(locale):
case /^sv\b/.test(locale): case /^sv\b/.test(locale):
locale = "sv"; locale = "sv";
@@ -142,7 +147,7 @@ export const i18n = createI18n({
export const isRtl = (locale?: string) => { export const isRtl = (locale?: string) => {
// see below // see below
// @ts-ignore // @ts-expect-error incorrect type when legacy
return rtlLanguages.includes(locale || i18n.global.locale.value); return rtlLanguages.includes(locale || i18n.global.locale.value);
}; };
@@ -150,7 +155,7 @@ export function setLocale(locale: string) {
dayjs.locale(locale); dayjs.locale(locale);
// according to doc u only need .value if legacy: false but they lied // according to doc u only need .value if legacy: false but they lied
// https://vue-i18n.intlify.dev/guide/essentials/scope.html#local-scope-1 // https://vue-i18n.intlify.dev/guide/essentials/scope.html#local-scope-1
//@ts-ignore // @ts-expect-error incorrect type when legacy
i18n.global.locale.value = locale; i18n.global.locale.value = locale;
} }

View File

@@ -3,13 +3,18 @@
"cancel": "Hætta við", "cancel": "Hætta við",
"clear": "Hreinsa", "clear": "Hreinsa",
"close": "Loka", "close": "Loka",
"continue": "Continue",
"copy": "Afrita", "copy": "Afrita",
"copyFile": "Afrita skjal", "copyFile": "Afrita skjal",
"copyToClipboard": "Afrita", "copyToClipboard": "Afrita",
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
"create": "Búa til", "create": "Búa til",
"delete": "Eyða", "delete": "Eyða",
"download": "Sækja", "download": "Sækja",
"hideDotfiles": "", "file": "File",
"folder": "Folder",
"fullScreen": "Toggle full screen",
"hideDotfiles": "Hide dotfiles",
"info": "Upplýsingar", "info": "Upplýsingar",
"more": "Meira", "more": "Meira",
"move": "Færa", "move": "Færa",
@@ -19,6 +24,7 @@
"ok": "OK", "ok": "OK",
"permalink": "Sækja fastan hlekk", "permalink": "Sækja fastan hlekk",
"previous": "Fyrri", "previous": "Fyrri",
"preview": "Preview",
"publish": "Gefa út", "publish": "Gefa út",
"rename": "Endurnefna", "rename": "Endurnefna",
"replace": "Skipta út", "replace": "Skipta út",
@@ -30,20 +36,27 @@
"selectMultiple": "Velja mörg", "selectMultiple": "Velja mörg",
"share": "Deila", "share": "Deila",
"shell": "Sýna skipanaglugga", "shell": "Sýna skipanaglugga",
"submit": "Submit",
"switchView": "Skipta um útlit", "switchView": "Skipta um útlit",
"toggleSidebar": "Sýna hliðarstiku", "toggleSidebar": "Sýna hliðarstiku",
"update": "Vista", "update": "Vista",
"upload": "Hlaða upp" "upload": "Hlaða upp",
"openFile": "Open file",
"discardChanges": "Discard"
}, },
"download": { "download": {
"downloadFile": "Sækja skjal", "downloadFile": "Sækja skjal",
"downloadFolder": "Sækja möppu", "downloadFolder": "Sækja möppu",
"downloadSelected": "" "downloadSelected": "Download Selected"
},
"upload": {
"abortUpload": "Are you sure you wish to abort?"
}, },
"errors": { "errors": {
"forbidden": "Þú hefur ekki aðgang að þessari síðu.", "forbidden": "Þú hefur ekki aðgang að þessari síðu.",
"internal": "Eitthvað fór úrskeiðis.", "internal": "Eitthvað fór úrskeiðis.",
"notFound": "Ekki er hægt að opna þessa síðu." "notFound": "Ekki er hægt að opna þessa síðu.",
"connection": "The server can't be reached."
}, },
"files": { "files": {
"body": "Meginmál", "body": "Meginmál",
@@ -60,7 +73,8 @@
"size": "Stærð", "size": "Stærð",
"sortByLastModified": "Flokka eftir Seinast breytt", "sortByLastModified": "Flokka eftir Seinast breytt",
"sortByName": "Flokka eftir nafni", "sortByName": "Flokka eftir nafni",
"sortBySize": "Flokka eftir stærð" "sortBySize": "Flokka eftir stærð",
"noPreview": "Preview is not available for this file."
}, },
"help": { "help": {
"click": "velja skjal eða möppu", "click": "velja skjal eða möppu",
@@ -95,6 +109,8 @@
"currentlyNavigating": "Núverandi staðsetning:", "currentlyNavigating": "Núverandi staðsetning:",
"deleteMessageMultiple": "Ertu viss um að þú viljir eyða {count} skjölum?", "deleteMessageMultiple": "Ertu viss um að þú viljir eyða {count} skjölum?",
"deleteMessageSingle": "Ertu viss um að þú viljir eyða þessu skjali/möppu?", "deleteMessageSingle": "Ertu viss um að þú viljir eyða þessu skjali/möppu?",
"deleteMessageShare": "Are you sure you wish to delete this share({path})?",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "Eyða skjölum", "deleteTitle": "Eyða skjölum",
"displayName": "Nafn: ", "displayName": "Nafn: ",
"download": "Sækja skjöl", "download": "Sækja skjöl",
@@ -120,8 +136,12 @@
"scheduleMessage": "Veldu dagsetningu og tíma fyrir áætlaða útgáfu. ", "scheduleMessage": "Veldu dagsetningu og tíma fyrir áætlaða útgáfu. ",
"show": "Sýna", "show": "Sýna",
"size": "Stærð", "size": "Stærð",
"upload": "", "upload": "Upload",
"uploadMessage": "" "uploadFiles": "Uploading {files} files...",
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
}, },
"search": { "search": {
"images": "Myndir", "images": "Myndir",
@@ -150,6 +170,14 @@
"commandRunnerHelp": "Hér geturðu sett inn skipanir sem eru keyrðar eftir því sem þú tilgreinir. Skrifaðu eina skipun í hverja línu. Umhverfisbreyturnar {0} og {1} verða aðgengilegar ({0} miðast við {1}). Til að lesa meira og sjá lista yfir þær skipanir sem eru í boði, vinsamlegast lestu {2}. ", "commandRunnerHelp": "Hér geturðu sett inn skipanir sem eru keyrðar eftir því sem þú tilgreinir. Skrifaðu eina skipun í hverja línu. Umhverfisbreyturnar {0} og {1} verða aðgengilegar ({0} miðast við {1}). Til að lesa meira og sjá lista yfir þær skipanir sem eru í boði, vinsamlegast lestu {2}. ",
"commandsUpdated": "Skipanastillingar vistaðar!", "commandsUpdated": "Skipanastillingar vistaðar!",
"createUserDir": "Auto create user home dir while adding new user", "createUserDir": "Auto create user home dir while adding new user",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Chunked Uploads",
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
"userHomeBasePath": "Base path for user home directories",
"userScopeGenerationPlaceholder": "The scope will be auto generated",
"createUserHomeDirectory": "Create user home directory",
"customStylesheet": "Custom Stylesheet", "customStylesheet": "Custom Stylesheet",
"defaultUserDescription": "Þetta eru sjálfgefnar stillingar fyrir nýja notendur.", "defaultUserDescription": "Þetta eru sjálfgefnar stillingar fyrir nýja notendur.",
"disableExternalLinks": "Sýna ytri-hlekki (fyrir utan leiðbeiningar)", "disableExternalLinks": "Sýna ytri-hlekki (fyrir utan leiðbeiningar)",
@@ -160,7 +188,7 @@
"executeOnShellDescription": "Sjálfgefnar stillingar File Browser eru að keyra skipanir beint með því að sækja binaries. Ef þú villt keyra skipanir í skel (t.d. í Bash eða PowerShell), þá geturðu skilgreint það hér með nauðsynlegum arguments og flags. Ef þetta er stillt, þá verður skipuninni bætt fyrir aftan sem argument. Þetta gildir bæði um skipanir notenda og event hooks.", "executeOnShellDescription": "Sjálfgefnar stillingar File Browser eru að keyra skipanir beint með því að sækja binaries. Ef þú villt keyra skipanir í skel (t.d. í Bash eða PowerShell), þá geturðu skilgreint það hér með nauðsynlegum arguments og flags. Ef þetta er stillt, þá verður skipuninni bætt fyrir aftan sem argument. Þetta gildir bæði um skipanir notenda og event hooks.",
"globalRules": "Þetta eru sjálfgegnar aðgangsreglur. Þær gilda um alla notendur. Þú getur tilgreint sérstakar reglur í stillingum fyrir hvern notenda til að ógilda þessar reglur. ", "globalRules": "Þetta eru sjálfgegnar aðgangsreglur. Þær gilda um alla notendur. Þú getur tilgreint sérstakar reglur í stillingum fyrir hvern notenda til að ógilda þessar reglur. ",
"globalSettings": "Global stillingar", "globalSettings": "Global stillingar",
"hideDotfiles": "", "hideDotfiles": "Hide dotfiles",
"insertPath": "Settu inn slóð", "insertPath": "Settu inn slóð",
"insertRegex": "Setja inn reglulega segð", "insertRegex": "Setja inn reglulega segð",
"instanceName": "Nafn tilviks", "instanceName": "Nafn tilviks",
@@ -171,7 +199,7 @@
"newUser": "Nýr notandi", "newUser": "Nýr notandi",
"password": "Lykilorð", "password": "Lykilorð",
"passwordUpdated": "Lykilorð vistað!", "passwordUpdated": "Lykilorð vistað!",
"path": "", "path": "Path",
"perm": { "perm": {
"create": "Búa til sköl og möppur", "create": "Búa til sköl og möppur",
"delete": "Eyða skjölum og möppum", "delete": "Eyða skjölum og möppum",
@@ -189,14 +217,17 @@
"rules": "Reglur", "rules": "Reglur",
"rulesHelp": "Hér getur þú skilgreint hvaða reglur gilda um notandann. Skjölin sem hann hefur ekki aðgang að eru óaðgengileg og hann sér þau ekki. Stuðst er við reglulegar segðir og slóðir sem miðast við sýn notandans. ", "rulesHelp": "Hér getur þú skilgreint hvaða reglur gilda um notandann. Skjölin sem hann hefur ekki aðgang að eru óaðgengileg og hann sér þau ekki. Stuðst er við reglulegar segðir og slóðir sem miðast við sýn notandans. ",
"scope": "Sýn notandans", "scope": "Sýn notandans",
"setDateFormat": "Set exact date format",
"settingsUpdated": "Stillingar vistaðar!", "settingsUpdated": "Stillingar vistaðar!",
"shareDuration": "", "shareDuration": "Share Duration",
"shareManagement": "", "shareManagement": "Share Management",
"singleClick": "", "shareDeleted": "Share deleted!",
"singleClick": "Use single clicks to open files and directories",
"themes": { "themes": {
"dark": "", "default": "System default",
"light": "", "dark": "Dark",
"title": "" "light": "Light",
"title": "Theme"
}, },
"user": "Notandi", "user": "Notandi",
"userCommands": "Skipanir", "userCommands": "Skipanir",

View File

@@ -7,9 +7,13 @@
"copy": "Copia", "copy": "Copia",
"copyFile": "Copia file", "copyFile": "Copia file",
"copyToClipboard": "Copia negli appunti", "copyToClipboard": "Copia negli appunti",
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
"create": "Crea", "create": "Crea",
"delete": "Elimina", "delete": "Elimina",
"download": "Scarica", "download": "Scarica",
"file": "File",
"folder": "Folder",
"fullScreen": "Toggle full screen",
"hideDotfiles": "Nascondi dotfile", "hideDotfiles": "Nascondi dotfile",
"info": "Informazioni", "info": "Informazioni",
"more": "Altro", "more": "Altro",
@@ -20,6 +24,7 @@
"ok": "OK", "ok": "OK",
"permalink": "Ottieni link permanente", "permalink": "Ottieni link permanente",
"previous": "Precedente", "previous": "Precedente",
"preview": "Preview",
"publish": "Publica", "publish": "Publica",
"rename": "Rinomina", "rename": "Rinomina",
"replace": "Sostituisci", "replace": "Sostituisci",
@@ -31,20 +36,27 @@
"selectMultiple": "Seleziona molteplici", "selectMultiple": "Seleziona molteplici",
"share": "Condividi", "share": "Condividi",
"shell": "Mostra/nascondi shell", "shell": "Mostra/nascondi shell",
"submit": "Submit",
"switchView": "Cambia vista", "switchView": "Cambia vista",
"toggleSidebar": "Mostra/nascondi la barra laterale", "toggleSidebar": "Mostra/nascondi la barra laterale",
"update": "Aggiorna", "update": "Aggiorna",
"upload": "Carica" "upload": "Carica",
"openFile": "Open file",
"discardChanges": "Discard"
}, },
"download": { "download": {
"downloadFile": "Scarica file", "downloadFile": "Scarica file",
"downloadFolder": "Scarica cartella", "downloadFolder": "Scarica cartella",
"downloadSelected": "Scarica selezionati" "downloadSelected": "Scarica selezionati"
}, },
"upload": {
"abortUpload": "Are you sure you wish to abort?"
},
"errors": { "errors": {
"forbidden": "Non hai i permessi per accedere a questo file.", "forbidden": "Non hai i permessi per accedere a questo file.",
"internal": "Qualcosa è andato veramente male.", "internal": "Qualcosa è andato veramente male.",
"notFound": "Questo percorso non può essere raggiunto." "notFound": "Questo percorso non può essere raggiunto.",
"connection": "The server can't be reached."
}, },
"files": { "files": {
"body": "Contenuto", "body": "Contenuto",
@@ -61,7 +73,8 @@
"size": "Dimensione", "size": "Dimensione",
"sortByLastModified": "Ordina per ultima modifica", "sortByLastModified": "Ordina per ultima modifica",
"sortByName": "Ordina per nome", "sortByName": "Ordina per nome",
"sortBySize": "Ordina per dimensione" "sortBySize": "Ordina per dimensione",
"noPreview": "Preview is not available for this file."
}, },
"help": { "help": {
"click": "seleziona un file o una cartella", "click": "seleziona un file o una cartella",
@@ -96,6 +109,8 @@
"currentlyNavigating": "Attualmente navigando su:", "currentlyNavigating": "Attualmente navigando su:",
"deleteMessageMultiple": "Sei sicuro di voler eliminare {count} file?", "deleteMessageMultiple": "Sei sicuro di voler eliminare {count} file?",
"deleteMessageSingle": "Sei sicuro di voler eliminare questo file/cartella?", "deleteMessageSingle": "Sei sicuro di voler eliminare questo file/cartella?",
"deleteMessageShare": "Are you sure you wish to delete this share({path})?",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "Elimina", "deleteTitle": "Elimina",
"displayName": "Nome visualizzato:", "displayName": "Nome visualizzato:",
"download": "Scarica files", "download": "Scarica files",
@@ -122,7 +137,11 @@
"show": "Mostra", "show": "Mostra",
"size": "Dimensione", "size": "Dimensione",
"upload": "Carica", "upload": "Carica",
"uploadMessage": "Seleziona un'opzione per il caricamento." "uploadFiles": "Uploading {files} files...",
"uploadMessage": "Seleziona un'opzione per il caricamento.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
}, },
"search": { "search": {
"images": "Immagini", "images": "Immagini",
@@ -151,6 +170,14 @@
"commandRunnerHelp": "Qui puoi impostare i comandi da eseguire negli eventi nominati. Ne devi scrivere uno per riga. Le variabili d'ambiente {0} e {1} sono disponibili, essendo {0} relativo a {1}. Per altre informazioni su questa funzionalità e sulle variabili d'ambiente utilizzabili, leggi la {2}.", "commandRunnerHelp": "Qui puoi impostare i comandi da eseguire negli eventi nominati. Ne devi scrivere uno per riga. Le variabili d'ambiente {0} e {1} sono disponibili, essendo {0} relativo a {1}. Per altre informazioni su questa funzionalità e sulle variabili d'ambiente utilizzabili, leggi la {2}.",
"commandsUpdated": "Comandi aggiornati!", "commandsUpdated": "Comandi aggiornati!",
"createUserDir": "Crea automaticamente la home directory dell'utente quando lo aggiungi", "createUserDir": "Crea automaticamente la home directory dell'utente quando lo aggiungi",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Chunked Uploads",
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
"userHomeBasePath": "Base path for user home directories",
"userScopeGenerationPlaceholder": "The scope will be auto generated",
"createUserHomeDirectory": "Create user home directory",
"customStylesheet": "Foglio di stile personalizzato", "customStylesheet": "Foglio di stile personalizzato",
"defaultUserDescription": "Queste sono le impostazioni predefinite per i nuovi utenti.", "defaultUserDescription": "Queste sono le impostazioni predefinite per i nuovi utenti.",
"disableExternalLinks": "Disabilita link esterni (tranne per la documentazione)", "disableExternalLinks": "Disabilita link esterni (tranne per la documentazione)",
@@ -190,11 +217,14 @@
"rules": "Regole", "rules": "Regole",
"rulesHelp": "Qui è possibile definire una serie di regole e permessi per questo specifico utente. I file bloccati non appariranno negli elenchi e non saranno accessibili dagli utenti. all'utente. Sia regex che i percorsi relativi all'ambito di applicazione degli utenti sono supportati.\n", "rulesHelp": "Qui è possibile definire una serie di regole e permessi per questo specifico utente. I file bloccati non appariranno negli elenchi e non saranno accessibili dagli utenti. all'utente. Sia regex che i percorsi relativi all'ambito di applicazione degli utenti sono supportati.\n",
"scope": "Scope", "scope": "Scope",
"setDateFormat": "Set exact date format",
"settingsUpdated": "Impostazioni aggiornate!", "settingsUpdated": "Impostazioni aggiornate!",
"shareDuration": "Durata della condivisione", "shareDuration": "Durata della condivisione",
"shareManagement": "Gestione delle condivisioni", "shareManagement": "Gestione delle condivisioni",
"shareDeleted": "Share deleted!",
"singleClick": "Usa un singolo click per aprire file e cartelle", "singleClick": "Usa un singolo click per aprire file e cartelle",
"themes": { "themes": {
"default": "System default",
"dark": "Scuro", "dark": "Scuro",
"light": "Chiaro", "light": "Chiaro",
"title": "Tema" "title": "Tema"

View File

@@ -3,6 +3,7 @@
"cancel": "キャンセル", "cancel": "キャンセル",
"clear": "クリアー", "clear": "クリアー",
"close": "閉じる", "close": "閉じる",
"continue": "続行",
"copy": "コピー", "copy": "コピー",
"copyFile": "ファイルのコピー", "copyFile": "ファイルのコピー",
"copyToClipboard": "共有リンクをコピー", "copyToClipboard": "共有リンクをコピー",
@@ -12,6 +13,7 @@
"download": "ダウンロード", "download": "ダウンロード",
"file": "ファイル", "file": "ファイル",
"folder": "フォルダー", "folder": "フォルダー",
"fullScreen": "Toggle full screen",
"hideDotfiles": "ドットで始まるファイルを表示しない", "hideDotfiles": "ドットで始まるファイルを表示しない",
"info": "情報", "info": "情報",
"more": "さらに", "more": "さらに",
@@ -22,6 +24,7 @@
"ok": "OK", "ok": "OK",
"permalink": "パーマリンクを取得", "permalink": "パーマリンクを取得",
"previous": "前へ", "previous": "前へ",
"preview": "Preview",
"publish": "公開", "publish": "公開",
"rename": "名前の変更", "rename": "名前の変更",
"replace": "置換する", "replace": "置換する",
@@ -39,7 +42,7 @@
"update": "更新", "update": "更新",
"upload": "アップロード", "upload": "アップロード",
"openFile": "ファイルを開く", "openFile": "ファイルを開く",
"continue": "続行" "discardChanges": "Discard"
}, },
"download": { "download": {
"downloadFile": "ファイルのダウンロード", "downloadFile": "ファイルのダウンロード",
@@ -57,7 +60,6 @@
}, },
"files": { "files": {
"body": "本文", "body": "本文",
"clear": "消去",
"closePreview": "プレビューを閉じる", "closePreview": "プレビューを閉じる",
"files": "ファイル", "files": "ファイル",
"folders": "フォルダー", "folders": "フォルダー",
@@ -108,6 +110,7 @@
"deleteMessageMultiple": "{count} 個のファイルを削除してもよろしいですか?", "deleteMessageMultiple": "{count} 個のファイルを削除してもよろしいですか?",
"deleteMessageSingle": "このファイル/フォルダーを削除してもよろしいですか?", "deleteMessageSingle": "このファイル/フォルダーを削除してもよろしいですか?",
"deleteMessageShare": "共有中のファイル({path})を削除してもよろしいですか?", "deleteMessageShare": "共有中のファイル({path})を削除してもよろしいですか?",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "ファイルの削除", "deleteTitle": "ファイルの削除",
"displayName": "表示名:", "displayName": "表示名:",
"download": "ファイルのダウンロード", "download": "ファイルのダウンロード",
@@ -136,7 +139,9 @@
"upload": "アップロード", "upload": "アップロード",
"uploadFiles": "{files} 個のファイルをアップロードしています…", "uploadFiles": "{files} 個のファイルをアップロードしています…",
"uploadMessage": "アップロードするオプションを選択してください。", "uploadMessage": "アップロードするオプションを選択してください。",
"optionalPassword": "パスワード(オプション)" "optionalPassword": "パスワード(オプション)",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
}, },
"search": { "search": {
"images": "画像", "images": "画像",
@@ -165,6 +170,7 @@
"commandRunnerHelp": "ここでは、指定したイベントの際に実行されるコマンドを設定することができます。1行に1つずつ書く必要があります。環境変数として {0} や {1} が使用可能で、{0} は {1} に関連した変数として扱われます。この機能と使用可能な環境変数の詳細については、{2}をお読みください。", "commandRunnerHelp": "ここでは、指定したイベントの際に実行されるコマンドを設定することができます。1行に1つずつ書く必要があります。環境変数として {0} や {1} が使用可能で、{0} は {1} に関連した変数として扱われます。この機能と使用可能な環境変数の詳細については、{2}をお読みください。",
"commandsUpdated": "コマンドを更新しました!", "commandsUpdated": "コマンドを更新しました!",
"createUserDir": "新規ユーザー追加時にユーザーのホームディレクトリを自動生成する", "createUserDir": "新規ユーザー追加時にユーザーのホームディレクトリを自動生成する",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "チャンクされたファイルアップロード", "tusUploads": "チャンクされたファイルアップロード",
"tusUploadsHelp": "File Browser はチャンクされたファイルアップロードをサポートしており、信頼性の低いネットワーク上でも、効率的で信頼性の高い、再開可能なチャンクされたファイルアップロードを作成することができます。", "tusUploadsHelp": "File Browser はチャンクされたファイルアップロードをサポートしており、信頼性の低いネットワーク上でも、効率的で信頼性の高い、再開可能なチャンクされたファイルアップロードを作成することができます。",
"tusUploadsChunkSize": "1チャンクあたりのリクエストの最大サイズ。バイト数を示す整数か、10MB、1GBなどの文字列を入力できます。", "tusUploadsChunkSize": "1チャンクあたりのリクエストの最大サイズ。バイト数を示す整数か、10MB、1GBなどの文字列を入力できます。",
@@ -218,6 +224,7 @@
"shareDeleted": "ファイルの共有を削除しました!", "shareDeleted": "ファイルの共有を削除しました!",
"singleClick": "ダブルクリックの代わりにクリックでファイルやフォルダーを開く", "singleClick": "ダブルクリックの代わりにクリックでファイルやフォルダーを開く",
"themes": { "themes": {
"default": "System default",
"dark": "ダーク", "dark": "ダーク",
"light": "ライト", "light": "ライト",
"title": "テーマ" "title": "テーマ"

View File

@@ -3,13 +3,18 @@
"cancel": "취소", "cancel": "취소",
"clear": "지우기", "clear": "지우기",
"close": "닫기", "close": "닫기",
"continue": "Continue",
"copy": "복사", "copy": "복사",
"copyFile": "파일 복사", "copyFile": "파일 복사",
"copyToClipboard": "클립보드 복사", "copyToClipboard": "클립보드 복사",
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
"create": "생성", "create": "생성",
"delete": "삭제", "delete": "삭제",
"download": "다운로드", "download": "다운로드",
"hideDotfiles": "", "file": "File",
"folder": "Folder",
"fullScreen": "Toggle full screen",
"hideDotfiles": "숨김파일(dotfile)을 표시 안함",
"info": "정보", "info": "정보",
"more": "더보기", "more": "더보기",
"move": "이동", "move": "이동",
@@ -19,6 +24,7 @@
"ok": "확인", "ok": "확인",
"permalink": "링크 얻기", "permalink": "링크 얻기",
"previous": "이전", "previous": "이전",
"preview": "Preview",
"publish": "게시", "publish": "게시",
"rename": "이름 바꾸기", "rename": "이름 바꾸기",
"replace": "대체", "replace": "대체",
@@ -30,20 +36,27 @@
"selectMultiple": "다중 선택", "selectMultiple": "다중 선택",
"share": "공유", "share": "공유",
"shell": "쉘 전환", "shell": "쉘 전환",
"submit": "Submit",
"switchView": "보기 전환", "switchView": "보기 전환",
"toggleSidebar": "사이드바 전환", "toggleSidebar": "사이드바 전환",
"update": "업데이트", "update": "업데이트",
"upload": "업로드" "upload": "업로드",
"openFile": "Open file",
"discardChanges": "Discard"
}, },
"download": { "download": {
"downloadFile": "파일 다운로드", "downloadFile": "파일 다운로드",
"downloadFolder": "폴더 다운로드", "downloadFolder": "폴더 다운로드",
"downloadSelected": "" "downloadSelected": "선택 항목 다운로드"
},
"upload": {
"abortUpload": "Are you sure you wish to abort?"
}, },
"errors": { "errors": {
"forbidden": "접근 권한이 없습니다.", "forbidden": "접근 권한이 없습니다.",
"internal": "오류가 발생하였습니다.", "internal": "오류가 발생하였습니다.",
"notFound": "해당 경로를 찾을 수 없습니다." "notFound": "해당 경로를 찾을 수 없습니다.",
"connection": "The server can't be reached."
}, },
"files": { "files": {
"body": "본문", "body": "본문",
@@ -60,7 +73,8 @@
"size": "크기", "size": "크기",
"sortByLastModified": "수정시간순 정렬", "sortByLastModified": "수정시간순 정렬",
"sortByName": "이름순", "sortByName": "이름순",
"sortBySize": "크기순" "sortBySize": "크기순",
"noPreview": "Preview is not available for this file."
}, },
"help": { "help": {
"click": "파일이나 디렉토리를 선택해주세요.", "click": "파일이나 디렉토리를 선택해주세요.",
@@ -95,6 +109,8 @@
"currentlyNavigating": "현재 위치:", "currentlyNavigating": "현재 위치:",
"deleteMessageMultiple": "{count} 개의 파일을 삭제하시겠습니까?", "deleteMessageMultiple": "{count} 개의 파일을 삭제하시겠습니까?",
"deleteMessageSingle": "파일 혹은 디렉토리를 삭제하시겠습니까?", "deleteMessageSingle": "파일 혹은 디렉토리를 삭제하시겠습니까?",
"deleteMessageShare": "Are you sure you wish to delete this share({path})?",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "파일 삭제", "deleteTitle": "파일 삭제",
"displayName": "게시 이름:", "displayName": "게시 이름:",
"download": "파일 다운로드", "download": "파일 다운로드",
@@ -120,8 +136,12 @@
"scheduleMessage": "이 글을 공개할 시간을 알려주세요.", "scheduleMessage": "이 글을 공개할 시간을 알려주세요.",
"show": "보기", "show": "보기",
"size": "크기", "size": "크기",
"upload": "", "upload": "업로드",
"uploadMessage": "" "uploadFiles": "Uploading {files} files...",
"uploadMessage": "업로드 옵션을 선택하세요.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
}, },
"search": { "search": {
"images": "이미지", "images": "이미지",
@@ -150,6 +170,14 @@
"commandRunnerHelp": "이벤트에 해당하는 명령을 설정하세요. 줄당 1개의 명령을 적으세요. 환경 변수{0} 와 {1}이 사용가능하며, {0} 은 {1}에 상대 경로 입니다. 자세한 사항은 {2} 를 참조하세요.", "commandRunnerHelp": "이벤트에 해당하는 명령을 설정하세요. 줄당 1개의 명령을 적으세요. 환경 변수{0} 와 {1}이 사용가능하며, {0} 은 {1}에 상대 경로 입니다. 자세한 사항은 {2} 를 참조하세요.",
"commandsUpdated": "명령 수정됨!", "commandsUpdated": "명령 수정됨!",
"createUserDir": "Auto create user home dir while adding new user", "createUserDir": "Auto create user home dir while adding new user",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Chunked Uploads",
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
"userHomeBasePath": "Base path for user home directories",
"userScopeGenerationPlaceholder": "The scope will be auto generated",
"createUserHomeDirectory": "Create user home directory",
"customStylesheet": "커스텀 스타일시트", "customStylesheet": "커스텀 스타일시트",
"defaultUserDescription": "아래 사항은 신규 사용자들에 대한 기본 설정입니다.", "defaultUserDescription": "아래 사항은 신규 사용자들에 대한 기본 설정입니다.",
"disableExternalLinks": "외부 링크 감추기", "disableExternalLinks": "외부 링크 감추기",
@@ -160,7 +188,7 @@
"executeOnShellDescription": "기본적으로 File Browser 는 바이너리를 명령어로 호출하여 실행합니다. 쉘을 통해 실행하기를 원한다면, Bash 또는 PowerShell 에 필요한 인수와 플래그를 설정하세요. 사용자 명령어와 이벤트 훅에 모두 적용됩니다.", "executeOnShellDescription": "기본적으로 File Browser 는 바이너리를 명령어로 호출하여 실행합니다. 쉘을 통해 실행하기를 원한다면, Bash 또는 PowerShell 에 필요한 인수와 플래그를 설정하세요. 사용자 명령어와 이벤트 훅에 모두 적용됩니다.",
"globalRules": "규칙에 대한 전역설정으로 모든 사용자에게 적용됩니다. 지정된 규칙은 사용자 설정을 덮어쓰기 합니다.", "globalRules": "규칙에 대한 전역설정으로 모든 사용자에게 적용됩니다. 지정된 규칙은 사용자 설정을 덮어쓰기 합니다.",
"globalSettings": "전역 설정", "globalSettings": "전역 설정",
"hideDotfiles": "", "hideDotfiles": "숨김파일(dotfile)을 표시하지 않습니다.",
"insertPath": "경로 입력", "insertPath": "경로 입력",
"insertRegex": "정규식 입력", "insertRegex": "정규식 입력",
"instanceName": "인스턴스 이름", "instanceName": "인스턴스 이름",
@@ -171,7 +199,7 @@
"newUser": "새로운 사용자", "newUser": "새로운 사용자",
"password": "비밀번호", "password": "비밀번호",
"passwordUpdated": "비밀번호 수정 완료!", "passwordUpdated": "비밀번호 수정 완료!",
"path": "", "path": "경로",
"perm": { "perm": {
"create": "파일이나 디렉토리 생성하기", "create": "파일이나 디렉토리 생성하기",
"delete": "화일이나 디렉토리 삭제하기", "delete": "화일이나 디렉토리 삭제하기",
@@ -189,14 +217,17 @@
"rules": "룰", "rules": "룰",
"rulesHelp": "사용자별로 규칙을 허용/방지를 지정할 수 있습니다. 방지된 파일은 보이지 않고 사용자들은 접근할 수 없습니다. 사용자의 접근 허용 범위와 관련해 정규표현식(regex)과 경로를 지원합니다.\n", "rulesHelp": "사용자별로 규칙을 허용/방지를 지정할 수 있습니다. 방지된 파일은 보이지 않고 사용자들은 접근할 수 없습니다. 사용자의 접근 허용 범위와 관련해 정규표현식(regex)과 경로를 지원합니다.\n",
"scope": "범위", "scope": "범위",
"setDateFormat": "Set exact date format",
"settingsUpdated": "설정 수정됨!", "settingsUpdated": "설정 수정됨!",
"shareDuration": "", "shareDuration": "공유 기간",
"shareManagement": "", "shareManagement": "공유 내역 관리",
"singleClick": "", "shareDeleted": "Share deleted!",
"singleClick": "한번 클릭으로 파일과 폴더를 열도록 합니다.",
"themes": { "themes": {
"dark": "", "default": "System default",
"light": "", "dark": "다크테마",
"title": "" "light": "라이트테마",
"title": "테마"
}, },
"user": "사용자", "user": "사용자",
"userCommands": "명령어", "userCommands": "명령어",

View File

@@ -3,13 +3,18 @@
"cancel": "Annuleren", "cancel": "Annuleren",
"clear": "Wissen", "clear": "Wissen",
"close": "Sluiten", "close": "Sluiten",
"continue": "Continue",
"copy": "Kopiëren", "copy": "Kopiëren",
"copyFile": "Bestand kopiëren", "copyFile": "Bestand kopiëren",
"copyToClipboard": "Kopiëren naar klembord", "copyToClipboard": "Kopiëren naar klembord",
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
"create": "Aanmaken", "create": "Aanmaken",
"delete": "Verwijderen", "delete": "Verwijderen",
"download": "Downloaden", "download": "Downloaden",
"hideDotfiles": "", "file": "File",
"folder": "Folder",
"fullScreen": "Toggle full screen",
"hideDotfiles": "Hide dotfiles",
"info": "Info", "info": "Info",
"more": "Meer", "more": "Meer",
"move": "Verplaatsen", "move": "Verplaatsen",
@@ -19,6 +24,7 @@
"ok": "OK", "ok": "OK",
"permalink": "Maak permanente link", "permalink": "Maak permanente link",
"previous": "Vorige", "previous": "Vorige",
"preview": "Preview",
"publish": "Publiceren", "publish": "Publiceren",
"rename": "Hernoemen", "rename": "Hernoemen",
"replace": "Vervangen", "replace": "Vervangen",
@@ -30,20 +36,27 @@
"selectMultiple": "Meerdere selecteren", "selectMultiple": "Meerdere selecteren",
"share": "Delen", "share": "Delen",
"shell": "Open shell", "shell": "Open shell",
"submit": "Submit",
"switchView": "Beeld wisselen", "switchView": "Beeld wisselen",
"toggleSidebar": "Zijbalk tonen", "toggleSidebar": "Zijbalk tonen",
"update": "Updaten", "update": "Updaten",
"upload": "Uploaden" "upload": "Uploaden",
"openFile": "Open file",
"discardChanges": "Discard"
}, },
"download": { "download": {
"downloadFile": "Bestand downloaden", "downloadFile": "Bestand downloaden",
"downloadFolder": "Map downloaden", "downloadFolder": "Map downloaden",
"downloadSelected": "" "downloadSelected": "Download Selected"
},
"upload": {
"abortUpload": "Are you sure you wish to abort?"
}, },
"errors": { "errors": {
"forbidden": "U hebt geen rechten om hier toegang toe te krijgen.", "forbidden": "U hebt geen rechten om hier toegang toe te krijgen.",
"internal": "Er ging iets mis.", "internal": "Er ging iets mis.",
"notFound": "Deze locatie kan niet worden bereikt." "notFound": "Deze locatie kan niet worden bereikt.",
"connection": "The server can't be reached."
}, },
"files": { "files": {
"body": "Body", "body": "Body",
@@ -60,7 +73,8 @@
"size": "Grootte", "size": "Grootte",
"sortByLastModified": "Sorteren op laatst bewerkt", "sortByLastModified": "Sorteren op laatst bewerkt",
"sortByName": "Sorteren op naam", "sortByName": "Sorteren op naam",
"sortBySize": "Sorteren op grootte" "sortBySize": "Sorteren op grootte",
"noPreview": "Preview is not available for this file."
}, },
"help": { "help": {
"click": "selecteer bestand of map", "click": "selecteer bestand of map",
@@ -95,6 +109,8 @@
"currentlyNavigating": "Momenteel zoeken op: ", "currentlyNavigating": "Momenteel zoeken op: ",
"deleteMessageMultiple": "Weet u zeker dat u {count} bestand(en) wil verwijderen?", "deleteMessageMultiple": "Weet u zeker dat u {count} bestand(en) wil verwijderen?",
"deleteMessageSingle": "Weet u zeker dat u dit bestand/map wil verwijderen?", "deleteMessageSingle": "Weet u zeker dat u dit bestand/map wil verwijderen?",
"deleteMessageShare": "Are you sure you wish to delete this share({path})?",
"deleteUser": "Are you sure you want to delete this user?",
"deleteTitle": "Bestanden verwijderen", "deleteTitle": "Bestanden verwijderen",
"displayName": "Weergavenaam: ", "displayName": "Weergavenaam: ",
"download": "Bestanden downloaden", "download": "Bestanden downloaden",
@@ -120,8 +136,12 @@
"scheduleMessage": "Kies een datum en tijd om de publicatie van dit bericht in te plannen.", "scheduleMessage": "Kies een datum en tijd om de publicatie van dit bericht in te plannen.",
"show": "Tonen", "show": "Tonen",
"size": "Grootte", "size": "Grootte",
"upload": "", "upload": "Upload",
"uploadMessage": "" "uploadFiles": "Uploading {files} files...",
"uploadMessage": "Select an option to upload.",
"optionalPassword": "Optional password",
"resolution": "Resolution",
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
}, },
"search": { "search": {
"images": "Afbeeldingen", "images": "Afbeeldingen",
@@ -150,6 +170,14 @@
"commandRunnerHelp": "Hier kunt u opdrachten instellen die worden uitgevoerd in de benoemde gebeurtenissen. U moet er één per regel schrijven. De omgevingsvariabelen {0} en {1} zijn beschikbaar, zijnde {0} relatief ten opzichte van {1}. Raadpleeg {2} voor meer informatie over deze functie en de beschikbare omgevingsvariabelen.", "commandRunnerHelp": "Hier kunt u opdrachten instellen die worden uitgevoerd in de benoemde gebeurtenissen. U moet er één per regel schrijven. De omgevingsvariabelen {0} en {1} zijn beschikbaar, zijnde {0} relatief ten opzichte van {1}. Raadpleeg {2} voor meer informatie over deze functie en de beschikbare omgevingsvariabelen.",
"commandsUpdated": "Commando's bijgewerkt!", "commandsUpdated": "Commando's bijgewerkt!",
"createUserDir": "Maak automatisch een thuismap aan wanneer een nieuwe gebruiker wordt aangemaakt", "createUserDir": "Maak automatisch een thuismap aan wanneer een nieuwe gebruiker wordt aangemaakt",
"minimumPasswordLength": "Minimum password length",
"tusUploads": "Chunked Uploads",
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
"userHomeBasePath": "Base path for user home directories",
"userScopeGenerationPlaceholder": "The scope will be auto generated",
"createUserHomeDirectory": "Create user home directory",
"customStylesheet": "Aangepast Stylesheet", "customStylesheet": "Aangepast Stylesheet",
"defaultUserDescription": "Dit zijn de standaardinstellingen voor nieuwe gebruikers.", "defaultUserDescription": "Dit zijn de standaardinstellingen voor nieuwe gebruikers.",
"disableExternalLinks": "Schakel externe links uit (behalve documentatie)", "disableExternalLinks": "Schakel externe links uit (behalve documentatie)",
@@ -160,7 +188,7 @@
"executeOnShellDescription": "File Browser voert de opdrachten standaard uit door hun binaire bestanden rechtstreeks op te roepen. Als u ze in plaats daarvan wilt uitvoeren op een shell (zoals Bash of PowerShell), kunt u dit hier definiëren met de vereiste argumenten en vlaggen. Indien ingesteld, wordt de opdracht die u uitvoert, toegevoegd als een argument. Dit is van toepassing op zowel gebruikersopdrachten als event hooks.", "executeOnShellDescription": "File Browser voert de opdrachten standaard uit door hun binaire bestanden rechtstreeks op te roepen. Als u ze in plaats daarvan wilt uitvoeren op een shell (zoals Bash of PowerShell), kunt u dit hier definiëren met de vereiste argumenten en vlaggen. Indien ingesteld, wordt de opdracht die u uitvoert, toegevoegd als een argument. Dit is van toepassing op zowel gebruikersopdrachten als event hooks.",
"globalRules": "Dit is een algemene reeks toegestane en niet toegestane regels. Ze zijn van toepassing op elke gebruiker. U kunt specifieke regels voor de instellingen van elke gebruiker definiëren om deze te overschrijven.", "globalRules": "Dit is een algemene reeks toegestane en niet toegestane regels. Ze zijn van toepassing op elke gebruiker. U kunt specifieke regels voor de instellingen van elke gebruiker definiëren om deze te overschrijven.",
"globalSettings": "Algemene Instellingen", "globalSettings": "Algemene Instellingen",
"hideDotfiles": "", "hideDotfiles": "Hide dotfiles",
"insertPath": "Voeg een pad toe", "insertPath": "Voeg een pad toe",
"insertRegex": "Regex expressie invoeren", "insertRegex": "Regex expressie invoeren",
"instanceName": "Instantienaam", "instanceName": "Instantienaam",
@@ -171,7 +199,7 @@
"newUser": "Nieuwe gebruiker", "newUser": "Nieuwe gebruiker",
"password": "Wachtwoord", "password": "Wachtwoord",
"passwordUpdated": "Wachtwoord bijgewerkt!", "passwordUpdated": "Wachtwoord bijgewerkt!",
"path": "", "path": "Path",
"perm": { "perm": {
"create": "Bestanden en mappen aanmaken", "create": "Bestanden en mappen aanmaken",
"delete": "Bestanden en mappen verwijderen", "delete": "Bestanden en mappen verwijderen",
@@ -189,14 +217,17 @@
"rules": "Regels", "rules": "Regels",
"rulesHelp": "Hier kunt u een reeks regels voor toestaan en niet toestaan voor deze specifieke gebruiker definiëren. De geblokkeerde bestanden verschijnen niet in de lijsten en zijn niet toegankelijk voor de gebruiker. We ondersteunen regex en paden relatief ten opzichte van het bereik van gebruikers. \n", "rulesHelp": "Hier kunt u een reeks regels voor toestaan en niet toestaan voor deze specifieke gebruiker definiëren. De geblokkeerde bestanden verschijnen niet in de lijsten en zijn niet toegankelijk voor de gebruiker. We ondersteunen regex en paden relatief ten opzichte van het bereik van gebruikers. \n",
"scope": "Scope", "scope": "Scope",
"setDateFormat": "Set exact date format",
"settingsUpdated": "Instellingen bijgewerkt!", "settingsUpdated": "Instellingen bijgewerkt!",
"shareDuration": "", "shareDuration": "Share Duration",
"shareManagement": "", "shareManagement": "Share Management",
"singleClick": "", "shareDeleted": "Share deleted!",
"singleClick": "Use single clicks to open files and directories",
"themes": { "themes": {
"dark": "", "default": "System default",
"light": "", "dark": "Dark",
"title": "" "light": "Light",
"title": "Theme"
}, },
"user": "Gebruiker", "user": "Gebruiker",
"userCommands": "Commando's", "userCommands": "Commando's",

View File

@@ -3,133 +3,153 @@
"cancel": "Anuluj", "cancel": "Anuluj",
"clear": "Wyczyść", "clear": "Wyczyść",
"close": "Zamknij", "close": "Zamknij",
"continue": "Kontynuuj",
"copy": "Kopiuj", "copy": "Kopiuj",
"copyFile": "Kopiuj plik", "copyFile": "Kopiuj plik",
"copyToClipboard": "kopiuj do schowka", "copyToClipboard": "Kopiuj do schowka",
"copyDownloadLinkToClipboard": "Kopiuj link pobierania do schowka",
"create": "Utwórz", "create": "Utwórz",
"delete": "Usuń", "delete": "Usuń",
"download": "Pobierz", "download": "Pobierz",
"hideDotfiles": "", "file": "Plik",
"info": "Informacja", "folder": "Folder",
"more": "Więce", "fullScreen": "Przełącz tryb pełnoekranowy",
"hideDotfiles": "Ukryj pliki poprzedzone kropką",
"info": "Informacje",
"more": "Więcej",
"move": "Przenieś", "move": "Przenieś",
"moveFile": "Przenieś plik", "moveFile": "Przenieś plik",
"new": "Nowy", "new": "Nowy",
"next": "Następny", "next": "Następny",
"ok": "OK", "ok": "OK",
"permalink": "Uzyskaj link bezpośredni (permalink)", "permalink": "Uzyskaj stały link",
"previous": "Poprzedni", "previous": "Poprzedni",
"preview": "Podgląd",
"publish": "Opublikuj", "publish": "Opublikuj",
"rename": "Zmień nazwę", "rename": "Zmień nazwę",
"replace": "Zamień", "replace": "Zamień",
"reportIssue": "Zgłoś problem", "reportIssue": "Zgłoś problem",
"save": "Zapisz", "save": "Zapisz",
"schedule": "Grafik", "schedule": "Harmonogram",
"search": "Szukaj", "search": "Szukaj",
"select": "Wybierz", "select": "Zaznacz",
"selectMultiple": "Zaznacz wiele", "selectMultiple": "Zaznacz wiele",
"share": "Udostępnij", "share": "Udostępnij",
"shell": "Pokaż/ukryj powłokę", "shell": "Przełącz powłokę",
"submit": "Prześlij",
"switchView": "Zmień widok", "switchView": "Zmień widok",
"toggleSidebar": "Pokaż/ukryj panel boczny", "toggleSidebar": "Przełącz pasek boczny",
"update": "Aktualizuj", "update": "Aktualizuj",
"upload": "Wgraj" "upload": "Wyślij",
"openFile": "Otwórz plik",
"discardChanges": "Odrzuć"
}, },
"download": { "download": {
"downloadFile": "Pobierz plik", "downloadFile": "Pobierz plik",
"downloadFolder": "Pobierz folder", "downloadFolder": "Pobierz folder",
"downloadSelected": "Pobierz zaznaczone" "downloadSelected": "Pobierz zaznaczone"
}, },
"upload": {
"abortUpload": "Czy na pewno chcesz przerwać?"
},
"errors": { "errors": {
"forbidden": "Nie posiadasz uprawnień potrzebnych, by uzyskać do tego dostęp.", "forbidden": "Nie masz zezwolenia na dostęp do tego.",
"internal": "Pojawił się poważny problem.", "internal": "Pojawił się poważny problem.",
"notFound": "Ten adres nie jest poprawny." "notFound": "Ta lokalizacja jest nieosiągalna.",
"connection": "Serwer jest nieosiągalny."
}, },
"files": { "files": {
"body": "Body", "body": "Zawartość",
"closePreview": "Zamknij poprzednie", "closePreview": "Zamknij podgląd",
"files": "Pliki", "files": "Pliki",
"folders": "Foldery", "folders": "Foldery",
"home": "Katalog domowy", "home": "Główny",
"lastModified": "Ostatnio modyfikowane", "lastModified": "Ostatnio zmodyfikowano",
"loading": "Ładowanie...", "loading": "Ładowanie...",
"lonely": "Smutno gdy tak pusto...", "lonely": "Smutno, gdy tak pusto...",
"metadata": "Metadane", "metadata": "Metadane",
"multipleSelectionEnabled": "Zaznaczenie wielu włączone", "multipleSelectionEnabled": "Włączono zaznaczenie wielokrotne",
"name": "Nazwa", "name": "Nazwa",
"size": "Rozmiar", "size": "Rozmiar",
"sortByLastModified": "Sortuj wg. daty modyfikacji", "sortByLastModified": "Sortuj wg ostatniej modyfikacji",
"sortByName": "Sortuj wg. nazwy", "sortByName": "Sortuj wg nazwy",
"sortBySize": "Sortuj wg. rozmiaru" "sortBySize": "Sortuj wg rozmiaru",
"noPreview": "Podgląd tego pliku jest niedostępny."
}, },
"help": { "help": {
"click": "wybierz plik lub foler", "click": "zaznacz plik lub folder",
"ctrl": { "ctrl": {
"click": "wybierz wiele plików lub folderów", "click": "zaznacz wiele plików lub folderów",
"f": "otwórz wyszukiwarkę", "f": "otwórz wyszukiwarkę",
"s": "pobierz aktywny plik lub folder" "s": "pobierz aktywny plik lub folder"
}, },
"del": "usuń zaznaczone", "del": "usuń zaznaczone elementy",
"doubleClick": "otwórz plik lub folder", "doubleClick": "otwórz plik lub folder",
"esc": "wyczyść zaznaczenie i/lub zamknij okno z powiadomieniem", "esc": "wyczyść zaznaczenie i/lub zamknij monit",
"f1": "ta informacja", "f1": "te informacje",
"f2": "zmień nazwę pliku", "f2": "zmień nazwę pliku",
"help": "Pomoc" "help": "Pomoc"
}, },
"login": { "login": {
"createAnAccount": "Utwórz konto", "createAnAccount": "Utwórz konto",
"loginInstead": "Takie konto już istnieje", "loginInstead": "Mam już konto",
"password": "Hasło", "password": "Hasło",
"passwordConfirm": "Potwierdzenie hasła", "passwordConfirm": "Potwierdzenie hasła",
"passwordsDontMatch": "Hasła różnią się", "passwordsDontMatch": "Hasła nie pasują do siebie",
"signup": "Rejestracja", "signup": "Rejestracja",
"submit": "Logowanie", "submit": "Zaloguj",
"username": "Nazwa użytkownika", "username": "Nazwa użytkownika",
"usernameTaken": "Nazwa użytkownika j zajęta", "usernameTaken": "Ta nazwa użytkownika jest zajęta",
"wrongCredentials": "Błędne dane logowania" "wrongCredentials": "Błędne dane logowania"
}, },
"permanent": "Permanentny", "permanent": "Permanentny",
"prompts": { "prompts": {
"copy": "Kopiuj", "copy": "Kopiuj",
"copyMessage": "Wybierz lokalizację do której mają być skopiowane wybrane pliki", "copyMessage": "Wybierz lokalizację docelową:",
"currentlyNavigating": "Obecnie przeglądasz:", "currentlyNavigating": "Aktualnie poruszasz się po:",
"deleteMessageMultiple": "Czy jesteś pewien że chcesz usunąć {count} plik(ów)?", "deleteMessageMultiple": "Czy na pewno chcesz usunąć pliki: {count}?",
"deleteMessageSingle": "Czy jesteś pewien, że chcesz usunąć ten plik/folder?", "deleteMessageSingle": "Czy na pewno chcesz usunąć ten plik/folder?",
"deleteMessageShare": "Czy na pewno chcesz usunąć ten udział ({path})?",
"deleteUser": "Czy na pewno chcesz usunąć tego użytkownika?",
"deleteTitle": "Usuń pliki", "deleteTitle": "Usuń pliki",
"displayName": "Wyświetlana Nazwa:", "displayName": "Wyświetlana nazwa:",
"download": "Pobierz pliki", "download": "Pobierz pliki",
"downloadMessage": "Wybierz format, jaki chesz pobrać.", "downloadMessage": "Wybierz format, w którym chcesz pobrać.",
"error": "Pojawił się nieznany błąd", "error": "Pojawił się jakiś błąd",
"fileInfo": "Informacje o pliku", "fileInfo": "Informacje o pliku",
"filesSelected": "{count} plików zostało zaznaczonych.", "filesSelected": "Zaznaczone pliki: {count}",
"lastModified": "Osatnio Zmodyfikowane", "lastModified": "Ostatnio zmodyfikowano",
"move": "Przenieś", "move": "Przenieś",
"moveMessage": "Wybierz nową lokalizację dla swoich plik(ów)/folder(ów):", "moveMessage": "Wybierz nową lokalizację dla swoich plików/folderów:",
"newArchetype": "Utwórz nowy wpis na bazie wybranego wzorca. Twój plik będzie utworzony w wybranym folderze.", "newArchetype": "Utwórz nowy wpis na bazie wybranego wzorca. Twój plik będzie utworzony w wybranym folderze.",
"newDir": "Nowy folder", "newDir": "Nowy folder",
"newDirMessage": "Podaj nazwę tworzonego folderu.", "newDirMessage": "Nazwij nowy folder.",
"newFile": "Nowy plik", "newFile": "Nowy plik",
"newFileMessage": "Podaj nazwętworzonego pliku.", "newFileMessage": "Nazwij nowy plik.",
"numberDirs": "Ilość katalogów", "numberDirs": "Liczba folderów",
"numberFiles": "Ilość plików", "numberFiles": "Liczba plików",
"rename": "Zmień nazwę", "rename": "Zmień nazwę",
"renameMessage": "Podaj nową nazwę dla", "renameMessage": "Podaj nową nazwę dla",
"replace": "Zamień", "replace": "Zamień",
"replaceMessage": "Jednen z plików który próbujesz wrzucić próbje nadpisać plik o tej samej nazwie. Czy chcesz nadpisać poprzedni plik?\n", "replaceMessage": "Jeden z przesyłanych plików chce nadpisać istniejący plik o tej samej nazwie. Chcesz pominąć ten plik i kontynuować przesyłanie reszty plików, czy nadpisać istniejący plik?\n",
"schedule": "Grafi", "schedule": "Grafik",
"scheduleMessage": "Wybierz datę i czas dla publikacji tego wpisu.", "scheduleMessage": "Wybierz datę i czas dla publikacji tego wpisu.",
"show": "Pokaż", "show": "Pokaż",
"size": "Rozmiar", "size": "Rozmiar",
"upload": "Prześlij", "upload": "Wyślij",
"uploadMessage": "Proszę wybrać metodę przesyłania" "uploadFiles": "Wysyłam pliki: {files}...",
"uploadMessage": "Wybierz opcję przesyłania.",
"optionalPassword": "Opcjonalne hasło",
"resolution": "Rozdzielczość",
"discardEditorChanges": "Czy na pewno chcesz odrzucić wprowadzone zmiany?"
}, },
"search": { "search": {
"images": "Zdjęcia", "images": "Obrazy",
"music": "Muzyka", "music": "Muzyka",
"pdf": "PDF", "pdf": "PDF",
"pressToSearch": "Wciśnij enter, aby wyszukać...", "pressToSearch": "Naciśnij Enter, aby wyszukać...",
"search": "Szukaj...", "search": "Szukaj...",
"typeToSearch": "Zacznij pisać, aby wyszukać...", "typeToSearch": "Typ plików do wyszukania...",
"types": "Typy", "types": "Typy",
"video": "Wideo" "video": "Wideo"
}, },
@@ -137,70 +157,81 @@
"admin": "Admin", "admin": "Admin",
"administrator": "Administrator", "administrator": "Administrator",
"allowCommands": "Wykonaj polecenie", "allowCommands": "Wykonaj polecenie",
"allowEdit": "Edycja, zmiana nazwy i usuniecie plików lub folderów", "allowEdit": "Edycja, zmiana nazwy i usuniecie plików lub folderów",
"allowNew": "Tworzenie nowych plików lub folderów", "allowNew": "Tworzenie nowych plików lub folderów",
"allowPublish": "Tworzenie nowych wpisów i stron", "allowPublish": "Tworzenie nowych wpisów i stron",
"allowSignup": "Zezwól na rejestrację użytkowników", "allowSignup": "Pozwól użytkownikom na rejestrację",
"avoidChanges": "(pozostaw puste aby nie zosatało zmienione)", "avoidChanges": "(pozostaw puste, aby uniknąć zmian)",
"branding": "Branding", "branding": "Personalizacja",
"brandingDirectoryPath": "Folder brandingowy", "brandingDirectoryPath": "Ścieżka do folderu personalizacji",
"brandingHelp": "Możesz dostosować wygląd i doznania użytkownika swojej instancji File Browser poprzez zmianę jej nazwy, zmianę logo, dodanie własnych stylów, a nawet wyłączyć linki zewnętrzne do GitHuba.\nW celu pozyskania większej ilości informacji nt. osobistego brandingu, zapoznaj się z {0}.", "brandingHelp": "Możesz zmodyfikować wygląd instancji File Browser poprzez zmianę nazwy, logo, dodanie własnych stylów graficznych, a nawet usunięcia linków do serwisu GitHub. Więcej informacji o modyfikacji wyglądu znajdziesz w {0}.",
"changePassword": "Zmień Hasło", "changePassword": "Zmień hasło",
"commandRunner": "Narzędzie do wykonywania poleceń", "commandRunner": "Narzędzie do wykonywania poleceń",
"commandRunnerHelp": "Tu możesz ustawić komendy, które będą wykonywane przy danych zdarzeniach. Musisz wpisywać po jednej na linjkę. Zmienne środowiskowe {0} i {1} będą dostępne, gdzie {0} jest względne wobec {1}. Więcej informacji o tej funkcji i dostępnych zmiennych środowiskowych znajdziesz tutaj: {2}.", "commandRunnerHelp": "Tu możesz ustawić polecenia, które będą wykonywane przy danych zdarzeniach. Musisz wpisywać po jednym na wiersz. Zmienne środowiskowe {0} i {1} będą dostępne, gdzie {0} jest względne wobec {1}. Więcej informacji o tej funkcji i dostępnych zmiennych środowiskowych znajdziesz w {2}.",
"commandsUpdated": "Polecenie zaktualizowane!", "commandsUpdated": "Polecenie zaktualizowane!",
"createUserDir": "Automatycznie utwórz katalog domowy użytkownika podczas dodania nowego użytkownika", "createUserDir": "Automatycznie twórz katalog domowy podczas dodawania użytkownika",
"customStylesheet": "Własny arkusz stylów", "minimumPasswordLength": "Minimalna długość hasła",
"defaultUserDescription": "Oto domyślne ustawienia dla nowych użytkowników.", "tusUploads": "Przesyłanie we fragmentach",
"disableExternalLinks": "Wyłącz linki zewnętrzne (z wyjątkiem dokumentacji)", "tusUploadsHelp": "File Browser wspiera przesyłanie plików we fragmentach, co pozwala na proces przesyłania, który jest wydajny, pewny i możliwy do wznowienia nawet w sieciach o wątpliwej stabilności przesyłu danych.",
"disableUsedDiskPercentage": "Disable used disk percentage graph", "tusUploadsChunkSize": "Oznacza maksymalny rozmiar przesyłanych plików (dla mniejszych plików użyte zostanie przesyłanie bezpośrednie). Możesz ustawić tę wartość zarówno zapisaną samymi cyframi w bajtach, jak i podać ją w formie skróconej, np. poprzez 10MB, 1GB itp.",
"documentation": "dokumentacja", "tusUploadsRetryCount": "Liczba prób ponowienia transferu w przypadku wystapienia problemu z przesyłem.",
"userHomeBasePath": "Ścieżka podstawowa dla katalogów domowych użytkowników",
"userScopeGenerationPlaceholder": "Zakres zostanie wygenerowany automatycznie",
"createUserHomeDirectory": "Utwórz katalog domowy użytkownika",
"customStylesheet": "Własny arkusz stylu",
"defaultUserDescription": "To są domyślne ustawienia dla nowych użytkowników.",
"disableExternalLinks": "Wyłącz linki zewnętrzne (z wyjątkiem dokumentacji)",
"disableUsedDiskPercentage": "Wyłącz wykres procentowy używanego dysku",
"documentation": "dokumentacji",
"examples": "Przykłady", "examples": "Przykłady",
"executeOnShell": "Wykonaj w powłoce", "executeOnShell": "Wykonaj w powłoce",
"executeOnShellDescription": "Domyślnie File Browser wykonuje polecenia wywołując ich pliki binarne bezpośrednio. Jesli preferujesz wykonywanie ich w powłoce (jak np. Bash czy PowerShell), możesz zdefiniować to tutaj wraz z wymaganymi flagami i argumentami. Jeśli to ustawienie jest aktywne, polecenie które wykonarz zostanie dodane jako argument. Stosuje się to zarówno do poleceń użytkownika jak i zaczepów zdarzeń.", "executeOnShellDescription": "Domyślnie File Browser wykonuje polecenia poprzez bezpośrednie uruchomienie odpowiednich plików binarnych. Jeśli chcesz uruchamiać polecenia z poziomu powłoki (np. Bash lub PowerShell), możesz zdefiniować je tutaj, z wykorzystaniem odpowiednich argumentów i flag. Gdy się na to zdecydujesz, wykonywane polecenie będzie załączone jako argument. Tyczy się to tak poleceń użytkownika, jak i zaczepów zdarzeń.",
"globalRules": "To jest globalne zestawienie reguł zezwalających i zabraniających. Stosują się one do każdego użytkownika. Możesz zdefiniować indywidualne zasady w ustawieniach każdego użytkownika, by zignorować te reguły.", "globalRules": "Globalny zestaw reguł zezwalających i zakazujących. Dotyczą każdego użytkownika. Aby zastąpić ustawienia globalne, możesz zdefiniować określone reguły indywidualnie dla każdego użytkownika.",
"globalSettings": "Ustawienia Globalne", "globalSettings": "Ustawienia globalne",
"hideDotfiles": "Ukryj ukryte pliki", "hideDotfiles": "Ukryj pliki poprzedzone kropką",
"insertPath": "Wstaw ścieżkę", "insertPath": "Wstaw ścieżkę",
"insertRegex": "Wstaw wyrażenie regularne", "insertRegex": "Wstaw wyrażenie regularne",
"instanceName": "Nazwa instancji", "instanceName": "Nazwa instancji",
"language": "Język", "language": "Język",
"lockPassword": "Zablokuj użytkownikowi możliwość zmiany hasła", "lockPassword": "Zablokuj użytkownikowi możliwość zmiany hasła",
"newPassword": "Twoje nowe hasło", "newPassword": "Nowe hasło",
"newPasswordConfirm": "Potwierdź swoje hasło", "newPasswordConfirm": "Potwierdź nowe hasło",
"newUser": "Nowy Użytkownik", "newUser": "Nowy użytkownik",
"password": "Hasło", "password": "Hasło",
"passwordUpdated": "Hasło zostało zapisane!", "passwordUpdated": "Hasło zostało zaktualizowane!",
"path": "Ścieżka", "path": "Ścieżka",
"perm": { "perm": {
"create": "Tworzenie plików i katalogów", "create": "Tworzenie plików i folderów",
"delete": "Usuwanie plików i katalogów", "delete": "Usuwanie plików i folderów",
"download": "Pobieranie", "download": "Pobieranie",
"execute": "Wykonywanie poleceń", "execute": "Wykonywanie poleceń",
"modify": "Edycja plików", "modify": "Edytowanie plików",
"rename": "Zmiana nazw lub przenoszenie plików i katalogów", "rename": "Zmienianie nazwy lub przenoszenie plików i katalogów",
"share": "Udostępnianie plików" "share": "Udostępnianie plików"
}, },
"permissions": "Uprawnienia", "permissions": "Uprawnienia",
"permissionsHelp": "Możesz uczynić użytkownika administratorem, lub wybrać uprawnienia indywidualnie. Jeśli zaznaczysz opcję \"Administrator\", wszystkie pozostałe opcje zostaną automatycznie zaznaczone. Zarządzanie użytkownikami pozostaje przywilejem administratora.\n", "permissionsHelp": "Możesz ustawić użytkownika jako administratora lub wybrać uprawnienia indywidualnie. Jeśli wybierzesz „Administrator, wszystkie pozostałe opcje zostaną automatycznie zaznaczone. Zarządzanie użytkownikami pozostaje przywilejem administratora.\n",
"profileSettings": "Twój profil", "profileSettings": "Twój profil",
"ruleExample1": "uniemożliwia dostęp do któregokolwiek z ukrytych plików (takich jak .git, .gitignore) w każdym folderze.\n", "ruleExample1": "uniemożliwia dostęp do plików poprzedzonych kropką (takich jak .git, .gitignore) we wszystkich folderach.\n",
"ruleExample2": "blokuje dostęp do pliku Caddyfile w głównym katalogu zakresu.", "ruleExample2": "blokuje dostęp do pliku o nazwie Caddyfile w katalogu głównym zakresu.",
"rules": "Uprawnienia", "rules": "Uprawnienia",
"rulesHelp": "Tu możesz zdefiniować zestawienie reguł zezwalających i zabraniających dla tego konkretnego użytkownika. Zablokowane pliki nie będą widoczne na listach i nie będą dostępne dla użytkownika. Wspierane są wyrażenia regularne i ścieżki względne wobec zakresu użytkownika.\n", "rulesHelp": "Tutaj możesz zdefiniować zestaw reguł zezwalających i zakazujących dla tego użytkownika. Zablokowane pliki nie pojawią się na listach i nie będą dostępne dla użytkownika. Obsługujemy wyrażenia regularne i ścieżki względne w stosunku do zakresu użytkownika.\n",
"scope": "Zakres", "scope": "Zakres",
"settingsUpdated": "Uprawnienia Zapisane!", "setDateFormat": "Ustaw dokładny format daty",
"settingsUpdated": "Ustawienia zaktualizowane!",
"shareDuration": "Okres udostępniania", "shareDuration": "Okres udostępniania",
"shareManagement": "Zarządzanie udostępnianiem", "shareManagement": "Zarządzanie udostępnianiem",
"singleClick": "Pojedyncze kliknięcie", "shareDeleted": "Udostępnienie usunięte!",
"singleClick": "Używaj pojedynczych kliknięć, aby otwierać pliki i foldery",
"themes": { "themes": {
"dark": "ciemny", "default": "Domyślny systemowy",
"light": "jasny", "dark": "Ciemny",
"title": "Motywy" "light": "Jasny",
"title": "Motyw"
}, },
"user": "Użytkownik", "user": "Użytkownik",
"userCommands": "Polecenia", "userCommands": "Polecenia",
"userCommandsHelp": "Lista oddzielonych spacjami poleceń dostępnych dla tego użytkownika. Przykład:\n", "userCommandsHelp": "Oddzielona spacjami lista z dostępnymi poleceniami dla tego użytkownika. Przykład:\n",
"userCreated": "Użytkownik zapisany!", "userCreated": "Użytkownik zapisany!",
"userDefaults": "Domyślne ustawienia użytkownika", "userDefaults": "Domyślne ustawienia użytkownika",
"userDeleted": "Użytkownik usunięty!", "userDeleted": "Użytkownik usunięty!",
@@ -211,8 +242,8 @@
}, },
"sidebar": { "sidebar": {
"help": "Pomoc", "help": "Pomoc",
"hugoNew": "Hugo New", "hugoNew": "Nowy Hugo",
"login": "Login", "login": "Zaloguj",
"logout": "Wyloguj", "logout": "Wyloguj",
"myFiles": "Moje pliki", "myFiles": "Moje pliki",
"newFile": "Nowy plik", "newFile": "Nowy plik",
@@ -220,10 +251,10 @@
"preview": "Podgląd", "preview": "Podgląd",
"settings": "Ustawienia", "settings": "Ustawienia",
"signup": "Rejestracja", "signup": "Rejestracja",
"siteSettings": "Ustawienia Strony" "siteSettings": "Ustawienia strony"
}, },
"success": { "success": {
"linkCopied": "Link Skopiowany!" "linkCopied": "Link skopiowany!"
}, },
"time": { "time": {
"days": "Dni", "days": "Dni",

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