Compare commits

...

57 Commits

Author SHA1 Message Date
Elias Schneider
46783ce463 release: 0.25.0 2024-06-10 11:43:12 +02:00
Elias Schneider
c0cc16fa43 fix: share size not displayed on my shares page 2024-06-10 11:41:41 +02:00
Ivan Li
4fd29037a0 Feature: add auto open share modal config for global. (#474)
* feat(admin): add auto open share modal config for global.

* feat(upload): Apply the flag that disables the automatic open create share modal.

* fix: remove migration and add new config variable to seed script

* chore(translations): improve auto open share modal description

* refactor: run formatter

---------

Co-authored-by: Elias Schneider <login@eliasschneider.com>
2024-06-10 11:32:52 +02:00
Leo Li
1c7832ad1f feat(frontend): locale for dates and tooltip for copy link button (#492)
* Add tooltip for copy button

* Set locale globally for moment.js

* format

* remove debugging log

* refactor: rename translation key

---------

Co-authored-by: Elias Schneider <login@eliasschneider.com>
2024-06-10 11:01:59 +02:00
Cabeza
962ec27df4 chore: sanitize appUrl to remove trailing slash in updateConfigVariable function (#496) 2024-06-10 11:01:08 +02:00
Elias Schneider
9268e35141 chore(translations): update translations via Crowdin (#485)
* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Korean)

* New translations en-us.ts (Korean)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Russian)
2024-06-10 10:48:37 +02:00
Elias Schneider
e8be0d60e6 docs: add Discord to issue page 2024-05-24 09:29:18 +02:00
Elias Schneider
0eabf78f13 chore: remove question issue template 2024-05-24 08:09:47 +02:00
Elias Schneider
4136bf5778 docs: update Discord link 2024-05-24 08:09:16 +02:00
Elias Schneider
42b3604e2a docs: add badges to README 2024-05-23 22:08:52 +02:00
Elias Schneider
84f4c39c1e release: 0.24.2 2024-05-22 15:21:07 +02:00
Elias Schneider
bfef246d98 New translations en-us.ts (French) (#475) 2024-05-22 15:20:50 +02:00
Elias Schneider
3b89fb950a chore: update dependencies 2024-05-22 15:20:33 +02:00
Elias Schneider
7afda85f03 fix: admin couldn't delete shares created by anonymous users 2024-05-17 15:13:56 +02:00
Elias Schneider
a3a7a5d9ab Merge branch 'main' of https://github.com/stonith404/pingvin-share 2024-05-17 14:42:27 +02:00
Elias Schneider
74cd520cb8 fix: whitespace in title on homepage 2024-05-17 14:42:14 +02:00
Elias Schneider
a511f24a6b chore(translations): update translations via Crowdin (#467)
* New translations en-us.ts (Portuguese, Brazilian)

* New translations en-us.ts (Korean)

* New translations en-us.ts (Korean)

* New translations en-us.ts (Korean)

* New translations en-us.ts (Italian)

* New translations en-us.ts (German)

* New translations en-us.ts (Chinese Simplified)

* New translations en-us.ts (Chinese Simplified)
2024-05-14 09:49:51 +02:00
Maurice Schorn
b3862f3f3e change docker command (#470) 2024-05-14 09:49:40 +02:00
Elias Schneider
d147614f76 release: 0.24.1 2024-05-04 14:45:19 +03:00
Elias Schneider
c999df15e0 fix: error on admin share management page if a share was created by an anonymous user 2024-05-04 14:45:08 +03:00
Elias Schneider
908d6e298f release: 0.24.0 2024-05-04 10:11:19 +03:00
Elias Schneider
44c4a2e269 chore(translations): update translations via Crowdin (#465)
* New translations en-us.ts (Spanish)

* New translations en-us.ts (Italian)

* New translations en-us.ts (Chinese Simplified)

* New translations en-us.ts (Portuguese, Brazilian)

* New translations en-us.ts (German)

* New translations en-us.ts (Spanish)

* New translations en-us.ts (French)

* New translations en-us.ts (Danish)

* New translations en-us.ts (Greek)

* New translations en-us.ts (Finnish)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Italian)

* New translations en-us.ts (Japanese)

* New translations en-us.ts (Polish)

* New translations en-us.ts (Russian)

* New translations en-us.ts (Slovenian)

* New translations en-us.ts (Serbian (Cyrillic))

* New translations en-us.ts (Swedish)

* New translations en-us.ts (Ukrainian)

* New translations en-us.ts (Chinese Simplified)

* New translations en-us.ts (Chinese Traditional)

* New translations en-us.ts (Portuguese, Brazilian)

* New translations en-us.ts (Thai)

* New translations en-us.ts (Dutch, Belgium)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Korean)
2024-05-04 10:09:01 +03:00
Elias Schneider
dc060f258b chore(translations): add korean language files 2024-05-04 00:22:17 +03:00
SFGrenade
3b1c9f1efb feat: add admin-exclusive share-management page (#461)
* testing with all_shares

* share table

* share table

* change icon on admin page

* add share size to list

---------

Co-authored-by: Elias Schneider <login@eliasschneider.com>
2024-05-04 00:18:27 +03:00
Elias Schneider
a45184995f chore(translations): update translations via Crowdin (#464)
* New translations en-us.ts (German)

* New translations en-us.ts (Spanish)

* New translations en-us.ts (French)

* New translations en-us.ts (Danish)

* New translations en-us.ts (Greek)

* New translations en-us.ts (Finnish)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Italian)

* New translations en-us.ts (Japanese)

* New translations en-us.ts (Polish)

* New translations en-us.ts (Russian)

* New translations en-us.ts (Slovenian)

* New translations en-us.ts (Serbian (Cyrillic))

* New translations en-us.ts (Swedish)

* New translations en-us.ts (Ukrainian)

* New translations en-us.ts (Chinese Simplified)

* New translations en-us.ts (Chinese Traditional)

* New translations en-us.ts (Portuguese, Brazilian)

* New translations en-us.ts (Thai)

* New translations en-us.ts (Dutch, Belgium)

* New translations en-us.ts (Arabic, Egypt)
2024-05-03 17:24:27 +02:00
Elias Schneider
b717663b5c feat: add name property to share (#462)
* add name property to share

* refactor: run formatter

* tests: adapt system tests

* tests: adapt second system test
2024-05-03 17:12:26 +02:00
Elias Schneider
0e12ba87bc chore(translations): update translations via Crowdin (#453)
* New translations en-us.ts (German)

* New translations en-us.ts (German)

* New translations en-us.ts (Spanish)
2024-04-26 13:20:46 +03:00
Yuanlin Lin
ec1feadee9 doc: add Zeabur installation guide (#447)
* docs: add Zeabur installation

https://youtu.be/JOhWUvSSJYQ

* chore: remove zeabur button
2024-04-26 13:19:00 +03:00
Elias Schneider
2e0d8d4fed chore(translations): update translations via Crowdin (#440)
* New translations en-us.ts (Danish)

* New translations en-us.ts (Hungarian)

* New translations en-us.ts (French)

* New translations en-us.ts (Spanish)

* New translations en-us.ts (German)

* New translations en-us.ts (Greek)

* New translations en-us.ts (Finnish)

* New translations en-us.ts (Italian)

* New translations en-us.ts (Japanese)

* New translations en-us.ts (Polish)

* New translations en-us.ts (Russian)

* New translations en-us.ts (Slovenian)

* New translations en-us.ts (Serbian (Cyrillic))

* New translations en-us.ts (Swedish)

* New translations en-us.ts (Ukrainian)

* New translations en-us.ts (Chinese Simplified)

* New translations en-us.ts (Chinese Traditional)

* New translations en-us.ts (Portuguese, Brazilian)

* New translations en-us.ts (Thai)

* New translations en-us.ts (Dutch, Belgium)

* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (Portuguese, Brazilian)

* New translations en-us.ts (Italian)

* New translations en-us.ts (Slovenian)

* New translations en-us.ts (Slovenian)

* New translations en-us.ts (Danish)

* New translations en-us.ts (French)

* New translations en-us.ts (Swedish)

* New translations en-us.ts (Greek)
2024-04-23 12:01:45 +03:00
MaYunFei
b7f0f9d3ee chore(translations): rename Simplified Chinese -> 简体中文 (#451) 2024-04-23 12:01:33 +03:00
Elias Schneider
c303454db3 release: 0.23.1 2024-04-05 13:54:55 +02:00
Elias Schneider
3972589f76 fix: normal shares were added to the previous reverse share 2024-04-05 13:54:36 +02:00
Elias Schneider
3c5e0ad513 fix: incorrect layout on 404 page 2024-04-05 12:03:38 +02:00
Elias Schneider
384fd19203 fix: redirect vulnerability on error, sign in and totp page 2024-04-05 12:00:41 +02:00
Elias Schneider
9d1a12b0d1 fix: disable js execution on raw file view 2024-04-05 11:37:47 +02:00
Elias Schneider
24e100bd7b fix: changing the chunk size needed an app restart 2024-04-05 11:31:43 +02:00
Elias Schneider
1da4feeb89 fix(backend): crash on unhandled promise rejections 2024-04-04 23:18:00 +02:00
Elias Schneider
c0a245e11b release: 0.23.0 2024-04-04 22:54:39 +02:00
Elias Schneider
7a15fbb465 fix: memory leak while uploading files by disabling base64 encoding of chunks 2024-04-04 20:55:45 +02:00
Elias Schneider
0bfbaea49a feat: add config variable to adjust chunk size 2024-04-04 20:54:21 +02:00
Elias Schneider
82871ce5dc chore(translations): update translations via Crowdin (#436)
* New translations en-us.ts (Hungarian)

* New translations en-us.ts (Ukrainian)

* New translations en-us.ts (Ukrainian)
2024-04-04 20:01:04 +02:00
Elias Schneider
593a65dac1 chore(translations): rename language code of Ukrainian to uk-UA 2024-04-04 19:58:39 +02:00
theGrove
92ee1ab527 chore(translations): add Ukrainian (#438)
* add Ukrainian lenguage

add Ukrainian lenguage

* fix: change locale key

---------

Co-authored-by: Elias Schneider <login@eliasschneider.com>
2024-04-04 19:52:03 +02:00
Elias Schneider
e71f6cd159 fix: delete share files if user gets deleted 2024-03-28 11:59:50 +01:00
Elias Schneider
0b07bfbc14 docs: update frontend start command 2024-03-28 11:48:34 +01:00
Elias Schneider
63842cd0cc chore(translations): add hungarian files 2024-03-28 11:33:43 +01:00
Elias Schneider
9f686c6ee3 chore(translations): update translations via Crowdin (#416)
* New translations en-us.ts (Arabic, Egypt)

* New translations en-us.ts (French)
2024-03-28 11:32:30 +01:00
Elias Schneider
c6d8188e4e fix: error in logs if "allow unauthenticated shares" is enabled 2024-03-25 19:12:27 +01:00
Elias Schneider
6d87e20e29 docs: add npm install to upgrade guide 2024-03-07 09:43:14 +01:00
Elias Schneider
b8efb9f54b release: 0.22.2 2024-02-29 14:43:08 +01:00
Elias Schneider
013b9886af fix: extend access token cookie expiration 2024-02-29 14:42:05 +01:00
Elias Schneider
43bff91db2 fix: replace Nginx with Caddy to fix "premature close" error while downloading larger files 2024-02-29 14:41:45 +01:00
Elias Schneider
1aa3d8e5e8 fix: reduce refresh access token calls 2024-02-27 09:40:52 +01:00
Elias Schneider
4dae7e250a docs: improve configuration section in README 2024-02-27 09:24:07 +01:00
Elias Schneider
7e91d83f9a chore(translations): add Arabic translation files 2024-02-27 09:12:46 +01:00
Elias Schneider
e11dbfe893 chore(translations): update translations via Crowdin (#411)
* New translations en-us.ts (French)

* New translations en-us.ts (Spanish)

* New translations en-us.ts (Dutch, Belgium)

* New translations en-us.ts (Italian)

* New translations en-us.ts (Danish)

* New translations en-us.ts (German)

* New translations en-us.ts (Greek)

* New translations en-us.ts (Finnish)

* New translations en-us.ts (Japanese)

* New translations en-us.ts (Polish)

* New translations en-us.ts (Russian)

* New translations en-us.ts (Slovenian)

* New translations en-us.ts (Serbian (Cyrillic))

* New translations en-us.ts (Swedish)

* New translations en-us.ts (Chinese Simplified)

* New translations en-us.ts (Chinese Traditional)

* New translations en-us.ts (Portuguese, Brazilian)

* New translations en-us.ts (Thai)

* New translations en-us.ts (Portuguese, Brazilian)

* New translations en-us.ts (Italian)

* New translations en-us.ts (Polish)
2024-02-27 09:11:25 +01:00
Elias Schneider
ea83cf3876 docs: add environment variable step to stand-alone docs 2024-02-18 21:53:11 +01:00
81 changed files with 9691 additions and 10521 deletions

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

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: 💬 Discord
url: https://discord.gg/wHRQ9nFRcK
about: For help and chatting with the community

View File

@@ -1,17 +0,0 @@
name: ❓ Question
description: "Submit a question"
title: "❓ Question:"
labels: [question]
body:
- type: textarea
id: feature-description
validations:
required: true
attributes:
label: "🙋‍♂️ Question"
description: "A clear question. Please provide as much detail as possible."
placeholder: "How do I ...?"
- type: markdown
attributes:
value: |
Before submitting, please check if the question hasn't been asked before.

View File

@@ -1,3 +1,74 @@
## [0.25.0](https://github.com/stonith404/pingvin-share/compare/v0.24.2...v0.25.0) (2024-06-10)
### Features
* add auto open share modal config for global. ([#474](https://github.com/stonith404/pingvin-share/issues/474)) ([4fd2903](https://github.com/stonith404/pingvin-share/commit/4fd29037a08dbe505bdd8cf20f6f114cbade8483))
* **frontend:** locale for dates and tooltip for copy link button ([#492](https://github.com/stonith404/pingvin-share/issues/492)) ([1c7832a](https://github.com/stonith404/pingvin-share/commit/1c7832ad1fb445fd1dbe1c111be5a331eaa4b797))
### Bug Fixes
* share size not displayed on my shares page ([c0cc16f](https://github.com/stonith404/pingvin-share/commit/c0cc16fa430bc64afb024c19d5faf24456bd417c))
## [0.24.2](https://github.com/stonith404/pingvin-share/compare/v0.24.1...v0.24.2) (2024-05-22)
### Bug Fixes
* admin couldn't delete shares created by anonymous users ([7afda85](https://github.com/stonith404/pingvin-share/commit/7afda85f03d410a6c611860d0c3fb2b88a2e3679))
* whitespace in title on homepage ([74cd520](https://github.com/stonith404/pingvin-share/commit/74cd520cb8c4ea87822ab6d54c0bf010455f401b))
## [0.24.1](https://github.com/stonith404/pingvin-share/compare/v0.24.0...v0.24.1) (2024-05-04)
### Bug Fixes
* error on admin share management page if a share was created by an anonymous user ([c999df1](https://github.com/stonith404/pingvin-share/commit/c999df15e04a927f6e952db3c807b9591fb14894))
## [0.24.0](https://github.com/stonith404/pingvin-share/compare/v0.23.1...v0.24.0) (2024-05-04)
### Features
* add admin-exclusive share-management page ([#461](https://github.com/stonith404/pingvin-share/issues/461)) ([3b1c9f1](https://github.com/stonith404/pingvin-share/commit/3b1c9f1efb7d02469e92537a2d1378b6cb412878))
* add name property to share ([#462](https://github.com/stonith404/pingvin-share/issues/462)) ([b717663](https://github.com/stonith404/pingvin-share/commit/b717663b5c3a4a98e361e7e39b680f4852537c59))
## [0.23.1](https://github.com/stonith404/pingvin-share/compare/v0.23.0...v0.23.1) (2024-04-05)
### Bug Fixes
* **backend:** crash on unhandled promise rejections ([1da4fee](https://github.com/stonith404/pingvin-share/commit/1da4feeb895a13d0a0ae754bd716a84e8186d081))
* changing the chunk size needed an app restart ([24e100b](https://github.com/stonith404/pingvin-share/commit/24e100bd7be8bf20778bdf2767aa35cae8d7e502))
* disable js execution on raw file view ([9d1a12b](https://github.com/stonith404/pingvin-share/commit/9d1a12b0d1812214f1fe6fa56e3848091ce4945c))
* incorrect layout on 404 page ([3c5e0ad](https://github.com/stonith404/pingvin-share/commit/3c5e0ad5134ee2d405ac420152b5825102f65bfc))
* normal shares were added to the previous reverse share ([3972589](https://github.com/stonith404/pingvin-share/commit/3972589f76519b03074d916fb2460c795b1f0737))
* redirect vulnerability on error, sign in and totp page ([384fd19](https://github.com/stonith404/pingvin-share/commit/384fd19203b63eeb4b952f83a9e1eaab1b19b90d))
## [0.23.0](https://github.com/stonith404/pingvin-share/compare/v0.22.2...v0.23.0) (2024-04-04)
### Features
* add config variable to adjust chunk size ([0bfbaea](https://github.com/stonith404/pingvin-share/commit/0bfbaea49aad0c695fee6558c89c661687912e4f))
### Bug Fixes
* delete share files if user gets deleted ([e71f6cd](https://github.com/stonith404/pingvin-share/commit/e71f6cd1598ed87366074398042a6b88675587ca))
* error in logs if "allow unauthenticated shares" is enabled ([c6d8188](https://github.com/stonith404/pingvin-share/commit/c6d8188e4e33ba682551a3ca79205ff5a6d7ead5))
* memory leak while uploading files by disabling base64 encoding of chunks ([7a15fbb](https://github.com/stonith404/pingvin-share/commit/7a15fbb4651c2fee32fb4c1ee2c9d7f12323feb0))
## [0.22.2](https://github.com/stonith404/pingvin-share/compare/v0.22.1...v0.22.2) (2024-02-29)
### Bug Fixes
* extend access token cookie expiration ([013b988](https://github.com/stonith404/pingvin-share/commit/013b9886af5629b2ead6000b962267afc761c612))
* reduce refresh access token calls ([1aa3d8e](https://github.com/stonith404/pingvin-share/commit/1aa3d8e5e89b3696cc9554f41e9ce13806dde406))
* replace Nginx with Caddy to fix "premature close" error while downloading larger files ([43bff91](https://github.com/stonith404/pingvin-share/commit/43bff91db2ba4ec68d76e601f7bc42cb7a506bc5))
## [0.22.1](https://github.com/stonith404/pingvin-share/compare/v0.22.0...v0.22.1) (2024-02-18)

15
Caddyfile Normal file
View File

@@ -0,0 +1,15 @@
:3000 {
# Reverse proxy for /api
reverse_proxy /api/* http://localhost:8080 {
header_up X-Forwarded-Host {host}:{server_port}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
# Reverse proxy for all other requests
reverse_proxy http://localhost:3333 {
header_up X-Forwarded-Host {host}:{server_port}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}

View File

@@ -30,12 +30,12 @@ RUN npm run build && npm prune --production
FROM node:20-alpine AS runner
ENV NODE_ENV=docker
# Alpine specific dependencies
RUN apk update --no-cache
RUN apk upgrade --no-cache
RUN apk add --no-cache curl nginx
# Install Caddy
RUN apk update --no-cache \
&& apk upgrade --no-cache \
&& apk add --no-cache curl caddy
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./Caddyfile /etc/caddy/Caddyfile
WORKDIR /opt/app/frontend
COPY --from=frontend-builder /opt/app/public ./public
@@ -53,9 +53,8 @@ WORKDIR /opt/app
EXPOSE 3000
# Add a health check to ensure the container is healthy
# Health check remains unchanged
HEALTHCHECK --interval=10s --timeout=3s CMD curl -f http://localhost:3000/api/health || exit 1
# Application startup
# HOSTNAME=0.0.0.0 fixes https://github.com/vercel/next.js/issues/51684. It can be removed as soon as the issue is fixed
CMD cp -rn /tmp/img/* /opt/app/frontend/public/img && nginx && PORT=3333 HOSTNAME=0.0.0.0 node frontend/server.js & cd backend && npm run prod
# Application startup updated for Caddy
CMD cp -rn /tmp/img/* /opt/app/frontend/public/img && caddy run --config /etc/caddy/Caddyfile & PORT=3333 HOSTNAME=0.0.0.0 node frontend/server.js & cd backend && npm run prod

View File

@@ -1,8 +1,8 @@
# <div align="center"><img src="https://user-images.githubusercontent.com/58886915/166198400-c2134044-1198-4647-a8b6-da9c4a204c68.svg" width="40"/> </br>Pingvin Share</div>
---
[![](https://dcbadge.limes.pink/api/server/wHRQ9nFRcK)](https://discord.gg/wHRQ9nFRcK) [![](https://img.shields.io/badge/Crowdin-2E3340.svg?style=for-the-badge&logo=Crowdin&logoColor=white)](https://crowdin.com/project/pingvin-share) [![](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge&logo=GitHub-Sponsors&logoColor=#white)](https://github.com/sponsors/stonith404)
_Read this in another language: [Spanish](/docs/README.es.md), [English](/README.md), [Simplified Chinese](/docs/README.zh-cn.md), [日本語](/docs/README.ja-jp.md)_
_Read this in another language: [Spanish](/docs/README.es.md), [English](/README.md), [简体中文](/docs/README.zh-cn.md), [日本語](/docs/README.ja-jp.md)_
---
@@ -31,7 +31,7 @@ Pingvin Share is self-hosted file sharing platform and an alternative for WeTran
### Installation with Docker (recommended)
1. Download the `docker-compose.yml` file
2. Run `docker-compose up -d`
2. Run `docker compose up -d`
The website is now listening on `http://localhost:3000`, have fun with Pingvin Share 🐧!
@@ -60,11 +60,11 @@ pm2 start --name="pingvin-share-backend" npm -- run prod
cd ../frontend
npm install
npm run build
API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080
pm2 start --name="pingvin-share-frontend" npm -- run start
API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080
pm2 start --name="pingvin-share-frontend" .next/standalone/server.js
```
**Uploading Large Files**: By default, Pingvin Share uses a built-in reverse proxy to reduce the installation steps. However, this reverse proxy is not optimized for uploading large files. If you wish to upload larger files, you can either use the Docker installation or set up your own reverse proxy. An example configuration for Nginx can be found in `/nginx/nginx.conf`.
**Uploading Large Files**: By default, Pingvin Share uses a built-in reverse proxy to reduce the installation steps. However, this reverse proxy is not optimized for uploading large files. If you wish to upload larger files, you can either use the Docker installation or set up your own reverse proxy. An example configuration for Caddy can be found in `./Caddyfile`.
The website is now listening on `http://localhost:3000`, have fun with Pingvin Share 🐧!
@@ -87,6 +87,7 @@ View the [OAuth 2 guide](/docs/oauth2-guide.md) for more information.
### Additional resources
- [Synology NAS installation](https://mariushosting.com/how-to-install-pingvin-share-on-your-synology-nas/)
- [Zeabur installation](https://zeabur.com/templates/19G6OK)
### Upgrade to a new version
@@ -115,18 +116,21 @@ docker compose up -d
# Start the backend
cd backend
npm install
npm run build
pm2 restart pingvin-share-backend
# Start the frontend
cd ../frontend
npm install
npm run build
API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080
pm2 restart pingvin-share-frontend
```
### Configuration
You can customize Pingvin Share by going to the configuration page in your admin dashboard.
You can customize Pingvin Share like changing your domain by going to the configuration page in your admin dashboard `/admin/config`.
#### Environment variables

9474
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "pingvin-share-backend",
"version": "0.22.1",
"version": "0.25.0",
"scripts": {
"build": "nest build",
"dev": "cross-env NODE_ENV=development nest start --watch",
@@ -13,73 +13,73 @@
"seed": "ts-node prisma/seed/config.seed.ts"
},
"dependencies": {
"@nestjs/cache-manager": "^2.1.0",
"@nestjs/common": "^10.1.2",
"@nestjs/config": "^3.0.0",
"@nestjs/core": "^10.1.2",
"@nestjs/jwt": "^10.1.0",
"@nestjs/passport": "^10.0.0",
"@nestjs/platform-express": "^10.1.2",
"@nestjs/schedule": "^3.0.1",
"@nestjs/swagger": "^7.1.4",
"@nestjs/cache-manager": "^2.2.2",
"@nestjs/common": "^10.3.8",
"@nestjs/config": "^3.2.2",
"@nestjs/core": "^10.3.8",
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.3.8",
"@nestjs/schedule": "^3.0.4",
"@nestjs/swagger": "^7.3.1",
"@nestjs/throttler": "^4.2.1",
"@prisma/client": "^5.0.0",
"archiver": "^5.3.1",
"argon2": "^0.30.3",
"@prisma/client": "^5.14.0",
"archiver": "^5.3.2",
"argon2": "^0.40.1",
"body-parser": "^1.20.2",
"cache-manager": "^5.2.4",
"clamscan": "^2.1.2",
"cache-manager": "^5.5.2",
"clamscan": "^2.2.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"class-validator": "^0.14.1",
"content-disposition": "^0.5.4",
"cookie-parser": "^1.4.6",
"mime-types": "^2.1.35",
"moment": "^2.29.4",
"nanoid": "^3.3.6",
"moment": "^2.30.1",
"nanoid": "^3.3.7",
"node-fetch": "^2.7.0",
"nodemailer": "^6.9.4",
"nodemailer": "^6.9.13",
"otplib": "^12.0.1",
"passport": "^0.6.0",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"qrcode-svg": "^1.1.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^5.0.1",
"reflect-metadata": "^0.1.12",
"rimraf": "^5.0.7",
"rxjs": "^7.8.1",
"sharp": "^0.32.4",
"ts-node": "^10.9.1"
"ts-node": "^10.9.2"
},
"devDependencies": {
"@nestjs/cli": "^10.1.10",
"@nestjs/schematics": "^10.0.1",
"@nestjs/testing": "^10.1.2",
"@types/archiver": "^5.3.2",
"@types/clamscan": "^2.0.4",
"@types/cookie-parser": "^1.4.3",
"@nestjs/cli": "^10.3.2",
"@nestjs/schematics": "^10.1.1",
"@nestjs/testing": "^10.3.8",
"@types/archiver": "^5.3.4",
"@types/clamscan": "^2.0.8",
"@types/cookie-parser": "^1.4.7",
"@types/cron": "^2.0.1",
"@types/express": "^4.17.17",
"@types/mime-types": "^2.1.1",
"@types/multer": "^1.4.7",
"@types/node": "^20.4.5",
"@types/node-fetch": "^2.6.6",
"@types/nodemailer": "^6.4.9",
"@types/passport-jwt": "^3.0.9",
"@types/qrcode-svg": "^1.1.1",
"@types/express": "^4.17.21",
"@types/mime-types": "^2.1.4",
"@types/multer": "^1.4.11",
"@types/node": "^20.12.12",
"@types/node-fetch": "^2.6.11",
"@types/nodemailer": "^6.4.15",
"@types/passport-jwt": "^3.0.13",
"@types/qrcode-svg": "^1.1.4",
"@types/sharp": "^0.31.1",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^6.2.0",
"@typescript-eslint/parser": "^6.2.0",
"@types/supertest": "^2.0.16",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"cross-env": "^7.0.3",
"eslint": "^8.46.0",
"eslint-config-prettier": "^8.9.0",
"eslint-plugin-prettier": "^5.0.0",
"newman": "^5.3.2",
"prettier": "^3.0.0",
"prisma": "^5.0.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-prettier": "^5.1.3",
"newman": "^6.1.2",
"prettier": "^3.2.5",
"prisma": "^5.14.0",
"source-map-support": "^0.5.21",
"ts-loader": "^9.4.4",
"ts-loader": "^9.5.1",
"tsconfig-paths": "4.2.0",
"typescript": "^5.1.6",
"wait-on": "^7.0.1"
"typescript": "^5.4.5",
"wait-on": "^7.2.0"
}
}

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Share" ADD COLUMN "name" TEXT;

View File

@@ -75,6 +75,7 @@ model Share {
id String @id @default(uuid())
createdAt DateTime @default(now())
name String?
uploadLocked Boolean @default(false)
isZipReady Boolean @default(false)
views Int @default(0)

View File

@@ -51,6 +51,16 @@ const configVariables: ConfigVariables = {
type: "number",
defaultValue: "9",
},
chunkSize: {
type: "number",
defaultValue: "10000000",
secret: false,
},
autoOpenShareModal: {
type: "boolean",
defaultValue: "false",
secret: false,
},
},
email: {
enableShareEmailRecipients: {

View File

@@ -99,7 +99,7 @@ export class AuthService {
include: { resetPasswordToken: true },
});
if (!user) throw new BadRequestException("User not found");
if (!user) return;
// Delete old reset password token
if (user.resetPasswordToken) {
@@ -227,13 +227,16 @@ export class AuthService {
accessToken?: string,
) {
if (accessToken)
response.cookie("access_token", accessToken, { sameSite: "lax" });
response.cookie("access_token", accessToken, {
sameSite: "lax",
maxAge: 1000 * 60 * 60 * 24 * 30 * 3, // 3 months
});
if (refreshToken)
response.cookie("refresh_token", refreshToken, {
path: "/api/auth/token",
httpOnly: true,
sameSite: "strict",
maxAge: 1000 * 60 * 60 * 24 * 30 * 3,
maxAge: 1000 * 60 * 60 * 24 * 30 * 3, // 3 months
});
}

View File

@@ -26,18 +26,21 @@ export class FileController {
@SkipThrottle()
@UseGuards(CreateShareGuard, ShareOwnerGuard)
async create(
@Query() query: any,
@Query()
query: {
id: string;
name: string;
chunkIndex: string;
totalChunks: string;
},
@Body() body: string,
@Param("shareId") shareId: string,
) {
const { id, name, chunkIndex, totalChunks } = query;
// Data can be empty if the file is empty
const data = body.toString().split(",")[1] ?? "";
return await this.fileService.create(
data,
body,
{ index: parseInt(chunkIndex), total: parseInt(totalChunks) },
{ id, name },
shareId,
@@ -72,6 +75,7 @@ export class FileController {
const headers = {
"Content-Type": file.metaData.mimeType,
"Content-Length": file.metaData.size,
"Content-Security-Policy": "script-src 'none'",
};
if (download === "true") {

View File

@@ -47,7 +47,7 @@ export class FileService {
}
// If the sent chunk index and the expected chunk index doesn't match throw an error
const chunkSize = 10 * 1024 * 1024; // 10MB
const chunkSize = this.config.get("share.chunkSize");
const expectedChunkIndex = Math.ceil(diskFileSize / chunkSize);
if (expectedChunkIndex != chunk.index)

View File

@@ -1,11 +1,17 @@
import { ClassSerializerInterceptor, ValidationPipe } from "@nestjs/common";
import {
ClassSerializerInterceptor,
Logger,
ValidationPipe,
} from "@nestjs/common";
import { NestFactory, Reflector } from "@nestjs/core";
import { NestExpressApplication } from "@nestjs/platform-express";
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
import * as bodyParser from "body-parser";
import * as cookieParser from "cookie-parser";
import { NextFunction, Request, Response } from "express";
import * as fs from "fs";
import { AppModule } from "./app.module";
import { ConfigService } from "./config/config.service";
import { DATA_DIRECTORY } from "./constants";
async function bootstrap() {
@@ -13,7 +19,16 @@ async function bootstrap() {
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
app.use(bodyParser.raw({ type: "application/octet-stream", limit: "20mb" }));
const config = app.get<ConfigService>(ConfigService);
app.use((req: Request, res: Response, next: NextFunction) => {
const chunkSize = config.get("share.chunkSize");
bodyParser.raw({
type: "application/octet-stream",
limit: `${chunkSize}B`,
})(req, res, next);
});
app.use(cookieParser());
app.set("trust proxy", true);
@@ -34,5 +49,8 @@ async function bootstrap() {
}
await app.listen(parseInt(process.env.PORT) || 8080);
const logger = new Logger("UnhandledAsyncError");
process.on("unhandledRejection", (e) => logger.error(e));
}
bootstrap();

View File

@@ -13,7 +13,7 @@ export class ReverseShareTokenWithShares extends OmitType(ReverseShareDTO, [
@Type(() => OmitType(MyShareDTO, ["recipients", "hasPassword"] as const))
shares: Omit<
MyShareDTO,
"recipients" | "files" | "from" | "fromList" | "hasPassword"
"recipients" | "files" | "from" | "fromList" | "hasPassword" | "size"
>[];
@Expose()

View File

@@ -0,0 +1,27 @@
import { OmitType } from "@nestjs/swagger";
import { Expose, plainToClass } from "class-transformer";
import { ShareDTO } from "./share.dto";
export class AdminShareDTO extends OmitType(ShareDTO, [
"files",
"from",
"fromList",
] as const) {
@Expose()
views: number;
@Expose()
createdAt: Date;
from(partial: Partial<AdminShareDTO>) {
return plainToClass(AdminShareDTO, partial, {
excludeExtraneousValues: true,
});
}
fromList(partial: Partial<AdminShareDTO>[]) {
return partial.map((part) =>
plainToClass(AdminShareDTO, part, { excludeExtraneousValues: true }),
);
}
}

View File

@@ -18,6 +18,10 @@ export class CreateShareDTO {
@Length(3, 50)
id: string;
@Length(3, 30)
@IsOptional()
name: string;
@IsString()
expiration: string;

View File

@@ -6,6 +6,9 @@ export class ShareDTO {
@Expose()
id: string;
@Expose()
name?: string;
@Expose()
expiration: Date;
@@ -23,6 +26,9 @@ export class ShareDTO {
@Expose()
hasPassword: boolean;
@Expose()
size: number;
from(partial: Partial<ShareDTO>) {
return plainToClass(ShareDTO, partial, { excludeExtraneousValues: true });
}

View File

@@ -20,9 +20,8 @@ export class CreateShareGuard extends JwtGuard {
if (!reverseShareTokenId) return false;
const isReverseShareTokenValid = await this.reverseShareService.isValid(
reverseShareTokenId,
);
const isReverseShareTokenValid =
await this.reverseShareService.isValid(reverseShareTokenId);
return isReverseShareTokenValid;
}

View File

@@ -5,9 +5,9 @@ import {
} from "@nestjs/common";
import { User } from "@prisma/client";
import { Request } from "express";
import { ConfigService } from "src/config/config.service";
import { PrismaService } from "src/prisma/prisma.service";
import { JwtGuard } from "../../auth/guard/jwt.guard";
import { ConfigService } from "src/config/config.service";
@Injectable()
export class ShareOwnerGuard extends JwtGuard {
@@ -34,10 +34,20 @@ export class ShareOwnerGuard extends JwtGuard {
if (!share) throw new NotFoundException("Share not found");
// Run the JWTGuard to set the user
await super.canActivate(context);
const user = request.user as User;
// If the user is an admin, allow access
if (user?.isAdmin) return true;
// If it's a anonymous share, allow access
if (!share.creatorId) return true;
if (!(await super.canActivate(context))) return false;
// If not signed in, deny access
if (!user) return false;
return share.creatorId == (request.user as User).id;
// If the user is the creator of the share, allow access
return share.creatorId == user.id;
}
}

View File

@@ -14,6 +14,7 @@ import { Throttle } from "@nestjs/throttler";
import { User } from "@prisma/client";
import { Request, Response } from "express";
import { GetUser } from "src/auth/decorator/getUser.decorator";
import { AdministratorGuard } from "src/auth/guard/isAdmin.guard";
import { JwtGuard } from "src/auth/guard/jwt.guard";
import { CreateShareDTO } from "./dto/createShare.dto";
import { MyShareDTO } from "./dto/myShare.dto";
@@ -25,10 +26,17 @@ import { ShareOwnerGuard } from "./guard/shareOwner.guard";
import { ShareSecurityGuard } from "./guard/shareSecurity.guard";
import { ShareTokenSecurity } from "./guard/shareTokenSecurity.guard";
import { ShareService } from "./share.service";
import { AdminShareDTO } from "./dto/adminShare.dto";
@Controller("shares")
export class ShareController {
constructor(private shareService: ShareService) {}
@Get("all")
@UseGuards(JwtGuard, AdministratorGuard)
async getAllShares() {
return new AdminShareDTO().fromList(await this.shareService.getShares());
}
@Get()
@UseGuards(JwtGuard)
async getMyShares(@GetUser() user: User) {
@@ -86,8 +94,9 @@ export class ShareController {
@Delete(":id")
@UseGuards(ShareOwnerGuard)
async remove(@Param("id") id: string) {
await this.shareService.remove(id);
async remove(@Param("id") id: string, @GetUser() user: User) {
const isDeleterAdmin = user?.isAdmin === true;
await this.shareService.remove(id, isDeleterAdmin);
}
@Throttle(10, 60)

View File

@@ -46,9 +46,8 @@ export class ShareService {
let expirationDate: Date;
// If share is created by a reverse share token override the expiration date
const reverseShare = await this.reverseShareService.getByToken(
reverseShareToken,
);
const reverseShare =
await this.reverseShareService.getByToken(reverseShareToken);
if (reverseShare) {
expirationDate = reverseShare.shareExpiration;
} else {
@@ -194,6 +193,22 @@ export class ShareService {
});
}
async getShares() {
const shares = await this.prisma.share.findMany({
orderBy: {
expiration: "desc",
},
include: { files: true, creator: true },
});
return shares.map((share) => {
return {
...share,
size: share.files.reduce((acc, file) => acc + parseInt(file.size), 0),
};
});
}
async getSharesByUser(userId: string) {
const shares = await this.prisma.share.findMany({
where: {
@@ -214,6 +229,7 @@ export class ShareService {
return shares.map((share) => {
return {
...share,
size: share.files.reduce((acc, file) => acc + parseInt(file.size), 0),
recipients: share.recipients.map((recipients) => recipients.email),
};
});
@@ -251,13 +267,14 @@ export class ShareService {
return share;
}
async remove(shareId: string) {
async remove(shareId: string, isDeleterAdmin = false) {
const share = await this.prisma.share.findUnique({
where: { id: shareId },
});
if (!share) throw new NotFoundException("Share not found");
if (!share.creatorId)
if (!share.creatorId && !isDeleterAdmin)
throw new ForbiddenException("Anonymous shares can't be deleted");
await this.fileService.deleteAllFiles(shareId);

View File

@@ -27,7 +27,8 @@ export class UserController {
// Own user operations
@Get("me")
@UseGuards(JwtGuard)
async getCurrentUser(@GetUser() user: User) {
async getCurrentUser(@GetUser() user?: User) {
if (!user) return null;
const userDTO = new UserDTO().from(user);
userDTO.hasPassword = !!user.password;
return userDTO;

View File

@@ -2,9 +2,10 @@ import { Module } from "@nestjs/common";
import { EmailModule } from "src/email/email.module";
import { UserController } from "./user.controller";
import { UserSevice } from "./user.service";
import { FileModule } from "src/file/file.module";
@Module({
imports: [EmailModule],
imports: [EmailModule, FileModule],
providers: [UserSevice],
controllers: [UserController],
})

View File

@@ -4,6 +4,7 @@ import * as argon from "argon2";
import * as crypto from "crypto";
import { EmailService } from "src/email/email.service";
import { PrismaService } from "src/prisma/prisma.service";
import { FileService } from "../file/file.service";
import { CreateUserDTO } from "./dto/createUser.dto";
import { UpdateUserDto } from "./dto/updateUser.dto";
@@ -12,6 +13,7 @@ export class UserSevice {
constructor(
private prisma: PrismaService,
private emailService: EmailService,
private fileService: FileService,
) {}
async list() {
@@ -74,6 +76,16 @@ export class UserSevice {
}
async delete(id: string) {
const user = await this.prisma.user.findUnique({
where: { id },
include: { shares: true },
});
if (!user) throw new BadRequestException("User not found");
await Promise.all(
user.shares.map((share) => this.fileService.deleteAllFiles(share.id)),
);
return await this.prisma.user.delete({ where: { id } });
}
}

View File

@@ -432,7 +432,7 @@
" const responseBody = pm.response.json();",
" pm.expect(responseBody).to.have.property(\"id\")",
" pm.expect(responseBody).to.have.property(\"expiration\")",
" pm.expect(Object.keys(responseBody).length).be.equal(3)",
" pm.expect(Object.keys(responseBody).length).be.equal(4)",
"});",
""
],
@@ -626,7 +626,7 @@
" const responseBody = pm.response.json();",
" pm.expect(responseBody).to.have.property(\"id\")",
" pm.expect(responseBody).to.have.property(\"expiration\")",
" pm.expect(Object.keys(responseBody).length).be.equal(3)",
" pm.expect(Object.keys(responseBody).length).be.equal(4)",
"});",
""
],

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "pingvin-share-frontend",
"version": "0.22.1",
"version": "0.25.0",
"scripts": {
"dev": "next dev",
"build": "next build",
@@ -9,46 +9,47 @@
"format": "prettier --end-of-line=auto --write \"src/**/*.ts*\""
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/react": "^11.11.4",
"@emotion/server": "^11.11.0",
"@mantine/core": "^6.0.17",
"@mantine/dropzone": "^6.0.17",
"@mantine/form": "^6.0.17",
"@mantine/hooks": "^6.0.17",
"@mantine/modals": "^6.0.17",
"@mantine/next": "^6.0.17",
"@mantine/notifications": "^6.0.17",
"axios": "^1.4.0",
"@mantine/core": "^6.0.21",
"@mantine/dropzone": "^6.0.21",
"@mantine/form": "^6.0.21",
"@mantine/hooks": "^6.0.21",
"@mantine/modals": "^6.0.21",
"@mantine/next": "^6.0.21",
"@mantine/notifications": "^6.0.21",
"axios": "^1.7.2",
"cookies-next": "^2.1.2",
"file-saver": "^2.0.5",
"jose": "^4.14.4",
"jose": "^4.15.5",
"jwt-decode": "^3.1.2",
"markdown-to-jsx": "^7.4.1",
"markdown-to-jsx": "^7.4.7",
"mime-types": "^2.1.35",
"moment": "^2.29.4",
"next": "^13.4.12",
"moment": "^2.30.1",
"next": "^14.2.3",
"next-cookies": "^2.0.3",
"next-http-proxy-middleware": "^1.2.5",
"next-http-proxy-middleware": "^1.2.6",
"next-pwa": "^5.6.0",
"p-limit": "^4.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.10.1",
"react-intl": "^6.4.4",
"sharp": "^0.32.4",
"yup": "^1.2.0"
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^4.12.0",
"react-intl": "^6.6.8",
"sharp": "^0.33.4",
"yup": "^1.4.0"
},
"devDependencies": {
"@types/mime-types": "^2.1.1",
"@types/node": "20.4.5",
"@types/react": "18.2.17",
"@types/react-dom": "18.2.7",
"axios": "^1.4.0",
"eslint": "8.46.0",
"eslint-config-next": "^13.4.12",
"eslint-config-prettier": "^8.9.0",
"prettier": "^3.0.0",
"tar": "^6.1.15",
"typescript": "^5.1.6"
"@types/mime-types": "^2.1.4",
"@types/node": "20.12.12",
"@types/react": "18.3.2",
"@types/react-dom": "18.3.0",
"@typescript-eslint/parser": "^7.10.0",
"axios": "^1.7.2",
"eslint": "8.57.0",
"eslint-config-next": "^13.5.6",
"eslint-config-prettier": "^8.10.0",
"prettier": "^3.2.5",
"tar": "^6.2.1",
"typescript": "^5.4.5"
}
}

View File

@@ -83,7 +83,7 @@ const CreateEnableTotpModal = ({
</span>
</Center>
<Tooltip label={t("account.modal.totp.clickToCopy")}>
<Tooltip label={t("common.button.clickToCopy")}>
<Button
onClick={() => {
navigator.clipboard.writeText(options.secret);

View File

@@ -17,13 +17,9 @@ const showShareInformationsModal = (
const t = translateOutsideContext();
const link = `${appUrl}/s/${share.id}`;
let shareSize: number = 0;
for (let file of share.files as FileMetaData[])
shareSize += parseInt(file.size);
const formattedShareSize = byteToHumanSizeString(shareSize);
const formattedShareSize = byteToHumanSizeString(share.size);
const formattedMaxShareSize = byteToHumanSizeString(maxShareSize);
const shareSizeProgress = (shareSize / maxShareSize) * 100;
const shareSizeProgress = (share.size / maxShareSize) * 100;
const formattedCreatedAt = moment(share.createdAt).format("LLL");
const formattedExpiration =
@@ -42,12 +38,18 @@ const showShareInformationsModal = (
</b>
{share.id}
</Text>
<Text size="sm">
<b>
<FormattedMessage id="account.shares.table.name" />:{" "}
</b>
{share.name || "-"}
</Text>
<Text size="sm">
<b>
<FormattedMessage id="account.shares.table.description" />:{" "}
</b>
{share.description || "No description"}
{share.description || "-"}
</Text>
<Text size="sm">
@@ -75,15 +77,15 @@ const showShareInformationsModal = (
</Text>
<Flex align="center" justify="center">
{shareSize / maxShareSize < 0.1 && (
{share.size / maxShareSize < 0.1 && (
<Text size="xs" style={{ marginRight: "4px" }}>
{formattedShareSize}
</Text>
)}
<Progress
value={shareSizeProgress}
label={shareSize / maxShareSize >= 0.1 ? formattedShareSize : ""}
style={{ width: shareSize / maxShareSize < 0.1 ? "70%" : "80%" }}
label={share.size / maxShareSize >= 0.1 ? formattedShareSize : ""}
style={{ width: share.size / maxShareSize < 0.1 ? "70%" : "80%" }}
size="xl"
radius="xl"
/>

View File

@@ -33,6 +33,7 @@ const LogoConfigInput = ({
value={logo}
onChange={(v) => setLogo(v)}
accept=".png"
// @ts-ignore (https://github.com/mantinedev/mantine/issues/5401)
placeholder={t("admin.config.general.logo.placeholder")}
/>
</Box>

View File

@@ -0,0 +1,149 @@
import {
ActionIcon,
Box,
Group,
MediaQuery,
Skeleton,
Table,
Text,
} from "@mantine/core";
import { useClipboard } from "@mantine/hooks";
import { useModals } from "@mantine/modals";
import moment from "moment";
import { TbLink, TbTrash } from "react-icons/tb";
import { FormattedMessage } from "react-intl";
import useConfig from "../../../hooks/config.hook";
import useTranslate from "../../../hooks/useTranslate.hook";
import { MyShare } from "../../../types/share.type";
import { byteToHumanSizeString } from "../../../utils/fileSize.util";
import toast from "../../../utils/toast.util";
import showShareLinkModal from "../../account/showShareLinkModal";
const ManageShareTable = ({
shares,
deleteShare,
isLoading,
}: {
shares: MyShare[];
deleteShare: (share: MyShare) => void;
isLoading: boolean;
}) => {
const modals = useModals();
const clipboard = useClipboard();
const config = useConfig();
const t = useTranslate();
return (
<Box sx={{ display: "block", overflowX: "auto" }}>
<Table verticalSpacing="sm">
<thead>
<tr>
<th>
<FormattedMessage id="account.shares.table.id" />
</th>
<th>
<FormattedMessage id="account.shares.table.name" />
</th>
<th>
<FormattedMessage id="admin.shares.table.username" />
</th>
<th>
<FormattedMessage id="account.shares.table.visitors" />
</th>
<th>
<FormattedMessage id="account.shares.table.size" />
</th>
<th>
<FormattedMessage id="account.shares.table.expiresAt" />
</th>
<th></th>
</tr>
</thead>
<tbody>
{isLoading
? skeletonRows
: shares.map((share) => (
<tr key={share.id}>
<td>{share.id}</td>
<td>{share.name}</td>
<td>
{share.creator ? (
share.creator.username
) : (
<Text color="dimmed">Anonymous</Text>
)}
</td>
<td>{share.views}</td>
<td>{byteToHumanSizeString(share.size)}</td>
<td>
{moment(share.expiration).unix() === 0
? "Never"
: moment(share.expiration).format("LLL")}
</td>
<td>
<Group position="right">
<ActionIcon
color="victoria"
variant="light"
size={25}
onClick={() => {
if (window.isSecureContext) {
clipboard.copy(
`${config.get("general.appUrl")}/s/${share.id}`,
);
toast.success(t("common.notify.copied"));
} else {
showShareLinkModal(
modals,
share.id,
config.get("general.appUrl"),
);
}
}}
>
<TbLink />
</ActionIcon>
<ActionIcon
variant="light"
color="red"
size="sm"
onClick={() => deleteShare(share)}
>
<TbTrash />
</ActionIcon>
</Group>
</td>
</tr>
))}
</tbody>
</Table>
</Box>
);
};
const skeletonRows = [...Array(10)].map((v, i) => (
<tr key={i}>
<td>
<Skeleton key={i} height={20} />
</td>
<MediaQuery smallerThan="md" styles={{ display: "none" }}>
<td>
<Skeleton key={i} height={20} />
</td>
</MediaQuery>
<td>
<Skeleton key={i} height={20} />
</td>
<td>
<Skeleton key={i} height={20} />
</td>
<td>
<Skeleton key={i} height={20} />
</td>
<td>
<Skeleton key={i} height={20} />
</td>
</tr>
));
export default ManageShareTable;

View File

@@ -25,6 +25,7 @@ import useTranslate from "../../hooks/useTranslate.hook";
import authService from "../../services/auth.service";
import { getOAuthIcon, getOAuthUrl } from "../../utils/oauth.util";
import toast from "../../utils/toast.util";
import { safeRedirectPath } from "../../utils/router.util";
const useStyles = createStyles((theme) => ({
or: {
@@ -98,7 +99,7 @@ const SignInForm = ({ redirectPath }: { redirectPath: string }) => {
);
} else {
await refreshUser();
router.replace(redirectPath);
router.replace(safeRedirectPath(redirectPath));
}
})
.catch(toast.axiosError);

View File

@@ -6,15 +6,16 @@ import {
PinInput,
Title,
} from "@mantine/core";
import { useForm, yupResolver } from "@mantine/form";
import { useRouter } from "next/router";
import { useState } from "react";
import { FormattedMessage } from "react-intl";
import * as yup from "yup";
import useTranslate from "../../hooks/useTranslate.hook";
import { useForm, yupResolver } from "@mantine/form";
import { useState } from "react";
import authService from "../../services/auth.service";
import toast from "../../utils/toast.util";
import { useRouter } from "next/router";
import useUser from "../../hooks/user.hook";
import authService from "../../services/auth.service";
import { safeRedirectPath } from "../../utils/router.util";
import toast from "../../utils/toast.util";
function TotpForm({ redirectPath }: { redirectPath: string }) {
const t = useTranslate();
@@ -46,7 +47,7 @@ function TotpForm({ redirectPath }: { redirectPath: string }) {
router.query.loginToken as string,
);
await refreshUser();
await router.replace(redirectPath);
await router.replace(safeRedirectPath(redirectPath));
} catch (e) {
toast.axiosError(e);
form.setFieldError("code", "error");

View File

@@ -53,10 +53,18 @@ function CopyTextField(props: { link: string }) {
</ActionIcon>
</a>
</Tooltip>
{window.isSecureContext && (
<ActionIcon onClick={copyLink}>
{checkState ? <TbCheck /> : <TbCopy />}
</ActionIcon>
<Tooltip
label={t("common.button.clickToCopy")}
position="top"
offset={-2}
openDelay={200}
>
<ActionIcon onClick={copyLink}>
{checkState ? <TbCheck /> : <TbCopy />}
</ActionIcon>
</Tooltip>
)}
</>
}

View File

@@ -36,12 +36,12 @@ const Dropzone = ({
title,
isUploading,
maxShareSize,
showCreateUploadModalCallback,
onFilesChanged,
}: {
title?: string;
isUploading: boolean;
maxShareSize: number;
showCreateUploadModalCallback: (files: FileUpload[]) => void;
onFilesChanged: (files: FileUpload[]) => void;
}) => {
const t = useTranslate();
@@ -69,7 +69,7 @@ const Dropzone = ({
newFile.uploadingProgress = 0;
return newFile;
});
showCreateUploadModalCallback(files);
onFilesChanged(files);
}
}}
className={classes.dropzone}

View File

@@ -1,22 +1,19 @@
import { Button, Group } from "@mantine/core";
import { useModals } from "@mantine/modals";
import { cleanNotifications } from "@mantine/notifications";
import { AxiosError } from "axios";
import { useRouter } from "next/router";
import pLimit from "p-limit";
import { useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import { FormattedMessage } from "react-intl";
import Dropzone from "../../components/upload/Dropzone";
import FileList from "../../components/upload/FileList";
import showCompletedUploadModal from "../../components/upload/modals/showCompletedUploadModal";
import useConfig from "../../hooks/config.hook";
import useTranslate from "../../hooks/useTranslate.hook";
import shareService from "../../services/share.service";
import { FileListItem, FileMetaData, FileUpload } from "../../types/File.type";
import toast from "../../utils/toast.util";
import { useRouter } from "next/router";
const promiseLimit = pLimit(3);
const chunkSize = 10 * 1024 * 1024; // 10MB
let errorToastShown = false;
const EditableUpload = ({
@@ -33,6 +30,8 @@ const EditableUpload = ({
const router = useRouter();
const config = useConfig();
const chunkSize = useRef(parseInt(config.get("share.chunkSize")));
const [existingFiles, setExistingFiles] =
useState<Array<FileMetaData & { deleted?: boolean }>>(savedFiles);
const [uploadingFiles, setUploadingFiles] = useState<FileUpload[]>([]);
@@ -66,7 +65,7 @@ const EditableUpload = ({
const fileUploadPromises = files.map(async (file, fileIndex) =>
// Limit the number of concurrent uploads to 3
promiseLimit(async () => {
let fileId: string;
let fileId: string | undefined;
const setFileProgress = (progress: number) => {
setUploadingFiles((files) =>
@@ -81,38 +80,30 @@ const EditableUpload = ({
setFileProgress(1);
let chunks = Math.ceil(file.size / chunkSize);
let chunks = Math.ceil(file.size / chunkSize.current);
// If the file is 0 bytes, we still need to upload 1 chunk
if (chunks == 0) chunks++;
for (let chunkIndex = 0; chunkIndex < chunks; chunkIndex++) {
const from = chunkIndex * chunkSize;
const to = from + chunkSize;
const from = chunkIndex * chunkSize.current;
const to = from + chunkSize.current;
const blob = file.slice(from, to);
try {
await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async (event) =>
await shareService
.uploadFile(
shareId,
event,
{
id: fileId,
name: file.name,
},
chunkIndex,
chunks,
)
.then((response) => {
fileId = response.id;
resolve(response);
})
.catch(reject);
reader.readAsDataURL(blob);
});
await shareService
.uploadFile(
shareId,
blob,
{
id: fileId,
name: file.name,
},
chunkIndex,
chunks,
)
.then((response) => {
fileId = response.id;
});
setFileProgress(((chunkIndex + 1) / chunks) * 100);
} catch (e) {
@@ -226,7 +217,7 @@ const EditableUpload = ({
<Dropzone
title={t("share.edit.append-upload")}
maxShareSize={maxShareSize}
showCreateUploadModalCallback={appendFiles}
onFilesChanged={appendFiles}
isUploading={isUploading}
/>
{existingAndUploadedFiles.length > 0 && (

View File

@@ -92,11 +92,16 @@ const CreateUploadModalBody = ({
.matches(new RegExp("^[a-zA-Z0-9_-]*$"), {
message: t("upload.modal.link.error.invalid"),
}),
name: yup
.string()
.transform((value) => value || undefined)
.min(3, t("common.error.too-short", { length: 3 }))
.max(30, t("common.error.too-long", { length: 30 })),
password: yup
.string()
.transform((value) => value || undefined)
.min(3)
.max(30),
.min(3, t("common.error.too-short", { length: 3 }))
.max(30, t("common.error.too-long", { length: 30 })),
maxViews: yup
.number()
.transform((value) => value || undefined)
@@ -105,6 +110,7 @@ const CreateUploadModalBody = ({
const form = useForm({
initialValues: {
name: undefined,
link: generatedLink,
recipients: [] as string[],
password: undefined,
@@ -154,6 +160,7 @@ const CreateUploadModalBody = ({
uploadCallback(
{
id: values.link,
name: values.name,
expiration: expirationString,
recipients: values.recipients,
description: values.description,
@@ -308,14 +315,21 @@ const CreateUploadModalBody = ({
<Accordion>
<Accordion.Item value="description" sx={{ borderBottom: "none" }}>
<Accordion.Control>
<FormattedMessage id="upload.modal.accordion.description.title" />
<FormattedMessage id="upload.modal.accordion.name-and-description.title" />
</Accordion.Control>
<Accordion.Panel>
<Stack align="stretch">
<TextInput
variant="filled"
placeholder={t(
"upload.modal.accordion.name-and-description.name.placeholder",
)}
{...form.getInputProps("name")}
/>
<Textarea
variant="filled"
placeholder={t(
"upload.modal.accordion.description.placeholder",
"upload.modal.accordion.name-and-description.description.placeholder",
)}
{...form.getInputProps("description")}
/>

View File

@@ -1,3 +1,4 @@
import arabic from "./translations/ar-EG";
import danish from "./translations/da-DK";
import german from "./translations/de-DE";
import greek from "./translations/el-GR";
@@ -5,8 +6,10 @@ import english from "./translations/en-US";
import spanish from "./translations/es-ES";
import finnish from "./translations/fi-FI";
import french from "./translations/fr-FR";
import hungarian from "./translations/hu-HU";
import italian from "./translations/it-IT";
import japanese from "./translations/ja-JP";
import korean from "./translations/ko-KR";
import dutch from "./translations/nl-BE";
import polish from "./translations/pl-PL";
import portuguese from "./translations/pt-BR";
@@ -15,6 +18,7 @@ import slovenian from "./translations/sl-SI";
import serbian from "./translations/sr-SP";
import swedish from "./translations/sv-SE";
import thai from "./translations/th-TH";
import ukrainian from "./translations/uk-UA";
import chineseSimplified from "./translations/zh-CN";
import chineseTraditional from "./translations/zh-TW";
@@ -69,6 +73,11 @@ export const LOCALES = {
code: "ru-RU",
messages: russian,
},
UKRAINIAN: {
name: "Українська",
code: "uk-UA",
messages: ukrainian,
},
THAI: {
name: "ไทย",
code: "th-TH",
@@ -114,4 +123,19 @@ export const LOCALES = {
code: "sl-SI",
messages: slovenian,
},
ARABIC: {
name: "العربية",
code: "ar-EG",
messages: arabic,
},
HUNGARIAN: {
name: "Hungarian",
code: "hu-HU",
messages: hungarian,
},
KOREAN: {
name: "한국어",
code: "ko-KR",
messages: korean,
},
};

View File

@@ -0,0 +1,512 @@
export default {
// Navbar
"navbar.upload": "رفع",
"navbar.signin": "تسجيل الدخول",
"navbar.home": "الصفحة الرئيسية",
"navbar.signup": "إنشاء حساب",
"navbar.links.shares": "مشاركاتي",
"navbar.links.reverse": "مشاركاتي العكسية",
"navbar.avatar.account": "حسابي",
"navbar.avatar.admin": "الإدارة",
"navbar.avatar.signout": "تسجيل الخروج",
// END navbar
// /
"home.title": "منصة لمشاركة الملفات <h>باستضافة ذاتية</h>.",
"home.description":
"أحقًا تريد تسليم ملفاتك الشخصية لطرف ثالث مثل WeTransfer؟",
"home.bullet.a.name": "استضافة ذاتية",
"home.bullet.a.description": "قم باستضافة Pingvin Share على جهازك.",
"home.bullet.b.name": "الخصوصية",
"home.bullet.b.description":
"ملفاتك تخصّك وحدك فقط، ولا ينبغي أبدًا أن تقع بأيدي طرفٍ ثالث.",
"home.bullet.c.name": "ليس هناك أية قيود على حجم الملفات",
"home.bullet.c.description":
"ارفع أي ملف تريده مهما كان حجمه كبيرًا. إن مساحة قرصك الصلب هي المحدد الوحيد هنا.",
"home.button.start": "ابدأ",
"home.button.source": "النص البرمجي المصدري",
// END /
// /auth/signin
"signin.title": "أهلًا بعودتك",
"signin.description": "ليس لديك حساب؟",
"signin.button.signup": "إنشاء حساب",
"signin.input.email-or-username": "البريد أو اسم المستخدم",
"signin.input.email-or-username.placeholder": "بريدك أو اسم المستخدم",
"signin.input.password": "كلمة السر",
"signin.input.password.placeholder": "كلمة السر",
"signin.button.submit": "تسجيل الدخول",
"signIn.notify.totp-required.title": "إن المصادقة الثنائية ضرورية",
"signIn.notify.totp-required.description": "فضلًا أدخل رمز المصادقة الثنائية",
"signIn.oauth.or": "أو",
"signIn.oauth.github": "GitHub",
"signIn.oauth.google": "Google",
"signIn.oauth.microsoft": "Microsoft",
"signIn.oauth.discord": "Discord",
"signIn.oauth.oidc": "OpenID",
// END /auth/signin
// /auth/signup
"signup.title": "أنشئ حسابًا",
"signup.description": "لديك حساب بالفعل؟",
"signup.button.signin": "تسجيل الدخول",
"signup.input.username": "اسم المستخدم",
"signup.input.username.placeholder": "اسم المستخدم",
"signup.input.email": "البريد",
"signup.input.email.placeholder": "بريدك",
"signup.button.submit": "لنبدأ",
// END /auth/signup
// /auth/totp
"totp.title": "كلمة المرور لمرة واحدة المؤقتة TOTP",
"totp.button.signIn": "تسجيل الدخول",
// END /auth/totp
// /auth/reset-password
"resetPassword.title": "نسيت كلمة سرّك؟",
"resetPassword.description": "اكتب بريدك لتعيد تعيين كلمة السر.",
"resetPassword.notify.success":
"إذا كان هذا البريد مسجلًا لدينا فستصله الآن رسالة فيها رابط لإعادة تعيين كلمة السرّ.",
"resetPassword.button.back": "العودة لصفحة تسجيل الدخول",
"resetPassword.text.resetPassword": "إعادة تعيين كلمة السر",
"resetPassword.text.enterNewPassword": "أدخل كلمة السر الجديدة",
"resetPassword.input.password": "كلمة السر الجديدة",
"resetPassword.notify.passwordReset": "أعدتَ تعيين كلمة السر بنجاح.",
// /account
"account.title": "حسابي",
"account.card.info.title": "معلومات الحساب",
"account.card.info.username": "اسم المستخدم",
"account.card.info.email": "البريد",
"account.notify.info.success": "تم تحديث الحساب بنجاح",
"account.card.password.title": "كلمة السر",
"account.card.password.old": "كلمة السر القديمة",
"account.card.password.new": "كلمة السر الجديدة",
"account.card.password.noPasswordSet":
"ليس لحسابك كلمة سر. إذا أردت تسجيل الدخول باستخدام البريد وكلمة سر، فعليك أن تُعيِّن كلمة سر.",
"account.notify.password.success": "غيرت كلمة السر بنجاح",
"account.card.oauth.title": "الدخول بحساب تواصل اجتماعي",
"account.card.oauth.github": "GitHub",
"account.card.oauth.google": "Google",
"account.card.oauth.microsoft": "Microsoft",
"account.card.oauth.discord": "Discord",
"account.card.oauth.oidc": "OpenID",
"account.card.oauth.link": "ربط",
"account.card.oauth.unlink": "فك الربط",
"account.card.oauth.unlinked": "تم فك الربط",
"account.modal.unlink.title": "فك ربط الحساب",
"account.modal.unlink.description":
"قد يؤدي إلغاء ربط حساباتك الاجتماعية إلى فقدان وصولك لحسابك إذا كنت لا تتذكر اسم المستخدم وكلمة السر الخاصة بك.",
"account.notify.oauth.unlinked.success": "تم فك الربط بنجاح",
"account.card.security.title": "الأمان",
"account.card.security.totp.enable.description":
"اكتب كلمة سرّك لبدء تمكين TOTP",
"account.card.security.totp.disable.description":
"اكتب كلمة سرّك لتعطيل TOTP",
"account.card.security.totp.button.start": "ابدأ",
"account.modal.totp.title": "تمكين TOTP",
"account.modal.totp.step1": "الخطوة 1: أضف تطبيق المصادقة",
"account.modal.totp.step2": "الخطوة 2: تحقّق من صحة رمزك",
"account.modal.totp.enterManually": "أدخل يدوياً",
"account.modal.totp.code": "الرمز",
"common.button.clickToCopy": "انقر للنسخ",
"account.modal.totp.verify": "تحقق",
"account.notify.totp.disable": "تم تعطيل TOTP بنجاح",
"account.notify.totp.enable": "تم تمكين TOTP بنجاح",
"account.card.language.title": "اللغة",
"account.card.language.description":
"يقوم المجتمع بترجمة هذا المشروع. ربما بعض اللغات لم تكتمل ترجمتها بعد.",
"account.card.color.title": "نظام الألوان",
// ThemeSwitcher.tsx
"account.theme.dark": "داكن",
"account.theme.light": "فاتح",
"account.theme.system": "حسب النظام",
"account.button.delete": "حذف الحساب",
"account.modal.delete.title": "حذف الحساب",
"account.modal.delete.description":
"هل تريد حقاً حذف حسابك بما في ذلك جميع مشاركاتك النشطة؟",
// END /account
// /account/shares
"account.shares.title": "مشاركاتي",
"account.shares.title.empty": "المكان خالٍ هنا 👀",
"account.shares.description.empty": "ليس لديك أي مشاركات.",
"account.shares.button.create": "أنشئ واحدًا",
"account.shares.info.title": "معلومات المشاركة",
"account.shares.table.id": "الرقم التعريفي",
"account.shares.table.name": "الاسم",
"account.shares.table.description": "الوصف",
"account.shares.table.visitors": "الزوار",
"account.shares.table.expiresAt": "تاريخ انتهاء الصلاحية",
"account.shares.table.createdAt": "تاريخ الإنشاء",
"account.shares.table.size": "الحجم",
"account.shares.modal.share-informations": "معلومات المشاركة",
"account.shares.modal.share-link": "رابط المشاركة",
"account.shares.modal.delete.title": "حذف المشاركة {share}",
"account.shares.modal.delete.description": "هل تريد حذف هذه المشاركة حقاً؟",
// END /account/shares
// /account/reverseShares
"account.reverseShares.title": "المشاركات العكسية",
"account.reverseShares.description":
"تسمح لك المشاركة العكسية بإنشاء رابط فريد يسمح للمستخدمين الخارجيين بإنشاء مشاركة.",
"account.reverseShares.title.empty": "المكان خالٍ هنا 👀",
"account.reverseShares.description.empty": "ليس لديك أي مشاركات عكسية.",
// showCreateReverseShareModal.tsx
"account.reverseShares.modal.title": "إنشاء مشاركة عكسية",
"account.reverseShares.modal.expiration.label": "انتهاء الصلاحية",
"account.reverseShares.modal.expiration.minute-singular": "دقيقة",
"account.reverseShares.modal.expiration.minute-plural": "دقائق",
"account.reverseShares.modal.expiration.hour-singular": "ساعة",
"account.reverseShares.modal.expiration.hour-plural": "ساعات",
"account.reverseShares.modal.expiration.day-singular": "يوم",
"account.reverseShares.modal.expiration.day-plural": "أيام",
"account.reverseShares.modal.expiration.week-singular": "أسبوع",
"account.reverseShares.modal.expiration.week-plural": "أسابيع",
"account.reverseShares.modal.expiration.month-singular": "شهر",
"account.reverseShares.modal.expiration.month-plural": "أشهر",
"account.reverseShares.modal.expiration.year-singular": "سنة",
"account.reverseShares.modal.expiration.year-plural": "سنوات",
"account.reverseShares.modal.max-size.label": "الحد الأقصى لحجم المشاركة",
"account.reverseShares.modal.send-email": "أرسل إشعارًا بالبريد",
"account.reverseShares.modal.send-email.description":
"إرسال إشعار بالبريد الإلكتروني عند إنشاء مشاركة باستخدام رابط المشاركة العكسي هذا.",
"account.reverseShares.modal.max-use.label": "الحد الأقصى لعدد الاستخدامات",
"account.reverseShares.modal.max-use.description":
"أقصى عدد من المرّات التي يمكن فيها استخدام هذا الرابط لإنشاء مشاركة.",
"account.reverseShare.never-expires":
"لن تنتهي صلاحية هذه المشاركة العكسية أبدًا.",
"account.reverseShare.expires-on":
"هذه المشاركة العكسية ستنتهي صلاحيتها في {expiration}.",
"account.reverseShares.table.no-shares": "لم يتم إنشاء أي مشاركة بعد",
"account.reverseShares.table.count.singular": "مشاركة",
"account.reverseShares.table.count.plural": "مشاركات",
"account.reverseShares.table.shares": "مشاركات",
"account.reverseShares.table.remaining": "الاستخدامات المتبقية",
"account.reverseShares.table.max-size": "الحد الأقصى لحجم المشاركة",
"account.reverseShares.table.expires": "تاريخ انتهاء الصلاحية",
"account.reverseShares.modal.reverse-share-link": "رابط المشاركة العكسية",
"account.reverseShares.modal.delete.title": "حذف المشاركة العكسية",
"account.reverseShares.modal.delete.description":
"هل تريد حقاً حذف هذه المشاركة العكسية؟ إذا قمت بذلك، فسيتم حذف المشاركات المرتبطة بها أيضاً.",
// END /account/reverseShares
// /admin
"admin.title": "الإدارة",
"admin.button.users": "إدارة المستخدم",
"admin.button.shares": "إدارة المشاركة",
"admin.button.config": "الإعدادات",
"admin.version": "الإصدار",
// END /admin
// /admin/users
"admin.users.title": "إدارة المستخدم",
"admin.users.table.username": "اسم المستخدم",
"admin.users.table.email": "البريد",
"admin.users.table.admin": "المدير",
"admin.users.edit.update.title": "تحديث المستخدم {username}",
"admin.users.edit.update.admin-privileges": "صلاحيات المدير",
"admin.users.edit.update.change-password.title": "تغيير كلمة السر",
"admin.users.edit.update.change-password.field": "كلمة السر الجديدة",
"admin.users.edit.update.change-password.button": "حفظ كلمة السر الجديدة",
"admin.users.edit.update.notify.password.success": "غيرت كلمة السر بنجاح",
"admin.users.edit.delete.title": "حذف المستخدم {username}",
"admin.users.edit.delete.description":
"هل تريد حقاً حذف هذا المستخدم وكل مشاركاته؟",
// showCreateUserModal.tsx
"admin.users.modal.create.title": "أنشئ مستخدمًا",
"admin.users.modal.create.username": "اسم المستخدم",
"admin.users.modal.create.email": "البريد",
"admin.users.modal.create.password": "كلمة السر",
"admin.users.modal.create.manual-password": "تعيين كلمة السر يدوياً",
"admin.users.modal.create.manual-password.description":
"بدون هذا الخيار، سيتلقى المستخدم رسالة بريد إلكتروني فيها رابط لتعيين كلمة السر الخاصة به.",
"admin.users.modal.create.admin": "صلاحيات المدير",
"admin.users.modal.create.admin.description":
"مع هذا الخيار، سيتمكن المستخدم من الدخول إلى لوحة الإدارة.",
// END /admin/users
// /admin/shares
"admin.shares.title": "إدارة المشاركة",
"admin.shares.table.id": "معرّف المشاركة",
"admin.shares.table.username": "المُنشئ",
"admin.shares.table.visitors": "الزوار",
"admin.shares.table.expires": "تاريخ انتهاء الصلاحية",
"admin.shares.edit.delete.title": "حذف المشاركة {id}",
"admin.shares.edit.delete.description": "هل تريد حذف هذه المشاركة حقاً؟",
// END /admin/shares
// /upload
"upload.title": "رفع",
"upload.notify.generic-error": "حدث خطأ أثناء إنهاء مشاركتك.",
"upload.notify.count-failed": "فشل رفع {count} ملفات. تجري المحاولة مجددًا.",
// Dropzone.tsx
"upload.dropzone.title": "رفع الملفات",
"upload.dropzone.description":
"اسحب الملفات إلى هنا لبدء مشاركتك. يمكننا فقط قبول الملفات التي لا يزيد حجمها عن {maxSize} بالمجمل.",
"upload.dropzone.notify.file-too-big":
"تتجاوز ملفاتك الحجم الأقصى للمشاركة والذي هو {maxSize}.",
// FileList.tsx
"upload.filelist.name": "الاسم",
"upload.filelist.size": "الحجم",
// showCreateUploadModal.tsx
"upload.modal.title": "إنشاء مشاركة",
"upload.modal.link.error.invalid":
"يمكن أن يحتوي فقط على الأحرف والأرقام والشرطات السفلية والواصلات",
"upload.modal.link.error.taken": "هذا الرابط مستخدم مسبقاً",
"upload.modal.not-signed-in": "لم تقم بتسجيل الدخول",
"upload.modal.not-signed-in-description":
"لن تتمكن من حذف مشاركتك يدوياً أو عرض عدد الزوار.",
"upload.modal.expires.never": "أبدًا",
"upload.modal.expires.never-long": "لا تنتهي الصلاحية أبداً",
"upload.modal.expires.error.too-long":
"انتهاء الصلاحية يتجاوز الحد الأقصى لتاريخ انتهاء الصلاحية والذي هو {max}.",
"upload.modal.link.label": "الرابط",
"upload.modal.expires.label": "انتهاء الصلاحية",
"upload.modal.expires.minute-singular": "دقيقة",
"upload.modal.expires.minute-plural": "دقائق",
"upload.modal.expires.hour-singular": "ساعة",
"upload.modal.expires.hour-plural": "ساعات",
"upload.modal.expires.day-singular": "يوم",
"upload.modal.expires.day-plural": "أيام",
"upload.modal.expires.week-singular": "أسبوع",
"upload.modal.expires.week-plural": "أسابيع",
"upload.modal.expires.month-singular": "شهر",
"upload.modal.expires.month-plural": "أشهر",
"upload.modal.expires.year-singular": "سنة",
"upload.modal.expires.year-plural": "سنوات",
"upload.modal.accordion.name-and-description.title": "الاسم والوصف",
"upload.modal.accordion.name-and-description.name.placeholder": "الاسم",
"upload.modal.accordion.name-and-description.description.placeholder":
"ملاحظة لمستقبلي هذه المشاركة",
"upload.modal.accordion.email.title": "مستلمو البريد الإلكتروني",
"upload.modal.accordion.email.placeholder": "أدخل مستلمي البريد",
"upload.modal.accordion.email.invalid-email": "عنوان البريد غير صحيح",
"upload.modal.accordion.security.title": "خيارات الأمان",
"upload.modal.accordion.security.password.label": "الحماية بكلمة السر",
"upload.modal.accordion.security.password.placeholder": "لا توجد كلمة سر",
"upload.modal.accordion.security.max-views.label": "الحد الأقصى للمشاهدات",
"upload.modal.accordion.security.max-views.placeholder": "لا يوجد حد",
// showCompletedUploadModal.tsx
"upload.modal.completed.never-expires": "لن تنتهي صلاحية هذه المشاركة أبدًا.",
"upload.modal.completed.expires-on":
"هذه المشاركة ستنتهي صلاحيتها في {expiration}.",
"upload.modal.completed.share-ready": "المشاركة جاهزة",
// END /upload
// /share/[id]
"share.title": "المشاركة {shareId}",
"share.description": "انظر ما الذي شاركته معك!",
"share.error.visitor-limit-exceeded.title": "تم تجاوز حد المشاهدات",
"share.error.visitor-limit-exceeded.description":
"تم تجاوز الحد الأقصى لزوار هذه المشاركة.",
"share.error.removed.title": "تمت إزالة المشاركة",
"share.error.not-found.title": "المشاركة غير موجودة",
"share.error.not-found.description": "المشاركة التي تبحث عنها غير موجودة.",
"share.modal.password.title": "كلمة السر مطلوبة",
"share.modal.password.description":
"للوصول إلى هذه المشاركة الرجاء إدخال كلمة سر المشاركة.",
"share.modal.password": "كلمة السر",
"share.modal.error.invalid-password": "كلمة السر غير صحيحة",
"share.button.download-all": "تنزيل الكل",
"share.notify.download-all-preparing":
"يتم تحضير المشاركة. حاول مرة أخرى في بضع دقائق.",
"share.modal.file-link": "رابط الملف",
"share.table.name": "الاسم",
"share.table.size": "الحجم",
"share.modal.file-preview.error.not-supported.title": "المعاينة غير مدعومة",
"share.modal.file-preview.error.not-supported.description":
"معاينة هذا النوع من الملفات غير مدعومة. الرجاء تنزيل الملف لعرضه.",
// END /share/[id]
// /share/[id]/edit
"share.edit.title": "تحرير {shareId}",
"share.edit.append-upload": "إضافة ملف",
"share.edit.notify.generic-error": "حدث خطأ أثناء إنهاء مشاركتك.",
"share.edit.notify.save-success": "تم تحديث المشاركة بنجاح",
// END /share/[id]/edit
// /admin/config
"admin.config.title": "الإعدادات",
"admin.config.category.general": "عام",
"admin.config.category.share": "مشاركة",
"admin.config.category.email": "البريد",
"admin.config.category.smtp": "بروتوكول نقل البريد البسيط SMTP",
"admin.config.category.oauth": "الدخول بحساب تواصل اجتماعي",
"admin.config.general.app-name": "اسم التطبيق",
"admin.config.general.app-name.description": "اسم التطبيق",
"admin.config.general.app-url": "رابط التطبيق",
"admin.config.general.app-url.description":
"الرابط الذي تكون مشاركة Pingvin صالحة عليه",
"admin.config.general.show-home-page": "إظهار الصفحة الرئيسية",
"admin.config.general.show-home-page.description":
"تحديد ما إذا كان سيتم عرض الصفحة الرئيسية",
"admin.config.general.logo": "الشعار",
"admin.config.general.logo.description":
"يمكنك تغيير شعارك عن طريق تحميل صورة جديدة. يجب أن تكون الصورة PNG ويجب أن يكون تنسيقها 1:1.",
"admin.config.general.logo.placeholder": "اختر صورة",
"admin.config.email.enable-share-email-recipients":
"تفعيل مستلمي البريد الإلكتروني لهذه المشاركة",
"admin.config.email.enable-share-email-recipients.description":
"السماح لرسائل البريد بأن تُشارك المستلمين. لا تفعّل هذا الخيار ما لم تفعّل SMTP مسبقًا.",
"admin.config.email.share-recipients-subject":
"عنوان الرسالة لمستلمي المشاركة",
"admin.config.email.share-recipients-subject.description":
"عنوان البريد الذي سيُرسَل لمستقبِلي المشاركة.",
"admin.config.email.share-recipients-message": "رسالتك لمستقبِلي المشاركة",
"admin.config.email.share-recipients-message.description":
"الرسالة التي ستُرسل لمستقبِلي المشاركة. يمكنك استخدام هذه المتغيرات:\n{creator} - اسم المستخدم الذي أنشأ المشاركة\n{shareUrl} - رابط المشاركة\n{desc} - وصف المشاركة\n{expires} - تاريخ انتهاء صلاحية المشاركة\nستتم كتابة قيم هذه المتغيرات تلقائيًا.",
"admin.config.email.reverse-share-subject": "عنوان المشاركة العكسية",
"admin.config.email.reverse-share-subject.description":
"عنوان البريد الذي سيُرسل عندما يُنشئ شخص ما مشاركةً باستخدام رابط المشاركة العكسية الخاص بك.",
"admin.config.email.reverse-share-message": "رسالة المشاركة العكسية",
"admin.config.email.reverse-share-message.description":
"الرسالة التي ستُرسل عندما يُنشئ شخص ما مشاركة باستخدام رابط المشاركة الخاص بك. سيُوضع اسم المُنشِئ ورابط المشاركة مكان {shareUrl}.",
"admin.config.email.reset-password-subject": "رسالة إعادة تعيين كلمة السر",
"admin.config.email.reset-password-subject.description":
"عنوان البريد الذي سيُرسل حين يطلب مستخدم ما إعادة تعيين كلمة سرّه.",
"admin.config.email.reset-password-message": "رسالة إعادة تعيين كلمة السر",
"admin.config.email.reset-password-message.description":
"الرسالة التي ستُرسل عندما يطلب المستخدم إعادة تعيين كلمة سرّه. سيُوضع رابط إعادة تعيين كلمة السر مكان {url}.",
"admin.config.email.invite-subject": "عنوان الدعوة",
"admin.config.email.invite-subject.description":
"عنوان البريد الذي سيُرسل عندما يقوم المشرف بدعوة مستخدم ما.",
"admin.config.email.invite-message": "رسالة الدعوة",
"admin.config.email.invite-message.description":
"الرسالة التي ستُرسل عندما يدعو مشرفٌ مستخدمًا. سيُوضع رابط الدعوة مكان {url} وكلمة السر مكان {password}.",
"admin.config.share.allow-registration": "السماح بالتسجيل",
"admin.config.share.allow-registration.description": "إتاحة تسجيل حساب جديد",
"admin.config.share.allow-unauthenticated-shares":
"السماح بالمشاركات غير المصادق عليها",
"admin.config.share.allow-unauthenticated-shares.description":
"إتاحة إنشاء المشاركات للمستخدمين غير الموثقين",
"admin.config.share.max-expiration": "أبعد زمن لانتهاء الصلاحية",
"admin.config.share.max-expiration.description":
"أطول زمن لانتهاء صلاحية المشاركات بالساعات. الصفر يعني أن المشاركة لن تنتهي صلاحيتها.",
"admin.config.share.max-size": "أكبر حجم",
"admin.config.share.max-size.description": "أكبر حجم للمشاركة مقيسًا بالبايت",
"admin.config.share.zip-compression-level": "مستوى ضغط الZip",
"admin.config.share.zip-compression-level.description":
"ضبط الميزان بين حجم الملف وسرعة الضغط. يمكنك إدخال قيم بين 0 إلى 9، حيث 0 تعني بدون ضغط و9 تعني أقصى ضغط. ",
"admin.config.share.chunk-size": "حجم القطعة",
"admin.config.share.chunk-size.description":
"ضبط حجم القطعة (بالبايت) لملفاتك المرفوعة للموازنة بين الكفاءة والفعالية حسب قوة اتصالك بالإنترنت. القطع الأصغر يمكن أن ترفع معدل النجاح في حال كان اتصالك بالإنترنت غير مستقر، بينما القطع الأكبر يمكنها أن تُسرّع رفع الملفات في حال كان الاتصال بالإنترنت مستقرًا.",
"admin.config.smtp.enabled": "مفعل",
"admin.config.smtp.enabled.description":
"تفعيل الـSMTP. لا تفعّله إلا إذا قمت بإدخال المضيف، والمنفذ، والبريد الإلكتروني، واسم المستخدم، وكلمة السر لخادم الـSMTP.",
"admin.config.smtp.host": "المُضيف",
"admin.config.smtp.host.description": "مضيف خادم الـSMTP",
"admin.config.smtp.port": "المنفذ",
"admin.config.smtp.port.description": "منفذ خادم الـSMTP",
"admin.config.smtp.email": "البريد الإلكتروني",
"admin.config.smtp.email.description":
"عنوان البريد الذي ستُرسَل الرسائل منه",
"admin.config.smtp.username": "اسم المستخدم",
"admin.config.smtp.username.description": "اسم المستخدم لخادم الـSMTP",
"admin.config.smtp.password": "كلمة السر",
"admin.config.smtp.password.description": "كلمة السر لخادم الـSMTP",
"admin.config.smtp.button.test": "إرسال رسالة بريد تجريبية",
"admin.config.oauth.allow-registration": "السماح بتسجيل الحسابات الجديدة",
"admin.config.oauth.allow-registration.description":
"السماح للمستخدمين بالدخول بواسطة حساباتهم الاجتماعية",
"admin.config.oauth.ignore-totp": "تجاهل TOTP",
"admin.config.oauth.ignore-totp.description":
"تجاهل TOTP إذا دخل المستخدم بحسابه الاجتماعي",
"admin.config.oauth.github-enabled": "GitHub",
"admin.config.oauth.github-enabled.description":
"تفعيل خيار الدخول بحساب GitHub",
"admin.config.oauth.github-client-id": "GitHub Client ID",
"admin.config.oauth.github-client-id.description":
"معرف العميل لتطبيق GitHub OAuth",
"admin.config.oauth.github-client-secret": "الرمز السرّي لـGitHub Client",
"admin.config.oauth.github-client-secret.description":
"الرّمز السرّي للعميل لتطبيق GitHub OAuth",
"admin.config.oauth.google-enabled": "Google",
"admin.config.oauth.google-enabled.description":
"تفعيل خيار الدخول بحساب Google",
"admin.config.oauth.google-client-id": "Google Client ID",
"admin.config.oauth.google-client-id.description":
"معرف العميل لتطبيق Google OAuth",
"admin.config.oauth.google-client-secret": "الرمز السرّي لـ Google Client",
"admin.config.oauth.google-client-secret.description":
"الرّمز السرّي للعميل لتطبيق Google OAuth",
"admin.config.oauth.microsoft-enabled": "Microsoft",
"admin.config.oauth.microsoft-enabled.description":
"تفعيل خيار الدخول بحساب Microsoft",
"admin.config.oauth.microsoft-tenant": "Microsoft Tenant",
"admin.config.oauth.microsoft-tenant.description":
"معرف Tenant لتطبيق مايكروسوفت OAuth\nالشائع: يمكن للمستخدمين الذين لديهم حساب مايكروسوفت شخصي وحساب عمل أو مدرسة من معرف Microsoft Entra أن يسجلوا الدخول إلى التطبيق. بالنسبة المؤسسات: يمكن فقط للمستخدمين الذين لديهم حسابات عمل أو مدرسة من Microsoft Entra ID تسجيل الدخول إلى التطبيق.\nالمستهلكين: يمكن فقط للمستخدمين الذين لديهم حساب مايكروسوفت الشخصي تسجيل الدخول إلى التطبيق.\nاسم نطاق مستأجر Microsoft Entra أو معرف المستأجر بتنسيق GUID: يمكن فقط للمستخدمين من مستأجر Microsoft Entra محدد (أعضاء الإدارة الذين لديهم حساب عمل أو مدرسة أو ضيوف الإدارة الذين لديهم حساب شخصي لمايكروسوفت) تسجيل الدخول إلى التطبيق.",
"admin.config.oauth.microsoft-client-id": "Microsoft Client ID",
"admin.config.oauth.microsoft-client-id.description":
"معرف العميل لتطبيق Microsoft OAuth",
"admin.config.oauth.microsoft-client-secret":
"الرمز السرّي لـMicrosoft Client",
"admin.config.oauth.microsoft-client-secret.description":
"الرّمز السرّي للعميل لتطبيق Microsoft OAuth",
"admin.config.oauth.discord-enabled": "Discord",
"admin.config.oauth.discord-enabled.description":
"تفعيل خيار الدخول بحساب Discord",
"admin.config.oauth.discord-limited-guild": "مُعرِّف خادم Discord المحدود",
"admin.config.oauth.discord-limited-guild.description":
"حصر تسجيل الدخول على المستخدمين الموجودين في خادم محدّد. اترك هذا الخيار فارغًا لتعطيله.",
"admin.config.oauth.discord-client-id": "Discord Client ID",
"admin.config.oauth.discord-client-id.description":
"معرف العميل لتطبيق Discord OAuth",
"admin.config.oauth.discord-client-secret": "الرمز السرّي لـDiscord Client",
"admin.config.oauth.discord-client-secret.description":
"الرّمز السرّي للعميل لتطبيق Discord OAuth",
"admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description":
"تفعيل الدخول باستخدام OpenID Connect",
"admin.config.oauth.oidc-discovery-uri": "OpenID Connect Discovery URI",
"admin.config.oauth.oidc-discovery-uri.description":
"رابط الاستكشاف لتطبيق OpenID Connect OAuth",
"admin.config.oauth.oidc-username-claim": "OpenID Connect username claim",
"admin.config.oauth.oidc-username-claim.description":
"طلب اسم المستخدم في رمز معرف OpenID Connect. إذا كنت لا تعرف معنى هذا الإعداد، اتركه فارغًا.",
"admin.config.oauth.oidc-client-id": "OpenID Connect Client ID",
"admin.config.oauth.oidc-client-id.description":
"معرف العميل لتطبيق OpenID Connect OAuth",
"admin.config.oauth.oidc-client-secret": "OpenID Connect Client secret",
"admin.config.oauth.oidc-client-secret.description":
"الرّمز السرّي للعميل لتطبيق OpenID Connect OAuth",
// 404
"404.description": "هذه الصفحة غير موجودة.",
"404.button.home": "أعدني للصفحة الرئيسية",
// error
"error.title": "خطأ",
"error.description": "عذرًا!",
"error.button.back": "العودة",
"error.msg.default": "حَدث خطأ ما.",
"error.msg.access_denied":
"قمت بإلغاء عملية المصادقة، الرجاء المحاولة مرة أخرى.",
"error.msg.expired_token":
"استغرقت عملية المصادقة وقتًا طويلًا، يرجى المحاولة مرة أخرى.",
"error.msg.invalid_token": "خطأ داخلي",
"error.msg.no_user": "المستخدم المرتبط بهذا الحساب {0} غير موجود.",
"error.msg.no_email":
"لا يمكن الحصول على عنوان البريد الإلكتروني من هذا الحساب {0}.",
"error.msg.already_linked": "حساب {0} هذا مرتبط بالفعل بحساب آخر.",
"error.msg.not_linked": "لم يتم ربط حساب {0} هذا بأي حساب حتى الآن.",
"error.msg.unverified_account":
"لم يتم التحقق من حساب {0} هذا، يرجى المحاولة مرة أخرى بعد التحقق.",
"error.msg.discord_guild_permission_denied": "غير مسموح لك بتسجيل الدخول.",
"error.msg.cannot_get_user_info":
"فشلت عملية جلب معلومات المستخدم الخاصة بك من حساب {0} هذا.",
"error.param.provider_github": "GitHub",
"error.param.provider_google": "Google",
"error.param.provider_microsoft": "Microsoft",
"error.param.provider_discord": "Discord",
"error.param.provider_oidc": "OpenID Connect",
// Common translations
"common.button.save": "حفظ",
"common.button.create": "إنشاء",
"common.button.submit": "إرسال",
"common.button.delete": "حذف",
"common.button.cancel": "إلغاء",
"common.button.confirm": "تأكيد",
"common.button.disable": "إيقاف",
"common.button.share": "مشاركة",
"common.button.generate": "توليد",
"common.button.done": "تم",
"common.text.link": "الرابط",
"common.text.navigate-to-link": "الذهاب إلى الرابط",
"common.text.or": "أو",
"common.button.go-back": "العودة",
"common.button.go-home": "العودة للصفحة الرئيسية",
"common.notify.copied": "تم نسخ الرابط إلى الحافظة",
"common.success": "تم",
"common.error": "خطأ",
"common.error.unknown": "حدث خطأ غير معروف",
"common.error.invalid-email": "عنوان البريد غير صحيح",
"common.error.too-short": "يجب أن يكون على الأقل {length} حرفًا",
"common.error.too-long": "يجب أن يكون على الأكثر {length} حرفًا",
"common.error.exact-length": "يجب أن يكون بالضبط {length} حرفًا",
"common.error.invalid-number": "يجب أن يكون رقماً",
"common.error.field-required": "هذا الحقل مطلوب",
};

View File

@@ -106,7 +106,7 @@ export default {
"account.modal.totp.step2": "Trin 2: Valider din kode",
"account.modal.totp.enterManually": "Indtast manuelt",
"account.modal.totp.code": "Kode",
"account.modal.totp.clickToCopy": "Klik for at kopiere",
"common.button.clickToCopy": "Klik for at kopiere",
"account.modal.totp.verify": "Bekræft",
"account.notify.totp.disable": "2-faktor blev deaktiveret",
"account.notify.totp.enable": "2-faktor blev deaktiveret",
@@ -190,6 +190,7 @@ export default {
// /admin
"admin.title": "Administration",
"admin.button.users": "Brugeradministration",
"admin.button.shares": "Share management",
"admin.button.config": "Konfiguration",
"admin.version": "Version",
// END /admin
@@ -219,6 +220,16 @@ export default {
"admin.users.modal.create.admin.description":
"If checked, the user will be able to access the admin panel.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Upload",
"upload.notify.generic-error":
@@ -259,9 +270,10 @@ export default {
"upload.modal.expires.month-plural": "Måneder",
"upload.modal.expires.year-singular": "År",
"upload.modal.expires.year-plural": "År",
"upload.modal.accordion.description.title": "Beskrivelse",
"upload.modal.accordion.description.placeholder":
"Bemærkning til modtagerne af dette share",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "E-mail modtagere",
"upload.modal.accordion.email.placeholder": "Indtast e-mail modtagere",
"upload.modal.accordion.email.invalid-email": "Ugyldig e-mailadresse",
@@ -371,6 +383,9 @@ export default {
"admin.config.share.zip-compression-level": "Zip compression level",
"admin.config.share.zip-compression-level.description":
"Adjust the level to balance between file size and compression speed. Valid values range from 0 to 9, with 0 being no compression and 9 being maximum compression. ",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "Aktiveret",
"admin.config.smtp.enabled.description":
"Om SMTP er aktiveret. Aktiver kun SMTP, hvis du har indtastet SMTP-server vært, port, e-mail, bruger og adgangskode.",
@@ -386,7 +401,7 @@ export default {
"admin.config.smtp.password": "Adgangskode",
"admin.config.smtp.password.description": "Adgangskoden til SMTP serveren",
"admin.config.smtp.button.test": "Send test e-mail",
"admin.config.oauth.allow-registration": "Allow registration",
"admin.config.oauth.allow-registration": "Tillad registrering",
"admin.config.oauth.allow-registration.description":
"Allow users to register via social login",
"admin.config.oauth.ignore-totp": "Ignore TOTP",
@@ -461,7 +476,7 @@ export default {
"You canceled the authentication process, please try again.",
"error.msg.expired_token":
"The authentication process took too long, please try again.",
"error.msg.invalid_token": "Internal Error",
"error.msg.invalid_token": "Intern Fejl",
"error.msg.no_user": "User linked to this {0} account doesn't exist.",
"error.msg.no_email": "Can't get email address from this {0} account.",
"error.msg.already_linked":

View File

@@ -65,7 +65,7 @@ export default {
"resetPassword.description":
"Gib deine Email Adresse ein, um dein Passwort zurückzusetzen.",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"Wir haben dir einen Link gesendet, unter dem du dein Passwort zurücksetzen kannst.",
"resetPassword.button.back": "Zurück zur Anmeldeseite",
"resetPassword.text.resetPassword": "Passwort zurücksetzen",
"resetPassword.text.enterNewPassword": "Gib dein neues Passwort ein",
@@ -108,7 +108,7 @@ export default {
"account.modal.totp.step2": "Schritt 2: Bestätige deinen Code",
"account.modal.totp.enterManually": "Manuell eingeben",
"account.modal.totp.code": "Code",
"account.modal.totp.clickToCopy": "Klicken zum Kopieren",
"common.button.clickToCopy": "Klicken zum Kopieren",
"account.modal.totp.verify": "Überprüfen",
"account.notify.totp.disable": "TOTP erfolgreich deaktiviert",
"account.notify.totp.enable": "TOTP erfolgreich aktiviert",
@@ -192,6 +192,7 @@ export default {
// /admin
"admin.title": "Verwaltung",
"admin.button.users": "Benutzerverwaltung",
"admin.button.shares": "Freigabenverwaltung",
"admin.button.config": "Konfiguration",
"admin.version": "Version",
// END /admin
@@ -222,6 +223,16 @@ export default {
"admin.users.modal.create.admin.description":
"Wenn aktiviert, kann der Benutzer auf das Administrator-Panel zugreifen.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Freigabenverwaltung",
"admin.shares.table.id": "ID teilen",
"admin.shares.table.username": "Ersteller",
"admin.shares.table.visitors": "Besucher",
"admin.shares.table.expires": "Läuft ab am",
"admin.shares.edit.delete.title": "Lösche Freigabe {id}",
"admin.shares.edit.delete.description":
"Möchtest du wirklich diese Freigabe löschen?",
// END /admin/shares
// /upload
"upload.title": "Upload",
"upload.notify.generic-error":
@@ -263,8 +274,9 @@ export default {
"upload.modal.expires.month-plural": "Monate",
"upload.modal.expires.year-singular": "Jahr",
"upload.modal.expires.year-plural": "Year",
"upload.modal.accordion.description.title": "Beschreibung",
"upload.modal.accordion.description.placeholder":
"upload.modal.accordion.name-and-description.title": "Name und Beschreibung",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Hinweis für die Empfänger dieser Freigabe",
"upload.modal.accordion.email.title": "Email Empfänger",
"upload.modal.accordion.email.placeholder": "Email der Empfänger eingeben",
@@ -303,7 +315,7 @@ export default {
"share.modal.file-preview.error.not-supported.title":
"Vorschau wird nicht unterstützt",
"share.modal.file-preview.error.not-supported.description":
"A preview for this file type is unsupported. Please download the file to view it.",
"Eine Vorschau für diesen Dateityp wird nicht unterstützt. Bitte lade die Datei herunter, um sie anzusehen.",
// END /share/[id]
// /share/[id]/edit
"share.edit.title": "{shareId} bearbeiten",
@@ -379,6 +391,9 @@ export default {
"admin.config.share.zip-compression-level": "Zip Komprimierungsstufe",
"admin.config.share.zip-compression-level.description":
"Passe den Wert an, um ein Gleichgewicht zwischen Dateigröße und Komprimierungsgeschwindigkeit herzustellen. Gültige Werte liegen zwischen 0 und 9, wobei 0 für keine Komprimierung und 9 für maximale Komprimierung steht.",
"admin.config.share.chunk-size": "Chunkgröße",
"admin.config.share.chunk-size.description":
"Passe die Chunkgröße (in Bytes) für deine Uploads an, um die Zuverlässigkeit deiner Internetverbindung auszugleichen. Kleinere Chunks können die Erfolgsraten für instabile Verbindungen verbessern, während größere Chunks Uploads für stabile Verbindungen beschleunigen können.",
"admin.config.smtp.enabled": "Aktiviert",
"admin.config.smtp.enabled.description":
"Gibt an, ob SMTP aktiviert ist. Aktiviere dies nur, wenn Du den Host, den Port, die Email, den Benutzernamen und das Passwort deines SMTP-Servers eingegeben hast.",
@@ -430,9 +445,9 @@ export default {
"Client-Secret der Microsoft OAuth-App",
"admin.config.oauth.discord-enabled": "Discord",
"admin.config.oauth.discord-enabled.description": "Discord Anmeldung erlaubt",
"admin.config.oauth.discord-limited-guild": "Discord limited server ID",
"admin.config.oauth.discord-limited-guild": "Discord Server-ID",
"admin.config.oauth.discord-limited-guild.description":
"Limit signing in to users in a specific server. Leave it blank to disable.",
"Die Anmeldung auf Benutzer in einem bestimmten Server beschränken. Leer lassen, um zu deaktivieren.",
"admin.config.oauth.discord-client-id": "Discord Client-ID",
"admin.config.oauth.discord-client-id.description":
"Client-ID der Discord OAuth-App",
@@ -442,12 +457,13 @@ export default {
"admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description":
"OpenID Connect Anmeldung erlaubt",
"admin.config.oauth.oidc-discovery-uri": "OpenID Connect Discovery URI",
"admin.config.oauth.oidc-discovery-uri": "OpenID Verbindung Discovery URL",
"admin.config.oauth.oidc-discovery-uri.description":
"Discovery URI of the OpenID Connect OAuth app",
"admin.config.oauth.oidc-username-claim": "OpenID Connect username claim",
"Discovery-URL der OpenID OAuth App",
"admin.config.oauth.oidc-username-claim":
"OpenID Connect Benutzername anfordern",
"admin.config.oauth.oidc-username-claim.description":
"Username claim in OpenID Connect ID token. Leave it blank if you don't know what this config is.",
"Benutzername im OpenID Token. Leer lassen, wenn du nicht weißt, was diese Konfiguration bedeutet.",
"admin.config.oauth.oidc-client-id": "OpenID Connect Client-ID",
"admin.config.oauth.oidc-client-id.description":
"Client-ID der OpenID Connect OAuth-App",
@@ -501,7 +517,7 @@ export default {
"common.text.navigate-to-link": "Link öffnen",
"common.text.or": "oder",
"common.button.go-back": "Zurück",
"common.button.go-home": "Go home",
"common.button.go-home": "Zur Startseite",
"common.notify.copied": "Dein Link wurde in die Zwischenablage kopiert",
"common.success": "Erfolg",
"common.error": "Fehler",

View File

@@ -109,7 +109,7 @@ export default {
"account.modal.totp.step2": "Βήμα 2: Επικυρώστε τον κωδικό σας",
"account.modal.totp.enterManually": "Χειροκίνητη εισαγωγή",
"account.modal.totp.code": "Κώδικας",
"account.modal.totp.clickToCopy": "Κάνε κλικ για αντιγραφή",
"common.button.clickToCopy": "Κάνε κλικ για αντιγραφή",
"account.modal.totp.verify": "Επαλήθευση",
"account.notify.totp.disable": "Το TOTP απενεργοποιήθηκε επιτυχώς",
"account.notify.totp.enable": "Το TOTP ενεργοποιήθηκε επιτυχώς",
@@ -196,6 +196,7 @@ export default {
// /admin
"admin.title": "Διαχείριση",
"admin.button.users": "Διαχείριση χρηστών",
"admin.button.shares": "Share management",
"admin.button.config": "Διαμόρφωση",
"admin.version": "Έκδοση",
// END /admin
@@ -228,6 +229,16 @@ export default {
"admin.users.modal.create.admin.description":
"Αν ενεργοποιηθεί, ο χρήστης θα μπορεί να έχει πρόσβαση στον πίνακα διαχείρισης.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Μεταφόρτωση",
"upload.notify.generic-error":
@@ -269,9 +280,10 @@ export default {
"upload.modal.expires.month-plural": "Μήνες",
"upload.modal.expires.year-singular": "Έτος",
"upload.modal.expires.year-plural": "Έτη",
"upload.modal.accordion.description.title": "Περιγραφή",
"upload.modal.accordion.description.placeholder":
"Σημείωση για τους παραλήπτες αυτής της κοινοποίησης",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Αποδέκτες email",
"upload.modal.accordion.email.placeholder": "Εισάγετε αποδέκτες email",
"upload.modal.accordion.email.invalid-email": "Μη έγκυρη διεύθυνση e-mail",
@@ -311,7 +323,7 @@ export default {
"share.modal.file-preview.error.not-supported.title":
"Η προεπισκόπηση δεν υποστηρίζεται",
"share.modal.file-preview.error.not-supported.description":
"A preview for this file type is unsupported. Please download the file to view it.",
"Η προεπισκόπηση για αυτό τον τύπο αρχείου δεν υποστηρίζεται. Παρακαλώ κατεβάστε το αρχείο για να το δείτε.",
// END /share/[id]
// /share/[id]/edit
"share.edit.title": "Ενημέρωση {shareId}",
@@ -389,6 +401,9 @@ export default {
"admin.config.share.zip-compression-level": "Βαθμός συμπίεσης ZIP",
"admin.config.share.zip-compression-level.description":
"Προσαρμόστε το βαθμό συμπίεσης για να εξισορροπηθεί το μέγεθος του αρχείου και η ταχύτητα επεξεργασίας. Έγκυρες τιμές κυμαίνονται από 0 έως 9, με 0 χωρίς συμπίεση και 9 μέγιστη συμπίεση.",
"admin.config.share.chunk-size": "Μέγεθος κομματιών",
"admin.config.share.chunk-size.description":
"Προσαρμόστε το μέγεθος κομματιών (σε bytes) για να εξισορροπήσετε την αποδοτικότητα και την αξιοπιστία του συστήματος σύμφωνα με τη σύνδεσή σας στο διαδίκτυο. Μικρότερα κομμάτια μπορούν να βελτιώσουν τα ποσοστά επιτυχίας σε ασταθείς συνδέσεις, ενώ μεγαλύτερα κομμάτια επιταχύνουν τις μεταφορτώσεις σε σταθερές συνδέσεις.",
"admin.config.smtp.enabled": "Ενεργοποιημένο",
"admin.config.smtp.enabled.description":
"Εάν η λειτουργία SMTP είναι ενεργοποιημένη. Ενεργοποιήστε τη μόνον όταν ορίσετε σωστά τις παραμέτρους που ακολουθούν.",
@@ -516,7 +531,7 @@ export default {
"common.text.navigate-to-link": "Μεταβείτε στο σύνδεσμο",
"common.text.or": "ή",
"common.button.go-back": "Επιστροφή",
"common.button.go-home": "Go home",
"common.button.go-home": "Μετάβαση στην αρχική",
"common.notify.copied": "Ο σύνδεσμος σας αντιγράφηκε στο πρόχειρο",
"common.success": "Επιτυχία",
"common.error": "Σφάλμα",

View File

@@ -122,7 +122,7 @@ export default {
"account.modal.totp.step2": "Step 2: Validate your code",
"account.modal.totp.enterManually": "Enter manually",
"account.modal.totp.code": "Code",
"account.modal.totp.clickToCopy": "Click to copy",
"common.button.clickToCopy": "Click to copy",
"account.modal.totp.verify": "Verify",
"account.notify.totp.disable": "TOTP disabled successfully",
"account.notify.totp.enable": "TOTP enabled successfully",
@@ -224,6 +224,7 @@ export default {
// /admin
"admin.title": "Administration",
"admin.button.users": "User management",
"admin.button.shares": "Share management",
"admin.button.config": "Configuration",
"admin.version": "Version",
// END /admin
@@ -260,6 +261,19 @@ export default {
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Upload",
@@ -307,8 +321,9 @@ export default {
"upload.modal.expires.year-singular": "Year",
"upload.modal.expires.year-plural": "Years",
"upload.modal.accordion.description.title": "Description",
"upload.modal.accordion.description.placeholder":
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Email recipients",
@@ -432,6 +447,10 @@ export default {
"admin.config.share.zip-compression-level": "Zip compression level",
"admin.config.share.zip-compression-level.description":
"Adjust the level to balance between file size and compression speed. Valid values range from 0 to 9, with 0 being no compression and 9 being maximum compression. ",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description": "Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.share.auto-open-share-modal": "Auto open create share modal",
"admin.config.share.auto-open-share-modal.description": "The share creation modal automatically appears when a user selects files, eliminating the need to manually click the button.",
"admin.config.smtp.enabled": "Enabled",
"admin.config.smtp.enabled.description":

View File

@@ -64,7 +64,7 @@ export default {
"resetPassword.description":
"Ingresa tu correo para restablecer tu contraseña.",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"Se ha enviado un mensaje con un enlace para restablecer tu contraseña.",
"resetPassword.button.back": "Volver al inicio de sesión",
"resetPassword.text.resetPassword": "Restablecer contraseña",
"resetPassword.text.enterNewPassword": "Ingresa tu nueva contraseña",
@@ -107,7 +107,7 @@ export default {
"account.modal.totp.step2": "Paso 2: Validar tu código",
"account.modal.totp.enterManually": "Ingresar manualmente",
"account.modal.totp.code": "Código",
"account.modal.totp.clickToCopy": "Clic para copiar",
"common.button.clickToCopy": "Clic para copiar",
"account.modal.totp.verify": "Verificar",
"account.notify.totp.disable": "TOTP deshabilitado correctamente",
"account.notify.totp.enable": "TOTP habilitado correctamente",
@@ -193,6 +193,7 @@ export default {
// /admin
"admin.title": "Administración",
"admin.button.users": "Gestión de usuarios",
"admin.button.shares": "Share management",
"admin.button.config": "Configuración",
"admin.version": "Versión",
// END /admin
@@ -224,6 +225,16 @@ export default {
"admin.users.modal.create.admin.description":
"Si se marca, el usuario podrá acceder al panel de administrador.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Subir",
"upload.notify.generic-error":
@@ -265,8 +276,9 @@ export default {
"upload.modal.expires.month-plural": "Meses",
"upload.modal.expires.year-singular": "Año",
"upload.modal.expires.year-plural": "Años",
"upload.modal.accordion.description.title": "Descripción",
"upload.modal.accordion.description.placeholder":
"upload.modal.accordion.name-and-description.title": "Nombre y descripción",
"upload.modal.accordion.name-and-description.name.placeholder": "Nombre",
"upload.modal.accordion.name-and-description.description.placeholder":
"Nota para los destinatarios de este compartido",
"upload.modal.accordion.email.title": "Correo de los destinatarios",
"upload.modal.accordion.email.placeholder":
@@ -381,6 +393,9 @@ export default {
"admin.config.share.zip-compression-level": "Nivel de compresión del Zip",
"admin.config.share.zip-compression-level.description":
"Ajustar el nivel para equilibrar entre el tamaño del archivo y la velocidad de compresión. Los valores válidos van del 0 al 9, siendo 0 sin compresión y 9 el nivel máximo de compresión. ",
"admin.config.share.chunk-size": "Tamaño de los fragmentos",
"admin.config.share.chunk-size.description":
"Ajusta el tamaño de los fragmentos (en bytes) para tus cargas para equilibrar la eficiencia y la fiabilidad según tu conexión a internet. Fragmentos más pequeños pueden mejorar las tasas de éxito para conexiones inestables, mientras que fragmentos más grandes aceleran las cargas para conexiones estables.",
"admin.config.smtp.enabled": "Habilitado",
"admin.config.smtp.enabled.description":
"Si SMTP está habilitado. Active solo si ha introducido el host, el puerto, el correo, el usuario y la contraseña de su servidor SMTP.",
@@ -508,7 +523,7 @@ export default {
"common.text.navigate-to-link": "Ir al enlace",
"common.text.or": "o",
"common.button.go-back": "Volver",
"common.button.go-home": "Go home",
"common.button.go-home": "Página de inicio",
"common.notify.copied": "Tu enlace se ha copiado al portapapeles",
"common.success": "Éxito",
"common.error": "Error",

View File

@@ -107,7 +107,7 @@ export default {
"account.modal.totp.step2": "Vaihe 2: Vahvista koodisi",
"account.modal.totp.enterManually": "Syötä manuaalisesti",
"account.modal.totp.code": "Koodi",
"account.modal.totp.clickToCopy": "Klikkaa kopioidaksesi",
"common.button.clickToCopy": "Klikkaa kopioidaksesi",
"account.modal.totp.verify": "Vahvista",
"account.notify.totp.disable": "TOTP poistettu käytöstä",
"account.notify.totp.enable": "TOTP otettu käyttöön onnistuneesti",
@@ -192,6 +192,7 @@ export default {
// /admin
"admin.title": "Ylläpito",
"admin.button.users": "Käyttäjien Hallinta",
"admin.button.shares": "Share management",
"admin.button.config": "Asetukset",
"admin.version": "Versio",
// END /admin
@@ -221,6 +222,16 @@ export default {
"admin.users.modal.create.admin.description":
"Jos valittu, käyttäjä voi käyttää hallintapaneelia.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Pilvetä",
"upload.notify.generic-error":
@@ -262,9 +273,10 @@ export default {
"upload.modal.expires.month-plural": "Kuukautta",
"upload.modal.expires.year-singular": "Vuosi",
"upload.modal.expires.year-plural": "Vuotta",
"upload.modal.accordion.description.title": "Kuvaus",
"upload.modal.accordion.description.placeholder":
"Huomautus tämän jaon vastaanottajille",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Sähköpostin vastaanottajat",
"upload.modal.accordion.email.placeholder":
"Syötä sähköpostin vastaanottajat",
@@ -374,6 +386,9 @@ export default {
"admin.config.share.zip-compression-level": "Zip puristustaso",
"admin.config.share.zip-compression-level.description":
"Säädä tasoa tiedoston koon ja pakkausnopeuden välillä. Kelvolliset arvot vaihtelevat 09, 0 ei puristusta ja 9 on suurin puristusvoima. ",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "Käytössä",
"admin.config.smtp.enabled.description":
"Onko SMTP käytössä. Aseta tämä todeksi vain, jos olet syöttänyt SMTP-palvelimen isäntän, portin, sähköpostin, käyttäjän ja salasanan.",

View File

@@ -65,7 +65,7 @@ export default {
"resetPassword.description":
"Saisissez votre courriel pour réinitialiser votre mot de passe.",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"Un message avec un lien pour réinitialiser votre mot de passe a été envoyé si le courriel existe.",
"resetPassword.button.back": "Retour à la page de connexion",
"resetPassword.text.resetPassword": "Réinitialiser le mot de passe",
"resetPassword.text.enterNewPassword": "Saisissez votre nouveau mot de passe",
@@ -109,7 +109,7 @@ export default {
"account.modal.totp.step2": "Étape 2 : Valider votre code",
"account.modal.totp.enterManually": "Saisir manuellement",
"account.modal.totp.code": "Code",
"account.modal.totp.clickToCopy": "Cliquez pour copier",
"common.button.clickToCopy": "Cliquez pour copier",
"account.modal.totp.verify": "Vérifier",
"account.notify.totp.disable": "TOTP désactivé avec succès",
"account.notify.totp.enable": "TOTP activé avec succès",
@@ -193,6 +193,7 @@ export default {
// /admin
"admin.title": "Administration",
"admin.button.users": "Gestion des utilisateurs",
"admin.button.shares": "Gestion des partages",
"admin.button.config": "Paramètres",
"admin.version": "Version",
// END /admin
@@ -225,6 +226,16 @@ export default {
"admin.users.modal.create.admin.description":
"Si coché, lutilisateur pourra accéder au panneau d'administration.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Gestion des partages",
"admin.shares.table.id": "ID de partage",
"admin.shares.table.username": "Créateur",
"admin.shares.table.visitors": "Visiteurs",
"admin.shares.table.expires": "Expire le",
"admin.shares.edit.delete.title": "Supprimer le partage {id}",
"admin.shares.edit.delete.description":
"Voulez-vous vraiment supprimer ce partage ?",
// END /admin/shares
// /upload
"upload.title": "Envoyer",
"upload.notify.generic-error":
@@ -266,8 +277,9 @@ export default {
"upload.modal.expires.month-plural": "Mois",
"upload.modal.expires.year-singular": "An",
"upload.modal.expires.year-plural": "Ans",
"upload.modal.accordion.description.title": "Description",
"upload.modal.accordion.description.placeholder":
"upload.modal.accordion.name-and-description.title": "Nom et description",
"upload.modal.accordion.name-and-description.name.placeholder": "Nom",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note pour les destinataires de ce partage",
"upload.modal.accordion.email.title": "Adresse courriel des destinataires",
"upload.modal.accordion.email.placeholder":
@@ -381,6 +393,9 @@ export default {
"admin.config.share.zip-compression-level": "Niveau de compression",
"admin.config.share.zip-compression-level.description":
"Ajustez le niveau pour trouver l'équilibre entre la taille du fichier et la vitesse de compression. Les valeurs valides vont de 0 à 9, 0 étant sans compression et 9 étant la compression maximale. ",
"admin.config.share.chunk-size": "Taille des tronçons",
"admin.config.share.chunk-size.description":
"Ajustez la taille des tronçons (en octets) pour que vos téléchargements équilibrent efficacité et fiabilité en fonction de votre connexion Internet. Les petits tronçons peuvent améliorer les taux de succès sur les connexions instables, tandis que les tronçons plus importants accélèrent les téléchargements sur les connexions stables.",
"admin.config.smtp.enabled": "Activer",
"admin.config.smtp.enabled.description":
"Active SMTP. Activez ceci uniquement si vous avez saisi lhôte, le port, le courriel, lutilisateur et son mot de passe, de votre serveur SMTP.",

View File

@@ -0,0 +1,529 @@
export default {
// Navbar
"navbar.upload": "Feltöltés",
"navbar.signin": "Bejelentkezés",
"navbar.home": "Home",
"navbar.signup": "Feliratkozás",
"navbar.links.shares": "Megosztásaim",
"navbar.links.reverse": "Fordított megosztások",
"navbar.avatar.account": "Fiókom",
"navbar.avatar.admin": "Admin ügyek",
"navbar.avatar.signout": "Kijelentkezés",
// END navbar
// /
"home.title": "<h>Saját üzemeltetésű</h> fájl megosztó platform.",
"home.description":
"Valóban hozzáférhetővé akarja tenni fájljait a WeTransfer és más hasonló harmadik felek számára?",
"home.bullet.a.name": "Saját üzemeltetés",
"home.bullet.a.description":
"A Pingvin Share megosztót saját gépéről futtathatja.",
"home.bullet.b.name": "Adatvédelem",
"home.bullet.b.description":
"A saját fájlok személyesek és semmi keresnivalójuk harmadik feleknél.",
"home.bullet.c.name": "Nincs bosszantó fájl méretkorlát",
"home.bullet.c.description":
"Akkora fájlokat oszt meg, amekkorákat csak akar. Határt csak a lemezterület szab.",
"home.button.start": "Nosza, kezdjük",
"home.button.source": "Forráskód",
// END /
// /auth/signin
"signin.title": "Üdv ismét itt",
"signin.description": "Nincsen még fiókja?",
"signin.button.signup": "Feliratkozás",
"signin.input.email-or-username": "Email vagy felhasználónév",
"signin.input.email-or-username.placeholder":
"Az Ön emailcíme vagy felhasználóneve",
"signin.input.password": "Jelszó",
"signin.input.password.placeholder": "Az Ön jelszava",
"signin.button.submit": "Bejelentkezés",
"signIn.notify.totp-required.title": "Kétfaktoros hitelesítésre van szükség",
"signIn.notify.totp-required.description":
"Adja meg a másik úton kapott kódját",
"signIn.oauth.or": "VAGY",
"signIn.oauth.github": "GitHub",
"signIn.oauth.google": "Google",
"signIn.oauth.microsoft": "Microsoft",
"signIn.oauth.discord": "Discord",
"signIn.oauth.oidc": "OpenID",
// END /auth/signin
// /auth/signup
"signup.title": "Fiók létrehozása",
"signup.description": "Már van fiókja?",
"signup.button.signin": "Bejelentkezés",
"signup.input.username": "Felhasználónév",
"signup.input.username.placeholder": "Az Ön felhasználói neve",
"signup.input.email": "Email",
"signup.input.email.placeholder": "Az Ön emailcíme",
"signup.button.submit": "Kezdhetjük",
// END /auth/signup
// /auth/totp
"totp.title": "TOTP hitelesítés",
"totp.button.signIn": "Bejelentkezés",
// END /auth/totp
// /auth/reset-password
"resetPassword.title": "Elfelejtette jelszavát?",
"resetPassword.description":
"Adja meg emailcímét a jelszó alaphelyzetbe állításához.",
"resetPassword.notify.success":
"A jelszó visszaállítására szolgáló linket tartalmazó üzenetet küldtünk, ha az e-mail létezik.",
"resetPassword.button.back": "Vissza a bejelentkezési oldalra",
"resetPassword.text.resetPassword": "Jelszó alaphelyzetbe állítása",
"resetPassword.text.enterNewPassword": "Adja meg új jelszavát",
"resetPassword.input.password": "Új jelszó",
"resetPassword.notify.passwordReset": "Sikeresen megadta az új jelszót.",
// /account
"account.title": "Fiókom",
"account.card.info.title": "Fiókinformáció",
"account.card.info.username": "Felhasználónév",
"account.card.info.email": "Email",
"account.notify.info.success": "A fiók sikeresen frissítésre került",
"account.card.password.title": "Jelszó",
"account.card.password.old": "Régi jelszó",
"account.card.password.new": "Új jelszó",
"account.card.password.noPasswordSet":
"Még nincs jelszava. Ha email és jelszó kombinációval kíván bejelentkezni, létre kell hoznia egy jelszót.",
"account.notify.password.success": "A jelszó sikeresen frissítésre került",
"account.card.oauth.title": "Közösségi bejelentkezés",
"account.card.oauth.github": "GitHub",
"account.card.oauth.google": "Google",
"account.card.oauth.microsoft": "Microsoft",
"account.card.oauth.discord": "Discord",
"account.card.oauth.oidc": "OpenID",
"account.card.oauth.link": "Összekapcsolás",
"account.card.oauth.unlink": "Leválasztás",
"account.card.oauth.unlinked": "Leválasztva",
"account.modal.unlink.title": "Fiók leválasztása",
"account.modal.unlink.description":
"A közösségi hálón keresztül csatolt fiók leválasztásával elveszítheti hozzáférését a fiókhoz, ha a név és jelszó kombinációra nem emlékszik.",
"account.notify.oauth.unlinked.success": "Leválasztás sikeres",
"account.card.security.title": "Biztonság",
"account.card.security.totp.enable.description":
"Adja meg az aktuális jelszavát a TOTP engedélyezéséhez",
"account.card.security.totp.disable.description":
"Adja meg aktuális jelszavát a TOTP letiltásához",
"account.card.security.totp.button.start": "Kezdés",
"account.modal.totp.title": "TOTP engedélyezése",
"account.modal.totp.step1": "1. lépés: Hitelesítő megadása",
"account.modal.totp.step2": "2. lépés: Kód érvényesítése",
"account.modal.totp.enterManually": "Kézi megadás",
"account.modal.totp.code": "Kód",
"common.button.clickToCopy": "Kattintson a másoláshoz",
"account.modal.totp.verify": "Hitelesítés",
"account.notify.totp.disable": "TOTP sikeresen letiltva",
"account.notify.totp.enable": "TOTP sikeresen engedélyezve",
"account.card.language.title": "Nyelv",
"account.card.language.description":
"A projekt nyelvi verzióit a közösség fordítja. Egyes nyelvi verziók nem feltétlenül teljesek.",
"account.card.color.title": "Színséma",
// ThemeSwitcher.tsx
"account.theme.dark": "Sötét",
"account.theme.light": "Világos",
"account.theme.system": "Rendszer",
"account.button.delete": "Fiók törlése",
"account.modal.delete.title": "Fiók törlése",
"account.modal.delete.description":
"Valóban törölni kívánja a fiókot és vele az összes meglévő aktív megosztást?",
// END /account
// /account/shares
"account.shares.title": "Megosztásaim",
"account.shares.title.empty": "Üres 👀, itt nincs semmi",
"account.shares.description.empty": "Nincsenek megosztások.",
"account.shares.button.create": "Létrehozás",
"account.shares.info.title": "Megosztás adatai",
"account.shares.table.id": "ID",
"account.shares.table.name": "Megnevezés",
"account.shares.table.description": "Leírás",
"account.shares.table.visitors": "Látogatók",
"account.shares.table.expiresAt": "Lejárat",
"account.shares.table.createdAt": "Létrehozás időpontja",
"account.shares.table.size": "Méret",
"account.shares.modal.share-informations": "Megosztás adatai",
"account.shares.modal.share-link": "Hivatkozás",
"account.shares.modal.delete.title": "Törlés: {share}",
"account.shares.modal.delete.description":
"Biztos abban, hogy törölni kívánja ezt a megosztást?",
// END /account/shares
// /account/reverseShares
"account.reverseShares.title": "Fordított megosztás",
"account.reverseShares.description":
"A fordított megosztással egy egyedi URL azonosító készül, amivel a rendszeren kívülről készíthető megosztás.",
"account.reverseShares.title.empty": "Üres 👀, itt nincs semmi",
"account.reverseShares.description.empty": "Nincsenek fordított megosztások.",
// showCreateReverseShareModal.tsx
"account.reverseShares.modal.title": "Fordított megosztás létrehozása",
"account.reverseShares.modal.expiration.label": "Lejárat",
"account.reverseShares.modal.expiration.minute-singular": "perc",
"account.reverseShares.modal.expiration.minute-plural": "perc",
"account.reverseShares.modal.expiration.hour-singular": "óra",
"account.reverseShares.modal.expiration.hour-plural": "óra",
"account.reverseShares.modal.expiration.day-singular": "nap",
"account.reverseShares.modal.expiration.day-plural": "nap",
"account.reverseShares.modal.expiration.week-singular": "hét",
"account.reverseShares.modal.expiration.week-plural": "hét",
"account.reverseShares.modal.expiration.month-singular": "hónap",
"account.reverseShares.modal.expiration.month-plural": "hónap",
"account.reverseShares.modal.expiration.year-singular": "év",
"account.reverseShares.modal.expiration.year-plural": "év",
"account.reverseShares.modal.max-size.label":
"Megosztás megengedett max mérete",
"account.reverseShares.modal.send-email": "Email értesítés küldése",
"account.reverseShares.modal.send-email.description":
"Email értesítés arról, amikor a fordított megosztási hivatkozást használva megosztást hoznak létre.",
"account.reverseShares.modal.max-use.label": "Megengedett alkalmak száma",
"account.reverseShares.modal.max-use.description":
"A megosztási hivatkozás megengedett felhasználási alkalmainak száma.",
"account.reverseShare.never-expires":
"Ez a fordított megosztás soha nem fog lejárni.",
"account.reverseShare.expires-on":
"A fordított megosztás lejárata: {expiration}.",
"account.reverseShares.table.no-shares": "Még nincsenek megosztások",
"account.reverseShares.table.count.singular": "megosztás",
"account.reverseShares.table.count.plural": "megosztás",
"account.reverseShares.table.shares": "Megosztások",
"account.reverseShares.table.remaining": "Fennmaradó alkalmak",
"account.reverseShares.table.max-size": "Megengedett max méret",
"account.reverseShares.table.expires": "Lejárat",
"account.reverseShares.modal.reverse-share-link":
"Fordított megosztási hivatkozás",
"account.reverseShares.modal.delete.title": "Fordított megosztás törlése",
"account.reverseShares.modal.delete.description":
"Valóban törölni kívánja ezt a fordított megosztást? A használatával készített megosztások is törlésre kerülnek.",
// END /account/reverseShares
// /admin
"admin.title": "Admin ügyek",
"admin.button.users": "Felhasználókezelés",
"admin.button.shares": "Megosztáskezelés",
"admin.button.config": "Konfiguráció",
"admin.version": "Verzió",
// END /admin
// /admin/users
"admin.users.title": "Felhasználókezelés",
"admin.users.table.username": "Felhasználónév",
"admin.users.table.email": "Email",
"admin.users.table.admin": "Admin ügyek",
"admin.users.edit.update.title": "{username} felhasználó frissítése",
"admin.users.edit.update.admin-privileges": "Adminisztrátori jogosultságok",
"admin.users.edit.update.change-password.title": "Jelszó módosítása",
"admin.users.edit.update.change-password.field": "Új jelszó",
"admin.users.edit.update.change-password.button": "Új jelszó mentése",
"admin.users.edit.update.notify.password.success":
"A jelszó sikeresen frissítésre került",
"admin.users.edit.delete.title": "{username} felhasználó törlése",
"admin.users.edit.delete.description":
"Valóban törölni kívánja ezt a felhasználót és vele az ő minden egyes megosztását?",
// showCreateUserModal.tsx
"admin.users.modal.create.title": "Felhasználó létrehozása",
"admin.users.modal.create.username": "Felhasználónév",
"admin.users.modal.create.email": "Email",
"admin.users.modal.create.password": "Jelszó",
"admin.users.modal.create.manual-password": "Jelszó kézi megadása",
"admin.users.modal.create.manual-password.description":
"Ha nincs bejelölve, akkor a felhasználó egy emailt és benne egy jelszó létrehozási hivatkozást kap.",
"admin.users.modal.create.admin": "Adminisztrátori jogosultságok",
"admin.users.modal.create.admin.description":
"Bejelölt állapotában a felhasználó hozzáfér az admin beállító oldalhoz.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Megosztáskezelés",
"admin.shares.table.id": "Megosztás ID",
"admin.shares.table.username": "Létrehozó",
"admin.shares.table.visitors": "Látogatók",
"admin.shares.table.expires": "Lejárat",
"admin.shares.edit.delete.title": "{id} megosztás törlése",
"admin.shares.edit.delete.description":
"Valóban törölni kívánja ezt a megosztást?",
// END /admin/shares
// /upload
"upload.title": "Feltöltés",
"upload.notify.generic-error":
"Hiba lépett fel a megosztás befejezése közben.",
"upload.notify.count-failed":
"{count} darab fájlt nem sikerült feltölteni. Próbálja ismét.",
// Dropzone.tsx
"upload.dropzone.title": "Fájlok feltöltése",
"upload.dropzone.description":
"Húzza ide a fájlokat a megosztás elkészítéséhez. Összesen legfeljebb {maxSize} fájl húzható egy megosztásba.",
"upload.dropzone.notify.file-too-big":
"A fájlok mérete meghaladja a megengedett {maxSize} méretet.",
// FileList.tsx
"upload.filelist.name": "Megnevezés",
"upload.filelist.size": "Méret",
// showCreateUploadModal.tsx
"upload.modal.title": "Megosztás létrehozása",
"upload.modal.link.error.invalid":
"Csak betű, szám, aláhúzás és kötőjel karaktereket tartalmazhat",
"upload.modal.link.error.taken": "Ez a hivatkozás név már használatban van",
"upload.modal.not-signed-in": "Nincs bejelentkezve",
"upload.modal.not-signed-in-description":
"Nem lesz képes megosztását kézzel törölni vagy megtekinteni a látogatók számát.",
"upload.modal.expires.never": "soha",
"upload.modal.expires.never-long": "Nincs lejárat",
"upload.modal.expires.error.too-long":
"A lejárat meghaladja a megengedett max {max} értéket.",
"upload.modal.link.label": "Hivatkozás",
"upload.modal.expires.label": "Lejárat",
"upload.modal.expires.minute-singular": "perc",
"upload.modal.expires.minute-plural": "perc",
"upload.modal.expires.hour-singular": "óra",
"upload.modal.expires.hour-plural": "óra",
"upload.modal.expires.day-singular": "nap",
"upload.modal.expires.day-plural": "nap",
"upload.modal.expires.week-singular": "hét",
"upload.modal.expires.week-plural": "hét",
"upload.modal.expires.month-singular": "hónap",
"upload.modal.expires.month-plural": "hónap",
"upload.modal.expires.year-singular": "év",
"upload.modal.expires.year-plural": "év",
"upload.modal.accordion.name-and-description.title": "Megnevezés és leírás",
"upload.modal.accordion.name-and-description.name.placeholder": "Megnevezés",
"upload.modal.accordion.name-and-description.description.placeholder":
"A megosztást kapóknak küldendő üzenet",
"upload.modal.accordion.email.title": "Email címzettek",
"upload.modal.accordion.email.placeholder": "Adja meg az email címzetteket",
"upload.modal.accordion.email.invalid-email": "Érvénytelen emailcím",
"upload.modal.accordion.security.title": "Biztonsági beállítások",
"upload.modal.accordion.security.password.label": "Jelszavas védelem",
"upload.modal.accordion.security.password.placeholder": "Nincs jelszó",
"upload.modal.accordion.security.max-views.label": "Megtekintések max száma",
"upload.modal.accordion.security.max-views.placeholder": "Nincs korlát",
// showCompletedUploadModal.tsx
"upload.modal.completed.never-expires":
"Ez a megosztás soha nem fog lejárni.",
"upload.modal.completed.expires-on": "A megosztás lejárata: {expiration}.",
"upload.modal.completed.share-ready": "A megosztás készen áll",
// END /upload
// /share/[id]
"share.title": "Megosztás: {shareId}",
"share.description": "Megosztottak Önnel valami fontosat!",
"share.error.visitor-limit-exceeded.title": "Túl sok látogató",
"share.error.visitor-limit-exceeded.description":
"A látogatók száma elérte a megszabott korlátot.",
"share.error.removed.title": "Korábban már eltávolított megosztás",
"share.error.not-found.title": "Fel nem lelhető megosztás",
"share.error.not-found.description": "A keresett megosztás nem létezik.",
"share.modal.password.title": "Jelszó szükséges",
"share.modal.password.description":
"A megosztott tartalom eléréséhez adja meg a megosztás jelszavát.",
"share.modal.password": "Jelszó",
"share.modal.error.invalid-password": "Érvénytelen jelszó",
"share.button.download-all": "Mindet letölti",
"share.notify.download-all-preparing":
"A megosztás éppen előkészületben. Kérjük próbálja újra néhány perc múlva.",
"share.modal.file-link": "Fájl hivatkozás",
"share.table.name": "Megnevezés",
"share.table.size": "Méret",
"share.modal.file-preview.error.not-supported.title":
"Az előnézetek nem támogatottak",
"share.modal.file-preview.error.not-supported.description":
"E fájltípushoz nincsen támogatott előnézet. Töltse le a fájlt a megtekintéshez.",
// END /share/[id]
// /share/[id]/edit
"share.edit.title": "Módosítás: {shareId}",
"share.edit.append-upload": "Fájl hozzáfűzése",
"share.edit.notify.generic-error":
"Hiba lépett fel a megosztás befejezése közben.",
"share.edit.notify.save-success": "A megosztás frissítésre került",
// END /share/[id]/edit
// /admin/config
"admin.config.title": "Konfiguráció",
"admin.config.category.general": "Általános",
"admin.config.category.share": "Megosztás",
"admin.config.category.email": "Email",
"admin.config.category.smtp": "SMTP",
"admin.config.category.oauth": "Közösségi bejelentkezés",
"admin.config.general.app-name": "Alkalmazás neve",
"admin.config.general.app-name.description": "Az alkalmazás neve",
"admin.config.general.app-url": "Alkalmazás URL hivatkozás",
"admin.config.general.app-url.description":
"A Pingvin Share megosztáskezelőre mutató hivatkozás",
"admin.config.general.show-home-page": "Kezdőlap mutatása",
"admin.config.general.show-home-page.description":
"A kezdőlap mutatásának ki- és bekapcsolása",
"admin.config.general.logo": "Logó",
"admin.config.general.logo.description":
"A logó személyessé tételéhez töltsön fel egy új képet. A formátum legyen PNG, az oldalarány 1:1.",
"admin.config.general.logo.placeholder": "Kép kiválasztása",
"admin.config.email.enable-share-email-recipients":
"Megosztás emailben küldésének engedélyezése",
"admin.config.email.enable-share-email-recipients.description":
"Email küldése a megosztásról a címzetteknek. Csak akkor engedélyezze, ha az SMTP már engedélyezett.",
"admin.config.email.share-recipients-subject": "Megosztási email tárgya",
"admin.config.email.share-recipients-subject.description":
"A megosztások címzettjeinek küldött email tárgya.",
"admin.config.email.share-recipients-message": "Megosztási email szövege",
"admin.config.email.share-recipients-message.description":
"A megosztás címzettjeinek küldött email tartalma. Beépíthető változók:\n {creator} - A megosztás létrehozójának neve\n {shareUrl} - A megosztás URL hivatkozása\n {desc} - A megosztás ismertetése\n {expires} - A megosztás lejáratának dátuma\n A változók helyén az aktuális tartalom fog szerepelni.",
"admin.config.email.reverse-share-subject": "Fordított megosztás tárgya",
"admin.config.email.reverse-share-subject.description":
"Annak az emailnek a tárgya, ami a fordított megosztást használva készített megosztásról kerül kiküldésre.",
"admin.config.email.reverse-share-message": "Fordított megosztás üzenete",
"admin.config.email.reverse-share-message.description":
"Az Ön által kiküldött fordított megosztási hivatkozás használatával készített megosztás emailjének szövege. A(z) {shareUrl} helyére a létrehozó neve és a megosztás URL hivatkozása kerül.",
"admin.config.email.reset-password-subject": "Jelszó visszaállítási tárgy",
"admin.config.email.reset-password-subject.description":
"A felhasználó által kezdeményezett jelszó visszaállításkor küldött email tárgya.",
"admin.config.email.reset-password-message": "Jelszó visszaállítási üzenet",
"admin.config.email.reset-password-message.description":
"A felhasználó által kezdeményezett jelszó visszaállításkor küldött email szövege. A(z) {url} helyére a jelszó visszaállítási URL hivatkozás kerül.",
"admin.config.email.invite-subject": "Meghívó tárgya",
"admin.config.email.invite-subject.description":
"Az adminisztrátortól a meghívott felhasználó felé küldött email tárgya.",
"admin.config.email.invite-message": "Meghívó szövege",
"admin.config.email.invite-message.description":
"Az adminisztrátortól a meghívott felhasználó felé küldött email szövege. A(z) {url} helyére a meghívó URL hivatkozása kerül, a(z) {password} helyére a jelszó.",
"admin.config.share.allow-registration": "Regisztráció engedélyezése",
"admin.config.share.allow-registration.description":
"Regisztráció engedélyezésének ki- és bekapcsolása",
"admin.config.share.allow-unauthenticated-shares":
"Hitelesítés nélküli megosztások engedélyezése",
"admin.config.share.allow-unauthenticated-shares.description":
"Hitelesítés nélküli felhasználók létre hozhatnak-e megosztásokat",
"admin.config.share.max-expiration": "Max lejárat",
"admin.config.share.max-expiration.description":
"A megosztások megengedett leghosszabb lejárata órában. 0 értékkel a lejárat kikapcsolható.",
"admin.config.share.max-size": "Max méret",
"admin.config.share.max-size.description":
"A megosztások megengedett legnagyobb mérete bájtban",
"admin.config.share.zip-compression-level": "Zip tömörítési szint",
"admin.config.share.zip-compression-level.description":
"A fájlméret és a tömörítésre fordított idő közötti választás. Az érték 0 - 9 közül választható, 0: nincs tömörítés, 9: legnagyobb mértékű tömörítés. ",
"admin.config.share.chunk-size": "Darabolási méret",
"admin.config.share.chunk-size.description":
"Az internet kapcsolat megbízhatóságának és átvitelének megfelelően választható feltöltési darabok mérete bájtban. A kisebb darabok növelhetik a szakadozó kapcsolatok használatának sikerességét, a nagyobb darabok a stabil kapcsolatokat gyorsítják.",
"admin.config.smtp.enabled": "Engedélyezett",
"admin.config.smtp.enabled.description":
"A(z) SMTP bekapcsolása. Csak akkor engedélyezze, ha már megadta a kiszolgáló, port, email, felhasználónév és jelszó beállításokat az SMTP kiszolgálóhoz.",
"admin.config.smtp.host": "Kiszolgáló",
"admin.config.smtp.host.description": "Az SMTP szerver kiszolgáló gépe",
"admin.config.smtp.port": "Port",
"admin.config.smtp.port.description": "Az SMTP kiszolgáló portja",
"admin.config.smtp.email": "Email",
"admin.config.smtp.email.description":
"Az emailek kiküldésére használt email cím",
"admin.config.smtp.username": "Felhasználónév",
"admin.config.smtp.username.description":
"Felhasználónév az SMTP kiszolgálón",
"admin.config.smtp.password": "Jelszó",
"admin.config.smtp.password.description": "Jelszó az SMTP kiszolgálón",
"admin.config.smtp.button.test": "Teszt email küldése",
"admin.config.oauth.allow-registration": "Regisztráció engedélyezése",
"admin.config.oauth.allow-registration.description":
"A felhasználók közösségi bejelentkezésen át is regisztrálhatnak",
"admin.config.oauth.ignore-totp": "TOTP mellőzése",
"admin.config.oauth.ignore-totp.description":
"TOTP mellőzése a közösségi bejelentkezést használó felhasználónál",
"admin.config.oauth.github-enabled": "GitHub",
"admin.config.oauth.github-enabled.description":
"GitHub bejelentkezés engedélyezése",
"admin.config.oauth.github-client-id": "GitHub ügyfél ID",
"admin.config.oauth.github-client-id.description":
"A GitHub OAuth applikáció ügyfél ID azonosítója",
"admin.config.oauth.github-client-secret": "GitHub ügyfél titok",
"admin.config.oauth.github-client-secret.description":
"A GitHub OAuth applikáció ügyfél titka",
"admin.config.oauth.google-enabled": "Google",
"admin.config.oauth.google-enabled.description":
"Google bejelentkezés engedélyezése",
"admin.config.oauth.google-client-id": "Google ügyfél ID azonosító",
"admin.config.oauth.google-client-id.description":
"A Google OAuth applikáció ügyfél ID azonosítója",
"admin.config.oauth.google-client-secret": "Google ügyfél titok",
"admin.config.oauth.google-client-secret.description":
"A Google OAuth applikáció ügyfél titka",
"admin.config.oauth.microsoft-enabled": "Microsoft",
"admin.config.oauth.microsoft-enabled.description":
"Microsoft login engedélyezése",
"admin.config.oauth.microsoft-tenant": "Microsoft bérlő",
"admin.config.oauth.microsoft-tenant.description":
"A Microsoft OAuth applikáció bérlő ID azonosítója\náltalános (common): személyes Microsoft fiókkal és munkahelyi vagy iskolai fiókkal rendelkező Microsoft Entra ID azonosítókkal egyaránt lehetséges a bejelentkezés. \nszervezetek (organizations): Csak a Microsoft Entra ID munkahelyi vagy iskolai fiókkal rendelkező felhasználók jelentkezhetnek be az alkalmazásba.\nfogyasztók (consumers): Csak személyes Microsoft-fiókkal rendelkező felhasználók jelentkezhetnek be az alkalmazásba.\nA Microsoft Entra bérlő tartományneve vagy a bérlő azonosítója GUID formátumban: Az alkalmazásba csak egy adott Microsoft Entra bérlő felhasználói jelentkezhetnek be (munkahelyi vagy iskolai fiókkal rendelkező könyvtártagok vagy személyes Microsoft-fiókkal rendelkező könyvtárvendégek).",
"admin.config.oauth.microsoft-client-id": "Microsoft ügyfél ID azonosító",
"admin.config.oauth.microsoft-client-id.description":
"A Microsoft OAuth applikáció ügyfél ID azonosítója",
"admin.config.oauth.microsoft-client-secret": "Microsoft ügyfél titok",
"admin.config.oauth.microsoft-client-secret.description":
"A Microsoft Oauth applikáció ügyfél titka",
"admin.config.oauth.discord-enabled": "Discord",
"admin.config.oauth.discord-enabled.description":
"Discord bejelentkezés engedélyezése",
"admin.config.oauth.discord-limited-guild":
"Discord limitált kiszolgáló ID azonosítója",
"admin.config.oauth.discord-limited-guild.description":
"A kiszolgálón engedélyezett bejelentkezett felhasználók száma. Hagyja üresen a kikapcsoláshoz.",
"admin.config.oauth.discord-client-id": "Discord ügyfél ID azonosító",
"admin.config.oauth.discord-client-id.description":
"A Discord OAuth applikáció ügyfél ID azonosítója",
"admin.config.oauth.discord-client-secret": "Discord ügyfél titok",
"admin.config.oauth.discord-client-secret.description":
"A Discord OAuth applikáció ügyfél titka",
"admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description":
"OpenID Connect bejelentkezés engedélyezése",
"admin.config.oauth.oidc-discovery-uri": "OpenID Connect Discovery URI",
"admin.config.oauth.oidc-discovery-uri.description":
"Az OpenID Connect OAuth applikáció Discovery URI azonosítója",
"admin.config.oauth.oidc-username-claim":
"OpenID Connect felhasználónév igény",
"admin.config.oauth.oidc-username-claim.description":
"Az OpenID Connect ID token felhasználónév igénye. Hagyja üresen ha nincs információja a beállításról.",
"admin.config.oauth.oidc-client-id": "OpenID Connect ügyfél ID azonosító",
"admin.config.oauth.oidc-client-id.description":
"Az OpenID Connect OAuth applikáció ügyfél ID azonosítója",
"admin.config.oauth.oidc-client-secret": "OpenID Connect ügyfél titok",
"admin.config.oauth.oidc-client-secret.description":
"Az OpenID Connect OAuth applikáció ügyfél titka",
// 404
"404.description": "Hoppá - ez az oldal nem létezik.",
"404.button.home": "Vissza a Kezdőlapra",
// error
"error.title": "Hiba",
"error.description": "Hoppá!",
"error.button.back": "Vissza",
"error.msg.default": "Hiba történt.",
"error.msg.access_denied":
"Megszakította a hitelesítési folyamatot, kérem próbálja újra.",
"error.msg.expired_token":
"A hitelesítési folyamat túl sokáig tartott, kérem próbálja újra.",
"error.msg.invalid_token": "Belső hiba",
"error.msg.no_user": "A(z) {0} fiókhoz kapcsolt felhasználó nem létezik.",
"error.msg.no_email": "Nem nyerhető ki a(z) {0} fiók emailcíme.",
"error.msg.already_linked":
"Ez a(z) {0} fiók már kapcsolódik egy másik fiókhoz.",
"error.msg.not_linked":
"Ez a(z){0} fiók még nem kapcsolódott egyetlen fiókhoz sem.",
"error.msg.unverified_account":
"Ezt a(z) {0} fiókot még nem igazolták vissza, kérem próbálja újra a megerősítés után.",
"error.msg.discord_guild_permission_denied": "Nem jelentkezhet be.",
"error.msg.cannot_get_user_info":
"Nem nyerhető ki felhasználói információ ebből a(z) {0} fiókból.",
"error.param.provider_github": "GitHub",
"error.param.provider_google": "Google",
"error.param.provider_microsoft": "Microsoft",
"error.param.provider_discord": "Discord",
"error.param.provider_oidc": "OpenID Connect",
// Common translations
"common.button.save": "Mentés",
"common.button.create": "Létrehozás",
"common.button.submit": "Küldés",
"common.button.delete": "Törlés",
"common.button.cancel": "Mégse",
"common.button.confirm": "Megerősítés",
"common.button.disable": "Letiltás",
"common.button.share": "Megosztás",
"common.button.generate": "Létrehozás",
"common.button.done": "Kész",
"common.text.link": "Hivatkozás",
"common.text.navigate-to-link": "Ugrás a hivatkozásra",
"common.text.or": "vagy",
"common.button.go-back": "Vissza",
"common.button.go-home": "Kezdőlap",
"common.notify.copied": "A hivatkozást a Vágólapra másoltuk",
"common.success": "Siker",
"common.error": "Hiba",
"common.error.unknown": "Ismeretlen hiba lépett fel",
"common.error.invalid-email": "Érvénytelen emailcím",
"common.error.too-short": "Legalább {length} karakter kell",
"common.error.too-long": "Legfejlebb {length} karakter adható meg",
"common.error.exact-length": "Pontosan {length} karakter szükséges",
"common.error.invalid-number": "Számot kell megadnia",
"common.error.field-required": "Ez egy kötelező mező",
};

View File

@@ -63,7 +63,7 @@ export default {
"resetPassword.description":
"Inserisci la tua email per reimpostare la password.",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"Un messaggio con un link per reimpostare la password è stato inviato se l'e-mail esiste.",
"resetPassword.button.back": "Torna alla pagina di login",
"resetPassword.text.resetPassword": "Reimposta password",
"resetPassword.text.enterNewPassword": "Inserisci la tua nuova password",
@@ -106,7 +106,7 @@ export default {
"account.modal.totp.step2": "Passo 2: Convalida il tuo codice",
"account.modal.totp.enterManually": "Inserisci manualmente",
"account.modal.totp.code": "Codice",
"account.modal.totp.clickToCopy": "Clicca per copiare",
"common.button.clickToCopy": "Clicca per copiare",
"account.modal.totp.verify": "Verifica",
"account.notify.totp.disable": "TOTP disabilitato con successo",
"account.notify.totp.enable": "TOTP abilitato con successo",
@@ -194,6 +194,7 @@ export default {
// /admin
"admin.title": "Amministrazione",
"admin.button.users": "Gestione degli utenti",
"admin.button.shares": "Gestione condivisioni",
"admin.button.config": "Configurazione",
"admin.version": "Versione",
// END /admin
@@ -224,6 +225,16 @@ export default {
"admin.users.modal.create.admin.description":
"Se selezionato, l'utente sarà in grado di accedere al pannello amministratore.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Gestione condivisioni",
"admin.shares.table.id": "ID Condivisione",
"admin.shares.table.username": "Autore",
"admin.shares.table.visitors": "Visitatori",
"admin.shares.table.expires": "Scade il",
"admin.shares.edit.delete.title": "Elimina condivisione {id}",
"admin.shares.edit.delete.description":
"Vuoi davvero cancellare questa condivisione?",
// END /admin/shares
// /upload
"upload.title": "Upload",
"upload.notify.generic-error":
@@ -264,8 +275,9 @@ export default {
"upload.modal.expires.month-plural": "Mesi",
"upload.modal.expires.year-singular": "Anno",
"upload.modal.expires.year-plural": "Anni",
"upload.modal.accordion.description.title": "Descrizione",
"upload.modal.accordion.description.placeholder":
"upload.modal.accordion.name-and-description.title": "Nome e descrizione",
"upload.modal.accordion.name-and-description.name.placeholder": "Nome",
"upload.modal.accordion.name-and-description.description.placeholder":
"Nota per i destinatari di questa condivisione",
"upload.modal.accordion.email.title": "Destinatari di posta elettronica",
"upload.modal.accordion.email.placeholder":
@@ -384,6 +396,9 @@ export default {
"admin.config.share.zip-compression-level": "Livello di compressione Zip",
"admin.config.share.zip-compression-level.description":
"Regola il livello per bilanciare la dimensione del file e la velocità di compressione. Valori validi da 0 a 9, con 0 senza compressione e 9 con compressione massima. ",
"admin.config.share.chunk-size": "Dimensione dei chunk",
"admin.config.share.chunk-size.description":
"Regola la dimensione del chunk (in byte) per i tuoi caricamenti per bilanciare l'efficienza e l'affidabilità in base alla tua connessione internet. I chunk più piccoli possono migliorare i tassi di successo per connessioni instabili, mentre i chunks più grandi velocizzano i caricamenti per connessioni stabili.",
"admin.config.smtp.enabled": "Abilitato",
"admin.config.smtp.enabled.description":
"Indica se SMTP è abilitato. Impostalo a VERO solo se hai inserito host, porta, email, utente e password del tuo server SMTP.",

View File

@@ -106,7 +106,7 @@ export default {
"account.modal.totp.step2": "ステップ2: コードを検証",
"account.modal.totp.enterManually": "手動で入力",
"account.modal.totp.code": "コピー",
"account.modal.totp.clickToCopy": "ここをクリックしてコピー",
"common.button.clickToCopy": "ここをクリックしてコピー",
"account.modal.totp.verify": "検証",
"account.notify.totp.disable": "2段階認証の無効化に成功しました",
"account.notify.totp.enable": "2段階認証の有効化に成功しました",
@@ -190,6 +190,7 @@ export default {
// /admin
"admin.title": "管理画面",
"admin.button.users": "ユーザー管理",
"admin.button.shares": "Share management",
"admin.button.config": "設定",
"admin.version": "バージョン",
// END /admin
@@ -220,6 +221,16 @@ export default {
"admin.users.modal.create.admin.description":
"チェックされている場合、ユーザーは管理画面にアクセスできるようになります。",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "アップロード",
"upload.notify.generic-error":
@@ -261,9 +272,10 @@ export default {
"upload.modal.expires.month-plural": "ヶ月間",
"upload.modal.expires.year-singular": "年間",
"upload.modal.expires.year-plural": "年間",
"upload.modal.accordion.description.title": "説明",
"upload.modal.accordion.description.placeholder":
"この共有に関する受信者へのメモ",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "メールで受け取る相手",
"upload.modal.accordion.email.placeholder": "メールの宛先を入力",
"upload.modal.accordion.email.invalid-email": "無効なメールアドレスです",
@@ -370,6 +382,9 @@ export default {
"admin.config.share.zip-compression-level": "Zip圧縮レベル",
"admin.config.share.zip-compression-level.description":
"ファイルサイズと圧縮速度のバランスを取るように、レベルを調整できます。有効な値は09の間で、0が無圧縮、9で最大限の圧縮となります。 ",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "有効",
"admin.config.smtp.enabled.description":
"SMTPを有効にするかどうかを選択してください。SMTPサーバーのホスト名、ポート番号、電子メールアドレス、ユーザー名、パスワードが入力されている場合にのみ、有効にしてください。",

View File

@@ -0,0 +1,453 @@
export default {
// Navbar
"navbar.upload": "업로드",
"navbar.signin": "로그인",
"navbar.home": "홈",
"navbar.signup": "계정 만들기",
"navbar.links.shares": "내 공유",
"navbar.links.reverse": "역방향 공유",
"navbar.avatar.account": "내 계정",
"navbar.avatar.admin": "관리자",
"navbar.avatar.signout": "로그아웃",
// END navbar
// /
"home.title": "<h>직접 호스팅</h>하는 파일 공유 플랫폼.",
"home.description":
"정말 WeTransfer와 같은 제3자에게 개인 파일을 맡기고 싶으세요?",
"home.bullet.a.name": "직접 호스팅",
"home.bullet.a.description":
"자신의 컴퓨터에서 Pingvin Share를 호스팅하세요.",
"home.bullet.b.name": "개인 정보 보호",
"home.bullet.b.description":
"당신의 파일은 당신의 것이므로 절대로 제3자의 손에 들어가서는 안 됩니다.",
"home.bullet.c.name": "귀찮은 파일 크기 제한 없음",
"home.bullet.c.description":
"원하는 만큼 큰 파일을 업로드하세요. 오직 여러분의 하드 디스크만이 한계가 될 것입니다.",
"home.button.start": "시작하기",
"home.button.source": "소스 코드",
// END /
// /auth/signin
"signin.title": "다시 오신 것을 환영합니다!",
"signin.description": "아직 계정이 없으신가요?",
"signin.button.signup": "계정 만들기",
"signin.input.email-or-username": "이메일 또는 사용자 이름",
"signin.input.email-or-username.placeholder":
"당신의 이메일 또는 사용자 이름",
"signin.input.password": "비밀번호",
"signin.input.password.placeholder": "당신의 비밀번호",
"signin.button.submit": "로그인",
"signIn.notify.totp-required.title": "2단계 인증이 필요합니다",
"signIn.notify.totp-required.description": "2단계 인증 코드를 입력해주세요",
"signIn.oauth.or": "또는",
"signIn.oauth.github": "깃허브",
"signIn.oauth.google": "구글",
"signIn.oauth.microsoft": "마이크로소프트",
"signIn.oauth.discord": "디스코드",
"signIn.oauth.oidc": "오픈ID",
// END /auth/signin
// /auth/signup
"signup.title": "계정 만들기",
"signup.description": "이미 계정이 있으신가요?",
"signup.button.signin": "로그인",
"signup.input.username": "사용자 이름",
"signup.input.username.placeholder": "당신의 사용지 이름",
"signup.input.email": "이메일",
"signup.input.email.placeholder": "당신의 이메일",
"signup.button.submit": "시작하기",
// END /auth/signup
// /auth/totp
"totp.title": "TOTP 인증",
"totp.button.signIn": "로그인",
// END /auth/totp
// /auth/reset-password
"resetPassword.title": "비밀번호를 잊으셨나요?",
"resetPassword.description": "비밀번호를 재설정하려면 이메일을 입력하세요.",
"resetPassword.notify.success":
"이메일이 존재한다면 비밀번호를 재설정하는 링크를 포함한 메시지가 발송되었습니다.",
"resetPassword.button.back": "로그인 페이지로 돌아가기",
"resetPassword.text.resetPassword": "비밀번호 재설정",
"resetPassword.text.enterNewPassword": "새로운 비밀번호를 입력하세요",
"resetPassword.input.password": "새로운 비밀번호",
"resetPassword.notify.passwordReset":
"비밀번호가 성공적으로 재설정되었습니다.",
// /account
"account.title": "내 계정",
"account.card.info.title": "계정 정보",
"account.card.info.username": "사용자 이름",
"account.card.info.email": "이메일",
"account.notify.info.success": "계정이 업데이트되었습니다.",
"account.card.password.title": "비밀번호",
"account.card.password.old": "기존 비밀번호",
"account.card.password.new": "새로운 비밀번호",
"account.card.password.noPasswordSet":
"비밀번호를 설정하지 않았습니다. 이메일과 비밀번호로 로그인하려면 비밀번호를 설정해야 합니다.",
"account.notify.password.success": "비밀번호 변경 완료",
"account.card.oauth.title": "소셜 로그인",
"account.card.oauth.github": "깃허브",
"account.card.oauth.google": "구글",
"account.card.oauth.microsoft": "마이크로소프트",
"account.card.oauth.discord": "디스코드",
"account.card.oauth.oidc": "오픈ID",
"account.card.oauth.link": "연결",
"account.card.oauth.unlink": "연결 해제",
"account.card.oauth.unlinked": "연결 해제",
"account.modal.unlink.title": "계정 연결 해제",
"account.modal.unlink.description":
"소셜 계정 연결을 해제하면 사용자 이름과 비밀번호를 기억하지 못할 경우 계정을 잃을 수 있습니다.",
"account.notify.oauth.unlinked.success": "연결 해제됨",
"account.card.security.title": "보안",
"account.card.security.totp.enable.description":
"TOTP 활성화를 시작하려면 현재 비밀번호를 입력하세요.",
"account.card.security.totp.disable.description":
"TOTP 를 비활성화 하려면 비밀번호를 입력하세요.",
"account.card.security.totp.button.start": "시작",
"account.modal.totp.title": "TOTP 활성화",
"account.modal.totp.step1": "1단계: 인증기를 추가하세요.",
"account.modal.totp.step2": "2 단계: 코드 유효성 검사",
"account.modal.totp.enterManually": "직접 입력",
"account.modal.totp.code": "코드",
"common.button.clickToCopy": "클릭하여 복사",
"account.modal.totp.verify": "인증",
"account.notify.totp.disable": "TOTP가 비활성화되었습니다.",
"account.notify.totp.enable": "TOTP가 활성화 되었습니다.",
"account.card.language.title": "언어",
"account.card.language.description":
"이 프로젝트는 커뮤니티에 의해 번역됩니다. 일부 언어는 불완전할 수 있습니다.",
"account.card.color.title": "배경 설정",
// ThemeSwitcher.tsx
"account.theme.dark": "어두운 배경",
"account.theme.light": "밝은 배경",
"account.theme.system": "시스템",
"account.button.delete": "계정 삭제",
"account.modal.delete.title": "계정 삭제",
"account.modal.delete.description":
"정말로 활성화된 모든 공유를 포함하여 계정을 삭제하시겠습니까?",
// END /account
// /account/shares
"account.shares.title": "내 공유",
"account.shares.title.empty": "이곳은 아무것도 없는것 같아요 👀",
"account.shares.description.empty": "당신은 아무것도 공유한것이 없어요.",
"account.shares.button.create": "파일 업로드",
"account.shares.info.title": "공유 정보",
"account.shares.table.id": "ID",
"account.shares.table.name": "이름",
"account.shares.table.description": "설명",
"account.shares.table.visitors": "방문자",
"account.shares.table.expiresAt": "만료일",
"account.shares.table.createdAt": "생성일",
"account.shares.table.size": "크기",
"account.shares.modal.share-informations": "공유 정보",
"account.shares.modal.share-link": "공유 링크",
"account.shares.modal.delete.title": "공유 삭제 {share}",
"account.shares.modal.delete.description":
"정말로 이 공유를 삭제하시겠습니까?",
// END /account/shares
// /account/reverseShares
"account.reverseShares.title": "역방향 공유",
"account.reverseShares.description":
"역방향 공유를 통해 외부 사용자가 공유를 생성할 수 있는 고유 URL을 생성할 수 있습니다.",
"account.reverseShares.title.empty": "이곳은 아무것도 없는것 같아요 👀",
"account.reverseShares.description.empty": "당신은 역방향 공유한것이 없어요.",
// showCreateReverseShareModal.tsx
"account.reverseShares.modal.title": "새로운 역방향 공유 생성",
"account.reverseShares.modal.expiration.label": "만료일",
"account.reverseShares.modal.expiration.minute-singular": "분",
"account.reverseShares.modal.expiration.minute-plural": "분",
"account.reverseShares.modal.expiration.hour-singular": "시",
"account.reverseShares.modal.expiration.hour-plural": "시",
"account.reverseShares.modal.expiration.day-singular": "일",
"account.reverseShares.modal.expiration.day-plural": "일",
"account.reverseShares.modal.expiration.week-singular": "주",
"account.reverseShares.modal.expiration.week-plural": "주",
"account.reverseShares.modal.expiration.month-singular": "개월",
"account.reverseShares.modal.expiration.month-plural": "개월",
"account.reverseShares.modal.expiration.year-singular": "년",
"account.reverseShares.modal.expiration.year-plural": "년",
"account.reverseShares.modal.max-size.label": "최대 공유 크기",
"account.reverseShares.modal.send-email": "이메일 알림 보내기",
"account.reverseShares.modal.send-email.description":
"이 역방향 공유 링크를 사용하여 공유가 생성되면 이메일 알림을 보냅니다.",
"account.reverseShares.modal.max-use.label": "공유 생성 제한",
"account.reverseShares.modal.max-use.description":
"이 URL을 사용하여 공유를 생성할 수 있는 최대 횟수입니다.",
"account.reverseShare.never-expires": "이 역공유 링크는 만료되지 않습니다.",
"account.reverseShare.expires-on":
"이 역방향 공유는 {expiration} 에 만료됩니다.",
"account.reverseShares.table.no-shares": "아직 생성된 공유가 없습니다.",
"account.reverseShares.table.count.singular": "공유",
"account.reverseShares.table.count.plural": "공유",
"account.reverseShares.table.shares": "공유",
"account.reverseShares.table.remaining": "남은 링크 사용 횟수",
"account.reverseShares.table.max-size": "최대 공유 크기",
"account.reverseShares.table.expires": "만료 날짜",
"account.reverseShares.modal.reverse-share-link": "역방향 공유 링크",
"account.reverseShares.modal.delete.title": "역방향 공유 삭제",
"account.reverseShares.modal.delete.description": "이 역방향 공유를 삭제하시겠습니까? 삭제하면 관련 공유도 삭제됩니다.",
// END /account/reverseShares
// /admin
"admin.title": "관리자",
"admin.button.users": "사용자 관리",
"admin.button.shares": "공유 관리",
"admin.button.config": "구성",
"admin.version": "버전",
// END /admin
// /admin/users
"admin.users.title": "사용자 관리",
"admin.users.table.username": "사용자 이름",
"admin.users.table.email": "이메일",
"admin.users.table.admin": "관리자",
"admin.users.edit.update.title": "{username} 사용자 업데이트",
"admin.users.edit.update.admin-privileges": "Admin Privilege",
"admin.users.edit.update.change-password.title": "비밀번호 변경",
"admin.users.edit.update.change-password.field": "새로운 비밀번호",
"admin.users.edit.update.change-password.button": "새 비밀번호 저장",
"admin.users.edit.update.notify.password.success": "비밀번호 변경 완료",
"admin.users.edit.delete.title": "{username} 사용자 삭제",
"admin.users.edit.delete.description": "이 사용자의 모든 공유를 삭제하시겠습니까?",
// showCreateUserModal.tsx
"admin.users.modal.create.title": "사용자 생성",
"admin.users.modal.create.username": "사용자 이름",
"admin.users.modal.create.email": "이메일",
"admin.users.modal.create.password": "비밀번호",
"admin.users.modal.create.manual-password": "수동 암호 설정",
"admin.users.modal.create.manual-password.description": "선택하지 않으면 사용자는 암호를 설정할 수 있는 링크가 포함된 이메일을 받게 됩니다.",
"admin.users.modal.create.admin": "Admin Privilege",
"admin.users.modal.create.admin.description": "이 옵션을 선택하면 사용자는 관리 패널에 액세스할 수 있습니다.",
// END /admin/users
// /admin/shares
"admin.shares.title": "공유 관리",
"admin.shares.table.id": "공유 ID",
"admin.shares.table.username": "만든이",
"admin.shares.table.visitors": "방문자",
"admin.shares.table.expires": "만료일",
"admin.shares.edit.delete.title": "공유 삭제 {id}",
"admin.shares.edit.delete.description": "정말로 이 공유를 삭제하시겠습니까?",
// END /admin/shares
// /upload
"upload.title": "업로드",
"upload.notify.generic-error": "공유를 완료하는 동안 오류가 발생했습니다.",
"upload.notify.count-failed": "{count}개의 파일을 업로드하지 못했습니다. 다시 시도하세요.",
// Dropzone.tsx
"upload.dropzone.title": "파일 업로드",
"upload.dropzone.description": "파일을 여기로 드래그&드랍하여 파일 업로드를 시작합니다. {maxSize} 를 초과하지 않는 파일만 업로드할 수 있습니다.",
"upload.dropzone.notify.file-too-big": "파일이 {maxSize} 의 최대 공유 크기를 초과합니다.",
// FileList.tsx
"upload.filelist.name": "이름",
"upload.filelist.size": "크기",
// showCreateUploadModal.tsx
"upload.modal.title": "공유 생성",
"upload.modal.link.error.invalid": "문자, 숫자, 밑줄 및 하이픈만 포함할 수 있습니다",
"upload.modal.link.error.taken": "이미 사용 중인 링크입니다",
"upload.modal.not-signed-in": "로그인하지 않았습니다",
"upload.modal.not-signed-in-description": "공유를 수동으로 삭제하고 방문자 수를 볼 수 없습니다.",
"upload.modal.expires.never": "절대 안 함",
"upload.modal.expires.never-long": "만료 없음",
"upload.modal.expires.error.too-long": "만료가 {max} 의 최대 만료일을 초과합니다.",
"upload.modal.link.label": "링크",
"upload.modal.expires.label": "만료일",
"upload.modal.expires.minute-singular": "분",
"upload.modal.expires.minute-plural": "분",
"upload.modal.expires.hour-singular": "시",
"upload.modal.expires.hour-plural": "시",
"upload.modal.expires.day-singular": "일",
"upload.modal.expires.day-plural": "일",
"upload.modal.expires.week-singular": "주",
"upload.modal.expires.week-plural": "주",
"upload.modal.expires.month-singular": "개월",
"upload.modal.expires.month-plural": "개월",
"upload.modal.expires.year-singular": "년",
"upload.modal.expires.year-plural": "년",
"upload.modal.accordion.name-and-description.title": "이름과 설명",
"upload.modal.accordion.name-and-description.name.placeholder": "이름",
"upload.modal.accordion.name-and-description.description.placeholder": "공유를 받을 사람에게 메모",
"upload.modal.accordion.email.title": "받는 사람 메일 주소",
"upload.modal.accordion.email.placeholder": "메일 주소 입력",
"upload.modal.accordion.email.invalid-email": "이메일 주소가 틀립니다",
"upload.modal.accordion.security.title": "보안 설정",
"upload.modal.accordion.security.password.label": "비밀번호로 보호",
"upload.modal.accordion.security.password.placeholder": "비밀번호 없음",
"upload.modal.accordion.security.max-views.label": "최대 보기 횟수",
"upload.modal.accordion.security.max-views.placeholder": "제한 없음",
// showCompletedUploadModal.tsx
"upload.modal.completed.never-expires": "이 공유 만료되지 않습니다.",
"upload.modal.completed.expires-on": "이 공유는 {expiration} 에 만료됩니다.",
"upload.modal.completed.share-ready": "공유 준비",
// END /upload
// /share/[id]
"share.title": "공유 {shareId}",
"share.description": "내가 당신과 공유한 것을 보세요!",
"share.error.visitor-limit-exceeded.title": "방문자 제한 초과",
"share.error.visitor-limit-exceeded.description": "The visitor limit from this share has been exceeded.",
"share.error.removed.title": "공유가 삭제됨",
"share.error.not-found.title": "공유를 찾을 수 없습니다.",
"share.error.not-found.description": "당신이 찾는 공유는 존재하지 않습니다.",
"share.modal.password.title": "비밀번호 필요",
"share.modal.password.description": "이 공유에 액세스하려면 공유의 암호를 입력하십시오.",
"share.modal.password": "비밀번호",
"share.modal.error.invalid-password": "잘못된 비밀번호",
"share.button.download-all": "모두 다운로드",
"share.notify.download-all-preparing": "공유가 준비 중입니다. 잠시 후에 다시 시도하십시오.",
"share.modal.file-link": "파일 링크",
"share.table.name": "이름",
"share.table.size": "크기",
"share.modal.file-preview.error.not-supported.title": "미리보기는 지원되지 않습니다",
"share.modal.file-preview.error.not-supported.description": "이 파일 형식의 미리보기가 지원되지 않습니다. 파일을 다운로드하여 확인하십시오.",
// END /share/[id]
// /share/[id]/edit
"share.edit.title": "수정 {shareId}",
"share.edit.append-upload": "파일 추가",
"share.edit.notify.generic-error": "공유를 완료하는 동안 오류가 발생했습니다.",
"share.edit.notify.save-success": "공유가 업데이트 되었습니다.",
// END /share/[id]/edit
// /admin/config
"admin.config.title": "구성",
"admin.config.category.general": "일반",
"admin.config.category.share": "공유",
"admin.config.category.email": "이메일",
"admin.config.category.smtp": "SMTP",
"admin.config.category.oauth": "소셜 로그인",
"admin.config.general.app-name": "앱 이름",
"admin.config.general.app-name.description": "Name of the application",
"admin.config.general.app-url": "앱 URL",
"admin.config.general.app-url.description": "Pingvin Share를 사용할 수 있는 URL",
"admin.config.general.show-home-page": "홈 페이지 표시",
"admin.config.general.show-home-page.description": "홈 페이지를 표시할지 여부를 점검하십시오.",
"admin.config.general.logo": "로고",
"admin.config.general.logo.description": "새 이미지를 업로드하여 로고를 변경하십시오. 이미지는 PNG여야 하며 1:1 비율이어야 합니다.",
"admin.config.general.logo.placeholder": "이미지 선택",
"admin.config.email.enable-share-email-recipients": "메일 수신 허용",
"admin.config.email.enable-share-email-recipients.description": "메일이 수신자를 공유하도록 허용할지 여부. SMTP를 사용 가능으로 설정한 경우에만 이 옵션을 사용 가능으로 설정합니다.",
"admin.config.email.share-recipients-subject": "공유 제목",
"admin.config.email.share-recipients-subject.description": "공유 수신자에게 전송되는 이메일의 제목입니다.",
"admin.config.email.share-recipients-message": "수신자 메시지 공유",
"admin.config.email.share-recipients-message.description": "공유 수신자에게 보내는 메시지입니다. 사용 가능한 변수:\n {creator} - 공유 작성자의 사용자 이름\n {shareUrl} - 공유의 URL\n {desc} - 공유에 대한 설명\n {expires} - 공유 만료일\n 변수는 실제 값으로 대체됩니다.",
"admin.config.email.reverse-share-subject": "역공유 제목",
"admin.config.email.reverse-share-subject.description": "누군가 당신이 공유한 역방향 공유 링크를 사용하여 공유를 생성했을 때 전송되는 이메일의 제목입니다.",
"admin.config.email.reverse-share-message": "역공유 메시지",
"admin.config.email.reverse-share-message.description": "누군가 귀하의 역방향 공유 링크를 사용하여 공유를 생성하면 전송되는 메시지입니다.. {shareUrl} 은 작성자 이름 및 공유 URL로 대체됩니다.",
"admin.config.email.reset-password-subject": "비밀번호 재설정 제목",
"admin.config.email.reset-password-subject.description": "사용자가 암호 재설정을 요청할 때 전송되는 메일의 제목입니다.",
"admin.config.email.reset-password-message": "비밀번호 재설정 메시지",
"admin.config.email.reset-password-message.description": "사용자가 비밀번호 재설정을 요청할 때 전송되는 메시지입니다. {url} 은 비밀번호 재설정 URL로 대체됩니다.",
"admin.config.email.invite-subject": "초대 제목",
"admin.config.email.invite-subject.description": "관리자가 사용자를 초대할 때 전송되는 이메일의 제목입니다.",
"admin.config.email.invite-message": "초대 메시지",
"admin.config.email.invite-message.description": "관리자가 사용자를 초대하면 전송되는 메시지입니다. {url} 은 초대 URL로, {password} 는 비밀번호로 대체됩니다.",
"admin.config.share.allow-registration": "가입 허용",
"admin.config.share.allow-registration.description": "등록 가능 여부",
"admin.config.share.allow-unauthenticated-shares": "인증되지 않은 공유 허용",
"admin.config.share.allow-unauthenticated-shares.description": "인증되지 않은 사용자가 공유를 생성할 수 있는지 여부",
"admin.config.share.max-expiration": "최대 만료일",
"admin.config.share.max-expiration.description": "최대 공유 만료 시간입니다. 만료 기간을 설정하지 않는경우 0으로 설정합니다.",
"admin.config.share.max-size": "최대 크기",
"admin.config.share.max-size.description": "공유 최대 크기 - 바이트",
"admin.config.share.zip-compression-level": "압축 레벨",
"admin.config.share.zip-compression-level.description": "파일 크기와 압축 속도 간의 균형을 맞추도록 레벨을 조정합니다. 유효한 값의 범위는 0에서 9까지이며, 0은 압축되지 않고 9는 최대 압축입니다. ",
"admin.config.share.chunk-size": "청크 크기",
"admin.config.share.chunk-size.description": "업로드할 청크 크기(바이트 단위)를 조정하여 인터넷 연결에 따라 효율성과 신뢰성의 균형을 유지합니다. 더 작은 청크는 불안정한 연결에 대한 성공률을 향상시킬 수 있고, 더 큰 청크는 안정적인 연결에 대한 업로드 속도를 높일 수 있습니다.",
"admin.config.smtp.enabled": "활성화됨",
"admin.config.smtp.enabled.description": "SMTP 사용 여부 SMTP 서버의 호스트, 포트, 전자 메일, 사용자 및 암호를 입력한 경우에만 true로 설정합니다.",
"admin.config.smtp.host": "호스트",
"admin.config.smtp.host.description": "SMTP 서버의 호스트",
"admin.config.smtp.port": "포트",
"admin.config.smtp.port.description": "SMTP 서버 포트",
"admin.config.smtp.email": "이메일",
"admin.config.smtp.email.description": "전자 메일을 보낸 전자 메일 주소",
"admin.config.smtp.username": "사용자 이름",
"admin.config.smtp.username.description": "SMTP 사용자 이름, 서버 비밀번호",
"admin.config.smtp.password": "비밀번호",
"admin.config.smtp.password.description": "SMTP 서버 비밀번호",
"admin.config.smtp.button.test": "테스트 이메일 보내기",
"admin.config.oauth.allow-registration": "가입 허용",
"admin.config.oauth.allow-registration.description": "사용자가 소셜 로그인을 통해 등록할 수 있도록 허용",
"admin.config.oauth.ignore-totp": "TOTP 무시",
"admin.config.oauth.ignore-totp.description": "사용자가 소셜 로그인을 사용하는 경우 TOTP를 무시할 것인지 여부",
"admin.config.oauth.github-enabled": "깃허브",
"admin.config.oauth.github-enabled.description": "깃허브 로그인 사용 여부",
"admin.config.oauth.github-client-id": "GitHub 클라이언트 ID",
"admin.config.oauth.github-client-id.description": "GitHub OAuth 앱의 클라이언트 ID",
"admin.config.oauth.github-client-secret": "GitHub 클라이언트 secret",
"admin.config.oauth.github-client-secret.description": "GitHub OAuth 앱의 클라이언트 secret",
"admin.config.oauth.google-enabled": "구글",
"admin.config.oauth.google-enabled.description": "구글 로그인 활성화 여부",
"admin.config.oauth.google-client-id": "Google 클라이언트 ID",
"admin.config.oauth.google-client-id.description": "Google OAuth 앱의 클라이언트 ID",
"admin.config.oauth.google-client-secret": "Google 클라이언트 secret",
"admin.config.oauth.google-client-secret.description": "Google OAuth 앱의 클라이언트 secret",
"admin.config.oauth.microsoft-enabled": "마이크로소프트",
"admin.config.oauth.microsoft-enabled.description": "마이크로소프트 로그인 사용 여부",
"admin.config.oauth.microsoft-tenant": "마이크로소프트 테넌트",
"admin.config.oauth.microsoft-tenant.description": "Microsoft OAuth 앱의 테넌트 ID\n공통: Microsoft 개인 계정과 Microsoft Entra ID의 직장 또는 학교 계정을 모두 가진 사용자는 응용 프로그램에 로그인할 수 있습니다. 조직: Microsoft Entra ID의 직장 또는 학교 계정을 가진 사용자만 응용 프로그램에 로그인할 수 있습니다.\n소비자: 개인 마이크로소프트 계정을 가진 사용자만 애플리케이션에 로그인할 수 있습니다.\nMicrosoft Entra 테넌트의 도메인 이름 또는 GUID 형식의 테넌트 ID: 특정 Microsoft Entra 테넌트의 사용자(직장 또는 학교 계정을 가진 디렉토리 구성원 또는 개인 Microsoft 계정을 가진 디렉토리 게스트)만 응용 프로그램에 로그인할 수 있습니다.",
"admin.config.oauth.microsoft-client-id": "마이크로소프트 클라이언트 ID",
"admin.config.oauth.microsoft-client-id.description": "Microsoft OAuth 앱의 클라이언트 ID",
"admin.config.oauth.microsoft-client-secret": "Microsoft 클라이언트 secret",
"admin.config.oauth.microsoft-client-secret.description": "Microsoft OAuth 앱의 클라이언트 비밀",
"admin.config.oauth.discord-enabled": "디스코드",
"admin.config.oauth.discord-enabled.description": "Discord 로그인 활성화 여부",
"admin.config.oauth.discord-limited-guild": "디스코드 제한 서버 ID",
"admin.config.oauth.discord-limited-guild.description": "특정 서버의 사용자로 로그인을 제한합니다. 사용하지 않으려면 비워 둡니다.",
"admin.config.oauth.discord-client-id": "디스코드 클라이언트 ID",
"admin.config.oauth.discord-client-id.description": "Discord OAuth 앱의 클라이언트 ID",
"admin.config.oauth.discord-client-secret": "Discord 클라이언트 secret",
"admin.config.oauth.discord-client-secret.description": "Discord OAuth 앱의 클라이언트 secret",
"admin.config.oauth.oidc-enabled": "OpenID 연결",
"admin.config.oauth.oidc-enabled.description": "OpenID Connect 로그인 사용 여부",
"admin.config.oauth.oidc-discovery-uri": "OpenID Connect Discovery URI",
"admin.config.oauth.oidc-discovery-uri.description":
"Discovery URI of the OpenID Connect OAuth app",
"admin.config.oauth.oidc-username-claim": "OpenID Connect username claim",
"admin.config.oauth.oidc-username-claim.description": "OpenID Connect ID 토큰의 Username claim 입니다. 이 구성이 무엇인지 모르면 비워 둡니다.",
"admin.config.oauth.oidc-client-id": "OpenID Connect 클라이언트 ID",
"admin.config.oauth.oidc-client-id.description": "OpenID Connect OAuth 앱의 클라이언트 ID",
"admin.config.oauth.oidc-client-secret": "OpenID 클라이언트 secret",
"admin.config.oauth.oidc-client-secret.description": "OpenID Connect OAuth 앱의 클라이언트 secret",
// 404
"404.description": "이런, 이 페이지는 존재하지 않습니다.",
"404.button.home": "나를 집으로 데려다 줘",
// error
"error.title": "에러",
"error.description": "이런!",
"error.button.back": "뒤로 가기",
"error.msg.default": "문제가 발생했습니다",
"error.msg.access_denied": "인증 프로세스가 취소되었습니다. 다시 시도하십시오.",
"error.msg.expired_token": "인증 절차가 너무 오래 걸렸습니다. 다시 시도하십시오.",
"error.msg.invalid_token": "내부 오류",
"error.msg.no_user": "{0} 계정에 연결된 사용자가 없습니다.",
"error.msg.no_email": "이 {0} 계정에서 메일 주소를 가져올 수 없습니다.",
"error.msg.already_linked": "이 {0} 계정은 이미 다른 계정에 연결되어 있습니다.",
"error.msg.not_linked": "이 {0} 계정은 아직 어떤 계정에도 연결되지 않았습니다.",
"error.msg.unverified_account": "이 {0} 계정은 확인되지 않았습니다. 확인 후 다시 시도하십시오.",
"error.msg.discord_guild_permission_denied": "로그인할 수 없습니다.",
"error.msg.cannot_get_user_info": "이 {0} 계정에서 사용자 정보를 가져올 수 없습니다",
"error.param.provider_github": "깃허브",
"error.param.provider_google": "구글",
"error.param.provider_microsoft": "마이크로소프트",
"error.param.provider_discord": "디스코드",
"error.param.provider_oidc": "OpenID 연결",
// Common translations
"common.button.save": "저장",
"common.button.create": "새로 만들기",
"common.button.submit": "제출",
"common.button.delete": "삭제",
"common.button.cancel": "취소",
"common.button.confirm": "확인",
"common.button.disable": "비활성화",
"common.button.share": "공유",
"common.button.generate": "생성",
"common.button.done": "완료",
"common.text.link": "링크",
"common.text.navigate-to-link": "링크로 이동",
"common.text.or": "또는",
"common.button.go-back": "뒤로 가기",
"common.button.go-home": "첫 페이지",
"common.notify.copied": "당신의 링크가 클립보드에 복사되었습니다.",
"common.success": "성공",
"common.error": "에러",
"common.error.unknown": "알 수 없는 오류가 발생했습니다.",
"common.error.invalid-email": "이메일 주소가 틀립니다",
"common.error.too-short": "최소 {length} 자 이상이어야 합니다",
"common.error.too-long": "최대 {length} 자 까지 입력가능합니다.",
"common.error.exact-length": "{length} 자 이어야 합니다.",
"common.error.invalid-number": "숫자만 가능합니다.",
"common.error.field-required": "이 필드는 필수입니다"
};

View File

@@ -107,7 +107,7 @@ export default {
"account.modal.totp.step2": "Stap 2: Valideer uw code",
"account.modal.totp.enterManually": "Handmatig invoeren",
"account.modal.totp.code": "Code",
"account.modal.totp.clickToCopy": "Klik om te kopiëren",
"common.button.clickToCopy": "Klik om te kopiëren",
"account.modal.totp.verify": "Verifiëren",
"account.notify.totp.disable": "TOTP succesvol uitgeschakeld",
"account.notify.totp.enable": "TOTP succesvol ingeschakeld",
@@ -192,6 +192,7 @@ export default {
// /admin
"admin.title": "Instellingen",
"admin.button.users": "Gebruikers beheer",
"admin.button.shares": "Share management",
"admin.button.config": "Configuratie",
"admin.version": "Versie",
// END /admin
@@ -222,6 +223,16 @@ export default {
"admin.users.modal.create.admin.description":
"Indien aangevinkt, heeft de gebruiker toegang tot de beheeromgeving.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Uploaden",
"upload.notify.generic-error":
@@ -263,9 +274,10 @@ export default {
"upload.modal.expires.month-plural": "Maanden",
"upload.modal.expires.year-singular": "Jaar",
"upload.modal.expires.year-plural": "Jaren",
"upload.modal.accordion.description.title": "Beschrijving",
"upload.modal.accordion.description.placeholder":
"Opmerking voor de ontvangers van deze share",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "E-mail van de ontvangers",
"upload.modal.accordion.email.placeholder": "Voer e-mail ontvangers in",
"upload.modal.accordion.email.invalid-email": "Ongeldig e-mailadres",
@@ -380,6 +392,9 @@ export default {
"admin.config.share.zip-compression-level": "Zip compressie niveau",
"admin.config.share.zip-compression-level.description":
"Pas het niveau aan voor evenwicht tussen bestandsgrootte en compressie snelheid. Geldige waarden variëren van 0 tot 9, waarbij 0 geen compressie is en 9 de maximale compressie is. ",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "Inschakelen",
"admin.config.smtp.enabled.description":
"Of SMTP is ingeschakeld. Stel dit alleen in op true als u de host hebt ingevoerd, poort, e-mail, gebruiker en wachtwoord van uw SMTP-server.",

View File

@@ -66,7 +66,7 @@ export default {
"resetPassword.description":
"Wprowadź swój e-mail, aby zresetować swoje hasło.",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"Jeśli e-mail istnieje, to została wysłana wiadomość z linkiem do zresetowania hasła.",
"resetPassword.button.back": "Powrót do strony logowania",
"resetPassword.text.resetPassword": "Resetuj hasło",
"resetPassword.text.enterNewPassword": "Wprowadź nowe hasło",
@@ -108,7 +108,7 @@ export default {
"account.modal.totp.step2": "Krok 2: Potwierdź swój kod",
"account.modal.totp.enterManually": "Wpisz ręcznie",
"account.modal.totp.code": "Kod",
"account.modal.totp.clickToCopy": "Kliknij, aby skopiować",
"common.button.clickToCopy": "Kliknij, aby skopiować",
"account.modal.totp.verify": "Weryfikuj",
"account.notify.totp.disable": "%s wyłączono pomyślnie",
"account.notify.totp.enable": "TOTP włączono pomyślnie",
@@ -193,6 +193,7 @@ export default {
// /admin
"admin.title": "Administracja",
"admin.button.users": "Zarządzanie użytkownikami",
"admin.button.shares": "Share management",
"admin.button.config": "Konfiguracja",
"admin.version": "Wersja",
// END /admin
@@ -223,6 +224,16 @@ export default {
"admin.users.modal.create.admin.description":
"Jeśli zaznaczone, użytkownik będzie miał dostęp do panelu administratora.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Prześlij",
"upload.notify.generic-error":
@@ -264,9 +275,10 @@ export default {
"upload.modal.expires.month-plural": "Miesiące/ęcy",
"upload.modal.expires.year-singular": "Rok",
"upload.modal.expires.year-plural": "Lat/a",
"upload.modal.accordion.description.title": "Opis",
"upload.modal.accordion.description.placeholder":
"Notatka dla odbiorców tego udziału",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Odbiorcy wiadomości e-mail",
"upload.modal.accordion.email.placeholder":
"Wprowadź adresatów wiadomości e-mail",
@@ -382,6 +394,9 @@ export default {
"admin.config.share.zip-compression-level": "Poziom kompresji Zip",
"admin.config.share.zip-compression-level.description":
"Dostosuj poziom do równowagi między rozmiarem pliku a szybkością kompresji. Prawidłowe wartości mieszczą się w zakresie od 0 do 9, przy czym 0 to brak kompresji a 9 maksymalną kompresją. ",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "Włączony",
"admin.config.smtp.enabled.description":
"Czy SMTP ma zostać włączony. Ustaw to, tylko jeśli wprowadziłeś host, port, e-mail, nazwę użytkownika i hasło serwera SMTP.",

View File

@@ -66,7 +66,7 @@ export default {
"resetPassword.description":
"Insira o seu e-mail para redefinir a sua senha.",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"Uma mensagem com um link para redefinir sua senha foi enviada se o e-mail existir.",
"resetPassword.button.back": "Voltar para a página inicial",
"resetPassword.text.resetPassword": "Redefinir senha",
"resetPassword.text.enterNewPassword": "Digite uma nova senha",
@@ -109,7 +109,7 @@ export default {
"account.modal.totp.step2": "Passo 2: Valide o seu código",
"account.modal.totp.enterManually": "Inserir manualmente",
"account.modal.totp.code": "Código",
"account.modal.totp.clickToCopy": "Clique para copiar",
"common.button.clickToCopy": "Clique para copiar",
"account.modal.totp.verify": "Verificar",
"account.notify.totp.disable": "TOTP desabilitado com sucesso",
"account.notify.totp.enable": "TOTP habilitado com sucesso",
@@ -197,6 +197,7 @@ export default {
// /admin
"admin.title": "Administração",
"admin.button.users": "Gerenciamento de usuários",
"admin.button.shares": "Gerenciamento de compartilhamentos",
"admin.button.config": "Configuração",
"admin.version": "Versão",
// END /admin
@@ -227,6 +228,16 @@ export default {
"admin.users.modal.create.admin.description":
"Se marcado, o usuário poderá acessar o painel de administração.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Gerenciamento de compartilhamentos",
"admin.shares.table.id": "ID do Compartilhamento",
"admin.shares.table.username": "Criador",
"admin.shares.table.visitors": "Visitantes",
"admin.shares.table.expires": "Expira em",
"admin.shares.edit.delete.title": "Excluir compartilhamento {id}",
"admin.shares.edit.delete.description":
"Tem certeza que deseja excluir este compartilhamento?",
// END /admin/shares
// /upload
"upload.title": "Carregar",
"upload.notify.generic-error":
@@ -268,8 +279,9 @@ export default {
"upload.modal.expires.month-plural": "Meses",
"upload.modal.expires.year-singular": "Ano",
"upload.modal.expires.year-plural": "Anos",
"upload.modal.accordion.description.title": "Descrição",
"upload.modal.accordion.description.placeholder":
"upload.modal.accordion.name-and-description.title": "Nome e descrição",
"upload.modal.accordion.name-and-description.name.placeholder": "Nome",
"upload.modal.accordion.name-and-description.description.placeholder":
"Nota para os destinatários deste compartilhamento",
"upload.modal.accordion.email.title": "Destinatários de e-mail",
"upload.modal.accordion.email.placeholder":
@@ -388,6 +400,9 @@ export default {
"admin.config.share.zip-compression-level": "Nível de compressão",
"admin.config.share.zip-compression-level.description":
"Ajuste o nível para equilibrar entre o tamanho do arquivo e a velocidade de compressão. Valores válidos vão de 0 a 9, com 0 sendo sem compressão e 9 sendo compressão máxima. ",
"admin.config.share.chunk-size": "Tamanho do pedaço",
"admin.config.share.chunk-size.description":
"Ajuste o tamanho do pedaço (em bytes) para seus uploads equilibrarem eficiência e confiabilidade de acordo com sua conexão com a internet. Pedaços menores podem aumentar as taxas de sucesso para conexões instáveis, enquanto partes maiores aceleram uploads para conexões estáveis.",
"admin.config.smtp.enabled": "Ativado",
"admin.config.smtp.enabled.description":
"Se o SMTP está habilitado. Apenas defina como verdadeiro se você digitou o servidor, porta, e-mail, usuário e senha do seu servidor SMTP.",

View File

@@ -104,7 +104,7 @@ export default {
"account.modal.totp.step2": "Шаг 2: Проверка кода",
"account.modal.totp.enterManually": "Ввести вручную",
"account.modal.totp.code": "Код",
"account.modal.totp.clickToCopy": "Нажмите, чтобы скопировать",
"common.button.clickToCopy": "Нажмите, чтобы скопировать",
"account.modal.totp.verify": "Подтвердить",
"account.notify.totp.disable": "TOTP успешно отключен",
"account.notify.totp.enable": "TOTP успешно включен",
@@ -189,6 +189,7 @@ export default {
// /admin
"admin.title": "Администрирование",
"admin.button.users": "Управление пользователями",
"admin.button.shares": "Share management",
"admin.button.config": "Конфигурация",
"admin.version": "Версия",
// END /admin
@@ -218,6 +219,16 @@ export default {
"admin.users.modal.create.admin.description":
"Если отмечено, пользователь будет иметь доступ к панели администратора.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Загрузить",
"upload.notify.generic-error":
@@ -259,9 +270,9 @@ export default {
"upload.modal.expires.month-plural": "Месяца(-ев)",
"upload.modal.expires.year-singular": "Год",
"upload.modal.expires.year-plural": "Года (лет)",
"upload.modal.accordion.description.title": "Описание",
"upload.modal.accordion.description.placeholder":
"Примечание для получателей этой загрузки",
"upload.modal.accordion.name-and-description.title": "Имя и описание",
"upload.modal.accordion.name-and-description.name.placeholder": "Имя",
"upload.modal.accordion.name-and-description.description.placeholder": "Note for the recipients of this share",
"upload.modal.accordion.email.title": "Получатели письма",
"upload.modal.accordion.email.placeholder": "Получатели e-mail",
"upload.modal.accordion.email.invalid-email":
@@ -372,8 +383,9 @@ export default {
"admin.config.share.max-size.description":
"Максимальный размер файла в байтах",
"admin.config.share.zip-compression-level": "Уровень сжатия Zip",
"admin.config.share.zip-compression-level.description":
"Регулировка уровня баланса между размером файла и скоростью сжатия. Допустимые значения от 0 до 9, с 0 без сжатия, а 9 - максимальное сжатие. ",
"admin.config.share.zip-compression-level.description": "Регулировка уровня баланса между размером файла и скоростью сжатия. Допустимые значения от 0 до 9, с 0 без сжатия, а 9 - максимальное сжатие. ",
"admin.config.share.chunk-size": "Размер чанка",
"admin.config.share.chunk-size.description": "Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "Включено",
"admin.config.smtp.enabled.description":
"Включено ли SMTP. Установите значение true только если вы ввели хост, порт, email, пользователь и пароль вашего SMTP-сервера.",
@@ -498,7 +510,7 @@ export default {
"common.text.navigate-to-link": "Go to the link",
"common.text.or": "или",
"common.button.go-back": "Назад",
"common.button.go-home": "Go home",
"common.button.go-home": "Домой",
"common.notify.copied": "Ваша ссылка скопирована в буфер обмена",
"common.success": "Успешно",
"common.error": "Ошибочка",

View File

@@ -65,7 +65,7 @@ export default {
"resetPassword.description":
"Vnesite svoj e-poštni naslov za ponastavitev gesla.",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"Sporočilo s povezavo za ponastavitev vašega gesla je bilo poslano, če vaš e-poštni naslov obstaja.",
"resetPassword.button.back": "Nazaj na stran za prijavo",
"resetPassword.text.resetPassword": "Ponastavi geslo",
"resetPassword.text.enterNewPassword": "Vnesite novo geslo",
@@ -109,7 +109,7 @@ export default {
"account.modal.totp.step2": "2. Korak: Potrdite svojo kodo",
"account.modal.totp.enterManually": "Vnesite ročno",
"account.modal.totp.code": "Koda",
"account.modal.totp.clickToCopy": "Kliknite za kopiranje",
"common.button.clickToCopy": "Kliknite za kopiranje",
"account.modal.totp.verify": "Preveri",
"account.notify.totp.disable": "TOTP je uspešno onemogočen",
"account.notify.totp.enable": "TOTP je uspešno omogočen",
@@ -194,6 +194,7 @@ export default {
// /admin
"admin.title": "Administracija",
"admin.button.users": "Upravljanje uporabnikov",
"admin.button.shares": "Share management",
"admin.button.config": "Nastavitve",
"admin.version": "Različica",
// END /admin
@@ -224,6 +225,16 @@ export default {
"admin.users.modal.create.admin.description":
"Če je omogočeno, bo lahko porabnik dostopal do administratorskega vmesnika.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Naložite",
"upload.notify.generic-error":
@@ -265,9 +276,10 @@ export default {
"upload.modal.expires.month-plural": "Meseci",
"upload.modal.expires.year-singular": "Leto",
"upload.modal.expires.year-plural": "Leta",
"upload.modal.accordion.description.title": "Opis",
"upload.modal.accordion.description.placeholder":
"Sporočilo za prejemnika te delitve",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Prejemnik e-pošte",
"upload.modal.accordion.email.placeholder": "Vnesite prejemnika e-pošte",
"upload.modal.accordion.email.invalid-email": "Neveljaven e-poštni naslov",
@@ -375,6 +387,9 @@ export default {
"admin.config.share.zip-compression-level": "Nivo Zip stiskanja",
"admin.config.share.zip-compression-level.description":
"Nivo stiskanja, ki uravnoveša med velikostjo datoteke in hitrostjo stiskanja. Veljavne vrednosti so med 0 in 9, kjer 0 pomeni brez kompresije in 9 pomeni največjo kompresijo. ",
"admin.config.share.chunk-size": "Velikost delcev",
"admin.config.share.chunk-size.description":
"Prilagodite velikost delcev (v bajtih) vaših nalaganj, da uravnovesite med učinkovitostjo in zanesljivostjo glede na vašo internetno povezavo. Manjša velikost delcev lahko zviša uspešnost nalaganj pri nestabilni povezavi, medtem ko večja velikost delcev poviša hitrost nalaganja pri stabilni povezavi.",
"admin.config.smtp.enabled": "Omogočeno",
"admin.config.smtp.enabled.description":
"Če je SMTP omogočen. Omogočite samo, če ste vnesli strežnik, vrata, e-pošto, uporabniško ime in geslo vašega SMTP strežnika.",

View File

@@ -107,7 +107,7 @@ export default {
"account.modal.totp.step2": "Корак 2: Потврдите свој код",
"account.modal.totp.enterManually": "Унесите ручно",
"account.modal.totp.code": "Код",
"account.modal.totp.clickToCopy": "Кликните за копирање",
"common.button.clickToCopy": "Кликните за копирање",
"account.modal.totp.verify": "Верификуј",
"account.notify.totp.disable": "ТОТП је успешно онемогућен",
"account.notify.totp.enable": "ТОТП је успешно омогућен",
@@ -190,6 +190,7 @@ export default {
// /admin
"admin.title": "Администрација",
"admin.button.users": "Управљање корисницима",
"admin.button.shares": "Share management",
"admin.button.config": "Конфигурација",
"admin.version": "Верзија",
// END /admin
@@ -220,6 +221,16 @@ export default {
"admin.users.modal.create.admin.description":
"Ако је означено, корисник ће моћи да приступи административном панелу.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Пошаљи",
"upload.notify.generic-error": "Дошло је до грешке при довршавању дељења.",
@@ -260,9 +271,10 @@ export default {
"upload.modal.expires.month-plural": "Месеци",
"upload.modal.expires.year-singular": "Година",
"upload.modal.expires.year-plural": "Године",
"upload.modal.accordion.description.title": "Опис",
"upload.modal.accordion.description.placeholder":
"Напомена за примаоце овог дељења",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Примаоци е-поште",
"upload.modal.accordion.email.placeholder": "Унесите примаоце е-поште",
"upload.modal.accordion.email.invalid-email": "Неисправна адреса е-поште",
@@ -371,6 +383,9 @@ export default {
"admin.config.share.zip-compression-level": "Ниво zip компресије",
"admin.config.share.zip-compression-level.description":
"Подесите ниво да бисте балансирали између величине датотеке и брзине компресије. Важеће вредности се крећу од 0 до 9, при чему је 0 без компресије, а 9 је максимална компресија. ",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "Омогућено",
"admin.config.smtp.enabled.description":
"Да ли је SMTP омогућен. Поставите ово на тачно само ако сте унели хост, порт, е-пошту, корисника и лозинку вашег SMTP сервера.",

View File

@@ -64,7 +64,7 @@ export default {
"resetPassword.description":
"Ange din e-postadress för att återställa ditt lösenord.",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"Ett meddelande med en länk för att återställa ditt lösenord har skickats om e-postadressen finns.",
"resetPassword.button.back": "Tillbaka till inloggningssidan",
"resetPassword.text.resetPassword": "Återställ lösenord",
"resetPassword.text.enterNewPassword": "Ange ditt nya lösenord",
@@ -106,7 +106,7 @@ export default {
"account.modal.totp.step2": "Steg 2: Bekräfta din kod",
"account.modal.totp.enterManually": "Ange manuellt",
"account.modal.totp.code": "Kod",
"account.modal.totp.clickToCopy": "Klicka för att kopiera",
"common.button.clickToCopy": "Klicka för att kopiera",
"account.modal.totp.verify": "Verifiera",
"account.notify.totp.disable": "TOTP har inaktiverats",
"account.notify.totp.enable": "TOTP aktiverat",
@@ -189,6 +189,7 @@ export default {
// /admin
"admin.title": "Administration",
"admin.button.users": "Användarhantering",
"admin.button.shares": "Share management",
"admin.button.config": "Konfiguration",
"admin.version": "Version",
// END /admin
@@ -218,6 +219,16 @@ export default {
"admin.users.modal.create.admin.description":
"Om detta markeras kommer användaren att kunna komma åt administratörspanelen.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Ladda upp",
"upload.notify.generic-error":
@@ -259,9 +270,10 @@ export default {
"upload.modal.expires.month-plural": "Månader",
"upload.modal.expires.year-singular": "År",
"upload.modal.expires.year-plural": "År",
"upload.modal.accordion.description.title": "Beskrivning",
"upload.modal.accordion.description.placeholder":
"Anteckning till mottagare av denna delning",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "E-postmottagare",
"upload.modal.accordion.email.placeholder": "Ange e-postmottagare",
"upload.modal.accordion.email.invalid-email": "Ogiltig e-postadress",
@@ -373,6 +385,9 @@ export default {
"admin.config.share.zip-compression-level": "Komprimeringsnivå för zip",
"admin.config.share.zip-compression-level.description":
"Justera nivån för att balansera mellan filstorlek och komprimeringshastighet. Giltiga värden varierar från 0 till 9, med 0 som ingen komprimering och 9 som maximal komprimering. ",
"admin.config.share.chunk-size": "Bitstorleken",
"admin.config.share.chunk-size.description":
"Justera bitstorleken (i bytes) för dina uppladdningar för att balansera effektivitet och tillförlitlighet enligt din internetanslutning. Mindre bitar kan öka framgångsgraden för instabila anslutningar, medan större bitar snabbar upp uppladdningar för stabila anslutningar.",
"admin.config.smtp.enabled": "Aktiverad",
"admin.config.smtp.enabled.description":
"Om SMTP skall vara aktiverat. Ange endast detta som sant om du angav adress, port, e-post, användare och lösenord för din SMTP-server.",

View File

@@ -104,7 +104,7 @@ export default {
"account.modal.totp.step2": "ขั้นตอนที่ 2: ป้อนรหัสยืนยันตัวตน",
"account.modal.totp.enterManually": "ป้อนด้วยตนเอง",
"account.modal.totp.code": "รหัส",
"account.modal.totp.clickToCopy": "คลิกเพื่อคัดลอก",
"common.button.clickToCopy": "คลิกเพื่อคัดลอก",
"account.modal.totp.verify": "ยืนยัน",
"account.notify.totp.disable": "TOTP ถูกปิดใช้งานเรียบร้อยแล้ว",
"account.notify.totp.enable": "TOTP ถูกเปิดใช้งานเรียบร้อยแล้ว",
@@ -184,6 +184,7 @@ export default {
// /admin
"admin.title": "แผงควบคุมระบบ",
"admin.button.users": "การจัดการผู้ใช้",
"admin.button.shares": "Share management",
"admin.button.config": "การตั้งค่า",
"admin.version": "เวอร์ชัน",
// END /admin
@@ -214,6 +215,16 @@ export default {
"admin.users.modal.create.admin.description":
"หากติ๊กเลือก ผู้ใช้จะสามารถเข้าถึงแผงควบคุมระบบได้",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "อัปโหลด",
"upload.notify.generic-error": "เกิดข้อผิดพลาดขณะที่กำลังจัดการการแชร์ของคุณ",
@@ -254,9 +265,10 @@ export default {
"upload.modal.expires.month-plural": "เดือน",
"upload.modal.expires.year-singular": "ปี",
"upload.modal.expires.year-plural": "ปี",
"upload.modal.accordion.description.title": "คำอธิบาย",
"upload.modal.accordion.description.placeholder":
"หมายเหตุสำหรับผู้รับการแชร์นี้",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "ผู้รับอีเมล์",
"upload.modal.accordion.email.placeholder": "ป้อนผู้รับอีเมล์",
"upload.modal.accordion.email.invalid-email": "ที่อยู่อีเมล์ไม่ถูกต้อง",
@@ -366,6 +378,9 @@ export default {
"admin.config.share.zip-compression-level": "ระดับการบีบอัดไฟล์ Zip",
"admin.config.share.zip-compression-level.description":
"ปรับระดับเพื่อปรับความสมดุลระหว่างขนาดไฟล์และความเร็วในการบีบอัด ค่าอยู่ระหว่าง 0-9 โดย 0 คือไม่มีการบีบอัดและ 9 คือการบีบอัดสูงสุด",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "เปิด",
"admin.config.smtp.enabled.description":
"เปิดใช้งาน SMTP สำหรับการส่งอีเมล์์์์์์ เปิดได้เท่านั้นต่อเมื่อคุณใส่ข้อมูลโฮสต์ พอร์ต อีเมล์ ผู้ใช้ และรหัสผ่านของเซิร์ฟเวอร์ SMTP ของคุณ",

View File

@@ -0,0 +1,533 @@
export default {
// Navbar
"navbar.upload": "Завантажити",
"navbar.signin": "Вхід",
"navbar.home": "Головна",
"navbar.signup": "Зареєструватися",
"navbar.links.shares": "Мої завантаження",
"navbar.links.reverse": "Зворотні завантаження",
"navbar.avatar.account": "Мій аккаунт",
"navbar.avatar.admin": "Адміністрування",
"navbar.avatar.signout": "Вийти",
// END navbar
// /
"home.title": "Платформа для обміну файлами із <h>власного хостингу</h>.",
"home.description":
"Ви дійсно бажаєте надати свої особисті файли У руки третіх осіб, таких як WeTransfer?",
"home.bullet.a.name": "На власному сервері",
"home.bullet.a.description": "Pingvin Share працює на вашій машині.",
"home.bullet.b.name": "Конфіденційність",
"home.bullet.b.description":
"Ваші файли - це ваші файли і ніколи не повинні потрапляти до рук третіх осіб.",
"home.bullet.c.name": "Без дратівливого обмеження розміру файлу",
"home.bullet.c.description":
"Завантажуйте файли з будь-яким розміром. Тільки ваш жорсткий диск буде межею.",
"home.button.start": "Почнемо",
"home.button.source": "Вихідний код",
// END /
// /auth/signin
"signin.title": "З поверненням",
"signin.description": "У вас ще немає облікового запису?",
"signin.button.signup": "Зареєструватися",
"signin.input.email-or-username": "Email або логін",
"signin.input.email-or-username.placeholder": "Ел. пошта або логін",
"signin.input.password": "Пароль",
"signin.input.password.placeholder": "Ваш пароль",
"signin.button.submit": "Вхід",
"signIn.notify.totp-required.title": "Потрібна двофакторна аутентифікація",
"signIn.notify.totp-required.description":
"Будь ласка, введіть код Вашої 2-х факторної аутентифікації",
"signIn.oauth.or": "АБО",
"signIn.oauth.github": "GitHub",
"signIn.oauth.google": "Google",
"signIn.oauth.microsoft": "Microsoft",
"signIn.oauth.discord": "Discord",
"signIn.oauth.oidc": "OpenID",
// END /auth/signin
// /auth/signup
"signup.title": "Створити акаунт",
"signup.description": "Уже є обліковий запис?",
"signup.button.signin": "Вхід",
"signup.input.username": "Логін",
"signup.input.username.placeholder": "Ваш логін (ім'я користувача)",
"signup.input.email": "Електронна пошта",
"signup.input.email.placeholder": "Адреса ел. пошти",
"signup.button.submit": "Давайте почнемо",
// END /auth/signup
// /auth/totp
"totp.title": "Авторизація TOTP",
"totp.button.signIn": "Увійти",
// END /auth/totp
// /auth/reset-password
"resetPassword.title": "Забули пароль?",
"resetPassword.description": "Введіть ваш email для відновлення пароля.",
"resetPassword.notify.success":
"Відправлено повідомлення з посиланням для скидання пароля, якщо email існує.",
"resetPassword.button.back": "Повернутися на сторінку входу",
"resetPassword.text.resetPassword": "Скинути пароль",
"resetPassword.text.enterNewPassword": "Введіть новий пароль",
"resetPassword.input.password": "Новий пароль",
"resetPassword.notify.passwordReset": "Ваш пароль було успішно скинуто!",
// /account
"account.title": "Мій акаунт",
"account.card.info.title": "Інформація про акаунт",
"account.card.info.username": "Логін",
"account.card.info.email": "Електронна пошта",
"account.notify.info.success":
"Налаштування облікового запису успішно оновлено",
"account.card.password.title": "Пароль",
"account.card.password.old": "Старий пароль",
"account.card.password.new": "Новий пароль",
"account.card.password.noPasswordSet":
"У вас не встановлено пароль. Якщо ви хочете увійти за допомогою електронної пошти та пароля, вам необхідно встановити пароль.",
"account.notify.password.success": "Пароль успішно змінено",
"account.card.oauth.title": "Авторизація через соціальні мережі",
"account.card.oauth.github": "GitHub",
"account.card.oauth.google": "Google",
"account.card.oauth.microsoft": "Microsoft",
"account.card.oauth.discord": "Discord",
"account.card.oauth.oidc": "OpenID",
"account.card.oauth.link": "Підключити",
"account.card.oauth.unlink": "Відключити",
"account.card.oauth.unlinked": "Відключено",
"account.modal.unlink.title": "Відключити зв'язок з обліковим записом",
"account.modal.unlink.description":
"Відключення зв'язку з обліковим записом соціальних акаунтів може призвести до втрати вашого облікового запису, якщо ви не пам'ятаєте своє ім'я користувача і пароль.",
"account.notify.oauth.unlinked.success": "Відключення пройшло успішно",
"account.card.security.title": "Безпека",
"account.card.security.totp.enable.description":
"Введіть ваш поточний пароль для початку увімкнення TOTP",
"account.card.security.totp.disable.description":
"Введіть ваш поточний пароль, щоб відключити TOTP",
"account.card.security.totp.button.start": "Почати",
"account.modal.totp.title": "Увімкнути TOTP",
"account.modal.totp.step1": "Крок 1: Додайте свій аутентифікатор",
"account.modal.totp.step2": "Крок 2: Перевірка коду",
"account.modal.totp.enterManually": "Ввести вручну",
"account.modal.totp.code": "Код",
"common.button.clickToCopy": "Натисніть, щоб скопіювати",
"account.modal.totp.verify": "Підтвердити",
"account.notify.totp.disable": "TOTP успішно відключено",
"account.notify.totp.enable": "TOTP успішно увімкнено",
"account.card.language.title": "Мова",
"account.card.language.description":
"Проєкт перекладено спільнотою. Деякі мови можуть бути неповними.",
"account.card.color.title": "Колірна схема",
// ThemeSwitcher.tsx
"account.theme.dark": "Темна",
"account.theme.light": "Світла",
"account.theme.system": "Системна",
"account.button.delete": "Видалити акаунт",
"account.modal.delete.title": "Видалити акаунт",
"account.modal.delete.description":
"Ви дійсно хочете видалити свій обліковий запис, включно з усіма вашими завантаженнями?",
// END /account
// /account/shares
"account.shares.title": "Мої завантаження",
"account.shares.title.empty": "Тут порожньо 👀",
"account.shares.description.empty": "У вас немає завантажень.",
"account.shares.button.create": "Створити одну",
"account.shares.info.title": "Відомості",
"account.shares.table.id": "ID",
"account.shares.table.name": "Назва",
"account.shares.table.description": "Опис",
"account.shares.table.visitors": "Відвідувачів",
"account.shares.table.expiresAt": "Дійсно до",
"account.shares.table.createdAt": "Створено",
"account.shares.table.size": "Розмір",
"account.shares.modal.share-informations": "Відомості",
"account.shares.modal.share-link": "Поділитися посиланням",
"account.shares.modal.delete.title": "Видалити завантаження {share}",
"account.shares.modal.delete.description":
"Ви дійсно хочете видалити це завантаження?",
// END /account/shares
// /account/reverseShares
"account.reverseShares.title": "Зворотні завантаження",
"account.reverseShares.description":
"Зворотне завантаження дає змогу генерувати унікальний URL, що дозволяє зовнішнім користувачам завантажувати файли.",
"account.reverseShares.title.empty": "Тут порожньо 👀",
"account.reverseShares.description.empty":
"У вас поки що немає зворотних завантажень.",
// showCreateReverseShareModal.tsx
"account.reverseShares.modal.title": "Створити зворотне посилання на файл",
"account.reverseShares.modal.expiration.label": "Закінчується",
"account.reverseShares.modal.expiration.minute-singular": "Хвилина",
"account.reverseShares.modal.expiration.minute-plural": "Хвилин(и)",
"account.reverseShares.modal.expiration.hour-singular": "Година",
"account.reverseShares.modal.expiration.hour-plural": "Годин",
"account.reverseShares.modal.expiration.day-singular": "День",
"account.reverseShares.modal.expiration.day-plural": "Днів",
"account.reverseShares.modal.expiration.week-singular": "Тиждень",
"account.reverseShares.modal.expiration.week-plural": "Тиждень",
"account.reverseShares.modal.expiration.month-singular": "Місяць",
"account.reverseShares.modal.expiration.month-plural": "Місяця(-ів)",
"account.reverseShares.modal.expiration.year-singular": "Рік",
"account.reverseShares.modal.expiration.year-plural": "Роки (роки)",
"account.reverseShares.modal.max-size.label": "Макс. розмір завантаження",
"account.reverseShares.modal.send-email":
"Надіслати повідомлення електронною поштою",
"account.reverseShares.modal.send-email.description":
"Надсилати повідомлення електронною поштою, коли завантаження створюється за допомогою цього зворотного посилання.",
"account.reverseShares.modal.max-use.label": "Максимум використань",
"account.reverseShares.modal.max-use.description":
"Максимальна кількість разів, коли URL може бути використаний для створення завантаження.",
"account.reverseShare.never-expires":
"Це зворотне завантаження ніколи не застаріє.",
"account.reverseShare.expires-on":
"Це зворотне завантаження застаріє {expiration}.",
"account.reverseShares.table.no-shares": "Немає створених завантажень",
"account.reverseShares.table.count.singular": "завантаження",
"account.reverseShares.table.count.plural": "завантаження",
"account.reverseShares.table.shares": "Завантаження",
"account.reverseShares.table.remaining": "Залишилося використань",
"account.reverseShares.table.max-size": "Макс. розмір завантаження",
"account.reverseShares.table.expires": "Дійсно до",
"account.reverseShares.modal.reverse-share-link":
"Посилання зворотного завантаження",
"account.reverseShares.modal.delete.title": "Видалити зворотне завантаження",
"account.reverseShares.modal.delete.description":
"Ви дійсно хочете видалити це зворотне завантаження? Якщо ви це зробите, то всі пов'язані зворотні завантаження будуть також видалені.",
// END /account/reverseShares
// /admin
"admin.title": "Адміністрування",
"admin.button.users": "Управління користувачами",
"admin.button.shares": "Share management",
"admin.button.config": "Конфігурація",
"admin.version": "Версія",
// END /admin
// /admin/users
"admin.users.title": "Управління користувачами",
"admin.users.table.username": "Логін",
"admin.users.table.email": "Електронна пошта",
"admin.users.table.admin": "Адміністратор",
"admin.users.edit.update.title": "Оновити користувача {username}",
"admin.users.edit.update.admin-privileges": "Права адміністратора",
"admin.users.edit.update.change-password.title": "Змінити пароль",
"admin.users.edit.update.change-password.field": "Новий пароль",
"admin.users.edit.update.change-password.button": "Зберегти новий пароль",
"admin.users.edit.update.notify.password.success": "Пароль успішно змінено",
"admin.users.edit.delete.title": "Видалити користувача {username}",
"admin.users.edit.delete.description":
"Ви дійсно хочете видалити цього користувача і всі його завантаження?",
// showCreateUserModal.tsx
"admin.users.modal.create.title": "Створити користувача",
"admin.users.modal.create.username": "Логін",
"admin.users.modal.create.email": "Електронна пошта",
"admin.users.modal.create.password": "Пароль",
"admin.users.modal.create.manual-password": "Встановити пароль вручну",
"admin.users.modal.create.manual-password.description":
"Якщо прапорець не встановлено, користувач отримає лист із посиланням для встановлення пароля.",
"admin.users.modal.create.admin": "Права адміністратора",
"admin.users.modal.create.admin.description":
"Якщо зазначено, користувач матиме доступ до панелі адміністратора.",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "Завантажити",
"upload.notify.generic-error":
"Сталася помилка під час завершення вашого завантаження.",
"upload.notify.count-failed":
"Не вдалося завантажити файли {count}. Повтор спроби.",
// Dropzone.tsx
"upload.dropzone.title": "Завантажити файли",
"upload.dropzone.description":
"Перетягніть сюди файли для початку завантаження. Ми можемо приймати тільки файли, які менше {maxSize}.",
"upload.dropzone.notify.file-too-big":
"Ваші файли перевищують максимальний розмір у {maxSize}.",
// FileList.tsx
"upload.filelist.name": "Назва",
"upload.filelist.size": "Розмір",
// showCreateUploadModal.tsx
"upload.modal.title": "Завантажити",
"upload.modal.link.error.invalid":
"Ім'я користувача повинно складатися тільки з букв, цифр, підкреслень і дефісів",
"upload.modal.link.error.taken": "Це посилання вже використовується",
"upload.modal.not-signed-in": "Ви не авторизовані",
"upload.modal.not-signed-in-description":
"Ви не зможете видалити свої файли вручну і переглянути кількість відвідувачів.",
"upload.modal.expires.never": "ніколи",
"upload.modal.expires.never-long": "Ніколи не закінчується",
"upload.modal.expires.error.too-long":
"Термін дії перевищує максимальну дату закінчення терміну дії {max}.",
"upload.modal.link.label": "Посилання",
"upload.modal.expires.label": "Закінчується",
"upload.modal.expires.minute-singular": "Хвилина",
"upload.modal.expires.minute-plural": "Хвилин(и)",
"upload.modal.expires.hour-singular": "Година",
"upload.modal.expires.hour-plural": "Годин",
"upload.modal.expires.day-singular": "День",
"upload.modal.expires.day-plural": "Днів",
"upload.modal.expires.week-singular": "Тиждень",
"upload.modal.expires.week-plural": "Тижнів",
"upload.modal.expires.month-singular": "Місяць",
"upload.modal.expires.month-plural": "Місяця(-ів)",
"upload.modal.expires.year-singular": "Рік",
"upload.modal.expires.year-plural": "Роки (роки)",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Одержувачі листа",
"upload.modal.accordion.email.placeholder": "Одержувачі e-mail",
"upload.modal.accordion.email.invalid-email":
"Неприпустима адреса електронної пошти",
"upload.modal.accordion.security.title": "Параметри безпеки",
"upload.modal.accordion.security.password.label": "Захист паролем",
"upload.modal.accordion.security.password.placeholder": "Без пароля",
"upload.modal.accordion.security.max-views.label": "Максимум переглядів",
"upload.modal.accordion.security.max-views.placeholder": "Без обмеження",
// showCompletedUploadModal.tsx
"upload.modal.completed.never-expires": "Це завантаження ніколи не застаріє.",
"upload.modal.completed.expires-on": "Це завантаження застаріє {expiration}.",
"upload.modal.completed.share-ready": "Готово",
// END /upload
// /share/[id]
"share.title": "Завантаження {shareId}",
"share.description": "Подивіться, чим я поділився з вами!",
"share.error.visitor-limit-exceeded.title": "Перевищено ліміт відвідувачів",
"share.error.visitor-limit-exceeded.description":
"Перевищено ліміт відвідувачів.",
"share.error.removed.title": "Завантаження видалено",
"share.error.not-found.title": "Завантаження не знайдено",
"share.error.not-found.description": "Сторінка, яку ви шукаєте, не існує.",
"share.modal.password.title": "Потрібен пароль",
"share.modal.password.description":
"Для доступу до цього ресурсу введіть пароль для загального доступу.",
"share.modal.password": "Пароль",
"share.modal.error.invalid-password": "Невірний пароль",
"share.button.download-all": "Завантажити все",
"share.notify.download-all-preparing":
"Завантаження готується. Повторіть спробу через кілька хвилин.",
"share.modal.file-link": "Посилання на файл",
"share.table.name": "Назва",
"share.table.size": "Розмір",
"share.modal.file-preview.error.not-supported.title":
"Попередній перегляд не підтримується",
"share.modal.file-preview.error.not-supported.description":
"Попередній перегляд для цього типу файлів не підтримується. Будь ласка, завантажте файл, щоб переглянути його.",
// END /share/[id]
// /share/[id]/edit
"share.edit.title": "Редагувати {shareId}",
"share.edit.append-upload": "Додати файл",
"share.edit.notify.generic-error":
"Сталася помилка під час завершення вашого завантаження.",
"share.edit.notify.save-success": "Посилання на ресурс успішно оновлено",
// END /share/[id]/edit
// /admin/config
"admin.config.title": "Конфігурація",
"admin.config.category.general": "Загальне",
"admin.config.category.share": "Завантаження",
"admin.config.category.email": "Електронна пошта",
"admin.config.category.smtp": "SMTP",
"admin.config.category.oauth": "Авторизація через соціальні мережі",
"admin.config.general.app-name": "Назва програми",
"admin.config.general.app-name.description": "Видима назва додатка",
"admin.config.general.app-url": "URL-адреса програми",
"admin.config.general.app-url.description":
"Адреса, на якій доступний Pingvin Share",
"admin.config.general.show-home-page": "Показувати домашню сторінку",
"admin.config.general.show-home-page.description":
"Показувати домашню сторінку чи ні",
"admin.config.general.logo": "Логотип",
"admin.config.general.logo.description":
"Змініть свій логотип, завантаживши нове зображення. Зображення має бути PNG і повинно мати формат 1:1.",
"admin.config.general.logo.placeholder": "Виберіть зображення",
"admin.config.email.enable-share-email-recipients":
"Увімкнути обмін з одержувачами електронної пошти",
"admin.config.email.enable-share-email-recipients.description":
"Чи дозволити надсилання листів одержувачам. Увімкніть, тільки якщо ви ввімкнули SMTP.",
"admin.config.email.share-recipients-subject":
"Заголовок листа (завантаження)",
"admin.config.email.share-recipients-subject.description":
"Тема листа, який надсилається одержувачам акції.",
"admin.config.email.share-recipients-message":
"Повідомлення листа завантаження",
"admin.config.email.share-recipients-message.description":
"Повідомлення, яке надсилається одержувачам публікації. Доступні змінні:\n {creator} - Ім'я користувача творця завантаження\n {shareUrl} - URL завантаження\n {desc} - Опис завантаження\n {expires} - Дата закінчення завантаження\n Змінні будуть замінені на фактичне значення.",
"admin.config.email.reverse-share-subject":
"Заголовок листа (зворотне завантаження)",
"admin.config.email.reverse-share-subject.description":
"Тема листа, який надсилається, коли хтось створив завантаження з вашим зворотним посиланням.",
"admin.config.email.reverse-share-message":
"Повідомлення листа зворотного завантаження",
"admin.config.email.reverse-share-message.description":
"Повідомлення, яке надсилається, коли хтось створив завантаження з вашим зворотним посиланням. {shareUrl} буде замінено ім'ям творця та URL-адресою загального доступу.",
"admin.config.email.reset-password-subject": "Тема скидання пароля",
"admin.config.email.reset-password-subject.description":
"Тема листа, який надсилається, коли користувач запитує скидання пароля.",
"admin.config.email.reset-password-message":
"Повідомлення про скидання пароля",
"admin.config.email.reset-password-message.description":
"Повідомлення, яке надсилається при запиті скидання пароля. {url} буде замінено посиланням.",
"admin.config.email.invite-subject": "Тема запрошення",
"admin.config.email.invite-subject.description":
"Тема листа, який надсилається, коли адміністратор запрошує користувача.",
"admin.config.email.invite-message": "Повідомлення із запрошенням",
"admin.config.email.invite-message.description":
"Повідомлення запрошення. {url} буде замінено посиланням запрошення, а {password} паролем.",
"admin.config.share.allow-registration": "Дозволити реєстрацію",
"admin.config.share.allow-registration.description":
"Чи дозволена реєстрація",
"admin.config.share.allow-unauthenticated-shares":
"Дозволити неавторизовані завантаження",
"admin.config.share.allow-unauthenticated-shares.description":
"Чи можуть неавторизовані користувачі створювати завантаження",
"admin.config.share.max-expiration": "Максимальний термін дії",
"admin.config.share.max-expiration.description":
"Максимальний термін дії загального доступу в годинах. Встановіть значення 0, щоб дозволити необмежений термін дії.",
"admin.config.share.max-size": "Максимальний розмір",
"admin.config.share.max-size.description":
"Максимальний розмір файлу в байтах",
"admin.config.share.zip-compression-level": "Рівень стиснення Zip",
"admin.config.share.zip-compression-level.description":
"Регулювання рівня балансу між розміром файлу і швидкістю стиснення. Допустимі значення від 0 до 9, з 0 без стиснення, а 9 - максимальне стиснення. ",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "Увімкнено",
"admin.config.smtp.enabled.description":
"Чи увімкнено SMTP. Встановіть значення true тільки якщо ви ввели хост, порт, email, користувач і пароль вашого SMTP-сервера.",
"admin.config.smtp.host": "Хост",
"admin.config.smtp.host.description": "Сервер SMTP-сервера",
"admin.config.smtp.port": "Порт",
"admin.config.smtp.port.description": "Порт SMTP сервера",
"admin.config.smtp.email": "Електронна пошта",
"admin.config.smtp.email.description":
"Адреса електронної пошти, від якої надсилаються листи",
"admin.config.smtp.username": "Логін",
"admin.config.smtp.username.description": "Ім'я користувача SMTP-сервера",
"admin.config.smtp.password": "Пароль",
"admin.config.smtp.password.description": "Пароль SMTP-сервера",
"admin.config.smtp.button.test": "Відправити тестовий лист",
"admin.config.oauth.allow-registration": "Дозволити реєстрацію",
"admin.config.oauth.allow-registration.description":
"Дозволити користувачам реєструватися, використовуючи облікові записи соціальних мереж",
"admin.config.oauth.ignore-totp": "Ігнорувати TOTP",
"admin.config.oauth.ignore-totp.description":
"Ігнорувати TOTP при використанні соціальної авторизації",
"admin.config.oauth.github-enabled": "GitHub",
"admin.config.oauth.github-enabled.description":
"Чи ввімкнено логін на GitHub",
"admin.config.oauth.github-client-id": "ID клієнта GitHub",
"admin.config.oauth.github-client-id.description":
"ID клієнта в додатку GitHub OAuth",
"admin.config.oauth.github-client-secret": "Секретний ключ клієнта GitHub",
"admin.config.oauth.github-client-secret.description":
"Секретний ключ клієнта в додатку GitHub OAuth",
"admin.config.oauth.google-enabled": "Google",
"admin.config.oauth.google-enabled.description":
"Чи увімкнено логін Google на GitHub",
"admin.config.oauth.google-client-id": "ID клієнта Google",
"admin.config.oauth.google-client-id.description":
"ID клієнта в додатку Google OAuth",
"admin.config.oauth.google-client-secret": "Секретний ключ клієнта Google",
"admin.config.oauth.google-client-secret.description":
"Секретний ключ клієнта в додатку Google OAuth",
"admin.config.oauth.microsoft-enabled": "Microsoft",
"admin.config.oauth.microsoft-enabled.description":
"Чи ввімкнено логін Microsoft",
"admin.config.oauth.microsoft-tenant": "Корпоративний акаунт Microsoft",
"admin.config.oauth.microsoft-tenant.description":
"Ідентифікатор орендаря додатка Microsoft OAuth\ncommon: Користувачі з особистим обліковим записом Microsoft і робочим або навчальним обліковим записом від Microsoft Entra ID можуть увійти в додаток. organizations: Тільки користувачі з робочим або навчальним обліковим записом від Microsoft Entra ID можуть увійти в застосунок.\nconsumers: Тільки користувачі з особистим обліковим записом Microsoft можуть увійти в застосунок.ім'я домену орендаря Microsoft Entra або ідентифікатор орендаря у форматі GUID: Тільки користувачі з певного орендаря Microsoft Entra (учасники каталогу з робочим або навчальним обліковим записом або гості каталогу з особистим обліковим записом Microsoft) можуть увійти в застосунок.",
"admin.config.oauth.microsoft-client-id": "Ідентифікатор клієнта Microsoft",
"admin.config.oauth.microsoft-client-id.description":
"ID клієнта в додатку Microsoft OAuth",
"admin.config.oauth.microsoft-client-secret":
"Секретний ключ клієнта Microsoft",
"admin.config.oauth.microsoft-client-secret.description":
"Секретний ключ клієнта в додатку Microsoft OAuth",
"admin.config.oauth.discord-enabled": "Discord",
"admin.config.oauth.discord-enabled.description":
"Чи увімкнено логін Discord",
"admin.config.oauth.discord-limited-guild": "ID обмеженого сервера Discord",
"admin.config.oauth.discord-limited-guild.description":
"Обмеження входу для користувачів певного сервера. Залиште порожнім, щоб відключити.",
"admin.config.oauth.discord-client-id": "ID клієнта Discord",
"admin.config.oauth.discord-client-id.description":
"ID клієнта в додатку Discord OAuth",
"admin.config.oauth.discord-client-secret": "Секретний ключ клієнта Discord",
"admin.config.oauth.discord-client-secret.description":
"Секретний ключ клієнта в додатку Discord OAuth",
"admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description":
"Чи ввімкнено логін OpenID Connect",
"admin.config.oauth.oidc-discovery-uri": "OpenID Connect Discovery URI",
"admin.config.oauth.oidc-discovery-uri.description":
"URI Discovery URI додатка OpenID Connect OAuth",
"admin.config.oauth.oidc-username-claim":
"Заява на ім'я користувача OpenID Connect",
"admin.config.oauth.oidc-username-claim.description":
"Заява про ім'я користувача в токені OpenID Connect ID. Залиште порожнім, якщо не знаєте, що це за конфіг.",
"admin.config.oauth.oidc-client-id": "OpenID Connect Client ID",
"admin.config.oauth.oidc-client-id.description":
"Клієнтський ідентифікатор додатка OpenID Connect OAuth",
"admin.config.oauth.oidc-client-secret": "Секрет клієнта OpenID Connect",
"admin.config.oauth.oidc-client-secret.description":
"Клієнтський секрет програми OpenID Connect OAuth",
// 404
"404.description": "Бляха, цієї строрінки не існує.",
"404.button.home": "Поверни мене додому",
// error
"error.title": "Помилка",
"error.description": "Щось пішло не так!",
"error.button.back": "Назад",
"error.msg.default": "Щось пішло не так.",
"error.msg.access_denied":
"Ви скасували процес аутентифікації, будь ласка, спробуйте ще раз.",
"error.msg.expired_token":
"Процес аутентифікації зайняв занадто багато часу, будь ласка, спробуйте ще раз.",
"error.msg.invalid_token": "Внутрішня помилка",
"error.msg.no_user":
"Користувач, пов'язаний з обліковим записом {0}, не існує.",
"error.msg.no_email":
"Не вдається отримати адресу електронної пошти від облікового запису {0}.",
"error.msg.already_linked":
"Цей обліковий запис {0} уже прив'язано до іншого акаунта.",
"error.msg.not_linked":
"Цей обліковий запис {0} ще не прив'язаний до жодного акаунту.",
"error.msg.unverified_account":
"Цей обліковий запис {0} не підтверджено, повторіть спробу після підтвердження.",
"error.msg.discord_guild_permission_denied": "У вас немає дозволу на вхід.",
"error.msg.cannot_get_user_info":
"Не вдається отримати інфу про користувача з цього {0} облікового запису.",
"error.param.provider_github": "GitHub",
"error.param.provider_google": "Google",
"error.param.provider_microsoft": "Microsoft",
"error.param.provider_discord": "Discord",
"error.param.provider_oidc": "OpenID Connect",
// Common translations
"common.button.save": "Зберегти",
"common.button.create": "Створити",
"common.button.submit": "Відправити",
"common.button.delete": "Видалити",
"common.button.cancel": "Скасувати",
"common.button.confirm": "Підтвердити",
"common.button.disable": "Відключити",
"common.button.share": "Поділитися",
"common.button.generate": "Згенерувати",
"common.button.done": "Готово",
"common.text.link": "Посилання",
"common.text.navigate-to-link": "Перейти до посилання",
"common.text.or": "або",
"common.button.go-back": "Назад",
"common.button.go-home": "Перейти додому",
"common.notify.copied": "Ваше посилання скопійовано в буфер обміну",
"common.success": "Успішно",
"common.error": "Помилка",
"common.error.unknown": "Сталася невідома помилка",
"common.error.invalid-email": "Неприпустима адреса електронної пошти",
"common.error.too-short": "Повинно бути не менше {length} символів",
"common.error.too-long": "Повинно бути не більше {length} символів",
"common.error.exact-length": "Повинно бути рівно {length} символів",
"common.error.invalid-number": "Повинно бути числом",
"common.error.field-required": "Поле обов'язкове для заповнення",
};

View File

@@ -18,7 +18,7 @@ export default {
"home.bullet.b.name": "完全隐私",
"home.bullet.b.description": "你的文件只属于你!不要将它放到第三方文件平台",
"home.bullet.c.name": "完全无限",
"home.bullet.c.description": "想上传多大都可以,更需要担心的是你的存储卷容量",
"home.bullet.c.description": "想上传多大都可以,硬盘容量的大小是唯一的限制",
"home.button.start": "开始使用",
"home.button.source": "源代码",
// END /
@@ -33,7 +33,7 @@ export default {
"signin.button.submit": "登录",
"signIn.notify.totp-required.title": "请继续两步验证",
"signIn.notify.totp-required.description": "请输入一次性验证码",
"signIn.oauth.or": "OR",
"signIn.oauth.or": "",
"signIn.oauth.github": "GitHub",
"signIn.oauth.google": "谷歌",
"signIn.oauth.microsoft": "Microsoft",
@@ -56,9 +56,9 @@ export default {
// END /auth/totp
// /auth/reset-password
"resetPassword.title": "忘记密码?",
"resetPassword.description": "请输入电子邮件接受重置密码邮件",
"resetPassword.description": "请输入电子邮箱地址来接收重置密码邮件",
"resetPassword.notify.success":
"A message with a link to reset your password has been sent if the email exists.",
"如果该电子邮箱存在,则已发送一条包含重置密码链接的邮件。",
"resetPassword.button.back": "返回登录页面",
"resetPassword.text.resetPassword": "重置密码",
"resetPassword.text.enterNewPassword": "请输入新密码",
@@ -82,10 +82,10 @@ export default {
"account.card.oauth.microsoft": "Microsoft",
"account.card.oauth.discord": "Discord",
"account.card.oauth.oidc": "OpenID",
"account.card.oauth.link": "Link",
"account.card.oauth.unlink": "Unlink",
"account.card.oauth.unlinked": "Unlinked",
"account.modal.unlink.title": "Unlink account",
"account.card.oauth.link": "关联",
"account.card.oauth.unlink": "解除关联",
"account.card.oauth.unlinked": "已解除关联",
"account.modal.unlink.title": "解除关联",
"account.modal.unlink.description":
"如果您不记得您的用户名和密码,解除和社交账号的关联可能会导致丢失账户。",
"account.notify.oauth.unlinked.success": "解除关联成功",
@@ -99,7 +99,7 @@ export default {
"account.modal.totp.step2": "第二步:输入一次性验证码",
"account.modal.totp.enterManually": "手动输入",
"account.modal.totp.code": "验证码",
"account.modal.totp.clickToCopy": "点击复制",
"common.button.clickToCopy": "点击复制",
"account.modal.totp.verify": "确定",
"account.notify.totp.disable": "成功关闭两步验证!",
"account.notify.totp.enable": "成功开启两步验证!",
@@ -179,6 +179,7 @@ export default {
// /admin
"admin.title": "管理",
"admin.button.users": "用户管理",
"admin.button.shares": "共享管理",
"admin.button.config": "配置管理",
"admin.version": "版本",
// END /admin
@@ -208,6 +209,15 @@ export default {
"admin.users.modal.create.admin.description":
"如果勾选,用户将能访问管理员面板",
// END /admin/users
// /admin/shares
"admin.shares.title": "共享管理",
"admin.shares.table.id": "共享 ID",
"admin.shares.table.username": "创建者",
"admin.shares.table.visitors": "访问者",
"admin.shares.table.expires": "过期时间",
"admin.shares.edit.delete.title": "删除共享 {id}",
"admin.shares.edit.delete.description": "你真的要删除这个共享吗?",
// END /admin/shares
// /upload
"upload.title": "上传",
"upload.notify.generic-error": "创建共享的过程中发生了错误",
@@ -245,8 +255,10 @@ export default {
"upload.modal.expires.month-plural": "月",
"upload.modal.expires.year-singular": "1 年",
"upload.modal.expires.year-plural": "年",
"upload.modal.accordion.description.title": "描述",
"upload.modal.accordion.description.placeholder": "共享文件备注信息",
"upload.modal.accordion.name-and-description.title": "名称与描述",
"upload.modal.accordion.name-and-description.name.placeholder": "名称",
"upload.modal.accordion.name-and-description.description.placeholder":
"写给接收者的备注",
"upload.modal.accordion.email.title": "邮件提醒",
"upload.modal.accordion.email.placeholder": "收件人电子邮件地址",
"upload.modal.accordion.email.invalid-email": "邮件地址不可用",
@@ -279,7 +291,7 @@ export default {
"share.table.size": "文件大小",
"share.modal.file-preview.error.not-supported.title": "该文件类型不支持预览",
"share.modal.file-preview.error.not-supported.description":
"A preview for this file type is unsupported. Please download the file to view it.",
"不支持此文件类型的预览,请下载文件查看。",
// END /share/[id]
// /share/[id]/edit
"share.edit.title": "编辑 {shareId}",
@@ -345,6 +357,10 @@ export default {
"admin.config.share.zip-compression-level": "Zip 文件压缩质量",
"admin.config.share.zip-compression-level.description":
"调整压缩质量来平衡压缩文件的大小和压缩的速度。有效值介于 0 和 9 之间0 为不压缩9 为最高质量压缩。 ",
"admin.config.share.chunk-size": "块大小",
"admin.config.share.chunk-size.description": "根据你的互联网连接情况调整上传文件的块大小(以字节为单位),以平衡效率和可靠性。 较小的块有助于提高不稳定网络环境中的上传成功率,而较大的块则可以加快稳定网络环境中的上传速度。",
"admin.config.share.auto-open-share-modal": "自动打开创建共享对话框",
"admin.config.share.auto-open-share-modal.description": "每当用户选择完将要被上传的文件后,自动打开创建共享的对话框。",
"admin.config.smtp.enabled": "启用",
"admin.config.smtp.enabled.description":
"是否开启 SMTP仅当输入主机名、端口、发送邮箱、用户名和密码后开启",
@@ -370,7 +386,7 @@ export default {
"admin.config.oauth.github-client-id": "GitHub Client ID",
"admin.config.oauth.github-client-id.description":
"GitHub OAuth App 的 Client ID",
"admin.config.oauth.github-client-secret": "GitHub Client secret",
"admin.config.oauth.github-client-secret": "GitHub Client secret",
"admin.config.oauth.github-client-secret.description":
"GitHub OAuth App 的 Client secret",
"admin.config.oauth.google-enabled": "谷歌",
@@ -383,9 +399,9 @@ export default {
"Google OAuth App 的 Client secret",
"admin.config.oauth.microsoft-enabled": "Microsoft",
"admin.config.oauth.microsoft-enabled.description": "是否启用微软账号登录",
"admin.config.oauth.microsoft-tenant": "Microsoft Tenant",
"admin.config.oauth.microsoft-tenant": "Microsoft 租户(Tenant",
"admin.config.oauth.microsoft-tenant.description":
"Tenant ID of the Microsoft OAuth app\ncommon: Users with both a personal Microsoft account and a work or school account from Microsoft Entra ID can sign in to the application. organizations: Only users with work or school accounts from Microsoft Entra ID can sign in to the application.\nconsumers: Only users with a personal Microsoft account can sign in to the application.\ndomain name of the Microsoft Entra tenant or the tenant ID in GUID format: Only users from a specific Microsoft Entra tenant (directory members with a work or school account or directory guests with a personal Microsoft account) can sign in to the application.",
"Microsoft OAuth 应用的 租户(Tenant ID共有四种类型参阅https://learn.microsoft.com/zh-cn/security/zero-trust/develop/identity-supported-account-types。\ncommon常规个人 Microsoft 账户和 Microsoft Entra ID 工作或学校账户均可登录。\norganizations组织只有Microsoft Entra ID 工作或学校账户可以登录。\nconsumers客户只有个人 Microsoft 账户可以登录。\nMicrosoft Entra 租户的域名或 GUID 格式的租户 ID只有来自特定 Microsoft Entra 租户的用户(具有工作或学校账户的目录成员或具有个人 Microsoft 账户的目录来宾)才能登录。",
"admin.config.oauth.microsoft-client-id": "Microsoft Client ID",
"admin.config.oauth.microsoft-client-id.description":
"Microsoft OAuth App 的 Client ID",
@@ -455,7 +471,7 @@ export default {
"common.text.navigate-to-link": "访问链接",
"common.text.or": "或",
"common.button.go-back": "返回",
"common.button.go-home": "Go home",
"common.button.go-home": "返回主页",
"common.notify.copied": "已复制到剪贴板",
"common.success": "成功",
"common.error": "错误",

View File

@@ -100,7 +100,7 @@ export default {
"account.modal.totp.step2": "第二步:輸入一次性驗證碼",
"account.modal.totp.enterManually": "手動輸入",
"account.modal.totp.code": "驗證碼",
"account.modal.totp.clickToCopy": "複製",
"common.button.clickToCopy": "複製",
"account.modal.totp.verify": "確認",
"account.notify.totp.disable": "成功關閉兩步驗證!",
"account.notify.totp.enable": "成功開啟兩步驗證!",
@@ -180,6 +180,7 @@ export default {
// /admin
"admin.title": "管理",
"admin.button.users": "使用者管理",
"admin.button.shares": "Share management",
"admin.button.config": "配置管理",
"admin.version": "版本",
// END /admin
@@ -209,6 +210,16 @@ export default {
"admin.users.modal.create.admin.description":
"如果勾選,使用者將能查看管理員面板",
// END /admin/users
// /admin/shares
"admin.shares.title": "Share management",
"admin.shares.table.id": "Share ID",
"admin.shares.table.username": "Creator",
"admin.shares.table.visitors": "Visitors",
"admin.shares.table.expires": "Expires At",
"admin.shares.edit.delete.title": "Delete share {id}",
"admin.shares.edit.delete.description":
"Do you really want to delete this share?",
// END /admin/shares
// /upload
"upload.title": "上傳",
"upload.notify.generic-error": "建立分享的過程中發生了錯誤",
@@ -245,8 +256,10 @@ export default {
"upload.modal.expires.month-plural": "月",
"upload.modal.expires.year-singular": "年",
"upload.modal.expires.year-plural": "年",
"upload.modal.accordion.description.title": "描述",
"upload.modal.accordion.description.placeholder": "分享檔案備註資訊",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Email提醒",
"upload.modal.accordion.email.placeholder": "收件人Email地址",
"upload.modal.accordion.email.invalid-email": "Email地址不可用",
@@ -345,6 +358,9 @@ export default {
"admin.config.share.zip-compression-level": "Zip 壓縮等級",
"admin.config.share.zip-compression-level.description":
"調整壓縮等級以平衡檔案大小和壓縮速度。 有效值範圍從 0 到 9其中 0 表示無壓縮9 表示最大壓縮",
"admin.config.share.chunk-size": "Chunk size",
"admin.config.share.chunk-size.description":
"Adjust the chunk size (in bytes) for your uploads to balance efficiency and reliability according to your internet connection. Smaller chunks can enhance success rates for unstable connections, while larger chunks speed up uploads for stable connections.",
"admin.config.smtp.enabled": "啟用",
"admin.config.smtp.enabled.description":
"是否開啟 SMTP需輸入Host、Port、發送郵箱、使用者名稱和密碼後才有作用",

View File

@@ -1,14 +1,7 @@
import {
Button,
Container,
createStyles,
Group,
Text,
Title,
} from "@mantine/core";
import { Button, Container, createStyles, Group, Title } from "@mantine/core";
import Link from "next/link";
import Meta from "../components/Meta";
import { FormattedMessage } from "react-intl";
import Meta from "../components/Meta";
const useStyles = createStyles((theme) => ({
root: {
@@ -21,19 +14,13 @@ const useStyles = createStyles((theme) => ({
fontWeight: 900,
fontSize: 220,
lineHeight: 1,
marginBottom: `calc(${theme.spacing.xl} * 100)`,
marginBottom: 20,
color: theme.colors.gray[2],
[theme.fn.smallerThan("sm")]: {
fontSize: 120,
},
},
description: {
maxWidth: 500,
margin: "auto",
marginBottom: `calc(${theme.spacing.xl} * 100)`,
},
}));
const ErrorNotFound = () => {
@@ -47,12 +34,7 @@ const ErrorNotFound = () => {
<Title align="center" order={3}>
<FormattedMessage id="404.description" />
</Title>
<Text
color="dimmed"
align="center"
className={classes.description}
></Text>
<Group position="center">
<Group position="center" mt={50}>
<Button component={Link} href="/" variant="light">
<FormattedMessage id="404.button.home" />
</Button>

View File

@@ -29,6 +29,8 @@ import Config from "../types/config.type";
import { CurrentUser } from "../types/user.type";
import i18nUtil from "../utils/i18n.util";
import userPreferences from "../utils/userPreferences.util";
import "moment/min/locales";
import moment from "moment";
const excludeDefaultLayoutRoutes = ["/admin/config/[category]"];
@@ -50,7 +52,12 @@ function App({ Component, pageProps }: AppProps) {
}, [router.pathname]);
useEffect(() => {
setInterval(async () => await authService.refreshAccessToken(), 30 * 1000);
const interval = setInterval(
async () => await authService.refreshAccessToken(),
2 * 60 * 1000, // 2 minutes
);
return () => clearInterval(interval);
}, []);
useEffect(() => {
@@ -79,6 +86,7 @@ function App({ Component, pageProps }: AppProps) {
};
const language = useRef(pageProps.language);
moment.locale(language.current);
return (
<>

View File

@@ -68,15 +68,12 @@ const MyShares = () => {
<Table>
<thead>
<tr>
<th>
<FormattedMessage id="account.shares.table.id" />
</th>
<th>
<FormattedMessage id="account.shares.table.name" />
</th>
<MediaQuery smallerThan="md" styles={{ display: "none" }}>
<th>
<FormattedMessage id="account.shares.table.description" />
</th>
</MediaQuery>
<th>
<FormattedMessage id="account.shares.table.visitors" />
</th>
@@ -90,18 +87,7 @@ const MyShares = () => {
{shares.map((share) => (
<tr key={share.id}>
<td>{share.id}</td>
<MediaQuery smallerThan="sm" styles={{ display: "none" }}>
<td
style={{
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
maxWidth: "300px",
}}
>
{share.description || ""}
</td>
</MediaQuery>
<td>{share.name}</td>
<td>{share.views}</td>
<td>
{moment(share.expiration).unix() === 0

View File

@@ -72,6 +72,10 @@ export default function AppShellDemo() {
};
const updateConfigVariable = (configVariable: UpdateConfig) => {
if (configVariable.key === "general.appUrl") {
configVariable.value = sanitizeUrl(configVariable.value);
}
const index = updatedConfigVariables.findIndex(
(item) => item.key === configVariable.key,
);
@@ -86,6 +90,10 @@ export default function AppShellDemo() {
}
};
const sanitizeUrl = (url: string): string => {
return url.endsWith("/") ? url.slice(0, -1) : url;
};
useEffect(() => {
configService.getByCategory(categoryId).then((configVariables) => {
setConfigVariables(configVariables);

View File

@@ -10,7 +10,7 @@ import {
} from "@mantine/core";
import Link from "next/link";
import { useEffect, useState } from "react";
import { TbRefresh, TbSettings, TbUsers } from "react-icons/tb";
import { TbLink, TbRefresh, TbSettings, TbUsers } from "react-icons/tb";
import { FormattedMessage } from "react-intl";
import Meta from "../../components/Meta";
import useTranslate from "../../hooks/useTranslate.hook";
@@ -41,6 +41,11 @@ const Admin = () => {
icon: TbUsers,
route: "/admin/users",
},
{
title: t("admin.button.shares"),
icon: TbLink,
route: "/admin/shares",
},
{
title: t("admin.button.config"),
icon: TbSettings,

View File

@@ -0,0 +1,74 @@
import { Group, Space, Text, Title } from "@mantine/core";
import { useModals } from "@mantine/modals";
import { useEffect, useState } from "react";
import { FormattedMessage } from "react-intl";
import Meta from "../../components/Meta";
import ManageShareTable from "../../components/admin/shares/ManageShareTable";
import useTranslate from "../../hooks/useTranslate.hook";
import shareService from "../../services/share.service";
import { MyShare } from "../../types/share.type";
import toast from "../../utils/toast.util";
const Shares = () => {
const [shares, setShares] = useState<MyShare[]>([]);
const [isLoading, setIsLoading] = useState(true);
const modals = useModals();
const t = useTranslate();
const getShares = () => {
setIsLoading(true);
shareService.list().then((shares) => {
setShares(shares);
setIsLoading(false);
});
};
const deleteShare = (share: MyShare) => {
modals.openConfirmModal({
title: t("admin.shares.edit.delete.title", {
id: share.id,
}),
children: (
<Text size="sm">
<FormattedMessage id="admin.shares.edit.delete.description" />
</Text>
),
labels: {
confirm: t("common.button.delete"),
cancel: t("common.button.cancel"),
},
confirmProps: { color: "red" },
onConfirm: async () => {
shareService
.remove(share.id)
.then(() => setShares(shares.filter((v) => v.id != share.id)))
.catch(toast.axiosError);
},
});
};
useEffect(() => {
getShares();
}, []);
return (
<>
<Meta title={t("admin.shares.title")} />
<Group position="apart" align="baseline" mb={20}>
<Title mb={30} order={3}>
<FormattedMessage id="admin.shares.title" />
</Title>
</Group>
<ManageShareTable
shares={shares}
deleteShare={deleteShare}
isLoading={isLoading}
/>
<Space h="xl" />
</>
);
};
export default Shares;

View File

@@ -12,7 +12,7 @@ export const config = {
const { apiURL } = getConfig().serverRuntimeConfig;
// A proxy to the API server only used in development.
// In production this route gets overridden by nginx.
// In production this route gets overridden by Caddy.
export default (req: NextApiRequest, res: NextApiResponse) => {
httpProxyMiddleware(req, res, {
headers: {

View File

@@ -4,6 +4,7 @@ import Meta from "../components/Meta";
import useTranslate from "../hooks/useTranslate.hook";
import { useRouter } from "next/router";
import { FormattedMessage } from "react-intl";
import { safeRedirectPath } from "../utils/router.util";
const useStyle = createStyles({
title: {
@@ -39,7 +40,9 @@ export default function Error() {
</Text>
<Button
mt="xl"
onClick={() => router.push((router.query.redirect as string) || "/")}
onClick={() =>
router.push(safeRedirectPath(router.query.redirect as string))
}
>
{t("error.button.back")}
</Button>

View File

@@ -94,7 +94,7 @@ export default function Home() {
id="home.title"
values={{
h: (chunks) => (
<span className={classes.highlight}>{chunks} </span>
<span className={classes.highlight}>{chunks}</span>
),
}}
/>

View File

@@ -91,13 +91,13 @@ const Share = ({ shareId }: { shareId: string }) => {
return (
<>
<Meta
title={t("share.title", { shareId })}
title={t("share.title", { shareId: share?.name || shareId })}
description={t("share.description")}
/>
<Group position="apart" mb="lg">
<Box style={{ maxWidth: "70%" }}>
<Title order={3}>{share?.id}</Title>
<Title order={3}>{share?.name || share?.id}</Title>
<Text size="sm">{share?.description}</Text>
</Box>
{share?.files.length > 1 && <DownloadAllButton shareId={shareId} />}

View File

@@ -3,7 +3,7 @@ import { useModals } from "@mantine/modals";
import { cleanNotifications } from "@mantine/notifications";
import { AxiosError } from "axios";
import pLimit from "p-limit";
import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { FormattedMessage } from "react-intl";
import Meta from "../../components/Meta";
import Dropzone from "../../components/upload/Dropzone";
@@ -19,7 +19,6 @@ import { CreateShare, Share } from "../../types/share.type";
import toast from "../../utils/toast.util";
const promiseLimit = pLimit(3);
const chunkSize = 10 * 1024 * 1024; // 10MB
let errorToastShown = false;
let createdShare: Share;
@@ -38,7 +37,10 @@ const Upload = ({
const [files, setFiles] = useState<FileUpload[]>([]);
const [isUploading, setisUploading] = useState(false);
const chunkSize = useRef(parseInt(config.get("share.chunkSize")));
maxShareSize ??= parseInt(config.get("share.maxSize"));
const autoOpenCreateUploadModal = config.get("share.autoOpenShareModal");
const uploadFiles = async (share: CreateShare, files: FileUpload[]) => {
setisUploading(true);
@@ -54,7 +56,7 @@ const Upload = ({
const fileUploadPromises = files.map(async (file, fileIndex) =>
// Limit the number of concurrent uploads to 3
promiseLimit(async () => {
let fileId: string;
let fileId;
const setFileProgress = (progress: number) => {
setFiles((files) =>
@@ -69,38 +71,30 @@ const Upload = ({
setFileProgress(1);
let chunks = Math.ceil(file.size / chunkSize);
let chunks = Math.ceil(file.size / chunkSize.current);
// If the file is 0 bytes, we still need to upload 1 chunk
if (chunks == 0) chunks++;
for (let chunkIndex = 0; chunkIndex < chunks; chunkIndex++) {
const from = chunkIndex * chunkSize;
const to = from + chunkSize;
const from = chunkIndex * chunkSize.current;
const to = from + chunkSize.current;
const blob = file.slice(from, to);
try {
await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async (event) =>
await shareService
.uploadFile(
createdShare.id,
event,
{
id: fileId,
name: file.name,
},
chunkIndex,
chunks,
)
.then((response) => {
fileId = response.id;
resolve(response);
})
.catch(reject);
reader.readAsDataURL(blob);
});
await shareService
.uploadFile(
createdShare.id,
blob,
{
id: fileId,
name: file.name,
},
chunkIndex,
chunks,
)
.then((response) => {
fileId = response.id;
});
setFileProgress(((chunkIndex + 1) / chunks) * 100);
} catch (e) {
@@ -128,7 +122,6 @@ const Upload = ({
};
const showCreateUploadModalCallback = (files: FileUpload[]) => {
setFiles(files);
showCreateUploadModal(
modals,
{
@@ -146,6 +139,15 @@ const Upload = ({
);
};
const handleDropzoneFilesChanged = (files: FileUpload[]) => {
if (autoOpenCreateUploadModal) {
setFiles(files);
showCreateUploadModalCallback(files);
} else {
setFiles((oldArr) => [...oldArr, ...files]);
}
};
useEffect(() => {
// Check if there are any files that failed to upload
const fileErrorCount = files.filter(
@@ -198,8 +200,13 @@ const Upload = ({
</Button>
</Group>
<Dropzone
title={
!autoOpenCreateUploadModal && files.length > 0
? t("share.edit.append-upload")
: undefined
}
maxShareSize={maxShareSize}
showCreateUploadModalCallback={showCreateUploadModalCallback}
onFilesChanged={handleDropzoneFilesChanged}
isUploading={isUploading}
/>
{files.length > 0 && (

View File

@@ -36,8 +36,10 @@ const signOut = async () => {
const refreshAccessToken = async () => {
try {
const accessToken = getCookie("access_token") as string;
// If the access token expires in less than 2 minutes refresh it
if (
!accessToken ||
accessToken &&
(jose.decodeJwt(accessToken).exp ?? 0) * 1000 < Date.now() + 2 * 60 * 1000
) {
await api.post("/auth/token");

View File

@@ -1,4 +1,4 @@
import { setCookie } from "cookies-next";
import { deleteCookie, setCookie } from "cookies-next";
import mime from "mime-types";
import { FileUploadResponse } from "../types/File.type";
@@ -11,12 +11,18 @@ import {
} from "../types/share.type";
import api from "./api.service";
const list = async (): Promise<MyShare[]> => {
return (await api.get(`shares/all`)).data;
};
const create = async (share: CreateShare) => {
return (await api.post("shares", share)).data;
};
const completeShare = async (id: string) => {
return (await api.post(`shares/${id}/complete`)).data;
const response = (await api.post(`shares/${id}/complete`)).data;
deleteCookie("reverse_share_token");
return response;
};
const revertComplete = async (id: string) => {
@@ -77,7 +83,7 @@ const removeFile = async (shareId: string, fileId: string) => {
const uploadFile = async (
shareId: string,
readerEvent: ProgressEvent<FileReader>,
chunk: Blob,
file: {
id?: string;
name: string;
@@ -85,10 +91,8 @@ const uploadFile = async (
chunkIndex: number,
totalChunks: number,
): Promise<FileUploadResponse> => {
const data = readerEvent.target!.result;
return (
await api.post(`shares/${shareId}/files`, data, {
await api.post(`shares/${shareId}/files`, chunk, {
headers: { "Content-Type": "application/octet-stream" },
params: {
id: file.id,
@@ -131,6 +135,7 @@ const removeReverseShare = async (id: string) => {
};
export default {
list,
create,
completeShare,
revertComplete,

View File

@@ -2,15 +2,18 @@ import User from "./user.type";
export type Share = {
id: string;
name?: string;
files: any;
creator: User;
creator?: User;
description?: string;
expiration: Date;
size: number;
hasPassword: boolean;
};
export type CreateShare = {
id: string;
name?: string;
description?: string;
recipients: string[];
expiration: string;

View File

@@ -0,0 +1,7 @@
export function safeRedirectPath(path: string | undefined) {
if (!path) return "/";
if (!path.startsWith("/")) return `/${path}`;
return path;
}

View File

@@ -1,22 +0,0 @@
events {}
http {
server {
listen 3000;
client_max_body_size 100M;
location /api {
proxy_pass http://localhost:8080;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://localhost:3333;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}

1615
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "pingvin-share",
"version": "0.22.1",
"version": "0.25.0",
"scripts": {
"format": "cd frontend && npm run format && cd ../backend && npm run format",
"lint": "cd frontend && npm run lint && cd ../backend && npm run lint",