Compare commits

...

31 Commits

Author SHA1 Message Date
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
64 changed files with 2250 additions and 453 deletions

View File

@@ -1,3 +1,44 @@
## [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) ## [0.22.2](https://github.com/stonith404/pingvin-share/compare/v0.22.1...v0.22.2) (2024-02-29)

View File

@@ -2,7 +2,7 @@
--- ---
_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)_
--- ---
@@ -61,7 +61,7 @@ cd ../frontend
npm install npm install
npm run build npm run build
API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080 API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080
pm2 start --name="pingvin-share-frontend" npm -- run start 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 Caddy can be found in `./Caddyfile`. **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`.
@@ -87,6 +87,7 @@ View the [OAuth 2 guide](/docs/oauth2-guide.md) for more information.
### Additional resources ### Additional resources
- [Synology NAS installation](https://mariushosting.com/how-to-install-pingvin-share-on-your-synology-nas/) - [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 ### Upgrade to a new version
@@ -115,11 +116,13 @@ docker compose up -d
# Start the backend # Start the backend
cd backend cd backend
npm install
npm run build npm run build
pm2 restart pingvin-share-backend pm2 restart pingvin-share-backend
# Start the frontend # Start the frontend
cd ../frontend cd ../frontend
npm install
npm run build npm run build
API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080 API_URL=http://localhost:8080 # Set the URL of the backend, default: http://localhost:8080
pm2 restart pingvin-share-frontend pm2 restart pingvin-share-frontend

View File

@@ -1,12 +1,12 @@
{ {
"name": "pingvin-share-backend", "name": "pingvin-share-backend",
"version": "0.22.2", "version": "0.24.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "pingvin-share-backend", "name": "pingvin-share-backend",
"version": "0.22.2", "version": "0.24.1",
"dependencies": { "dependencies": {
"@nestjs/cache-manager": "^2.1.0", "@nestjs/cache-manager": "^2.1.0",
"@nestjs/common": "^10.1.2", "@nestjs/common": "^10.1.2",

View File

@@ -1,6 +1,6 @@
{ {
"name": "pingvin-share-backend", "name": "pingvin-share-backend",
"version": "0.22.2", "version": "0.24.1",
"scripts": { "scripts": {
"build": "nest build", "build": "nest build",
"dev": "cross-env NODE_ENV=development nest start --watch", "dev": "cross-env NODE_ENV=development nest start --watch",

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()) id String @id @default(uuid())
createdAt DateTime @default(now()) createdAt DateTime @default(now())
name String?
uploadLocked Boolean @default(false) uploadLocked Boolean @default(false)
isZipReady Boolean @default(false) isZipReady Boolean @default(false)
views Int @default(0) views Int @default(0)

View File

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

View File

@@ -99,7 +99,7 @@ export class AuthService {
include: { resetPasswordToken: true }, include: { resetPasswordToken: true },
}); });
if (!user) throw new BadRequestException("User not found"); if (!user) return;
// Delete old reset password token // Delete old reset password token
if (user.resetPasswordToken) { if (user.resetPasswordToken) {

View File

@@ -26,18 +26,21 @@ export class FileController {
@SkipThrottle() @SkipThrottle()
@UseGuards(CreateShareGuard, ShareOwnerGuard) @UseGuards(CreateShareGuard, ShareOwnerGuard)
async create( async create(
@Query() query: any, @Query()
query: {
id: string;
name: string;
chunkIndex: string;
totalChunks: string;
},
@Body() body: string, @Body() body: string,
@Param("shareId") shareId: string, @Param("shareId") shareId: string,
) { ) {
const { id, name, chunkIndex, totalChunks } = query; const { id, name, chunkIndex, totalChunks } = query;
// Data can be empty if the file is empty // Data can be empty if the file is empty
const data = body.toString().split(",")[1] ?? "";
return await this.fileService.create( return await this.fileService.create(
data, body,
{ index: parseInt(chunkIndex), total: parseInt(totalChunks) }, { index: parseInt(chunkIndex), total: parseInt(totalChunks) },
{ id, name }, { id, name },
shareId, shareId,
@@ -72,6 +75,7 @@ export class FileController {
const headers = { const headers = {
"Content-Type": file.metaData.mimeType, "Content-Type": file.metaData.mimeType,
"Content-Length": file.metaData.size, "Content-Length": file.metaData.size,
"Content-Security-Policy": "script-src 'none'",
}; };
if (download === "true") { 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 // 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); const expectedChunkIndex = Math.ceil(diskFileSize / chunkSize);
if (expectedChunkIndex != chunk.index) 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 { NestFactory, Reflector } from "@nestjs/core";
import { NestExpressApplication } from "@nestjs/platform-express"; import { NestExpressApplication } from "@nestjs/platform-express";
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger"; import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
import * as bodyParser from "body-parser"; import * as bodyParser from "body-parser";
import * as cookieParser from "cookie-parser"; import * as cookieParser from "cookie-parser";
import { NextFunction, Request, Response } from "express";
import * as fs from "fs"; import * as fs from "fs";
import { AppModule } from "./app.module"; import { AppModule } from "./app.module";
import { ConfigService } from "./config/config.service";
import { DATA_DIRECTORY } from "./constants"; import { DATA_DIRECTORY } from "./constants";
async function bootstrap() { async function bootstrap() {
@@ -13,7 +19,16 @@ async function bootstrap() {
app.useGlobalPipes(new ValidationPipe({ whitelist: true })); app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector))); 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.use(cookieParser());
app.set("trust proxy", true); app.set("trust proxy", true);
@@ -34,5 +49,8 @@ async function bootstrap() {
} }
await app.listen(parseInt(process.env.PORT) || 8080); await app.listen(parseInt(process.env.PORT) || 8080);
const logger = new Logger("UnhandledAsyncError");
process.on("unhandledRejection", (e) => logger.error(e));
} }
bootstrap(); bootstrap();

View File

@@ -13,7 +13,7 @@ export class ReverseShareTokenWithShares extends OmitType(ReverseShareDTO, [
@Type(() => OmitType(MyShareDTO, ["recipients", "hasPassword"] as const)) @Type(() => OmitType(MyShareDTO, ["recipients", "hasPassword"] as const))
shares: Omit< shares: Omit<
MyShareDTO, MyShareDTO,
"recipients" | "files" | "from" | "fromList" | "hasPassword" "recipients" | "files" | "from" | "fromList" | "hasPassword" | "size"
>[]; >[];
@Expose() @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) @Length(3, 50)
id: string; id: string;
@Length(3, 30)
@IsOptional()
name: string;
@IsString() @IsString()
expiration: string; expiration: string;

View File

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

View File

@@ -14,6 +14,7 @@ import { Throttle } from "@nestjs/throttler";
import { User } from "@prisma/client"; import { User } from "@prisma/client";
import { Request, Response } from "express"; import { Request, Response } from "express";
import { GetUser } from "src/auth/decorator/getUser.decorator"; 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 { JwtGuard } from "src/auth/guard/jwt.guard";
import { CreateShareDTO } from "./dto/createShare.dto"; import { CreateShareDTO } from "./dto/createShare.dto";
import { MyShareDTO } from "./dto/myShare.dto"; import { MyShareDTO } from "./dto/myShare.dto";
@@ -25,10 +26,17 @@ import { ShareOwnerGuard } from "./guard/shareOwner.guard";
import { ShareSecurityGuard } from "./guard/shareSecurity.guard"; import { ShareSecurityGuard } from "./guard/shareSecurity.guard";
import { ShareTokenSecurity } from "./guard/shareTokenSecurity.guard"; import { ShareTokenSecurity } from "./guard/shareTokenSecurity.guard";
import { ShareService } from "./share.service"; import { ShareService } from "./share.service";
import { AdminShareDTO } from "./dto/adminShare.dto";
@Controller("shares") @Controller("shares")
export class ShareController { export class ShareController {
constructor(private shareService: ShareService) {} constructor(private shareService: ShareService) {}
@Get("all")
@UseGuards(JwtGuard, AdministratorGuard)
async getAllShares() {
return new AdminShareDTO().fromList(await this.shareService.getShares());
}
@Get() @Get()
@UseGuards(JwtGuard) @UseGuards(JwtGuard)
async getMyShares(@GetUser() user: User) { async getMyShares(@GetUser() user: User) {

View File

@@ -194,6 +194,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) { async getSharesByUser(userId: string) {
const shares = await this.prisma.share.findMany({ const shares = await this.prisma.share.findMany({
where: { where: {

View File

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

View File

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

View File

@@ -4,6 +4,7 @@ import * as argon from "argon2";
import * as crypto from "crypto"; import * as crypto from "crypto";
import { EmailService } from "src/email/email.service"; import { EmailService } from "src/email/email.service";
import { PrismaService } from "src/prisma/prisma.service"; import { PrismaService } from "src/prisma/prisma.service";
import { FileService } from "../file/file.service";
import { CreateUserDTO } from "./dto/createUser.dto"; import { CreateUserDTO } from "./dto/createUser.dto";
import { UpdateUserDto } from "./dto/updateUser.dto"; import { UpdateUserDto } from "./dto/updateUser.dto";
@@ -12,6 +13,7 @@ export class UserSevice {
constructor( constructor(
private prisma: PrismaService, private prisma: PrismaService,
private emailService: EmailService, private emailService: EmailService,
private fileService: FileService,
) {} ) {}
async list() { async list() {
@@ -74,6 +76,16 @@ export class UserSevice {
} }
async delete(id: string) { 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 } }); return await this.prisma.user.delete({ where: { id } });
} }
} }

View File

@@ -432,7 +432,7 @@
" const responseBody = pm.response.json();", " const responseBody = pm.response.json();",
" pm.expect(responseBody).to.have.property(\"id\")", " pm.expect(responseBody).to.have.property(\"id\")",
" pm.expect(responseBody).to.have.property(\"expiration\")", " 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();", " const responseBody = pm.response.json();",
" pm.expect(responseBody).to.have.property(\"id\")", " pm.expect(responseBody).to.have.property(\"id\")",
" pm.expect(responseBody).to.have.property(\"expiration\")", " 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)",
"});", "});",
"" ""
], ],

View File

@@ -1,12 +1,12 @@
{ {
"name": "pingvin-share-frontend", "name": "pingvin-share-frontend",
"version": "0.22.2", "version": "0.24.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "pingvin-share-frontend", "name": "pingvin-share-frontend",
"version": "0.22.2", "version": "0.24.1",
"dependencies": { "dependencies": {
"@emotion/react": "^11.11.1", "@emotion/react": "^11.11.1",
"@emotion/server": "^11.11.0", "@emotion/server": "^11.11.0",

View File

@@ -1,6 +1,6 @@
{ {
"name": "pingvin-share-frontend", "name": "pingvin-share-frontend",
"version": "0.22.2", "version": "0.24.1",
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,33 +4,24 @@ export default {
"navbar.signin": "Sign in", "navbar.signin": "Sign in",
"navbar.home": "Home", "navbar.home": "Home",
"navbar.signup": "Sign Up", "navbar.signup": "Sign Up",
"navbar.links.shares": "My shares", "navbar.links.shares": "My shares",
"navbar.links.reverse": "Reverse shares", "navbar.links.reverse": "Reverse shares",
"navbar.avatar.account": "My account", "navbar.avatar.account": "My account",
"navbar.avatar.admin": "Administration", "navbar.avatar.admin": "Administration",
"navbar.avatar.signout": "Sign out", "navbar.avatar.signout": "Sign out",
// END navbar // END navbar
// / // /
"home.title": "A <h>self-hosted</h> file sharing platform.", "home.title": "A <h>self-hosted</h> file sharing platform.",
"home.description": "Do you really want to give your personal files in the hand of third parties like WeTransfer?",
"home.description":
"Do you really want to give your personal files in the hand of third parties like WeTransfer?",
"home.bullet.a.name": "Self-Hosted", "home.bullet.a.name": "Self-Hosted",
"home.bullet.a.description": "Host Pingvin Share on your own machine.", "home.bullet.a.description": "Host Pingvin Share on your own machine.",
"home.bullet.b.name": "Privacy", "home.bullet.b.name": "Privacy",
"home.bullet.b.description": "home.bullet.b.description": "Your files are your files and should never get into the hands of third parties.",
"Your files are your files and should never get into the hands of third parties.",
"home.bullet.c.name": "No annoying file size limit", "home.bullet.c.name": "No annoying file size limit",
"home.bullet.c.description": "home.bullet.c.description": "Upload as big files as you want. Only your hard drive will be your limit.",
"Upload as big files as you want. Only your hard drive will be your limit.",
"home.button.start": "Get started", "home.button.start": "Get started",
"home.button.source": "Source code", "home.button.source": "Source code",
// END / // END /
// /auth/signin // /auth/signin
"signin.title": "Welcome back", "signin.title": "Welcome back",
"signin.description": "You don't have an account yet?", "signin.description": "You don't have an account yet?",
@@ -41,17 +32,14 @@ export default {
"signin.input.password.placeholder": "Your password", "signin.input.password.placeholder": "Your password",
"signin.button.submit": "Sign in", "signin.button.submit": "Sign in",
"signIn.notify.totp-required.title": "Two-factor authentication required", "signIn.notify.totp-required.title": "Two-factor authentication required",
"signIn.notify.totp-required.description": "signIn.notify.totp-required.description": "Please enter your two-factor authentication code",
"Please enter your two-factor authentication code",
"signIn.oauth.or": "OR", "signIn.oauth.or": "OR",
"signIn.oauth.github": "GitHub", "signIn.oauth.github": "GitHub",
"signIn.oauth.google": "Google", "signIn.oauth.google": "Google",
"signIn.oauth.microsoft": "Microsoft", "signIn.oauth.microsoft": "Microsoft",
"signIn.oauth.discord": "Discord", "signIn.oauth.discord": "Discord",
"signIn.oauth.oidc": "OpenID", "signIn.oauth.oidc": "OpenID",
// END /auth/signin // END /auth/signin
// /auth/signup // /auth/signup
"signup.title": "Create an account", "signup.title": "Create an account",
"signup.description": "Already have an account?", "signup.description": "Already have an account?",
@@ -61,42 +49,31 @@ export default {
"signup.input.email": "Email", "signup.input.email": "Email",
"signup.input.email.placeholder": "Your email", "signup.input.email.placeholder": "Your email",
"signup.button.submit": "Let's get started", "signup.button.submit": "Let's get started",
// END /auth/signup // END /auth/signup
// /auth/totp // /auth/totp
"totp.title": "TOTP Authentication", "totp.title": "TOTP Authentication",
"totp.button.signIn": "Sign in", "totp.button.signIn": "Sign in",
// END /auth/totp // END /auth/totp
// /auth/reset-password // /auth/reset-password
"resetPassword.title": "Forgot your password?", "resetPassword.title": "Forgot your password?",
"resetPassword.description": "Enter your email to reset your password.", "resetPassword.description": "Enter your email to reset your password.",
"resetPassword.notify.success": "resetPassword.notify.success": "A message with a link to reset your password has been sent if the email exists.",
"A message with a link to reset your password has been sent if the email exists.",
"resetPassword.button.back": "Back to sign in page", "resetPassword.button.back": "Back to sign in page",
"resetPassword.text.resetPassword": "Reset password", "resetPassword.text.resetPassword": "Reset password",
"resetPassword.text.enterNewPassword": "Enter your new password", "resetPassword.text.enterNewPassword": "Enter your new password",
"resetPassword.input.password": "New password", "resetPassword.input.password": "New password",
"resetPassword.notify.passwordReset": "resetPassword.notify.passwordReset": "Your password has been reset successfully.",
"Your password has been reset successfully.",
// /account // /account
"account.title": "My account", "account.title": "My account",
"account.card.info.title": "Account info", "account.card.info.title": "Account info",
"account.card.info.username": "Username", "account.card.info.username": "Username",
"account.card.info.email": "Email", "account.card.info.email": "Email",
"account.notify.info.success": "Account updated successfully", "account.notify.info.success": "Account updated successfully",
"account.card.password.title": "Password", "account.card.password.title": "Password",
"account.card.password.old": "Old password", "account.card.password.old": "Old password",
"account.card.password.new": "New password", "account.card.password.new": "New password",
"account.card.password.noPasswordSet": "account.card.password.noPasswordSet": "You don't have a password set. If you want to sign in with email and password you need to set a password.",
"You don't have a password set. If you want to sign in with email and password you need to set a password.",
"account.notify.password.success": "Password changed successfully", "account.notify.password.success": "Password changed successfully",
"account.card.oauth.title": "Social login", "account.card.oauth.title": "Social login",
"account.card.oauth.github": "GitHub", "account.card.oauth.github": "GitHub",
"account.card.oauth.google": "Google", "account.card.oauth.google": "Google",
@@ -107,15 +84,11 @@ export default {
"account.card.oauth.unlink": "Unlink", "account.card.oauth.unlink": "Unlink",
"account.card.oauth.unlinked": "Unlinked", "account.card.oauth.unlinked": "Unlinked",
"account.modal.unlink.title": "Unlink account", "account.modal.unlink.title": "Unlink account",
"account.modal.unlink.description": "account.modal.unlink.description": "Unlinking your social accounts may cause you to lose your account if you don't remember your username and password.",
"Unlinking your social accounts may cause you to lose your account if you don't remember your username and password.",
"account.notify.oauth.unlinked.success": "Unlinked successfully", "account.notify.oauth.unlinked.success": "Unlinked successfully",
"account.card.security.title": "Security", "account.card.security.title": "Security",
"account.card.security.totp.enable.description": "account.card.security.totp.enable.description": "Enter your current password to start enabling TOTP",
"Enter your current password to start enabling TOTP", "account.card.security.totp.disable.description": "Enter your current password to disable TOTP",
"account.card.security.totp.disable.description":
"Enter your current password to disable TOTP",
"account.card.security.totp.button.start": "Start", "account.card.security.totp.button.start": "Start",
"account.modal.totp.title": "Enable TOTP", "account.modal.totp.title": "Enable TOTP",
"account.modal.totp.step1": "Step 1: Add your authenticator", "account.modal.totp.step1": "Step 1: Add your authenticator",
@@ -126,29 +99,22 @@ export default {
"account.modal.totp.verify": "Verify", "account.modal.totp.verify": "Verify",
"account.notify.totp.disable": "TOTP disabled successfully", "account.notify.totp.disable": "TOTP disabled successfully",
"account.notify.totp.enable": "TOTP enabled successfully", "account.notify.totp.enable": "TOTP enabled successfully",
"account.card.language.title": "Language", "account.card.language.title": "Language",
"account.card.language.description": "account.card.language.description": "The project is translated by the community. Some languages might be incomplete.",
"The project is translated by the community. Some languages might be incomplete.",
"account.card.color.title": "Color scheme", "account.card.color.title": "Color scheme",
// ThemeSwitcher.tsx // ThemeSwitcher.tsx
"account.theme.dark": "Dark", "account.theme.dark": "Dark",
"account.theme.light": "Light", "account.theme.light": "Light",
"account.theme.system": "System", "account.theme.system": "System",
"account.button.delete": "Delete Account", "account.button.delete": "Delete Account",
"account.modal.delete.title": "Delete Account", "account.modal.delete.title": "Delete Account",
"account.modal.delete.description": "account.modal.delete.description": "Do you really want to delete your account including all your active shares?",
"Do you really want to delete your account including all your active shares?",
// END /account // END /account
// /account/shares // /account/shares
"account.shares.title": "My shares", "account.shares.title": "My shares",
"account.shares.title.empty": "It's empty here 👀", "account.shares.title.empty": "It's empty here 👀",
"account.shares.description.empty": "You don't have any shares.", "account.shares.description.empty": "You don't have any shares.",
"account.shares.button.create": "Create one", "account.shares.button.create": "Create one",
"account.shares.info.title": "Share informations", "account.shares.info.title": "Share informations",
"account.shares.table.id": "ID", "account.shares.table.id": "ID",
"account.shares.table.name": "Name", "account.shares.table.name": "Name",
@@ -157,25 +123,16 @@ export default {
"account.shares.table.expiresAt": "Expires at", "account.shares.table.expiresAt": "Expires at",
"account.shares.table.createdAt": "Created at", "account.shares.table.createdAt": "Created at",
"account.shares.table.size": "Size", "account.shares.table.size": "Size",
"account.shares.modal.share-informations": "Share informations", "account.shares.modal.share-informations": "Share informations",
"account.shares.modal.share-link": "Share link", "account.shares.modal.share-link": "Share link",
"account.shares.modal.delete.title": "Delete share {share}", "account.shares.modal.delete.title": "Delete share {share}",
"account.shares.modal.delete.description": "account.shares.modal.delete.description": "Do you really want to delete this share?",
"Do you really want to delete this share?",
// END /account/shares // END /account/shares
// /account/reverseShares // /account/reverseShares
"account.reverseShares.title": "Reverse shares", "account.reverseShares.title": "Reverse shares",
"account.reverseShares.description": "account.reverseShares.description": "A reverse share allows you to generate a unique URL that allows external users to create a share.",
"A reverse share allows you to generate a unique URL that allows external users to create a share.",
"account.reverseShares.title.empty": "It's empty here 👀", "account.reverseShares.title.empty": "It's empty here 👀",
"account.reverseShares.description.empty": "account.reverseShares.description.empty": "You don't have any reverse shares.",
"You don't have any reverse shares.",
// showCreateReverseShareModal.tsx // showCreateReverseShareModal.tsx
"account.reverseShares.modal.title": "Create reverse share", "account.reverseShares.modal.title": "Create reverse share",
"account.reverseShares.modal.expiration.label": "Expiration", "account.reverseShares.modal.expiration.label": "Expiration",
@@ -191,20 +148,13 @@ export default {
"account.reverseShares.modal.expiration.month-plural": "Months", "account.reverseShares.modal.expiration.month-plural": "Months",
"account.reverseShares.modal.expiration.year-singular": "Year", "account.reverseShares.modal.expiration.year-singular": "Year",
"account.reverseShares.modal.expiration.year-plural": "Years", "account.reverseShares.modal.expiration.year-plural": "Years",
"account.reverseShares.modal.max-size.label": "Max share size", "account.reverseShares.modal.max-size.label": "Max share size",
"account.reverseShares.modal.send-email": "Send email notification", "account.reverseShares.modal.send-email": "Send email notification",
"account.reverseShares.modal.send-email.description": "account.reverseShares.modal.send-email.description": "Send an email notification when a share is created with this reverse share link.",
"Send an email notification when a share is created with this reverse share link.",
"account.reverseShares.modal.max-use.label": "Max uses", "account.reverseShares.modal.max-use.label": "Max uses",
"account.reverseShares.modal.max-use.description": "account.reverseShares.modal.max-use.description": "The maximum amount of times this URL can be used to create a share.",
"The maximum amount of times this URL can be used to create a share.",
"account.reverseShare.never-expires": "This reverse share will never expire.", "account.reverseShare.never-expires": "This reverse share will never expire.",
"account.reverseShare.expires-on": "account.reverseShare.expires-on": "This reverse share will expire on {expiration}.",
"This reverse share will expire on {expiration}.",
"account.reverseShares.table.no-shares": "No shares created yet", "account.reverseShares.table.no-shares": "No shares created yet",
"account.reverseShares.table.count.singular": "share", "account.reverseShares.table.count.singular": "share",
"account.reverseShares.table.count.plural": "shares", "account.reverseShares.table.count.plural": "shares",
@@ -212,86 +162,69 @@ export default {
"account.reverseShares.table.remaining": "Remaining uses", "account.reverseShares.table.remaining": "Remaining uses",
"account.reverseShares.table.max-size": "Max share size", "account.reverseShares.table.max-size": "Max share size",
"account.reverseShares.table.expires": "Expires at", "account.reverseShares.table.expires": "Expires at",
"account.reverseShares.modal.reverse-share-link": "Reverse share link", "account.reverseShares.modal.reverse-share-link": "Reverse share link",
"account.reverseShares.modal.delete.title": "Delete reverse share", "account.reverseShares.modal.delete.title": "Delete reverse share",
"account.reverseShares.modal.delete.description": "account.reverseShares.modal.delete.description": "Do you really want to delete this reverse share? If you do, the associated shares will be deleted as well.",
"Do you really want to delete this reverse share? If you do, the associated shares will be deleted as well.",
// END /account/reverseShares // END /account/reverseShares
// /admin // /admin
"admin.title": "Administration", "admin.title": "Administration",
"admin.button.users": "User management", "admin.button.users": "User management",
"admin.button.shares": "Share management",
"admin.button.config": "Configuration", "admin.button.config": "Configuration",
"admin.version": "Version", "admin.version": "Version",
// END /admin // END /admin
// /admin/users // /admin/users
"admin.users.title": "User management", "admin.users.title": "User management",
"admin.users.table.username": "Username", "admin.users.table.username": "Username",
"admin.users.table.email": "Email", "admin.users.table.email": "Email",
"admin.users.table.admin": "Admin", "admin.users.table.admin": "Admin",
"admin.users.edit.update.title": "Update user {username}", "admin.users.edit.update.title": "Update user {username}",
"admin.users.edit.update.admin-privileges": "Admin privileges", "admin.users.edit.update.admin-privileges": "Admin privileges",
"admin.users.edit.update.change-password.title": "Change password", "admin.users.edit.update.change-password.title": "Change password",
"admin.users.edit.update.change-password.field": "New password", "admin.users.edit.update.change-password.field": "New password",
"admin.users.edit.update.change-password.button": "Save new password", "admin.users.edit.update.change-password.button": "Save new password",
"admin.users.edit.update.notify.password.success": "admin.users.edit.update.notify.password.success": "Password changed successfully",
"Password changed successfully",
"admin.users.edit.delete.title": "Delete user {username}", "admin.users.edit.delete.title": "Delete user {username}",
"admin.users.edit.delete.description": "admin.users.edit.delete.description": "Do you really want to delete this user and all his shares?",
"Do you really want to delete this user and all his shares?",
// showCreateUserModal.tsx // showCreateUserModal.tsx
"admin.users.modal.create.title": "Create user", "admin.users.modal.create.title": "Create user",
"admin.users.modal.create.username": "Username", "admin.users.modal.create.username": "Username",
"admin.users.modal.create.email": "Email", "admin.users.modal.create.email": "Email",
"admin.users.modal.create.password": "Password", "admin.users.modal.create.password": "Password",
"admin.users.modal.create.manual-password": "Set password manually", "admin.users.modal.create.manual-password": "Set password manually",
"admin.users.modal.create.manual-password.description": "admin.users.modal.create.manual-password.description": "If not checked, the user will receive an email with a link to set their password.",
"If not checked, the user will receive an email with a link to set their password.",
"admin.users.modal.create.admin": "Admin privileges", "admin.users.modal.create.admin": "Admin privileges",
"admin.users.modal.create.admin.description": "admin.users.modal.create.admin.description": "If checked, the user will be able to access the admin panel.",
"If checked, the user will be able to access the admin panel.",
// END /admin/users // 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
"upload.title": "Upload", "upload.title": "Upload",
"upload.notify.generic-error": "An error occurred while finishing your share.",
"upload.notify.generic-error":
"An error occurred while finishing your share.",
"upload.notify.count-failed": "{count} files failed to upload. Trying again.", "upload.notify.count-failed": "{count} files failed to upload. Trying again.",
// Dropzone.tsx // Dropzone.tsx
"upload.dropzone.title": "Upload files", "upload.dropzone.title": "Upload files",
"upload.dropzone.description": "upload.dropzone.description": "Drag'n'drop files here to start your share. We can accept only files that are less than {maxSize} in total.",
"Drag'n'drop files here to start your share. We can accept only files that are less than {maxSize} in total.", "upload.dropzone.notify.file-too-big": "Your files exceed the maximum share size of {maxSize}.",
"upload.dropzone.notify.file-too-big":
"Your files exceed the maximum share size of {maxSize}.",
// FileList.tsx // FileList.tsx
"upload.filelist.name": "Name", "upload.filelist.name": "Name",
"upload.filelist.size": "Size", "upload.filelist.size": "Size",
// showCreateUploadModal.tsx // showCreateUploadModal.tsx
"upload.modal.title": "Create Share", "upload.modal.title": "Create Share",
"upload.modal.link.error.invalid": "upload.modal.link.error.invalid": "Can only contain letters, numbers, underscores, and hyphens",
"Can only contain letters, numbers, underscores, and hyphens",
"upload.modal.link.error.taken": "This link is already in use", "upload.modal.link.error.taken": "This link is already in use",
"upload.modal.not-signed-in": "You're not signed in", "upload.modal.not-signed-in": "You're not signed in",
"upload.modal.not-signed-in-description": "upload.modal.not-signed-in-description": "You will be unable to delete your share manually and view the visitor count.",
"You will be unable to delete your share manually and view the visitor count.",
"upload.modal.expires.never": "never", "upload.modal.expires.never": "never",
"upload.modal.expires.never-long": "Never Expires", "upload.modal.expires.never-long": "Never Expires",
"upload.modal.expires.error.too-long": "upload.modal.expires.error.too-long": "Expiration exceeds maximum expiration date of {max}.",
"Expiration exceeds maximum expiration date of {max}.",
"upload.modal.link.label": "Link", "upload.modal.link.label": "Link",
"upload.modal.expires.label": "Expiration", "upload.modal.expires.label": "Expiration",
"upload.modal.expires.minute-singular": "Minute", "upload.modal.expires.minute-singular": "Minute",
@@ -306,68 +239,48 @@ export default {
"upload.modal.expires.month-plural": "Months", "upload.modal.expires.month-plural": "Months",
"upload.modal.expires.year-singular": "Year", "upload.modal.expires.year-singular": "Year",
"upload.modal.expires.year-plural": "Years", "upload.modal.expires.year-plural": "Years",
"upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.title": "Description", "upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.description.placeholder": "upload.modal.accordion.name-and-description.description.placeholder": "Note for the recipients of this share",
"Note for the recipients of this share",
"upload.modal.accordion.email.title": "Email recipients", "upload.modal.accordion.email.title": "Email recipients",
"upload.modal.accordion.email.placeholder": "Enter email recipients", "upload.modal.accordion.email.placeholder": "Enter email recipients",
"upload.modal.accordion.email.invalid-email": "Invalid email address", "upload.modal.accordion.email.invalid-email": "Invalid email address",
"upload.modal.accordion.security.title": "Security options", "upload.modal.accordion.security.title": "Security options",
"upload.modal.accordion.security.password.label": "Password protection", "upload.modal.accordion.security.password.label": "Password protection",
"upload.modal.accordion.security.password.placeholder": "No password", "upload.modal.accordion.security.password.placeholder": "No password",
"upload.modal.accordion.security.max-views.label": "Maximum views", "upload.modal.accordion.security.max-views.label": "Maximum views",
"upload.modal.accordion.security.max-views.placeholder": "No limit", "upload.modal.accordion.security.max-views.placeholder": "No limit",
// showCompletedUploadModal.tsx // showCompletedUploadModal.tsx
"upload.modal.completed.never-expires": "This share will never expire.", "upload.modal.completed.never-expires": "This share will never expire.",
"upload.modal.completed.expires-on": "upload.modal.completed.expires-on": "This share will expire on {expiration}.",
"This share will expire on {expiration}.",
"upload.modal.completed.share-ready": "Share ready", "upload.modal.completed.share-ready": "Share ready",
// END /upload // END /upload
// /share/[id] // /share/[id]
"share.title": "Share {shareId}", "share.title": "Share {shareId}",
"share.description": "Look what I've shared with you!", "share.description": "Look what I've shared with you!",
"share.error.visitor-limit-exceeded.title": "Visitor limit exceeded", "share.error.visitor-limit-exceeded.title": "Visitor limit exceeded",
"share.error.visitor-limit-exceeded.description": "share.error.visitor-limit-exceeded.description": "The visitor limit from this share has been exceeded.",
"The visitor limit from this share has been exceeded.",
"share.error.removed.title": "Share removed", "share.error.removed.title": "Share removed",
"share.error.not-found.title": "Share not found", "share.error.not-found.title": "Share not found",
"share.error.not-found.description": "share.error.not-found.description": "The share you're looking for doesn't exist.",
"The share you're looking for doesn't exist.",
"share.modal.password.title": "Password required", "share.modal.password.title": "Password required",
"share.modal.password.description": "share.modal.password.description": "To access this share please enter the password for the share.",
"To access this share please enter the password for the share.",
"share.modal.password": "Password", "share.modal.password": "Password",
"share.modal.error.invalid-password": "Invalid password", "share.modal.error.invalid-password": "Invalid password",
"share.button.download-all": "Download all", "share.button.download-all": "Download all",
"share.notify.download-all-preparing": "share.notify.download-all-preparing": "The share is preparing. Try again in a few minutes.",
"The share is preparing. Try again in a few minutes.",
"share.modal.file-link": "File link", "share.modal.file-link": "File link",
"share.table.name": "Name", "share.table.name": "Name",
"share.table.size": "Size", "share.table.size": "Size",
"share.modal.file-preview.error.not-supported.title": "Preview not supported", "share.modal.file-preview.error.not-supported.title": "Preview not supported",
"share.modal.file-preview.error.not-supported.description": "share.modal.file-preview.error.not-supported.description": "A preview for this file type is unsupported. Please download the file to view it.",
"A preview for this file type is unsupported. Please download the file to view it.",
// END /share/[id] // END /share/[id]
// /share/[id]/edit // /share/[id]/edit
"share.edit.title": "Edit {shareId}", "share.edit.title": "Edit {shareId}",
"share.edit.append-upload": "Append file", "share.edit.append-upload": "Append file",
"share.edit.notify.generic-error": "share.edit.notify.generic-error": "An error occurred while finishing your share.",
"An error occurred while finishing your share.",
"share.edit.notify.save-success": "Share updated successfully", "share.edit.notify.save-success": "Share updated successfully",
// END /share/[id]/edit // END /share/[id]/edit
// /admin/config // /admin/config
"admin.config.title": "Configuration", "admin.config.title": "Configuration",
"admin.config.category.general": "General", "admin.config.category.general": "General",
@@ -375,175 +288,123 @@ export default {
"admin.config.category.email": "Email", "admin.config.category.email": "Email",
"admin.config.category.smtp": "SMTP", "admin.config.category.smtp": "SMTP",
"admin.config.category.oauth": "Social Login", "admin.config.category.oauth": "Social Login",
"admin.config.general.app-name": "App name", "admin.config.general.app-name": "App name",
"admin.config.general.app-name.description": "Name of the application", "admin.config.general.app-name.description": "Name of the application",
"admin.config.general.app-url": "App URL", "admin.config.general.app-url": "App URL",
"admin.config.general.app-url.description": "admin.config.general.app-url.description": "On which URL Pingvin Share is available",
"On which URL Pingvin Share is available",
"admin.config.general.show-home-page": "Show home page", "admin.config.general.show-home-page": "Show home page",
"admin.config.general.show-home-page.description": "admin.config.general.show-home-page.description": "Whether to show the home page",
"Whether to show the home page",
"admin.config.general.logo": "Logo", "admin.config.general.logo": "Logo",
"admin.config.general.logo.description": "admin.config.general.logo.description": "Change your logo by uploading a new image. The image must be a PNG and should have the format 1:1.",
"Change your logo by uploading a new image. The image must be a PNG and should have the format 1:1.",
"admin.config.general.logo.placeholder": "Pick image", "admin.config.general.logo.placeholder": "Pick image",
"admin.config.email.enable-share-email-recipients": "Enable share email recipients",
"admin.config.email.enable-share-email-recipients": "admin.config.email.enable-share-email-recipients.description": "Whether to allow emails to share recipients. Only enable this if you have enabled SMTP.",
"Enable share email recipients",
"admin.config.email.enable-share-email-recipients.description":
"Whether to allow emails to share recipients. Only enable this if you have enabled SMTP.",
"admin.config.email.share-recipients-subject": "Share recipients subject", "admin.config.email.share-recipients-subject": "Share recipients subject",
"admin.config.email.share-recipients-subject.description": "admin.config.email.share-recipients-subject.description": "Subject of the email which gets sent to the share recipients.",
"Subject of the email which gets sent to the share recipients.",
"admin.config.email.share-recipients-message": "Share recipients message", "admin.config.email.share-recipients-message": "Share recipients message",
"admin.config.email.share-recipients-message.description": "admin.config.email.share-recipients-message.description": "Message which gets sent to the share recipients. Available variables:\n {creator} - The username of the creator of the share\n {shareUrl} - The URL of the share\n {desc} - The description of the share\n {expires} - The expiration date of the share\n The variables will be replaced with the actual value.",
"Message which gets sent to the share recipients. Available variables:\n {creator} - The username of the creator of the share\n {shareUrl} - The URL of the share\n {desc} - The description of the share\n {expires} - The expiration date of the share\n The variables will be replaced with the actual value.",
"admin.config.email.reverse-share-subject": "Reverse share subject", "admin.config.email.reverse-share-subject": "Reverse share subject",
"admin.config.email.reverse-share-subject.description": "admin.config.email.reverse-share-subject.description": "Subject of the email which gets sent when someone created a share with your reverse share link.",
"Subject of the email which gets sent when someone created a share with your reverse share link.",
"admin.config.email.reverse-share-message": "Reverse share message", "admin.config.email.reverse-share-message": "Reverse share message",
"admin.config.email.reverse-share-message.description": "admin.config.email.reverse-share-message.description": "Message which gets sent when someone created a share with your reverse share link. {shareUrl} will be replaced with the creator's name and the share URL.",
"Message which gets sent when someone created a share with your reverse share link. {shareUrl} will be replaced with the creator's name and the share URL.",
"admin.config.email.reset-password-subject": "Reset password subject", "admin.config.email.reset-password-subject": "Reset password subject",
"admin.config.email.reset-password-subject.description": "admin.config.email.reset-password-subject.description": "Subject of the email which gets sent when a user requests a password reset.",
"Subject of the email which gets sent when a user requests a password reset.",
"admin.config.email.reset-password-message": "Reset password message", "admin.config.email.reset-password-message": "Reset password message",
"admin.config.email.reset-password-message.description": "admin.config.email.reset-password-message.description": "Message which gets sent when a user requests a password reset. {url} will be replaced with the reset password URL.",
"Message which gets sent when a user requests a password reset. {url} will be replaced with the reset password URL.",
"admin.config.email.invite-subject": "Invite subject", "admin.config.email.invite-subject": "Invite subject",
"admin.config.email.invite-subject.description": "admin.config.email.invite-subject.description": "Subject of the email which gets sent when an admin invites a user.",
"Subject of the email which gets sent when an admin invites a user.",
"admin.config.email.invite-message": "Invite message", "admin.config.email.invite-message": "Invite message",
"admin.config.email.invite-message.description": "admin.config.email.invite-message.description": "Message which gets sent when an admin invites a user. {url} will be replaced with the invite URL and {password} with the password.",
"Message which gets sent when an admin invites a user. {url} will be replaced with the invite URL and {password} with the password.",
"admin.config.share.allow-registration": "Allow registration", "admin.config.share.allow-registration": "Allow registration",
"admin.config.share.allow-registration.description": "admin.config.share.allow-registration.description": "Whether registration is allowed",
"Whether registration is allowed", "admin.config.share.allow-unauthenticated-shares": "Allow unauthenticated shares",
"admin.config.share.allow-unauthenticated-shares": "admin.config.share.allow-unauthenticated-shares.description": "Whether unauthenticated users can create shares",
"Allow unauthenticated shares",
"admin.config.share.allow-unauthenticated-shares.description":
"Whether unauthenticated users can create shares",
"admin.config.share.max-expiration": "Max expiration", "admin.config.share.max-expiration": "Max expiration",
"admin.config.share.max-expiration.description": "admin.config.share.max-expiration.description": "Maximum share expiration in hours. Set to 0 to allow unlimited expiration.",
"Maximum share expiration in hours. Set to 0 to allow unlimited expiration.",
"admin.config.share.max-size": "Max size", "admin.config.share.max-size": "Max size",
"admin.config.share.max-size.description": "Maximum share size in bytes", "admin.config.share.max-size.description": "Maximum share size in bytes",
"admin.config.share.zip-compression-level": "Zip compression level", "admin.config.share.zip-compression-level": "Zip compression level",
"admin.config.share.zip-compression-level.description": "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. ",
"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": "Enabled", "admin.config.smtp.enabled": "Enabled",
"admin.config.smtp.enabled.description": "admin.config.smtp.enabled.description": "Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.",
"Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.",
"admin.config.smtp.host": "Host", "admin.config.smtp.host": "Host",
"admin.config.smtp.host.description": "Host of the SMTP server", "admin.config.smtp.host.description": "Host of the SMTP server",
"admin.config.smtp.port": "Port", "admin.config.smtp.port": "Port",
"admin.config.smtp.port.description": "Port of the SMTP server", "admin.config.smtp.port.description": "Port of the SMTP server",
"admin.config.smtp.email": "Email", "admin.config.smtp.email": "Email",
"admin.config.smtp.email.description": "admin.config.smtp.email.description": "Email address which the emails get sent from",
"Email address which the emails get sent from",
"admin.config.smtp.username": "Username", "admin.config.smtp.username": "Username",
"admin.config.smtp.username.description": "Username of the SMTP server", "admin.config.smtp.username.description": "Username of the SMTP server",
"admin.config.smtp.password": "Password", "admin.config.smtp.password": "Password",
"admin.config.smtp.password.description": "Password of the SMTP server", "admin.config.smtp.password.description": "Password of the SMTP server",
"admin.config.smtp.button.test": "Send test email", "admin.config.smtp.button.test": "Send test email",
"admin.config.oauth.allow-registration": "Allow registration", "admin.config.oauth.allow-registration": "Allow registration",
"admin.config.oauth.allow-registration.description": "admin.config.oauth.allow-registration.description": "Allow users to register via social login",
"Allow users to register via social login",
"admin.config.oauth.ignore-totp": "Ignore TOTP", "admin.config.oauth.ignore-totp": "Ignore TOTP",
"admin.config.oauth.ignore-totp.description": "admin.config.oauth.ignore-totp.description": "Whether to ignore TOTP when user using social login",
"Whether to ignore TOTP when user using social login",
"admin.config.oauth.github-enabled": "GitHub", "admin.config.oauth.github-enabled": "GitHub",
"admin.config.oauth.github-enabled.description": "admin.config.oauth.github-enabled.description": "Whether GitHub login is enabled",
"Whether GitHub login is enabled",
"admin.config.oauth.github-client-id": "GitHub Client ID", "admin.config.oauth.github-client-id": "GitHub Client ID",
"admin.config.oauth.github-client-id.description": "admin.config.oauth.github-client-id.description": "Client ID of the GitHub OAuth app",
"Client ID of the GitHub OAuth app",
"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": "admin.config.oauth.github-client-secret.description": "Client secret of the GitHub OAuth app",
"Client secret of the GitHub OAuth app",
"admin.config.oauth.google-enabled": "Google", "admin.config.oauth.google-enabled": "Google",
"admin.config.oauth.google-enabled.description": "admin.config.oauth.google-enabled.description": "Whether Google login is enabled",
"Whether Google login is enabled",
"admin.config.oauth.google-client-id": "Google Client ID", "admin.config.oauth.google-client-id": "Google Client ID",
"admin.config.oauth.google-client-id.description": "admin.config.oauth.google-client-id.description": "Client ID of the Google OAuth app",
"Client ID of the Google OAuth app",
"admin.config.oauth.google-client-secret": "Google Client secret", "admin.config.oauth.google-client-secret": "Google Client secret",
"admin.config.oauth.google-client-secret.description": "admin.config.oauth.google-client-secret.description": "Client secret of the Google OAuth app",
"Client secret of the Google OAuth app",
"admin.config.oauth.microsoft-enabled": "Microsoft", "admin.config.oauth.microsoft-enabled": "Microsoft",
"admin.config.oauth.microsoft-enabled.description": "admin.config.oauth.microsoft-enabled.description": "Whether Microsoft login is enabled",
"Whether Microsoft login is enabled",
"admin.config.oauth.microsoft-tenant": "Microsoft Tenant", "admin.config.oauth.microsoft-tenant": "Microsoft Tenant",
"admin.config.oauth.microsoft-tenant.description": "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.",
"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.",
"admin.config.oauth.microsoft-client-id": "Microsoft Client ID", "admin.config.oauth.microsoft-client-id": "Microsoft Client ID",
"admin.config.oauth.microsoft-client-id.description": "admin.config.oauth.microsoft-client-id.description": "Client ID of the Microsoft OAuth app",
"Client ID of the Microsoft OAuth app",
"admin.config.oauth.microsoft-client-secret": "Microsoft Client secret", "admin.config.oauth.microsoft-client-secret": "Microsoft Client secret",
"admin.config.oauth.microsoft-client-secret.description": "admin.config.oauth.microsoft-client-secret.description": "Client secret of the Microsoft OAuth app",
"Client secret of the Microsoft OAuth app",
"admin.config.oauth.discord-enabled": "Discord", "admin.config.oauth.discord-enabled": "Discord",
"admin.config.oauth.discord-enabled.description": "admin.config.oauth.discord-enabled.description": "Whether Discord login is enabled",
"Whether Discord login is enabled",
"admin.config.oauth.discord-limited-guild": "Discord limited server ID", "admin.config.oauth.discord-limited-guild": "Discord limited server ID",
"admin.config.oauth.discord-limited-guild.description": "admin.config.oauth.discord-limited-guild.description": "Limit signing in to users in a specific server. Leave it blank to disable.",
"Limit signing in to users in a specific server. Leave it blank to disable.",
"admin.config.oauth.discord-client-id": "Discord Client ID", "admin.config.oauth.discord-client-id": "Discord Client ID",
"admin.config.oauth.discord-client-id.description": "admin.config.oauth.discord-client-id.description": "Client ID of the Discord OAuth app",
"Client ID of the Discord OAuth app",
"admin.config.oauth.discord-client-secret": "Discord Client secret", "admin.config.oauth.discord-client-secret": "Discord Client secret",
"admin.config.oauth.discord-client-secret.description": "admin.config.oauth.discord-client-secret.description": "Client secret of the Discord OAuth app",
"Client secret of the Discord OAuth app",
"admin.config.oauth.oidc-enabled": "OpenID Connect", "admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description": "admin.config.oauth.oidc-enabled.description": "Whether OpenID Connect login is enabled",
"Whether OpenID Connect login is enabled",
"admin.config.oauth.oidc-discovery-uri": "OpenID Connect Discovery URI", "admin.config.oauth.oidc-discovery-uri": "OpenID Connect Discovery URI",
"admin.config.oauth.oidc-discovery-uri.description": "admin.config.oauth.oidc-discovery-uri.description": "Discovery URI of the OpenID Connect OAuth app",
"Discovery URI of the OpenID Connect OAuth app",
"admin.config.oauth.oidc-username-claim": "OpenID Connect username claim", "admin.config.oauth.oidc-username-claim": "OpenID Connect username claim",
"admin.config.oauth.oidc-username-claim.description": "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.",
"Username claim in OpenID Connect ID token. Leave it blank if you don't know what this config is.",
"admin.config.oauth.oidc-client-id": "OpenID Connect Client ID", "admin.config.oauth.oidc-client-id": "OpenID Connect Client ID",
"admin.config.oauth.oidc-client-id.description": "admin.config.oauth.oidc-client-id.description": "Client ID of the OpenID Connect OAuth app",
"Client ID of the OpenID Connect OAuth app",
"admin.config.oauth.oidc-client-secret": "OpenID Connect Client secret", "admin.config.oauth.oidc-client-secret": "OpenID Connect Client secret",
"admin.config.oauth.oidc-client-secret.description": "admin.config.oauth.oidc-client-secret.description": "Client secret of the OpenID Connect OAuth app",
"Client secret of the OpenID Connect OAuth app",
// 404 // 404
"404.description": "Oops this page doesn't exist.", "404.description": "Oops this page doesn't exist.",
"404.button.home": "Bring me back home", "404.button.home": "Bring me back home",
// error // error
"error.title": "Error", "error.title": "Error",
"error.description": "Oops!", "error.description": "Oops!",
"error.button.back": "Go back", "error.button.back": "Go back",
"error.msg.default": "Something went wrong.", "error.msg.default": "Something went wrong.",
"error.msg.access_denied": "error.msg.access_denied": "You canceled the authentication process, please try again.",
"You canceled the authentication process, please try again.", "error.msg.expired_token": "The authentication process took too long, 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": "Internal Error",
"error.msg.no_user": "User linked to this {0} account doesn't exist.", "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.no_email": "Can't get email address from this {0} account.",
"error.msg.already_linked": "error.msg.already_linked": "This {0} account is already linked to another account.",
"This {0} account is already linked to another account.",
"error.msg.not_linked": "This {0} account haven't linked to any account yet.", "error.msg.not_linked": "This {0} account haven't linked to any account yet.",
"error.msg.unverified_account": "error.msg.unverified_account": "This {0} account is unverified, please try again after verification.",
"This {0} account is unverified, please try again after verification.", "error.msg.discord_guild_permission_denied": "You are not allowed to sign in.",
"error.msg.discord_guild_permission_denied": "error.msg.cannot_get_user_info": "Can not get your user info from this {0} account.",
"You are not allowed to sign in.",
"error.msg.cannot_get_user_info":
"Can not get your user info from this {0} account.",
"error.param.provider_github": "GitHub", "error.param.provider_github": "GitHub",
"error.param.provider_google": "Google", "error.param.provider_google": "Google",
"error.param.provider_microsoft": "Microsoft", "error.param.provider_microsoft": "Microsoft",
"error.param.provider_discord": "Discord", "error.param.provider_discord": "Discord",
"error.param.provider_oidc": "OpenID Connect", "error.param.provider_oidc": "OpenID Connect",
// Common translations // Common translations
"common.button.save": "Save", "common.button.save": "Save",
"common.button.create": "Create", "common.button.create": "Create",
@@ -562,7 +423,6 @@ export default {
"common.button.go-home": "Go home", "common.button.go-home": "Go home",
"common.notify.copied": "Your link was copied to the clipboard", "common.notify.copied": "Your link was copied to the clipboard",
"common.success": "Success", "common.success": "Success",
"common.error": "Error", "common.error": "Error",
"common.error.unknown": "An unknown error occurred", "common.error.unknown": "An unknown error occurred",
"common.error.invalid-email": "Invalid email address", "common.error.invalid-email": "Invalid email address",
@@ -570,5 +430,5 @@ export default {
"common.error.too-long": "Must be at most {length} characters", "common.error.too-long": "Must be at most {length} characters",
"common.error.exact-length": "Must be exactly {length} characters", "common.error.exact-length": "Must be exactly {length} characters",
"common.error.invalid-number": "Must be a number", "common.error.invalid-number": "Must be a number",
"common.error.field-required": "This field is required", "common.error.field-required": "This field is required"
}; };

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Administration", "admin.title": "Administration",
"admin.button.users": "Brugeradministration", "admin.button.users": "Brugeradministration",
"admin.button.shares": "Share management",
"admin.button.config": "Konfiguration", "admin.button.config": "Konfiguration",
"admin.version": "Version", "admin.version": "Version",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Admin rettigheder", "admin.users.modal.create.admin": "Admin rettigheder",
"admin.users.modal.create.admin.description": "If checked, the user will be able to access the admin panel.", "admin.users.modal.create.admin.description": "If checked, the user will be able to access the admin panel.",
// END /admin/users // 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
"upload.title": "Upload", "upload.title": "Upload",
"upload.notify.generic-error": "Der opstod en fejl under afslutningen af din deling.", "upload.notify.generic-error": "Der opstod en fejl under afslutningen af din deling.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Måneder", "upload.modal.expires.month-plural": "Måneder",
"upload.modal.expires.year-singular": "År", "upload.modal.expires.year-singular": "År",
"upload.modal.expires.year-plural": "År", "upload.modal.expires.year-plural": "År",
"upload.modal.accordion.description.title": "Beskrivelse", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Bemærkning til modtagerne af dette share", "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.title": "E-mail modtagere",
"upload.modal.accordion.email.placeholder": "Indtast e-mail modtagere", "upload.modal.accordion.email.placeholder": "Indtast e-mail modtagere",
"upload.modal.accordion.email.invalid-email": "Ugyldig e-mailadresse", "upload.modal.accordion.email.invalid-email": "Ugyldig e-mailadresse",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Maksimal filstørrelse i bytes", "admin.config.share.max-size.description": "Maksimal filstørrelse i bytes",
"admin.config.share.zip-compression-level": "Zip compression level", "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.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": "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.", "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.",
"admin.config.smtp.host": "Vært", "admin.config.smtp.host": "Vært",
@@ -327,7 +340,7 @@ export default {
"admin.config.smtp.password": "Adgangskode", "admin.config.smtp.password": "Adgangskode",
"admin.config.smtp.password.description": "Adgangskoden til SMTP serveren", "admin.config.smtp.password.description": "Adgangskoden til SMTP serveren",
"admin.config.smtp.button.test": "Send test e-mail", "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.allow-registration.description": "Allow users to register via social login",
"admin.config.oauth.ignore-totp": "Ignore TOTP", "admin.config.oauth.ignore-totp": "Ignore TOTP",
"admin.config.oauth.ignore-totp.description": "Whether to ignore TOTP when user using social login", "admin.config.oauth.ignore-totp.description": "Whether to ignore TOTP when user using social login",
@@ -379,7 +392,7 @@ export default {
"error.msg.default": "Something went wrong.", "error.msg.default": "Something went wrong.",
"error.msg.access_denied": "You canceled the authentication process, please try again.", "error.msg.access_denied": "You canceled the authentication process, please try again.",
"error.msg.expired_token": "The authentication process took too long, 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_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.no_email": "Can't get email address from this {0} account.",
"error.msg.already_linked": "This {0} account is already linked to another account.", "error.msg.already_linked": "This {0} account is already linked to another account.",

View File

@@ -57,7 +57,7 @@ export default {
// /auth/reset-password // /auth/reset-password
"resetPassword.title": "Passwort vergessen?", "resetPassword.title": "Passwort vergessen?",
"resetPassword.description": "Gib deine Email Adresse ein, um dein Passwort zurückzusetzen.", "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.", "resetPassword.notify.success": "Wir haben dir einen Link gesendet, unter dem du dein Passwort zurücksetzen kannst.",
"resetPassword.button.back": "Zurück zur Anmeldeseite", "resetPassword.button.back": "Zurück zur Anmeldeseite",
"resetPassword.text.resetPassword": "Passwort zurücksetzen", "resetPassword.text.resetPassword": "Passwort zurücksetzen",
"resetPassword.text.enterNewPassword": "Gib dein neues Passwort ein", "resetPassword.text.enterNewPassword": "Gib dein neues Passwort ein",
@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Verwaltung", "admin.title": "Verwaltung",
"admin.button.users": "Benutzerverwaltung", "admin.button.users": "Benutzerverwaltung",
"admin.button.shares": "Share management",
"admin.button.config": "Konfiguration", "admin.button.config": "Konfiguration",
"admin.version": "Version", "admin.version": "Version",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Administratorrechte", "admin.users.modal.create.admin": "Administratorrechte",
"admin.users.modal.create.admin.description": "Wenn aktiviert, kann der Benutzer auf das Administrator-Panel zugreifen.", "admin.users.modal.create.admin.description": "Wenn aktiviert, kann der Benutzer auf das Administrator-Panel zugreifen.",
// END /admin/users // 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
"upload.title": "Upload", "upload.title": "Upload",
"upload.notify.generic-error": "Während der Erstellung der Freigabe ist ein Fehler aufgetreten.", "upload.notify.generic-error": "Während der Erstellung der Freigabe ist ein Fehler aufgetreten.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Monate", "upload.modal.expires.month-plural": "Monate",
"upload.modal.expires.year-singular": "Jahr", "upload.modal.expires.year-singular": "Jahr",
"upload.modal.expires.year-plural": "Year", "upload.modal.expires.year-plural": "Year",
"upload.modal.accordion.description.title": "Beschreibung", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Hinweis für die Empfänger dieser Freigabe", "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 Empfänger", "upload.modal.accordion.email.title": "Email Empfänger",
"upload.modal.accordion.email.placeholder": "Email der Empfänger eingeben", "upload.modal.accordion.email.placeholder": "Email der Empfänger eingeben",
"upload.modal.accordion.email.invalid-email": "Ungültige Emailadresse", "upload.modal.accordion.email.invalid-email": "Ungültige Emailadresse",
@@ -262,7 +273,7 @@ export default {
"share.table.name": "Name", "share.table.name": "Name",
"share.table.size": "Größe", "share.table.size": "Größe",
"share.modal.file-preview.error.not-supported.title": "Vorschau wird nicht unterstützt", "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.", "share.modal.file-preview.error.not-supported.description": "Eine Vorschau für diesen Dateityp wird nicht unterstützt. Bitte lade die Datei herunter, um sie anzusehen.",
// END /share/[id] // END /share/[id]
// /share/[id]/edit // /share/[id]/edit
"share.edit.title": "{shareId} bearbeiten", "share.edit.title": "{shareId} bearbeiten",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Maximale Größe einer Freigabe in Bytes", "admin.config.share.max-size.description": "Maximale Größe einer Freigabe in Bytes",
"admin.config.share.zip-compression-level": "Zip Komprimierungsstufe", "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.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": "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.", "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.",
"admin.config.smtp.host": "Host", "admin.config.smtp.host": "Host",
@@ -353,18 +366,18 @@ export default {
"admin.config.oauth.microsoft-client-secret.description": "Client-Secret der Microsoft OAuth-App", "admin.config.oauth.microsoft-client-secret.description": "Client-Secret der Microsoft OAuth-App",
"admin.config.oauth.discord-enabled": "Discord", "admin.config.oauth.discord-enabled": "Discord",
"admin.config.oauth.discord-enabled.description": "Discord Anmeldung erlaubt", "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.", "admin.config.oauth.discord-limited-guild.description": "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": "Discord Client-ID",
"admin.config.oauth.discord-client-id.description": "Client-ID der Discord OAuth-App", "admin.config.oauth.discord-client-id.description": "Client-ID der Discord OAuth-App",
"admin.config.oauth.discord-client-secret": "Discord Client-Secret", "admin.config.oauth.discord-client-secret": "Discord Client-Secret",
"admin.config.oauth.discord-client-secret.description": "Client-Secret der Discord OAuth-App", "admin.config.oauth.discord-client-secret.description": "Client-Secret der Discord OAuth-App",
"admin.config.oauth.oidc-enabled": "OpenID Connect", "admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description": "OpenID Connect Anmeldung erlaubt", "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-discovery-uri.description": "Discovery-URL der OpenID OAuth App",
"admin.config.oauth.oidc-username-claim": "OpenID Connect username claim", "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.", "admin.config.oauth.oidc-username-claim.description": "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": "OpenID Connect Client-ID",
"admin.config.oauth.oidc-client-id.description": "Client-ID der OpenID Connect OAuth-App", "admin.config.oauth.oidc-client-id.description": "Client-ID der OpenID Connect OAuth-App",
"admin.config.oauth.oidc-client-secret": "OpenID Connect Client-Secret", "admin.config.oauth.oidc-client-secret": "OpenID Connect Client-Secret",
@@ -407,7 +420,7 @@ export default {
"common.text.navigate-to-link": "Link öffnen", "common.text.navigate-to-link": "Link öffnen",
"common.text.or": "oder", "common.text.or": "oder",
"common.button.go-back": "Zurück", "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.notify.copied": "Dein Link wurde in die Zwischenablage kopiert",
"common.success": "Erfolg", "common.success": "Erfolg",
"common.error": "Fehler", "common.error": "Fehler",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Διαχείριση", "admin.title": "Διαχείριση",
"admin.button.users": "Διαχείριση χρηστών", "admin.button.users": "Διαχείριση χρηστών",
"admin.button.shares": "Share management",
"admin.button.config": "Διαμόρφωση", "admin.button.config": "Διαμόρφωση",
"admin.version": "Έκδοση", "admin.version": "Έκδοση",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Δικαιώματα διαχειριστή", "admin.users.modal.create.admin": "Δικαιώματα διαχειριστή",
"admin.users.modal.create.admin.description": "Αν ενεργοποιηθεί, ο χρήστης θα μπορεί να έχει πρόσβαση στον πίνακα διαχείρισης.", "admin.users.modal.create.admin.description": "Αν ενεργοποιηθεί, ο χρήστης θα μπορεί να έχει πρόσβαση στον πίνακα διαχείρισης.",
// END /admin/users // 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
"upload.title": "Μεταφόρτωση", "upload.title": "Μεταφόρτωση",
"upload.notify.generic-error": "Παρουσιάστηκε σφάλμα κατά την ολοκλήρωση της κοινής χρήσης σας.", "upload.notify.generic-error": "Παρουσιάστηκε σφάλμα κατά την ολοκλήρωση της κοινής χρήσης σας.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Μήνες", "upload.modal.expires.month-plural": "Μήνες",
"upload.modal.expires.year-singular": "Έτος", "upload.modal.expires.year-singular": "Έτος",
"upload.modal.expires.year-plural": "Έτη", "upload.modal.expires.year-plural": "Έτη",
"upload.modal.accordion.description.title": "Περιγραφή", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Σημείωση για τους παραλήπτες αυτής της κοινοποίησης", "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.title": "Αποδέκτες email",
"upload.modal.accordion.email.placeholder": "Εισάγετε αποδέκτες email", "upload.modal.accordion.email.placeholder": "Εισάγετε αποδέκτες email",
"upload.modal.accordion.email.invalid-email": "Μη έγκυρη διεύθυνση e-mail", "upload.modal.accordion.email.invalid-email": "Μη έγκυρη διεύθυνση e-mail",
@@ -262,7 +273,7 @@ export default {
"share.table.name": "Όνομα", "share.table.name": "Όνομα",
"share.table.size": "Μέγεθος", "share.table.size": "Μέγεθος",
"share.modal.file-preview.error.not-supported.title": "Η προεπισκόπηση δεν υποστηρίζεται", "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.", "share.modal.file-preview.error.not-supported.description": "Η προεπισκόπηση για αυτό τον τύπο αρχείου δεν υποστηρίζεται. Παρακαλώ κατεβάστε το αρχείο για να το δείτε.",
// END /share/[id] // END /share/[id]
// /share/[id]/edit // /share/[id]/edit
"share.edit.title": "Ενημέρωση {shareId}", "share.edit.title": "Ενημέρωση {shareId}",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Μέγιστο μέγεθος κοινοποίησης σε bytes", "admin.config.share.max-size.description": "Μέγιστο μέγεθος κοινοποίησης σε bytes",
"admin.config.share.zip-compression-level": "Βαθμός συμπίεσης ZIP", "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": "Προσαρμόστε το μέγεθος κομματιών (σε bytes) για να εξισορροπήσετε την αποδοτικότητα και την αξιοπιστία του συστήματος σύμφωνα με τη σύνδεσή σας στο διαδίκτυο. Μικρότερα κομμάτια μπορούν να βελτιώσουν τα ποσοστά επιτυχίας σε ασταθείς συνδέσεις, ενώ μεγαλύτερα κομμάτια επιταχύνουν τις μεταφορτώσεις σε σταθερές συνδέσεις.",
"admin.config.smtp.enabled": "Ενεργοποιημένο", "admin.config.smtp.enabled": "Ενεργοποιημένο",
"admin.config.smtp.enabled.description": "Εάν η λειτουργία SMTP είναι ενεργοποιημένη. Ενεργοποιήστε τη μόνον όταν ορίσετε σωστά τις παραμέτρους που ακολουθούν.", "admin.config.smtp.enabled.description": "Εάν η λειτουργία SMTP είναι ενεργοποιημένη. Ενεργοποιήστε τη μόνον όταν ορίσετε σωστά τις παραμέτρους που ακολουθούν.",
"admin.config.smtp.host": "Εξυπηρετητής", "admin.config.smtp.host": "Εξυπηρετητής",
@@ -407,7 +420,7 @@ export default {
"common.text.navigate-to-link": "Μεταβείτε στο σύνδεσμο", "common.text.navigate-to-link": "Μεταβείτε στο σύνδεσμο",
"common.text.or": "ή", "common.text.or": "ή",
"common.button.go-back": "Επιστροφή", "common.button.go-back": "Επιστροφή",
"common.button.go-home": "Go home", "common.button.go-home": "Μετάβαση στην αρχική",
"common.notify.copied": "Ο σύνδεσμος σας αντιγράφηκε στο πρόχειρο", "common.notify.copied": "Ο σύνδεσμος σας αντιγράφηκε στο πρόχειρο",
"common.success": "Επιτυχία", "common.success": "Επιτυχία",
"common.error": "Σφάλμα", "common.error": "Σφάλμα",

View File

@@ -224,6 +224,7 @@ export default {
// /admin // /admin
"admin.title": "Administration", "admin.title": "Administration",
"admin.button.users": "User management", "admin.button.users": "User management",
"admin.button.shares": "Share management",
"admin.button.config": "Configuration", "admin.button.config": "Configuration",
"admin.version": "Version", "admin.version": "Version",
// END /admin // END /admin
@@ -260,6 +261,19 @@ export default {
// END /admin/users // 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
"upload.title": "Upload", "upload.title": "Upload",
@@ -307,8 +321,9 @@ export default {
"upload.modal.expires.year-singular": "Year", "upload.modal.expires.year-singular": "Year",
"upload.modal.expires.year-plural": "Years", "upload.modal.expires.year-plural": "Years",
"upload.modal.accordion.description.title": "Description", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "upload.modal.accordion.name-and-description.name.placeholder": "Name",
"upload.modal.accordion.name-and-description.description.placeholder":
"Note for the recipients of this share", "Note for the recipients of this share",
"upload.modal.accordion.email.title": "Email recipients", "upload.modal.accordion.email.title": "Email recipients",
@@ -432,7 +447,9 @@ export default {
"admin.config.share.zip-compression-level": "Zip compression level", "admin.config.share.zip-compression-level": "Zip compression level",
"admin.config.share.zip-compression-level.description": "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. ", "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": "Enabled", "admin.config.smtp.enabled": "Enabled",
"admin.config.smtp.enabled.description": "admin.config.smtp.enabled.description":
"Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.", "Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.",

View File

@@ -57,7 +57,7 @@ export default {
// /auth/reset-password // /auth/reset-password
"resetPassword.title": "¿Olvidaste tu contraseña?", "resetPassword.title": "¿Olvidaste tu contraseña?",
"resetPassword.description": "Ingresa tu correo para restablecer tu contraseña.", "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.", "resetPassword.notify.success": "Se ha enviado un mensaje con un enlace para restablecer tu contraseña.",
"resetPassword.button.back": "Volver al inicio de sesión", "resetPassword.button.back": "Volver al inicio de sesión",
"resetPassword.text.resetPassword": "Restablecer contraseña", "resetPassword.text.resetPassword": "Restablecer contraseña",
"resetPassword.text.enterNewPassword": "Ingresa tu nueva contraseña", "resetPassword.text.enterNewPassword": "Ingresa tu nueva contraseña",
@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Administración", "admin.title": "Administración",
"admin.button.users": "Gestión de usuarios", "admin.button.users": "Gestión de usuarios",
"admin.button.shares": "Share management",
"admin.button.config": "Configuración", "admin.button.config": "Configuración",
"admin.version": "Versión", "admin.version": "Versión",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Privilegios de administrador", "admin.users.modal.create.admin": "Privilegios de administrador",
"admin.users.modal.create.admin.description": "Si se marca, el usuario podrá acceder al panel de administrador.", "admin.users.modal.create.admin.description": "Si se marca, el usuario podrá acceder al panel de administrador.",
// END /admin/users // 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
"upload.title": "Subir", "upload.title": "Subir",
"upload.notify.generic-error": "Ha ocurrido un error mientras se compartía tu archivo.", "upload.notify.generic-error": "Ha ocurrido un error mientras se compartía tu archivo.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Meses", "upload.modal.expires.month-plural": "Meses",
"upload.modal.expires.year-singular": "Año", "upload.modal.expires.year-singular": "Año",
"upload.modal.expires.year-plural": "Años", "upload.modal.expires.year-plural": "Años",
"upload.modal.accordion.description.title": "Descripción", "upload.modal.accordion.name-and-description.title": "Nombre y descripción",
"upload.modal.accordion.description.placeholder": "Nota para los destinatarios de este compartido", "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.title": "Correo de los destinatarios",
"upload.modal.accordion.email.placeholder": "Ingresa los correos de los destinatarios", "upload.modal.accordion.email.placeholder": "Ingresa los correos de los destinatarios",
"upload.modal.accordion.email.invalid-email": "Dirección de correo inválida", "upload.modal.accordion.email.invalid-email": "Dirección de correo inválida",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Tamaño máximo de los archivos, en bytes", "admin.config.share.max-size.description": "Tamaño máximo de los archivos, en bytes",
"admin.config.share.zip-compression-level": "Nivel de compresión del Zip", "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.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": "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.", "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.",
"admin.config.smtp.host": "Host", "admin.config.smtp.host": "Host",
@@ -407,7 +420,7 @@ export default {
"common.text.navigate-to-link": "Ir al enlace", "common.text.navigate-to-link": "Ir al enlace",
"common.text.or": "o", "common.text.or": "o",
"common.button.go-back": "Volver", "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.notify.copied": "Tu enlace se ha copiado al portapapeles",
"common.success": "Éxito", "common.success": "Éxito",
"common.error": "Error", "common.error": "Error",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Ylläpito", "admin.title": "Ylläpito",
"admin.button.users": "Käyttäjien Hallinta", "admin.button.users": "Käyttäjien Hallinta",
"admin.button.shares": "Share management",
"admin.button.config": "Asetukset", "admin.button.config": "Asetukset",
"admin.version": "Versio", "admin.version": "Versio",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Ylläpitäjän oikeudet", "admin.users.modal.create.admin": "Ylläpitäjän oikeudet",
"admin.users.modal.create.admin.description": "Jos valittu, käyttäjä voi käyttää hallintapaneelia.", "admin.users.modal.create.admin.description": "Jos valittu, käyttäjä voi käyttää hallintapaneelia.",
// END /admin/users // 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
"upload.title": "Pilvetä", "upload.title": "Pilvetä",
"upload.notify.generic-error": "Kohdattiin odottamaton virhe jaon luomisessa.", "upload.notify.generic-error": "Kohdattiin odottamaton virhe jaon luomisessa.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Kuukautta", "upload.modal.expires.month-plural": "Kuukautta",
"upload.modal.expires.year-singular": "Vuosi", "upload.modal.expires.year-singular": "Vuosi",
"upload.modal.expires.year-plural": "Vuotta", "upload.modal.expires.year-plural": "Vuotta",
"upload.modal.accordion.description.title": "Kuvaus", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Huomautus tämän jaon vastaanottajille", "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.title": "Sähköpostin vastaanottajat",
"upload.modal.accordion.email.placeholder": "Syötä sähköpostin vastaanottajat", "upload.modal.accordion.email.placeholder": "Syötä sähköpostin vastaanottajat",
"upload.modal.accordion.email.invalid-email": "Virheellinen sähköpostiosoite", "upload.modal.accordion.email.invalid-email": "Virheellinen sähköpostiosoite",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Jaon enimmäiskoko tavuissa (bytes)", "admin.config.share.max-size.description": "Jaon enimmäiskoko tavuissa (bytes)",
"admin.config.share.zip-compression-level": "Zip puristustaso", "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.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": "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.", "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.",
"admin.config.smtp.host": "Isäntä", "admin.config.smtp.host": "Isäntä",

View File

@@ -57,7 +57,7 @@ export default {
// /auth/reset-password // /auth/reset-password
"resetPassword.title": "Mot de passe oublié ?", "resetPassword.title": "Mot de passe oublié ?",
"resetPassword.description": "Saisissez votre courriel pour réinitialiser votre mot de passe.", "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.", "resetPassword.notify.success": "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.button.back": "Retour à la page de connexion",
"resetPassword.text.resetPassword": "Réinitialiser le mot de passe", "resetPassword.text.resetPassword": "Réinitialiser le mot de passe",
"resetPassword.text.enterNewPassword": "Saisissez votre nouveau mot de passe", "resetPassword.text.enterNewPassword": "Saisissez votre nouveau mot de passe",
@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Administration", "admin.title": "Administration",
"admin.button.users": "Gestion des utilisateurs", "admin.button.users": "Gestion des utilisateurs",
"admin.button.shares": "Share management",
"admin.button.config": "Paramètres", "admin.button.config": "Paramètres",
"admin.version": "Version", "admin.version": "Version",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Privilèges dadmin", "admin.users.modal.create.admin": "Privilèges dadmin",
"admin.users.modal.create.admin.description": "Si coché, lutilisateur pourra accéder au panneau d'administration.", "admin.users.modal.create.admin.description": "Si coché, lutilisateur pourra accéder au panneau d'administration.",
// END /admin/users // 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
"upload.title": "Envoyer", "upload.title": "Envoyer",
"upload.notify.generic-error": "Une erreur est survenue durant le traitement de votre partage.", "upload.notify.generic-error": "Une erreur est survenue durant le traitement de votre partage.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Mois", "upload.modal.expires.month-plural": "Mois",
"upload.modal.expires.year-singular": "An", "upload.modal.expires.year-singular": "An",
"upload.modal.expires.year-plural": "Ans", "upload.modal.expires.year-plural": "Ans",
"upload.modal.accordion.description.title": "Description", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Note pour les destinataires de ce partage", "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": "Adresse courriel des destinataires", "upload.modal.accordion.email.title": "Adresse courriel des destinataires",
"upload.modal.accordion.email.placeholder": "Saisir les destinataires de ce partage", "upload.modal.accordion.email.placeholder": "Saisir les destinataires de ce partage",
"upload.modal.accordion.email.invalid-email": "Courriel invalide", "upload.modal.accordion.email.invalid-email": "Courriel invalide",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Taille maximale du partage en octets", "admin.config.share.max-size.description": "Taille maximale du partage en octets",
"admin.config.share.zip-compression-level": "Niveau de compression", "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.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": "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.", "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.",
"admin.config.smtp.host": "Hôte", "admin.config.smtp.host": "Hôte",

View File

@@ -0,0 +1,434 @@
export default {
// Navbar
"navbar.upload": "Upload",
"navbar.signin": "Sign in",
"navbar.home": "Home",
"navbar.signup": "Sign Up",
"navbar.links.shares": "My shares",
"navbar.links.reverse": "Reverse shares",
"navbar.avatar.account": "My account",
"navbar.avatar.admin": "Administration",
"navbar.avatar.signout": "Sign out",
// END navbar
// /
"home.title": "A <h>self-hosted</h> file sharing platform.",
"home.description": "Do you really want to give your personal files in the hand of third parties like WeTransfer?",
"home.bullet.a.name": "Self-Hosted",
"home.bullet.a.description": "Host Pingvin Share on your own machine.",
"home.bullet.b.name": "Privacy",
"home.bullet.b.description": "Your files are your files and should never get into the hands of third parties.",
"home.bullet.c.name": "No annoying file size limit",
"home.bullet.c.description": "Upload as big files as you want. Only your hard drive will be your limit.",
"home.button.start": "Get started",
"home.button.source": "Source code",
// END /
// /auth/signin
"signin.title": "Welcome back",
"signin.description": "You don't have an account yet?",
"signin.button.signup": "Sign up",
"signin.input.email-or-username": "Email or username",
"signin.input.email-or-username.placeholder": "Your email or username",
"signin.input.password": "Password",
"signin.input.password.placeholder": "Your password",
"signin.button.submit": "Sign in",
"signIn.notify.totp-required.title": "Two-factor authentication required",
"signIn.notify.totp-required.description": "Please enter your two-factor authentication code",
"signIn.oauth.or": "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": "Create an account",
"signup.description": "Already have an account?",
"signup.button.signin": "Sign in",
"signup.input.username": "Username",
"signup.input.username.placeholder": "Your username",
"signup.input.email": "Email",
"signup.input.email.placeholder": "Your email",
"signup.button.submit": "Let's get started",
// END /auth/signup
// /auth/totp
"totp.title": "TOTP Authentication",
"totp.button.signIn": "Sign in",
// END /auth/totp
// /auth/reset-password
"resetPassword.title": "Forgot your password?",
"resetPassword.description": "Enter your email to reset your password.",
"resetPassword.notify.success": "A message with a link to reset your password has been sent if the email exists.",
"resetPassword.button.back": "Back to sign in page",
"resetPassword.text.resetPassword": "Reset password",
"resetPassword.text.enterNewPassword": "Enter your new password",
"resetPassword.input.password": "New password",
"resetPassword.notify.passwordReset": "Your password has been reset successfully.",
// /account
"account.title": "My account",
"account.card.info.title": "Account info",
"account.card.info.username": "Username",
"account.card.info.email": "Email",
"account.notify.info.success": "Account updated successfully",
"account.card.password.title": "Password",
"account.card.password.old": "Old password",
"account.card.password.new": "New password",
"account.card.password.noPasswordSet": "You don't have a password set. If you want to sign in with email and password you need to set a password.",
"account.notify.password.success": "Password changed successfully",
"account.card.oauth.title": "Social login",
"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": "Link",
"account.card.oauth.unlink": "Unlink",
"account.card.oauth.unlinked": "Unlinked",
"account.modal.unlink.title": "Unlink account",
"account.modal.unlink.description": "Unlinking your social accounts may cause you to lose your account if you don't remember your username and password.",
"account.notify.oauth.unlinked.success": "Unlinked successfully",
"account.card.security.title": "Security",
"account.card.security.totp.enable.description": "Enter your current password to start enabling TOTP",
"account.card.security.totp.disable.description": "Enter your current password to disable TOTP",
"account.card.security.totp.button.start": "Start",
"account.modal.totp.title": "Enable TOTP",
"account.modal.totp.step1": "Step 1: Add your authenticator",
"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",
"account.modal.totp.verify": "Verify",
"account.notify.totp.disable": "TOTP disabled successfully",
"account.notify.totp.enable": "TOTP enabled successfully",
"account.card.language.title": "Language",
"account.card.language.description": "The project is translated by the community. Some languages might be incomplete.",
"account.card.color.title": "Color scheme",
// ThemeSwitcher.tsx
"account.theme.dark": "Dark",
"account.theme.light": "Light",
"account.theme.system": "System",
"account.button.delete": "Delete Account",
"account.modal.delete.title": "Delete Account",
"account.modal.delete.description": "Do you really want to delete your account including all your active shares?",
// END /account
// /account/shares
"account.shares.title": "My shares",
"account.shares.title.empty": "It's empty here 👀",
"account.shares.description.empty": "You don't have any shares.",
"account.shares.button.create": "Create one",
"account.shares.info.title": "Share informations",
"account.shares.table.id": "ID",
"account.shares.table.name": "Name",
"account.shares.table.description": "Description",
"account.shares.table.visitors": "Visitors",
"account.shares.table.expiresAt": "Expires at",
"account.shares.table.createdAt": "Created at",
"account.shares.table.size": "Size",
"account.shares.modal.share-informations": "Share informations",
"account.shares.modal.share-link": "Share link",
"account.shares.modal.delete.title": "Delete share {share}",
"account.shares.modal.delete.description": "Do you really want to delete this share?",
// END /account/shares
// /account/reverseShares
"account.reverseShares.title": "Reverse shares",
"account.reverseShares.description": "A reverse share allows you to generate a unique URL that allows external users to create a share.",
"account.reverseShares.title.empty": "It's empty here 👀",
"account.reverseShares.description.empty": "You don't have any reverse shares.",
// showCreateReverseShareModal.tsx
"account.reverseShares.modal.title": "Create reverse share",
"account.reverseShares.modal.expiration.label": "Expiration",
"account.reverseShares.modal.expiration.minute-singular": "Minute",
"account.reverseShares.modal.expiration.minute-plural": "Minutes",
"account.reverseShares.modal.expiration.hour-singular": "Hour",
"account.reverseShares.modal.expiration.hour-plural": "Hours",
"account.reverseShares.modal.expiration.day-singular": "Day",
"account.reverseShares.modal.expiration.day-plural": "Days",
"account.reverseShares.modal.expiration.week-singular": "Week",
"account.reverseShares.modal.expiration.week-plural": "Weeks",
"account.reverseShares.modal.expiration.month-singular": "Month",
"account.reverseShares.modal.expiration.month-plural": "Months",
"account.reverseShares.modal.expiration.year-singular": "Year",
"account.reverseShares.modal.expiration.year-plural": "Years",
"account.reverseShares.modal.max-size.label": "Max share size",
"account.reverseShares.modal.send-email": "Send email notification",
"account.reverseShares.modal.send-email.description": "Send an email notification when a share is created with this reverse share link.",
"account.reverseShares.modal.max-use.label": "Max uses",
"account.reverseShares.modal.max-use.description": "The maximum amount of times this URL can be used to create a share.",
"account.reverseShare.never-expires": "This reverse share will never expire.",
"account.reverseShare.expires-on": "This reverse share will expire on {expiration}.",
"account.reverseShares.table.no-shares": "No shares created yet",
"account.reverseShares.table.count.singular": "share",
"account.reverseShares.table.count.plural": "shares",
"account.reverseShares.table.shares": "Shares",
"account.reverseShares.table.remaining": "Remaining uses",
"account.reverseShares.table.max-size": "Max share size",
"account.reverseShares.table.expires": "Expires at",
"account.reverseShares.modal.reverse-share-link": "Reverse share link",
"account.reverseShares.modal.delete.title": "Delete reverse share",
"account.reverseShares.modal.delete.description": "Do you really want to delete this reverse share? If you do, the associated shares will be deleted as well.",
// END /account/reverseShares
// /admin
"admin.title": "Administration",
"admin.button.users": "User management",
"admin.button.shares": "Share management",
"admin.button.config": "Configuration",
"admin.version": "Version",
// END /admin
// /admin/users
"admin.users.title": "User management",
"admin.users.table.username": "Username",
"admin.users.table.email": "Email",
"admin.users.table.admin": "Admin",
"admin.users.edit.update.title": "Update user {username}",
"admin.users.edit.update.admin-privileges": "Admin privileges",
"admin.users.edit.update.change-password.title": "Change password",
"admin.users.edit.update.change-password.field": "New password",
"admin.users.edit.update.change-password.button": "Save new password",
"admin.users.edit.update.notify.password.success": "Password changed successfully",
"admin.users.edit.delete.title": "Delete user {username}",
"admin.users.edit.delete.description": "Do you really want to delete this user and all his shares?",
// showCreateUserModal.tsx
"admin.users.modal.create.title": "Create user",
"admin.users.modal.create.username": "Username",
"admin.users.modal.create.email": "Email",
"admin.users.modal.create.password": "Password",
"admin.users.modal.create.manual-password": "Set password manually",
"admin.users.modal.create.manual-password.description": "If not checked, the user will receive an email with a link to set their password.",
"admin.users.modal.create.admin": "Admin privileges",
"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": "An error occurred while finishing your share.",
"upload.notify.count-failed": "{count} files failed to upload. Trying again.",
// Dropzone.tsx
"upload.dropzone.title": "Upload files",
"upload.dropzone.description": "Drag'n'drop files here to start your share. We can accept only files that are less than {maxSize} in total.",
"upload.dropzone.notify.file-too-big": "Your files exceed the maximum share size of {maxSize}.",
// FileList.tsx
"upload.filelist.name": "Name",
"upload.filelist.size": "Size",
// showCreateUploadModal.tsx
"upload.modal.title": "Create Share",
"upload.modal.link.error.invalid": "Can only contain letters, numbers, underscores, and hyphens",
"upload.modal.link.error.taken": "This link is already in use",
"upload.modal.not-signed-in": "You're not signed in",
"upload.modal.not-signed-in-description": "You will be unable to delete your share manually and view the visitor count.",
"upload.modal.expires.never": "never",
"upload.modal.expires.never-long": "Never Expires",
"upload.modal.expires.error.too-long": "Expiration exceeds maximum expiration date of {max}.",
"upload.modal.link.label": "Link",
"upload.modal.expires.label": "Expiration",
"upload.modal.expires.minute-singular": "Minute",
"upload.modal.expires.minute-plural": "Minutes",
"upload.modal.expires.hour-singular": "Hour",
"upload.modal.expires.hour-plural": "Hours",
"upload.modal.expires.day-singular": "Day",
"upload.modal.expires.day-plural": "Days",
"upload.modal.expires.week-singular": "Week",
"upload.modal.expires.week-plural": "Weeks",
"upload.modal.expires.month-singular": "Month",
"upload.modal.expires.month-plural": "Months",
"upload.modal.expires.year-singular": "Year",
"upload.modal.expires.year-plural": "Years",
"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",
"upload.modal.accordion.email.placeholder": "Enter email recipients",
"upload.modal.accordion.email.invalid-email": "Invalid email address",
"upload.modal.accordion.security.title": "Security options",
"upload.modal.accordion.security.password.label": "Password protection",
"upload.modal.accordion.security.password.placeholder": "No password",
"upload.modal.accordion.security.max-views.label": "Maximum views",
"upload.modal.accordion.security.max-views.placeholder": "No limit",
// showCompletedUploadModal.tsx
"upload.modal.completed.never-expires": "This share will never expire.",
"upload.modal.completed.expires-on": "This share will expire on {expiration}.",
"upload.modal.completed.share-ready": "Share ready",
// END /upload
// /share/[id]
"share.title": "Share {shareId}",
"share.description": "Look what I've shared with you!",
"share.error.visitor-limit-exceeded.title": "Visitor limit exceeded",
"share.error.visitor-limit-exceeded.description": "The visitor limit from this share has been exceeded.",
"share.error.removed.title": "Share removed",
"share.error.not-found.title": "Share not found",
"share.error.not-found.description": "The share you're looking for doesn't exist.",
"share.modal.password.title": "Password required",
"share.modal.password.description": "To access this share please enter the password for the share.",
"share.modal.password": "Password",
"share.modal.error.invalid-password": "Invalid password",
"share.button.download-all": "Download all",
"share.notify.download-all-preparing": "The share is preparing. Try again in a few minutes.",
"share.modal.file-link": "File link",
"share.table.name": "Name",
"share.table.size": "Size",
"share.modal.file-preview.error.not-supported.title": "Preview not supported",
"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": "Edit {shareId}",
"share.edit.append-upload": "Append file",
"share.edit.notify.generic-error": "An error occurred while finishing your share.",
"share.edit.notify.save-success": "Share updated successfully",
// END /share/[id]/edit
// /admin/config
"admin.config.title": "Configuration",
"admin.config.category.general": "General",
"admin.config.category.share": "Share",
"admin.config.category.email": "Email",
"admin.config.category.smtp": "SMTP",
"admin.config.category.oauth": "Social Login",
"admin.config.general.app-name": "App name",
"admin.config.general.app-name.description": "Name of the application",
"admin.config.general.app-url": "App URL",
"admin.config.general.app-url.description": "On which URL Pingvin Share is available",
"admin.config.general.show-home-page": "Show home page",
"admin.config.general.show-home-page.description": "Whether to show the home page",
"admin.config.general.logo": "Logo",
"admin.config.general.logo.description": "Change your logo by uploading a new image. The image must be a PNG and should have the format 1:1.",
"admin.config.general.logo.placeholder": "Pick image",
"admin.config.email.enable-share-email-recipients": "Enable share email recipients",
"admin.config.email.enable-share-email-recipients.description": "Whether to allow emails to share recipients. Only enable this if you have enabled SMTP.",
"admin.config.email.share-recipients-subject": "Share recipients subject",
"admin.config.email.share-recipients-subject.description": "Subject of the email which gets sent to the share recipients.",
"admin.config.email.share-recipients-message": "Share recipients message",
"admin.config.email.share-recipients-message.description": "Message which gets sent to the share recipients. Available variables:\n {creator} - The username of the creator of the share\n {shareUrl} - The URL of the share\n {desc} - The description of the share\n {expires} - The expiration date of the share\n The variables will be replaced with the actual value.",
"admin.config.email.reverse-share-subject": "Reverse share subject",
"admin.config.email.reverse-share-subject.description": "Subject of the email which gets sent when someone created a share with your reverse share link.",
"admin.config.email.reverse-share-message": "Reverse share message",
"admin.config.email.reverse-share-message.description": "Message which gets sent when someone created a share with your reverse share link. {shareUrl} will be replaced with the creator's name and the share URL.",
"admin.config.email.reset-password-subject": "Reset password subject",
"admin.config.email.reset-password-subject.description": "Subject of the email which gets sent when a user requests a password reset.",
"admin.config.email.reset-password-message": "Reset password message",
"admin.config.email.reset-password-message.description": "Message which gets sent when a user requests a password reset. {url} will be replaced with the reset password URL.",
"admin.config.email.invite-subject": "Invite subject",
"admin.config.email.invite-subject.description": "Subject of the email which gets sent when an admin invites a user.",
"admin.config.email.invite-message": "Invite message",
"admin.config.email.invite-message.description": "Message which gets sent when an admin invites a user. {url} will be replaced with the invite URL and {password} with the password.",
"admin.config.share.allow-registration": "Allow registration",
"admin.config.share.allow-registration.description": "Whether registration is allowed",
"admin.config.share.allow-unauthenticated-shares": "Allow unauthenticated shares",
"admin.config.share.allow-unauthenticated-shares.description": "Whether unauthenticated users can create shares",
"admin.config.share.max-expiration": "Max expiration",
"admin.config.share.max-expiration.description": "Maximum share expiration in hours. Set to 0 to allow unlimited expiration.",
"admin.config.share.max-size": "Max size",
"admin.config.share.max-size.description": "Maximum share size in bytes",
"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": "Enabled",
"admin.config.smtp.enabled.description": "Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.",
"admin.config.smtp.host": "Host",
"admin.config.smtp.host.description": "Host of the SMTP server",
"admin.config.smtp.port": "Port",
"admin.config.smtp.port.description": "Port of the SMTP server",
"admin.config.smtp.email": "Email",
"admin.config.smtp.email.description": "Email address which the emails get sent from",
"admin.config.smtp.username": "Username",
"admin.config.smtp.username.description": "Username of the SMTP server",
"admin.config.smtp.password": "Password",
"admin.config.smtp.password.description": "Password of the SMTP server",
"admin.config.smtp.button.test": "Send test email",
"admin.config.oauth.allow-registration": "Allow registration",
"admin.config.oauth.allow-registration.description": "Allow users to register via social login",
"admin.config.oauth.ignore-totp": "Ignore TOTP",
"admin.config.oauth.ignore-totp.description": "Whether to ignore TOTP when user using social login",
"admin.config.oauth.github-enabled": "GitHub",
"admin.config.oauth.github-enabled.description": "Whether GitHub login is enabled",
"admin.config.oauth.github-client-id": "GitHub Client ID",
"admin.config.oauth.github-client-id.description": "Client ID of the GitHub OAuth app",
"admin.config.oauth.github-client-secret": "GitHub Client secret",
"admin.config.oauth.github-client-secret.description": "Client secret of the GitHub OAuth app",
"admin.config.oauth.google-enabled": "Google",
"admin.config.oauth.google-enabled.description": "Whether Google login is enabled",
"admin.config.oauth.google-client-id": "Google Client ID",
"admin.config.oauth.google-client-id.description": "Client ID of the Google OAuth app",
"admin.config.oauth.google-client-secret": "Google Client secret",
"admin.config.oauth.google-client-secret.description": "Client secret of the Google OAuth app",
"admin.config.oauth.microsoft-enabled": "Microsoft",
"admin.config.oauth.microsoft-enabled.description": "Whether Microsoft login is enabled",
"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.",
"admin.config.oauth.microsoft-client-id": "Microsoft Client ID",
"admin.config.oauth.microsoft-client-id.description": "Client ID of the Microsoft OAuth app",
"admin.config.oauth.microsoft-client-secret": "Microsoft Client secret",
"admin.config.oauth.microsoft-client-secret.description": "Client secret of the Microsoft OAuth app",
"admin.config.oauth.discord-enabled": "Discord",
"admin.config.oauth.discord-enabled.description": "Whether Discord login is enabled",
"admin.config.oauth.discord-limited-guild": "Discord limited server ID",
"admin.config.oauth.discord-limited-guild.description": "Limit signing in to users in a specific server. Leave it blank to disable.",
"admin.config.oauth.discord-client-id": "Discord Client ID",
"admin.config.oauth.discord-client-id.description": "Client ID of the Discord OAuth app",
"admin.config.oauth.discord-client-secret": "Discord Client secret",
"admin.config.oauth.discord-client-secret.description": "Client secret of the Discord OAuth app",
"admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description": "Whether OpenID Connect login is enabled",
"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": "Username claim in OpenID Connect ID token. Leave it blank if you don't know what this config is.",
"admin.config.oauth.oidc-client-id": "OpenID Connect Client ID",
"admin.config.oauth.oidc-client-id.description": "Client ID of the OpenID Connect OAuth app",
"admin.config.oauth.oidc-client-secret": "OpenID Connect Client secret",
"admin.config.oauth.oidc-client-secret.description": "Client secret of the OpenID Connect OAuth app",
// 404
"404.description": "Oops this page doesn't exist.",
"404.button.home": "Bring me back home",
// error
"error.title": "Error",
"error.description": "Oops!",
"error.button.back": "Go back",
"error.msg.default": "Something went wrong.",
"error.msg.access_denied": "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.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": "This {0} account is already linked to another account.",
"error.msg.not_linked": "This {0} account haven't linked to any account yet.",
"error.msg.unverified_account": "This {0} account is unverified, please try again after verification.",
"error.msg.discord_guild_permission_denied": "You are not allowed to sign in.",
"error.msg.cannot_get_user_info": "Can not get your user info from this {0} account.",
"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": "Save",
"common.button.create": "Create",
"common.button.submit": "Submit",
"common.button.delete": "Delete",
"common.button.cancel": "Cancel",
"common.button.confirm": "Confirm",
"common.button.disable": "Disable",
"common.button.share": "Share",
"common.button.generate": "Generate",
"common.button.done": "Done",
"common.text.link": "Link",
"common.text.navigate-to-link": "Go to the link",
"common.text.or": "or",
"common.button.go-back": "Go back",
"common.button.go-home": "Go home",
"common.notify.copied": "Your link was copied to the clipboard",
"common.success": "Success",
"common.error": "Error",
"common.error.unknown": "An unknown error occurred",
"common.error.invalid-email": "Invalid email address",
"common.error.too-short": "Must be at least {length} characters",
"common.error.too-long": "Must be at most {length} characters",
"common.error.exact-length": "Must be exactly {length} characters",
"common.error.invalid-number": "Must be a number",
"common.error.field-required": "This field is required"
};

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Amministrazione", "admin.title": "Amministrazione",
"admin.button.users": "Gestione degli utenti", "admin.button.users": "Gestione degli utenti",
"admin.button.shares": "Share management",
"admin.button.config": "Configurazione", "admin.button.config": "Configurazione",
"admin.version": "Versione", "admin.version": "Versione",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Privilegi di amministrazione", "admin.users.modal.create.admin": "Privilegi di amministrazione",
"admin.users.modal.create.admin.description": "Se selezionato, l'utente sarà in grado di accedere al pannello amministratore.", "admin.users.modal.create.admin.description": "Se selezionato, l'utente sarà in grado di accedere al pannello amministratore.",
// END /admin/users // 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
"upload.title": "Upload", "upload.title": "Upload",
"upload.notify.generic-error": "Si è verificato un errore durante il completamento della condivisione.", "upload.notify.generic-error": "Si è verificato un errore durante il completamento della condivisione.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Mesi", "upload.modal.expires.month-plural": "Mesi",
"upload.modal.expires.year-singular": "Anno", "upload.modal.expires.year-singular": "Anno",
"upload.modal.expires.year-plural": "Anni", "upload.modal.expires.year-plural": "Anni",
"upload.modal.accordion.description.title": "Descrizione", "upload.modal.accordion.name-and-description.title": "Nome e descrizione",
"upload.modal.accordion.description.placeholder": "Nota per i destinatari di questa condivisione", "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.title": "Destinatari di posta elettronica",
"upload.modal.accordion.email.placeholder": "Inserisci le email dei destinatari", "upload.modal.accordion.email.placeholder": "Inserisci le email dei destinatari",
"upload.modal.accordion.email.invalid-email": "Indirizzo email non valido", "upload.modal.accordion.email.invalid-email": "Indirizzo email non valido",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Dimensione massima di condivisione in byte", "admin.config.share.max-size.description": "Dimensione massima di condivisione in byte",
"admin.config.share.zip-compression-level": "Livello di compressione Zip", "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.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": "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.", "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.",
"admin.config.smtp.host": "Host", "admin.config.smtp.host": "Host",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "管理画面", "admin.title": "管理画面",
"admin.button.users": "ユーザー管理", "admin.button.users": "ユーザー管理",
"admin.button.shares": "Share management",
"admin.button.config": "設定", "admin.button.config": "設定",
"admin.version": "バージョン", "admin.version": "バージョン",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "管理者権限", "admin.users.modal.create.admin": "管理者権限",
"admin.users.modal.create.admin.description": "チェックされている場合、ユーザーは管理画面にアクセスできるようになります。", "admin.users.modal.create.admin.description": "チェックされている場合、ユーザーは管理画面にアクセスできるようになります。",
// END /admin/users // 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
"upload.title": "アップロード", "upload.title": "アップロード",
"upload.notify.generic-error": "共有を仕上げている最中にエラーが発生しました。", "upload.notify.generic-error": "共有を仕上げている最中にエラーが発生しました。",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "ヶ月間", "upload.modal.expires.month-plural": "ヶ月間",
"upload.modal.expires.year-singular": "年間", "upload.modal.expires.year-singular": "年間",
"upload.modal.expires.year-plural": "年間", "upload.modal.expires.year-plural": "年間",
"upload.modal.accordion.description.title": "説明", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "この共有に関する受信者へのメモ", "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.title": "メールで受け取る相手",
"upload.modal.accordion.email.placeholder": "メールの宛先を入力", "upload.modal.accordion.email.placeholder": "メールの宛先を入力",
"upload.modal.accordion.email.invalid-email": "無効なメールアドレスです", "upload.modal.accordion.email.invalid-email": "無効なメールアドレスです",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "最大ファイルサイズbyte単位", "admin.config.share.max-size.description": "最大ファイルサイズbyte単位",
"admin.config.share.zip-compression-level": "Zip圧縮レベル", "admin.config.share.zip-compression-level": "Zip圧縮レベル",
"admin.config.share.zip-compression-level.description": "ファイルサイズと圧縮速度のバランスを取るように、レベルを調整できます。有効な値は09の間で、0が無圧縮、9で最大限の圧縮となります。 ", "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": "有効",
"admin.config.smtp.enabled.description": "SMTPを有効にするかどうかを選択してください。SMTPサーバーのホスト名、ポート番号、電子メールアドレス、ユーザー名、パスワードが入力されている場合にのみ、有効にしてください。", "admin.config.smtp.enabled.description": "SMTPを有効にするかどうかを選択してください。SMTPサーバーのホスト名、ポート番号、電子メールアドレス、ユーザー名、パスワードが入力されている場合にのみ、有効にしてください。",
"admin.config.smtp.host": "ホスト名", "admin.config.smtp.host": "ホスト名",

View File

@@ -0,0 +1,434 @@
export default {
// Navbar
"navbar.upload": "Upload",
"navbar.signin": "Sign in",
"navbar.home": "Home",
"navbar.signup": "Sign Up",
"navbar.links.shares": "My shares",
"navbar.links.reverse": "Reverse shares",
"navbar.avatar.account": "My account",
"navbar.avatar.admin": "Administration",
"navbar.avatar.signout": "Sign out",
// END navbar
// /
"home.title": "A <h>self-hosted</h> file sharing platform.",
"home.description": "Do you really want to give your personal files in the hand of third parties like WeTransfer?",
"home.bullet.a.name": "Self-Hosted",
"home.bullet.a.description": "Host Pingvin Share on your own machine.",
"home.bullet.b.name": "Privacy",
"home.bullet.b.description": "Your files are your files and should never get into the hands of third parties.",
"home.bullet.c.name": "No annoying file size limit",
"home.bullet.c.description": "Upload as big files as you want. Only your hard drive will be your limit.",
"home.button.start": "Get started",
"home.button.source": "Source code",
// END /
// /auth/signin
"signin.title": "Welcome back",
"signin.description": "You don't have an account yet?",
"signin.button.signup": "Sign up",
"signin.input.email-or-username": "Email or username",
"signin.input.email-or-username.placeholder": "Your email or username",
"signin.input.password": "Password",
"signin.input.password.placeholder": "Your password",
"signin.button.submit": "Sign in",
"signIn.notify.totp-required.title": "Two-factor authentication required",
"signIn.notify.totp-required.description": "Please enter your two-factor authentication code",
"signIn.oauth.or": "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": "Create an account",
"signup.description": "Already have an account?",
"signup.button.signin": "Sign in",
"signup.input.username": "Username",
"signup.input.username.placeholder": "Your username",
"signup.input.email": "Email",
"signup.input.email.placeholder": "Your email",
"signup.button.submit": "Let's get started",
// END /auth/signup
// /auth/totp
"totp.title": "TOTP Authentication",
"totp.button.signIn": "Sign in",
// END /auth/totp
// /auth/reset-password
"resetPassword.title": "Forgot your password?",
"resetPassword.description": "Enter your email to reset your password.",
"resetPassword.notify.success": "A message with a link to reset your password has been sent if the email exists.",
"resetPassword.button.back": "Back to sign in page",
"resetPassword.text.resetPassword": "Reset password",
"resetPassword.text.enterNewPassword": "Enter your new password",
"resetPassword.input.password": "New password",
"resetPassword.notify.passwordReset": "Your password has been reset successfully.",
// /account
"account.title": "My account",
"account.card.info.title": "Account info",
"account.card.info.username": "Username",
"account.card.info.email": "Email",
"account.notify.info.success": "Account updated successfully",
"account.card.password.title": "Password",
"account.card.password.old": "Old password",
"account.card.password.new": "New password",
"account.card.password.noPasswordSet": "You don't have a password set. If you want to sign in with email and password you need to set a password.",
"account.notify.password.success": "Password changed successfully",
"account.card.oauth.title": "Social login",
"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": "Link",
"account.card.oauth.unlink": "Unlink",
"account.card.oauth.unlinked": "Unlinked",
"account.modal.unlink.title": "Unlink account",
"account.modal.unlink.description": "Unlinking your social accounts may cause you to lose your account if you don't remember your username and password.",
"account.notify.oauth.unlinked.success": "Unlinked successfully",
"account.card.security.title": "Security",
"account.card.security.totp.enable.description": "Enter your current password to start enabling TOTP",
"account.card.security.totp.disable.description": "Enter your current password to disable TOTP",
"account.card.security.totp.button.start": "Start",
"account.modal.totp.title": "Enable TOTP",
"account.modal.totp.step1": "Step 1: Add your authenticator",
"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",
"account.modal.totp.verify": "Verify",
"account.notify.totp.disable": "TOTP disabled successfully",
"account.notify.totp.enable": "TOTP enabled successfully",
"account.card.language.title": "Language",
"account.card.language.description": "The project is translated by the community. Some languages might be incomplete.",
"account.card.color.title": "Color scheme",
// ThemeSwitcher.tsx
"account.theme.dark": "Dark",
"account.theme.light": "Light",
"account.theme.system": "System",
"account.button.delete": "Delete Account",
"account.modal.delete.title": "Delete Account",
"account.modal.delete.description": "Do you really want to delete your account including all your active shares?",
// END /account
// /account/shares
"account.shares.title": "My shares",
"account.shares.title.empty": "It's empty here 👀",
"account.shares.description.empty": "You don't have any shares.",
"account.shares.button.create": "Create one",
"account.shares.info.title": "Share informations",
"account.shares.table.id": "ID",
"account.shares.table.name": "Name",
"account.shares.table.description": "Description",
"account.shares.table.visitors": "Visitors",
"account.shares.table.expiresAt": "Expires at",
"account.shares.table.createdAt": "Created at",
"account.shares.table.size": "Size",
"account.shares.modal.share-informations": "Share informations",
"account.shares.modal.share-link": "Share link",
"account.shares.modal.delete.title": "Delete share {share}",
"account.shares.modal.delete.description": "Do you really want to delete this share?",
// END /account/shares
// /account/reverseShares
"account.reverseShares.title": "Reverse shares",
"account.reverseShares.description": "A reverse share allows you to generate a unique URL that allows external users to create a share.",
"account.reverseShares.title.empty": "It's empty here 👀",
"account.reverseShares.description.empty": "You don't have any reverse shares.",
// showCreateReverseShareModal.tsx
"account.reverseShares.modal.title": "Create reverse share",
"account.reverseShares.modal.expiration.label": "Expiration",
"account.reverseShares.modal.expiration.minute-singular": "Minute",
"account.reverseShares.modal.expiration.minute-plural": "Minutes",
"account.reverseShares.modal.expiration.hour-singular": "Hour",
"account.reverseShares.modal.expiration.hour-plural": "Hours",
"account.reverseShares.modal.expiration.day-singular": "Day",
"account.reverseShares.modal.expiration.day-plural": "Days",
"account.reverseShares.modal.expiration.week-singular": "Week",
"account.reverseShares.modal.expiration.week-plural": "Weeks",
"account.reverseShares.modal.expiration.month-singular": "Month",
"account.reverseShares.modal.expiration.month-plural": "Months",
"account.reverseShares.modal.expiration.year-singular": "Year",
"account.reverseShares.modal.expiration.year-plural": "Years",
"account.reverseShares.modal.max-size.label": "Max share size",
"account.reverseShares.modal.send-email": "Send email notification",
"account.reverseShares.modal.send-email.description": "Send an email notification when a share is created with this reverse share link.",
"account.reverseShares.modal.max-use.label": "Max uses",
"account.reverseShares.modal.max-use.description": "The maximum amount of times this URL can be used to create a share.",
"account.reverseShare.never-expires": "This reverse share will never expire.",
"account.reverseShare.expires-on": "This reverse share will expire on {expiration}.",
"account.reverseShares.table.no-shares": "No shares created yet",
"account.reverseShares.table.count.singular": "share",
"account.reverseShares.table.count.plural": "shares",
"account.reverseShares.table.shares": "Shares",
"account.reverseShares.table.remaining": "Remaining uses",
"account.reverseShares.table.max-size": "Max share size",
"account.reverseShares.table.expires": "Expires at",
"account.reverseShares.modal.reverse-share-link": "Reverse share link",
"account.reverseShares.modal.delete.title": "Delete reverse share",
"account.reverseShares.modal.delete.description": "Do you really want to delete this reverse share? If you do, the associated shares will be deleted as well.",
// END /account/reverseShares
// /admin
"admin.title": "Administration",
"admin.button.users": "User management",
"admin.button.shares": "Share management",
"admin.button.config": "Configuration",
"admin.version": "Version",
// END /admin
// /admin/users
"admin.users.title": "User management",
"admin.users.table.username": "Username",
"admin.users.table.email": "Email",
"admin.users.table.admin": "Admin",
"admin.users.edit.update.title": "Update user {username}",
"admin.users.edit.update.admin-privileges": "Admin privileges",
"admin.users.edit.update.change-password.title": "Change password",
"admin.users.edit.update.change-password.field": "New password",
"admin.users.edit.update.change-password.button": "Save new password",
"admin.users.edit.update.notify.password.success": "Password changed successfully",
"admin.users.edit.delete.title": "Delete user {username}",
"admin.users.edit.delete.description": "Do you really want to delete this user and all his shares?",
// showCreateUserModal.tsx
"admin.users.modal.create.title": "Create user",
"admin.users.modal.create.username": "Username",
"admin.users.modal.create.email": "Email",
"admin.users.modal.create.password": "Password",
"admin.users.modal.create.manual-password": "Set password manually",
"admin.users.modal.create.manual-password.description": "If not checked, the user will receive an email with a link to set their password.",
"admin.users.modal.create.admin": "Admin privileges",
"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": "An error occurred while finishing your share.",
"upload.notify.count-failed": "{count} files failed to upload. Trying again.",
// Dropzone.tsx
"upload.dropzone.title": "Upload files",
"upload.dropzone.description": "Drag'n'drop files here to start your share. We can accept only files that are less than {maxSize} in total.",
"upload.dropzone.notify.file-too-big": "Your files exceed the maximum share size of {maxSize}.",
// FileList.tsx
"upload.filelist.name": "Name",
"upload.filelist.size": "Size",
// showCreateUploadModal.tsx
"upload.modal.title": "Create Share",
"upload.modal.link.error.invalid": "Can only contain letters, numbers, underscores, and hyphens",
"upload.modal.link.error.taken": "This link is already in use",
"upload.modal.not-signed-in": "You're not signed in",
"upload.modal.not-signed-in-description": "You will be unable to delete your share manually and view the visitor count.",
"upload.modal.expires.never": "never",
"upload.modal.expires.never-long": "Never Expires",
"upload.modal.expires.error.too-long": "Expiration exceeds maximum expiration date of {max}.",
"upload.modal.link.label": "Link",
"upload.modal.expires.label": "Expiration",
"upload.modal.expires.minute-singular": "Minute",
"upload.modal.expires.minute-plural": "Minutes",
"upload.modal.expires.hour-singular": "Hour",
"upload.modal.expires.hour-plural": "Hours",
"upload.modal.expires.day-singular": "Day",
"upload.modal.expires.day-plural": "Days",
"upload.modal.expires.week-singular": "Week",
"upload.modal.expires.week-plural": "Weeks",
"upload.modal.expires.month-singular": "Month",
"upload.modal.expires.month-plural": "Months",
"upload.modal.expires.year-singular": "Year",
"upload.modal.expires.year-plural": "Years",
"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",
"upload.modal.accordion.email.placeholder": "Enter email recipients",
"upload.modal.accordion.email.invalid-email": "Invalid email address",
"upload.modal.accordion.security.title": "Security options",
"upload.modal.accordion.security.password.label": "Password protection",
"upload.modal.accordion.security.password.placeholder": "No password",
"upload.modal.accordion.security.max-views.label": "Maximum views",
"upload.modal.accordion.security.max-views.placeholder": "No limit",
// showCompletedUploadModal.tsx
"upload.modal.completed.never-expires": "This share will never expire.",
"upload.modal.completed.expires-on": "This share will expire on {expiration}.",
"upload.modal.completed.share-ready": "Share ready",
// END /upload
// /share/[id]
"share.title": "Share {shareId}",
"share.description": "Look what I've shared with you!",
"share.error.visitor-limit-exceeded.title": "Visitor limit exceeded",
"share.error.visitor-limit-exceeded.description": "The visitor limit from this share has been exceeded.",
"share.error.removed.title": "Share removed",
"share.error.not-found.title": "Share not found",
"share.error.not-found.description": "The share you're looking for doesn't exist.",
"share.modal.password.title": "Password required",
"share.modal.password.description": "To access this share please enter the password for the share.",
"share.modal.password": "Password",
"share.modal.error.invalid-password": "Invalid password",
"share.button.download-all": "Download all",
"share.notify.download-all-preparing": "The share is preparing. Try again in a few minutes.",
"share.modal.file-link": "File link",
"share.table.name": "Name",
"share.table.size": "Size",
"share.modal.file-preview.error.not-supported.title": "Preview not supported",
"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": "Edit {shareId}",
"share.edit.append-upload": "Append file",
"share.edit.notify.generic-error": "An error occurred while finishing your share.",
"share.edit.notify.save-success": "Share updated successfully",
// END /share/[id]/edit
// /admin/config
"admin.config.title": "Configuration",
"admin.config.category.general": "General",
"admin.config.category.share": "Share",
"admin.config.category.email": "Email",
"admin.config.category.smtp": "SMTP",
"admin.config.category.oauth": "Social Login",
"admin.config.general.app-name": "App name",
"admin.config.general.app-name.description": "Name of the application",
"admin.config.general.app-url": "App URL",
"admin.config.general.app-url.description": "On which URL Pingvin Share is available",
"admin.config.general.show-home-page": "Show home page",
"admin.config.general.show-home-page.description": "Whether to show the home page",
"admin.config.general.logo": "Logo",
"admin.config.general.logo.description": "Change your logo by uploading a new image. The image must be a PNG and should have the format 1:1.",
"admin.config.general.logo.placeholder": "Pick image",
"admin.config.email.enable-share-email-recipients": "Enable share email recipients",
"admin.config.email.enable-share-email-recipients.description": "Whether to allow emails to share recipients. Only enable this if you have enabled SMTP.",
"admin.config.email.share-recipients-subject": "Share recipients subject",
"admin.config.email.share-recipients-subject.description": "Subject of the email which gets sent to the share recipients.",
"admin.config.email.share-recipients-message": "Share recipients message",
"admin.config.email.share-recipients-message.description": "Message which gets sent to the share recipients. Available variables:\n {creator} - The username of the creator of the share\n {shareUrl} - The URL of the share\n {desc} - The description of the share\n {expires} - The expiration date of the share\n The variables will be replaced with the actual value.",
"admin.config.email.reverse-share-subject": "Reverse share subject",
"admin.config.email.reverse-share-subject.description": "Subject of the email which gets sent when someone created a share with your reverse share link.",
"admin.config.email.reverse-share-message": "Reverse share message",
"admin.config.email.reverse-share-message.description": "Message which gets sent when someone created a share with your reverse share link. {shareUrl} will be replaced with the creator's name and the share URL.",
"admin.config.email.reset-password-subject": "Reset password subject",
"admin.config.email.reset-password-subject.description": "Subject of the email which gets sent when a user requests a password reset.",
"admin.config.email.reset-password-message": "Reset password message",
"admin.config.email.reset-password-message.description": "Message which gets sent when a user requests a password reset. {url} will be replaced with the reset password URL.",
"admin.config.email.invite-subject": "Invite subject",
"admin.config.email.invite-subject.description": "Subject of the email which gets sent when an admin invites a user.",
"admin.config.email.invite-message": "Invite message",
"admin.config.email.invite-message.description": "Message which gets sent when an admin invites a user. {url} will be replaced with the invite URL and {password} with the password.",
"admin.config.share.allow-registration": "Allow registration",
"admin.config.share.allow-registration.description": "Whether registration is allowed",
"admin.config.share.allow-unauthenticated-shares": "Allow unauthenticated shares",
"admin.config.share.allow-unauthenticated-shares.description": "Whether unauthenticated users can create shares",
"admin.config.share.max-expiration": "Max expiration",
"admin.config.share.max-expiration.description": "Maximum share expiration in hours. Set to 0 to allow unlimited expiration.",
"admin.config.share.max-size": "Max size",
"admin.config.share.max-size.description": "Maximum share size in bytes",
"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": "Enabled",
"admin.config.smtp.enabled.description": "Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.",
"admin.config.smtp.host": "Host",
"admin.config.smtp.host.description": "Host of the SMTP server",
"admin.config.smtp.port": "Port",
"admin.config.smtp.port.description": "Port of the SMTP server",
"admin.config.smtp.email": "Email",
"admin.config.smtp.email.description": "Email address which the emails get sent from",
"admin.config.smtp.username": "Username",
"admin.config.smtp.username.description": "Username of the SMTP server",
"admin.config.smtp.password": "Password",
"admin.config.smtp.password.description": "Password of the SMTP server",
"admin.config.smtp.button.test": "Send test email",
"admin.config.oauth.allow-registration": "Allow registration",
"admin.config.oauth.allow-registration.description": "Allow users to register via social login",
"admin.config.oauth.ignore-totp": "Ignore TOTP",
"admin.config.oauth.ignore-totp.description": "Whether to ignore TOTP when user using social login",
"admin.config.oauth.github-enabled": "GitHub",
"admin.config.oauth.github-enabled.description": "Whether GitHub login is enabled",
"admin.config.oauth.github-client-id": "GitHub Client ID",
"admin.config.oauth.github-client-id.description": "Client ID of the GitHub OAuth app",
"admin.config.oauth.github-client-secret": "GitHub Client secret",
"admin.config.oauth.github-client-secret.description": "Client secret of the GitHub OAuth app",
"admin.config.oauth.google-enabled": "Google",
"admin.config.oauth.google-enabled.description": "Whether Google login is enabled",
"admin.config.oauth.google-client-id": "Google Client ID",
"admin.config.oauth.google-client-id.description": "Client ID of the Google OAuth app",
"admin.config.oauth.google-client-secret": "Google Client secret",
"admin.config.oauth.google-client-secret.description": "Client secret of the Google OAuth app",
"admin.config.oauth.microsoft-enabled": "Microsoft",
"admin.config.oauth.microsoft-enabled.description": "Whether Microsoft login is enabled",
"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.",
"admin.config.oauth.microsoft-client-id": "Microsoft Client ID",
"admin.config.oauth.microsoft-client-id.description": "Client ID of the Microsoft OAuth app",
"admin.config.oauth.microsoft-client-secret": "Microsoft Client secret",
"admin.config.oauth.microsoft-client-secret.description": "Client secret of the Microsoft OAuth app",
"admin.config.oauth.discord-enabled": "Discord",
"admin.config.oauth.discord-enabled.description": "Whether Discord login is enabled",
"admin.config.oauth.discord-limited-guild": "Discord limited server ID",
"admin.config.oauth.discord-limited-guild.description": "Limit signing in to users in a specific server. Leave it blank to disable.",
"admin.config.oauth.discord-client-id": "Discord Client ID",
"admin.config.oauth.discord-client-id.description": "Client ID of the Discord OAuth app",
"admin.config.oauth.discord-client-secret": "Discord Client secret",
"admin.config.oauth.discord-client-secret.description": "Client secret of the Discord OAuth app",
"admin.config.oauth.oidc-enabled": "OpenID Connect",
"admin.config.oauth.oidc-enabled.description": "Whether OpenID Connect login is enabled",
"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": "Username claim in OpenID Connect ID token. Leave it blank if you don't know what this config is.",
"admin.config.oauth.oidc-client-id": "OpenID Connect Client ID",
"admin.config.oauth.oidc-client-id.description": "Client ID of the OpenID Connect OAuth app",
"admin.config.oauth.oidc-client-secret": "OpenID Connect Client secret",
"admin.config.oauth.oidc-client-secret.description": "Client secret of the OpenID Connect OAuth app",
// 404
"404.description": "Oops this page doesn't exist.",
"404.button.home": "Bring me back home",
// error
"error.title": "Error",
"error.description": "Oops!",
"error.button.back": "Go back",
"error.msg.default": "Something went wrong.",
"error.msg.access_denied": "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.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": "This {0} account is already linked to another account.",
"error.msg.not_linked": "This {0} account haven't linked to any account yet.",
"error.msg.unverified_account": "This {0} account is unverified, please try again after verification.",
"error.msg.discord_guild_permission_denied": "You are not allowed to sign in.",
"error.msg.cannot_get_user_info": "Can not get your user info from this {0} account.",
"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": "Save",
"common.button.create": "Create",
"common.button.submit": "Submit",
"common.button.delete": "Delete",
"common.button.cancel": "Cancel",
"common.button.confirm": "Confirm",
"common.button.disable": "Disable",
"common.button.share": "Share",
"common.button.generate": "Generate",
"common.button.done": "Done",
"common.text.link": "Link",
"common.text.navigate-to-link": "Go to the link",
"common.text.or": "or",
"common.button.go-back": "Go back",
"common.button.go-home": "Go home",
"common.notify.copied": "Your link was copied to the clipboard",
"common.success": "Success",
"common.error": "Error",
"common.error.unknown": "An unknown error occurred",
"common.error.invalid-email": "Invalid email address",
"common.error.too-short": "Must be at least {length} characters",
"common.error.too-long": "Must be at most {length} characters",
"common.error.exact-length": "Must be exactly {length} characters",
"common.error.invalid-number": "Must be a number",
"common.error.field-required": "This field is required"
};

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Instellingen", "admin.title": "Instellingen",
"admin.button.users": "Gebruikers beheer", "admin.button.users": "Gebruikers beheer",
"admin.button.shares": "Share management",
"admin.button.config": "Configuratie", "admin.button.config": "Configuratie",
"admin.version": "Versie", "admin.version": "Versie",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Beheerdersrechten", "admin.users.modal.create.admin": "Beheerdersrechten",
"admin.users.modal.create.admin.description": "Indien aangevinkt, heeft de gebruiker toegang tot de beheeromgeving.", "admin.users.modal.create.admin.description": "Indien aangevinkt, heeft de gebruiker toegang tot de beheeromgeving.",
// END /admin/users // 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
"upload.title": "Uploaden", "upload.title": "Uploaden",
"upload.notify.generic-error": "Er is een fout opgetreden tijdens het voltooien van uw share.", "upload.notify.generic-error": "Er is een fout opgetreden tijdens het voltooien van uw share.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Maanden", "upload.modal.expires.month-plural": "Maanden",
"upload.modal.expires.year-singular": "Jaar", "upload.modal.expires.year-singular": "Jaar",
"upload.modal.expires.year-plural": "Jaren", "upload.modal.expires.year-plural": "Jaren",
"upload.modal.accordion.description.title": "Beschrijving", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Opmerking voor de ontvangers van deze share", "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.title": "E-mail van de ontvangers",
"upload.modal.accordion.email.placeholder": "Voer e-mail ontvangers in", "upload.modal.accordion.email.placeholder": "Voer e-mail ontvangers in",
"upload.modal.accordion.email.invalid-email": "Ongeldig e-mailadres", "upload.modal.accordion.email.invalid-email": "Ongeldig e-mailadres",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Maximale share grootte in bytes", "admin.config.share.max-size.description": "Maximale share grootte in bytes",
"admin.config.share.zip-compression-level": "Zip compressie niveau", "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.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": "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.", "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.",
"admin.config.smtp.host": "Host", "admin.config.smtp.host": "Host",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Administracja", "admin.title": "Administracja",
"admin.button.users": "Zarządzanie użytkownikami", "admin.button.users": "Zarządzanie użytkownikami",
"admin.button.shares": "Share management",
"admin.button.config": "Konfiguracja", "admin.button.config": "Konfiguracja",
"admin.version": "Wersja", "admin.version": "Wersja",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Uprawnienia administratora", "admin.users.modal.create.admin": "Uprawnienia administratora",
"admin.users.modal.create.admin.description": "Jeśli zaznaczone, użytkownik będzie miał dostęp do panelu administratora.", "admin.users.modal.create.admin.description": "Jeśli zaznaczone, użytkownik będzie miał dostęp do panelu administratora.",
// END /admin/users // 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
"upload.title": "Prześlij", "upload.title": "Prześlij",
"upload.notify.generic-error": "Wystąpił błąd podczas zakończenia tworzenia udziału.", "upload.notify.generic-error": "Wystąpił błąd podczas zakończenia tworzenia udziału.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Miesiące/ęcy", "upload.modal.expires.month-plural": "Miesiące/ęcy",
"upload.modal.expires.year-singular": "Rok", "upload.modal.expires.year-singular": "Rok",
"upload.modal.expires.year-plural": "Lat/a", "upload.modal.expires.year-plural": "Lat/a",
"upload.modal.accordion.description.title": "Opis", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Notatka dla odbiorców tego udziału", "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.title": "Odbiorcy wiadomości e-mail",
"upload.modal.accordion.email.placeholder": "Wprowadź adresatów wiadomości e-mail", "upload.modal.accordion.email.placeholder": "Wprowadź adresatów wiadomości e-mail",
"upload.modal.accordion.email.invalid-email": "Adres e-mail jest nieprawidłowy", "upload.modal.accordion.email.invalid-email": "Adres e-mail jest nieprawidłowy",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Maksymalny rozmiar udziału w bajtach", "admin.config.share.max-size.description": "Maksymalny rozmiar udziału w bajtach",
"admin.config.share.zip-compression-level": "Poziom kompresji Zip", "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.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": "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.", "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.",
"admin.config.smtp.host": "Host", "admin.config.smtp.host": "Host",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Administração", "admin.title": "Administração",
"admin.button.users": "Gerenciamento de usuários", "admin.button.users": "Gerenciamento de usuários",
"admin.button.shares": "Share management",
"admin.button.config": "Configuração", "admin.button.config": "Configuração",
"admin.version": "Versão", "admin.version": "Versão",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Privilégios de administrador", "admin.users.modal.create.admin": "Privilégios de administrador",
"admin.users.modal.create.admin.description": "Se marcado, o usuário poderá acessar o painel de administração.", "admin.users.modal.create.admin.description": "Se marcado, o usuário poderá acessar o painel de administração.",
// END /admin/users // 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
"upload.title": "Carregar", "upload.title": "Carregar",
"upload.notify.generic-error": "Ocorreu um erro ao terminar seu compartilhamento.", "upload.notify.generic-error": "Ocorreu um erro ao terminar seu compartilhamento.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Meses", "upload.modal.expires.month-plural": "Meses",
"upload.modal.expires.year-singular": "Ano", "upload.modal.expires.year-singular": "Ano",
"upload.modal.expires.year-plural": "Anos", "upload.modal.expires.year-plural": "Anos",
"upload.modal.accordion.description.title": "Descrição", "upload.modal.accordion.name-and-description.title": "Nome e descrição",
"upload.modal.accordion.description.placeholder": "Nota para os destinatários deste compartilhamento", "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.title": "Destinatários de e-mail",
"upload.modal.accordion.email.placeholder": "Insira os destinatários do e-mail", "upload.modal.accordion.email.placeholder": "Insira os destinatários do e-mail",
"upload.modal.accordion.email.invalid-email": "Endereço de e-mail inválido", "upload.modal.accordion.email.invalid-email": "Endereço de e-mail inválido",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Tamanho máximo do compartilhamento em bytes", "admin.config.share.max-size.description": "Tamanho máximo do compartilhamento em bytes",
"admin.config.share.zip-compression-level": "Nível de compressão", "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.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": "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.", "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.",
"admin.config.smtp.host": "Servidor", "admin.config.smtp.host": "Servidor",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Администрирование", "admin.title": "Администрирование",
"admin.button.users": "Управление пользователями", "admin.button.users": "Управление пользователями",
"admin.button.shares": "Share management",
"admin.button.config": "Конфигурация", "admin.button.config": "Конфигурация",
"admin.version": "Версия", "admin.version": "Версия",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Права администратора", "admin.users.modal.create.admin": "Права администратора",
"admin.users.modal.create.admin.description": "Если отмечено, пользователь будет иметь доступ к панели администратора.", "admin.users.modal.create.admin.description": "Если отмечено, пользователь будет иметь доступ к панели администратора.",
// END /admin/users // 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
"upload.title": "Загрузить", "upload.title": "Загрузить",
"upload.notify.generic-error": "Произошла ошибка при завершении вашей загрузки.", "upload.notify.generic-error": "Произошла ошибка при завершении вашей загрузки.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Месяца(-ев)", "upload.modal.expires.month-plural": "Месяца(-ев)",
"upload.modal.expires.year-singular": "Год", "upload.modal.expires.year-singular": "Год",
"upload.modal.expires.year-plural": "Года (лет)", "upload.modal.expires.year-plural": "Года (лет)",
"upload.modal.accordion.description.title": "Описание", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Примечание для получателей этой загрузки", "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.title": "Получатели письма",
"upload.modal.accordion.email.placeholder": "Получатели e-mail", "upload.modal.accordion.email.placeholder": "Получатели e-mail",
"upload.modal.accordion.email.invalid-email": "Недопустимый адрес электронной почты", "upload.modal.accordion.email.invalid-email": "Недопустимый адрес электронной почты",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Максимальный размер файла в байтах", "admin.config.share.max-size.description": "Максимальный размер файла в байтах",
"admin.config.share.zip-compression-level": "Уровень сжатия Zip", "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": "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": "Включено",
"admin.config.smtp.enabled.description": "Включено ли SMTP. Установите значение true только если вы ввели хост, порт, email, пользователь и пароль вашего SMTP-сервера.", "admin.config.smtp.enabled.description": "Включено ли SMTP. Установите значение true только если вы ввели хост, порт, email, пользователь и пароль вашего SMTP-сервера.",
"admin.config.smtp.host": "Хост", "admin.config.smtp.host": "Хост",

View File

@@ -57,7 +57,7 @@ export default {
// /auth/reset-password // /auth/reset-password
"resetPassword.title": "Ste pozabili svoje geslo?", "resetPassword.title": "Ste pozabili svoje geslo?",
"resetPassword.description": "Vnesite svoj e-poštni naslov za ponastavitev gesla.", "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.", "resetPassword.notify.success": "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.button.back": "Nazaj na stran za prijavo",
"resetPassword.text.resetPassword": "Ponastavi geslo", "resetPassword.text.resetPassword": "Ponastavi geslo",
"resetPassword.text.enterNewPassword": "Vnesite novo geslo", "resetPassword.text.enterNewPassword": "Vnesite novo geslo",
@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Administracija", "admin.title": "Administracija",
"admin.button.users": "Upravljanje uporabnikov", "admin.button.users": "Upravljanje uporabnikov",
"admin.button.shares": "Share management",
"admin.button.config": "Nastavitve", "admin.button.config": "Nastavitve",
"admin.version": "Različica", "admin.version": "Različica",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Administratorski privilegiji", "admin.users.modal.create.admin": "Administratorski privilegiji",
"admin.users.modal.create.admin.description": "Če je omogočeno, bo lahko porabnik dostopal do administratorskega vmesnika.", "admin.users.modal.create.admin.description": "Če je omogočeno, bo lahko porabnik dostopal do administratorskega vmesnika.",
// END /admin/users // 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
"upload.title": "Naložite", "upload.title": "Naložite",
"upload.notify.generic-error": "Prišlo je do napake pri ustvarjanju vašega deljenja.", "upload.notify.generic-error": "Prišlo je do napake pri ustvarjanju vašega deljenja.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Meseci", "upload.modal.expires.month-plural": "Meseci",
"upload.modal.expires.year-singular": "Leto", "upload.modal.expires.year-singular": "Leto",
"upload.modal.expires.year-plural": "Leta", "upload.modal.expires.year-plural": "Leta",
"upload.modal.accordion.description.title": "Opis", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Sporočilo za prejemnika te delitve", "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.title": "Prejemnik e-pošte",
"upload.modal.accordion.email.placeholder": "Vnesite prejemnika e-pošte", "upload.modal.accordion.email.placeholder": "Vnesite prejemnika e-pošte",
"upload.modal.accordion.email.invalid-email": "Neveljaven e-poštni naslov", "upload.modal.accordion.email.invalid-email": "Neveljaven e-poštni naslov",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Največja velikost delitve v bytih", "admin.config.share.max-size.description": "Največja velikost delitve v bytih",
"admin.config.share.zip-compression-level": "Nivo Zip stiskanja", "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.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": "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.", "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.",
"admin.config.smtp.host": "Gostitelj", "admin.config.smtp.host": "Gostitelj",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Администрација", "admin.title": "Администрација",
"admin.button.users": "Управљање корисницима", "admin.button.users": "Управљање корисницима",
"admin.button.shares": "Share management",
"admin.button.config": "Конфигурација", "admin.button.config": "Конфигурација",
"admin.version": "Верзија", "admin.version": "Верзија",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Администраторске привилегије", "admin.users.modal.create.admin": "Администраторске привилегије",
"admin.users.modal.create.admin.description": "Ако је означено, корисник ће моћи да приступи административном панелу.", "admin.users.modal.create.admin.description": "Ако је означено, корисник ће моћи да приступи административном панелу.",
// END /admin/users // 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
"upload.title": "Пошаљи", "upload.title": "Пошаљи",
"upload.notify.generic-error": "Дошло је до грешке при довршавању дељења.", "upload.notify.generic-error": "Дошло је до грешке при довршавању дељења.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Месеци", "upload.modal.expires.month-plural": "Месеци",
"upload.modal.expires.year-singular": "Година", "upload.modal.expires.year-singular": "Година",
"upload.modal.expires.year-plural": "Године", "upload.modal.expires.year-plural": "Године",
"upload.modal.accordion.description.title": "Опис", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Напомена за примаоце овог дељења", "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.title": "Примаоци е-поште",
"upload.modal.accordion.email.placeholder": "Унесите примаоце е-поште", "upload.modal.accordion.email.placeholder": "Унесите примаоце е-поште",
"upload.modal.accordion.email.invalid-email": "Неисправна адреса е-поште", "upload.modal.accordion.email.invalid-email": "Неисправна адреса е-поште",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Максимална величина дељења у бајтовима", "admin.config.share.max-size.description": "Максимална величина дељења у бајтовима",
"admin.config.share.zip-compression-level": "Ниво zip компресије", "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": "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": "Омогућено",
"admin.config.smtp.enabled.description": "Да ли је SMTP омогућен. Поставите ово на тачно само ако сте унели хост, порт, е-пошту, корисника и лозинку вашег SMTP сервера.", "admin.config.smtp.enabled.description": "Да ли је SMTP омогућен. Поставите ово на тачно само ако сте унели хост, порт, е-пошту, корисника и лозинку вашег SMTP сервера.",
"admin.config.smtp.host": "Домаћин", "admin.config.smtp.host": "Домаћин",

View File

@@ -57,7 +57,7 @@ export default {
// /auth/reset-password // /auth/reset-password
"resetPassword.title": "Glömt ditt lösenord?", "resetPassword.title": "Glömt ditt lösenord?",
"resetPassword.description": "Ange din e-postadress för att återställa ditt lösenord.", "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.", "resetPassword.notify.success": "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.button.back": "Tillbaka till inloggningssidan",
"resetPassword.text.resetPassword": "Återställ lösenord", "resetPassword.text.resetPassword": "Återställ lösenord",
"resetPassword.text.enterNewPassword": "Ange ditt nya lösenord", "resetPassword.text.enterNewPassword": "Ange ditt nya lösenord",
@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "Administration", "admin.title": "Administration",
"admin.button.users": "Användarhantering", "admin.button.users": "Användarhantering",
"admin.button.shares": "Share management",
"admin.button.config": "Konfiguration", "admin.button.config": "Konfiguration",
"admin.version": "Version", "admin.version": "Version",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "Administratörsbehörigheter", "admin.users.modal.create.admin": "Administratörsbehörigheter",
"admin.users.modal.create.admin.description": "Om detta markeras kommer användaren att kunna komma åt administratörspanelen.", "admin.users.modal.create.admin.description": "Om detta markeras kommer användaren att kunna komma åt administratörspanelen.",
// END /admin/users // 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
"upload.title": "Ladda upp", "upload.title": "Ladda upp",
"upload.notify.generic-error": "Ett fel uppstod när din delning skulle slutföras.", "upload.notify.generic-error": "Ett fel uppstod när din delning skulle slutföras.",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "Månader", "upload.modal.expires.month-plural": "Månader",
"upload.modal.expires.year-singular": "År", "upload.modal.expires.year-singular": "År",
"upload.modal.expires.year-plural": "År", "upload.modal.expires.year-plural": "År",
"upload.modal.accordion.description.title": "Beskrivning", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "Anteckning till mottagare av denna delning", "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.title": "E-postmottagare",
"upload.modal.accordion.email.placeholder": "Ange e-postmottagare", "upload.modal.accordion.email.placeholder": "Ange e-postmottagare",
"upload.modal.accordion.email.invalid-email": "Ogiltig e-postadress", "upload.modal.accordion.email.invalid-email": "Ogiltig e-postadress",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "Maximal storlek för delning i bytes", "admin.config.share.max-size.description": "Maximal storlek för delning i bytes",
"admin.config.share.zip-compression-level": "Komprimeringsnivå för zip", "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.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": "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.", "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.",
"admin.config.smtp.host": "Adress", "admin.config.smtp.host": "Adress",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "แผงควบคุมระบบ", "admin.title": "แผงควบคุมระบบ",
"admin.button.users": "การจัดการผู้ใช้", "admin.button.users": "การจัดการผู้ใช้",
"admin.button.shares": "Share management",
"admin.button.config": "การตั้งค่า", "admin.button.config": "การตั้งค่า",
"admin.version": "เวอร์ชัน", "admin.version": "เวอร์ชัน",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "สิทธิ์ของผู้ดูแลระบบ", "admin.users.modal.create.admin": "สิทธิ์ของผู้ดูแลระบบ",
"admin.users.modal.create.admin.description": "หากติ๊กเลือก ผู้ใช้จะสามารถเข้าถึงแผงควบคุมระบบได้", "admin.users.modal.create.admin.description": "หากติ๊กเลือก ผู้ใช้จะสามารถเข้าถึงแผงควบคุมระบบได้",
// END /admin/users // 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
"upload.title": "อัปโหลด", "upload.title": "อัปโหลด",
"upload.notify.generic-error": "เกิดข้อผิดพลาดขณะที่กำลังจัดการการแชร์ของคุณ", "upload.notify.generic-error": "เกิดข้อผิดพลาดขณะที่กำลังจัดการการแชร์ของคุณ",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "เดือน", "upload.modal.expires.month-plural": "เดือน",
"upload.modal.expires.year-singular": "ปี", "upload.modal.expires.year-singular": "ปี",
"upload.modal.expires.year-plural": "ปี", "upload.modal.expires.year-plural": "ปี",
"upload.modal.accordion.description.title": "คำอธิบาย", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "หมายเหตุสำหรับผู้รับการแชร์นี้", "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.title": "ผู้รับอีเมล์",
"upload.modal.accordion.email.placeholder": "ป้อนผู้รับอีเมล์", "upload.modal.accordion.email.placeholder": "ป้อนผู้รับอีเมล์",
"upload.modal.accordion.email.invalid-email": "ที่อยู่อีเมล์ไม่ถูกต้อง", "upload.modal.accordion.email.invalid-email": "ที่อยู่อีเมล์ไม่ถูกต้อง",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "ขนาดสูงสุดของแชร์", "admin.config.share.max-size.description": "ขนาดสูงสุดของแชร์",
"admin.config.share.zip-compression-level": "ระดับการบีบอัดไฟล์ Zip", "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": "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": "เปิด",
"admin.config.smtp.enabled.description": "เปิดใช้งาน SMTP สำหรับการส่งอีเมล์์์์์์ เปิดได้เท่านั้นต่อเมื่อคุณใส่ข้อมูลโฮสต์ พอร์ต อีเมล์ ผู้ใช้ และรหัสผ่านของเซิร์ฟเวอร์ SMTP ของคุณ", "admin.config.smtp.enabled.description": "เปิดใช้งาน SMTP สำหรับการส่งอีเมล์์์์์์ เปิดได้เท่านั้นต่อเมื่อคุณใส่ข้อมูลโฮสต์ พอร์ต อีเมล์ ผู้ใช้ และรหัสผ่านของเซิร์ฟเวอร์ SMTP ของคุณ",
"admin.config.smtp.host": "โฮสต์", "admin.config.smtp.host": "โฮสต์",

View File

@@ -0,0 +1,434 @@
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": "Код",
"account.modal.totp.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

@@ -56,7 +56,7 @@ export default {
// END /auth/totp // END /auth/totp
// /auth/reset-password // /auth/reset-password
"resetPassword.title": "忘记密码?", "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.notify.success": "A message with a link to reset your password has been sent if the email exists.",
"resetPassword.button.back": "返回登录页面", "resetPassword.button.back": "返回登录页面",
"resetPassword.text.resetPassword": "重置密码", "resetPassword.text.resetPassword": "重置密码",
@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "管理", "admin.title": "管理",
"admin.button.users": "用户管理", "admin.button.users": "用户管理",
"admin.button.shares": "Share management",
"admin.button.config": "配置管理", "admin.button.config": "配置管理",
"admin.version": "版本", "admin.version": "版本",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "管理员", "admin.users.modal.create.admin": "管理员",
"admin.users.modal.create.admin.description": "如果勾选,用户将能访问管理员面板", "admin.users.modal.create.admin.description": "如果勾选,用户将能访问管理员面板",
// END /admin/users // 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
"upload.title": "上传", "upload.title": "上传",
"upload.notify.generic-error": "创建共享的过程中发生了错误", "upload.notify.generic-error": "创建共享的过程中发生了错误",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "月", "upload.modal.expires.month-plural": "月",
"upload.modal.expires.year-singular": "1 年", "upload.modal.expires.year-singular": "1 年",
"upload.modal.expires.year-plural": "年", "upload.modal.expires.year-plural": "年",
"upload.modal.accordion.description.title": "描述", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "共享文件备注信息", "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.title": "邮件提醒",
"upload.modal.accordion.email.placeholder": "收件人电子邮件地址", "upload.modal.accordion.email.placeholder": "收件人电子邮件地址",
"upload.modal.accordion.email.invalid-email": "邮件地址不可用", "upload.modal.accordion.email.invalid-email": "邮件地址不可用",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "最大文件上限,单位 bytes (1GB=1024MB=1048576KB=1073741824bytes)", "admin.config.share.max-size.description": "最大文件上限,单位 bytes (1GB=1024MB=1048576KB=1073741824bytes)",
"admin.config.share.zip-compression-level": "Zip 文件压缩质量", "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": "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": "启用",
"admin.config.smtp.enabled.description": "是否开启 SMTP仅当输入主机名、端口、发送邮箱、用户名和密码后开启", "admin.config.smtp.enabled.description": "是否开启 SMTP仅当输入主机名、端口、发送邮箱、用户名和密码后开启",
"admin.config.smtp.host": "主机名", "admin.config.smtp.host": "主机名",

View File

@@ -169,6 +169,7 @@ export default {
// /admin // /admin
"admin.title": "管理", "admin.title": "管理",
"admin.button.users": "使用者管理", "admin.button.users": "使用者管理",
"admin.button.shares": "Share management",
"admin.button.config": "配置管理", "admin.button.config": "配置管理",
"admin.version": "版本", "admin.version": "版本",
// END /admin // END /admin
@@ -195,6 +196,15 @@ export default {
"admin.users.modal.create.admin": "管理員", "admin.users.modal.create.admin": "管理員",
"admin.users.modal.create.admin.description": "如果勾選,使用者將能查看管理員面板", "admin.users.modal.create.admin.description": "如果勾選,使用者將能查看管理員面板",
// END /admin/users // 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
"upload.title": "上傳", "upload.title": "上傳",
"upload.notify.generic-error": "建立分享的過程中發生了錯誤", "upload.notify.generic-error": "建立分享的過程中發生了錯誤",
@@ -229,8 +239,9 @@ export default {
"upload.modal.expires.month-plural": "月", "upload.modal.expires.month-plural": "月",
"upload.modal.expires.year-singular": "年", "upload.modal.expires.year-singular": "年",
"upload.modal.expires.year-plural": "年", "upload.modal.expires.year-plural": "年",
"upload.modal.accordion.description.title": "描述", "upload.modal.accordion.name-and-description.title": "Name and description",
"upload.modal.accordion.description.placeholder": "分享檔案備註資訊", "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.title": "Email提醒",
"upload.modal.accordion.email.placeholder": "收件人Email地址", "upload.modal.accordion.email.placeholder": "收件人Email地址",
"upload.modal.accordion.email.invalid-email": "Email地址不可用", "upload.modal.accordion.email.invalid-email": "Email地址不可用",
@@ -314,6 +325,8 @@ export default {
"admin.config.share.max-size.description": "最大檔案上限,單位 bytes (1GB=1024MB=1048576KB=1073741824bytes)", "admin.config.share.max-size.description": "最大檔案上限,單位 bytes (1GB=1024MB=1048576KB=1073741824bytes)",
"admin.config.share.zip-compression-level": "Zip 壓縮等級", "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": "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": "啟用",
"admin.config.smtp.enabled.description": "是否開啟 SMTP需輸入Host、Port、發送郵箱、使用者名稱和密碼後才有作用", "admin.config.smtp.enabled.description": "是否開啟 SMTP需輸入Host、Port、發送郵箱、使用者名稱和密碼後才有作用",
"admin.config.smtp.host": "Host", "admin.config.smtp.host": "Host",

View File

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

View File

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

View File

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

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

View File

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

View File

@@ -3,7 +3,7 @@ import { useModals } from "@mantine/modals";
import { cleanNotifications } from "@mantine/notifications"; import { cleanNotifications } from "@mantine/notifications";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import pLimit from "p-limit"; import pLimit from "p-limit";
import { useEffect, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import Meta from "../../components/Meta"; import Meta from "../../components/Meta";
import Dropzone from "../../components/upload/Dropzone"; import Dropzone from "../../components/upload/Dropzone";
@@ -19,7 +19,6 @@ import { CreateShare, Share } from "../../types/share.type";
import toast from "../../utils/toast.util"; import toast from "../../utils/toast.util";
const promiseLimit = pLimit(3); const promiseLimit = pLimit(3);
const chunkSize = 10 * 1024 * 1024; // 10MB
let errorToastShown = false; let errorToastShown = false;
let createdShare: Share; let createdShare: Share;
@@ -38,6 +37,8 @@ const Upload = ({
const [files, setFiles] = useState<FileUpload[]>([]); const [files, setFiles] = useState<FileUpload[]>([]);
const [isUploading, setisUploading] = useState(false); const [isUploading, setisUploading] = useState(false);
const chunkSize = useRef(parseInt(config.get("share.chunkSize")));
maxShareSize ??= parseInt(config.get("share.maxSize")); maxShareSize ??= parseInt(config.get("share.maxSize"));
const uploadFiles = async (share: CreateShare, files: FileUpload[]) => { const uploadFiles = async (share: CreateShare, files: FileUpload[]) => {
@@ -54,7 +55,7 @@ const Upload = ({
const fileUploadPromises = files.map(async (file, fileIndex) => const fileUploadPromises = files.map(async (file, fileIndex) =>
// Limit the number of concurrent uploads to 3 // Limit the number of concurrent uploads to 3
promiseLimit(async () => { promiseLimit(async () => {
let fileId: string; let fileId;
const setFileProgress = (progress: number) => { const setFileProgress = (progress: number) => {
setFiles((files) => setFiles((files) =>
@@ -69,38 +70,30 @@ const Upload = ({
setFileProgress(1); 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 the file is 0 bytes, we still need to upload 1 chunk
if (chunks == 0) chunks++; if (chunks == 0) chunks++;
for (let chunkIndex = 0; chunkIndex < chunks; chunkIndex++) { for (let chunkIndex = 0; chunkIndex < chunks; chunkIndex++) {
const from = chunkIndex * chunkSize; const from = chunkIndex * chunkSize.current;
const to = from + chunkSize; const to = from + chunkSize.current;
const blob = file.slice(from, to); const blob = file.slice(from, to);
try { try {
await new Promise((resolve, reject) => { await shareService
const reader = new FileReader(); .uploadFile(
reader.onload = async (event) => createdShare.id,
await shareService blob,
.uploadFile( {
createdShare.id, id: fileId,
event, name: file.name,
{ },
id: fileId, chunkIndex,
name: file.name, chunks,
}, )
chunkIndex, .then((response) => {
chunks, fileId = response.id;
) });
.then((response) => {
fileId = response.id;
resolve(response);
})
.catch(reject);
reader.readAsDataURL(blob);
});
setFileProgress(((chunkIndex + 1) / chunks) * 100); setFileProgress(((chunkIndex + 1) / chunks) * 100);
} catch (e) { } catch (e) {

View File

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

View File

@@ -2,15 +2,18 @@ import User from "./user.type";
export type Share = { export type Share = {
id: string; id: string;
name?: string;
files: any; files: any;
creator: User; creator?: User;
description?: string; description?: string;
expiration: Date; expiration: Date;
size: number;
hasPassword: boolean; hasPassword: boolean;
}; };
export type CreateShare = { export type CreateShare = {
id: string; id: string;
name?: string;
description?: string; description?: string;
recipients: string[]; recipients: string[];
expiration: 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,6 +1,6 @@
{ {
"name": "pingvin-share", "name": "pingvin-share",
"version": "0.22.2", "version": "0.24.1",
"scripts": { "scripts": {
"format": "cd frontend && npm run format && cd ../backend && npm run format", "format": "cd frontend && npm run format && cd ../backend && npm run format",
"lint": "cd frontend && npm run lint && cd ../backend && npm run lint", "lint": "cd frontend && npm run lint && cd ../backend && npm run lint",