From dc2042a1eed89a62e7e6e56f12044ab90f560468 Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Fri, 27 Jun 2025 18:50:22 +1000 Subject: [PATCH 01/17] fix: rate limit api endpoints (#1863) Rate limit API endpoint --- apps/remix/package.json | 1 + apps/remix/server/router.ts | 20 ++++++++++++++++++++ package-lock.json | 10 ++++++++++ 3 files changed, 31 insertions(+) diff --git a/apps/remix/package.json b/apps/remix/package.json index 8cf9aa941..896826523 100644 --- a/apps/remix/package.json +++ b/apps/remix/package.json @@ -41,6 +41,7 @@ "colord": "^2.9.3", "framer-motion": "^10.12.8", "hono": "4.7.0", + "hono-rate-limiter": "^0.4.2", "hono-react-router-adapter": "^0.6.2", "input-otp": "^1.2.4", "isbot": "^5.1.17", diff --git a/apps/remix/server/router.ts b/apps/remix/server/router.ts index dfd9927b5..7d165d01f 100644 --- a/apps/remix/server/router.ts +++ b/apps/remix/server/router.ts @@ -1,4 +1,5 @@ import { Hono } from 'hono'; +import { rateLimiter } from 'hono-rate-limiter'; import { contextStorage } from 'hono/context-storage'; import { tsRestHonoApp } from '@documenso/api/hono'; @@ -21,6 +22,21 @@ export interface HonoEnv { const app = new Hono(); +/** + * Rate limiting for v1 and v2 API routes only. + * - 100 requests per minute per IP address + */ +const rateLimitMiddleware = rateLimiter({ + windowMs: 60 * 1000, // 1 minute + limit: 100, // 100 requests per window + keyGenerator: (c) => { + return c.req.header('x-forwarded-for') || c.req.header('x-real-ip') || 'unknown'; + }, + message: { + error: 'Too many requests, please try again later.', + }, +}); + /** * Attach session and context to requests. */ @@ -32,6 +48,10 @@ app.use(appContext); */ app.use('*', appMiddleware); +// Apply rate limit to /api/v1/* +app.use('/api/v1/*', rateLimitMiddleware); +app.use('/api/v2/*', rateLimitMiddleware); + // Auth server. app.route('/api/auth', auth); diff --git a/package-lock.json b/package-lock.json index 370f360b5..ce12af2b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -118,6 +118,7 @@ "colord": "^2.9.3", "framer-motion": "^10.12.8", "hono": "4.7.0", + "hono-rate-limiter": "^0.4.2", "hono-react-router-adapter": "^0.6.2", "input-otp": "^1.2.4", "isbot": "^5.1.17", @@ -20241,6 +20242,15 @@ "node": ">=16.9.0" } }, + "node_modules/hono-rate-limiter": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/hono-rate-limiter/-/hono-rate-limiter-0.4.2.tgz", + "integrity": "sha512-AAtFqgADyrmbDijcRTT/HJfwqfvhalya2Zo+MgfdrMPas3zSMD8SU03cv+ZsYwRU1swv7zgVt0shwN059yzhjw==", + "license": "MIT", + "peerDependencies": { + "hono": "^4.1.1" + } + }, "node_modules/hono-react-router-adapter": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/hono-react-router-adapter/-/hono-react-router-adapter-0.6.5.tgz", From 21dc4eee62b0d9194499b0a9569d0496290a0772 Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Fri, 27 Jun 2025 18:53:45 +1000 Subject: [PATCH 02/17] v1.12.0-rc.5 --- apps/remix/package.json | 2 +- package-lock.json | 6 +++--- package.json | 2 +- packages/trpc/utils/logger.ts | 0 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 packages/trpc/utils/logger.ts diff --git a/apps/remix/package.json b/apps/remix/package.json index 896826523..dd2673264 100644 --- a/apps/remix/package.json +++ b/apps/remix/package.json @@ -101,5 +101,5 @@ "vite-plugin-babel-macros": "^1.0.6", "vite-tsconfig-paths": "^5.1.4" }, - "version": "1.12.0-rc.4" + "version": "1.12.0-rc.5" } diff --git a/package-lock.json b/package-lock.json index ce12af2b4..8676634b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@documenso/root", - "version": "1.12.0-rc.4", + "version": "1.12.0-rc.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@documenso/root", - "version": "1.12.0-rc.4", + "version": "1.12.0-rc.5", "workspaces": [ "apps/*", "packages/*" @@ -89,7 +89,7 @@ }, "apps/remix": { "name": "@documenso/remix", - "version": "1.12.0-rc.4", + "version": "1.12.0-rc.5", "dependencies": { "@documenso/api": "*", "@documenso/assets": "*", diff --git a/package.json b/package.json index cf746f3cc..526e21ae3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "1.12.0-rc.4", + "version": "1.12.0-rc.5", "scripts": { "build": "turbo run build", "dev": "turbo run dev --filter=@documenso/remix", diff --git a/packages/trpc/utils/logger.ts b/packages/trpc/utils/logger.ts new file mode 100644 index 000000000..e69de29bb From e07a497b69721342ba51e99effefaffa7d31c6fa Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Fri, 27 Jun 2025 21:44:51 +1000 Subject: [PATCH 03/17] feat: api logging by pino (#1865) experiemental --- apps/remix/server/router.ts | 21 ++- package-lock.json | 192 +++++++++++++++++++- packages/api/hono.ts | 4 +- packages/api/v1/middleware/authenticated.ts | 12 ++ packages/lib/package.json | 6 +- packages/lib/utils/logger-legacy.ts | 112 ++++++++++++ packages/lib/utils/logger.ts | 129 +++---------- packages/trpc/server/context.ts | 9 +- packages/trpc/server/trpc.ts | 18 +- packages/trpc/utils/trpc-error-handler.ts | 2 +- 10 files changed, 389 insertions(+), 116 deletions(-) create mode 100644 packages/lib/utils/logger-legacy.ts diff --git a/apps/remix/server/router.ts b/apps/remix/server/router.ts index 7d165d01f..3e0e3f411 100644 --- a/apps/remix/server/router.ts +++ b/apps/remix/server/router.ts @@ -1,11 +1,15 @@ import { Hono } from 'hono'; import { rateLimiter } from 'hono-rate-limiter'; import { contextStorage } from 'hono/context-storage'; +import { requestId } from 'hono/request-id'; +import type { RequestIdVariables } from 'hono/request-id'; +import type { Logger } from 'pino'; import { tsRestHonoApp } from '@documenso/api/hono'; import { auth } from '@documenso/auth/server'; import { API_V2_BETA_URL } from '@documenso/lib/constants/app'; import { jobsClient } from '@documenso/lib/jobs/client'; +import { logger } from '@documenso/lib/utils/logger'; import { openApiDocument } from '@documenso/trpc/server/open-api'; import { filesRoute } from './api/files'; @@ -15,8 +19,9 @@ import { openApiTrpcServerHandler } from './trpc/hono-trpc-open-api'; import { reactRouterTrpcServer } from './trpc/hono-trpc-remix'; export interface HonoEnv { - Variables: { + Variables: RequestIdVariables & { context: AppContext; + logger: Logger; }; } @@ -47,6 +52,20 @@ app.use(appContext); * RR7 app middleware. */ app.use('*', appMiddleware); +app.use('*', requestId()); +app.use(async (c, next) => { + const metadata = c.get('context').requestMetadata; + + const honoLogger = logger.child({ + requestId: c.var.requestId, + ipAddress: metadata.ipAddress, + userAgent: metadata.userAgent, + }); + + c.set('logger', honoLogger); + + await next(); +}); // Apply rate limit to /api/v1/* app.use('/api/v1/*', rateLimitMiddleware); diff --git a/package-lock.json b/package-lock.json index 8676634b3..39e23a942 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13312,6 +13312,15 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/attr-accept": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", @@ -14937,7 +14946,6 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, "license": "MIT" }, "node_modules/colors": { @@ -16119,6 +16127,15 @@ "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/dayjs": { "version": "1.11.13", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", @@ -18241,6 +18258,12 @@ "node": ">=4" } }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -18309,6 +18332,21 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "license": "MIT" }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", @@ -21653,7 +21691,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -26084,6 +26121,15 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "license": "MIT" }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -26903,6 +26949,82 @@ "node": ">=0.10.0" } }, + "node_modules/pino": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.7.0.tgz", + "integrity": "sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/pino-pretty": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz", + "integrity": "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pump": "^3.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" + }, "node_modules/pirates": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", @@ -27780,6 +27902,22 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -28017,6 +28155,12 @@ ], "license": "MIT" }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", @@ -29408,6 +29552,15 @@ "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==", "license": "MIT" }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/recharts": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.3.tgz", @@ -30459,6 +30612,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -30524,6 +30686,12 @@ "node": ">=4" } }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause" + }, "node_modules/selderee": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz", @@ -31085,6 +31253,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/sonic-boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/sort-keys": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-5.1.0.tgz", @@ -32350,6 +32527,15 @@ "node": ">=0.8" } }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -36015,6 +36201,8 @@ "oslo": "^0.17.0", "pdf-lib": "^1.17.1", "pg": "^8.11.3", + "pino": "^9.7.0", + "pino-pretty": "^13.0.0", "playwright": "1.52.0", "posthog-js": "^1.245.0", "posthog-node": "^4.17.0", diff --git a/packages/api/hono.ts b/packages/api/hono.ts index 1e41c5ee0..4376e566a 100644 --- a/packages/api/hono.ts +++ b/packages/api/hono.ts @@ -8,10 +8,12 @@ import { testCredentialsHandler } from '@documenso/lib/server-only/public-api/te import { listDocumentsHandler } from '@documenso/lib/server-only/webhooks/zapier/list-documents'; import { subscribeHandler } from '@documenso/lib/server-only/webhooks/zapier/subscribe'; import { unsubscribeHandler } from '@documenso/lib/server-only/webhooks/zapier/unsubscribe'; +// This is a bit nasty. Todo: Extract +import type { HonoEnv } from '@documenso/remix/server/router'; // This is bad, ts-router will be created on each request. // But don't really have a choice here. -export const tsRestHonoApp = new Hono(); +export const tsRestHonoApp = new Hono(); tsRestHonoApp .get('/openapi', (c) => c.redirect('https://openapi-v1.documenso.com')) diff --git a/packages/api/v1/middleware/authenticated.ts b/packages/api/v1/middleware/authenticated.ts index 0249f2ebc..13366b42a 100644 --- a/packages/api/v1/middleware/authenticated.ts +++ b/packages/api/v1/middleware/authenticated.ts @@ -5,6 +5,7 @@ import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { getApiTokenByToken } from '@documenso/lib/server-only/public-api/get-api-token-by-token'; import type { ApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; import { extractRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; +import { logger } from '@documenso/lib/utils/logger'; type B = { // appRoute: any; @@ -62,6 +63,17 @@ export const authenticatedMiddleware = < }, }; + // Todo: Get from Hono context instead. + logger.info({ + ipAddress: metadata.requestMetadata.ipAddress, + userAgent: metadata.requestMetadata.userAgent, + auth: 'api', + source: 'apiV1', + path: request.url, + userId: apiToken.user.id, + apiTokenId: apiToken.id, + }); + return await handler( { ...args, diff --git a/packages/lib/package.json b/packages/lib/package.json index d319617a9..3a06087bd 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -27,7 +27,6 @@ "@lingui/core": "^5.2.0", "@lingui/macro": "^5.2.0", "@lingui/react": "^5.2.0", - "jose": "^6.0.0", "@noble/ciphers": "0.4.0", "@noble/hashes": "1.3.2", "@node-rs/bcrypt": "^1.10.0", @@ -37,6 +36,7 @@ "@vvo/tzdb": "^6.117.0", "csv-parse": "^5.6.0", "inngest": "^3.19.13", + "jose": "^6.0.0", "kysely": "0.26.3", "luxon": "^3.4.0", "micro": "^10.0.1", @@ -44,6 +44,8 @@ "oslo": "^0.17.0", "pdf-lib": "^1.17.1", "pg": "^8.11.3", + "pino": "^9.7.0", + "pino-pretty": "^13.0.0", "playwright": "1.52.0", "posthog-js": "^1.245.0", "posthog-node": "^4.17.0", @@ -59,4 +61,4 @@ "@types/luxon": "^3.3.1", "@types/pg": "^8.11.4" } -} \ No newline at end of file +} diff --git a/packages/lib/utils/logger-legacy.ts b/packages/lib/utils/logger-legacy.ts new file mode 100644 index 000000000..b708f2bdd --- /dev/null +++ b/packages/lib/utils/logger-legacy.ts @@ -0,0 +1,112 @@ +import Honeybadger from '@honeybadger-io/js'; + +import { env } from './env'; + +export const buildLogger = () => { + if (env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY')) { + return new HoneybadgerLogger(); + } + + return new DefaultLogger(); +}; + +interface LoggerDescriptionOptions { + method?: string; + path?: string; + context?: Record; + + /** + * The type of log to be captured. + * + * Defaults to `info`. + */ + level?: 'info' | 'error' | 'critical'; +} + +/** + * Basic logger implementation intended to be used in the server side for capturing + * explicit errors and other logs. + * + * Not intended to capture the request and responses. + */ +interface Logger { + log(message: string, options?: LoggerDescriptionOptions): void; + + error(error: Error, options?: LoggerDescriptionOptions): void; +} + +class DefaultLogger implements Logger { + log(_message: string, _options?: LoggerDescriptionOptions) { + // Do nothing. + } + + error(_error: Error, _options?: LoggerDescriptionOptions): void { + // Do nothing. + } +} + +class HoneybadgerLogger implements Logger { + constructor() { + if (!env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY')) { + throw new Error('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY is not set'); + } + + Honeybadger.configure({ + apiKey: env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY'), + }); + } + + /** + * Honeybadger doesn't really have a non-error logging system. + */ + log(message: string, options?: LoggerDescriptionOptions) { + const { context = {}, level = 'info' } = options || {}; + + try { + Honeybadger.event({ + message, + context: { + level, + ...context, + }, + }); + } catch (err) { + console.error(err); + + // Do nothing. + } + } + + error(error: Error, options?: LoggerDescriptionOptions): void { + const { context = {}, level = 'error', method, path } = options || {}; + + // const tags = [`level:${level}`]; + const tags = []; + + let errorMessage = error.message; + + if (method) { + tags.push(`method:${method}`); + + errorMessage = `[${method}]: ${error.message}`; + } + + if (path) { + tags.push(`path:${path}`); + } + + try { + Honeybadger.notify(errorMessage, { + context: { + level, + ...context, + }, + tags, + }); + } catch (err) { + console.error(err); + + // Do nothing. + } + } +} diff --git a/packages/lib/utils/logger.ts b/packages/lib/utils/logger.ts index b708f2bdd..e60ab0142 100644 --- a/packages/lib/utils/logger.ts +++ b/packages/lib/utils/logger.ts @@ -1,112 +1,27 @@ -import Honeybadger from '@honeybadger-io/js'; +import { pino } from 'pino'; -import { env } from './env'; +// const transports: TransportTargetOptions[] = []; -export const buildLogger = () => { - if (env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY')) { - return new HoneybadgerLogger(); - } +// if (env('NEXT_PRIVATE_LOGGING_DEV')) { +// transports.push({ +// target: 'pino-pretty', +// level: 'info', +// }); +// } - return new DefaultLogger(); -}; +// const loggingFilePath = env('NEXT_PRIVATE_LOGGING_FILE_PATH'); -interface LoggerDescriptionOptions { - method?: string; - path?: string; - context?: Record; +// if (loggingFilePath) { +// transports.push({ +// target: 'pino/file', +// level: 'info', +// options: { +// destination: loggingFilePath, +// mkdir: true, +// }, +// }); +// } - /** - * The type of log to be captured. - * - * Defaults to `info`. - */ - level?: 'info' | 'error' | 'critical'; -} - -/** - * Basic logger implementation intended to be used in the server side for capturing - * explicit errors and other logs. - * - * Not intended to capture the request and responses. - */ -interface Logger { - log(message: string, options?: LoggerDescriptionOptions): void; - - error(error: Error, options?: LoggerDescriptionOptions): void; -} - -class DefaultLogger implements Logger { - log(_message: string, _options?: LoggerDescriptionOptions) { - // Do nothing. - } - - error(_error: Error, _options?: LoggerDescriptionOptions): void { - // Do nothing. - } -} - -class HoneybadgerLogger implements Logger { - constructor() { - if (!env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY')) { - throw new Error('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY is not set'); - } - - Honeybadger.configure({ - apiKey: env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY'), - }); - } - - /** - * Honeybadger doesn't really have a non-error logging system. - */ - log(message: string, options?: LoggerDescriptionOptions) { - const { context = {}, level = 'info' } = options || {}; - - try { - Honeybadger.event({ - message, - context: { - level, - ...context, - }, - }); - } catch (err) { - console.error(err); - - // Do nothing. - } - } - - error(error: Error, options?: LoggerDescriptionOptions): void { - const { context = {}, level = 'error', method, path } = options || {}; - - // const tags = [`level:${level}`]; - const tags = []; - - let errorMessage = error.message; - - if (method) { - tags.push(`method:${method}`); - - errorMessage = `[${method}]: ${error.message}`; - } - - if (path) { - tags.push(`path:${path}`); - } - - try { - Honeybadger.notify(errorMessage, { - context: { - level, - ...context, - }, - tags, - }); - } catch (err) { - console.error(err); - - // Do nothing. - } - } -} +export const logger = pino({ + level: 'info', +}); diff --git a/packages/trpc/server/context.ts b/packages/trpc/server/context.ts index b11c23dd8..a11cab223 100644 --- a/packages/trpc/server/context.ts +++ b/packages/trpc/server/context.ts @@ -1,14 +1,17 @@ import type { Session } from '@prisma/client'; import type { Context } from 'hono'; +import type { Logger } from 'pino'; import { z } from 'zod'; import type { SessionUser } from '@documenso/auth/server/lib/session/session'; import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session'; import type { ApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; import { extractRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; +// This is a bit nasty. Todo: Extract +import type { HonoEnv } from '@documenso/remix/server/router'; type CreateTrpcContextOptions = { - c: Context; + c: Context; requestSource: 'app' | 'apiV1' | 'apiV2'; }; @@ -19,6 +22,7 @@ export const createTrpcContext = async ({ const { session, user } = await getOptionalSession(c); const req = c.req.raw; + const logger = c.get('logger'); const metadata: ApiRequestMetadata = { requestMetadata: extractRequestMetadata(req), @@ -36,6 +40,7 @@ export const createTrpcContext = async ({ if (!session || !user) { return { + logger, session: null, user: null, teamId, @@ -45,6 +50,7 @@ export const createTrpcContext = async ({ } return { + logger, session, user, teamId, @@ -66,4 +72,5 @@ export type TrpcContext = ( teamId: number | undefined; req: Request; metadata: ApiRequestMetadata; + logger: Logger; }; diff --git a/packages/trpc/server/trpc.ts b/packages/trpc/server/trpc.ts index 8e081390c..737df2a36 100644 --- a/packages/trpc/server/trpc.ts +++ b/packages/trpc/server/trpc.ts @@ -65,7 +65,13 @@ const t = initTRPC /** * Middlewares */ -export const authenticatedMiddleware = t.middleware(async ({ ctx, next }) => { +export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path }) => { + const logger = ctx.logger.child({ + path, + auth: ctx.metadata.auth, + source: ctx.metadata.source, + }); + const authorizationHeader = ctx.req.headers.get('authorization'); // Taken from `authenticatedMiddleware` in `@documenso/api/v1/middleware/authenticated.ts`. @@ -79,6 +85,11 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next }) => { const apiToken = await getApiTokenByToken({ token }); + logger.info({ + userId: apiToken.user.id, + apiTokenId: apiToken.id, + }); + return await next({ ctx: { ...ctx, @@ -111,6 +122,11 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next }) => { }); } + logger.info({ + userId: ctx.user.id, + apiTokenId: null, + }); + return await next({ ctx: { ...ctx, diff --git a/packages/trpc/utils/trpc-error-handler.ts b/packages/trpc/utils/trpc-error-handler.ts index cdd2ea157..aa488f612 100644 --- a/packages/trpc/utils/trpc-error-handler.ts +++ b/packages/trpc/utils/trpc-error-handler.ts @@ -1,7 +1,7 @@ import type { ErrorHandlerOptions } from '@trpc/server/unstable-core-do-not-import'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; -import { buildLogger } from '@documenso/lib/utils/logger'; +import { buildLogger } from '@documenso/lib/utils/logger-legacy'; const logger = buildLogger(); From 85ac65e40502387ee07873b447467ef1669c5372 Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Fri, 27 Jun 2025 21:46:16 +1000 Subject: [PATCH 04/17] v1.12.0-rc.6 --- apps/remix/package.json | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/remix/package.json b/apps/remix/package.json index dd2673264..c06129ee9 100644 --- a/apps/remix/package.json +++ b/apps/remix/package.json @@ -101,5 +101,5 @@ "vite-plugin-babel-macros": "^1.0.6", "vite-tsconfig-paths": "^5.1.4" }, - "version": "1.12.0-rc.5" + "version": "1.12.0-rc.6" } diff --git a/package-lock.json b/package-lock.json index 39e23a942..35e5b46e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@documenso/root", - "version": "1.12.0-rc.5", + "version": "1.12.0-rc.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@documenso/root", - "version": "1.12.0-rc.5", + "version": "1.12.0-rc.6", "workspaces": [ "apps/*", "packages/*" @@ -89,7 +89,7 @@ }, "apps/remix": { "name": "@documenso/remix", - "version": "1.12.0-rc.5", + "version": "1.12.0-rc.6", "dependencies": { "@documenso/api": "*", "@documenso/assets": "*", diff --git a/package.json b/package.json index 526e21ae3..b0f93019f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "1.12.0-rc.5", + "version": "1.12.0-rc.6", "scripts": { "build": "turbo run build", "dev": "turbo run dev --filter=@documenso/remix", From 20c8969272dc7777d42727f755e6b81ceaf9bc40 Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Fri, 27 Jun 2025 22:17:02 +1000 Subject: [PATCH 05/17] fix: get real ip for rate limit key --- apps/remix/server/router.ts | 7 ++++- packages/lib/universal/get-ip-address.ts | 39 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 packages/lib/universal/get-ip-address.ts diff --git a/apps/remix/server/router.ts b/apps/remix/server/router.ts index 3e0e3f411..e64f7d292 100644 --- a/apps/remix/server/router.ts +++ b/apps/remix/server/router.ts @@ -9,6 +9,7 @@ import { tsRestHonoApp } from '@documenso/api/hono'; import { auth } from '@documenso/auth/server'; import { API_V2_BETA_URL } from '@documenso/lib/constants/app'; import { jobsClient } from '@documenso/lib/jobs/client'; +import { getIpAddress } from '@documenso/lib/universal/get-ip-address'; import { logger } from '@documenso/lib/utils/logger'; import { openApiDocument } from '@documenso/trpc/server/open-api'; @@ -35,7 +36,11 @@ const rateLimitMiddleware = rateLimiter({ windowMs: 60 * 1000, // 1 minute limit: 100, // 100 requests per window keyGenerator: (c) => { - return c.req.header('x-forwarded-for') || c.req.header('x-real-ip') || 'unknown'; + try { + return getIpAddress(c.req.raw); + } catch (error) { + return 'unknown'; + } }, message: { error: 'Too many requests, please try again later.', diff --git a/packages/lib/universal/get-ip-address.ts b/packages/lib/universal/get-ip-address.ts new file mode 100644 index 000000000..8b838852b --- /dev/null +++ b/packages/lib/universal/get-ip-address.ts @@ -0,0 +1,39 @@ +export const getIpAddress = (req: Request) => { + // Check for forwarded headers first (common in proxy setups) + const forwarded = req.headers.get('x-forwarded-for'); + + if (forwarded) { + // x-forwarded-for can contain multiple IPs, take the first one + return forwarded.split(',')[0].trim(); + } + + // Check for real IP header (used by some proxies) + const realIp = req.headers.get('x-real-ip'); + + if (realIp) { + return realIp; + } + + // Check for client IP header + const clientIp = req.headers.get('x-client-ip'); + + if (clientIp) { + return clientIp; + } + + // Check for CF-Connecting-IP (Cloudflare) + const cfConnectingIp = req.headers.get('cf-connecting-ip'); + + if (cfConnectingIp) { + return cfConnectingIp; + } + + // Check for True-Client-IP (Akamai and Cloudflare) + const trueClientIp = req.headers.get('true-client-ip'); + + if (trueClientIp) { + return trueClientIp; + } + + throw new Error('No IP address found'); +}; From 58d97518c8947f4f51c3a60d73bcfa3d1be0aedf Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Fri, 27 Jun 2025 22:17:45 +1000 Subject: [PATCH 06/17] v1.12.0-rc.7 --- apps/remix/package.json | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/remix/package.json b/apps/remix/package.json index c06129ee9..8a5cc6817 100644 --- a/apps/remix/package.json +++ b/apps/remix/package.json @@ -101,5 +101,5 @@ "vite-plugin-babel-macros": "^1.0.6", "vite-tsconfig-paths": "^5.1.4" }, - "version": "1.12.0-rc.6" + "version": "1.12.0-rc.7" } diff --git a/package-lock.json b/package-lock.json index 35e5b46e2..4ae9c4e1d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@documenso/root", - "version": "1.12.0-rc.6", + "version": "1.12.0-rc.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@documenso/root", - "version": "1.12.0-rc.6", + "version": "1.12.0-rc.7", "workspaces": [ "apps/*", "packages/*" @@ -89,7 +89,7 @@ }, "apps/remix": { "name": "@documenso/remix", - "version": "1.12.0-rc.6", + "version": "1.12.0-rc.7", "dependencies": { "@documenso/api": "*", "@documenso/assets": "*", diff --git a/package.json b/package.json index b0f93019f..6dec2e494 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "1.12.0-rc.6", + "version": "1.12.0-rc.7", "scripts": { "build": "turbo run build", "dev": "turbo run dev --filter=@documenso/remix", From 0cc729e9bd0f25b7854fe90b60bca16592a94e37 Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Mon, 30 Jun 2025 19:11:16 +1000 Subject: [PATCH 07/17] feat: add sequential document view logs (#1871) ## Description Add a new document audit log to detect when the document is viewed. This should only be visible in the document audit log page Notes: 1. I wanted to reuse the `DOCUMENT_OPENED` event and add an additional paramter to track sequential views, but it's not query-able 2. This will log "DOCUMENT_VIEWED" before "DOCUMENT_OPENED" but i don't think it matters --- .../document-history-sheet-changes.tsx | 26 -- .../document/document-history-sheet.tsx | 410 ------------------ .../t.$teamUrl+/documents.$id._index.tsx | 18 +- .../server-only/document/viewed-document.ts | 25 +- packages/lib/types/document-audit-logs.ts | 18 + packages/lib/utils/document-audit-logs.ts | 4 + 6 files changed, 47 insertions(+), 454 deletions(-) delete mode 100644 apps/remix/app/components/general/document/document-history-sheet-changes.tsx delete mode 100644 apps/remix/app/components/general/document/document-history-sheet.tsx diff --git a/apps/remix/app/components/general/document/document-history-sheet-changes.tsx b/apps/remix/app/components/general/document/document-history-sheet-changes.tsx deleted file mode 100644 index 577dbc473..000000000 --- a/apps/remix/app/components/general/document/document-history-sheet-changes.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; - -import { Badge } from '@documenso/ui/primitives/badge'; - -export type DocumentHistorySheetChangesProps = { - values: { - key: string | React.ReactNode; - value: string | React.ReactNode; - }[]; -}; - -export const DocumentHistorySheetChanges = ({ values }: DocumentHistorySheetChangesProps) => { - return ( - - {values.map(({ key, value }, i) => ( -

- {key}: - {value} -

- ))} -
- ); -}; diff --git a/apps/remix/app/components/general/document/document-history-sheet.tsx b/apps/remix/app/components/general/document/document-history-sheet.tsx deleted file mode 100644 index f7c70bc84..000000000 --- a/apps/remix/app/components/general/document/document-history-sheet.tsx +++ /dev/null @@ -1,410 +0,0 @@ -import { useMemo, useState } from 'react'; - -import { useLingui } from '@lingui/react'; -import { Trans } from '@lingui/react/macro'; -import { ArrowRightIcon, Loader } from 'lucide-react'; -import { DateTime } from 'luxon'; -import { match } from 'ts-pattern'; -import { UAParser } from 'ua-parser-js'; - -import { DOCUMENT_AUDIT_LOG_EMAIL_FORMAT } from '@documenso/lib/constants/document-audit-logs'; -import { DOCUMENT_AUTH_TYPES } from '@documenso/lib/constants/document-auth'; -import { DOCUMENT_AUDIT_LOG_TYPE } from '@documenso/lib/types/document-audit-logs'; -import { formatDocumentAuditLogAction } from '@documenso/lib/utils/document-audit-logs'; -import { trpc } from '@documenso/trpc/react'; -import { cn } from '@documenso/ui/lib/utils'; -import { Avatar, AvatarFallback } from '@documenso/ui/primitives/avatar'; -import { Badge } from '@documenso/ui/primitives/badge'; -import { Button } from '@documenso/ui/primitives/button'; -import { Sheet, SheetContent, SheetTrigger } from '@documenso/ui/primitives/sheet'; - -import { DocumentHistorySheetChanges } from './document-history-sheet-changes'; - -export type DocumentHistorySheetProps = { - documentId: number; - userId: number; - isMenuOpen?: boolean; - onMenuOpenChange?: (_value: boolean) => void; - children?: React.ReactNode; -}; - -export const DocumentHistorySheet = ({ - documentId, - userId, - isMenuOpen, - onMenuOpenChange, - children, -}: DocumentHistorySheetProps) => { - const { _, i18n } = useLingui(); - - const [isUserDetailsVisible, setIsUserDetailsVisible] = useState(false); - - const { - data, - isLoading, - isLoadingError, - refetch, - hasNextPage, - fetchNextPage, - isFetchingNextPage, - } = trpc.document.findDocumentAuditLogs.useInfiniteQuery( - { - documentId, - }, - { - getNextPageParam: (lastPage) => lastPage.nextCursor, - placeholderData: (previousData) => previousData, - }, - ); - - const documentAuditLogs = useMemo(() => (data?.pages ?? []).flatMap((page) => page.data), [data]); - - const extractBrowser = (userAgent?: string | null) => { - if (!userAgent) { - return 'Unknown'; - } - - const parser = new UAParser(userAgent); - - parser.setUA(userAgent); - - const result = parser.getResult(); - - return result.browser.name; - }; - - /** - * Applies the following formatting for a given text: - * - Uppercase first lower, lowercase rest - * - Replace _ with spaces - * - * @param text The text to format - * @returns The formatted text - */ - const formatGenericText = (text?: string | string[] | null): string => { - if (!text) { - return ''; - } - - if (Array.isArray(text)) { - return text.map((t) => formatGenericText(t)).join(', '); - } - - return (text.charAt(0).toUpperCase() + text.slice(1).toLowerCase()).replaceAll('_', ' '); - }; - - return ( - - {children && {children}} - - -
-

- Document history -

- -
- - {isLoading && ( -
- -
- )} - - {isLoadingError && ( -
-

- Unable to load document history -

- -
- )} - - {data && ( -
    - {documentAuditLogs.map((auditLog) => ( -
  • -
    - - - {(auditLog?.email ?? auditLog?.name ?? '?').slice(0, 1).toUpperCase()} - - - -
    -

    - {formatDocumentAuditLogAction(_, auditLog, userId).description} -

    -

    - {DateTime.fromJSDate(auditLog.createdAt) - .setLocale(i18n.locales?.[0] || i18n.locale) - .toFormat('d MMM, yyyy HH:MM a')} -

    -
    -
    - - {match(auditLog) - .with( - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_CREATED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_COMPLETED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_DELETED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_OPENED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_COMPLETED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_REJECTED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_SENT }, - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_MOVED_TO_TEAM }, - () => null, - ) - .with( - { type: DOCUMENT_AUDIT_LOG_TYPE.RECIPIENT_CREATED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.RECIPIENT_DELETED }, - ({ data }) => { - const values = [ - { - key: 'Email', - value: data.recipientEmail, - }, - { - key: 'Role', - value: formatGenericText(data.recipientRole), - }, - ]; - - // Insert the name to the start of the array if available. - if (data.recipientName) { - values.unshift({ - key: 'Name', - value: data.recipientName, - }); - } - - return ; - }, - ) - .with({ type: DOCUMENT_AUDIT_LOG_TYPE.RECIPIENT_UPDATED }, ({ data }) => { - if (data.changes.length === 0) { - return null; - } - - return ( - ({ - key: formatGenericText(type), - value: ( - - {type === 'ROLE' ? formatGenericText(from) : from} - - {type === 'ROLE' ? formatGenericText(to) : to} - - ), - }))} - /> - ); - }) - .with( - { type: DOCUMENT_AUDIT_LOG_TYPE.FIELD_CREATED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.FIELD_DELETED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.FIELD_UPDATED }, - ({ data }) => ( - - ), - ) - .with( - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_GLOBAL_AUTH_ACCESS_UPDATED }, - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_GLOBAL_AUTH_ACTION_UPDATED }, - ({ data }) => ( - DOCUMENT_AUTH_TYPES[f]?.value || 'None') - .join(', ') - : DOCUMENT_AUTH_TYPES[data.from || '']?.value || 'None', - }, - { - key: 'New', - value: Array.isArray(data.to) - ? data.to - .map((f) => DOCUMENT_AUTH_TYPES[f]?.value || 'None') - .join(', ') - : DOCUMENT_AUTH_TYPES[data.to || '']?.value || 'None', - }, - ]} - /> - ), - ) - .with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_META_UPDATED }, ({ data }) => { - if (data.changes.length === 0) { - return null; - } - - return ( - ({ - key: formatGenericText(change.type), - value: change.type === 'PASSWORD' ? '*********' : change.to, - }))} - /> - ); - }) - .with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_TITLE_UPDATED }, ({ data }) => ( - - )) - .with( - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_EXTERNAL_ID_UPDATED }, - ({ data }) => ( - - ), - ) - .with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_FIELD_INSERTED }, ({ data }) => ( - - )) - .with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_FIELD_UNINSERTED }, ({ data }) => ( - - )) - .with({ type: DOCUMENT_AUDIT_LOG_TYPE.EMAIL_SENT }, ({ data }) => ( - - )) - .with( - { type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_VISIBILITY_UPDATED }, - ({ data }) => ( - - ), - ) - .with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_FIELD_PREFILLED }, ({ data }) => ( - - )) - .exhaustive()} - - {isUserDetailsVisible && ( - <> -
    - - IP: {auditLog.ipAddress ?? 'Unknown'} - - - - Browser: {extractBrowser(auditLog.userAgent)} - -
    - - )} -
  • - ))} - - {hasNextPage && ( -
    - -
    - )} -
- )} -
-
- ); -}; diff --git a/apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx b/apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx index 6513bddc0..99c2bd243 100644 --- a/apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx +++ b/apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx @@ -1,7 +1,7 @@ import { useLingui } from '@lingui/react'; import { Plural, Trans } from '@lingui/react/macro'; import { DocumentStatus, TeamMemberRole } from '@prisma/client'; -import { ChevronLeft, Clock9, Users2 } from 'lucide-react'; +import { ChevronLeft, Users2 } from 'lucide-react'; import { Link, redirect } from 'react-router'; import { match } from 'ts-pattern'; @@ -13,11 +13,9 @@ import { DocumentVisibility } from '@documenso/lib/types/document-visibility'; import { formatDocumentsPath } from '@documenso/lib/utils/teams'; import { DocumentReadOnlyFields } from '@documenso/ui/components/document/document-read-only-fields'; import { Badge } from '@documenso/ui/primitives/badge'; -import { Button } from '@documenso/ui/primitives/button'; import { Card, CardContent } from '@documenso/ui/primitives/card'; import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer'; -import { DocumentHistorySheet } from '~/components/general/document/document-history-sheet'; import { DocumentPageViewButton } from '~/components/general/document/document-page-view-button'; import { DocumentPageViewDropdown } from '~/components/general/document/document-page-view-dropdown'; import { DocumentPageViewInformation } from '~/components/general/document/document-page-view-information'; @@ -101,9 +99,6 @@ export default function DocumentPage() { const { recipients, documentData, documentMeta } = document; - // This was a feature flag. Leave to false since it's not ready. - const isDocumentHistoryEnabled = false; - return (
{document.status === DocumentStatus.PENDING && ( @@ -154,17 +149,6 @@ export default function DocumentPage() { )}
- - {isDocumentHistoryEnabled && ( -
- - - -
- )}
diff --git a/packages/lib/server-only/document/viewed-document.ts b/packages/lib/server-only/document/viewed-document.ts index fbc0aaa2d..a9faf992a 100644 --- a/packages/lib/server-only/document/viewed-document.ts +++ b/packages/lib/server-only/document/viewed-document.ts @@ -27,7 +27,6 @@ export const viewedDocument = async ({ const recipient = await prisma.recipient.findFirst({ where: { token, - readStatus: ReadStatus.NOT_OPENED, }, }); @@ -37,6 +36,30 @@ export const viewedDocument = async ({ const { documentId } = recipient; + await prisma.documentAuditLog.create({ + data: createDocumentAuditLogData({ + type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_VIEWED, + documentId, + user: { + name: recipient.name, + email: recipient.email, + }, + requestMetadata, + data: { + recipientEmail: recipient.email, + recipientId: recipient.id, + recipientName: recipient.name, + recipientRole: recipient.role, + accessAuth: recipientAccessAuth ?? [], + }, + }), + }); + + // Early return if already opened. + if (recipient.readStatus === ReadStatus.OPENED) { + return; + } + await prisma.$transaction(async (tx) => { await tx.recipient.update({ where: { diff --git a/packages/lib/types/document-audit-logs.ts b/packages/lib/types/document-audit-logs.ts index 25679287a..5c3f5bd86 100644 --- a/packages/lib/types/document-audit-logs.ts +++ b/packages/lib/types/document-audit-logs.ts @@ -33,6 +33,7 @@ export const ZDocumentAuditLogTypeSchema = z.enum([ 'DOCUMENT_GLOBAL_AUTH_ACTION_UPDATED', // When the global action authentication is updated. 'DOCUMENT_META_UPDATED', // When the document meta data is updated. 'DOCUMENT_OPENED', // When the document is opened by a recipient. + 'DOCUMENT_VIEWED', // When the document is viewed by a recipient. 'DOCUMENT_RECIPIENT_REJECTED', // When a recipient rejects the document. 'DOCUMENT_RECIPIENT_COMPLETED', // When a recipient completes all their required tasks for the document. 'DOCUMENT_SENT', // When the document transitions from DRAFT to PENDING. @@ -438,6 +439,22 @@ export const ZDocumentAuditLogEventDocumentOpenedSchema = z.object({ }), }); +/** + * Event: Document viewed. + */ +export const ZDocumentAuditLogEventDocumentViewedSchema = z.object({ + type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_VIEWED), + data: ZBaseRecipientDataSchema.extend({ + accessAuth: z.preprocess((unknownValue) => { + if (!unknownValue) { + return []; + } + + return Array.isArray(unknownValue) ? unknownValue : [unknownValue]; + }, z.array(ZRecipientAccessAuthTypesSchema)), + }), +}); + /** * Event: Document recipient completed the document (the recipient has fully actioned and completed their required steps for the document). */ @@ -601,6 +618,7 @@ export const ZDocumentAuditLogSchema = ZDocumentAuditLogBaseSchema.and( ZDocumentAuditLogEventDocumentGlobalAuthActionUpdatedSchema, ZDocumentAuditLogEventDocumentMetaUpdatedSchema, ZDocumentAuditLogEventDocumentOpenedSchema, + ZDocumentAuditLogEventDocumentViewedSchema, ZDocumentAuditLogEventDocumentRecipientCompleteSchema, ZDocumentAuditLogEventDocumentRecipientRejectedSchema, ZDocumentAuditLogEventDocumentSentSchema, diff --git a/packages/lib/utils/document-audit-logs.ts b/packages/lib/utils/document-audit-logs.ts index 287d4a823..58797510f 100644 --- a/packages/lib/utils/document-audit-logs.ts +++ b/packages/lib/utils/document-audit-logs.ts @@ -338,6 +338,10 @@ export const formatDocumentAuditLogAction = ( anonymous: msg`Document opened`, identified: msg`${prefix} opened the document`, })) + .with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_VIEWED }, () => ({ + anonymous: msg`Document viewed`, + identified: msg`${prefix} viewed the document`, + })) .with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_TITLE_UPDATED }, () => ({ anonymous: msg`Document title updated`, identified: msg`${prefix} updated the document title`, From 7487399123015cdc05c42c938c9268839f0ba369 Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Mon, 30 Jun 2025 19:46:32 +1000 Subject: [PATCH 08/17] feat: add more api logs (#1870) Adds more detailed API logging using Pino --- .env.example | 4 +- .gitignore | 3 + package-lock.json | 137 ------ packages/api/v1/implementation.ts | 445 +++++++++++------- packages/api/v1/middleware/authenticated.ts | 44 +- packages/lib/package.json | 1 - packages/lib/types/api-logs.ts | 29 ++ .../lib/universal/extract-request-metadata.ts | 14 +- packages/lib/utils/logger-legacy.ts | 112 ----- packages/lib/utils/logger.ts | 46 +- .../admin-router/create-admin-organisation.ts | 8 +- .../admin-router/create-stripe-customer.ts | 8 +- .../admin-router/create-subscription-claim.ts | 6 +- .../admin-router/delete-subscription-claim.ts | 8 +- .../admin-router/get-admin-organisation.ts | 8 +- packages/trpc/server/admin-router/router.ts | 108 ++++- .../admin-router/update-admin-organisation.ts | 8 +- .../admin-router/update-subscription-claim.ts | 6 +- .../trpc/server/api-token-router/router.ts | 13 + packages/trpc/server/auth-router/router.ts | 12 + .../server/billing/create-subscription.ts | 7 + packages/trpc/server/billing/get-invoices.ts | 6 + .../trpc/server/billing/get-subscription.ts | 6 + .../server/billing/manage-subscription.ts | 6 + packages/trpc/server/context.ts | 19 +- .../trpc/server/document-router/router.ts | 72 ++- .../server/document-router/update-document.ts | 6 + .../update-embedding-document.ts | 6 + .../update-embedding-template.ts | 6 + packages/trpc/server/field-router/router.ts | 96 ++++ packages/trpc/server/folder-router/router.ts | 78 ++- .../create-organisation-group.ts | 6 + .../create-organisation-member-invites.ts | 6 + .../create-organisation.ts | 6 + .../delete-organisation-group.ts | 7 + .../delete-organisation-member-invites.ts | 7 + .../delete-organisation-member.ts | 7 + .../delete-organisation-members.ts | 7 + .../delete-organisation.ts | 6 + .../find-organisation-groups.ts | 6 + .../find-organisation-member-invites.ts | 6 + .../organisation-router/get-organisation.ts | 6 + .../organisation-router/leave-organisation.ts | 7 +- .../resend-organisation-member-invite.ts | 7 + .../update-organisation-group.ts | 6 + .../update-organisation-members.ts | 7 + .../update-organisation-settings.ts | 6 + .../update-organisation.ts | 7 +- packages/trpc/server/profile-router/router.ts | 15 +- .../trpc/server/recipient-router/router.ts | 96 ++++ .../get-document-internal-url-for-qr-code.ts | 6 + .../trpc/server/share-link-router/router.ts | 6 + .../server/team-router/create-team-groups.ts | 7 + .../server/team-router/create-team-members.ts | 7 + .../trpc/server/team-router/create-team.ts | 6 + .../server/team-router/delete-team-group.ts | 7 + .../server/team-router/delete-team-member.ts | 7 + .../trpc/server/team-router/delete-team.ts | 6 + .../server/team-router/find-team-groups.ts | 7 + .../server/team-router/find-team-members.ts | 6 + .../trpc/server/team-router/find-teams.ts | 6 + .../server/team-router/get-team-members.ts | 6 + packages/trpc/server/team-router/get-team.ts | 10 +- packages/trpc/server/team-router/router.ts | 50 +- .../server/team-router/update-team-group.ts | 9 + .../server/team-router/update-team-member.ts | 7 + .../team-router/update-team-settings.ts | 6 + .../trpc/server/team-router/update-team.ts | 6 + .../trpc/server/template-router/router.ts | 76 ++- packages/trpc/server/trpc.ts | 84 +++- packages/trpc/server/webhook-router/router.ts | 33 ++ packages/trpc/utils/trpc-error-handler.ts | 26 +- packages/tsconfig/process-env.d.ts | 4 +- turbo.json | 2 +- 74 files changed, 1395 insertions(+), 544 deletions(-) create mode 100644 packages/lib/types/api-logs.ts delete mode 100644 packages/lib/utils/logger-legacy.ts diff --git a/.env.example b/.env.example index 15b0b3f5c..693f1d8a5 100644 --- a/.env.example +++ b/.env.example @@ -127,4 +127,6 @@ E2E_TEST_AUTHENTICATE_USER_EMAIL="testuser@mail.com" E2E_TEST_AUTHENTICATE_USER_PASSWORD="test_Password123" # [[LOGGER]] -NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY= +# OPTIONAL: The file to save the logger output to. Will disable stdout if provided. +NEXT_PRIVATE_LOGGER_FILE_PATH= + diff --git a/.gitignore b/.gitignore index b95fcc7d2..41ccab438 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,6 @@ yarn-error.log* !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json + +# logs +logs.json \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4ae9c4e1d..405ed6350 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3073,36 +3073,6 @@ "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==", "license": "MIT" }, - "node_modules/@honeybadger-io/core": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/@honeybadger-io/core/-/core-6.7.0.tgz", - "integrity": "sha512-bEXRe2UVbfr9q3434/2eO3AHguUT0froYEqrHfTPphR4Aw6+AlFac0YE8elqDZqUSgRQ6m1OXqxmq/HOF+W6LQ==", - "license": "MIT", - "dependencies": { - "json-nd": "^1.0.0", - "stacktrace-parser": "^0.1.10" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@honeybadger-io/js": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/@honeybadger-io/js/-/js-6.11.0.tgz", - "integrity": "sha512-nSibKUr9ccrs6Jb3Ql7uO/4MdEEv3ONGP1CrD0w3zSMHUvQKHe43NPYfESA7btxjrf9PVeV+m6ETP/193BSILg==", - "license": "MIT", - "dependencies": { - "@honeybadger-io/core": "^6.7.0", - "@types/aws-lambda": "^8.10.89", - "@types/express": "^4.17.13" - }, - "bin": { - "honeybadger-checkins-sync": "scripts/check-ins-sync-bin.js" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/@hono/node-server": { "version": "1.14.2", "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.14.2.tgz", @@ -11715,16 +11685,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, "node_modules/@types/bunyan": { "version": "1.8.11", "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.11.tgz", @@ -11845,30 +11805,6 @@ "@types/estree": "*" } }, - "node_modules/@types/express": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.22.tgz", - "integrity": "sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==", - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, "node_modules/@types/formidable": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-2.0.6.tgz", @@ -11898,12 +11834,6 @@ "hoist-non-react-statics": "^3.3.0" } }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "license": "MIT" - }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -11977,12 +11907,6 @@ "@types/node": "*" } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "license": "MIT" - }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -12070,12 +11994,6 @@ "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", "license": "MIT" }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", - "license": "MIT" - }, "node_modules/@types/ramda": { "version": "0.30.2", "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.30.2.tgz", @@ -12085,12 +12003,6 @@ "types-ramda": "^0.30.1" } }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "license": "MIT" - }, "node_modules/@types/react": { "version": "18.3.5", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz", @@ -12124,27 +12036,6 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "license": "MIT" }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "license": "MIT", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, "node_modules/@types/shimmer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", @@ -21899,12 +21790,6 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "license": "MIT" }, - "node_modules/json-nd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-nd/-/json-nd-1.0.0.tgz", - "integrity": "sha512-8TIp0HZAY0VVrwRQJJPb4+nOTSPoOWZeEKBTLizUfQO4oym5Fc/MKqN8vEbLCxcyxDf2vwNxOQ1q84O49GWPyQ==", - "license": "BSD-3-Clause" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -31491,27 +31376,6 @@ "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", "license": "MIT" }, - "node_modules/stacktrace-parser": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", - "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", - "license": "MIT", - "dependencies": { - "type-fest": "^0.7.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/stacktrace-parser/node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -36180,7 +36044,6 @@ "@documenso/email": "*", "@documenso/prisma": "*", "@documenso/signing": "*", - "@honeybadger-io/js": "^6.10.1", "@lingui/core": "^5.2.0", "@lingui/macro": "^5.2.0", "@lingui/react": "^5.2.0", diff --git a/packages/api/v1/implementation.ts b/packages/api/v1/implementation.ts index 819dc64b9..53becfeda 100644 --- a/packages/api/v1/implementation.ts +++ b/packages/api/v1/implementation.ts @@ -77,9 +77,15 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { }; }), - getDocument: authenticatedMiddleware(async (args, user, team) => { + getDocument: authenticatedMiddleware(async (args, user, team, { logger }) => { const { id: documentId } = args.params; + logger.info({ + input: { + id: documentId, + }, + }); + try { const document = await getDocumentById({ documentId: Number(documentId), @@ -139,10 +145,16 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - downloadSignedDocument: authenticatedMiddleware(async (args, user, team) => { + downloadSignedDocument: authenticatedMiddleware(async (args, user, team, { logger }) => { const { id: documentId } = args.params; const { downloadOriginalDocument } = args.query; + logger.info({ + input: { + id: documentId, + }, + }); + try { if (process.env.NEXT_PUBLIC_UPLOAD_TRANSPORT !== 's3') { return { @@ -204,9 +216,15 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - deleteDocument: authenticatedMiddleware(async (args, user, team, { metadata }) => { + deleteDocument: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId } = args.params; + logger.info({ + input: { + id: documentId, + }, + }); + try { const document = await getDocumentById({ documentId: Number(documentId), @@ -382,9 +400,15 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - deleteTemplate: authenticatedMiddleware(async (args, user, team) => { + deleteTemplate: authenticatedMiddleware(async (args, user, team, { logger }) => { const { id: templateId } = args.params; + logger.info({ + input: { + id: templateId, + }, + }); + try { const deletedTemplate = await deleteTemplate({ id: Number(templateId), @@ -406,9 +430,15 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - getTemplate: authenticatedMiddleware(async (args, user, team) => { + getTemplate: authenticatedMiddleware(async (args, user, team, { logger }) => { const { id: templateId } = args.params; + logger.info({ + input: { + id: templateId, + }, + }); + try { const template = await getTemplateById({ id: Number(templateId), @@ -463,202 +493,224 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - createDocumentFromTemplate: authenticatedMiddleware(async (args, user, team, { metadata }) => { - const { body, params } = args; + createDocumentFromTemplate: authenticatedMiddleware( + async (args, user, team, { logger, metadata }) => { + const { body, params } = args; - const { remaining } = await getServerLimits({ userId: user.id, teamId: team?.id }); - - if (remaining.documents <= 0) { - return { - status: 400, - body: { - message: 'You have reached the maximum number of documents allowed for this month', + logger.info({ + input: { + templateId: params.templateId, }, - }; - } - - const templateId = Number(params.templateId); - - const fileName = body.title.endsWith('.pdf') ? body.title : `${body.title}.pdf`; - - const document = await createDocumentFromTemplateLegacy({ - templateId, - userId: user.id, - teamId: team?.id, - recipients: body.recipients, - }); - - let documentDataId = document.documentDataId; - - if (body.formValues) { - const pdf = await getFileServerSide(document.documentData); - - const prefilled = await insertFormValuesInPdf({ - pdf: Buffer.from(pdf), - formValues: body.formValues, }); - const newDocumentData = await putPdfFileServerSide({ - name: fileName, - type: 'application/pdf', - arrayBuffer: async () => Promise.resolve(prefilled), - }); + const { remaining } = await getServerLimits({ userId: user.id, teamId: team?.id }); - documentDataId = newDocumentData.id; - } - - await updateDocument({ - documentId: document.id, - userId: user.id, - teamId: team?.id, - data: { - title: fileName, - externalId: body.externalId || null, - formValues: body.formValues, - documentData: { - connect: { - id: documentDataId, + if (remaining.documents <= 0) { + return { + status: 400, + body: { + message: 'You have reached the maximum number of documents allowed for this month', }, - }, - }, - }); + }; + } - if (body.meta) { - await upsertDocumentMeta({ - documentId: document.id, - userId: user.id, - teamId: team?.id, - ...body.meta, - requestMetadata: metadata, - }); - } + const templateId = Number(params.templateId); - if (body.authOptions) { - await updateDocumentSettings({ - documentId: document.id, - userId: user.id, - teamId: team?.id, - data: body.authOptions, - requestMetadata: metadata, - }); - } + const fileName = body.title.endsWith('.pdf') ? body.title : `${body.title}.pdf`; - return { - status: 200, - body: { - documentId: document.id, - recipients: document.recipients.map((recipient) => ({ - recipientId: recipient.id, - name: recipient.name, - email: recipient.email, - token: recipient.token, - role: recipient.role, - signingOrder: recipient.signingOrder, - - signingUrl: `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${recipient.token}`, - })), - }, - }; - }), - - generateDocumentFromTemplate: authenticatedMiddleware(async (args, user, team, { metadata }) => { - const { body, params } = args; - - const { remaining } = await getServerLimits({ userId: user.id, teamId: team?.id }); - - if (remaining.documents <= 0) { - return { - status: 400, - body: { - message: 'You have reached the maximum number of documents allowed for this month', - }, - }; - } - - const templateId = Number(params.templateId); - - let document: Awaited> | null = null; - - try { - document = await createDocumentFromTemplate({ + const document = await createDocumentFromTemplateLegacy({ templateId, - externalId: body.externalId || null, userId: user.id, teamId: team?.id, recipients: body.recipients, - prefillFields: body.prefillFields, - override: { - title: body.title, - ...body.meta, - }, - requestMetadata: metadata, - }); - } catch (err) { - return AppError.toRestAPIError(err); - } - - if (body.formValues) { - const fileName = document.title.endsWith('.pdf') ? document.title : `${document.title}.pdf`; - - const pdf = await getFileServerSide(document.documentData); - - const prefilled = await insertFormValuesInPdf({ - pdf: Buffer.from(pdf), - formValues: body.formValues, }); - const newDocumentData = await putPdfFileServerSide({ - name: fileName, - type: 'application/pdf', - arrayBuffer: async () => Promise.resolve(prefilled), - }); + let documentDataId = document.documentDataId; + + if (body.formValues) { + const pdf = await getFileServerSide(document.documentData); + + const prefilled = await insertFormValuesInPdf({ + pdf: Buffer.from(pdf), + formValues: body.formValues, + }); + + const newDocumentData = await putPdfFileServerSide({ + name: fileName, + type: 'application/pdf', + arrayBuffer: async () => Promise.resolve(prefilled), + }); + + documentDataId = newDocumentData.id; + } await updateDocument({ documentId: document.id, userId: user.id, teamId: team?.id, data: { + title: fileName, + externalId: body.externalId || null, formValues: body.formValues, documentData: { connect: { - id: newDocumentData.id, + id: documentDataId, }, }, }, }); - } - if (body.authOptions) { - await updateDocumentSettings({ - documentId: document.id, - userId: user.id, - teamId: team?.id, - data: body.authOptions, - requestMetadata: metadata, + if (body.meta) { + await upsertDocumentMeta({ + documentId: document.id, + userId: user.id, + teamId: team?.id, + ...body.meta, + requestMetadata: metadata, + }); + } + + if (body.authOptions) { + await updateDocumentSettings({ + documentId: document.id, + userId: user.id, + teamId: team?.id, + data: body.authOptions, + requestMetadata: metadata, + }); + } + + return { + status: 200, + body: { + documentId: document.id, + recipients: document.recipients.map((recipient) => ({ + recipientId: recipient.id, + name: recipient.name, + email: recipient.email, + token: recipient.token, + role: recipient.role, + signingOrder: recipient.signingOrder, + + signingUrl: `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${recipient.token}`, + })), + }, + }; + }, + ), + + generateDocumentFromTemplate: authenticatedMiddleware( + async (args, user, team, { logger, metadata }) => { + const { body, params } = args; + + logger.info({ + input: { + templateId: params.templateId, + }, }); - } - return { - status: 200, - body: { - documentId: document.id, - recipients: document.recipients.map((recipient) => ({ - recipientId: recipient.id, - name: recipient.name, - email: recipient.email, - token: recipient.token, - role: recipient.role, - signingOrder: recipient.signingOrder, - signingUrl: `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${recipient.token}`, - })), - }, - }; - }), + const { remaining } = await getServerLimits({ userId: user.id, teamId: team?.id }); - sendDocument: authenticatedMiddleware(async (args, user, team, { metadata }) => { + if (remaining.documents <= 0) { + return { + status: 400, + body: { + message: 'You have reached the maximum number of documents allowed for this month', + }, + }; + } + + const templateId = Number(params.templateId); + + let document: Awaited> | null = null; + + try { + document = await createDocumentFromTemplate({ + templateId, + externalId: body.externalId || null, + userId: user.id, + teamId: team?.id, + recipients: body.recipients, + prefillFields: body.prefillFields, + override: { + title: body.title, + ...body.meta, + }, + requestMetadata: metadata, + }); + } catch (err) { + return AppError.toRestAPIError(err); + } + + if (body.formValues) { + const fileName = document.title.endsWith('.pdf') ? document.title : `${document.title}.pdf`; + + const pdf = await getFileServerSide(document.documentData); + + const prefilled = await insertFormValuesInPdf({ + pdf: Buffer.from(pdf), + formValues: body.formValues, + }); + + const newDocumentData = await putPdfFileServerSide({ + name: fileName, + type: 'application/pdf', + arrayBuffer: async () => Promise.resolve(prefilled), + }); + + await updateDocument({ + documentId: document.id, + userId: user.id, + teamId: team?.id, + data: { + formValues: body.formValues, + documentData: { + connect: { + id: newDocumentData.id, + }, + }, + }, + }); + } + + if (body.authOptions) { + await updateDocumentSettings({ + documentId: document.id, + userId: user.id, + teamId: team?.id, + data: body.authOptions, + requestMetadata: metadata, + }); + } + + return { + status: 200, + body: { + documentId: document.id, + recipients: document.recipients.map((recipient) => ({ + recipientId: recipient.id, + name: recipient.name, + email: recipient.email, + token: recipient.token, + role: recipient.role, + signingOrder: recipient.signingOrder, + signingUrl: `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${recipient.token}`, + })), + }, + }; + }, + ), + + sendDocument: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId } = args.params; const { sendEmail, sendCompletionEmails } = args.body; + logger.info({ + input: { + id: documentId, + }, + }); + try { const document = await getDocumentById({ documentId: Number(documentId), @@ -730,10 +782,16 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - resendDocument: authenticatedMiddleware(async (args, user, team, { metadata }) => { + resendDocument: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId } = args.params; const { recipients } = args.body; + logger.info({ + input: { + id: documentId, + }, + }); + try { await resendDocument({ userId: user.id, @@ -759,10 +817,16 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - createRecipient: authenticatedMiddleware(async (args, user, team, { metadata }) => { + createRecipient: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId } = args.params; const { name, email, role, authOptions, signingOrder } = args.body; + logger.info({ + input: { + id: documentId, + }, + }); + const document = await getDocumentById({ documentId: Number(documentId), userId: user.id, @@ -850,10 +914,17 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - updateRecipient: authenticatedMiddleware(async (args, user, team, { metadata }) => { + updateRecipient: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId, recipientId } = args.params; const { name, email, role, authOptions, signingOrder } = args.body; + logger.info({ + input: { + id: documentId, + recipientId, + }, + }); + const document = await getDocumentById({ documentId: Number(documentId), userId: user.id, @@ -916,9 +987,16 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { }; }), - deleteRecipient: authenticatedMiddleware(async (args, user, team, { metadata }) => { + deleteRecipient: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId, recipientId } = args.params; + logger.info({ + input: { + id: documentId, + recipientId, + }, + }); + const document = await getDocumentById({ documentId: Number(documentId), userId: user.id, @@ -970,8 +1048,15 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { }; }), - createField: authenticatedMiddleware(async (args, user, team, { metadata }) => { + createField: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId } = args.params; + + logger.info({ + input: { + id: documentId, + }, + }); + const fields = Array.isArray(args.body) ? args.body : [args.body]; const document = await prisma.document.findFirst({ @@ -1131,11 +1216,18 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { } }), - updateField: authenticatedMiddleware(async (args, user, team, { metadata }) => { + updateField: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId, fieldId } = args.params; const { recipientId, type, pageNumber, pageWidth, pageHeight, pageX, pageY, fieldMeta } = args.body; + logger.info({ + input: { + id: documentId, + fieldId, + }, + }); + const document = await getDocumentById({ documentId: Number(documentId), userId: user.id, @@ -1222,9 +1314,16 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, { }; }), - deleteField: authenticatedMiddleware(async (args, user, team, { metadata }) => { + deleteField: authenticatedMiddleware(async (args, user, team, { logger, metadata }) => { const { id: documentId, fieldId } = args.params; + logger.info({ + input: { + id: documentId, + fieldId, + }, + }); + const document = await getDocumentById({ documentId: Number(documentId), userId: user.id, diff --git a/packages/api/v1/middleware/authenticated.ts b/packages/api/v1/middleware/authenticated.ts index 13366b42a..d83be7e8b 100644 --- a/packages/api/v1/middleware/authenticated.ts +++ b/packages/api/v1/middleware/authenticated.ts @@ -1,10 +1,13 @@ import type { Team, User } from '@prisma/client'; import type { TsRestRequest } from '@ts-rest/serverless'; +import type { Logger } from 'pino'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { getApiTokenByToken } from '@documenso/lib/server-only/public-api/get-api-token-by-token'; +import type { BaseApiLog, RootApiLog } from '@documenso/lib/types/api-logs'; import type { ApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; import { extractRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; +import { nanoid } from '@documenso/lib/universal/id'; import { logger } from '@documenso/lib/utils/logger'; type B = { @@ -28,10 +31,24 @@ export const authenticatedMiddleware = < args: T & { req: TsRestRequest }, user: Pick, team: Team, - options: { metadata: ApiRequestMetadata }, + options: { metadata: ApiRequestMetadata; logger: Logger }, ) => Promise, ) => { return async (args: T, { request }: B) => { + const requestMetadata = extractRequestMetadata(request); + + const apiLogger = logger.child({ + ipAddress: requestMetadata.ipAddress, + userAgent: requestMetadata.userAgent, + requestId: nanoid(), + } satisfies RootApiLog); + + const infoToLog: BaseApiLog = { + auth: 'api', + source: 'apiV1', + path: request.url, + }; + try { const { authorization } = args.headers; @@ -52,8 +69,14 @@ export const authenticatedMiddleware = < }); } + apiLogger.info({ + ...infoToLog, + userId: apiToken.user.id, + apiTokenId: apiToken.id, + } satisfies BaseApiLog); + const metadata: ApiRequestMetadata = { - requestMetadata: extractRequestMetadata(request), + requestMetadata, source: 'apiV1', auth: 'api', auditUser: { @@ -63,17 +86,6 @@ export const authenticatedMiddleware = < }, }; - // Todo: Get from Hono context instead. - logger.info({ - ipAddress: metadata.requestMetadata.ipAddress, - userAgent: metadata.requestMetadata.userAgent, - auth: 'api', - source: 'apiV1', - path: request.url, - userId: apiToken.user.id, - apiTokenId: apiToken.id, - }); - return await handler( { ...args, @@ -81,10 +93,12 @@ export const authenticatedMiddleware = < }, apiToken.user, apiToken.team, - { metadata }, + { metadata, logger: apiLogger }, ); } catch (err) { - console.log({ err: err }); + console.log({ err }); + + apiLogger.info(infoToLog); let message = 'Unauthorized'; diff --git a/packages/lib/package.json b/packages/lib/package.json index 3a06087bd..5d2a4053e 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -23,7 +23,6 @@ "@documenso/email": "*", "@documenso/prisma": "*", "@documenso/signing": "*", - "@honeybadger-io/js": "^6.10.1", "@lingui/core": "^5.2.0", "@lingui/macro": "^5.2.0", "@lingui/react": "^5.2.0", diff --git a/packages/lib/types/api-logs.ts b/packages/lib/types/api-logs.ts new file mode 100644 index 000000000..0a7db4966 --- /dev/null +++ b/packages/lib/types/api-logs.ts @@ -0,0 +1,29 @@ +import type { ApiRequestMetadata } from '../universal/extract-request-metadata'; + +/** + * The minimum required fields that the parent API logger must contain. + */ +export type RootApiLog = { + ipAddress?: string; + userAgent?: string; + requestId: string; +}; + +/** + * The minimum API log that must be logged at the start of every API request. + */ +export type BaseApiLog = Partial & { + path: string; + auth: ApiRequestMetadata['auth']; + source: ApiRequestMetadata['source']; + userId?: number | null; + apiTokenId?: number | null; +}; + +/** + * The TRPC API log. + */ +export type TrpcApiLog = BaseApiLog & { + trpcMiddleware: string; + unverifiedTeamId?: number | null; +}; diff --git a/packages/lib/universal/extract-request-metadata.ts b/packages/lib/universal/extract-request-metadata.ts index 6e24dc74a..c0aab29be 100644 --- a/packages/lib/universal/extract-request-metadata.ts +++ b/packages/lib/universal/extract-request-metadata.ts @@ -1,5 +1,7 @@ import { z } from 'zod'; +import { getIpAddress } from './get-ip-address'; + const ZIpSchema = z.string().ip(); export const ZRequestMetadataSchema = z.object({ @@ -40,11 +42,13 @@ export type ApiRequestMetadata = { }; export const extractRequestMetadata = (req: Request): RequestMetadata => { - const forwardedFor = req.headers.get('x-forwarded-for'); - const ip = forwardedFor - ?.split(',') - .map((ip) => ip.trim()) - .at(0); + let ip: string | undefined = undefined; + + try { + ip = getIpAddress(req); + } catch { + // Do nothing. + } const parsedIp = ZIpSchema.safeParse(ip); diff --git a/packages/lib/utils/logger-legacy.ts b/packages/lib/utils/logger-legacy.ts deleted file mode 100644 index b708f2bdd..000000000 --- a/packages/lib/utils/logger-legacy.ts +++ /dev/null @@ -1,112 +0,0 @@ -import Honeybadger from '@honeybadger-io/js'; - -import { env } from './env'; - -export const buildLogger = () => { - if (env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY')) { - return new HoneybadgerLogger(); - } - - return new DefaultLogger(); -}; - -interface LoggerDescriptionOptions { - method?: string; - path?: string; - context?: Record; - - /** - * The type of log to be captured. - * - * Defaults to `info`. - */ - level?: 'info' | 'error' | 'critical'; -} - -/** - * Basic logger implementation intended to be used in the server side for capturing - * explicit errors and other logs. - * - * Not intended to capture the request and responses. - */ -interface Logger { - log(message: string, options?: LoggerDescriptionOptions): void; - - error(error: Error, options?: LoggerDescriptionOptions): void; -} - -class DefaultLogger implements Logger { - log(_message: string, _options?: LoggerDescriptionOptions) { - // Do nothing. - } - - error(_error: Error, _options?: LoggerDescriptionOptions): void { - // Do nothing. - } -} - -class HoneybadgerLogger implements Logger { - constructor() { - if (!env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY')) { - throw new Error('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY is not set'); - } - - Honeybadger.configure({ - apiKey: env('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY'), - }); - } - - /** - * Honeybadger doesn't really have a non-error logging system. - */ - log(message: string, options?: LoggerDescriptionOptions) { - const { context = {}, level = 'info' } = options || {}; - - try { - Honeybadger.event({ - message, - context: { - level, - ...context, - }, - }); - } catch (err) { - console.error(err); - - // Do nothing. - } - } - - error(error: Error, options?: LoggerDescriptionOptions): void { - const { context = {}, level = 'error', method, path } = options || {}; - - // const tags = [`level:${level}`]; - const tags = []; - - let errorMessage = error.message; - - if (method) { - tags.push(`method:${method}`); - - errorMessage = `[${method}]: ${error.message}`; - } - - if (path) { - tags.push(`path:${path}`); - } - - try { - Honeybadger.notify(errorMessage, { - context: { - level, - ...context, - }, - tags, - }); - } catch (err) { - console.error(err); - - // Do nothing. - } - } -} diff --git a/packages/lib/utils/logger.ts b/packages/lib/utils/logger.ts index e60ab0142..8a76f270b 100644 --- a/packages/lib/utils/logger.ts +++ b/packages/lib/utils/logger.ts @@ -1,27 +1,35 @@ -import { pino } from 'pino'; +import { type TransportTargetOptions, pino } from 'pino'; -// const transports: TransportTargetOptions[] = []; +import { env } from './env'; -// if (env('NEXT_PRIVATE_LOGGING_DEV')) { -// transports.push({ -// target: 'pino-pretty', -// level: 'info', -// }); -// } +const transports: TransportTargetOptions[] = []; -// const loggingFilePath = env('NEXT_PRIVATE_LOGGING_FILE_PATH'); +if (env('NODE_ENV') !== 'production' && !env('INTERNAL_FORCE_JSON_LOGGER')) { + transports.push({ + target: 'pino-pretty', + level: 'info', + }); +} -// if (loggingFilePath) { -// transports.push({ -// target: 'pino/file', -// level: 'info', -// options: { -// destination: loggingFilePath, -// mkdir: true, -// }, -// }); -// } +const loggingFilePath = env('NEXT_PRIVATE_LOGGER_FILE_PATH'); + +if (loggingFilePath) { + transports.push({ + target: 'pino/file', + level: 'info', + options: { + destination: loggingFilePath, + mkdir: true, + }, + }); +} export const logger = pino({ level: 'info', + transport: + transports.length > 0 + ? { + targets: transports, + } + : undefined, }); diff --git a/packages/trpc/server/admin-router/create-admin-organisation.ts b/packages/trpc/server/admin-router/create-admin-organisation.ts index 1b7c4660d..e20df8854 100644 --- a/packages/trpc/server/admin-router/create-admin-organisation.ts +++ b/packages/trpc/server/admin-router/create-admin-organisation.ts @@ -12,9 +12,15 @@ import { export const createAdminOrganisationRoute = adminProcedure .input(ZCreateAdminOrganisationRequestSchema) .output(ZCreateAdminOrganisationResponseSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { ownerUserId, data } = input; + ctx.logger.info({ + input: { + ownerUserId, + }, + }); + const organisation = await createOrganisation({ userId: ownerUserId, name: data.name, diff --git a/packages/trpc/server/admin-router/create-stripe-customer.ts b/packages/trpc/server/admin-router/create-stripe-customer.ts index 7e68e6eaa..fc846e730 100644 --- a/packages/trpc/server/admin-router/create-stripe-customer.ts +++ b/packages/trpc/server/admin-router/create-stripe-customer.ts @@ -11,9 +11,15 @@ import { export const createStripeCustomerRoute = adminProcedure .input(ZCreateStripeCustomerRequestSchema) .output(ZCreateStripeCustomerResponseSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { organisationId } = input; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const organisation = await prisma.organisation.findUnique({ where: { id: organisationId, diff --git a/packages/trpc/server/admin-router/create-subscription-claim.ts b/packages/trpc/server/admin-router/create-subscription-claim.ts index 92fcbe0f5..b7b4a21e2 100644 --- a/packages/trpc/server/admin-router/create-subscription-claim.ts +++ b/packages/trpc/server/admin-router/create-subscription-claim.ts @@ -9,9 +9,13 @@ import { export const createSubscriptionClaimRoute = adminProcedure .input(ZCreateSubscriptionClaimRequestSchema) .output(ZCreateSubscriptionClaimResponseSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { name, teamCount, memberCount, flags } = input; + ctx.logger.info({ + input, + }); + await prisma.subscriptionClaim.create({ data: { name, diff --git a/packages/trpc/server/admin-router/delete-subscription-claim.ts b/packages/trpc/server/admin-router/delete-subscription-claim.ts index 41a3b93a8..183907087 100644 --- a/packages/trpc/server/admin-router/delete-subscription-claim.ts +++ b/packages/trpc/server/admin-router/delete-subscription-claim.ts @@ -10,9 +10,15 @@ import { export const deleteSubscriptionClaimRoute = adminProcedure .input(ZDeleteSubscriptionClaimRequestSchema) .output(ZDeleteSubscriptionClaimResponseSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { id } = input; + ctx.logger.info({ + input: { + id, + }, + }); + const existingClaim = await prisma.subscriptionClaim.findFirst({ where: { id, diff --git a/packages/trpc/server/admin-router/get-admin-organisation.ts b/packages/trpc/server/admin-router/get-admin-organisation.ts index d7ef4fd23..8990e0521 100644 --- a/packages/trpc/server/admin-router/get-admin-organisation.ts +++ b/packages/trpc/server/admin-router/get-admin-organisation.ts @@ -10,9 +10,15 @@ import { export const getAdminOrganisationRoute = adminProcedure .input(ZGetAdminOrganisationRequestSchema) .output(ZGetAdminOrganisationResponseSchema) - .query(async ({ input }) => { + .query(async ({ input, ctx }) => { const { organisationId } = input; + ctx.logger.info({ + input: { + organisationId, + }, + }); + return await getAdminOrganisation({ organisationId, }); diff --git a/packages/trpc/server/admin-router/router.ts b/packages/trpc/server/admin-router/router.ts index 08b49b38e..aca1a03d6 100644 --- a/packages/trpc/server/admin-router/router.ts +++ b/packages/trpc/server/admin-router/router.ts @@ -61,17 +61,30 @@ export const adminRouter = router({ updateUser: adminProcedure .input(ZAdminUpdateProfileMutationSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { id, name, email, roles } = input; + ctx.logger.info({ + input: { + id, + roles, + }, + }); + return await updateUser({ id, name, email, roles }); }), updateRecipient: adminProcedure .input(ZAdminUpdateRecipientMutationSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { id, name, email } = input; + ctx.logger.info({ + input: { + id, + }, + }); + return await updateRecipient({ id, name, email }); }), @@ -80,6 +93,12 @@ export const adminRouter = router({ .mutation(async ({ ctx, input }) => { const { id, enabled, data } = input; + ctx.logger.info({ + input: { + id, + }, + }); + return await upsertSiteSetting({ id, enabled, @@ -90,9 +109,15 @@ export const adminRouter = router({ resealDocument: adminProcedure .input(ZAdminResealDocumentMutationSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { id } = input; + ctx.logger.info({ + input: { + id, + }, + }); + const document = await getEntireDocument({ id }); const isResealing = isDocumentCompleted(document.status); @@ -100,44 +125,75 @@ export const adminRouter = router({ return await sealDocument({ documentId: id, isResealing }); }), - enableUser: adminProcedure.input(ZAdminEnableUserMutationSchema).mutation(async ({ input }) => { - const { id } = input; + enableUser: adminProcedure + .input(ZAdminEnableUserMutationSchema) + .mutation(async ({ input, ctx }) => { + const { id } = input; - const user = await getUserById({ id }).catch(() => null); - - if (!user) { - throw new AppError(AppErrorCode.NOT_FOUND, { - message: 'User not found', + ctx.logger.info({ + input: { + id, + }, }); - } - return await enableUser({ id }); - }), + const user = await getUserById({ id }).catch(() => null); - disableUser: adminProcedure.input(ZAdminDisableUserMutationSchema).mutation(async ({ input }) => { - const { id } = input; + if (!user) { + throw new AppError(AppErrorCode.NOT_FOUND, { + message: 'User not found', + }); + } - const user = await getUserById({ id }).catch(() => null); + return await enableUser({ id }); + }), - if (!user) { - throw new AppError(AppErrorCode.NOT_FOUND, { - message: 'User not found', + disableUser: adminProcedure + .input(ZAdminDisableUserMutationSchema) + .mutation(async ({ input, ctx }) => { + const { id } = input; + + ctx.logger.info({ + input: { + id, + }, }); - } - return await disableUser({ id }); - }), + const user = await getUserById({ id }).catch(() => null); - deleteUser: adminProcedure.input(ZAdminDeleteUserMutationSchema).mutation(async ({ input }) => { - const { id } = input; + if (!user) { + throw new AppError(AppErrorCode.NOT_FOUND, { + message: 'User not found', + }); + } - return await deleteUser({ id }); - }), + return await disableUser({ id }); + }), + + deleteUser: adminProcedure + .input(ZAdminDeleteUserMutationSchema) + .mutation(async ({ input, ctx }) => { + const { id } = input; + + ctx.logger.info({ + input: { + id, + }, + }); + + return await deleteUser({ id }); + }), deleteDocument: adminProcedure .input(ZAdminDeleteDocumentMutationSchema) .mutation(async ({ ctx, input }) => { const { id, reason } = input; + + ctx.logger.info({ + input: { + id, + }, + }); + await sendDeleteEmail({ documentId: id, reason }); return await superDeleteDocument({ diff --git a/packages/trpc/server/admin-router/update-admin-organisation.ts b/packages/trpc/server/admin-router/update-admin-organisation.ts index 25665a97b..6b4211939 100644 --- a/packages/trpc/server/admin-router/update-admin-organisation.ts +++ b/packages/trpc/server/admin-router/update-admin-organisation.ts @@ -10,9 +10,15 @@ import { export const updateAdminOrganisationRoute = adminProcedure .input(ZUpdateAdminOrganisationRequestSchema) .output(ZUpdateAdminOrganisationResponseSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { organisationId, data } = input; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const organisation = await prisma.organisation.findUnique({ where: { id: organisationId, diff --git a/packages/trpc/server/admin-router/update-subscription-claim.ts b/packages/trpc/server/admin-router/update-subscription-claim.ts index e3c1072f6..f5ac9f984 100644 --- a/packages/trpc/server/admin-router/update-subscription-claim.ts +++ b/packages/trpc/server/admin-router/update-subscription-claim.ts @@ -12,9 +12,13 @@ import { export const updateSubscriptionClaimRoute = adminProcedure .input(ZUpdateSubscriptionClaimRequestSchema) .output(ZUpdateSubscriptionClaimResponseSchema) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const { id, data } = input; + ctx.logger.info({ + input, + }); + const existingClaim = await prisma.subscriptionClaim.findUnique({ where: { id }, }); diff --git a/packages/trpc/server/api-token-router/router.ts b/packages/trpc/server/api-token-router/router.ts index 778c07b9a..f1439060c 100644 --- a/packages/trpc/server/api-token-router/router.ts +++ b/packages/trpc/server/api-token-router/router.ts @@ -15,6 +15,12 @@ export const apiTokenRouter = router({ .mutation(async ({ input, ctx }) => { const { tokenName, teamId, expirationDate } = input; + ctx.logger.info({ + input: { + teamId, + }, + }); + return await createApiToken({ userId: ctx.user.id, teamId, @@ -28,6 +34,13 @@ export const apiTokenRouter = router({ .mutation(async ({ input, ctx }) => { const { id, teamId } = input; + ctx.logger.info({ + input: { + id, + teamId, + }, + }); + return await deleteTokenById({ id, teamId, diff --git a/packages/trpc/server/auth-router/router.ts b/packages/trpc/server/auth-router/router.ts index b35fd160e..2eb54d1e6 100644 --- a/packages/trpc/server/auth-router/router.ts +++ b/packages/trpc/server/auth-router/router.ts @@ -66,6 +66,12 @@ export const authRouter = router({ .mutation(async ({ ctx, input }) => { const { passkeyId } = input; + ctx.logger.info({ + input: { + passkeyId, + }, + }); + await deletePasskey({ userId: ctx.user.id, passkeyId, @@ -91,6 +97,12 @@ export const authRouter = router({ .mutation(async ({ ctx, input }) => { const { passkeyId, name } = input; + ctx.logger.info({ + input: { + passkeyId, + }, + }); + await updatePasskey({ userId: ctx.user.id, passkeyId, diff --git a/packages/trpc/server/billing/create-subscription.ts b/packages/trpc/server/billing/create-subscription.ts index 8a0be6825..6de407902 100644 --- a/packages/trpc/server/billing/create-subscription.ts +++ b/packages/trpc/server/billing/create-subscription.ts @@ -14,6 +14,13 @@ export const createSubscriptionRoute = authenticatedProcedure .mutation(async ({ ctx, input }) => { const { organisationId, priceId } = input; + ctx.logger.info({ + input: { + organisationId, + priceId, + }, + }); + const userId = ctx.user.id; if (!IS_BILLING_ENABLED()) { diff --git a/packages/trpc/server/billing/get-invoices.ts b/packages/trpc/server/billing/get-invoices.ts index bc25a837c..7693d7559 100644 --- a/packages/trpc/server/billing/get-invoices.ts +++ b/packages/trpc/server/billing/get-invoices.ts @@ -13,6 +13,12 @@ export const getInvoicesRoute = authenticatedProcedure .query(async ({ ctx, input }) => { const { organisationId } = input; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const userId = ctx.user.id; if (!IS_BILLING_ENABLED()) { diff --git a/packages/trpc/server/billing/get-subscription.ts b/packages/trpc/server/billing/get-subscription.ts index 6c24dd455..9c7ffb4ea 100644 --- a/packages/trpc/server/billing/get-subscription.ts +++ b/packages/trpc/server/billing/get-subscription.ts @@ -11,6 +11,12 @@ export const getSubscriptionRoute = authenticatedProcedure .query(async ({ ctx, input }) => { const { organisationId } = input; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const userId = ctx.user.id; if (!IS_BILLING_ENABLED()) { diff --git a/packages/trpc/server/billing/manage-subscription.ts b/packages/trpc/server/billing/manage-subscription.ts index 2d215067a..de621ad06 100644 --- a/packages/trpc/server/billing/manage-subscription.ts +++ b/packages/trpc/server/billing/manage-subscription.ts @@ -14,6 +14,12 @@ export const manageSubscriptionRoute = authenticatedProcedure .mutation(async ({ ctx, input }) => { const { organisationId } = input; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const userId = ctx.user.id; if (!IS_BILLING_ENABLED()) { diff --git a/packages/trpc/server/context.ts b/packages/trpc/server/context.ts index a11cab223..ae319c4ce 100644 --- a/packages/trpc/server/context.ts +++ b/packages/trpc/server/context.ts @@ -5,8 +5,10 @@ import { z } from 'zod'; import type { SessionUser } from '@documenso/auth/server/lib/session/session'; import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session'; +import type { RootApiLog } from '@documenso/lib/types/api-logs'; import type { ApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; -import { extractRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; +import { alphaid } from '@documenso/lib/universal/id'; +import { logger } from '@documenso/lib/utils/logger'; // This is a bit nasty. Todo: Extract import type { HonoEnv } from '@documenso/remix/server/router'; @@ -22,16 +24,23 @@ export const createTrpcContext = async ({ const { session, user } = await getOptionalSession(c); const req = c.req.raw; - const logger = c.get('logger'); + + const requestMetadata = c.get('context').requestMetadata; const metadata: ApiRequestMetadata = { - requestMetadata: extractRequestMetadata(req), + requestMetadata, source: requestSource, auth: null, }; const rawTeamId = req.headers.get('x-team-id') || undefined; + const trpcLogger = logger.child({ + ipAddress: requestMetadata.ipAddress, + userAgent: requestMetadata.userAgent, + requestId: alphaid(), + } satisfies RootApiLog); + const teamId = z.coerce .number() .optional() @@ -40,7 +49,7 @@ export const createTrpcContext = async ({ if (!session || !user) { return { - logger, + logger: trpcLogger, session: null, user: null, teamId, @@ -50,7 +59,7 @@ export const createTrpcContext = async ({ } return { - logger, + logger: trpcLogger, session, user, teamId, diff --git a/packages/trpc/server/document-router/router.ts b/packages/trpc/server/document-router/router.ts index a2fa0467d..08cf6cd09 100644 --- a/packages/trpc/server/document-router/router.ts +++ b/packages/trpc/server/document-router/router.ts @@ -62,6 +62,7 @@ export const documentRouter = router({ find: findInboxRoute, getCount: getInboxCountRoute, }, + updateDocument: updateDocumentRoute, /** * @private @@ -72,6 +73,12 @@ export const documentRouter = router({ const { teamId } = ctx; const { documentId } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await getDocumentById({ userId: ctx.user.id, teamId, @@ -231,6 +238,13 @@ export const documentRouter = router({ const { teamId, user } = ctx; const { documentId, folderId } = input; + ctx.logger.info({ + input: { + documentId, + folderId, + }, + }); + return await getDocumentWithDetailsById({ userId: user.id, teamId, @@ -332,6 +346,12 @@ export const documentRouter = router({ const { user, teamId } = ctx; const { title, documentDataId, timezone, folderId } = input; + ctx.logger.info({ + input: { + folderId, + }, + }); + const { remaining } = await getServerLimits({ userId: user.id, teamId }); if (remaining.documents <= 0) { @@ -353,8 +373,6 @@ export const documentRouter = router({ }); }), - updateDocument: updateDocumentRoute, - /** * @public */ @@ -373,6 +391,12 @@ export const documentRouter = router({ const { teamId } = ctx; const { documentId } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + const userId = ctx.user.id; await deleteDocument({ @@ -396,6 +420,13 @@ export const documentRouter = router({ const { teamId } = ctx; const { documentId, signingOrder } = input; + ctx.logger.info({ + input: { + documentId, + signingOrder, + }, + }); + return await upsertDocumentMeta({ userId: ctx.user.id, teamId, @@ -427,6 +458,12 @@ export const documentRouter = router({ const { teamId } = ctx; const { documentId, meta = {} } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + if (Object.values(meta).length > 0) { await upsertDocumentMeta({ userId: ctx.user.id, @@ -474,6 +511,13 @@ export const documentRouter = router({ const { teamId } = ctx; const { documentId, recipients } = input; + ctx.logger.info({ + input: { + documentId, + recipients, + }, + }); + await resendDocument({ userId: ctx.user.id, teamId, @@ -503,6 +547,12 @@ export const documentRouter = router({ const { teamId, user } = ctx; const { documentId } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await duplicateDocument({ userId: user.id, teamId, @@ -544,6 +594,12 @@ export const documentRouter = router({ orderByDirection, } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await findDocumentAuditLogs({ userId: ctx.user.id, teamId, @@ -565,6 +621,12 @@ export const documentRouter = router({ const { teamId } = ctx; const { documentId } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + const document = await getDocumentById({ documentId, userId: ctx.user.id, @@ -597,6 +659,12 @@ export const documentRouter = router({ const { teamId } = ctx; const { documentId } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + const document = await getDocumentById({ documentId, userId: ctx.user.id, diff --git a/packages/trpc/server/document-router/update-document.ts b/packages/trpc/server/document-router/update-document.ts index ed2ca6acd..b60a592bb 100644 --- a/packages/trpc/server/document-router/update-document.ts +++ b/packages/trpc/server/document-router/update-document.ts @@ -19,6 +19,12 @@ export const updateDocumentRoute = authenticatedProcedure const { teamId } = ctx; const { documentId, data, meta = {} } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + const userId = ctx.user.id; if (Object.values(meta).length > 0) { diff --git a/packages/trpc/server/embedding-router/update-embedding-document.ts b/packages/trpc/server/embedding-router/update-embedding-document.ts index 9060b09ec..cd8dc305c 100644 --- a/packages/trpc/server/embedding-router/update-embedding-document.ts +++ b/packages/trpc/server/embedding-router/update-embedding-document.ts @@ -16,6 +16,12 @@ export const updateEmbeddingDocumentRoute = procedure .input(ZUpdateEmbeddingDocumentRequestSchema) .output(ZUpdateEmbeddingDocumentResponseSchema) .mutation(async ({ input, ctx }) => { + ctx.logger.info({ + input: { + documentId: input.documentId, + }, + }); + try { const authorizationHeader = ctx.req.headers.get('authorization'); diff --git a/packages/trpc/server/embedding-router/update-embedding-template.ts b/packages/trpc/server/embedding-router/update-embedding-template.ts index 52dca3004..38bf2a27a 100644 --- a/packages/trpc/server/embedding-router/update-embedding-template.ts +++ b/packages/trpc/server/embedding-router/update-embedding-template.ts @@ -15,6 +15,12 @@ export const updateEmbeddingTemplateRoute = procedure .input(ZUpdateEmbeddingTemplateRequestSchema) .output(ZUpdateEmbeddingTemplateResponseSchema) .mutation(async ({ input, ctx }) => { + ctx.logger.info({ + input: { + templateId: input.templateId, + }, + }); + try { const authorizationHeader = ctx.req.headers.get('authorization'); diff --git a/packages/trpc/server/field-router/router.ts b/packages/trpc/server/field-router/router.ts index 236afc360..1e022749c 100644 --- a/packages/trpc/server/field-router/router.ts +++ b/packages/trpc/server/field-router/router.ts @@ -62,6 +62,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { fieldId } = input; + ctx.logger.info({ + input: { + fieldId, + }, + }); + return await getFieldById({ userId: ctx.user.id, teamId, @@ -88,6 +94,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { documentId, field } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + const createdFields = await createDocumentFields({ userId: ctx.user.id, teamId, @@ -118,6 +130,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { documentId, fields } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await createDocumentFields({ userId: ctx.user.id, teamId, @@ -146,6 +164,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { documentId, field } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + const updatedFields = await updateDocumentFields({ userId: ctx.user.id, teamId, @@ -176,6 +200,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { documentId, fields } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await updateDocumentFields({ userId: ctx.user.id, teamId, @@ -203,6 +233,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { fieldId } = input; + ctx.logger.info({ + input: { + fieldId, + }, + }); + await deleteDocumentField({ userId: ctx.user.id, teamId, @@ -225,6 +261,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { documentId, fields } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await setFieldsForDocument({ documentId, userId: ctx.user.id, @@ -263,6 +305,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { templateId, field } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + const createdFields = await createTemplateFields({ userId: ctx.user.id, teamId, @@ -293,6 +341,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { fieldId } = input; + ctx.logger.info({ + input: { + fieldId, + }, + }); + return await getFieldById({ userId: ctx.user.id, teamId, @@ -319,6 +373,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { templateId, fields } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await createTemplateFields({ userId: ctx.user.id, teamId, @@ -346,6 +406,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { templateId, field } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + const updatedFields = await updateTemplateFields({ userId: ctx.user.id, teamId, @@ -375,6 +441,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { templateId, fields } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await updateTemplateFields({ userId: ctx.user.id, teamId, @@ -401,6 +473,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { fieldId } = input; + ctx.logger.info({ + input: { + fieldId, + }, + }); + await deleteTemplateField({ userId: ctx.user.id, teamId, @@ -422,6 +500,12 @@ export const fieldRouter = router({ const { teamId } = ctx; const { templateId, fields } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await setFieldsForTemplate({ templateId, userId: ctx.user.id, @@ -448,6 +532,12 @@ export const fieldRouter = router({ .mutation(async ({ input, ctx }) => { const { token, fieldId, value, isBase64, authOptions } = input; + ctx.logger.info({ + input: { + fieldId, + }, + }); + return await signFieldWithToken({ token, fieldId, @@ -467,6 +557,12 @@ export const fieldRouter = router({ .mutation(async ({ input, ctx }) => { const { token, fieldId } = input; + ctx.logger.info({ + input: { + fieldId, + }, + }); + return await removeSignedFieldWithToken({ token, fieldId, diff --git a/packages/trpc/server/folder-router/router.ts b/packages/trpc/server/folder-router/router.ts index fb3883481..f27998c84 100644 --- a/packages/trpc/server/folder-router/router.ts +++ b/packages/trpc/server/folder-router/router.ts @@ -42,6 +42,13 @@ export const folderRouter = router({ const { teamId, user } = ctx; const { parentId, type } = input; + ctx.logger.info({ + input: { + parentId, + type, + }, + }); + const folders = await findFolders({ userId: user.id, teamId, @@ -75,6 +82,13 @@ export const folderRouter = router({ const { teamId, user } = ctx; const { parentId, type } = input; + ctx.logger.info({ + input: { + parentId, + type, + }, + }); + const folders = await findFolders({ userId: user.id, teamId, @@ -107,6 +121,13 @@ export const folderRouter = router({ const { teamId, user } = ctx; const { name, parentId, type } = input; + ctx.logger.info({ + input: { + parentId, + type, + }, + }); + if (parentId) { try { await getFolderById({ @@ -146,6 +167,12 @@ export const folderRouter = router({ const { teamId, user } = ctx; const { id, name, visibility } = input; + ctx.logger.info({ + input: { + id, + }, + }); + const currentFolder = await getFolderById({ userId: user.id, teamId, @@ -177,6 +204,12 @@ export const folderRouter = router({ const { teamId, user } = ctx; const { id } = input; + ctx.logger.info({ + input: { + id, + }, + }); + await deleteFolder({ userId: user.id, teamId, @@ -193,6 +226,13 @@ export const folderRouter = router({ const { teamId, user } = ctx; const { id, parentId } = input; + ctx.logger.info({ + input: { + id, + parentId, + }, + }); + const currentFolder = await getFolderById({ userId: user.id, teamId, @@ -238,6 +278,13 @@ export const folderRouter = router({ const { teamId, user } = ctx; const { documentId, folderId } = input; + ctx.logger.info({ + input: { + documentId, + folderId, + }, + }); + if (folderId !== null) { try { await getFolderById({ @@ -277,6 +324,13 @@ export const folderRouter = router({ const { teamId, user } = ctx; const { templateId, folderId } = input; + ctx.logger.info({ + input: { + templateId, + folderId, + }, + }); + if (folderId !== null) { try { await getFolderById({ @@ -310,16 +364,24 @@ export const folderRouter = router({ * @private */ pinFolder: authenticatedProcedure.input(ZPinFolderSchema).mutation(async ({ ctx, input }) => { + const { folderId } = input; + + ctx.logger.info({ + input: { + folderId, + }, + }); + const currentFolder = await getFolderById({ userId: ctx.user.id, teamId: ctx.teamId, - folderId: input.folderId, + folderId, }); const result = await pinFolder({ userId: ctx.user.id, teamId: ctx.teamId, - folderId: input.folderId, + folderId, type: currentFolder.type, }); @@ -333,16 +395,24 @@ export const folderRouter = router({ * @private */ unpinFolder: authenticatedProcedure.input(ZUnpinFolderSchema).mutation(async ({ ctx, input }) => { + const { folderId } = input; + + ctx.logger.info({ + input: { + folderId, + }, + }); + const currentFolder = await getFolderById({ userId: ctx.user.id, teamId: ctx.teamId, - folderId: input.folderId, + folderId, }); const result = await unpinFolder({ userId: ctx.user.id, teamId: ctx.teamId, - folderId: input.folderId, + folderId, type: currentFolder.type, }); diff --git a/packages/trpc/server/organisation-router/create-organisation-group.ts b/packages/trpc/server/organisation-router/create-organisation-group.ts index 9f148764d..b2dc3cde9 100644 --- a/packages/trpc/server/organisation-router/create-organisation-group.ts +++ b/packages/trpc/server/organisation-router/create-organisation-group.ts @@ -24,6 +24,12 @@ export const createOrganisationGroupRoute = authenticatedProcedure const { organisationId, organisationRole, name, memberIds } = input; const { user } = ctx; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const organisation = await prisma.organisation.findFirst({ where: buildOrganisationWhereQuery({ organisationId, diff --git a/packages/trpc/server/organisation-router/create-organisation-member-invites.ts b/packages/trpc/server/organisation-router/create-organisation-member-invites.ts index 0178570e0..e468ce6fa 100644 --- a/packages/trpc/server/organisation-router/create-organisation-member-invites.ts +++ b/packages/trpc/server/organisation-router/create-organisation-member-invites.ts @@ -14,6 +14,12 @@ export const createOrganisationMemberInvitesRoute = authenticatedProcedure const userId = ctx.user.id; const userName = ctx.user.name || ''; + ctx.logger.info({ + input: { + organisationId, + }, + }); + await createOrganisationMemberInvites({ userId, userName, diff --git a/packages/trpc/server/organisation-router/create-organisation.ts b/packages/trpc/server/organisation-router/create-organisation.ts index 39086b55e..c4c02f9df 100644 --- a/packages/trpc/server/organisation-router/create-organisation.ts +++ b/packages/trpc/server/organisation-router/create-organisation.ts @@ -23,6 +23,12 @@ export const createOrganisationRoute = authenticatedProcedure const { name, priceId } = input; const { user } = ctx; + ctx.logger.info({ + input: { + priceId, + }, + }); + // Check if user can create a free organiastion. if (IS_BILLING_ENABLED() && !priceId) { const userOrganisations = await prisma.organisation.findMany({ diff --git a/packages/trpc/server/organisation-router/delete-organisation-group.ts b/packages/trpc/server/organisation-router/delete-organisation-group.ts index cf8d0bae9..3b5aadbff 100644 --- a/packages/trpc/server/organisation-router/delete-organisation-group.ts +++ b/packages/trpc/server/organisation-router/delete-organisation-group.ts @@ -19,6 +19,13 @@ export const deleteOrganisationGroupRoute = authenticatedProcedure const { groupId, organisationId } = input; const { user } = ctx; + ctx.logger.info({ + input: { + groupId, + organisationId, + }, + }); + const organisation = await prisma.organisation.findFirst({ where: buildOrganisationWhereQuery({ organisationId, diff --git a/packages/trpc/server/organisation-router/delete-organisation-member-invites.ts b/packages/trpc/server/organisation-router/delete-organisation-member-invites.ts index 44d30e097..2e07e1c98 100644 --- a/packages/trpc/server/organisation-router/delete-organisation-member-invites.ts +++ b/packages/trpc/server/organisation-router/delete-organisation-member-invites.ts @@ -19,6 +19,13 @@ export const deleteOrganisationMemberInvitesRoute = authenticatedProcedure const { organisationId, invitationIds } = input; const userId = ctx.user.id; + ctx.logger.info({ + input: { + organisationId, + invitationIds, + }, + }); + const organisation = await prisma.organisation.findFirst({ where: buildOrganisationWhereQuery({ organisationId, diff --git a/packages/trpc/server/organisation-router/delete-organisation-member.ts b/packages/trpc/server/organisation-router/delete-organisation-member.ts index 5da41bf1e..36ff79a20 100644 --- a/packages/trpc/server/organisation-router/delete-organisation-member.ts +++ b/packages/trpc/server/organisation-router/delete-organisation-member.ts @@ -13,6 +13,13 @@ export const deleteOrganisationMemberRoute = authenticatedProcedure const { organisationId, organisationMemberId } = input; const userId = ctx.user.id; + ctx.logger.info({ + input: { + organisationId, + organisationMemberId, + }, + }); + await deleteOrganisationMembers({ userId, organisationId, diff --git a/packages/trpc/server/organisation-router/delete-organisation-members.ts b/packages/trpc/server/organisation-router/delete-organisation-members.ts index 876111913..a73991772 100644 --- a/packages/trpc/server/organisation-router/delete-organisation-members.ts +++ b/packages/trpc/server/organisation-router/delete-organisation-members.ts @@ -21,6 +21,13 @@ export const deleteOrganisationMembersRoute = authenticatedProcedure const { organisationId, organisationMemberIds } = input; const userId = ctx.user.id; + ctx.logger.info({ + input: { + organisationId, + organisationMemberIds, + }, + }); + await deleteOrganisationMembers({ userId, organisationId, diff --git a/packages/trpc/server/organisation-router/delete-organisation.ts b/packages/trpc/server/organisation-router/delete-organisation.ts index 692368cce..edf7952d4 100644 --- a/packages/trpc/server/organisation-router/delete-organisation.ts +++ b/packages/trpc/server/organisation-router/delete-organisation.ts @@ -17,6 +17,12 @@ export const deleteOrganisationRoute = authenticatedProcedure const { organisationId } = input; const { user } = ctx; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const organisation = await prisma.organisation.findFirst({ where: buildOrganisationWhereQuery({ organisationId, diff --git a/packages/trpc/server/organisation-router/find-organisation-groups.ts b/packages/trpc/server/organisation-router/find-organisation-groups.ts index 1d6e39f95..8dee920e0 100644 --- a/packages/trpc/server/organisation-router/find-organisation-groups.ts +++ b/packages/trpc/server/organisation-router/find-organisation-groups.ts @@ -21,6 +21,12 @@ export const findOrganisationGroupsRoute = authenticatedProcedure input; const { user } = ctx; + ctx.logger.info({ + input: { + organisationId, + }, + }); + return await findOrganisationGroups({ userId: user.id, organisationId, diff --git a/packages/trpc/server/organisation-router/find-organisation-member-invites.ts b/packages/trpc/server/organisation-router/find-organisation-member-invites.ts index 29fe5369a..6c1b49b57 100644 --- a/packages/trpc/server/organisation-router/find-organisation-member-invites.ts +++ b/packages/trpc/server/organisation-router/find-organisation-member-invites.ts @@ -21,6 +21,12 @@ export const findOrganisationMemberInvitesRoute = authenticatedProcedure const { organisationId, query, page, perPage, status } = input; const { user } = ctx; + ctx.logger.info({ + input: { + organisationId, + }, + }); + return await findOrganisationMemberInvites({ userId: user.id, organisationId, diff --git a/packages/trpc/server/organisation-router/get-organisation.ts b/packages/trpc/server/organisation-router/get-organisation.ts index 51037550e..da8b0df6c 100644 --- a/packages/trpc/server/organisation-router/get-organisation.ts +++ b/packages/trpc/server/organisation-router/get-organisation.ts @@ -14,6 +14,12 @@ export const getOrganisationRoute = authenticatedProcedure .query(async ({ input, ctx }) => { const { organisationReference } = input; + ctx.logger.info({ + input: { + organisationReference, + }, + }); + return await getOrganisation({ userId: ctx.user.id, organisationReference, diff --git a/packages/trpc/server/organisation-router/leave-organisation.ts b/packages/trpc/server/organisation-router/leave-organisation.ts index c925adc6b..f203c61bb 100644 --- a/packages/trpc/server/organisation-router/leave-organisation.ts +++ b/packages/trpc/server/organisation-router/leave-organisation.ts @@ -17,9 +17,14 @@ export const leaveOrganisationRoute = authenticatedProcedure .output(ZLeaveOrganisationResponseSchema) .mutation(async ({ ctx, input }) => { const { organisationId } = input; - const userId = ctx.user.id; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const organisation = await prisma.organisation.findFirst({ where: buildOrganisationWhereQuery({ organisationId, userId }), include: { diff --git a/packages/trpc/server/organisation-router/resend-organisation-member-invite.ts b/packages/trpc/server/organisation-router/resend-organisation-member-invite.ts index 9dbae3b2c..b3c2bdc68 100644 --- a/packages/trpc/server/organisation-router/resend-organisation-member-invite.ts +++ b/packages/trpc/server/organisation-router/resend-organisation-member-invite.ts @@ -20,6 +20,13 @@ export const resendOrganisationMemberInviteRoute = authenticatedProcedure const userId = ctx.user.id; const userName = ctx.user.name || ''; + ctx.logger.info({ + input: { + organisationId, + invitationId, + }, + }); + await resendOrganisationMemberInvitation({ userId, userName, diff --git a/packages/trpc/server/organisation-router/update-organisation-group.ts b/packages/trpc/server/organisation-router/update-organisation-group.ts index 3eef706d3..cb5c3e1c4 100644 --- a/packages/trpc/server/organisation-router/update-organisation-group.ts +++ b/packages/trpc/server/organisation-router/update-organisation-group.ts @@ -25,6 +25,12 @@ export const updateOrganisationGroupRoute = authenticatedProcedure const { id, ...data } = input; const { user } = ctx; + ctx.logger.info({ + input: { + id, + }, + }); + const organisationGroup = await prisma.organisationGroup.findFirst({ where: { id, diff --git a/packages/trpc/server/organisation-router/update-organisation-members.ts b/packages/trpc/server/organisation-router/update-organisation-members.ts index 20bd2a1b9..7309aad77 100644 --- a/packages/trpc/server/organisation-router/update-organisation-members.ts +++ b/packages/trpc/server/organisation-router/update-organisation-members.ts @@ -24,6 +24,13 @@ export const updateOrganisationMemberRoute = authenticatedProcedure const { organisationId, organisationMemberId, data } = input; const userId = ctx.user.id; + ctx.logger.info({ + input: { + organisationId, + organisationMemberId, + }, + }); + const organisation = await prisma.organisation.findFirst({ where: buildOrganisationWhereQuery({ organisationId, diff --git a/packages/trpc/server/organisation-router/update-organisation-settings.ts b/packages/trpc/server/organisation-router/update-organisation-settings.ts index 114d8d0a0..09061bf07 100644 --- a/packages/trpc/server/organisation-router/update-organisation-settings.ts +++ b/packages/trpc/server/organisation-router/update-organisation-settings.ts @@ -16,6 +16,12 @@ export const updateOrganisationSettingsRoute = authenticatedProcedure const { user } = ctx; const { organisationId, data } = input; + ctx.logger.info({ + input: { + organisationId, + }, + }); + const { // Document related settings. documentVisibility, diff --git a/packages/trpc/server/organisation-router/update-organisation.ts b/packages/trpc/server/organisation-router/update-organisation.ts index 8179315ed..bc71b9de0 100644 --- a/packages/trpc/server/organisation-router/update-organisation.ts +++ b/packages/trpc/server/organisation-router/update-organisation.ts @@ -15,9 +15,14 @@ export const updateOrganisationRoute = authenticatedProcedure .output(ZUpdateOrganisationResponseSchema) .mutation(async ({ input, ctx }) => { const { organisationId, data } = input; - const userId = ctx.user.id; + ctx.logger.info({ + input: { + organisationId, + }, + }); + // Check if organisation exists and user has access to it const existingOrganisation = await prisma.organisation.findFirst({ where: buildOrganisationWhereQuery({ diff --git a/packages/trpc/server/profile-router/router.ts b/packages/trpc/server/profile-router/router.ts index cabbbd643..927409817 100644 --- a/packages/trpc/server/profile-router/router.ts +++ b/packages/trpc/server/profile-router/router.ts @@ -23,9 +23,15 @@ export const profileRouter = router({ }); }), - getUser: adminProcedure.input(ZRetrieveUserByIdQuerySchema).query(async ({ input }) => { + getUser: adminProcedure.input(ZRetrieveUserByIdQuerySchema).query(async ({ input, ctx }) => { const { id } = input; + ctx.logger.info({ + input: { + id, + }, + }); + return await getUserById({ id }); }), @@ -53,6 +59,13 @@ export const profileRouter = router({ .mutation(async ({ input, ctx }) => { const { bytes, teamId, organisationId } = input; + ctx.logger.info({ + input: { + teamId, + organisationId, + }, + }); + let target: SetAvatarImageOptions['target'] = { type: 'user', }; diff --git a/packages/trpc/server/recipient-router/router.ts b/packages/trpc/server/recipient-router/router.ts index 03dcc0fe5..dc66306e7 100644 --- a/packages/trpc/server/recipient-router/router.ts +++ b/packages/trpc/server/recipient-router/router.ts @@ -62,6 +62,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { recipientId } = input; + ctx.logger.info({ + input: { + recipientId, + }, + }); + return await getRecipientById({ userId: ctx.user.id, teamId, @@ -88,6 +94,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { documentId, recipient } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + const createdRecipients = await createDocumentRecipients({ userId: ctx.user.id, teamId, @@ -118,6 +130,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { documentId, recipients } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await createDocumentRecipients({ userId: ctx.user.id, teamId, @@ -146,6 +164,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { documentId, recipient } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + const updatedRecipients = await updateDocumentRecipients({ userId: ctx.user.id, teamId, @@ -176,6 +200,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { documentId, recipients } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await updateDocumentRecipients({ userId: ctx.user.id, teamId, @@ -203,6 +233,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { recipientId } = input; + ctx.logger.info({ + input: { + recipientId, + }, + }); + await deleteDocumentRecipient({ userId: ctx.user.id, teamId, @@ -223,6 +259,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { documentId, recipients } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await setDocumentRecipients({ userId: ctx.user.id, teamId, @@ -259,6 +301,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { recipientId } = input; + ctx.logger.info({ + input: { + recipientId, + }, + }); + return await getRecipientById({ userId: ctx.user.id, teamId, @@ -285,6 +333,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { templateId, recipient } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + const createdRecipients = await createTemplateRecipients({ userId: ctx.user.id, teamId, @@ -314,6 +368,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { templateId, recipients } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await createTemplateRecipients({ userId: ctx.user.id, teamId, @@ -341,6 +401,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { templateId, recipient } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + const updatedRecipients = await updateTemplateRecipients({ userId: ctx.user.id, teamId, @@ -370,6 +436,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { templateId, recipients } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await updateTemplateRecipients({ userId: ctx.user.id, teamId, @@ -396,6 +468,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { recipientId } = input; + ctx.logger.info({ + input: { + recipientId, + }, + }); + await deleteTemplateRecipient({ recipientId, userId: ctx.user.id, @@ -415,6 +493,12 @@ export const recipientRouter = router({ const { teamId } = ctx; const { templateId, recipients } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await setTemplateRecipients({ userId: ctx.user.id, teamId, @@ -438,6 +522,12 @@ export const recipientRouter = router({ .mutation(async ({ input, ctx }) => { const { token, documentId, authOptions, nextSigner } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await completeDocumentWithToken({ token, documentId, @@ -456,6 +546,12 @@ export const recipientRouter = router({ .mutation(async ({ input, ctx }) => { const { token, documentId, reason } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + return await rejectDocumentWithToken({ token, documentId, diff --git a/packages/trpc/server/share-link-router/get-document-internal-url-for-qr-code.ts b/packages/trpc/server/share-link-router/get-document-internal-url-for-qr-code.ts index 40054877a..20764d89d 100644 --- a/packages/trpc/server/share-link-router/get-document-internal-url-for-qr-code.ts +++ b/packages/trpc/server/share-link-router/get-document-internal-url-for-qr-code.ts @@ -14,6 +14,12 @@ export const getDocumentInternalUrlForQRCodeRoute = procedure .query(async ({ input, ctx }) => { const { documentId } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + if (!ctx.user) { return null; } diff --git a/packages/trpc/server/share-link-router/router.ts b/packages/trpc/server/share-link-router/router.ts index f10424cae..3f8ac695f 100644 --- a/packages/trpc/server/share-link-router/router.ts +++ b/packages/trpc/server/share-link-router/router.ts @@ -10,6 +10,12 @@ export const shareLinkRouter = router({ .mutation(async ({ ctx, input }) => { const { documentId, token } = input; + ctx.logger.info({ + input: { + documentId, + }, + }); + if (token) { return await createOrGetShareLink({ documentId, token }); } diff --git a/packages/trpc/server/team-router/create-team-groups.ts b/packages/trpc/server/team-router/create-team-groups.ts index 415125fb6..162bd57c3 100644 --- a/packages/trpc/server/team-router/create-team-groups.ts +++ b/packages/trpc/server/team-router/create-team-groups.ts @@ -27,6 +27,13 @@ export const createTeamGroupsRoute = authenticatedProcedure const { teamId, groups } = input; const { user } = ctx; + ctx.logger.info({ + input: { + teamId, + groups, + }, + }); + const team = await prisma.team.findFirst({ where: buildTeamWhereQuery({ teamId, diff --git a/packages/trpc/server/team-router/create-team-members.ts b/packages/trpc/server/team-router/create-team-members.ts index 296a74dc9..dc7d4d756 100644 --- a/packages/trpc/server/team-router/create-team-members.ts +++ b/packages/trpc/server/team-router/create-team-members.ts @@ -21,6 +21,13 @@ export const createTeamMembersRoute = authenticatedProcedure const { teamId, organisationMembers } = input; const { user } = ctx; + ctx.logger.info({ + input: { + teamId, + organisationMembers, + }, + }); + return await createTeamMembers({ userId: user.id, teamId, diff --git a/packages/trpc/server/team-router/create-team.ts b/packages/trpc/server/team-router/create-team.ts index c9422d864..927276402 100644 --- a/packages/trpc/server/team-router/create-team.ts +++ b/packages/trpc/server/team-router/create-team.ts @@ -11,6 +11,12 @@ export const createTeamRoute = authenticatedProcedure const { teamName, teamUrl, organisationId, inheritMembers } = input; const { user } = ctx; + ctx.logger.info({ + input: { + organisationId, + }, + }); + return await createTeam({ userId: user.id, teamName, diff --git a/packages/trpc/server/team-router/delete-team-group.ts b/packages/trpc/server/team-router/delete-team-group.ts index 6cc396536..ae8005770 100644 --- a/packages/trpc/server/team-router/delete-team-group.ts +++ b/packages/trpc/server/team-router/delete-team-group.ts @@ -19,6 +19,13 @@ export const deleteTeamGroupRoute = authenticatedProcedure const { teamGroupId, teamId } = input; const { user } = ctx; + ctx.logger.info({ + input: { + teamGroupId, + teamId, + }, + }); + const team = await prisma.team.findFirst({ where: buildTeamWhereQuery({ teamId, diff --git a/packages/trpc/server/team-router/delete-team-member.ts b/packages/trpc/server/team-router/delete-team-member.ts index f5799da19..9e50217d2 100644 --- a/packages/trpc/server/team-router/delete-team-member.ts +++ b/packages/trpc/server/team-router/delete-team-member.ts @@ -20,6 +20,13 @@ export const deleteTeamMemberRoute = authenticatedProcedure const { teamId, memberId } = input; const { user } = ctx; + ctx.logger.info({ + input: { + teamId, + memberId, + }, + }); + const team = await prisma.team.findFirst({ where: buildTeamWhereQuery({ teamId, diff --git a/packages/trpc/server/team-router/delete-team.ts b/packages/trpc/server/team-router/delete-team.ts index 46bec4b8a..2624a902b 100644 --- a/packages/trpc/server/team-router/delete-team.ts +++ b/packages/trpc/server/team-router/delete-team.ts @@ -11,6 +11,12 @@ export const deleteTeamRoute = authenticatedProcedure const { teamId } = input; const { user } = ctx; + ctx.logger.info({ + input: { + teamId, + }, + }); + await deleteTeam({ userId: user.id, teamId, diff --git a/packages/trpc/server/team-router/find-team-groups.ts b/packages/trpc/server/team-router/find-team-groups.ts index 5ac66a859..3ef9e5a6c 100644 --- a/packages/trpc/server/team-router/find-team-groups.ts +++ b/packages/trpc/server/team-router/find-team-groups.ts @@ -20,6 +20,13 @@ export const findTeamGroupsRoute = authenticatedProcedure const { teamId, types, query, page, perPage, teamGroupId, organisationRoles } = input; const { user } = ctx; + ctx.logger.info({ + input: { + teamId, + teamGroupId, + }, + }); + return await findTeamGroups({ userId: user.id, teamId, diff --git a/packages/trpc/server/team-router/find-team-members.ts b/packages/trpc/server/team-router/find-team-members.ts index c9550b0e4..91d046382 100644 --- a/packages/trpc/server/team-router/find-team-members.ts +++ b/packages/trpc/server/team-router/find-team-members.ts @@ -13,6 +13,12 @@ export const findTeamMembersRoute = authenticatedProcedure const { teamId, query, page, perPage } = input; const { user } = ctx; + ctx.logger.info({ + input: { + teamId, + }, + }); + return await findTeamMembers({ userId: user.id, teamId, diff --git a/packages/trpc/server/team-router/find-teams.ts b/packages/trpc/server/team-router/find-teams.ts index f6d9cc4e7..e4466d96c 100644 --- a/packages/trpc/server/team-router/find-teams.ts +++ b/packages/trpc/server/team-router/find-teams.ts @@ -11,5 +11,11 @@ export const findTeamsRoute = authenticatedProcedure const { organisationId } = input; const { user } = ctx; + ctx.logger.info({ + input: { + organisationId, + }, + }); + return findTeams({ userId: user.id, organisationId }); }); diff --git a/packages/trpc/server/team-router/get-team-members.ts b/packages/trpc/server/team-router/get-team-members.ts index a98c71dca..f941e497b 100644 --- a/packages/trpc/server/team-router/get-team-members.ts +++ b/packages/trpc/server/team-router/get-team-members.ts @@ -14,6 +14,12 @@ export const getTeamMembersRoute = authenticatedProcedure const { teamId } = input; const { user } = ctx; + ctx.logger.info({ + input: { + teamId, + }, + }); + return await getTeamMembers({ userId: user.id, teamId, diff --git a/packages/trpc/server/team-router/get-team.ts b/packages/trpc/server/team-router/get-team.ts index f36abb293..3b7db0871 100644 --- a/packages/trpc/server/team-router/get-team.ts +++ b/packages/trpc/server/team-router/get-team.ts @@ -8,8 +8,16 @@ export const getTeamRoute = authenticatedProcedure .input(ZGetTeamRequestSchema) .output(ZGetTeamResponseSchema) .query(async ({ input, ctx }) => { + const { teamReference } = input; + + ctx.logger.info({ + input: { + teamReference, + }, + }); + return await getTeam({ - teamReference: input.teamReference, + teamReference, userId: ctx.user.id, }); }); diff --git a/packages/trpc/server/team-router/router.ts b/packages/trpc/server/team-router/router.ts index aeb1fa8af..f982a4e1e 100644 --- a/packages/trpc/server/team-router/router.ts +++ b/packages/trpc/server/team-router/router.ts @@ -61,6 +61,12 @@ export const teamRouter = router({ update: authenticatedProcedure .input(ZUpdateTeamEmailMutationSchema) .mutation(async ({ input, ctx }) => { + ctx.logger.info({ + input: { + teamId: input.teamId, + }, + }); + return await updateTeamEmail({ userId: ctx.user.id, ...input, @@ -69,39 +75,71 @@ export const teamRouter = router({ delete: authenticatedProcedure .input(ZDeleteTeamEmailMutationSchema) .mutation(async ({ input, ctx }) => { + const { teamId } = input; + + ctx.logger.info({ + input: { + teamId, + }, + }); + return await deleteTeamEmail({ userId: ctx.user.id, userEmail: ctx.user.email, - ...input, + teamId, }); }), verification: { send: authenticatedProcedure .input(ZCreateTeamEmailVerificationMutationSchema) .mutation(async ({ input, ctx }) => { + const { teamId, email, name } = input; + + ctx.logger.info({ + input: { + teamId, + }, + }); + return await createTeamEmailVerification({ - teamId: input.teamId, + teamId, userId: ctx.user.id, data: { - email: input.email, - name: input.name, + email, + name, }, }); }), resend: authenticatedProcedure .input(ZResendTeamEmailVerificationMutationSchema) .mutation(async ({ input, ctx }) => { + const { teamId } = input; + + ctx.logger.info({ + input: { + teamId, + }, + }); + await resendTeamEmailVerification({ userId: ctx.user.id, - ...input, + teamId, }); }), delete: authenticatedProcedure .input(ZDeleteTeamEmailVerificationMutationSchema) .mutation(async ({ input, ctx }) => { + const { teamId } = input; + + ctx.logger.info({ + input: { + teamId, + }, + }); + return await deleteTeamEmailVerification({ userId: ctx.user.id, - ...input, + teamId, }); }), }, diff --git a/packages/trpc/server/team-router/update-team-group.ts b/packages/trpc/server/team-router/update-team-group.ts index 4c10ff18b..5090ef9f0 100644 --- a/packages/trpc/server/team-router/update-team-group.ts +++ b/packages/trpc/server/team-router/update-team-group.ts @@ -19,6 +19,15 @@ export const updateTeamGroupRoute = authenticatedProcedure const { id, data } = input; const { user } = ctx; + ctx.logger.info({ + input: { + id, + data: { + teamRole: data.teamRole, + }, + }, + }); + const teamGroup = await prisma.teamGroup.findFirst({ where: { id, diff --git a/packages/trpc/server/team-router/update-team-member.ts b/packages/trpc/server/team-router/update-team-member.ts index e418fb5be..c21e2e371 100644 --- a/packages/trpc/server/team-router/update-team-member.ts +++ b/packages/trpc/server/team-router/update-team-member.ts @@ -22,6 +22,13 @@ export const updateTeamMemberRoute = authenticatedProcedure const { teamId, memberId, data } = input; const userId = ctx.user.id; + ctx.logger.info({ + input: { + teamId, + memberId, + }, + }); + const team = await prisma.team.findFirst({ where: { AND: [ diff --git a/packages/trpc/server/team-router/update-team-settings.ts b/packages/trpc/server/team-router/update-team-settings.ts index 7c6083645..72082a9a1 100644 --- a/packages/trpc/server/team-router/update-team-settings.ts +++ b/packages/trpc/server/team-router/update-team-settings.ts @@ -16,6 +16,12 @@ export const updateTeamSettingsRoute = authenticatedProcedure const { user } = ctx; const { teamId, data } = input; + ctx.logger.info({ + input: { + teamId, + }, + }); + const { // Document related settings. documentVisibility, diff --git a/packages/trpc/server/team-router/update-team.ts b/packages/trpc/server/team-router/update-team.ts index 8aa9ab197..6dae1f829 100644 --- a/packages/trpc/server/team-router/update-team.ts +++ b/packages/trpc/server/team-router/update-team.ts @@ -13,6 +13,12 @@ export const updateTeamRoute = authenticatedProcedure const { name, url, profileBio, profileEnabled } = data; + ctx.logger.info({ + input: { + teamId, + }, + }); + if (name || url) { await updateTeam({ userId: ctx.user.id, diff --git a/packages/trpc/server/template-router/router.ts b/packages/trpc/server/template-router/router.ts index b10412c58..2fc8f6f86 100644 --- a/packages/trpc/server/template-router/router.ts +++ b/packages/trpc/server/template-router/router.ts @@ -67,6 +67,12 @@ export const templateRouter = router({ .query(async ({ input, ctx }) => { const { teamId } = ctx; + ctx.logger.info({ + input: { + folderId: input.folderId, + }, + }); + return await findTemplates({ userId: ctx.user.id, teamId, @@ -92,6 +98,12 @@ export const templateRouter = router({ const { teamId } = ctx; const { templateId } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await getTemplateById({ id: templateId, userId: ctx.user.id, @@ -120,6 +132,12 @@ export const templateRouter = router({ const { teamId } = ctx; const { title, templateDocumentDataId, folderId } = input; + ctx.logger.info({ + input: { + folderId, + }, + }); + return await createTemplate({ userId: ctx.user.id, teamId, @@ -146,9 +164,14 @@ export const templateRouter = router({ .mutation(async ({ input, ctx }) => { const { teamId } = ctx; const { templateId, data, meta } = input; - const userId = ctx.user.id; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await updateTemplate({ userId, teamId, @@ -176,6 +199,12 @@ export const templateRouter = router({ const { teamId } = ctx; const { templateId } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await duplicateTemplate({ userId: ctx.user.id, teamId, @@ -200,9 +229,14 @@ export const templateRouter = router({ .mutation(async ({ input, ctx }) => { const { teamId } = ctx; const { templateId } = input; - const userId = ctx.user.id; + ctx.logger.info({ + input: { + templateId, + }, + }); + await deleteTemplate({ userId, id: templateId, teamId }); return ZGenericSuccessResponse; @@ -228,6 +262,12 @@ export const templateRouter = router({ const { templateId, recipients, distributeDocument, customDocumentDataId, prefillFields } = input; + ctx.logger.info({ + input: { + templateId, + }, + }); + const limits = await getServerLimits({ userId: ctx.user.id, teamId }); if (limits.remaining.documents === 0) { @@ -291,6 +331,12 @@ export const templateRouter = router({ templateUpdatedAt, } = input; + ctx.logger.info({ + input: { + directTemplateToken, + }, + }); + return await createDocumentFromDirectTemplate({ directRecipientName, directRecipientEmail, @@ -330,6 +376,13 @@ export const templateRouter = router({ const userId = ctx.user.id; + ctx.logger.info({ + input: { + templateId, + directRecipientId, + }, + }); + const template = await getTemplateById({ id: templateId, teamId, userId: ctx.user.id }); const limits = await getServerLimits({ userId: ctx.user.id, teamId: template.teamId }); @@ -364,6 +417,12 @@ export const templateRouter = router({ const userId = ctx.user.id; + ctx.logger.info({ + input: { + templateId, + }, + }); + await deleteTemplateDirectLink({ userId, teamId, templateId }); return ZGenericSuccessResponse; @@ -390,6 +449,12 @@ export const templateRouter = router({ const userId = ctx.user.id; + ctx.logger.info({ + input: { + templateId, + }, + }); + return await toggleTemplateDirectLink({ userId, teamId, templateId, enabled }); }), @@ -402,6 +467,13 @@ export const templateRouter = router({ const { templateId, teamId, csv, sendImmediately } = input; const { user } = ctx; + ctx.logger.info({ + input: { + templateId, + teamId, + }, + }); + if (csv.length > 4 * 1024 * 1024) { throw new TRPCError({ code: 'BAD_REQUEST', diff --git a/packages/trpc/server/trpc.ts b/packages/trpc/server/trpc.ts index 737df2a36..d7ff12eee 100644 --- a/packages/trpc/server/trpc.ts +++ b/packages/trpc/server/trpc.ts @@ -4,7 +4,9 @@ import type { AnyZodObject } from 'zod'; import { AppError, genericErrorCodeToTrpcErrorCodeMap } from '@documenso/lib/errors/app-error'; import { getApiTokenByToken } from '@documenso/lib/server-only/public-api/get-api-token-by-token'; +import type { TrpcApiLog } from '@documenso/lib/types/api-logs'; import type { ApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; +import { alphaid } from '@documenso/lib/universal/id'; import { isAdmin } from '@documenso/lib/utils/is-admin'; import type { TrpcContext } from './context'; @@ -66,11 +68,13 @@ const t = initTRPC * Middlewares */ export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path }) => { - const logger = ctx.logger.child({ + const infoToLog: TrpcApiLog = { path, auth: ctx.metadata.auth, source: ctx.metadata.source, - }); + trpcMiddleware: 'authenticated', + unverifiedTeamId: ctx.teamId, + }; const authorizationHeader = ctx.req.headers.get('authorization'); @@ -85,10 +89,11 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path }) const apiToken = await getApiTokenByToken({ token }); - logger.info({ + ctx.logger.info({ + ...infoToLog, userId: apiToken.user.id, apiTokenId: apiToken.id, - }); + } satisfies TrpcApiLog); return await next({ ctx: { @@ -122,14 +127,21 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path }) }); } - logger.info({ + // Recreate the logger with a sub request ID to differentiate between batched requests. + const trpcSessionLogger = ctx.logger.child({ + nonBatchedRequestId: alphaid(), + }); + + trpcSessionLogger.info({ + ...infoToLog, userId: ctx.user.id, apiTokenId: null, - }); + } satisfies TrpcApiLog); return await next({ ctx: { ...ctx, + logger: trpcSessionLogger, user: ctx.user, session: ctx.session, metadata: { @@ -145,10 +157,26 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path }) }); }); -export const maybeAuthenticatedMiddleware = t.middleware(async ({ ctx, next }) => { +export const maybeAuthenticatedMiddleware = t.middleware(async ({ ctx, next, path }) => { + // Recreate the logger with a sub request ID to differentiate between batched requests. + const trpcSessionLogger = ctx.logger.child({ + nonBatchedRequestId: alphaid(), + }); + + ctx.logger.info({ + path, + auth: ctx.metadata.auth, + source: ctx.metadata.source, + userId: ctx.user?.id, + apiTokenId: null, + trpcMiddleware: 'maybeAuthenticated', + unverifiedTeamId: ctx.teamId, + } satisfies TrpcApiLog); + return await next({ ctx: { ...ctx, + logger: trpcSessionLogger, user: ctx.user, session: ctx.session, metadata: { @@ -166,7 +194,7 @@ export const maybeAuthenticatedMiddleware = t.middleware(async ({ ctx, next }) = }); }); -export const adminMiddleware = t.middleware(async ({ ctx, next }) => { +export const adminMiddleware = t.middleware(async ({ ctx, next, path }) => { if (!ctx.session || !ctx.user) { throw new TRPCError({ code: 'UNAUTHORIZED', @@ -183,9 +211,24 @@ export const adminMiddleware = t.middleware(async ({ ctx, next }) => { }); } + // Recreate the logger with a sub request ID to differentiate between batched requests. + const trpcSessionLogger = ctx.logger.child({ + nonBatchedRequestId: alphaid(), + }); + + trpcSessionLogger.info({ + path, + auth: ctx.metadata.auth, + source: ctx.metadata.source, + userId: ctx.user.id, + apiTokenId: null, + trpcMiddleware: 'admin', + } satisfies TrpcApiLog); + return await next({ ctx: { ...ctx, + logger: trpcSessionLogger, user: ctx.user, session: ctx.session, metadata: { @@ -201,11 +244,34 @@ export const adminMiddleware = t.middleware(async ({ ctx, next }) => { }); }); +export const procedureMiddleware = t.middleware(async ({ ctx, next, path }) => { + // Recreate the logger with a sub request ID to differentiate between batched requests. + const trpcSessionLogger = ctx.logger.child({ + nonBatchedRequestId: alphaid(), + }); + + trpcSessionLogger.info({ + path, + auth: ctx.metadata.auth, + source: ctx.metadata.source, + userId: ctx.user?.id, + apiTokenId: null, + trpcMiddleware: 'procedure', + } satisfies TrpcApiLog); + + return await next({ + ctx: { + ...ctx, + logger: trpcSessionLogger, + }, + }); +}); + /** * Routers and Procedures */ export const router = t.router; -export const procedure = t.procedure; +export const procedure = t.procedure.use(procedureMiddleware); export const authenticatedProcedure = t.procedure.use(authenticatedMiddleware); // While this is functionally the same as `procedure`, it's useful for indicating purpose export const maybeAuthenticatedProcedure = t.procedure.use(maybeAuthenticatedMiddleware); diff --git a/packages/trpc/server/webhook-router/router.ts b/packages/trpc/server/webhook-router/router.ts index 9323963ed..ce06e4e43 100644 --- a/packages/trpc/server/webhook-router/router.ts +++ b/packages/trpc/server/webhook-router/router.ts @@ -19,6 +19,12 @@ export const webhookRouter = router({ .query(async ({ ctx, input }) => { const { teamId } = input; + ctx.logger.info({ + input: { + teamId, + }, + }); + return await getWebhooksByTeamId(teamId, ctx.user.id); }), @@ -27,6 +33,13 @@ export const webhookRouter = router({ .query(async ({ input, ctx }) => { const { id, teamId } = input; + ctx.logger.info({ + input: { + id, + teamId, + }, + }); + return await getWebhookById({ id, userId: ctx.user.id, @@ -39,6 +52,12 @@ export const webhookRouter = router({ .mutation(async ({ input, ctx }) => { const { enabled, eventTriggers, secret, webhookUrl, teamId } = input; + ctx.logger.info({ + input: { + teamId, + }, + }); + return await createWebhook({ enabled, secret, @@ -54,6 +73,13 @@ export const webhookRouter = router({ .mutation(async ({ input, ctx }) => { const { id, teamId } = input; + ctx.logger.info({ + input: { + id, + teamId, + }, + }); + return await deleteWebhookById({ id, teamId, @@ -66,6 +92,13 @@ export const webhookRouter = router({ .mutation(async ({ input, ctx }) => { const { id, teamId, ...data } = input; + ctx.logger.info({ + input: { + id, + teamId, + }, + }); + return await editWebhook({ id, data, diff --git a/packages/trpc/utils/trpc-error-handler.ts b/packages/trpc/utils/trpc-error-handler.ts index aa488f612..1502d4d6e 100644 --- a/packages/trpc/utils/trpc-error-handler.ts +++ b/packages/trpc/utils/trpc-error-handler.ts @@ -1,14 +1,14 @@ import type { ErrorHandlerOptions } from '@trpc/server/unstable-core-do-not-import'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; -import { buildLogger } from '@documenso/lib/utils/logger-legacy'; +import { logger } from '@documenso/lib/utils/logger'; -const logger = buildLogger(); +import type { TrpcContext } from '../server/context'; // Parameters[0]['onError']>>[0], // :-) export const handleTrpcRouterError = ( - { error, path }: Pick, 'error' | 'path'>, - source: 'trpc' | 'apiV1' | 'apiV2', + { error, ctx }: Pick, 'error' | 'path' | 'ctx'>, + _source: 'trpc' | 'apiV1' | 'apiV2', ) => { const appError = AppError.parseError(error.cause || error); @@ -23,16 +23,16 @@ export const handleTrpcRouterError = ( // not an AppError. const isLoggableTrpcError = !isAppError && errorCodesToAlertOn.includes(error.code); - if (isLoggableAppError || isLoggableTrpcError) { - console.error(error); + const errorLogger = (ctx?.logger || logger).child({ + status: 'error', + appError: AppError.toJSON(appError), + }); - logger.error(error, { - method: path, - context: { - source, - appError: AppError.toJSON(appError), - }, - }); + // Only fully log the error on certain conditions since some errors are expected. + if (isLoggableAppError || isLoggableTrpcError) { + errorLogger.error(error); + } else { + errorLogger.info('TRPC_ERROR_HANDLER'); } }; diff --git a/packages/tsconfig/process-env.d.ts b/packages/tsconfig/process-env.d.ts index 143dbe30d..7962031f5 100644 --- a/packages/tsconfig/process-env.d.ts +++ b/packages/tsconfig/process-env.d.ts @@ -15,6 +15,8 @@ declare namespace NodeJS { NEXT_PRIVATE_ENCRYPTION_KEY: string; NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY: string; + NEXT_PRIVATE_LOGGER_FILE_PATH?: string; + NEXT_PRIVATE_STRIPE_API_KEY: string; NEXT_PRIVATE_STRIPE_WEBHOOK_SECRET: string; @@ -77,8 +79,6 @@ declare namespace NodeJS { NEXT_PRIVATE_INNGEST_APP_ID?: string; NEXT_PRIVATE_INNGEST_EVENT_KEY?: string; - NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY?: string; - POSTGRES_URL?: string; DATABASE_URL?: string; POSTGRES_PRISMA_URL?: string; diff --git a/turbo.json b/turbo.json index db492e33a..77c668b35 100644 --- a/turbo.json +++ b/turbo.json @@ -50,6 +50,7 @@ "NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT", "NEXT_PRIVATE_DATABASE_URL", "NEXT_PRIVATE_DIRECT_DATABASE_URL", + "NEXT_PRIVATE_LOGGER_FILE_PATH", "NEXT_PRIVATE_SIGNING_TRANSPORT", "NEXT_PRIVATE_SIGNING_PASSPHRASE", "NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH", @@ -104,7 +105,6 @@ "NEXT_PRIVATE_BROWSERLESS_URL", "NEXT_PRIVATE_JOBS_PROVIDER", "NEXT_PRIVATE_INNGEST_APP_ID", - "NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY", "INNGEST_EVENT_KEY", "NEXT_PRIVATE_INNGEST_EVENT_KEY", "CI", From 8695ef766e4bad73e4cf1ddb37c09491a356c40d Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Mon, 30 Jun 2025 19:47:37 +1000 Subject: [PATCH 09/17] v1.12.0-rc.8 --- apps/remix/package.json | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/remix/package.json b/apps/remix/package.json index 8a5cc6817..305a86bc4 100644 --- a/apps/remix/package.json +++ b/apps/remix/package.json @@ -101,5 +101,5 @@ "vite-plugin-babel-macros": "^1.0.6", "vite-tsconfig-paths": "^5.1.4" }, - "version": "1.12.0-rc.7" + "version": "1.12.0-rc.8" } diff --git a/package-lock.json b/package-lock.json index 405ed6350..01b3d3018 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@documenso/root", - "version": "1.12.0-rc.7", + "version": "1.12.0-rc.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@documenso/root", - "version": "1.12.0-rc.7", + "version": "1.12.0-rc.8", "workspaces": [ "apps/*", "packages/*" @@ -89,7 +89,7 @@ }, "apps/remix": { "name": "@documenso/remix", - "version": "1.12.0-rc.7", + "version": "1.12.0-rc.8", "dependencies": { "@documenso/api": "*", "@documenso/assets": "*", diff --git a/package.json b/package.json index 6dec2e494..175e034de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "1.12.0-rc.7", + "version": "1.12.0-rc.8", "scripts": { "build": "turbo run build", "dev": "turbo run dev --filter=@documenso/remix", From 8da4ab533f68b071d270188d82d4c64e8c1a271b Mon Sep 17 00:00:00 2001 From: Jan Piotrowski Date: Tue, 1 Jul 2025 04:34:14 +0200 Subject: [PATCH 10/17] fix(add-subject): remove superfluous word (#1866) --- packages/ui/primitives/document-flow/add-subject.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/primitives/document-flow/add-subject.tsx b/packages/ui/primitives/document-flow/add-subject.tsx index 92fe8f111..dedb9a2a9 100644 --- a/packages/ui/primitives/document-flow/add-subject.tsx +++ b/packages/ui/primitives/document-flow/add-subject.tsx @@ -206,7 +206,7 @@ export const AddSubjectFormPartial = ({

- We will generate signing links for with you, which you can send to the + We will generate signing links for you, which you can send to the recipients through your method of choice.

From eda0d5eeb66d103fdf0b3718433940cef6bed008 Mon Sep 17 00:00:00 2001 From: Ephraim Duncan <55143799+ephraimduncan@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:21:13 +0000 Subject: [PATCH 11/17] fix: open advanced settings when fields are added to templates (#1855) --- .../primitives/template-flow/add-template-fields.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/ui/primitives/template-flow/add-template-fields.tsx b/packages/ui/primitives/template-flow/add-template-fields.tsx index 5689db4e6..152f764aa 100644 --- a/packages/ui/primitives/template-flow/add-template-fields.tsx +++ b/packages/ui/primitives/template-flow/add-template-fields.tsx @@ -29,6 +29,7 @@ import { ZFieldMetaSchema, } from '@documenso/lib/types/field-meta'; import { nanoid } from '@documenso/lib/universal/id'; +import { ADVANCED_FIELD_TYPES_WITH_OPTIONAL_SETTING } from '@documenso/lib/utils/advanced-fields-helpers'; import { parseMessageDescriptor } from '@documenso/lib/utils/i18n'; import { cn } from '@documenso/ui/lib/utils'; import { Button } from '@documenso/ui/primitives/button'; @@ -324,7 +325,7 @@ export const AddTemplateFieldsFormPartial = ({ pageX -= fieldPageWidth / 2; pageY -= fieldPageHeight / 2; - append({ + const field = { formId: nanoid(12), type: selectedField, pageNumber, @@ -336,7 +337,13 @@ export const AddTemplateFieldsFormPartial = ({ signerId: selectedSigner.id, signerToken: selectedSigner.token ?? '', fieldMeta: undefined, - }); + }; + + append(field); + if (ADVANCED_FIELD_TYPES_WITH_OPTIONAL_SETTING.includes(selectedField)) { + setCurrentField(field); + setShowAdvancedSettings(true); + } setIsFieldWithinBounds(false); setSelectedField(null); From ea1cf481eb20dec47ee05e6093352f94a9bc09a5 Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Tue, 1 Jul 2025 21:27:35 +1000 Subject: [PATCH 12/17] chore: extract translations --- packages/lib/translations/de/web.po | 34 ++++++++++------------------- packages/lib/translations/en/web.po | 34 ++++++++++------------------- packages/lib/translations/es/web.po | 34 ++++++++++------------------- packages/lib/translations/fr/web.po | 34 ++++++++++------------------- packages/lib/translations/it/web.po | 34 ++++++++++------------------- packages/lib/translations/pl/web.po | 34 ++++++++++------------------- 6 files changed, 72 insertions(+), 132 deletions(-) diff --git a/packages/lib/translations/de/web.po b/packages/lib/translations/de/web.po index 3ee4ae957..8c68d4962 100644 --- a/packages/lib/translations/de/web.po +++ b/packages/lib/translations/de/web.po @@ -313,6 +313,10 @@ msgstr "{prefix} hat den Titel des Dokuments aktualisiert" msgid "{prefix} updated the document visibility" msgstr "{prefix} hat die Sichtbarkeit des Dokuments aktualisiert" +#: packages/lib/utils/document-audit-logs.ts +msgid "{prefix} viewed the document" +msgstr "" + #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} Dokument" @@ -1767,7 +1771,6 @@ msgstr "Klicken Sie hier, um zu beginnen" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Klicken Sie hier, um es erneut zu versuchen" @@ -2749,11 +2752,6 @@ msgstr "Externe ID des Dokuments aktualisiert" msgid "Document found in your account" msgstr "Dokument in Ihrem Konto gefunden" -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Document history" -msgstr "Dokumentverlauf" - #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2872,6 +2870,10 @@ msgstr "Dokumenten-Upload deaktiviert aufgrund unbezahlter Rechnungen" msgid "Document uploaded" msgstr "Dokument hochgeladen" +#: packages/lib/utils/document-audit-logs.ts +msgid "Document viewed" +msgstr "" + #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Dokument angesehen" @@ -3712,10 +3714,6 @@ msgstr "Hallo, {userName} <0>({userEmail})" msgid "Hide" msgstr "Ausblenden" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Hide additional information" -msgstr "Zusätzliche Informationen ausblenden" - #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -4139,10 +4137,10 @@ msgstr "Abonnement verwalten" msgid "Manage the {0} organisation" msgstr "Verwalten Sie die {0} Organisation" -#. placeholder {0}: organisation.name +#. placeholder {1}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {0} organisation subscription" -msgstr "Verwalten Sie das Abonnement der {0} Organisation" +msgid "Manage the {1} organisation subscription" +msgstr "" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -5814,10 +5812,6 @@ msgstr "Teilen Sie Ihre Unterzeichnungserfahrung!" msgid "Show" msgstr "Anzeigen" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Show additional information" -msgstr "Zusätzliche Informationen anzeigen" - #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -7247,7 +7241,6 @@ msgid "Unable to join this organisation at this time." msgstr "Zurzeit kann dieser Organisation nicht beigetreten werden." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Kann den Dokumentverlauf nicht laden" @@ -8016,11 +8009,8 @@ msgstr "Wir konnten Ihre E-Mail derzeit nicht verifizieren." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "Wir konnten Ihre E-Mail nicht bestätigen. Wenn Ihre E-Mail noch nicht bestätigt wurde, versuchen Sie es bitte erneut." -#: packages/ui/primitives/document-flow/add-subject.tsx -msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." -msgstr "Wir generieren Signierlinks mit Ihnen, die Sie den Empfängern über Ihre bevorzugte Methode senden können." - #: apps/remix/app/components/dialogs/template-use-dialog.tsx +#: packages/ui/primitives/document-flow/add-subject.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Wir werden Unterzeichnungslinks für Sie erstellen, die Sie an die Empfänger über Ihre bevorzugte Methode senden können." diff --git a/packages/lib/translations/en/web.po b/packages/lib/translations/en/web.po index 203351f68..a1994ef0e 100644 --- a/packages/lib/translations/en/web.po +++ b/packages/lib/translations/en/web.po @@ -308,6 +308,10 @@ msgstr "{prefix} updated the document title" msgid "{prefix} updated the document visibility" msgstr "{prefix} updated the document visibility" +#: packages/lib/utils/document-audit-logs.ts +msgid "{prefix} viewed the document" +msgstr "{prefix} viewed the document" + #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} document" @@ -1762,7 +1766,6 @@ msgstr "Click here to get started" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Click here to retry" @@ -2744,11 +2747,6 @@ msgstr "Document external ID updated" msgid "Document found in your account" msgstr "Document found in your account" -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Document history" -msgstr "Document history" - #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2867,6 +2865,10 @@ msgstr "Document upload disabled due to unpaid invoices" msgid "Document uploaded" msgstr "Document uploaded" +#: packages/lib/utils/document-audit-logs.ts +msgid "Document viewed" +msgstr "Document viewed" + #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Document Viewed" @@ -3707,10 +3709,6 @@ msgstr "Hi, {userName} <0>({userEmail})" msgid "Hide" msgstr "Hide" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Hide additional information" -msgstr "Hide additional information" - #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -4134,10 +4132,10 @@ msgstr "Manage subscription" msgid "Manage the {0} organisation" msgstr "Manage the {0} organisation" -#. placeholder {0}: organisation.name +#. placeholder {1}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {0} organisation subscription" -msgstr "Manage the {0} organisation subscription" +msgid "Manage the {1} organisation subscription" +msgstr "Manage the {1} organisation subscription" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -5809,10 +5807,6 @@ msgstr "Share your signing experience!" msgid "Show" msgstr "Show" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Show additional information" -msgstr "Show additional information" - #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -7254,7 +7248,6 @@ msgid "Unable to join this organisation at this time." msgstr "Unable to join this organisation at this time." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Unable to load document history" @@ -8023,11 +8016,8 @@ msgstr "We were unable to verify your email at this time." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "We were unable to verify your email. If your email is not verified already, please try again." -#: packages/ui/primitives/document-flow/add-subject.tsx -msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." -msgstr "We will generate signing links for with you, which you can send to the recipients through your method of choice." - #: apps/remix/app/components/dialogs/template-use-dialog.tsx +#: packages/ui/primitives/document-flow/add-subject.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "We will generate signing links for you, which you can send to the recipients through your method of choice." diff --git a/packages/lib/translations/es/web.po b/packages/lib/translations/es/web.po index 3dae1a047..2a3f7b8e2 100644 --- a/packages/lib/translations/es/web.po +++ b/packages/lib/translations/es/web.po @@ -313,6 +313,10 @@ msgstr "{prefix} actualizó el título del documento" msgid "{prefix} updated the document visibility" msgstr "{prefix} actualizó la visibilidad del documento" +#: packages/lib/utils/document-audit-logs.ts +msgid "{prefix} viewed the document" +msgstr "" + #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} documento" @@ -1767,7 +1771,6 @@ msgstr "Haga clic aquí para comenzar" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Haga clic aquí para reintentar" @@ -2749,11 +2752,6 @@ msgstr "ID externo del documento actualizado" msgid "Document found in your account" msgstr "Documento encontrado en tu cuenta" -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Document history" -msgstr "Historial de documentos" - #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2872,6 +2870,10 @@ msgstr "La carga de documentos está deshabilitada debido a facturas impagadas" msgid "Document uploaded" msgstr "Documento subido" +#: packages/lib/utils/document-audit-logs.ts +msgid "Document viewed" +msgstr "" + #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Documento visto" @@ -3712,10 +3714,6 @@ msgstr "Hola, {userName} <0>({userEmail})" msgid "Hide" msgstr "Ocultar" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Hide additional information" -msgstr "Ocultar información adicional" - #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -4139,10 +4137,10 @@ msgstr "Gestionar suscripción" msgid "Manage the {0} organisation" msgstr "Gestionar la organización {0}" -#. placeholder {0}: organisation.name +#. placeholder {1}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {0} organisation subscription" -msgstr "Gestionar la suscripción de la organización {0}" +msgid "Manage the {1} organisation subscription" +msgstr "" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -5814,10 +5812,6 @@ msgstr "¡Comparte tu experiencia de firma!" msgid "Show" msgstr "Mostrar" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Show additional information" -msgstr "Mostrar información adicional" - #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -7249,7 +7243,6 @@ msgid "Unable to join this organisation at this time." msgstr "No se puede unirse a esta organización en este momento." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "No se pudo cargar el historial del documento" @@ -8018,11 +8011,8 @@ msgstr "No pudimos verificar tu correo electrónico en este momento." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "No pudimos verificar tu correo electrónico. Si tu correo electrónico no está verificado ya, por favor inténtalo de nuevo." -#: packages/ui/primitives/document-flow/add-subject.tsx -msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." -msgstr "Generaremos enlaces de firma para ti, que podrás enviar a los destinatarios a través de tu método preferido." - #: apps/remix/app/components/dialogs/template-use-dialog.tsx +#: packages/ui/primitives/document-flow/add-subject.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Generaremos enlaces de firma para ti, que podrás enviar a los destinatarios a través de tu método preferido." diff --git a/packages/lib/translations/fr/web.po b/packages/lib/translations/fr/web.po index 9f98a65dd..626500381 100644 --- a/packages/lib/translations/fr/web.po +++ b/packages/lib/translations/fr/web.po @@ -313,6 +313,10 @@ msgstr "{prefix} a mis à jour le titre du document" msgid "{prefix} updated the document visibility" msgstr "{prefix} a mis à jour la visibilité du document" +#: packages/lib/utils/document-audit-logs.ts +msgid "{prefix} viewed the document" +msgstr "" + #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} document" @@ -1767,7 +1771,6 @@ msgstr "Cliquez ici pour commencer" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Cliquez ici pour réessayer" @@ -2749,11 +2752,6 @@ msgstr "ID externe du document mis à jour" msgid "Document found in your account" msgstr "Document trouvé dans votre compte" -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Document history" -msgstr "Historique du document" - #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2872,6 +2870,10 @@ msgstr "Importation de documents désactivé en raison de factures impayées" msgid "Document uploaded" msgstr "Document importé" +#: packages/lib/utils/document-audit-logs.ts +msgid "Document viewed" +msgstr "" + #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Document consulté" @@ -3712,10 +3714,6 @@ msgstr "Bonjour, {userName} <0>({userEmail})" msgid "Hide" msgstr "Cacher" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Hide additional information" -msgstr "Cacher des informations supplémentaires" - #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -4139,10 +4137,10 @@ msgstr "Gérer l'abonnement" msgid "Manage the {0} organisation" msgstr "Gérer l'organisation {0}" -#. placeholder {0}: organisation.name +#. placeholder {1}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {0} organisation subscription" -msgstr "Gérer l'abonnement de l'organisation {0}" +msgid "Manage the {1} organisation subscription" +msgstr "" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -5814,10 +5812,6 @@ msgstr "Partagez votre expérience de signature !" msgid "Show" msgstr "Afficher" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Show additional information" -msgstr "Afficher des informations supplémentaires" - #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -7247,7 +7241,6 @@ msgid "Unable to join this organisation at this time." msgstr "Impossible de rejoindre cette organisation pour le moment." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Impossible de charger l'historique des documents" @@ -8016,11 +8009,8 @@ msgstr "Nous n'avons pas pu vérifier votre email pour le moment." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "Nous n'avons pas pu vérifier votre e-mail. Si votre e-mail n'est pas déjà vérifié, veuillez réessayer." -#: packages/ui/primitives/document-flow/add-subject.tsx -msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." -msgstr "Nous générerons des liens de signature pour vous, que vous pourrez envoyer aux destinataires par votre méthode de choix." - #: apps/remix/app/components/dialogs/template-use-dialog.tsx +#: packages/ui/primitives/document-flow/add-subject.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Nous allons générer des liens de signature pour vous, que vous pouvez envoyer aux destinataires par votre méthode de choix." diff --git a/packages/lib/translations/it/web.po b/packages/lib/translations/it/web.po index 70cd628d2..fe707fb30 100644 --- a/packages/lib/translations/it/web.po +++ b/packages/lib/translations/it/web.po @@ -313,6 +313,10 @@ msgstr "{prefix} ha aggiornato il titolo del documento" msgid "{prefix} updated the document visibility" msgstr "{prefix} ha aggiornato la visibilità del documento" +#: packages/lib/utils/document-audit-logs.ts +msgid "{prefix} viewed the document" +msgstr "" + #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} documento" @@ -1767,7 +1771,6 @@ msgstr "Clicca qui per iniziare" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Clicca qui per riprovare" @@ -2749,11 +2752,6 @@ msgstr "ID esterno del documento aggiornato" msgid "Document found in your account" msgstr "Documento trovato nel tuo account" -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Document history" -msgstr "Cronologia del documento" - #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2872,6 +2870,10 @@ msgstr "Caricamento del documento disabilitato a causa di fatture non pagate" msgid "Document uploaded" msgstr "Documento caricato" +#: packages/lib/utils/document-audit-logs.ts +msgid "Document viewed" +msgstr "" + #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Documento visualizzato" @@ -3712,10 +3714,6 @@ msgstr "Ciao, {userName} <0>({userEmail})" msgid "Hide" msgstr "Nascondi" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Hide additional information" -msgstr "Nascondi informazioni aggiuntive" - #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -4139,10 +4137,10 @@ msgstr "Gestisci abbonamento" msgid "Manage the {0} organisation" msgstr "Gestisci l'organizzazione {0}" -#. placeholder {0}: organisation.name +#. placeholder {1}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {0} organisation subscription" -msgstr "Gestisci l'abbonamento dell'organizzazione {0}" +msgid "Manage the {1} organisation subscription" +msgstr "" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -5814,10 +5812,6 @@ msgstr "Condividi la tua esperienza di firma!" msgid "Show" msgstr "Mostra" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Show additional information" -msgstr "Mostra informazioni aggiuntive" - #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -7259,7 +7253,6 @@ msgid "Unable to join this organisation at this time." msgstr "Impossibile unirsi a questa organizzazione in questo momento." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Impossibile caricare la cronologia del documento" @@ -8028,11 +8021,8 @@ msgstr "Non siamo stati in grado di verificare la tua email in questo momento." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "Non siamo riusciti a verificare la tua email. Se la tua email non è già verificata, riprova." -#: packages/ui/primitives/document-flow/add-subject.tsx -msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." -msgstr "Genereremo link di firma con te, che potrai inviare ai destinatari tramite il tuo metodo preferito." - #: apps/remix/app/components/dialogs/template-use-dialog.tsx +#: packages/ui/primitives/document-flow/add-subject.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Genereremo link di firma per te, che potrai inviare ai destinatari tramite il metodo di tua scelta." diff --git a/packages/lib/translations/pl/web.po b/packages/lib/translations/pl/web.po index dc0dc8dac..f69f7099e 100644 --- a/packages/lib/translations/pl/web.po +++ b/packages/lib/translations/pl/web.po @@ -313,6 +313,10 @@ msgstr "Użytkownik {prefix} zaktualizował tytuł dokumentu" msgid "{prefix} updated the document visibility" msgstr "Użytkownik {prefix} zaktualizował widoczność dokumentu" +#: packages/lib/utils/document-audit-logs.ts +msgid "{prefix} viewed the document" +msgstr "" + #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} dokument" @@ -1767,7 +1771,6 @@ msgstr "Kliknij, aby rozpocząć" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Kliknij tutaj, aby spróbować ponownie" @@ -2749,11 +2752,6 @@ msgstr "Zaktualizowane ID zewnętrzne dokumentu" msgid "Document found in your account" msgstr "Dokument znaleziony na Twoim koncie" -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Document history" -msgstr "Historia dokumentu" - #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2872,6 +2870,10 @@ msgstr "Przesyłanie dokumentu wyłączone z powodu nieopłaconych faktur" msgid "Document uploaded" msgstr "Przesłano dokument" +#: packages/lib/utils/document-audit-logs.ts +msgid "Document viewed" +msgstr "" + #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Dokument został wyświetlony" @@ -3712,10 +3714,6 @@ msgstr "Cześć, {userName} <0>({userEmail})" msgid "Hide" msgstr "Ukryj" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Hide additional information" -msgstr "Ukryj dodatkowe informacje" - #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -4139,10 +4137,10 @@ msgstr "Zarządzaj subskrypcją" msgid "Manage the {0} organisation" msgstr "Zarządzaj organizacją {0}" -#. placeholder {0}: organisation.name +#. placeholder {1}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {0} organisation subscription" -msgstr "Zarządzaj subskrypcjami organizacji {0}" +msgid "Manage the {1} organisation subscription" +msgstr "" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -5814,10 +5812,6 @@ msgstr "Podziel się swoim doświadczeniem podpisywania!" msgid "Show" msgstr "Pokaż" -#: apps/remix/app/components/general/document/document-history-sheet.tsx -msgid "Show additional information" -msgstr "Pokaż dodatkowe informacje" - #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -7247,7 +7241,6 @@ msgid "Unable to join this organisation at this time." msgstr "Nie można w tej chwili dołączyć do tej organizacji." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx -#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Nie można załadować historii dokumentu" @@ -8016,11 +8009,8 @@ msgstr "Nie udało się zweryfikować Twojego e-maila w tym momencie." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "Nie udało się zweryfikować twojego e-maila. Jeśli twój e-mail nie jest jeszcze zweryfikowany, spróbuj ponownie." -#: packages/ui/primitives/document-flow/add-subject.tsx -msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." -msgstr "Wygenerujemy linki do podpisu dla Ciebie, które możesz wysłać do odbiorców w wybrany przez siebie sposób." - #: apps/remix/app/components/dialogs/template-use-dialog.tsx +#: packages/ui/primitives/document-flow/add-subject.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Wygenerujemy dla Ciebie linki do podpisania, które możesz wysłać do odbiorców za pomocą wybranej metody." From 1a1a30791e979ec3e9a7c00bdd14680c94063af2 Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Thu, 3 Jul 2025 10:01:03 +1000 Subject: [PATCH 13/17] v1.12.0 --- apps/remix/package.json | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/remix/package.json b/apps/remix/package.json index 305a86bc4..f4ecf9f7b 100644 --- a/apps/remix/package.json +++ b/apps/remix/package.json @@ -101,5 +101,5 @@ "vite-plugin-babel-macros": "^1.0.6", "vite-tsconfig-paths": "^5.1.4" }, - "version": "1.12.0-rc.8" + "version": "1.12.0" } diff --git a/package-lock.json b/package-lock.json index 01b3d3018..b6345f729 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@documenso/root", - "version": "1.12.0-rc.8", + "version": "1.12.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@documenso/root", - "version": "1.12.0-rc.8", + "version": "1.12.0", "workspaces": [ "apps/*", "packages/*" @@ -89,7 +89,7 @@ }, "apps/remix": { "name": "@documenso/remix", - "version": "1.12.0-rc.8", + "version": "1.12.0", "dependencies": { "@documenso/api": "*", "@documenso/assets": "*", diff --git a/package.json b/package.json index 175e034de..c8145108e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "1.12.0-rc.8", + "version": "1.12.0", "scripts": { "build": "turbo run build", "dev": "turbo run dev --filter=@documenso/remix", From b682d2785f196d21cb5edfda638828cc7af2f607 Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Thu, 3 Jul 2025 10:07:11 +1000 Subject: [PATCH 14/17] chore: add translations (#1835) Co-authored-by: Crowdin Bot --- packages/lib/translations/de/web.po | 135 ++++++++-------- packages/lib/translations/es/web.po | 138 ++++++++-------- packages/lib/translations/fr/web.po | 135 ++++++++-------- packages/lib/translations/it/web.po | 149 +++++++++-------- packages/lib/translations/ko/web.po | 237 +++++++++++++++++++++++----- packages/lib/translations/pl/web.po | 169 ++++++++++---------- packages/lib/translations/sq/web.po | 237 +++++++++++++++++++++++----- 7 files changed, 774 insertions(+), 426 deletions(-) diff --git a/packages/lib/translations/de/web.po b/packages/lib/translations/de/web.po index 8c68d4962..f51768049 100644 --- a/packages/lib/translations/de/web.po +++ b/packages/lib/translations/de/web.po @@ -8,7 +8,7 @@ msgstr "" "Language: de\n" "Project-Id-Version: documenso-app\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-10 02:27\n" +"PO-Revision-Date: 2025-06-19 06:05\n" "Last-Translator: \n" "Language-Team: German\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -75,12 +75,12 @@ msgstr "{0, plural, one {# Zeichen über dem Limit} other {# Zeichen über dem L #. placeholder {0}: folder._count.documents #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# document} other {# documents}}" -msgstr "" +msgstr "{0, plural, one {# Dokument} other {# Dokumente}}" #. placeholder {0}: folder._count.subfolders #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# folder} other {# folders}}" -msgstr "" +msgstr "{0, plural, one {# Ordner} other {# Ordner}}" #. placeholder {0}: template.recipients.length #: apps/remix/app/routes/_recipient+/d.$token+/_index.tsx @@ -95,7 +95,7 @@ msgstr "{0, plural, one {# Team} other {# Teams}}" #. placeholder {0}: folder._count.templates #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# template} other {# templates}}" -msgstr "" +msgstr "{0, plural, one {# Vorlage} other {# Vorlagen}}" #. placeholder {0}: data.length #: apps/remix/app/components/general/organisations/organisation-invitations.tsx @@ -313,10 +313,6 @@ msgstr "{prefix} hat den Titel des Dokuments aktualisiert" msgid "{prefix} updated the document visibility" msgstr "{prefix} hat die Sichtbarkeit des Dokuments aktualisiert" -#: packages/lib/utils/document-audit-logs.ts -msgid "{prefix} viewed the document" -msgstr "" - #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} Dokument" @@ -774,7 +770,7 @@ msgstr "Aktiv" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Active sessions" -msgstr "" +msgstr "Aktive Sitzungen" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Active Subscriptions" @@ -1345,7 +1341,7 @@ msgstr "Sind Sie sicher, dass Sie den folgenden Antrag löschen möchten?" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Are you sure you want to delete this folder?" -msgstr "" +msgstr "Möchten Sie diesen Ordner wirklich löschen?" #: apps/remix/app/components/dialogs/token-delete-dialog.tsx msgid "Are you sure you want to delete this token?" @@ -1771,6 +1767,7 @@ msgstr "Klicken Sie hier, um zu beginnen" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Klicken Sie hier, um es erneut zu versuchen" @@ -2164,11 +2161,11 @@ msgstr "Dokument aus der Vorlage erstellen" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Create folder" -msgstr "" +msgstr "Ordner erstellen" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create Folder" -msgstr "" +msgstr "Ordner erstellen" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx @@ -2181,7 +2178,7 @@ msgstr "Gruppen erstellen" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create New Folder" -msgstr "" +msgstr "Neuen Ordner erstellen" #: apps/remix/app/routes/_profile+/_layout.tsx msgid "Create now" @@ -2303,11 +2300,11 @@ msgstr "CSV-Struktur" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Cumulative MAU (signed in)" -msgstr "" +msgstr "Kumulative MAU (angemeldet)" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Current" -msgstr "" +msgstr "Aktuell" #: apps/remix/app/components/forms/password.tsx msgid "Current Password" @@ -2447,7 +2444,7 @@ msgstr "Dokument löschen" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Delete Folder" -msgstr "" +msgstr "Ordner löschen" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.general.tsx msgid "Delete organisation" @@ -2752,6 +2749,11 @@ msgstr "Externe ID des Dokuments aktualisiert" msgid "Document found in your account" msgstr "Dokument in Ihrem Konto gefunden" +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Document history" +msgstr "Dokumentverlauf" + #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2870,10 +2872,6 @@ msgstr "Dokumenten-Upload deaktiviert aufgrund unbezahlter Rechnungen" msgid "Document uploaded" msgstr "Dokument hochgeladen" -#: packages/lib/utils/document-audit-logs.ts -msgid "Document viewed" -msgstr "" - #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Dokument angesehen" @@ -3194,7 +3192,7 @@ msgstr "Beigefügte Dokument" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Enter a name for your new folder. Folders help you organise your items." -msgstr "" +msgstr "Geben Sie einen Namen für Ihren neuen Ordner ein. Ordner helfen Ihnen, Ihre Dateien zu organisieren." #: apps/remix/app/components/forms/subscription-claim-form.tsx msgid "Enter claim name" @@ -3334,7 +3332,7 @@ msgstr "Fehler beim Erstellen des Abonnementsanspruchs." #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Failed to delete folder" -msgstr "" +msgstr "Ordner konnte nicht gelöscht werden" #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Failed to delete subscription claim." @@ -3346,7 +3344,7 @@ msgstr "Fehler beim Laden des Dokuments" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Failed to move folder" -msgstr "" +msgstr "Ordner konnte nicht verschoben werden" #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx msgid "Failed to reseal document" @@ -3354,7 +3352,7 @@ msgstr "Dokument konnte nicht erneut versiegelt werden" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Failed to revoke session" -msgstr "" +msgstr "Sitzung konnte nicht widerrufen werden" #: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx msgid "Failed to save settings." @@ -3362,7 +3360,7 @@ msgstr "Einstellungen konnten nicht gespeichert werden." #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Failed to sign out all sessions" -msgstr "" +msgstr "Fehler beim Abmelden aller Sitzungen" #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx msgid "Failed to update document" @@ -3466,15 +3464,15 @@ msgstr "Ordner erfolgreich erstellt" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Folder deleted successfully" -msgstr "" +msgstr "Ordner erfolgreich gelöscht" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Folder moved successfully" -msgstr "" +msgstr "Ordner erfolgreich verschoben" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Folder Name" -msgstr "" +msgstr "Ordnername" #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3714,6 +3712,10 @@ msgstr "Hallo, {userName} <0>({userEmail})" msgid "Hide" msgstr "Ausblenden" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Hide additional information" +msgstr "Zusätzliche Informationen ausblenden" + #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3723,7 +3725,7 @@ msgstr "Startseite" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Home (No Folder)" -msgstr "" +msgstr "Startseite (kein Ordner)" #: packages/lib/constants/recipient-roles.ts msgid "I am a signer of this document" @@ -3972,7 +3974,7 @@ msgstr "Die letzten 7 Tage" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Last Active" -msgstr "" +msgstr "Zuletzt aktiv" #: apps/remix/app/components/general/template/template-page-view-information.tsx #: apps/remix/app/components/general/document/document-page-view-information.tsx @@ -4125,7 +4127,7 @@ msgstr "Verwalten Sie Berechtigungen und Zugangskontrollen" #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Manage sessions" -msgstr "" +msgstr "Sitzungen verwalten" #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx @@ -4137,10 +4139,10 @@ msgstr "Abonnement verwalten" msgid "Manage the {0} organisation" msgstr "Verwalten Sie die {0} Organisation" -#. placeholder {1}: organisation.name +#. placeholder {0}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {1} organisation subscription" -msgstr "" +msgid "Manage the {0} organisation subscription" +msgstr "Verwalten Sie das Abonnement der {0} Organisation" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -4206,7 +4208,7 @@ msgstr "MAU (hat Dokument abgeschlossen)" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "MAU (signed in)" -msgstr "" +msgstr "MAU (angemeldet)" #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx msgid "Max" @@ -4295,7 +4297,7 @@ msgstr "Dokument in Ordner verschieben" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Move Folder" -msgstr "" +msgstr "Ordner verschieben" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx msgid "Move Template to Folder" @@ -4312,7 +4314,7 @@ msgstr "Es können mehrere Zugriffsmethoden ausgewählt werden." #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "My Folder" -msgstr "" +msgstr "Mein Ordner" #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx @@ -4405,12 +4407,12 @@ msgstr "Keine aktiven Entwürfe" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "No folders found" -msgstr "" +msgstr "Keine Ordner gefunden" #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx msgid "No folders found matching \"{searchTerm}\"" -msgstr "" +msgstr "Keine Ordner gefunden, die \"{searchTerm}\" entsprechen" #: apps/remix/app/routes/_recipient+/sign.$token+/rejected.tsx #: apps/remix/app/components/embed/embed-document-rejected.tsx @@ -4723,7 +4725,7 @@ msgstr "Organisationen, in denen der Benutzer Mitglied ist." #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your documents" -msgstr "" +msgstr "Organisiere deine Dokumente" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Organise your members into groups which can be assigned to teams" @@ -4731,7 +4733,7 @@ msgstr "Organisieren Sie Ihre Mitglieder in Gruppen, die Teams zugewiesen werden #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your templates" -msgstr "" +msgstr "Organisiere deine Vorlagen" #: apps/remix/app/routes/_authenticated+/o.$orgUrl._index.tsx msgid "Organize your documents and templates" @@ -4910,7 +4912,7 @@ msgstr "Wählen Sie eine der folgenden Vereinbarungen aus und beginnen Sie das S #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Pin" -msgstr "" +msgstr "Anheften" #: packages/ui/primitives/document-flow/field-items-advanced-settings/text-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx @@ -5466,7 +5468,7 @@ msgstr "Zugriff widerrufen" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Revoke all sessions" -msgstr "" +msgstr "Alle Sitzungen widerrufen" #: apps/remix/app/components/tables/user-organisations-table.tsx #: apps/remix/app/components/tables/team-members-table.tsx @@ -5544,7 +5546,7 @@ msgstr "Dokumente suchen..." #: apps/remix/app/components/dialogs/folder-move-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Search folders..." -msgstr "" +msgstr "Ordner durchsuchen..." #: packages/ui/components/common/language-switcher-dialog.tsx msgid "Search languages..." @@ -5572,7 +5574,7 @@ msgstr "Auswählen" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Select a destination for this folder." -msgstr "" +msgstr "Wählen Sie ein Ziel für diesen Ordner aus." #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Select a folder to move this document to." @@ -5629,7 +5631,7 @@ msgstr "Gruppen auswählen" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups of members to add to the team." -msgstr "" +msgstr "Mitgliedsgruppen auswählen, die dem Team hinzugefügt werden sollen." #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups to add to this team" @@ -5753,11 +5755,11 @@ msgstr "Gesendet" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Session revoked" -msgstr "" +msgstr "Sitzung widerrufen" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Sessions have been revoked" -msgstr "" +msgstr "Sitzungen wurden widerrufen" #: apps/remix/app/components/general/claim-account.tsx msgid "Set a password" @@ -5812,6 +5814,10 @@ msgstr "Teilen Sie Ihre Unterzeichnungserfahrung!" msgid "Show" msgstr "Anzeigen" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Show additional information" +msgstr "Zusätzliche Informationen anzeigen" + #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -6627,8 +6633,7 @@ msgid "The following team has been deleted. You will no longer be able to access msgstr "Das folgende Team wurde gelöscht. Sie können nicht mehr auf dieses Team und seine Dokumente zugreifen." #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups.$id.tsx -msgid "" -"The organisation group you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation group you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Die Organisationsgruppe, nach der Sie suchen, wurde möglicherweise entfernt, umbenannt oder hat möglicherweise nie existiert." @@ -6637,14 +6642,12 @@ msgid "The organisation role that will be applied to all members in this group." msgstr "Die Organisationsrolle, die auf alle Mitglieder in dieser Gruppe angewendet wird." #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Die Organisation, nach der Sie suchen, wurde möglicherweise entfernt, umbenannt oder hat möglicherweise nie existiert." #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Die Organisation, nach der Sie suchen, wurde möglicherweise entfernt, umbenannt oder hat möglicherweise nie existiert." @@ -6728,14 +6731,12 @@ msgid "The team email <0>{teamEmail} has been removed from the following tea msgstr "Die Team-E-Mail <0>{teamEmail} wurde aus dem folgenden Team entfernt" #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Das Team, das Sie suchen, wurde möglicherweise entfernt, umbenannt oder hat möglicherweise nie existiert." #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Das Team, das Sie suchen, könnte entfernt, umbenannt oder nie existiert haben." @@ -6773,8 +6774,7 @@ msgid "The URL for Documenso to send webhook events to." msgstr "Die URL für Documenso, um Webhook-Ereignisse zu senden." #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx -msgid "" -"The user you are looking for may have been removed, renamed or may have never\n" +msgid "The user you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Der Benutzer, nach dem Sie suchen, wurde möglicherweise entfernt, umbenannt oder hat möglicherweise nie existiert." @@ -6930,7 +6930,7 @@ msgstr "Dieses Feld kann nicht geändert oder gelöscht werden. Wenn Sie den dir #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "This folder contains multiple items. Deleting it will also delete all items in the folder, including nested folders and their contents." -msgstr "" +msgstr "Dieser Ordner enthält mehrere Elemente. Wenn Sie ihn löschen, werden auch alle Elemente im Ordner gelöscht, einschließlich verschachtelter Ordner und deren Inhalt." #: packages/ui/primitives/template-flow/add-template-settings.tsx msgid "This is how the document will reach the recipients once the document is ready for signing." @@ -7012,7 +7012,7 @@ msgstr "Diese werden NUR Funktionsflags zurückspielen, die auf wahr gesetzt sin #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "This will sign you out of all other devices. You will need to sign in again on those devices to continue using your account." -msgstr "" +msgstr "Dies meldet Sie auf allen anderen Geräten ab. Sie müssen sich erneut auf diesen Geräten anmelden, um Ihr Konto weiter zu nutzen." #: apps/remix/app/components/tables/internal-audit-log-table.tsx #: apps/remix/app/components/tables/document-logs-table.tsx @@ -7241,6 +7241,7 @@ msgid "Unable to join this organisation at this time." msgstr "Zurzeit kann dieser Organisation nicht beigetreten werden." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Kann den Dokumentverlauf nicht laden" @@ -7315,7 +7316,7 @@ msgstr "Unbegrenzte Dokumente, API und mehr" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Unpin" -msgstr "" +msgstr "Lösen" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Untitled Group" @@ -7662,7 +7663,7 @@ msgstr "Sehen Sie sich alle Sicherheitsaktivitäten in Ihrem Konto an." #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "View and manage all active sessions for your account." -msgstr "" +msgstr "Alle aktiven Sitzungen Ihres Kontos anzeigen und verwalten." #: apps/remix/app/components/forms/2fa/view-recovery-codes-dialog.tsx msgid "View Codes" @@ -8009,8 +8010,11 @@ msgstr "Wir konnten Ihre E-Mail derzeit nicht verifizieren." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "Wir konnten Ihre E-Mail nicht bestätigen. Wenn Ihre E-Mail noch nicht bestätigt wurde, versuchen Sie es bitte erneut." -#: apps/remix/app/components/dialogs/template-use-dialog.tsx #: packages/ui/primitives/document-flow/add-subject.tsx +msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." +msgstr "Wir generieren Signierlinks mit Ihnen, die Sie den Empfängern über Ihre bevorzugte Methode senden können." + +#: apps/remix/app/components/dialogs/template-use-dialog.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Wir werden Unterzeichnungslinks für Sie erstellen, die Sie an die Empfänger über Ihre bevorzugte Methode senden können." @@ -8724,3 +8728,4 @@ msgstr "Ihr Token wurde erfolgreich erstellt! Stellen Sie sicher, dass Sie es ko #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.tokens.tsx msgid "Your tokens will be shown here once you create them." msgstr "Ihre Tokens werden hier angezeigt, sobald Sie sie erstellt haben." + diff --git a/packages/lib/translations/es/web.po b/packages/lib/translations/es/web.po index 2a3f7b8e2..43c1321cc 100644 --- a/packages/lib/translations/es/web.po +++ b/packages/lib/translations/es/web.po @@ -8,7 +8,7 @@ msgstr "" "Language: es\n" "Project-Id-Version: documenso-app\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-10 02:27\n" +"PO-Revision-Date: 2025-06-19 06:05\n" "Last-Translator: \n" "Language-Team: Spanish\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -75,12 +75,12 @@ msgstr "{0, plural, one {# carácter sobre el límite} other {# caracteres sobre #. placeholder {0}: folder._count.documents #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# document} other {# documents}}" -msgstr "" +msgstr "{0, plural, one {# documento} other {# documentos}}" #. placeholder {0}: folder._count.subfolders #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# folder} other {# folders}}" -msgstr "" +msgstr "{0, plural, one {# carpeta} other {# carpetas}}" #. placeholder {0}: template.recipients.length #: apps/remix/app/routes/_recipient+/d.$token+/_index.tsx @@ -95,7 +95,7 @@ msgstr "{0, plural, one {# equipo} other {# equipos}}" #. placeholder {0}: folder._count.templates #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# template} other {# templates}}" -msgstr "" +msgstr "{0, plural, one {# plantilla} other {# plantillas}}" #. placeholder {0}: data.length #: apps/remix/app/components/general/organisations/organisation-invitations.tsx @@ -313,10 +313,6 @@ msgstr "{prefix} actualizó el título del documento" msgid "{prefix} updated the document visibility" msgstr "{prefix} actualizó la visibilidad del documento" -#: packages/lib/utils/document-audit-logs.ts -msgid "{prefix} viewed the document" -msgstr "" - #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} documento" @@ -774,7 +770,7 @@ msgstr "Activo" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Active sessions" -msgstr "" +msgstr "Sesiones activas" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Active Subscriptions" @@ -1345,7 +1341,7 @@ msgstr "¿Estás seguro de que quieres eliminar la siguiente solicitud?" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Are you sure you want to delete this folder?" -msgstr "" +msgstr "¿Está seguro de que quiere eliminar esta carpeta?" #: apps/remix/app/components/dialogs/token-delete-dialog.tsx msgid "Are you sure you want to delete this token?" @@ -1771,6 +1767,7 @@ msgstr "Haga clic aquí para comenzar" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Haga clic aquí para reintentar" @@ -2164,11 +2161,11 @@ msgstr "Crear documento a partir de la plantilla" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Create folder" -msgstr "" +msgstr "Crear carpeta" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create Folder" -msgstr "" +msgstr "Crear Carpeta" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx @@ -2181,7 +2178,7 @@ msgstr "Crear Grupos" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create New Folder" -msgstr "" +msgstr "Crear Nueva Carpeta" #: apps/remix/app/routes/_profile+/_layout.tsx msgid "Create now" @@ -2303,11 +2300,11 @@ msgstr "Estructura CSV" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Cumulative MAU (signed in)" -msgstr "" +msgstr "MAU acumulativo (con sesión iniciada)" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Current" -msgstr "" +msgstr "Actual" #: apps/remix/app/components/forms/password.tsx msgid "Current Password" @@ -2447,7 +2444,7 @@ msgstr "Eliminar Documento" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Delete Folder" -msgstr "" +msgstr "Eliminar Carpeta" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.general.tsx msgid "Delete organisation" @@ -2752,6 +2749,11 @@ msgstr "ID externo del documento actualizado" msgid "Document found in your account" msgstr "Documento encontrado en tu cuenta" +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Document history" +msgstr "Historial de documentos" + #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2870,10 +2872,6 @@ msgstr "La carga de documentos está deshabilitada debido a facturas impagadas" msgid "Document uploaded" msgstr "Documento subido" -#: packages/lib/utils/document-audit-logs.ts -msgid "Document viewed" -msgstr "" - #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Documento visto" @@ -3194,7 +3192,7 @@ msgstr "Documento Adjunto" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Enter a name for your new folder. Folders help you organise your items." -msgstr "" +msgstr "Ingrese un nombre para su nueva carpeta. Las carpetas le ayudan a organizar sus elementos." #: apps/remix/app/components/forms/subscription-claim-form.tsx msgid "Enter claim name" @@ -3334,7 +3332,7 @@ msgstr "Error al crear reclamación de suscripción." #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Failed to delete folder" -msgstr "" +msgstr "Error al eliminar la carpeta" #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Failed to delete subscription claim." @@ -3346,7 +3344,7 @@ msgstr "Error al cargar el documento" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Failed to move folder" -msgstr "" +msgstr "Error al mover la carpeta" #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx msgid "Failed to reseal document" @@ -3354,7 +3352,7 @@ msgstr "Falló al volver a sellar el documento" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Failed to revoke session" -msgstr "" +msgstr "Error al revocar la sesión" #: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx msgid "Failed to save settings." @@ -3362,7 +3360,7 @@ msgstr "Fallo al guardar configuraciones." #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Failed to sign out all sessions" -msgstr "" +msgstr "Error al cerrar sesión en todas las sesiones" #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx msgid "Failed to update document" @@ -3466,15 +3464,15 @@ msgstr "Carpeta creada exitosamente" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Folder deleted successfully" -msgstr "" +msgstr "Carpeta eliminada correctamente" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Folder moved successfully" -msgstr "" +msgstr "Carpeta movida correctamente" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Folder Name" -msgstr "" +msgstr "Nombre de la Carpeta" #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3714,6 +3712,10 @@ msgstr "Hola, {userName} <0>({userEmail})" msgid "Hide" msgstr "Ocultar" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Hide additional information" +msgstr "Ocultar información adicional" + #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3723,7 +3725,7 @@ msgstr "Inicio" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Home (No Folder)" -msgstr "" +msgstr "Inicio (Sin Carpeta)" #: packages/lib/constants/recipient-roles.ts msgid "I am a signer of this document" @@ -3972,7 +3974,7 @@ msgstr "Últimos 7 días" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Last Active" -msgstr "" +msgstr "Última actividad" #: apps/remix/app/components/general/template/template-page-view-information.tsx #: apps/remix/app/components/general/document/document-page-view-information.tsx @@ -4125,7 +4127,7 @@ msgstr "Gestiona permisos y controles de acceso" #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Manage sessions" -msgstr "" +msgstr "Gestionar sesiones" #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx @@ -4137,10 +4139,10 @@ msgstr "Gestionar suscripción" msgid "Manage the {0} organisation" msgstr "Gestionar la organización {0}" -#. placeholder {1}: organisation.name +#. placeholder {0}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {1} organisation subscription" -msgstr "" +msgid "Manage the {0} organisation subscription" +msgstr "Gestionar la suscripción de la organización {0}" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -4206,7 +4208,7 @@ msgstr "MAU (documento completado)" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "MAU (signed in)" -msgstr "" +msgstr "MAU (con sesión iniciada)" #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx msgid "Max" @@ -4295,7 +4297,7 @@ msgstr "Mover Documento a Carpeta" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Move Folder" -msgstr "" +msgstr "Mover Carpeta" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx msgid "Move Template to Folder" @@ -4312,7 +4314,7 @@ msgstr "Se pueden seleccionar varios métodos de acceso." #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "My Folder" -msgstr "" +msgstr "Mi Carpeta" #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx @@ -4405,12 +4407,12 @@ msgstr "No hay borradores activos" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "No folders found" -msgstr "" +msgstr "No se encontraron carpetas" #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx msgid "No folders found matching \"{searchTerm}\"" -msgstr "" +msgstr "No se encontraron carpetas que coincidan con \"{searchTerm}\"" #: apps/remix/app/routes/_recipient+/sign.$token+/rejected.tsx #: apps/remix/app/components/embed/embed-document-rejected.tsx @@ -4723,7 +4725,7 @@ msgstr "Organizaciones de las que el usuario es miembro." #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your documents" -msgstr "" +msgstr "Organiza tus documentos" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Organise your members into groups which can be assigned to teams" @@ -4731,7 +4733,7 @@ msgstr "Organiza a tus miembros en grupos que se puedan asignar a equipos" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your templates" -msgstr "" +msgstr "Organiza tus plantillas" #: apps/remix/app/routes/_authenticated+/o.$orgUrl._index.tsx msgid "Organize your documents and templates" @@ -4910,7 +4912,7 @@ msgstr "Elige cualquiera de los siguientes acuerdos a continuación y comience a #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Pin" -msgstr "" +msgstr "Fijar" #: packages/ui/primitives/document-flow/field-items-advanced-settings/text-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx @@ -5466,7 +5468,7 @@ msgstr "Revocar acceso" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Revoke all sessions" -msgstr "" +msgstr "Revocar todas las sesiones" #: apps/remix/app/components/tables/user-organisations-table.tsx #: apps/remix/app/components/tables/team-members-table.tsx @@ -5544,7 +5546,7 @@ msgstr "Buscar documentos..." #: apps/remix/app/components/dialogs/folder-move-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Search folders..." -msgstr "" +msgstr "Buscar carpetas..." #: packages/ui/components/common/language-switcher-dialog.tsx msgid "Search languages..." @@ -5572,7 +5574,7 @@ msgstr "Seleccionar" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Select a destination for this folder." -msgstr "" +msgstr "Selecciona un destino para esta carpeta." #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Select a folder to move this document to." @@ -5629,7 +5631,7 @@ msgstr "Seleccionar grupos" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups of members to add to the team." -msgstr "" +msgstr "Seleccionar grupos de miembros para añadir al equipo." #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups to add to this team" @@ -5753,11 +5755,11 @@ msgstr "Enviado" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Session revoked" -msgstr "" +msgstr "Sesión revocada" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Sessions have been revoked" -msgstr "" +msgstr "Las sesiones han sido revocadas" #: apps/remix/app/components/general/claim-account.tsx msgid "Set a password" @@ -5812,6 +5814,10 @@ msgstr "¡Comparte tu experiencia de firma!" msgid "Show" msgstr "Mostrar" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Show additional information" +msgstr "Mostrar información adicional" + #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -6627,8 +6633,7 @@ msgid "The following team has been deleted. You will no longer be able to access msgstr "El siguiente equipo ha sido eliminado. Ya no podrá acceder a este equipo y sus documentos" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups.$id.tsx -msgid "" -"The organisation group you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation group you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "El grupo de organización que está buscando puede haber sido eliminado, renombrado o puede que nunca haya existido." @@ -6637,14 +6642,12 @@ msgid "The organisation role that will be applied to all members in this group." msgstr "El rol de organización que se aplicará a todos los miembros de este grupo." #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "La organización que está buscando puede haber sido eliminada, renombrada o puede que nunca haya existido." #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "La organización que está buscando puede haber sido eliminada, renombrada o puede que nunca haya existido." @@ -6728,17 +6731,14 @@ msgid "The team email <0>{teamEmail} has been removed from the following tea msgstr "El correo electrónico del equipo <0>{teamEmail} ha sido eliminado del siguiente equipo" #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "El equipo que está buscando puede haber sido eliminado, renombrado o puede que nunca haya existido." #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." -msgstr "" -"El equipo que buscas puede haber sido eliminado, renombrado o quizás nunca\n" +msgstr "El equipo que buscas puede haber sido eliminado, renombrado o quizás nunca\n" " existió." #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx @@ -6775,8 +6775,7 @@ msgid "The URL for Documenso to send webhook events to." msgstr "La URL para Documenso para enviar eventos de webhook." #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx -msgid "" -"The user you are looking for may have been removed, renamed or may have never\n" +msgid "The user you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "El usuario que está buscando puede haber sido eliminado, renombrado o puede que nunca haya existido." @@ -6932,7 +6931,7 @@ msgstr "Este campo no se puede modificar ni eliminar. Cuando comparta el enlace #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "This folder contains multiple items. Deleting it will also delete all items in the folder, including nested folders and their contents." -msgstr "" +msgstr "Esta carpeta contiene múltiples elementos. Eliminándola también se eliminarán todos los elementos de la carpeta, incluidas las carpetas anidadas y sus contenidos." #: packages/ui/primitives/template-flow/add-template-settings.tsx msgid "This is how the document will reach the recipients once the document is ready for signing." @@ -7014,7 +7013,7 @@ msgstr "Esto solo retroalimentará las banderas de características que estén c #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "This will sign you out of all other devices. You will need to sign in again on those devices to continue using your account." -msgstr "" +msgstr "Esto cerrará la sesión en todos los demás dispositivos. Necesitarás iniciar sesión nuevamente en esos dispositivos para continuar usando tu cuenta." #: apps/remix/app/components/tables/internal-audit-log-table.tsx #: apps/remix/app/components/tables/document-logs-table.tsx @@ -7243,6 +7242,7 @@ msgid "Unable to join this organisation at this time." msgstr "No se puede unirse a esta organización en este momento." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "No se pudo cargar el historial del documento" @@ -7317,7 +7317,7 @@ msgstr "Documentos ilimitados, API y más" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Unpin" -msgstr "" +msgstr "Desanclar" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Untitled Group" @@ -7664,7 +7664,7 @@ msgstr "Ver toda la actividad de seguridad relacionada con tu cuenta." #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "View and manage all active sessions for your account." -msgstr "" +msgstr "Ver y gestionar todas las sesiones activas de tu cuenta." #: apps/remix/app/components/forms/2fa/view-recovery-codes-dialog.tsx msgid "View Codes" @@ -8011,8 +8011,11 @@ msgstr "No pudimos verificar tu correo electrónico en este momento." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "No pudimos verificar tu correo electrónico. Si tu correo electrónico no está verificado ya, por favor inténtalo de nuevo." -#: apps/remix/app/components/dialogs/template-use-dialog.tsx #: packages/ui/primitives/document-flow/add-subject.tsx +msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." +msgstr "Generaremos enlaces de firma para ti, que podrás enviar a los destinatarios a través de tu método preferido." + +#: apps/remix/app/components/dialogs/template-use-dialog.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Generaremos enlaces de firma para ti, que podrás enviar a los destinatarios a través de tu método preferido." @@ -8726,3 +8729,4 @@ msgstr "¡Tu token se creó con éxito! ¡Asegúrate de copiarlo porque no podr #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.tokens.tsx msgid "Your tokens will be shown here once you create them." msgstr "Tus tokens se mostrarán aquí una vez que los crees." + diff --git a/packages/lib/translations/fr/web.po b/packages/lib/translations/fr/web.po index 626500381..93f70462e 100644 --- a/packages/lib/translations/fr/web.po +++ b/packages/lib/translations/fr/web.po @@ -8,7 +8,7 @@ msgstr "" "Language: fr\n" "Project-Id-Version: documenso-app\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-10 02:27\n" +"PO-Revision-Date: 2025-06-19 06:05\n" "Last-Translator: \n" "Language-Team: French\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" @@ -75,12 +75,12 @@ msgstr "{0, plural, one {# caractère au-dessus de la limite} other {# caractèr #. placeholder {0}: folder._count.documents #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# document} other {# documents}}" -msgstr "" +msgstr "{0, plural, one {# document} other {# documents}}" #. placeholder {0}: folder._count.subfolders #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# folder} other {# folders}}" -msgstr "" +msgstr "{0, plural, one {# dossier} other {# dossiers}}" #. placeholder {0}: template.recipients.length #: apps/remix/app/routes/_recipient+/d.$token+/_index.tsx @@ -95,7 +95,7 @@ msgstr "{0, plural, one {# équipe} other {# équipes}}" #. placeholder {0}: folder._count.templates #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# template} other {# templates}}" -msgstr "" +msgstr "{0, plural, one {# modèle} other {# modèles}}" #. placeholder {0}: data.length #: apps/remix/app/components/general/organisations/organisation-invitations.tsx @@ -313,10 +313,6 @@ msgstr "{prefix} a mis à jour le titre du document" msgid "{prefix} updated the document visibility" msgstr "{prefix} a mis à jour la visibilité du document" -#: packages/lib/utils/document-audit-logs.ts -msgid "{prefix} viewed the document" -msgstr "" - #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} document" @@ -774,7 +770,7 @@ msgstr "Actif" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Active sessions" -msgstr "" +msgstr "Sessions actives" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Active Subscriptions" @@ -1345,7 +1341,7 @@ msgstr "Êtes-vous sûr de vouloir supprimer la réclamation suivante?" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Are you sure you want to delete this folder?" -msgstr "" +msgstr "Êtes-vous sûr de vouloir supprimer ce dossier ?" #: apps/remix/app/components/dialogs/token-delete-dialog.tsx msgid "Are you sure you want to delete this token?" @@ -1771,6 +1767,7 @@ msgstr "Cliquez ici pour commencer" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Cliquez ici pour réessayer" @@ -2164,11 +2161,11 @@ msgstr "Créer un document à partir du modèle" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Create folder" -msgstr "" +msgstr "Créer un dossier" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create Folder" -msgstr "" +msgstr "Créer un Dossier" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx @@ -2181,7 +2178,7 @@ msgstr "Créer des groupes" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create New Folder" -msgstr "" +msgstr "Créer un Nouveau Dossier" #: apps/remix/app/routes/_profile+/_layout.tsx msgid "Create now" @@ -2303,11 +2300,11 @@ msgstr "Structure CSV" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Cumulative MAU (signed in)" -msgstr "" +msgstr "MAU cumulatif (connecté)" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Current" -msgstr "" +msgstr "Actuel" #: apps/remix/app/components/forms/password.tsx msgid "Current Password" @@ -2447,7 +2444,7 @@ msgstr "Supprimer le document" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Delete Folder" -msgstr "" +msgstr "Supprimer le Dossier" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.general.tsx msgid "Delete organisation" @@ -2752,6 +2749,11 @@ msgstr "ID externe du document mis à jour" msgid "Document found in your account" msgstr "Document trouvé dans votre compte" +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Document history" +msgstr "Historique du document" + #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2870,10 +2872,6 @@ msgstr "Importation de documents désactivé en raison de factures impayées" msgid "Document uploaded" msgstr "Document importé" -#: packages/lib/utils/document-audit-logs.ts -msgid "Document viewed" -msgstr "" - #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Document consulté" @@ -3194,7 +3192,7 @@ msgstr "Document joint" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Enter a name for your new folder. Folders help you organise your items." -msgstr "" +msgstr "Entrez un nom pour votre nouveau dossier. Les dossiers vous aident à organiser vos éléments." #: apps/remix/app/components/forms/subscription-claim-form.tsx msgid "Enter claim name" @@ -3334,7 +3332,7 @@ msgstr "Échec de la création de la réclamation d'abonnement." #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Failed to delete folder" -msgstr "" +msgstr "Échec de la suppression du dossier" #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Failed to delete subscription claim." @@ -3346,7 +3344,7 @@ msgstr "Échec du chargement du document" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Failed to move folder" -msgstr "" +msgstr "Échec du déplacement du dossier" #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx msgid "Failed to reseal document" @@ -3354,7 +3352,7 @@ msgstr "Échec du reseal du document" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Failed to revoke session" -msgstr "" +msgstr "Échec de la révocation de la session" #: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx msgid "Failed to save settings." @@ -3362,7 +3360,7 @@ msgstr "Échec de l'enregistrement des paramètres." #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Failed to sign out all sessions" -msgstr "" +msgstr "Impossible de se déconnecter de toutes les sessions" #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx msgid "Failed to update document" @@ -3466,15 +3464,15 @@ msgstr "Dossier créé avec succès" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Folder deleted successfully" -msgstr "" +msgstr "Dossier supprimé avec succès" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Folder moved successfully" -msgstr "" +msgstr "Dossier déplacé avec succès" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Folder Name" -msgstr "" +msgstr "Nom du Dossier" #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3714,6 +3712,10 @@ msgstr "Bonjour, {userName} <0>({userEmail})" msgid "Hide" msgstr "Cacher" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Hide additional information" +msgstr "Cacher des informations supplémentaires" + #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3723,7 +3725,7 @@ msgstr "Accueil" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Home (No Folder)" -msgstr "" +msgstr "Accueil (Pas de Dossier)" #: packages/lib/constants/recipient-roles.ts msgid "I am a signer of this document" @@ -3972,7 +3974,7 @@ msgstr "7 derniers jours" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Last Active" -msgstr "" +msgstr "Dernière activité" #: apps/remix/app/components/general/template/template-page-view-information.tsx #: apps/remix/app/components/general/document/document-page-view-information.tsx @@ -4125,7 +4127,7 @@ msgstr "Gérez les autorisations et les contrôles d'accès" #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Manage sessions" -msgstr "" +msgstr "Gérer les sessions" #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx @@ -4137,10 +4139,10 @@ msgstr "Gérer l'abonnement" msgid "Manage the {0} organisation" msgstr "Gérer l'organisation {0}" -#. placeholder {1}: organisation.name +#. placeholder {0}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {1} organisation subscription" -msgstr "" +msgid "Manage the {0} organisation subscription" +msgstr "Gérer l'abonnement de l'organisation {0}" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -4206,7 +4208,7 @@ msgstr "MAU (document terminé)" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "MAU (signed in)" -msgstr "" +msgstr "MAU (connecté)" #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx msgid "Max" @@ -4295,7 +4297,7 @@ msgstr "Déplacer le document vers un dossier" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Move Folder" -msgstr "" +msgstr "Déplacer le Dossier" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx msgid "Move Template to Folder" @@ -4312,7 +4314,7 @@ msgstr "Plusieurs méthodes d'accès peuvent être sélectionnées." #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "My Folder" -msgstr "" +msgstr "Mon Dossier" #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx @@ -4405,12 +4407,12 @@ msgstr "Pas de brouillons actifs" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "No folders found" -msgstr "" +msgstr "Aucun dossier trouvé" #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx msgid "No folders found matching \"{searchTerm}\"" -msgstr "" +msgstr "Aucun dossier correspondant à \"{searchTerm}\" trouvé" #: apps/remix/app/routes/_recipient+/sign.$token+/rejected.tsx #: apps/remix/app/components/embed/embed-document-rejected.tsx @@ -4723,7 +4725,7 @@ msgstr "Organisations dont l'utilisateur est membre." #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your documents" -msgstr "" +msgstr "Organisez vos documents" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Organise your members into groups which can be assigned to teams" @@ -4731,7 +4733,7 @@ msgstr "Organisez vos membres en groupes qui peuvent être assignés à des équ #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your templates" -msgstr "" +msgstr "Organisez vos modèles" #: apps/remix/app/routes/_authenticated+/o.$orgUrl._index.tsx msgid "Organize your documents and templates" @@ -4910,7 +4912,7 @@ msgstr "Choisissez l'un des accords suivants ci-dessous et commencez à signer p #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Pin" -msgstr "" +msgstr "Épingler" #: packages/ui/primitives/document-flow/field-items-advanced-settings/text-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx @@ -5466,7 +5468,7 @@ msgstr "Révoquer l'accès" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Revoke all sessions" -msgstr "" +msgstr "Révoquer toutes les sessions" #: apps/remix/app/components/tables/user-organisations-table.tsx #: apps/remix/app/components/tables/team-members-table.tsx @@ -5544,7 +5546,7 @@ msgstr "Rechercher des documents..." #: apps/remix/app/components/dialogs/folder-move-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Search folders..." -msgstr "" +msgstr "Rechercher dans les dossiers..." #: packages/ui/components/common/language-switcher-dialog.tsx msgid "Search languages..." @@ -5572,7 +5574,7 @@ msgstr "Sélectionner" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Select a destination for this folder." -msgstr "" +msgstr "Sélectionnez une destination pour ce dossier." #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Select a folder to move this document to." @@ -5629,7 +5631,7 @@ msgstr "Sélectionnez des groupes" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups of members to add to the team." -msgstr "" +msgstr "Sélectionnez des groupes de membres à ajouter à l'équipe." #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups to add to this team" @@ -5753,11 +5755,11 @@ msgstr "Envoyé" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Session revoked" -msgstr "" +msgstr "Session révoquée" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Sessions have been revoked" -msgstr "" +msgstr "Les sessions ont été révoquées" #: apps/remix/app/components/general/claim-account.tsx msgid "Set a password" @@ -5812,6 +5814,10 @@ msgstr "Partagez votre expérience de signature !" msgid "Show" msgstr "Afficher" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Show additional information" +msgstr "Afficher des informations supplémentaires" + #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -6627,8 +6633,7 @@ msgid "The following team has been deleted. You will no longer be able to access msgstr "L'équipe suivante a été supprimée. Vous ne pourrez plus accéder à cette équipe et à ses documents" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups.$id.tsx -msgid "" -"The organisation group you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation group you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Le groupe d'organisation que vous cherchez peut avoir été supprimé, renommé ou n'a peut-être jamais existé." @@ -6637,14 +6642,12 @@ msgid "The organisation role that will be applied to all members in this group." msgstr "Le rôle d'organisation qui sera appliqué à tous les membres de ce groupe." #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "L'organisation que vous cherchez peut avoir été supprimée, renommée ou n'a peut-être jamais existé." #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "L'organisation que vous cherchez peut avoir été supprimée, renommée ou n'a peut-être jamais existé." @@ -6728,14 +6731,12 @@ msgid "The team email <0>{teamEmail} has been removed from the following tea msgstr "L'email d'équipe <0>{teamEmail} a été supprimé de l'équipe suivante" #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "L'équipe que vous cherchez peut avoir été supprimée, renommée ou n'a peut-être jamais existé." #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "L'équipe que vous cherchez a peut-être été supprimée, renommée ou n'a peut-être jamais existé." @@ -6773,8 +6774,7 @@ msgid "The URL for Documenso to send webhook events to." msgstr "L'URL pour Documenso pour envoyer des événements webhook." #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx -msgid "" -"The user you are looking for may have been removed, renamed or may have never\n" +msgid "The user you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "L'utilisateur que vous cherchez peut avoir été supprimé, renommé ou n'a peut-être jamais existé." @@ -6930,7 +6930,7 @@ msgstr "Ce champ ne peut pas être modifié ou supprimé. Lorsque vous partagez #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "This folder contains multiple items. Deleting it will also delete all items in the folder, including nested folders and their contents." -msgstr "" +msgstr "Ce dossier contient plusieurs éléments. Le supprimer supprimera également tous les éléments du dossier, y compris les dossiers imbriqués et leur contenu." #: packages/ui/primitives/template-flow/add-template-settings.tsx msgid "This is how the document will reach the recipients once the document is ready for signing." @@ -7012,7 +7012,7 @@ msgstr "Cela ne fera que rétroporter les drapeaux de fonctionnalité qui sont a #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "This will sign you out of all other devices. You will need to sign in again on those devices to continue using your account." -msgstr "" +msgstr "Cela entraînera votre déconnexion de tous les autres appareils. Vous devrez vous reconnecter sur ces appareils pour continuer à utiliser votre compte." #: apps/remix/app/components/tables/internal-audit-log-table.tsx #: apps/remix/app/components/tables/document-logs-table.tsx @@ -7241,6 +7241,7 @@ msgid "Unable to join this organisation at this time." msgstr "Impossible de rejoindre cette organisation pour le moment." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Impossible de charger l'historique des documents" @@ -7315,7 +7316,7 @@ msgstr "Documents illimités, API et plus" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Unpin" -msgstr "" +msgstr "Détacher" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Untitled Group" @@ -7662,7 +7663,7 @@ msgstr "Voir toute l'activité de sécurité liée à votre compte." #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "View and manage all active sessions for your account." -msgstr "" +msgstr "Afficher et gérer toutes les sessions actives de votre compte." #: apps/remix/app/components/forms/2fa/view-recovery-codes-dialog.tsx msgid "View Codes" @@ -8009,8 +8010,11 @@ msgstr "Nous n'avons pas pu vérifier votre email pour le moment." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "Nous n'avons pas pu vérifier votre e-mail. Si votre e-mail n'est pas déjà vérifié, veuillez réessayer." -#: apps/remix/app/components/dialogs/template-use-dialog.tsx #: packages/ui/primitives/document-flow/add-subject.tsx +msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." +msgstr "Nous générerons des liens de signature pour vous, que vous pourrez envoyer aux destinataires par votre méthode de choix." + +#: apps/remix/app/components/dialogs/template-use-dialog.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Nous allons générer des liens de signature pour vous, que vous pouvez envoyer aux destinataires par votre méthode de choix." @@ -8724,3 +8728,4 @@ msgstr "Votre token a été créé avec succès ! Assurez-vous de le copier car #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.tokens.tsx msgid "Your tokens will be shown here once you create them." msgstr "Vos tokens seront affichés ici une fois que vous les aurez créés." + diff --git a/packages/lib/translations/it/web.po b/packages/lib/translations/it/web.po index fe707fb30..97738127a 100644 --- a/packages/lib/translations/it/web.po +++ b/packages/lib/translations/it/web.po @@ -8,7 +8,7 @@ msgstr "" "Language: it\n" "Project-Id-Version: documenso-app\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-10 02:27\n" +"PO-Revision-Date: 2025-06-19 06:05\n" "Last-Translator: \n" "Language-Team: Italian\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -75,12 +75,12 @@ msgstr "{0, plural, one {# carattere oltre il limite} other {# caratteri oltre i #. placeholder {0}: folder._count.documents #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# document} other {# documents}}" -msgstr "" +msgstr "{0, plural, one {# documento} other {# documenti}}" #. placeholder {0}: folder._count.subfolders #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# folder} other {# folders}}" -msgstr "" +msgstr "{0, plural, one {# cartella} other {# cartelle}}" #. placeholder {0}: template.recipients.length #: apps/remix/app/routes/_recipient+/d.$token+/_index.tsx @@ -95,7 +95,7 @@ msgstr "{0, plural, one {# squadra} other {# squadre}}" #. placeholder {0}: folder._count.templates #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# template} other {# templates}}" -msgstr "" +msgstr "{0, plural, one {# modello} other {# modelli}}" #. placeholder {0}: data.length #: apps/remix/app/components/general/organisations/organisation-invitations.tsx @@ -313,10 +313,6 @@ msgstr "{prefix} ha aggiornato il titolo del documento" msgid "{prefix} updated the document visibility" msgstr "{prefix} ha aggiornato la visibilità del documento" -#: packages/lib/utils/document-audit-logs.ts -msgid "{prefix} viewed the document" -msgstr "" - #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} documento" @@ -774,7 +770,7 @@ msgstr "Attivo" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Active sessions" -msgstr "" +msgstr "Sessioni attive" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Active Subscriptions" @@ -1345,7 +1341,7 @@ msgstr "Sei sicuro di voler eliminare la seguente richiesta?" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Are you sure you want to delete this folder?" -msgstr "" +msgstr "Sei sicuro di voler eliminare questa cartella?" #: apps/remix/app/components/dialogs/token-delete-dialog.tsx msgid "Are you sure you want to delete this token?" @@ -1771,6 +1767,7 @@ msgstr "Clicca qui per iniziare" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Clicca qui per riprovare" @@ -2164,11 +2161,11 @@ msgstr "Crea documento da modello" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Create folder" -msgstr "" +msgstr "Crea cartella" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create Folder" -msgstr "" +msgstr "Crea Cartella" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx @@ -2181,7 +2178,7 @@ msgstr "Crea Gruppi" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create New Folder" -msgstr "" +msgstr "Crea Nuova Cartella" #: apps/remix/app/routes/_profile+/_layout.tsx msgid "Create now" @@ -2307,7 +2304,7 @@ msgstr "" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Current" -msgstr "" +msgstr "Corrente" #: apps/remix/app/components/forms/password.tsx msgid "Current Password" @@ -2447,7 +2444,7 @@ msgstr "Elimina Documento" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Delete Folder" -msgstr "" +msgstr "Elimina Cartella" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.general.tsx msgid "Delete organisation" @@ -2752,6 +2749,11 @@ msgstr "ID esterno del documento aggiornato" msgid "Document found in your account" msgstr "Documento trovato nel tuo account" +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Document history" +msgstr "Cronologia del documento" + #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2870,10 +2872,6 @@ msgstr "Caricamento del documento disabilitato a causa di fatture non pagate" msgid "Document uploaded" msgstr "Documento caricato" -#: packages/lib/utils/document-audit-logs.ts -msgid "Document viewed" -msgstr "" - #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Documento visualizzato" @@ -3194,7 +3192,7 @@ msgstr "Documento Allegato" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Enter a name for your new folder. Folders help you organise your items." -msgstr "" +msgstr "Inserisci un nome per la tua nuova cartella. Le cartelle ti aiutano a organizzare i tuoi elementi." #: apps/remix/app/components/forms/subscription-claim-form.tsx msgid "Enter claim name" @@ -3334,7 +3332,7 @@ msgstr "Creazione della richiesta di abbonamento non riuscita." #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Failed to delete folder" -msgstr "" +msgstr "Impossibile eliminare la cartella" #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Failed to delete subscription claim." @@ -3346,7 +3344,7 @@ msgstr "Caricamento documento fallito." #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Failed to move folder" -msgstr "" +msgstr "Impossibile spostare la cartella" #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx msgid "Failed to reseal document" @@ -3354,7 +3352,7 @@ msgstr "Fallito il risigillo del documento" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Failed to revoke session" -msgstr "" +msgstr "Impossibile revocare la sessione" #: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx msgid "Failed to save settings." @@ -3362,7 +3360,7 @@ msgstr "Impossibile salvare le impostazioni." #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Failed to sign out all sessions" -msgstr "" +msgstr "Non è stato possibile disconnettere tutte le sessioni" #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx msgid "Failed to update document" @@ -3466,15 +3464,15 @@ msgstr "Cartella creata con successo" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Folder deleted successfully" -msgstr "" +msgstr "Cartella eliminata con successo" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Folder moved successfully" -msgstr "" +msgstr "Cartella spostata con successo" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Folder Name" -msgstr "" +msgstr "Nome Cartella" #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3714,6 +3712,10 @@ msgstr "Ciao, {userName} <0>({userEmail})" msgid "Hide" msgstr "Nascondi" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Hide additional information" +msgstr "Nascondi informazioni aggiuntive" + #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3723,7 +3725,7 @@ msgstr "Home" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Home (No Folder)" -msgstr "" +msgstr "Home (Nessuna Cartella)" #: packages/lib/constants/recipient-roles.ts msgid "I am a signer of this document" @@ -3972,7 +3974,7 @@ msgstr "Ultimi 7 giorni" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Last Active" -msgstr "" +msgstr "Ultimo accesso" #: apps/remix/app/components/general/template/template-page-view-information.tsx #: apps/remix/app/components/general/document/document-page-view-information.tsx @@ -4125,7 +4127,7 @@ msgstr "Gestisci le autorizzazioni e i controlli di accesso" #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Manage sessions" -msgstr "" +msgstr "Gestisci le sessioni" #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx @@ -4137,10 +4139,10 @@ msgstr "Gestisci abbonamento" msgid "Manage the {0} organisation" msgstr "Gestisci l'organizzazione {0}" -#. placeholder {1}: organisation.name +#. placeholder {0}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {1} organisation subscription" -msgstr "" +msgid "Manage the {0} organisation subscription" +msgstr "Gestisci l'abbonamento dell'organizzazione {0}" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -4295,7 +4297,7 @@ msgstr "Sposta documento nella cartella" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Move Folder" -msgstr "" +msgstr "Sposta Cartella" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx msgid "Move Template to Folder" @@ -4312,7 +4314,7 @@ msgstr "Possono essere selezionati più metodi di accesso." #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "My Folder" -msgstr "" +msgstr "La Mia Cartella" #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx @@ -4405,12 +4407,12 @@ msgstr "Nessuna bozza attiva" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "No folders found" -msgstr "" +msgstr "Nessuna cartella trovata" #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx msgid "No folders found matching \"{searchTerm}\"" -msgstr "" +msgstr "Nessuna cartella trovata corrispondente a \"{searchTerm}\"" #: apps/remix/app/routes/_recipient+/sign.$token+/rejected.tsx #: apps/remix/app/components/embed/embed-document-rejected.tsx @@ -4723,7 +4725,7 @@ msgstr "Organizzazioni di cui l'utente è membro." #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your documents" -msgstr "" +msgstr "Organizza i tuoi documenti" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Organise your members into groups which can be assigned to teams" @@ -4731,7 +4733,7 @@ msgstr "Organizza i tuoi membri in gruppi che possono essere assegnati ai team." #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your templates" -msgstr "" +msgstr "Organizza i tuoi modelli" #: apps/remix/app/routes/_authenticated+/o.$orgUrl._index.tsx msgid "Organize your documents and templates" @@ -4910,7 +4912,7 @@ msgstr "Scegli uno dei seguenti accordi e inizia a firmare per iniziare" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Pin" -msgstr "" +msgstr "Fissa" #: packages/ui/primitives/document-flow/field-items-advanced-settings/text-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx @@ -5466,7 +5468,7 @@ msgstr "Revoca l'accesso" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Revoke all sessions" -msgstr "" +msgstr "Revoca tutte le sessioni" #: apps/remix/app/components/tables/user-organisations-table.tsx #: apps/remix/app/components/tables/team-members-table.tsx @@ -5544,7 +5546,7 @@ msgstr "Cerca documenti..." #: apps/remix/app/components/dialogs/folder-move-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Search folders..." -msgstr "" +msgstr "Cerca cartelle..." #: packages/ui/components/common/language-switcher-dialog.tsx msgid "Search languages..." @@ -5572,7 +5574,7 @@ msgstr "Seleziona" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Select a destination for this folder." -msgstr "" +msgstr "Seleziona una destinazione per questa cartella." #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Select a folder to move this document to." @@ -5629,7 +5631,7 @@ msgstr "Seleziona gruppi" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups of members to add to the team." -msgstr "" +msgstr "Seleziona i gruppi di membri da aggiungere al team." #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups to add to this team" @@ -5753,11 +5755,11 @@ msgstr "Inviato" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Session revoked" -msgstr "" +msgstr "Sessione revocata" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Sessions have been revoked" -msgstr "" +msgstr "Le sessioni sono state revocate" #: apps/remix/app/components/general/claim-account.tsx msgid "Set a password" @@ -5812,6 +5814,10 @@ msgstr "Condividi la tua esperienza di firma!" msgid "Show" msgstr "Mostra" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Show additional information" +msgstr "Mostra informazioni aggiuntive" + #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -6627,11 +6633,9 @@ msgid "The following team has been deleted. You will no longer be able to access msgstr "Il seguente team è stato eliminato. Non potrai più accedere a questo team e ai suoi documenti" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups.$id.tsx -msgid "" -"The organisation group you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation group you are looking for may have been removed, renamed or may have never\n" " existed." -msgstr "" -"Il gruppo organizzativo che cerchi potrebbe essere stato rimosso, rinominato o potrebbe non essere mai\n" +msgstr "Il gruppo organizzativo che cerchi potrebbe essere stato rimosso, rinominato o potrebbe non essere mai\n" " esistito." #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups.$id.tsx @@ -6639,19 +6643,15 @@ msgid "The organisation role that will be applied to all members in this group." msgstr "Il ruolo organizzativo che verrà applicato a tutti i membri in questo gruppo." #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." -msgstr "" -"L'organizzazione che cerchi potrebbe essere stata rimossa, rinominata o potrebbe non essere mai\n" +msgstr "L'organizzazione che cerchi potrebbe essere stata rimossa, rinominata o potrebbe non essere mai\n" " esistita." #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." -msgstr "" -"L'organizzazione che cerchi potrebbe essere stata rimossa, rinominata o potrebbe non essere mai\n" +msgstr "L'organizzazione che cerchi potrebbe essere stata rimossa, rinominata o potrebbe non essere mai\n" " esistita." #: apps/remix/app/components/general/generic-error-layout.tsx @@ -6734,19 +6734,15 @@ msgid "The team email <0>{teamEmail} has been removed from the following tea msgstr "L'email del team <0>{teamEmail} è stata rimossa dal seguente team" #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." -msgstr "" -"Il team che cerchi potrebbe essere stato rimosso, rinominato o potrebbe non essere mai\n" +msgstr "Il team che cerchi potrebbe essere stato rimosso, rinominato o potrebbe non essere mai\n" " esistito." #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." -msgstr "" -"La squadra che stai cercando potrebbe essere stata rimossa, rinominata o potrebbe non essere mai\n" +msgstr "La squadra che stai cercando potrebbe essere stata rimossa, rinominata o potrebbe non essere mai\n" " esistita." #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx @@ -6783,11 +6779,9 @@ msgid "The URL for Documenso to send webhook events to." msgstr "L'URL per Documenso per inviare eventi webhook." #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx -msgid "" -"The user you are looking for may have been removed, renamed or may have never\n" +msgid "The user you are looking for may have been removed, renamed or may have never\n" " existed." -msgstr "" -"L'utente che cerchi potrebbe essere stato rimosso, rinominato o potrebbe non essere mai\n" +msgstr "L'utente che cerchi potrebbe essere stato rimosso, rinominato o potrebbe non essere mai\n" " esistito." #: apps/remix/app/components/dialogs/webhook-delete-dialog.tsx @@ -6942,7 +6936,7 @@ msgstr "Questo campo non può essere modificato o eliminato. Quando condividi il #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "This folder contains multiple items. Deleting it will also delete all items in the folder, including nested folders and their contents." -msgstr "" +msgstr "Questa cartella contiene più elementi. Cancellarla eliminerà anche tutti gli elementi nella cartella, incluse le cartelle nidificate e i loro contenuti." #: packages/ui/primitives/template-flow/add-template-settings.tsx msgid "This is how the document will reach the recipients once the document is ready for signing." @@ -7024,7 +7018,7 @@ msgstr "Questo farà SOLO il retroporting degli indicatori delle funzionalità i #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "This will sign you out of all other devices. You will need to sign in again on those devices to continue using your account." -msgstr "" +msgstr "Questa azione ti disconnetterà da tutti gli altri dispositivi. Dovrai accedere nuovamente su quei dispositivi per continuare a usare il tuo account." #: apps/remix/app/components/tables/internal-audit-log-table.tsx #: apps/remix/app/components/tables/document-logs-table.tsx @@ -7253,6 +7247,7 @@ msgid "Unable to join this organisation at this time." msgstr "Impossibile unirsi a questa organizzazione in questo momento." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Impossibile caricare la cronologia del documento" @@ -7327,7 +7322,7 @@ msgstr "Documenti illimitati, API e altro" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Unpin" -msgstr "" +msgstr "Rimuovi" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Untitled Group" @@ -7674,7 +7669,7 @@ msgstr "Visualizza tutte le attività di sicurezza relative al tuo account." #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "View and manage all active sessions for your account." -msgstr "" +msgstr "Visualizza e gestisci tutte le sessioni attive per il tuo account." #: apps/remix/app/components/forms/2fa/view-recovery-codes-dialog.tsx msgid "View Codes" @@ -8021,8 +8016,11 @@ msgstr "Non siamo stati in grado di verificare la tua email in questo momento." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "Non siamo riusciti a verificare la tua email. Se la tua email non è già verificata, riprova." -#: apps/remix/app/components/dialogs/template-use-dialog.tsx #: packages/ui/primitives/document-flow/add-subject.tsx +msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." +msgstr "Genereremo link di firma con te, che potrai inviare ai destinatari tramite il tuo metodo preferito." + +#: apps/remix/app/components/dialogs/template-use-dialog.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Genereremo link di firma per te, che potrai inviare ai destinatari tramite il metodo di tua scelta." @@ -8736,3 +8734,4 @@ msgstr "Il tuo token è stato creato con successo! Assicurati di copiarlo perch #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.tokens.tsx msgid "Your tokens will be shown here once you create them." msgstr "I tuoi token verranno mostrati qui una volta creati." + diff --git a/packages/lib/translations/ko/web.po b/packages/lib/translations/ko/web.po index 5cc79a1a2..9a838eba6 100644 --- a/packages/lib/translations/ko/web.po +++ b/packages/lib/translations/ko/web.po @@ -8,7 +8,7 @@ msgstr "" "Language: ko\n" "Project-Id-Version: documenso-app\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-10 02:27\n" +"PO-Revision-Date: 2025-06-19 06:05\n" "Last-Translator: \n" "Language-Team: Korean\n" "Plural-Forms: nplurals=1; plural=0;\n" @@ -72,6 +72,16 @@ msgstr "{0, plural, other {(#자 초과)}}" msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}" msgstr "{0, plural, other {#자 제한 초과}}" +#. placeholder {0}: folder._count.documents +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "{0, plural, one {# document} other {# documents}}" +msgstr "{0, plural, other {# 문서}}" + +#. placeholder {0}: folder._count.subfolders +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "{0, plural, one {# folder} other {# folders}}" +msgstr "{0, plural, other {# 폴더}}" + #. placeholder {0}: template.recipients.length #: apps/remix/app/routes/_recipient+/d.$token+/_index.tsx msgid "{0, plural, one {# recipient} other {# recipients}}" @@ -82,6 +92,11 @@ msgstr "{0, plural, other {#명의 수신자}}" msgid "{0, plural, one {# team} other {# teams}}" msgstr "" +#. placeholder {0}: folder._count.templates +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "{0, plural, one {# template} other {# templates}}" +msgstr "{0, plural, other {# 템플릿}}" + #. placeholder {0}: data.length #: apps/remix/app/components/general/organisations/organisation-invitations.tsx #: apps/remix/app/components/general/organisations/organisation-invitations.tsx @@ -752,6 +767,11 @@ msgstr "행동들" msgid "Active" msgstr "활성화됨" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx +msgid "Active sessions" +msgstr "활성 세션" + #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Active Subscriptions" msgstr "활성 구독" @@ -817,13 +837,13 @@ msgstr "필드 추가" msgid "Add group roles" msgstr "그룹 역할 추가" +#: apps/remix/app/components/dialogs/team-group-create-dialog.tsx #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Add groups" msgstr "그룹 추가" #: apps/remix/app/components/dialogs/team-member-create-dialog.tsx #: apps/remix/app/components/dialogs/team-member-create-dialog.tsx -#: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Add members" msgstr "멤버 추가" @@ -1243,17 +1263,14 @@ msgstr "예상치 못한 오류가 발생했습니다." msgid "An unknown error occurred" msgstr "알 수 없는 오류가 발생했습니다" -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "An unknown error occurred while creating the folder." msgstr "폴더를 생성하는 동안 알 수 없는 오류가 발생했습니다." -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "An unknown error occurred while deleting the folder." msgstr "폴더를 삭제하는 동안 알 수 없는 오류가 발생했습니다." -#: apps/remix/app/components/dialogs/template-folder-move-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "An unknown error occurred while moving the folder." msgstr "폴더를 이동하는 동안 알 수 없는 오류가 발생했습니다." @@ -1322,6 +1339,10 @@ msgstr "문서를 완료하시겠습니까? 이 작업은 되돌릴 수 없습 msgid "Are you sure you want to delete the following claim?" msgstr "정말 이 클레임을 삭제하시겠습니까?" +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "Are you sure you want to delete this folder?" +msgstr "이 폴더를 삭제하시겠습니까?" + #: apps/remix/app/components/dialogs/token-delete-dialog.tsx msgid "Are you sure you want to delete this token?" msgstr "정말 이 토큰을 삭제하시겠습니까?" @@ -1614,6 +1635,7 @@ msgstr "준비 가능" #: apps/remix/app/components/dialogs/team-delete-dialog.tsx #: apps/remix/app/components/dialogs/team-create-dialog.tsx #: apps/remix/app/components/dialogs/team-create-dialog.tsx +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/public-profile-template-manage-dialog.tsx #: apps/remix/app/components/dialogs/passkey-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-member-update-dialog.tsx @@ -1626,6 +1648,9 @@ msgstr "준비 가능" #: apps/remix/app/components/dialogs/organisation-delete-dialog.tsx #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx #: apps/remix/app/components/dialogs/document-resend-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-duplicate-dialog.tsx @@ -1921,7 +1946,6 @@ msgstr "확인을 위해 입력하세요 <0>{deleteMessage}" #: apps/remix/app/components/dialogs/webhook-delete-dialog.tsx #: apps/remix/app/components/dialogs/token-delete-dialog.tsx -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Confirm by typing: <0>{deleteMessage}" msgstr "확인을 위해 입력하세요: <0>{deleteMessage}" @@ -2065,6 +2089,7 @@ msgstr "토큰 복사" #: apps/remix/app/components/dialogs/webhook-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx #: apps/remix/app/components/dialogs/admin-organisation-create-dialog.tsx msgid "Create" msgstr "만들기" @@ -2134,6 +2159,14 @@ msgstr "직접 서명 링크 생성" msgid "Create document from template" msgstr "템플릿에서 문서 생성" +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Create folder" +msgstr "폴더 만들기" + +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "Create Folder" +msgstr "폴더 생성" + #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Create group" @@ -2143,6 +2176,10 @@ msgstr "그룹 생성" msgid "Create Groups" msgstr "그룹 생성" +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "Create New Folder" +msgstr "새 폴더 생성" + #: apps/remix/app/routes/_profile+/_layout.tsx msgid "Create now" msgstr "지금 생성" @@ -2221,6 +2258,7 @@ msgstr "계정을 만들고 최첨단 문서 서명을 사용해보세요." msgid "Create your account and start using state-of-the-art document signing. Open and beautiful signing is within your grasp." msgstr "계정을 만들고 최첨단 문서 서명을 사용해보세요. 개방적이고 아름다운 서명은 당신의 손 안에 있습니다." +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/admin+/documents._index.tsx #: apps/remix/app/components/tables/templates-table.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx @@ -2260,6 +2298,14 @@ msgstr "{0}에 생성됨" msgid "CSV Structure" msgstr "CSV 구조" +#: apps/remix/app/routes/_authenticated+/admin+/stats.tsx +msgid "Cumulative MAU (signed in)" +msgstr "누적 MAU (로그인 완료)" + +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +msgid "Current" +msgstr "현재" + #: apps/remix/app/components/forms/password.tsx msgid "Current Password" msgstr "현재 비밀번호" @@ -2342,6 +2388,7 @@ msgstr "삭제" #: apps/remix/app/components/tables/organisation-groups-table.tsx #: apps/remix/app/components/tables/documents-table-action-dropdown.tsx #: apps/remix/app/components/tables/admin-claims-table.tsx +#: apps/remix/app/components/general/folder/folder-card.tsx #: apps/remix/app/components/general/document/document-page-view-dropdown.tsx #: apps/remix/app/components/dialogs/webhook-delete-dialog.tsx #: apps/remix/app/components/dialogs/token-delete-dialog.tsx @@ -2353,6 +2400,7 @@ msgstr "삭제" #: apps/remix/app/components/dialogs/organisation-group-delete-dialog.tsx #: apps/remix/app/components/dialogs/organisation-delete-dialog.tsx #: apps/remix/app/components/dialogs/organisation-delete-dialog.tsx +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/document-delete-dialog.tsx #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Delete" @@ -2360,10 +2408,9 @@ msgstr "삭제" #. placeholder {0}: webhook.webhookUrl #. placeholder {0}: token.name -#. placeholder {0}: folder?.name ?? 'folder' +#. placeholder {0}: organisation.name #: apps/remix/app/components/dialogs/webhook-delete-dialog.tsx #: apps/remix/app/components/dialogs/token-delete-dialog.tsx -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/organisation-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "delete {0}" @@ -2395,6 +2442,10 @@ msgstr "문서 삭제" msgid "Delete Document" msgstr "문서 삭제" +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "Delete Folder" +msgstr "폴더 삭제" + #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.general.tsx msgid "Delete organisation" msgstr "조직 삭제" @@ -2453,6 +2504,7 @@ msgid "Details" msgstr "세부 정보" #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/components/tables/settings-security-activity-table.tsx msgid "Device" msgstr "장치" @@ -2833,7 +2885,6 @@ msgid "Document will be permanently deleted" msgstr "문서가 영구적으로 삭제될 것입니다" #: apps/remix/app/routes/_profile+/p.$url.tsx -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.f.$folderId._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.edit.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx @@ -3139,6 +3190,10 @@ msgstr "계정을 활성화하면 사용자가 다시 계정을 사용할 수 msgid "Enclosed Document" msgstr "첨부 문서" +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "Enter a name for your new folder. Folders help you organise your items." +msgstr "새 폴더의 이름을 입력하세요. 폴더는 항목을 정리하는 데 도움을 줍니다." + #: apps/remix/app/components/forms/subscription-claim-form.tsx msgid "Enter claim name" msgstr "클레임 이름 입력" @@ -3179,6 +3234,7 @@ msgstr "엔터프라이즈" #: apps/remix/app/routes/embed+/v1+/authoring+/template.edit.$id.tsx #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx @@ -3221,6 +3277,7 @@ msgstr "엔터프라이즈" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/template-duplicate-dialog.tsx +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/admin-user-enable-dialog.tsx @@ -3265,8 +3322,7 @@ msgstr "{0}에 만료됨" msgid "External ID" msgstr "외부 ID" -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Failed to create folder" msgstr "폴더 생성에 실패했습니다" @@ -3274,6 +3330,10 @@ msgstr "폴더 생성에 실패했습니다" msgid "Failed to create subscription claim." msgstr "구독 클레임 생성에 실패했습니다." +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "Failed to delete folder" +msgstr "폴더 삭제 실패" + #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Failed to delete subscription claim." msgstr "구독 클레임 삭제에 실패했습니다." @@ -3282,14 +3342,26 @@ msgstr "구독 클레임 삭제에 실패했습니다." msgid "Failed to load document" msgstr "문서 로드에 실패했습니다" +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +msgid "Failed to move folder" +msgstr "폴더 이동 실패" + #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx msgid "Failed to reseal document" msgstr "문서 걸쇠 잠금 실패" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +msgid "Failed to revoke session" +msgstr "세션을 취소하는 데 실패했습니다" + #: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx msgid "Failed to save settings." msgstr "설정 저장 실패." +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +msgid "Failed to sign out all sessions" +msgstr "모든 세션에서 로그아웃에 실패했습니다." + #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx msgid "Failed to update document" msgstr "문서 업데이트에 실패했습니다" @@ -3386,16 +3458,28 @@ msgstr "새로운 구독 클레임을 만들기 위한 세부 정보를 입력 msgid "Folder" msgstr "폴더" -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Folder created successfully" msgstr "폴더가 성공적으로 생성되었습니다" -#: apps/remix/app/components/dialogs/template-folder-settings-dialog.tsx +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "Folder deleted successfully" +msgstr "폴더가 성공적으로 삭제되었습니다" + +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +msgid "Folder moved successfully" +msgstr "폴더가 성공적으로 이동되었습니다" + +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "Folder Name" +msgstr "폴더 이름" + #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Folder not found" msgstr "폴더를 찾을 수 없습니다" -#: apps/remix/app/components/dialogs/template-folder-settings-dialog.tsx #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx msgid "Folder updated successfully" msgstr "폴더가 성공적으로 업데이트되었습니다" @@ -3633,9 +3717,16 @@ msgid "Hide additional information" msgstr "추가 정보 숨기기" #: apps/remix/app/components/general/generic-error-layout.tsx +#: apps/remix/app/components/general/folder/folder-grid.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Home" msgstr "홈" +#: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx +#: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx +msgid "Home (No Folder)" +msgstr "홈 (폴더 없음)" + #: packages/lib/constants/recipient-roles.ts msgid "I am a signer of this document" msgstr "저는 이 문서의 서명자입니다" @@ -3747,7 +3838,6 @@ msgstr "잘못된 코드입니다. 다시 시도해 주세요." msgid "Invalid email" msgstr "잘못된 이메일" -#: apps/remix/app/routes/_unauthenticated+/team.verify.transfer.$token.tsx #: apps/remix/app/routes/_unauthenticated+/team.verify.email.$token.tsx msgid "Invalid link" msgstr "잘못된 링크" @@ -3811,6 +3901,7 @@ msgid "Invoice" msgstr "송장" #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/components/tables/internal-audit-log-table.tsx msgid "IP Address" msgstr "IP 주소" @@ -3881,6 +3972,10 @@ msgstr "지난 30일" msgid "Last 7 days" msgstr "지난 7일" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +msgid "Last Active" +msgstr "마지막 활동" + #: apps/remix/app/components/general/template/template-page-view-information.tsx #: apps/remix/app/components/general/document/document-page-view-information.tsx msgid "Last modified" @@ -4030,6 +4125,10 @@ msgstr "패스키 관리" msgid "Manage permissions and access controls" msgstr "권한 및 접근 제어 관리" +#: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx +msgid "Manage sessions" +msgstr "세션 관리" + #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx msgid "Manage subscription" @@ -4107,6 +4206,10 @@ msgstr "MAU (생성된 문서)" msgid "MAU (had document completed)" msgstr "MAU (문서 완료)" +#: apps/remix/app/routes/_authenticated+/admin+/stats.tsx +msgid "MAU (signed in)" +msgstr "MAU (로그인 완료)" + #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx msgid "Max" msgstr "최대" @@ -4177,7 +4280,9 @@ msgstr "월간 활성 사용자: 최소 하나의 문서를 생성한 사용자" msgid "Monthly Active Users: Users that had at least one of their documents completed" msgstr "월간 활성 사용자: 최소 한 개의 문서가 완료된 사용자" +#: apps/remix/app/components/general/folder/folder-card.tsx #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Move" msgstr "이동" @@ -4190,6 +4295,10 @@ msgstr "\"{templateTitle}\"를 폴더로 이동" msgid "Move Document to Folder" msgstr "문서를 폴더로 이동" +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +msgid "Move Folder" +msgstr "폴더 이동" + #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx msgid "Move Template to Folder" msgstr "템플릿을 폴더로 이동" @@ -4203,6 +4312,10 @@ msgstr "폴더로 이동" msgid "Multiple access methods can be selected." msgstr "다중 접근 방법을 선택할 수 있습니다." +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "My Folder" +msgstr "내 폴더" + #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx #: apps/remix/app/components/tables/settings-security-passkey-table-actions.tsx @@ -4291,6 +4404,16 @@ msgstr "아니요" msgid "No active drafts" msgstr "활성화된 초안이 없음" +#: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx +#: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx +msgid "No folders found" +msgstr "폴더를 찾을 수 없습니다" + +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx +msgid "No folders found matching \"{searchTerm}\"" +msgstr "'{searchTerm}'와 일치하는 폴더를 찾을 수 없습니다" + #: apps/remix/app/routes/_recipient+/sign.$token+/rejected.tsx #: apps/remix/app/components/embed/embed-document-rejected.tsx msgid "No further action is required from you at this time." @@ -4600,10 +4723,18 @@ msgstr "조직들" msgid "Organisations that the user is a member of." msgstr "이 사용자가 멤버로 있는 조직들." +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Organise your documents" +msgstr "문서를 정리하세요" + #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Organise your members into groups which can be assigned to teams" msgstr "멤버들을 팀에 할당할 수 있는 그룹으로 구성하세요" +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Organise your templates" +msgstr "템플릿을 정리하세요" + #: apps/remix/app/routes/_authenticated+/o.$orgUrl._index.tsx msgid "Organize your documents and templates" msgstr "문서 및 템플릿을 정리하세요" @@ -4779,6 +4910,10 @@ msgstr "비밀번호 설정" msgid "Pick any of the following agreements below and start signing to get started" msgstr "다음의 동의서 중 하나를 선택하고 서명을 시작하여 시작하세요" +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Pin" +msgstr "고정" + #: packages/ui/primitives/document-flow/field-items-advanced-settings/text-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx @@ -5305,7 +5440,6 @@ msgstr "문서 보유" msgid "Retry" msgstr "다시 시도" -#: apps/remix/app/routes/_unauthenticated+/team.verify.transfer.$token.tsx #: apps/remix/app/routes/_unauthenticated+/team.verify.email.$token.tsx #: apps/remix/app/routes/_unauthenticated+/organisation.invite.$token.tsx #: apps/remix/app/routes/_unauthenticated+/organisation.decline.$token.tsx @@ -5321,6 +5455,7 @@ msgstr "홈으로 돌아가기" msgid "Return to sign in" msgstr "로그인 화면으로 돌아가기" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/components/general/teams/team-email-usage.tsx msgid "Revoke" msgstr "취소" @@ -5329,6 +5464,12 @@ msgstr "취소" msgid "Revoke access" msgstr "접근 권한 취소" +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +msgid "Revoke all sessions" +msgstr "모든 세션 취소" + #: apps/remix/app/components/tables/user-organisations-table.tsx #: apps/remix/app/components/tables/team-members-table.tsx #: apps/remix/app/components/tables/team-groups-table.tsx @@ -5348,11 +5489,6 @@ msgstr "역할" msgid "Roles" msgstr "역할들" -#: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx -#: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx -msgid "Root (No Folder)" -msgstr "루트 (폴더 없음)" - #: packages/ui/primitives/data-table-pagination.tsx msgid "Rows per page" msgstr "페이지당 행 수" @@ -5404,6 +5540,14 @@ msgstr "조직 ID, 이름, 고객 ID 또는 소유자 이메일로 검색" msgid "Search documents..." msgstr "문서 검색…" +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx +#: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +#: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx +msgid "Search folders..." +msgstr "폴더 검색..." + #: packages/ui/components/common/language-switcher-dialog.tsx msgid "Search languages..." msgstr "언어 검색…" @@ -5428,6 +5572,10 @@ msgstr "보안 활동" msgid "Select" msgstr "선택" +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +msgid "Select a destination for this folder." +msgstr "이 폴더의 목적지를 선택하세요." + #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Select a folder to move this document to." msgstr "이 문서를 이동할 폴더를 선택하세요." @@ -5481,6 +5629,10 @@ msgstr "기본 옵션 선택" msgid "Select groups" msgstr "그룹 선택" +#: apps/remix/app/components/dialogs/team-group-create-dialog.tsx +msgid "Select groups of members to add to the team." +msgstr "팀에 추가할 구성원 그룹을 선택하세요." + #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups to add to this team" msgstr "이 팀에 추가할 그룹 선택" @@ -5492,7 +5644,6 @@ msgid "Select members" msgstr "멤버 선택" #: apps/remix/app/components/dialogs/team-member-create-dialog.tsx -#: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select members or groups of members to add to the team." msgstr "팀에 추가할 멤버 또는 멤버 그룹을 선택하세요." @@ -5602,6 +5753,14 @@ msgstr "보내는 중…" msgid "Sent" msgstr "보냈음" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +msgid "Session revoked" +msgstr "세션이 해제되었습니다." + +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +msgid "Sessions have been revoked" +msgstr "세션이 취소되었습니다." + #: apps/remix/app/components/general/claim-account.tsx msgid "Set a password" msgstr "비밀번호 설정" @@ -5621,6 +5780,7 @@ msgstr "템플릿 속성과 수신자 정보를 설정하세요" #: apps/remix/app/components/general/app-nav-mobile.tsx #: apps/remix/app/components/general/app-command-menu.tsx #: apps/remix/app/components/general/app-command-menu.tsx +#: apps/remix/app/components/general/folder/folder-card.tsx msgid "Settings" msgstr "설정" @@ -6318,7 +6478,6 @@ msgstr "템플릿 제목" msgid "Template updated successfully" msgstr "템플릿이 성공적으로 업데이트되었습니다" -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.f.$folderId._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.$id._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.public-profile.tsx @@ -6449,12 +6608,10 @@ msgstr "URL로 전송될 웹훅을 트리거할 이벤트입니다." msgid "The fields have been updated to the new field insertion method successfully" msgstr "필드가 새로운 필드 삽입 방법으로 성공적으로 업데이트되었습니다" -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "The folder you are trying to delete does not exist." msgstr "삭제하려는 폴더가 존재하지 않습니다." -#: apps/remix/app/components/dialogs/template-folder-move-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "The folder you are trying to move does not exist." msgstr "이동하려는 폴더가 존재하지 않습니다." @@ -6771,10 +6928,9 @@ msgstr "다른 수신자가 아직 서명하지 않았을 경우 문서에 서 msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them." msgstr "이 필드는 수정되거나 삭제될 수 없습니다. 이 템플릿의 직접 링크를 공유하거나 공개 프로필에 추가하면, 누구나 이름과 이메일을 입력하고 할당된 필드를 기입할 수 있습니다." -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx -#: apps/remix/app/components/dialogs/folder-create-dialog.tsx -msgid "This folder name is already taken." -msgstr "이 폴더 이름은 이미 사용 중입니다." +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "This folder contains multiple items. Deleting it will also delete all items in the folder, including nested folders and their contents." +msgstr "이 폴더에는 여러 항목이 포함되어 있습니다. 삭제하면 중첩 폴더 및 그 내용물을 포함한 모든 항목이 삭제됩니다." #: packages/ui/primitives/template-flow/add-template-settings.tsx msgid "This is how the document will reach the recipients once the document is ready for signing." @@ -6784,10 +6940,6 @@ msgstr "이 문서를 서명할 준비가 되면 수신자에게 이렇게 도 msgid "This is the claim that this organisation was initially created with. Any feature flag changes to this claim will be backported into this organisation." msgstr "이것이 조직 초기 설립 당시의 클레임입니다. 이 클레임으로의 기능 플래그 변경은 조직에 백포팅됩니다." -#: apps/remix/app/routes/_unauthenticated+/team.verify.transfer.$token.tsx -msgid "This link is invalid or has expired." -msgstr "이 링크는 유효하지 않거나 만료되었습니다." - #: apps/remix/app/routes/_unauthenticated+/team.verify.email.$token.tsx msgid "This link is invalid or has expired. Please contact your team to resend a verification." msgstr "이 링크는 유효하지 않거나 만료되었습니다. 팀에 문의하여 확인을 다시 요청하십시오." @@ -6858,6 +7010,10 @@ msgstr "문서가 완전히 완료된 후 문서 소유자에게 이것이 발 msgid "This will ONLY backport feature flags which are set to true, anything disabled in the initial claim will not be backported" msgstr "기능 플래그 기본 설정은 사실의 경우에만 백포팅됩니다. 초기 클레임에 비활성화된 사항은 백포팅되지 않습니다." +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +msgid "This will sign you out of all other devices. You will need to sign in again on those devices to continue using your account." +msgstr "이 작업은 다른 모든 기기에서 로그아웃됩니다. 계정을 계속 사용하려면 해당 기기에서 다시 로그인해야 합니다." + #: apps/remix/app/components/tables/internal-audit-log-table.tsx #: apps/remix/app/components/tables/document-logs-table.tsx msgid "Time" @@ -7144,6 +7300,9 @@ msgstr "미완료" #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Unknown" msgstr "알 수 없음" @@ -7155,6 +7314,10 @@ msgstr "무제한" msgid "Unlimited documents, API and more" msgstr "무제한 문서, API 및 기타" +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Unpin" +msgstr "고정 해제" + #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Untitled Group" msgstr "제목없는 그룹" @@ -7497,6 +7660,11 @@ msgstr "모든 관련 문서 보기" msgid "View all security activity related to your account." msgstr "귀하의 계정과 관련된 모든 보안 활동 보기." +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx +msgid "View and manage all active sessions for your account." +msgstr "계정의 모든 활성 세션을 보고 관리하십시오." + #: apps/remix/app/components/forms/2fa/view-recovery-codes-dialog.tsx msgid "View Codes" msgstr "코드 보기" @@ -7855,7 +8023,6 @@ msgstr "저희가 서명 링크를 생성해드리며, 원하시는 방법으로 msgid "We won't send anything to notify recipients." msgstr "수신자에게 알리기 위해 아무것도 보내지 않습니다." -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.f.$folderId._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates._index.tsx #: apps/remix/app/components/tables/documents-table-empty-state.tsx msgid "We're all empty" @@ -8215,7 +8382,6 @@ msgstr "귀하에게 {recipientActionVerb}을 요구하는 문서 {0}을 시작 msgid "You have no webhooks yet. Your webhooks will be shown here once you create them." msgstr "아직 웹훅이 없습니다.웹훅을 만들면 여기에 표시됩니다." -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.f.$folderId._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates._index.tsx msgid "You have not yet created any templates. To create a template please upload one." msgstr "아직 템플릿을 생성하지 않았습니다.템플릿을 만들려면 하나를 업로드하세요." @@ -8317,7 +8483,6 @@ msgstr "<0>{0}에 대한 이메일 주소를 확인했습니다." msgid "You must enter '{deleteMessage}' to proceed" msgstr "계속하려면 '{deleteMessage}'을(를) 입력해야 합니다" -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "You must type '{deleteMessage}' to confirm" msgstr "확인을 위해 '{deleteMessage}'를 입력해야 합니다" diff --git a/packages/lib/translations/pl/web.po b/packages/lib/translations/pl/web.po index f69f7099e..02e1566d0 100644 --- a/packages/lib/translations/pl/web.po +++ b/packages/lib/translations/pl/web.po @@ -8,7 +8,7 @@ msgstr "" "Language: pl\n" "Project-Id-Version: documenso-app\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-10 12:05\n" +"PO-Revision-Date: 2025-06-19 06:05\n" "Last-Translator: \n" "Language-Team: Polish\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" @@ -75,12 +75,12 @@ msgstr "{0, plural, one {# znak przekroczony} few {# znaki przekroczone} many {# #. placeholder {0}: folder._count.documents #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# document} other {# documents}}" -msgstr "" +msgstr "{0, plural, one {# dokument} few {# dokumenty} many {# dokumentów} other {# dokumentów}}" #. placeholder {0}: folder._count.subfolders #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# folder} other {# folders}}" -msgstr "" +msgstr "{0, plural, one {# folder} few {# foldery} many {# folderów} other {# folderów}}" #. placeholder {0}: template.recipients.length #: apps/remix/app/routes/_recipient+/d.$token+/_index.tsx @@ -95,7 +95,7 @@ msgstr "{0, plural, one {# zespół} few {# zespoły} many {# zespołów} other #. placeholder {0}: folder._count.templates #: apps/remix/app/components/general/folder/folder-card.tsx msgid "{0, plural, one {# template} other {# templates}}" -msgstr "" +msgstr "{0, plural, one {# szablon} few {# szablony} many {# szablonów} other {# szablonów}}" #. placeholder {0}: data.length #: apps/remix/app/components/general/organisations/organisation-invitations.tsx @@ -283,7 +283,7 @@ msgstr "{prefix} niepodpisane pole" #: packages/lib/utils/document-audit-logs.ts msgid "{prefix} updated a field" -msgstr "{prefix} zaktualizowane pole" +msgstr "Użytkownik {prefix} zaktualizował pole" #: packages/lib/utils/document-audit-logs.ts msgid "{prefix} updated a recipient" @@ -313,10 +313,6 @@ msgstr "Użytkownik {prefix} zaktualizował tytuł dokumentu" msgid "{prefix} updated the document visibility" msgstr "Użytkownik {prefix} zaktualizował widoczność dokumentu" -#: packages/lib/utils/document-audit-logs.ts -msgid "{prefix} viewed the document" -msgstr "" - #: apps/remix/app/components/general/direct-template/direct-template-page.tsx msgid "{recipientActionVerb} document" msgstr "{recipientActionVerb} dokument" @@ -374,7 +370,7 @@ msgstr "{teamName} zaprosił cię do {action} {documentName}" #: packages/lib/utils/document-audit-logs.ts msgid "{userName} approved the document" -msgstr "{userName} zatwierdził dokument" +msgstr "Użytkownik {userName} zatwierdził dokument" #: packages/lib/utils/document-audit-logs.ts msgid "{userName} CC'd the document" @@ -386,15 +382,15 @@ msgstr "{userName} zakończył swoje zadanie" #: packages/lib/utils/document-audit-logs.ts msgid "{userName} rejected the document" -msgstr "{userName} odrzucił dokument" +msgstr "Użytkownik {userName} odrzucił dokument" #: packages/lib/utils/document-audit-logs.ts msgid "{userName} signed the document" -msgstr "{userName} podpisał dokument" +msgstr "Użytkownik {userName} podpisał dokument" #: packages/lib/utils/document-audit-logs.ts msgid "{userName} viewed the document" -msgstr "{userName} wyświetlił dokument" +msgstr "Użytkownik {userName} wyświetlił dokument" #: packages/ui/primitives/data-table-pagination.tsx msgid "{visibleRows, plural, one {Showing # result.} other {Showing # results.}}" @@ -490,11 +486,11 @@ msgstr "<0>Jesteś na drodze do zakończenia przeglądania \"<1>{documentTitle}< #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx msgid "0 Free organisations left" -msgstr "0 Wolnych organizacji pozostało" +msgstr "Pozostało 0 darmowych organizacji" #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx msgid "1 Free organisations left" -msgstr "1 Darmowa organizacja pozostała" +msgstr "Pozostała 1 darmowa organizacja" #: apps/remix/app/components/forms/token.tsx msgid "1 month" @@ -549,7 +545,7 @@ msgstr "5 dokumentów miesięcznie" #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx msgid "5 Documents a month" -msgstr "5 Dokumentów miesięcznie" +msgstr "5 dokumentów miesięcznie" #: apps/remix/app/components/general/generic-error-layout.tsx msgid "500 Internal Server Error" @@ -725,11 +721,11 @@ msgstr "Konto zostało usunięte" #: apps/remix/app/components/dialogs/admin-user-disable-dialog.tsx msgid "Account disabled" -msgstr "Konto wyłączone" +msgstr "Konto zostało wyłączone" #: apps/remix/app/components/dialogs/admin-user-enable-dialog.tsx msgid "Account enabled" -msgstr "Konto włączone" +msgstr "Konto zostało włączone" #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx msgid "Account Re-Authentication" @@ -774,7 +770,7 @@ msgstr "Aktywne" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Active sessions" -msgstr "" +msgstr "Aktywne sesje" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Active Subscriptions" @@ -1345,7 +1341,7 @@ msgstr "Czy na pewno chcesz usunąć następujący wniosek?" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Are you sure you want to delete this folder?" -msgstr "" +msgstr "Czy na pewno chcesz usunąć ten folder?" #: apps/remix/app/components/dialogs/token-delete-dialog.tsx msgid "Are you sure you want to delete this token?" @@ -1771,6 +1767,7 @@ msgstr "Kliknij, aby rozpocząć" #: apps/remix/app/components/tables/settings-public-profile-templates-table.tsx #: apps/remix/app/components/general/template/template-page-view-recent-activity.tsx #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Click here to retry" msgstr "Kliknij tutaj, aby spróbować ponownie" @@ -2164,11 +2161,11 @@ msgstr "Utwórz dokument z szablonu" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Create folder" -msgstr "" +msgstr "Utwórz folder" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create Folder" -msgstr "" +msgstr "Utwórz folder" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx @@ -2181,7 +2178,7 @@ msgstr "Utwórz grupy" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Create New Folder" -msgstr "" +msgstr "Utwórz nowy folder" #: apps/remix/app/routes/_profile+/_layout.tsx msgid "Create now" @@ -2303,11 +2300,11 @@ msgstr "Struktura CSV" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Cumulative MAU (signed in)" -msgstr "" +msgstr "Łączne MAU (zalogowani)" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Current" -msgstr "" +msgstr "Bieżący" #: apps/remix/app/components/forms/password.tsx msgid "Current Password" @@ -2447,7 +2444,7 @@ msgstr "Usuń dokument" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Delete Folder" -msgstr "" +msgstr "Usuń folder" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.general.tsx msgid "Delete organisation" @@ -2692,7 +2689,7 @@ msgstr "Dokument Zakończony!" #: apps/remix/app/components/dialogs/template-use-dialog.tsx #: packages/lib/utils/document-audit-logs.ts msgid "Document created" -msgstr "Dokument utworzony" +msgstr "Utworzono dokument" #: apps/remix/app/routes/embed+/v1+/authoring_.completed.create.tsx msgid "Document Created" @@ -2752,6 +2749,11 @@ msgstr "Zaktualizowane ID zewnętrzne dokumentu" msgid "Document found in your account" msgstr "Dokument znaleziony na Twoim koncie" +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Document history" +msgstr "Historia dokumentu" + #: apps/remix/app/routes/_internal+/[__htmltopdf]+/audit-log.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.logs.tsx msgid "Document ID" @@ -2791,7 +2793,7 @@ msgstr "Dokument nie jest już dostępny do podpisania" #: packages/lib/utils/document-audit-logs.ts msgid "Document opened" -msgstr "Dokument otwarty" +msgstr "Otwarto dokument" #: apps/remix/app/components/general/document/document-status.tsx msgid "Document pending" @@ -2827,7 +2829,7 @@ msgstr "Dokument ponownie zaplombowany" #: apps/remix/app/components/general/document/document-edit-form.tsx #: packages/lib/utils/document-audit-logs.ts msgid "Document sent" -msgstr "Dokument wysłany" +msgstr "Wysłano dokument" #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Signed" @@ -2870,10 +2872,6 @@ msgstr "Przesyłanie dokumentu wyłączone z powodu nieopłaconych faktur" msgid "Document uploaded" msgstr "Przesłano dokument" -#: packages/lib/utils/document-audit-logs.ts -msgid "Document viewed" -msgstr "" - #: apps/remix/app/routes/_recipient+/sign.$token+/complete.tsx msgid "Document Viewed" msgstr "Dokument został wyświetlony" @@ -3102,11 +3100,11 @@ msgstr "Opcje e-mail" #: packages/lib/utils/document-audit-logs.ts msgid "Email resent" -msgstr "E-mail wysłany ponownie" +msgstr "Wysłano ponownie wiadomość" #: packages/lib/utils/document-audit-logs.ts msgid "Email sent" -msgstr "E-mail wysłany" +msgstr "Wysłano wiadomość" #: apps/remix/app/routes/_unauthenticated+/check-email.tsx msgid "Email sent!" @@ -3194,7 +3192,7 @@ msgstr "Załączony dokument" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Enter a name for your new folder. Folders help you organise your items." -msgstr "" +msgstr "Wprowadź nazwę dla nowego folderu. Foldery pomogą ci zorganizować przedmioty." #: apps/remix/app/components/forms/subscription-claim-form.tsx msgid "Enter claim name" @@ -3334,7 +3332,7 @@ msgstr "Nie udało się utworzyć roszczenia subskrypcyjnego." #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Failed to delete folder" -msgstr "" +msgstr "Nie udało się usunąć folder" #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Failed to delete subscription claim." @@ -3346,7 +3344,7 @@ msgstr "Nie udało się załadować dokumentu" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Failed to move folder" -msgstr "" +msgstr "Nie udało się przenieść folderu" #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx msgid "Failed to reseal document" @@ -3354,7 +3352,7 @@ msgstr "Nie udało się ponownie zaplombować dokumentu" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Failed to revoke session" -msgstr "" +msgstr "Nie udało się unieważnić sesji" #: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx msgid "Failed to save settings." @@ -3362,7 +3360,7 @@ msgstr "Nie udało się zapisać ustawień." #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Failed to sign out all sessions" -msgstr "" +msgstr "Nie udało się wylogować ze wszystkich sesji" #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx msgid "Failed to update document" @@ -3427,11 +3425,11 @@ msgstr "Pole wstępnie wypełnione przez asystenta" #: packages/lib/utils/document-audit-logs.ts msgid "Field signed" -msgstr "Pole podpisane" +msgstr "Podpisano pole" #: packages/lib/utils/document-audit-logs.ts msgid "Field unsigned" -msgstr "Pole niepodpisane" +msgstr "Niepodpisano pole" #: apps/remix/app/components/tables/admin-document-recipient-item-table.tsx msgid "Fields" @@ -3466,15 +3464,15 @@ msgstr "Folder utworzony pomyślnie" #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Folder deleted successfully" -msgstr "" +msgstr "Folder został pomyślnie usunięty" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Folder moved successfully" -msgstr "" +msgstr "Folder został pomyślnie przeniesiony" #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Folder Name" -msgstr "" +msgstr "Nazwa foldera" #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3714,6 +3712,10 @@ msgstr "Cześć, {userName} <0>({userEmail})" msgid "Hide" msgstr "Ukryj" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Hide additional information" +msgstr "Ukryj dodatkowe informacje" + #: apps/remix/app/components/general/generic-error-layout.tsx #: apps/remix/app/components/general/folder/folder-grid.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx @@ -3723,7 +3725,7 @@ msgstr "Dom" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Home (No Folder)" -msgstr "" +msgstr "Strona główna (Brak folderu)" #: packages/lib/constants/recipient-roles.ts msgid "I am a signer of this document" @@ -3972,7 +3974,7 @@ msgstr "Ostatnie 7 dni" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Last Active" -msgstr "" +msgstr "Ostatnia aktywność" #: apps/remix/app/components/general/template/template-page-view-information.tsx #: apps/remix/app/components/general/document/document-page-view-information.tsx @@ -4125,7 +4127,7 @@ msgstr "Zarządzaj uprawnieniami i kontrolą dostępu" #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "Manage sessions" -msgstr "" +msgstr "Zarządzaj sesjami" #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx @@ -4137,10 +4139,10 @@ msgstr "Zarządzaj subskrypcją" msgid "Manage the {0} organisation" msgstr "Zarządzaj organizacją {0}" -#. placeholder {1}: organisation.name +#. placeholder {0}: organisation.name #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "Manage the {1} organisation subscription" -msgstr "" +msgid "Manage the {0} organisation subscription" +msgstr "Zarządzaj subskrypcjami organizacji {0}" #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups._index.tsx msgid "Manage the custom groups of members for your organisation." @@ -4206,7 +4208,7 @@ msgstr "MAU (zakończony dokument)" #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "MAU (signed in)" -msgstr "" +msgstr "MAU (zalogowani)" #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx msgid "Max" @@ -4295,7 +4297,7 @@ msgstr "Przenieś dokument do folderu" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Move Folder" -msgstr "" +msgstr "Przenieś folder" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx msgid "Move Template to Folder" @@ -4312,7 +4314,7 @@ msgstr "Można wybrać wiele metod dostępu." #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "My Folder" -msgstr "" +msgstr "Mój folder" #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx @@ -4405,12 +4407,12 @@ msgstr "Brak aktywnych szkiców" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "No folders found" -msgstr "" +msgstr "Nie znaleziono folderów" #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx msgid "No folders found matching \"{searchTerm}\"" -msgstr "" +msgstr "Nie znaleziono folderów zgodnych z \"{searchTerm}\"" #: apps/remix/app/routes/_recipient+/sign.$token+/rejected.tsx #: apps/remix/app/components/embed/embed-document-rejected.tsx @@ -4723,7 +4725,7 @@ msgstr "Organizacje, których użytkownik jest członkiem." #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your documents" -msgstr "" +msgstr "Zorganizuj swoje dokumenty" #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Organise your members into groups which can be assigned to teams" @@ -4731,7 +4733,7 @@ msgstr "Zorganizuj swoich członków w grupy, które można przypisać do zespo #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Organise your templates" -msgstr "" +msgstr "Zorganizuj swoje szablony" #: apps/remix/app/routes/_authenticated+/o.$orgUrl._index.tsx msgid "Organize your documents and templates" @@ -4910,7 +4912,7 @@ msgstr "Wybierz dowolną z poniższych umów i zacznij podpisywanie, aby rozpocz #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Pin" -msgstr "" +msgstr "Przypnij" #: packages/ui/primitives/document-flow/field-items-advanced-settings/text-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx @@ -5466,7 +5468,7 @@ msgstr "Cofnij dostęp" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Revoke all sessions" -msgstr "" +msgstr "Cofnij wszystkie sesje" #: apps/remix/app/components/tables/user-organisations-table.tsx #: apps/remix/app/components/tables/team-members-table.tsx @@ -5544,7 +5546,7 @@ msgstr "Szukaj dokumentów..." #: apps/remix/app/components/dialogs/folder-move-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Search folders..." -msgstr "" +msgstr "Szukaj folderów..." #: packages/ui/components/common/language-switcher-dialog.tsx msgid "Search languages..." @@ -5572,7 +5574,7 @@ msgstr "Wybierz" #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Select a destination for this folder." -msgstr "" +msgstr "Wybierz miejsce docelowe dla tego folderu." #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Select a folder to move this document to." @@ -5629,7 +5631,7 @@ msgstr "Wybierz grupy" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups of members to add to the team." -msgstr "" +msgstr "Wybierz grupy członków do dodania do zespołu." #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups to add to this team" @@ -5753,11 +5755,11 @@ msgstr "Wysłano" #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Session revoked" -msgstr "" +msgstr "Sesja odwołana" #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "Sessions have been revoked" -msgstr "" +msgstr "Sesje zostały odwołane" #: apps/remix/app/components/general/claim-account.tsx msgid "Set a password" @@ -5812,6 +5814,10 @@ msgstr "Podziel się swoim doświadczeniem podpisywania!" msgid "Show" msgstr "Pokaż" +#: apps/remix/app/components/general/document/document-history-sheet.tsx +msgid "Show additional information" +msgstr "Pokaż dodatkowe informacje" + #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx #: packages/ui/primitives/document-flow/add-signers.tsx msgid "Show advanced settings" @@ -6627,8 +6633,7 @@ msgid "The following team has been deleted. You will no longer be able to access msgstr "Poniższy zespół został usunięty. Nie będziesz mógł już uzyskać dostępu do tego zespołu i jego dokumentów." #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.groups.$id.tsx -msgid "" -"The organisation group you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation group you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Grupa organizacji, której szukasz, mogła zostać usunięta, zmieniona nazwa lub mogła nigdy nie istnieć." @@ -6637,14 +6642,12 @@ msgid "The organisation role that will be applied to all members in this group." msgstr "Rola organizacji, która zostanie zastosowana do wszystkich członków tej grupy." #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Organizacja, której szukasz, mogła zostać usunięta, zmieniona nazwa lub mogła nigdy nie istnieć." #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The organisation you are looking for may have been removed, renamed or may have never\n" +msgid "The organisation you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Organizacja, której szukasz, mogła zostać usunięta, zmieniona nazwa lub mogła nigdy nie istnieć." @@ -6728,14 +6731,12 @@ msgid "The team email <0>{teamEmail} has been removed from the following tea msgstr "Email zespołowy <0>{teamEmail} został usunięty z następującego zespołu" #: apps/remix/app/routes/_authenticated+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Zespół, którego szukasz, mógł zostać usunięty, zmienić nazwę lub mógł nigdy nie istnieć." #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/_layout.tsx -msgid "" -"The team you are looking for may have been removed, renamed or may have never\n" +msgid "The team you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Zespół, którego szukasz, mógł zostać usunięty, zmieniony na, albo nigdy nie istniał." @@ -6773,8 +6774,7 @@ msgid "The URL for Documenso to send webhook events to." msgstr "URL dla Documenso do wysyłania zdarzeń webhook." #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx -msgid "" -"The user you are looking for may have been removed, renamed or may have never\n" +msgid "The user you are looking for may have been removed, renamed or may have never\n" " existed." msgstr "Użytkownik, którego szukasz, mógł zostać usunięty, zmieniony nazwę lub mógł nigdy nie istnieć." @@ -6930,7 +6930,7 @@ msgstr "To pole nie może być modyfikowane ani usuwane. Po udostępnieniu bezpo #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "This folder contains multiple items. Deleting it will also delete all items in the folder, including nested folders and their contents." -msgstr "" +msgstr "Ten folder zawiera wiele elementów. Usunięcie go również usunie wszystkie elementy w folderze, w tym zagnieżdżone foldery i ich zawartość." #: packages/ui/primitives/template-flow/add-template-settings.tsx msgid "This is how the document will reach the recipients once the document is ready for signing." @@ -7012,7 +7012,7 @@ msgstr "To będzie TYLKO przenoś funkcje flag, które są ustawione na true, ws #: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx msgid "This will sign you out of all other devices. You will need to sign in again on those devices to continue using your account." -msgstr "" +msgstr "Zostaniesz wylogowany z wszystkich innych urządzeń. Aby dalej korzystać z konta, musisz ponownie się zalogować na tych urządzeniach." #: apps/remix/app/components/tables/internal-audit-log-table.tsx #: apps/remix/app/components/tables/document-logs-table.tsx @@ -7241,6 +7241,7 @@ msgid "Unable to join this organisation at this time." msgstr "Nie można w tej chwili dołączyć do tej organizacji." #: apps/remix/app/components/general/document/document-page-view-recent-activity.tsx +#: apps/remix/app/components/general/document/document-history-sheet.tsx msgid "Unable to load document history" msgstr "Nie można załadować historii dokumentu" @@ -7315,7 +7316,7 @@ msgstr "Nieograniczone dokumenty, API i więcej" #: apps/remix/app/components/general/folder/folder-card.tsx msgid "Unpin" -msgstr "" +msgstr "Odepnij" #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Untitled Group" @@ -7662,7 +7663,7 @@ msgstr "Wyświetl wszystkie aktywności związane z bezpieczeństwem twojego kon #: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx msgid "View and manage all active sessions for your account." -msgstr "" +msgstr "Przeglądaj i zarządzaj wszystkimi aktywnymi sesjami swojego konta." #: apps/remix/app/components/forms/2fa/view-recovery-codes-dialog.tsx msgid "View Codes" @@ -8009,8 +8010,11 @@ msgstr "Nie udało się zweryfikować Twojego e-maila w tym momencie." msgid "We were unable to verify your email. If your email is not verified already, please try again." msgstr "Nie udało się zweryfikować twojego e-maila. Jeśli twój e-mail nie jest jeszcze zweryfikowany, spróbuj ponownie." -#: apps/remix/app/components/dialogs/template-use-dialog.tsx #: packages/ui/primitives/document-flow/add-subject.tsx +msgid "We will generate signing links for with you, which you can send to the recipients through your method of choice." +msgstr "Wygenerujemy linki do podpisu dla Ciebie, które możesz wysłać do odbiorców w wybrany przez siebie sposób." + +#: apps/remix/app/components/dialogs/template-use-dialog.tsx msgid "We will generate signing links for you, which you can send to the recipients through your method of choice." msgstr "Wygenerujemy dla Ciebie linki do podpisania, które możesz wysłać do odbiorców za pomocą wybranej metody." @@ -8724,3 +8728,4 @@ msgstr "Twój token został pomyślnie utworzony! Upewnij się, że go skopiujes #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.tokens.tsx msgid "Your tokens will be shown here once you create them." msgstr "Twoje tokeny będą tutaj wyświetlane po ich utworzeniu." + diff --git a/packages/lib/translations/sq/web.po b/packages/lib/translations/sq/web.po index c381ed907..e77db9854 100644 --- a/packages/lib/translations/sq/web.po +++ b/packages/lib/translations/sq/web.po @@ -8,7 +8,7 @@ msgstr "" "Language: sq\n" "Project-Id-Version: documenso-app\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-06-10 02:27\n" +"PO-Revision-Date: 2025-06-19 06:05\n" "Last-Translator: \n" "Language-Team: Albanian\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -72,6 +72,16 @@ msgstr "{0, plural, one {(1 karakter më shumë)} other {(# karaktere më shumë msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}" msgstr "{0, plural, one {# karakter mbi kufi} other {# karaktere mbi kufi}}" +#. placeholder {0}: folder._count.documents +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "{0, plural, one {# document} other {# documents}}" +msgstr "{0, plural, one {# dokument} other {# dokumente}}" + +#. placeholder {0}: folder._count.subfolders +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "{0, plural, one {# folder} other {# folders}}" +msgstr "{0, plural, one {# dosje} other {# dosje}}" + #. placeholder {0}: template.recipients.length #: apps/remix/app/routes/_recipient+/d.$token+/_index.tsx msgid "{0, plural, one {# recipient} other {# recipients}}" @@ -82,6 +92,11 @@ msgstr "{0, plural, one {# marrës} other {# marrësa}}" msgid "{0, plural, one {# team} other {# teams}}" msgstr "{0, plural, one {# ekip} other {# ekipe}}" +#. placeholder {0}: folder._count.templates +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "{0, plural, one {# template} other {# templates}}" +msgstr "{0, plural, one {# model} other {# modele}}" + #. placeholder {0}: data.length #: apps/remix/app/components/general/organisations/organisation-invitations.tsx #: apps/remix/app/components/general/organisations/organisation-invitations.tsx @@ -752,6 +767,11 @@ msgstr "Veprime" msgid "Active" msgstr "Aktive" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx +msgid "Active sessions" +msgstr "Seanca aktive" + #: apps/remix/app/routes/_authenticated+/admin+/stats.tsx msgid "Active Subscriptions" msgstr "Abonime aktive" @@ -817,13 +837,13 @@ msgstr "Shto fusha" msgid "Add group roles" msgstr "Shto rolet e grupeve" +#: apps/remix/app/components/dialogs/team-group-create-dialog.tsx #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Add groups" msgstr "Shto grupet" #: apps/remix/app/components/dialogs/team-member-create-dialog.tsx #: apps/remix/app/components/dialogs/team-member-create-dialog.tsx -#: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Add members" msgstr "Shto anëtarët" @@ -1243,17 +1263,14 @@ msgstr "Ndodhi një gabim i papritur." msgid "An unknown error occurred" msgstr "Ndodhi një gabim i panjohur" -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx #: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "An unknown error occurred while creating the folder." msgstr "Një gabim i panjohur ndodhi gjatë krijimit të dosjes." -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "An unknown error occurred while deleting the folder." msgstr "Një gabim i panjohur ndodhi gjatë fshirjes së dosjes." -#: apps/remix/app/components/dialogs/template-folder-move-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "An unknown error occurred while moving the folder." msgstr "Një gabim i panjohur ndodhi gjatë zhvendosjes së dosjes." @@ -1322,6 +1339,10 @@ msgstr "A jeni të sigurt se doni të përfundoni dokumentin? Ky veprim nuk mund msgid "Are you sure you want to delete the following claim?" msgstr "A jeni të sigurt që doni të fshini ankesën e mëposhtme?" +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "Are you sure you want to delete this folder?" +msgstr "A jeni i sigurt që doni ta fshini këtë dosje?" + #: apps/remix/app/components/dialogs/token-delete-dialog.tsx msgid "Are you sure you want to delete this token?" msgstr "A jeni i sigurt që doni të fshini këtë token?" @@ -1614,6 +1635,7 @@ msgstr "Mund të përgatitë" #: apps/remix/app/components/dialogs/team-delete-dialog.tsx #: apps/remix/app/components/dialogs/team-create-dialog.tsx #: apps/remix/app/components/dialogs/team-create-dialog.tsx +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/public-profile-template-manage-dialog.tsx #: apps/remix/app/components/dialogs/passkey-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-member-update-dialog.tsx @@ -1626,6 +1648,9 @@ msgstr "Mund të përgatitë" #: apps/remix/app/components/dialogs/organisation-delete-dialog.tsx #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx #: apps/remix/app/components/dialogs/document-resend-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-duplicate-dialog.tsx @@ -1921,7 +1946,6 @@ msgstr "Konfirmo duke shtypur <0>{deleteMessage}" #: apps/remix/app/components/dialogs/webhook-delete-dialog.tsx #: apps/remix/app/components/dialogs/token-delete-dialog.tsx -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Confirm by typing: <0>{deleteMessage}" msgstr "Konfirmo duke shtypur: <0>{deleteMessage}" @@ -2065,6 +2089,7 @@ msgstr "Kopjo token" #: apps/remix/app/components/dialogs/webhook-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-create-dialog.tsx +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx #: apps/remix/app/components/dialogs/admin-organisation-create-dialog.tsx msgid "Create" msgstr "Krijo" @@ -2134,6 +2159,14 @@ msgstr "Krijo Lidhje të Drejtpërdrejtë për Nënshkrim" msgid "Create document from template" msgstr "Krijo dokument nga modeli" +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Create folder" +msgstr "Krijo dosje" + +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "Create Folder" +msgstr "Krijo Dosje" + #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Create group" @@ -2143,6 +2176,10 @@ msgstr "Krijo grup" msgid "Create Groups" msgstr "Krijo Grupet" +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "Create New Folder" +msgstr "Krijo Dosje të Re" + #: apps/remix/app/routes/_profile+/_layout.tsx msgid "Create now" msgstr "Krijo tani" @@ -2221,6 +2258,7 @@ msgstr "Krijoni llogarinë tuaj dhe filloni të përdorni nënshkrimin e dokumen msgid "Create your account and start using state-of-the-art document signing. Open and beautiful signing is within your grasp." msgstr "Krijoni llogarinë tuaj dhe filloni të përdorni nënshkrimin e dokumenteve në gjendje të artit. Nënshkrimi i hapur dhe i bukur është brenda arritjes tuaj." +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/admin+/documents._index.tsx #: apps/remix/app/components/tables/templates-table.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx @@ -2260,6 +2298,14 @@ msgstr "Krijuar më {0}" msgid "CSV Structure" msgstr "Struktura CSV" +#: apps/remix/app/routes/_authenticated+/admin+/stats.tsx +msgid "Cumulative MAU (signed in)" +msgstr "" + +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +msgid "Current" +msgstr "Aktual" + #: apps/remix/app/components/forms/password.tsx msgid "Current Password" msgstr "Fjalëkalimi aktual" @@ -2342,6 +2388,7 @@ msgstr "fshi" #: apps/remix/app/components/tables/organisation-groups-table.tsx #: apps/remix/app/components/tables/documents-table-action-dropdown.tsx #: apps/remix/app/components/tables/admin-claims-table.tsx +#: apps/remix/app/components/general/folder/folder-card.tsx #: apps/remix/app/components/general/document/document-page-view-dropdown.tsx #: apps/remix/app/components/dialogs/webhook-delete-dialog.tsx #: apps/remix/app/components/dialogs/token-delete-dialog.tsx @@ -2353,6 +2400,7 @@ msgstr "fshi" #: apps/remix/app/components/dialogs/organisation-group-delete-dialog.tsx #: apps/remix/app/components/dialogs/organisation-delete-dialog.tsx #: apps/remix/app/components/dialogs/organisation-delete-dialog.tsx +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/document-delete-dialog.tsx #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Delete" @@ -2360,10 +2408,9 @@ msgstr "Fshi" #. placeholder {0}: webhook.webhookUrl #. placeholder {0}: token.name -#. placeholder {0}: folder?.name ?? 'folder' +#. placeholder {0}: organisation.name #: apps/remix/app/components/dialogs/webhook-delete-dialog.tsx #: apps/remix/app/components/dialogs/token-delete-dialog.tsx -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/organisation-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "delete {0}" @@ -2395,6 +2442,10 @@ msgstr "Fshi dokumentin" msgid "Delete Document" msgstr "Fshi Dokumentin" +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "Delete Folder" +msgstr "Fshij Dosjen" + #: apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.general.tsx msgid "Delete organisation" msgstr "Fshij organizatën" @@ -2453,6 +2504,7 @@ msgid "Details" msgstr "Detaje" #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/components/tables/settings-security-activity-table.tsx msgid "Device" msgstr "Pajisje" @@ -2833,7 +2885,6 @@ msgid "Document will be permanently deleted" msgstr "Dokumenti do të Fshihet Përgjithmonë" #: apps/remix/app/routes/_profile+/p.$url.tsx -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.f.$folderId._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id.edit.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.$id._index.tsx @@ -3139,6 +3190,10 @@ msgstr "Aktivizimi i llogarisë rezulton që përdoruesi të jetë në gjendje t msgid "Enclosed Document" msgstr "Dokumenti i Bashkangjitur" +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "Enter a name for your new folder. Folders help you organise your items." +msgstr "Shkruani emrin për dosjen tuaj të re. Dosjet ju ndihmojnë të organizoni sendet tuaja." + #: apps/remix/app/components/forms/subscription-claim-form.tsx msgid "Enter claim name" msgstr "Vendos emrin e pretendimit" @@ -3179,6 +3234,7 @@ msgstr "Ndërmarrje" #: apps/remix/app/routes/embed+/v1+/authoring+/template.edit.$id.tsx #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx @@ -3221,6 +3277,7 @@ msgstr "Ndërmarrje" #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/template-duplicate-dialog.tsx +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx #: apps/remix/app/components/dialogs/admin-user-enable-dialog.tsx @@ -3265,8 +3322,7 @@ msgstr "Skadon më {0}" msgid "External ID" msgstr "ID i jashtëm" -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Failed to create folder" msgstr "Dështoi krijimi i dosjes" @@ -3274,6 +3330,10 @@ msgstr "Dështoi krijimi i dosjes" msgid "Failed to create subscription claim." msgstr "Dështoi krijimi i pretendimit të abonimit." +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "Failed to delete folder" +msgstr "Deshtim në fshirjen e dosjes" + #: apps/remix/app/components/dialogs/claim-delete-dialog.tsx msgid "Failed to delete subscription claim." msgstr "Dështoi fshirja e pretendimit të abonimit." @@ -3282,14 +3342,26 @@ msgstr "Dështoi fshirja e pretendimit të abonimit." msgid "Failed to load document" msgstr "Dështoi ngarkimi i dokumentit" +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +msgid "Failed to move folder" +msgstr "Deshtim në zhvendosjen e dosjes" + #: apps/remix/app/routes/_authenticated+/admin+/documents.$id.tsx msgid "Failed to reseal document" msgstr "Dështoi rihapja e dokumentit" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +msgid "Failed to revoke session" +msgstr "Dështoi të revokojë seancën" + #: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx msgid "Failed to save settings." msgstr "Dështoi të ruajë parametrat." +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +msgid "Failed to sign out all sessions" +msgstr "Dështoi të dilni nga të gjitha sesionet" + #: apps/remix/app/routes/embed+/v1+/authoring+/document.edit.$id.tsx msgid "Failed to update document" msgstr "Dështoi përditësimi i dokumentit" @@ -3386,16 +3458,28 @@ msgstr "Plotësoni detajet për të krijuar një pretendim të ri të abonimit." msgid "Folder" msgstr "Dosje" -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx msgid "Folder created successfully" msgstr "Dosja u krijua me sukses" -#: apps/remix/app/components/dialogs/template-folder-settings-dialog.tsx +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "Folder deleted successfully" +msgstr "Dosja u fshi me sukses" + +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +msgid "Folder moved successfully" +msgstr "Dosja u zhvendos me sukses" + +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "Folder Name" +msgstr "Emri i Dosjes" + #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "Folder not found" msgstr "Dosja nuk u gjet" -#: apps/remix/app/components/dialogs/template-folder-settings-dialog.tsx #: apps/remix/app/components/dialogs/folder-settings-dialog.tsx msgid "Folder updated successfully" msgstr "Dosja përditësuar me sukses" @@ -3633,9 +3717,16 @@ msgid "Hide additional information" msgstr "Fshih informacionin shtesë" #: apps/remix/app/components/general/generic-error-layout.tsx +#: apps/remix/app/components/general/folder/folder-grid.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "Home" msgstr "Shtëpia" +#: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx +#: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx +msgid "Home (No Folder)" +msgstr "Kryefaqe (Pa Dosje)" + #: packages/lib/constants/recipient-roles.ts msgid "I am a signer of this document" msgstr "Unë jam një nënshkrues i këtij dokumenti" @@ -3747,7 +3838,6 @@ msgstr "Kodi i pavlefshëm. Ju lutemi provoni përsëri." msgid "Invalid email" msgstr "Email i pavlefshëm" -#: apps/remix/app/routes/_unauthenticated+/team.verify.transfer.$token.tsx #: apps/remix/app/routes/_unauthenticated+/team.verify.email.$token.tsx msgid "Invalid link" msgstr "Lidhja e pavlefshme" @@ -3811,6 +3901,7 @@ msgid "Invoice" msgstr "Fatura" #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/components/tables/internal-audit-log-table.tsx msgid "IP Address" msgstr "Adresa IP" @@ -3881,6 +3972,10 @@ msgstr "30 ditët e fundit" msgid "Last 7 days" msgstr "7 ditët e fundit" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +msgid "Last Active" +msgstr "Aktiviteti i fundit" + #: apps/remix/app/components/general/template/template-page-view-information.tsx #: apps/remix/app/components/general/document/document-page-view-information.tsx msgid "Last modified" @@ -4030,6 +4125,10 @@ msgstr "Menaxho çelësat e aksesit" msgid "Manage permissions and access controls" msgstr "Menaxhoni lejet dhe kontrollin e qasjes" +#: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx +msgid "Manage sessions" +msgstr "Menaxho seancat" + #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx #: apps/remix/app/routes/_authenticated+/admin+/organisations.$id.tsx msgid "Manage subscription" @@ -4107,6 +4206,10 @@ msgstr "MAU (dokument i krijuar)" msgid "MAU (had document completed)" msgstr "MAU (dokument i përfunduar)" +#: apps/remix/app/routes/_authenticated+/admin+/stats.tsx +msgid "MAU (signed in)" +msgstr "" + #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx msgid "Max" msgstr "Maks" @@ -4177,7 +4280,9 @@ msgstr "Përdorues Aktivë Mujorë: Përdorues që kanë krijuar të paktën nj msgid "Monthly Active Users: Users that had at least one of their documents completed" msgstr "Përdorues Aktivë Mujorë: Përdorues që kanë përfunduar të paktën një nga dokumentet e tyre" +#: apps/remix/app/components/general/folder/folder-card.tsx #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Move" msgstr "Zhvendos" @@ -4190,6 +4295,10 @@ msgstr "Zhvendos \"{templateTitle}\" në një dosje" msgid "Move Document to Folder" msgstr "Zhvendos Dokumentin në Dosje" +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +msgid "Move Folder" +msgstr "Zhvendos Dosjen" + #: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx msgid "Move Template to Folder" msgstr "Zhvendos Shabllonin në Dosje" @@ -4203,6 +4312,10 @@ msgstr "Zhvendos në Dosje" msgid "Multiple access methods can be selected." msgstr "Mund të zgjedhni metoda të shumta të qasje." +#: apps/remix/app/components/dialogs/folder-create-dialog.tsx +msgid "My Folder" +msgstr "Dosja Ime" + #: apps/remix/app/routes/_authenticated+/admin+/users.$id.tsx #: apps/remix/app/components/tables/settings-security-passkey-table.tsx #: apps/remix/app/components/tables/settings-security-passkey-table-actions.tsx @@ -4291,6 +4404,16 @@ msgstr "Jo" msgid "No active drafts" msgstr "Asnjë draft aktiv" +#: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx +#: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx +msgid "No folders found" +msgstr "Nuk u gjetën dosje" + +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx +msgid "No folders found matching \"{searchTerm}\"" +msgstr "Nuk u gjetën dosje që përputhen me \"{searchTerm}\"" + #: apps/remix/app/routes/_recipient+/sign.$token+/rejected.tsx #: apps/remix/app/components/embed/embed-document-rejected.tsx msgid "No further action is required from you at this time." @@ -4600,10 +4723,18 @@ msgstr "Organizatat" msgid "Organisations that the user is a member of." msgstr "Organizatat të cilat përdoruesi është anëtar i. " +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Organise your documents" +msgstr "Organizoni dokumentet tuaja" + #: apps/remix/app/components/dialogs/organisation-group-create-dialog.tsx msgid "Organise your members into groups which can be assigned to teams" msgstr "Organizoni anëtarët tuaj në grupe që mund të caktohen në ekipe" +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Organise your templates" +msgstr "Organizoni shabllonet tuaja" + #: apps/remix/app/routes/_authenticated+/o.$orgUrl._index.tsx msgid "Organize your documents and templates" msgstr "Organizoni dokumentet dhe shabllonet tuaj" @@ -4779,6 +4910,10 @@ msgstr "Zgjidhni një fjalëkalim" msgid "Pick any of the following agreements below and start signing to get started" msgstr "Zgjidhni ndonjë nga marrëveshjet e mëposhtme dhe filloni të nënshkruani për të nisur" +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Pin" +msgstr "Vendos" + #: packages/ui/primitives/document-flow/field-items-advanced-settings/text-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx #: packages/ui/primitives/document-flow/field-items-advanced-settings/number-field.tsx @@ -5305,7 +5440,6 @@ msgstr "Ruajtja e Dokumenteve" msgid "Retry" msgstr "Provoni përsëri" -#: apps/remix/app/routes/_unauthenticated+/team.verify.transfer.$token.tsx #: apps/remix/app/routes/_unauthenticated+/team.verify.email.$token.tsx #: apps/remix/app/routes/_unauthenticated+/organisation.invite.$token.tsx #: apps/remix/app/routes/_unauthenticated+/organisation.decline.$token.tsx @@ -5321,6 +5455,7 @@ msgstr "Kthehu në Faqen Kryesore" msgid "Return to sign in" msgstr "Kthehu te Hyrja" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx #: apps/remix/app/components/general/teams/team-email-usage.tsx msgid "Revoke" msgstr "Revoko" @@ -5329,6 +5464,12 @@ msgstr "Revoko" msgid "Revoke access" msgstr "Revoko qasje" +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +msgid "Revoke all sessions" +msgstr "Revoko të gjitha seancat" + #: apps/remix/app/components/tables/user-organisations-table.tsx #: apps/remix/app/components/tables/team-members-table.tsx #: apps/remix/app/components/tables/team-groups-table.tsx @@ -5348,11 +5489,6 @@ msgstr "Roli" msgid "Roles" msgstr "Rolet" -#: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx -#: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx -msgid "Root (No Folder)" -msgstr "Rrënjë (Pa Dosje)" - #: packages/ui/primitives/data-table-pagination.tsx msgid "Rows per page" msgstr "Rreshta për faqe" @@ -5404,6 +5540,14 @@ msgstr "Kërko sipas ID të organizatës, emrit, ID të klientit ose email i pro msgid "Search documents..." msgstr "Kërko dokumente..." +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.folders._index.tsx +#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/documents.folders._index.tsx +#: apps/remix/app/components/dialogs/template-move-to-folder-dialog.tsx +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +#: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx +msgid "Search folders..." +msgstr "Kërkoni dosje..." + #: packages/ui/components/common/language-switcher-dialog.tsx msgid "Search languages..." msgstr "Kërko gjuhë..." @@ -5428,6 +5572,10 @@ msgstr "Aktiviteti i Sigurisë" msgid "Select" msgstr "Zgjidh" +#: apps/remix/app/components/dialogs/folder-move-dialog.tsx +msgid "Select a destination for this folder." +msgstr "Zgjidhni një destinacion për këtë dosje." + #: apps/remix/app/components/dialogs/document-move-to-folder-dialog.tsx msgid "Select a folder to move this document to." msgstr "Zgjidhni një dosje për të zhvendosur këtë dokument." @@ -5481,6 +5629,10 @@ msgstr "Zgjidh opsionin e paracaktuar" msgid "Select groups" msgstr "Zgjidh grupet" +#: apps/remix/app/components/dialogs/team-group-create-dialog.tsx +msgid "Select groups of members to add to the team." +msgstr "Zgjidh grupet e anëtarëve për t'i shtuar në ekip." + #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select groups to add to this team" msgstr "Zgjidh grupet për t'u shtuar në këtë ekip" @@ -5492,7 +5644,6 @@ msgid "Select members" msgstr "Zgjidh anëtarët" #: apps/remix/app/components/dialogs/team-member-create-dialog.tsx -#: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Select members or groups of members to add to the team." msgstr "Zgjidh anëtarët ose grupet e anëtarëve për t'i shtuar në ekip." @@ -5602,6 +5753,14 @@ msgstr "Duke Dërguar..." msgid "Sent" msgstr "Dërguar" +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +msgid "Session revoked" +msgstr "Sesion i revokuar" + +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +msgid "Sessions have been revoked" +msgstr "Sesione janë revokuar" + #: apps/remix/app/components/general/claim-account.tsx msgid "Set a password" msgstr "Vendosni një fjalëkalim" @@ -5621,6 +5780,7 @@ msgstr "Vendosni cilësitë e shabllonit tuaj dhe informacionin e marrësit" #: apps/remix/app/components/general/app-nav-mobile.tsx #: apps/remix/app/components/general/app-command-menu.tsx #: apps/remix/app/components/general/app-command-menu.tsx +#: apps/remix/app/components/general/folder/folder-card.tsx msgid "Settings" msgstr "Cilësimet" @@ -6318,7 +6478,6 @@ msgstr "Titulli i shabllonit" msgid "Template updated successfully" msgstr "Shablloni u përditësua me sukses" -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.f.$folderId._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.$id._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.public-profile.tsx @@ -6449,12 +6608,10 @@ msgstr "Ngjarjet që do të nxisin dërgimin e një webhook në URL-në tuaj." msgid "The fields have been updated to the new field insertion method successfully" msgstr "Fushat janë përditësuar në metodën e re të futjes së fushës me sukses" -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "The folder you are trying to delete does not exist." msgstr "Dosja që po përpiqeni të fshini nuk ekziston." -#: apps/remix/app/components/dialogs/template-folder-move-dialog.tsx #: apps/remix/app/components/dialogs/folder-move-dialog.tsx msgid "The folder you are trying to move does not exist." msgstr "Dosja që po përpiqeni të zhvendosni nuk ekziston." @@ -6771,10 +6928,9 @@ msgstr "Ky email do t'i ndërlidhet marrësit që sapo ka nënshkruar dokumentin msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them." msgstr "Ky fushë nuk mund të modifikohet apo të fshihet. Kur ndani lidhjen direkte të këtij model ose e shtoni në profilin tuaj publik, kushdo që e akseson mund të shkruajë emrin dhe email-in e tij, dhe të plotësojë fushat e caktuara për ta." -#: apps/remix/app/components/dialogs/template-folder-create-dialog.tsx -#: apps/remix/app/components/dialogs/folder-create-dialog.tsx -msgid "This folder name is already taken." -msgstr "Ky emër dosjeje është marrë tashmë." +#: apps/remix/app/components/dialogs/folder-delete-dialog.tsx +msgid "This folder contains multiple items. Deleting it will also delete all items in the folder, including nested folders and their contents." +msgstr "Kjo dosje përmban disa artikuj. Fshirja e saj do të fshijë gjithashtu të gjitha artikujt në dosje, duke përfshirë dosjet e mbivendosura dhe përmbajtjet e tyre." #: packages/ui/primitives/template-flow/add-template-settings.tsx msgid "This is how the document will reach the recipients once the document is ready for signing." @@ -6784,10 +6940,6 @@ msgstr "Kështu do të arrijë dokumenti te marrësit sapo dokumenti të jetë g msgid "This is the claim that this organisation was initially created with. Any feature flag changes to this claim will be backported into this organisation." msgstr "Kjo është kërkesa që kjo organizatë fillimisht u krijua me të. Çdo ndryshim në flamurët e veçorive në këtë kërkesë do të transferohet në këtë organizatë." -#: apps/remix/app/routes/_unauthenticated+/team.verify.transfer.$token.tsx -msgid "This link is invalid or has expired." -msgstr "Ky lidhje është e pavlefshme ose ka skaduar." - #: apps/remix/app/routes/_unauthenticated+/team.verify.email.$token.tsx msgid "This link is invalid or has expired. Please contact your team to resend a verification." msgstr "Ky link është i pavlefshëm ose ka skaduar. Ju lutem kontaktoni ekipin tuaj për të dërguar përsëri një verifikim." @@ -6858,6 +7010,10 @@ msgstr "Kjo do të dërgohet pronarit të dokumentit sapo dokumenti të jetë pl msgid "This will ONLY backport feature flags which are set to true, anything disabled in the initial claim will not be backported" msgstr "Kjo do të TRANSFEROHET VETËM flamujt e veçorive që janë vendosur në të vërtetë, çdo gjë që është çaktivizuar në kërkesën fillestare nuk do të transferohet" +#: apps/remix/app/components/dialogs/session-logout-all-dialog.tsx +msgid "This will sign you out of all other devices. You will need to sign in again on those devices to continue using your account." +msgstr "Kjo do t'ju nxjerrë nga të gjitha pajisjet e tjera. Do të duhet të hyni përsëri në ato pajisje për të vazhduar përdorimin e llogarisë suaj." + #: apps/remix/app/components/tables/internal-audit-log-table.tsx #: apps/remix/app/components/tables/document-logs-table.tsx msgid "Time" @@ -7144,6 +7300,9 @@ msgstr "I papërfunduar" #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx #: apps/remix/app/routes/_internal+/[__htmltopdf]+/certificate.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx msgid "Unknown" msgstr "E panjohur" @@ -7155,6 +7314,10 @@ msgstr "E pakufizuar" msgid "Unlimited documents, API and more" msgstr "Dokumente pa kufi, API dhe më shumë" +#: apps/remix/app/components/general/folder/folder-card.tsx +msgid "Unpin" +msgstr "Çaktivizo" + #: apps/remix/app/components/dialogs/team-group-create-dialog.tsx msgid "Untitled Group" msgstr "Grup pa titull" @@ -7497,6 +7660,11 @@ msgstr "Shiko të gjitha dokumentet e lidhura" msgid "View all security activity related to your account." msgstr "Shiko të gjitha aktivitetet e sigurisë lidhur me llogarinë tuaj." +#: apps/remix/app/routes/_authenticated+/settings+/security.sessions.tsx +#: apps/remix/app/routes/_authenticated+/settings+/security._index.tsx +msgid "View and manage all active sessions for your account." +msgstr "Shiko dhe menaxho të gjitha seancat aktive për llogarinë tuaj." + #: apps/remix/app/components/forms/2fa/view-recovery-codes-dialog.tsx msgid "View Codes" msgstr "Shiko Kodet" @@ -7855,7 +8023,6 @@ msgstr "Ne do të gjenerojmë lidhje nënshkrimi për ju, të cilat mund t'i dë msgid "We won't send anything to notify recipients." msgstr "Ne nuk do të dërgojmë asgjë për të njoftuar pranuesit." -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.f.$folderId._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates._index.tsx #: apps/remix/app/components/tables/documents-table-empty-state.tsx msgid "We're all empty" @@ -8215,7 +8382,6 @@ msgstr "Ju e keni iniciuar dokumentin {0} që ju kërkon të {recipientActionVer msgid "You have no webhooks yet. Your webhooks will be shown here once you create them." msgstr "Ju nuk keni ende ndonjë webhook. Webhook-et tuaja do të shfaqen këtu sapo t'i krijoni." -#: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates.f.$folderId._index.tsx #: apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates._index.tsx msgid "You have not yet created any templates. To create a template please upload one." msgstr "Ju ende nuk keni krijuar ndonjë shabllon. Për të krijuar një shabllon ju lutemi ngarkoni një." @@ -8317,7 +8483,6 @@ msgstr "Ju keni verifikuar adresën tuaj të emailit për <0>{0}." msgid "You must enter '{deleteMessage}' to proceed" msgstr "Duhet të shkruani '{deleteMessage}' për të vazhduar" -#: apps/remix/app/components/dialogs/template-folder-delete-dialog.tsx #: apps/remix/app/components/dialogs/folder-delete-dialog.tsx msgid "You must type '{deleteMessage}' to confirm" msgstr "Ju duhet të shkruani '{deleteMessage}' për të konfirmuar" From 8d1d098e3ac9c2eb428e1ac4ba07ce52b0d318e9 Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Thu, 3 Jul 2025 10:07:54 +1000 Subject: [PATCH 15/17] v1.12.1 --- apps/remix/package.json | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/remix/package.json b/apps/remix/package.json index f4ecf9f7b..282711a03 100644 --- a/apps/remix/package.json +++ b/apps/remix/package.json @@ -101,5 +101,5 @@ "vite-plugin-babel-macros": "^1.0.6", "vite-tsconfig-paths": "^5.1.4" }, - "version": "1.12.0" + "version": "1.12.1" } diff --git a/package-lock.json b/package-lock.json index b6345f729..fec06dcb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@documenso/root", - "version": "1.12.0", + "version": "1.12.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@documenso/root", - "version": "1.12.0", + "version": "1.12.1", "workspaces": [ "apps/*", "packages/*" @@ -89,7 +89,7 @@ }, "apps/remix": { "name": "@documenso/remix", - "version": "1.12.0", + "version": "1.12.1", "dependencies": { "@documenso/api": "*", "@documenso/assets": "*", diff --git a/package.json b/package.json index c8145108e..ee3d36a71 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "1.12.0", + "version": "1.12.1", "scripts": { "build": "turbo run build", "dev": "turbo run dev --filter=@documenso/remix", From cdb9b9ee039ef1d3a81dcf36bd1ef5e53e992b4b Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Thu, 3 Jul 2025 10:13:12 +1000 Subject: [PATCH 16/17] chore: add certificate error logs (#1875) Add certificate logs --- packages/lib/server-only/document/seal-document.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/lib/server-only/document/seal-document.ts b/packages/lib/server-only/document/seal-document.ts index 17d4b0d52..ae7a851ee 100644 --- a/packages/lib/server-only/document/seal-document.ts +++ b/packages/lib/server-only/document/seal-document.ts @@ -117,7 +117,12 @@ export const sealDocument = async ({ ? await getCertificatePdf({ documentId, language: document.documentMeta?.language, - }).catch(() => null) + }).catch((e) => { + console.log('Failed to get certificate PDF'); + console.error(e); + + return null; + }) : null; const doc = await PDFDocument.load(pdfData); From 9917def0ca341c3818b3f645a1165b2755c1abe4 Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Thu, 3 Jul 2025 10:31:22 +1000 Subject: [PATCH 17/17] v1.12.2-rc.0 --- apps/remix/package.json | 2 +- package-lock.json | 6 +++--- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/remix/package.json b/apps/remix/package.json index 282711a03..f2604ec00 100644 --- a/apps/remix/package.json +++ b/apps/remix/package.json @@ -101,5 +101,5 @@ "vite-plugin-babel-macros": "^1.0.6", "vite-tsconfig-paths": "^5.1.4" }, - "version": "1.12.1" + "version": "1.12.2-rc.0" } diff --git a/package-lock.json b/package-lock.json index fec06dcb4..8669c3dcc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@documenso/root", - "version": "1.12.1", + "version": "1.12.2-rc.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@documenso/root", - "version": "1.12.1", + "version": "1.12.2-rc.0", "workspaces": [ "apps/*", "packages/*" @@ -89,7 +89,7 @@ }, "apps/remix": { "name": "@documenso/remix", - "version": "1.12.1", + "version": "1.12.2-rc.0", "dependencies": { "@documenso/api": "*", "@documenso/assets": "*", diff --git a/package.json b/package.json index ee3d36a71..4dc1a8050 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "1.12.1", + "version": "1.12.2-rc.0", "scripts": { "build": "turbo run build", "dev": "turbo run dev --filter=@documenso/remix",