Compare commits
13 Commits
feat/unsub
...
feat/laka-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8708c97937 | ||
|
|
042b57bfaa | ||
|
|
c6a26ee2ed | ||
|
|
d3c8cbd6c0 | ||
|
|
6c3dbaefd3 | ||
|
|
f938723d9a | ||
|
|
0928709173 | ||
|
|
ade9aad4bf | ||
|
|
5fbaf26707 | ||
|
|
b69835f7de | ||
|
|
58ff6ad041 | ||
|
|
adbc945ed6 | ||
|
|
c5d85cdb2d |
@@ -17,6 +17,7 @@ SMTP_USER=
|
||||
SMTP_PASSWORD=
|
||||
EMAIL_FROM= # e.g. "Kan <hello@mail.kan.bn>"
|
||||
SMTP_SECURE= # set to "false" to use port 587
|
||||
SMTP_REJECT_UNAUTHORIZED= # set to "false" to accept invalid certs
|
||||
|
||||
# Switch email features off entirely (optional)
|
||||
NEXT_PUBLIC_DISABLE_EMAIL=
|
||||
|
||||
75
README.md
75
README.md
@@ -34,7 +34,7 @@ See our [roadmap](https://kan.bn/kan/roadmap) for upcoming features.
|
||||
|
||||
## Screenshot 👁️
|
||||
|
||||
<img width="1507" alt="hero-dark" src="https://github.com/user-attachments/assets/5f7b6ad3-f31d-4b45-93dc-0132b3f2afd4" />
|
||||
<img width="1507" alt="hero-dark" src="https://github.com/user-attachments/assets/8490104a-cd5d-49de-afc2-152fd8a93119" />
|
||||
|
||||
## Made With 🛠️
|
||||
|
||||
@@ -138,42 +138,43 @@ pnpm dev
|
||||
|
||||
## Environment Variables 🔐
|
||||
|
||||
| Variable | Description | Required | Example |
|
||||
| ----------------------------------------- | -------------------------------------------------------- | ------------------------ | ----------------------------------------------------------- |
|
||||
| `POSTGRES_URL` | PostgreSQL connection URL | To use external database | `postgres://user:pass@localhost:5432/db` |
|
||||
| `EMAIL_FROM` | Sender email address | For Email | `"Kan <hello@mail.kan.bn>"` |
|
||||
| `SMTP_HOST` | SMTP server hostname | For Email | `smtp.resend.com` |
|
||||
| `SMTP_PORT` | SMTP server port | For Email | `465` |
|
||||
| `SMTP_USER` | SMTP username/email | No | `resend` |
|
||||
| `SMTP_PASSWORD` | SMTP password/token | No | `re_xxxx` |
|
||||
| `SMTP_SECURE` | Use secure SMTP connection (defaults to true if not set) | For Email | `true` |
|
||||
| `NEXT_PUBLIC_DISABLE_EMAIL` | To disable all email features | For Email | `true` |
|
||||
| `NEXT_PUBLIC_BASE_URL` | Base URL of your installation | Yes | `http://localhost:3000` |
|
||||
| `BETTER_AUTH_SECRET` | Auth encryption secret | Yes | Random 32+ char string |
|
||||
| `BETTER_AUTH_TRUSTED_ORIGINS` | Allowed callback origins | No | `http://localhost:3000,http://localhost:3001` |
|
||||
| `GOOGLE_CLIENT_ID` | Google OAuth client ID | For Google login | `xxx.apps.googleusercontent.com` |
|
||||
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | For Google login | `xxx` |
|
||||
| `DISCORD_CLIENT_ID` | Discord OAuth client ID | For Discord login | `xxx` |
|
||||
| `DISCORD_CLIENT_SECRET` | Discord OAuth client secret | For Discord login | `xxx` |
|
||||
| `GITHUB_CLIENT_ID` | GitHub OAuth client ID | For GitHub login | `xxx` |
|
||||
| `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | For GitHub login | `xxx` |
|
||||
| `OIDC_CLIENT_ID` | Generic OIDC client ID | For OIDC login | `xxx` |
|
||||
| `OIDC_CLIENT_SECRET` | Generic OIDC client secret | For OIDC login | `xxx` |
|
||||
| `OIDC_DISCOVERY_URL` | OIDC discovery URL | For OIDC login | `https://auth.example.com/.well-known/openid-configuration` |
|
||||
| `TRELLO_APP_API_KEY` | Trello app API key | For Trello import | `xxx` |
|
||||
| `TRELLO_APP_API_SECRET` | Trello app API secret | For Trello import | `xxx` |
|
||||
| `S3_REGION` | S3 storage region | For file uploads | `WEUR` |
|
||||
| `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` |
|
||||
| `S3_ACCESS_KEY_ID` | S3 access key | For file uploads | `xxx` |
|
||||
| `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads | `xxx` |
|
||||
| `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` |
|
||||
| `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` |
|
||||
| `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` |
|
||||
| `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` |
|
||||
| `NEXT_PUBLIC_ATTATCHMENTS_BUCKET_NAME` | S3 bucket name for attatchments | For file uploads | `attatchments` |
|
||||
| `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` |
|
||||
| `NEXT_PUBLIC_DISABLE_SIGN_UP` | Disable sign up | For authentication | `false` |
|
||||
| `NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY` | Hide “Powered by kan.bn” on public boards (self-host) | For white labelling | `true` |
|
||||
| Variable | Description | Required | Example |
|
||||
| ----------------------------------------- | --------------------------------------------------------- | ------------------------ | ----------------------------------------------------------- |
|
||||
| `POSTGRES_URL` | PostgreSQL connection URL | To use external database | `postgres://user:pass@localhost:5432/db` |
|
||||
| `EMAIL_FROM` | Sender email address | For Email | `"Kan <hello@mail.kan.bn>"` |
|
||||
| `SMTP_HOST` | SMTP server hostname | For Email | `smtp.resend.com` |
|
||||
| `SMTP_PORT` | SMTP server port | For Email | `465` |
|
||||
| `SMTP_USER` | SMTP username/email | No | `resend` |
|
||||
| `SMTP_PASSWORD` | SMTP password/token | No | `re_xxxx` |
|
||||
| `SMTP_SECURE` | Use secure SMTP connection (defaults to true if not set) | For Email | `true` |
|
||||
| `SMTP_REJECT_UNAUTHORIZED` | Reject invalid certificates (defaults to true if not set) | For Email | `false` |
|
||||
| `NEXT_PUBLIC_DISABLE_EMAIL` | To disable all email features | For Email | `true` |
|
||||
| `NEXT_PUBLIC_BASE_URL` | Base URL of your installation | Yes | `http://localhost:3000` |
|
||||
| `BETTER_AUTH_SECRET` | Auth encryption secret | Yes | Random 32+ char string |
|
||||
| `BETTER_AUTH_TRUSTED_ORIGINS` | Allowed callback origins | No | `http://localhost:3000,http://localhost:3001` |
|
||||
| `GOOGLE_CLIENT_ID` | Google OAuth client ID | For Google login | `xxx.apps.googleusercontent.com` |
|
||||
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | For Google login | `xxx` |
|
||||
| `DISCORD_CLIENT_ID` | Discord OAuth client ID | For Discord login | `xxx` |
|
||||
| `DISCORD_CLIENT_SECRET` | Discord OAuth client secret | For Discord login | `xxx` |
|
||||
| `GITHUB_CLIENT_ID` | GitHub OAuth client ID | For GitHub login | `xxx` |
|
||||
| `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | For GitHub login | `xxx` |
|
||||
| `OIDC_CLIENT_ID` | Generic OIDC client ID | For OIDC login | `xxx` |
|
||||
| `OIDC_CLIENT_SECRET` | Generic OIDC client secret | For OIDC login | `xxx` |
|
||||
| `OIDC_DISCOVERY_URL` | OIDC discovery URL | For OIDC login | `https://auth.example.com/.well-known/openid-configuration` |
|
||||
| `TRELLO_APP_API_KEY` | Trello app API key | For Trello import | `xxx` |
|
||||
| `TRELLO_APP_API_SECRET` | Trello app API secret | For Trello import | `xxx` |
|
||||
| `S3_REGION` | S3 storage region | For file uploads | `WEUR` |
|
||||
| `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` |
|
||||
| `S3_ACCESS_KEY_ID` | S3 access key | For file uploads | `xxx` |
|
||||
| `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads | `xxx` |
|
||||
| `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` |
|
||||
| `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` |
|
||||
| `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` |
|
||||
| `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` |
|
||||
| `NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME` | S3 bucket name for attachments | For file uploads | `attachments` |
|
||||
| `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` |
|
||||
| `NEXT_PUBLIC_DISABLE_SIGN_UP` | Disable sign up | For authentication | `false` |
|
||||
| `NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY` | Hide “Powered by kan.bn” on public boards (self-host) | For white labelling | `true` |
|
||||
|
||||
See `.env.example` for a complete list of supported environment variables.
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ checksums:
|
||||
A%20powerful%2C%20flexible%20kanban%20app%20that%20helps%20you%20organise%20work%2C%20track%20progress%2C%20and%20deliver%20results%E2%80%94all%20in%20one%20place./singular: d405b83b0d631cb72f4347c10bcbb643
|
||||
Account/singular: 01215c12fb1cdb93bd0c84c1382bef56
|
||||
Account%20deleted/singular: a25da96a1579c4491be0a95669ef18a4
|
||||
Actions/singular: c46571856723b03262fd33f511116298
|
||||
Activity/singular: 1948763de8e531483a798b68195e297e
|
||||
Activity%20log/singular: 3ec6755040306fdc9ce801bcf6ab28e1
|
||||
Activity%20logs/singular: 8b1f0bb96a905646ecfad1cfdfa42168
|
||||
@@ -110,6 +109,7 @@ checksums:
|
||||
Complete%20control%20and%20ownership%3A/singular: 0d8b682ba873272217425ccfc96aa9cd
|
||||
completed%20a%20checklist%20item/singular: 757b04c6c80cc927e1c597c0ad4fda33
|
||||
completed%20checklist%20item%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 71ec18acf051fc909a48a07ca3578673
|
||||
Confirm%20your%20email%20preferences%3A/singular: 043c161dd9866231ae2418fdd9f61b9c
|
||||
Confirm%20your%20new%20password/singular: a0d2935d7b63f8dd19d7c0de47524416
|
||||
Connect%20Trello/singular: 4440a0b9e387ef7136e3958e7a089213
|
||||
Connect%20your%20favorite%20tools%20to%20streamline%20your%20workflow./singular: 033c5dcdb059ccb634aef7fe63f2f45d
|
||||
@@ -168,6 +168,7 @@ checksums:
|
||||
Display%20name%20must%20be%20at%20least%203%20characters%20long/singular: 84178b79845a70937af5e26020403052
|
||||
Display%20name%20updated/singular: 4e27503ca24ef5f009713951ca9e5b97
|
||||
Do%20you%20offer%20a%20free%20plan%3F/singular: 3ef16b0994f0d9ae17067782ca9bed1b
|
||||
Do%20you%20want%20to%20unsubscribe%3F/singular: 8173b82c731ba885939d223eeef2e40b
|
||||
docs/singular: 307bff5678ada918da1f1ec3edc76cac
|
||||
Docs/singular: 55fea190a0c0fb32acd3dc986cd3cc91
|
||||
Documentation/singular: 1563fcb5ddb5037b0709ccd3dd384a92
|
||||
@@ -230,7 +231,6 @@ checksums:
|
||||
Free%2C%20forever/singular: ae4f2f81e88a50b5f250ef8e8e77e74b
|
||||
Full-time/singular: fe6e201f6676ae354111435cf6c76910
|
||||
Fun/singular: 395bdc48e943762b6cde649f4a96771d
|
||||
General/singular: b891e8f15579fc5d97bcaf3637f5ae59
|
||||
Get%20started/singular: 5c783951b0100a168bdd2161ff294833
|
||||
Get%20Started/singular: 1d5f030c4ec9c869e647ae060518b948
|
||||
Get%20started%20by%20creating%20a%20new%20%7B0%7D/singular: 4ca5ef637c08104e9dbb5ff9f49f0680
|
||||
@@ -242,10 +242,6 @@ checksums:
|
||||
GitHub/singular: 6e1cf3c00fa6fbe24afcc78ea3b5f3e4
|
||||
Go%20Home/singular: 6251589da1964d55afabdfd64c84c335
|
||||
Go%20to%20app/singular: 896d0441384dcd2bfb3b23d61ff1944d
|
||||
Go%20to%20boards/singular: dc1362de207d67fe84fb0caf60262e73
|
||||
Go%20to%20members/singular: 445f4efbc4b1e7509f4fd79ebfbb1476
|
||||
Go%20to%20settings/singular: 24a7f96880650c9b37099d69f4b7e2a9
|
||||
Go%20to%20templates/singular: e4e58e33d637282d141df466d729bc7c
|
||||
High%20Priority/singular: 5d231ff8254aabc875f194c4b4f49c97
|
||||
Hired/singular: e5a9b1bd409b007141fe3d7890022f9a
|
||||
Host%20Kan%20on%20your%20own%20infrastructure.%20Ideal%20for%20organisations%20that%20need%20complete%20control%20over%20their%20data./singular: 8e7ae0783d60ef4624d3caf9bfc3747f
|
||||
@@ -289,7 +285,6 @@ checksums:
|
||||
Kanban%20is%20better%20with%20a%20team.%20Perfect%20for%20small%20and%20growing%20teams%20looking%20to%20collaborate./singular: a77bee43046b260797c8936ad23e9223
|
||||
Kanban%20reimagined/singular: 613ccfdd9f54c66cbf68cfa313498766
|
||||
Keep%20in%20mind%20that%20this%20action%20is%20irreversible./singular: 79702b2ad3be71cb8b87f1122a60c199
|
||||
Keyboard%20Shortcuts/singular: ef00d7494b69def6841620bd6554d040
|
||||
Labels/singular: 6f15627a90002323eac018274b6922d6
|
||||
Labels%20%26%20filters/singular: e1ceda0c6cc32fb04cb9423582ad8fe4
|
||||
Labels%20%26%20Filters/singular: 8f0bdd6084516f8241cb613178114390
|
||||
@@ -323,7 +318,6 @@ checksums:
|
||||
moved%20the%20card%20from%20%3C0%3E%7B0%7D%3C%2F0%3E%20to%3C1%3E%7B1%7D%3C%2F1%3E/singular: 11edf0427766c26db541d46379dc3c16
|
||||
moved%20the%20card%20to%20another%20list/singular: 2e8c41bfafb42fa299ce56e4300205ff
|
||||
Name/singular: 9368b5a047572b6051f334af5aa76819
|
||||
Navigation/singular: 0373afd8238db1c49f4be4fa6cdf5cd3
|
||||
Need%20help%3F/singular: 04e7322f2d3ffb2d73ff2f64b71637c8
|
||||
New/singular: 126d036fae5fb6b629728ecb97e6195b
|
||||
New%20%7B0%7D/singular: 67b6a22a65e0956f2091d00e6966652b
|
||||
@@ -345,15 +339,12 @@ checksums:
|
||||
No%20boards%20found/singular: e044088d2c51b6bdf660fafa86ee1e17
|
||||
No%20credit%20card%20required/singular: 2090aa4171dc0b60735069f89b592883
|
||||
No%20download%20URL%20available%20for%20this%20attachment./singular: e367d39420b2242f9d2fd749c87f446a
|
||||
No%20keyboard%20shortcuts%20registered./singular: 7f1ed5d777cade7d62303e9e591bbf63
|
||||
No%20lists/singular: cedf633d99c77ff4356e089f2d98c0a6
|
||||
No%20results%20found%20for%20%22%7BdebouncedQuery%7D%22./singular: 5db6294712528cd897b15ae36f4fd834
|
||||
Offer/singular: 82b4e0c9a3f5b4bd93590847de7c32a1
|
||||
Onboarding/singular: 52b23f9c62ff199d4c09920e7641829e
|
||||
Once%20you%20delete%20your%20account%2C%20there%20is%20no%20going%20back.%20This%20action%20cannot%20be%20undone./singular: 9cf7aa6ef30890e5124e266c081bae1c
|
||||
Once%20you%20delete%20your%20workspace%2C%20there%20is%20no%20going%20back.%20This%20action%20cannot%20be%20undone./singular: c9ce6a516ed1f361653e8f8db3dd5ffd
|
||||
Open%20command%20menu/singular: cf00563ea1a994e7c36a761d56664acc
|
||||
Open%20keyboard%20shortcuts/singular: 638ae0999fd03d2c611064274859422e
|
||||
Open%20source/singular: 81a747dc664de1a3389b495c8f84843b
|
||||
Open%20Source%20Friends/singular: ffe3d75e5d03b8469c9dcb019dceb164
|
||||
or/singular: 7b133c38bec0d5ee23cc6bcf9a8de50b
|
||||
@@ -432,7 +423,6 @@ checksums:
|
||||
Settings%20%7C%20Billing/singular: e44cba741d5414035a0b499c5766c203
|
||||
Settings%20%7C%20Integrations/singular: d04992e28016452f6d3d7dcc0b592415
|
||||
Settings%20%7C%20Workspace/singular: 5d0bacf7ff696da940f232df45edfd39
|
||||
Shortcuts/singular: db3330ed3240c398054f3be23c52851f
|
||||
Sign%20in/singular: cb8757c7450e17de1e226e82fb0fa4a2
|
||||
Sign%20In/singular: ec7b8f314fe9bc6591006707484ede61
|
||||
Sign%20Up/singular: 0dd2ae69be4618c1f9e615774a4509ca
|
||||
@@ -520,6 +510,7 @@ checksums:
|
||||
Unlimited%20lists/singular: 5c418701b27b9acbc5dd199719007362
|
||||
Unlimited%20members/singular: f2949ca2dc18b0063af92e60779abb65
|
||||
Unlimited%20workspaces/singular: b504d01997bf908af1d486d9942fed36
|
||||
Unsubscribe/singular: d1a0b07295687d1f08d4df1c411072dd
|
||||
Update/singular: 079fc039262fd31b10532929685c2d1b
|
||||
Update%20label/singular: 97880b503dfe956941c5f23025a1c102
|
||||
updated%20a%20checklist%20item/singular: 198e1d1d503f4b69b752dd84d0cc0e9d
|
||||
@@ -545,6 +536,7 @@ checksums:
|
||||
View%20workspace/singular: c9e4b789330b08c18ca8db7044409e5f
|
||||
Visibility/singular: 1ff412f8fcde0f460acbf11153649646
|
||||
We%20are%20using%20the%20%3C0%3EAGPL-3.0%20license%3C%2F0%3E./singular: 08c5ddd938a2a70f61d684e41e18697a
|
||||
We%20couldn't%20update%20your%20preferences.%20Please%20try%20again./singular: 69d1d2575f2e73b08ac622bde0a45b4d
|
||||
We're%20just%20getting%20started.%20/singular: 2dfa121e0ff1914e08068308a81973c0
|
||||
Welcome%20back/singular: 4928884739ba559e6e4b960e80fe1452
|
||||
What%20license%20are%20you%20using%3F/singular: 59d00e1bf28edc21b77fec94875f57ca
|
||||
@@ -577,6 +569,7 @@ checksums:
|
||||
You%20can%20self-host%20by%20following%20the%20instructions%20in%20our%20%3C0%3Erepo%3C%2F0%3E./singular: a6152a41b2d8f64d5a657e5b8bc808a9
|
||||
You%20have%20been%20logged%20in%20successfully./singular: ef8fad1dce13ae4112f17c5258655fea
|
||||
You%20have%20been%20signed%20up%20successfully./singular: f614a6e3b45f5ffb9a3b0fb420fef84b
|
||||
You%20have%20been%20unsubscribed!/singular: e0b9985faa4e7f25b71acc77750923a6
|
||||
You%20have%20unlimited%20seats%20with%20your%20Pro%20Plan.%20There%20is%20no%20additional%20charge%20for%20new%20members!/singular: e3dc59a5ba7211cd3d8516b3a79d85ca
|
||||
You've%20been%20invited%20to%20join%20a%20workspace%20on%20kan.bn./singular: 257b840726f972f384243a72767f880f
|
||||
You've%20been%20invited%20to%20join%20a%20workspace./singular: 24fc6cdc8740f37a83df85f582f03293
|
||||
@@ -588,6 +581,7 @@ checksums:
|
||||
Your%20profile%20image%20has%20been%20updated./singular: 099e1780348cd7bf617721344371a430
|
||||
Your%20Trello%20account%20has%20been%20disconnected./singular: 126aeeb73f7e4cad338056e4c933f39b
|
||||
Your%20Trello%20account%20is%20connected./singular: 0499d193001fce2fbec445ae034ce512
|
||||
Your%20unsubscribe%20link%20is%20missing%20a%20token.%20Please%20open%20the%20latest%20email%20and%20try%20again./singular: 3e4cce96bc1197a1caa2b7fb4d3c7e53
|
||||
Your%20workspace%20description%20has%20been%20updated./singular: 98de6f65c567c6654cc0adce3c9d5656
|
||||
Your%20workspace%20has%20been%20deleted./singular: e7a3efcfc7dd18cb3e917acb67498292
|
||||
Your%20workspace%20name%20has%20been%20updated./singular: a87ea3b0d71e6dc5dd525d77114a9322
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"@lingui/conf": "^5.3.2",
|
||||
"@lingui/macro": "^5.3.2",
|
||||
"@lingui/react": "^5.3.2",
|
||||
"@novu/api": "^3.11.0",
|
||||
"@t3-oss/env-nextjs": "^0.11.1",
|
||||
"@tailwindcss/typography": "^0.5.16",
|
||||
"@tanstack/react-query": "catalog:",
|
||||
@@ -46,6 +47,7 @@
|
||||
"aws-sdk": "^2.1692.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"geist": "^1.3.1",
|
||||
"jose": "^6.1.2",
|
||||
"next": "^15.3.4",
|
||||
"next-logger": "^5.0.1",
|
||||
"next-runtime-env": "^1.7.2",
|
||||
|
||||
@@ -2,8 +2,10 @@ import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import type { KeyboardShortcut } from "~/providers/keyboard-shortcuts";
|
||||
import LottieIcon from "~/components/LottieIcon";
|
||||
import { useIsMobile } from "~/hooks/useMediaQuery";
|
||||
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
|
||||
|
||||
const Button: React.FC<{
|
||||
href: string;
|
||||
@@ -12,10 +14,20 @@ const Button: React.FC<{
|
||||
json: object;
|
||||
isCollapsed?: boolean;
|
||||
onCloseSideNav?: () => void;
|
||||
}> = ({ href, current, name, json, isCollapsed = false, onCloseSideNav }) => {
|
||||
keyboardShortcut: KeyboardShortcut;
|
||||
}> = ({
|
||||
href,
|
||||
current,
|
||||
name,
|
||||
json,
|
||||
isCollapsed = false,
|
||||
keyboardShortcut,
|
||||
onCloseSideNav,
|
||||
}) => {
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const [index, setIndex] = useState(0);
|
||||
const isMobile = useIsMobile();
|
||||
const { keys: shortcutKeys } = useKeyboardShortcut(keyboardShortcut);
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
setIsHovered(true);
|
||||
@@ -34,18 +46,27 @@ const Button: React.FC<{
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onClick={handleClick}
|
||||
className={twMerge(
|
||||
"group flex h-[34px] items-center rounded-md p-1.5 text-sm font-normal leading-6 hover:bg-light-200 hover:text-light-1000 dark:hover:bg-dark-200 dark:hover:text-dark-1000",
|
||||
"group flex h-[34px] items-center justify-between rounded-md p-1.5 text-sm font-normal leading-6 hover:bg-light-200 hover:text-light-1000 dark:hover:bg-dark-200 dark:hover:text-dark-1000",
|
||||
current
|
||||
? "bg-light-200 text-light-1000 dark:bg-dark-200 dark:text-dark-1000"
|
||||
: "text-neutral-600 dark:bg-dark-100 dark:text-dark-900",
|
||||
isCollapsed
|
||||
? "justify-start gap-x-3 md:justify-center md:gap-x-0"
|
||||
: "gap-x-3",
|
||||
)}
|
||||
title={isCollapsed ? name : undefined}
|
||||
>
|
||||
<LottieIcon index={index} json={json} isPlaying={isHovered} />
|
||||
<span className={twMerge(isCollapsed && "md:hidden")}>{name}</span>
|
||||
<div
|
||||
className={twMerge(
|
||||
"flex items-center",
|
||||
isCollapsed
|
||||
? "justify-start gap-x-3 md:justify-center md:gap-x-0"
|
||||
: "gap-x-3",
|
||||
)}
|
||||
>
|
||||
<LottieIcon index={index} json={json} isPlaying={isHovered} />
|
||||
<span className={twMerge(isCollapsed && "md:hidden")}>{name}</span>
|
||||
</div>
|
||||
{!isCollapsed && (
|
||||
<div className="hidden md:group-hover:inline-flex">{shortcutKeys}</div>
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ import { twMerge } from "tailwind-merge";
|
||||
import type { Subscription } from "@kan/shared/utils";
|
||||
import { hasActiveSubscription } from "@kan/shared/utils";
|
||||
|
||||
import type { KeyboardShortcut } from "~/providers/keyboard-shortcuts";
|
||||
import boardsIconDark from "~/assets/boards-dark.json";
|
||||
import boardsIconLight from "~/assets/boards-light.json";
|
||||
import membersIconDark from "~/assets/members-dark.json";
|
||||
@@ -86,26 +87,59 @@ export default function SideNavigation({
|
||||
|
||||
const isDarkMode = resolvedTheme === "dark";
|
||||
|
||||
const navigation = [
|
||||
const navigation: {
|
||||
name: string;
|
||||
href: string;
|
||||
icon: object;
|
||||
keyboardShortcut: KeyboardShortcut;
|
||||
}[] = [
|
||||
{
|
||||
name: t`Boards`,
|
||||
href: "/boards",
|
||||
icon: isDarkMode ? boardsIconDark : boardsIconLight,
|
||||
keyboardShortcut: {
|
||||
type: "SEQUENCE",
|
||||
strokes: [{ key: "G" }, { key: "B" }],
|
||||
action: () => router.push("/boards"),
|
||||
group: "NAVIGATION",
|
||||
description: t`Go to boards`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: t`Templates`,
|
||||
href: "/templates",
|
||||
icon: isDarkMode ? templatesIconDark : templatesIconLight,
|
||||
keyboardShortcut: {
|
||||
type: "SEQUENCE",
|
||||
strokes: [{ key: "G" }, { key: "T" }],
|
||||
action: () => router.push("/templates"),
|
||||
group: "NAVIGATION",
|
||||
description: t`Go to templates`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: t`Members`,
|
||||
href: "/members",
|
||||
icon: isDarkMode ? membersIconDark : membersIconLight,
|
||||
keyboardShortcut: {
|
||||
type: "SEQUENCE",
|
||||
strokes: [{ key: "G" }, { key: "M" }],
|
||||
action: () => router.push("/members"),
|
||||
group: "NAVIGATION",
|
||||
description: t`Go to members`,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: t`Settings`,
|
||||
href: "/settings",
|
||||
icon: isDarkMode ? settingsIconDark : settingsIconLight,
|
||||
keyboardShortcut: {
|
||||
type: "SEQUENCE",
|
||||
strokes: [{ key: "G" }, { key: "S" }],
|
||||
action: () => router.push("/settings"),
|
||||
group: "NAVIGATION",
|
||||
description: t`Go to settings`,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -163,6 +197,7 @@ export default function SideNavigation({
|
||||
json={item.icon}
|
||||
isCollapsed={isCollapsed}
|
||||
onCloseSideNav={onCloseSideNav}
|
||||
keyboardShortcut={item.keyboardShortcut}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
|
||||
51
apps/web/src/components/Tooltip.tsx
Normal file
51
apps/web/src/components/Tooltip.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import type { ReactNode } from "react";
|
||||
import type { Root } from "react-dom/client";
|
||||
import type { Placement } from "tippy.js";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import tippy from "tippy.js";
|
||||
|
||||
interface TooltipProps {
|
||||
children: ReactNode;
|
||||
content: ReactNode;
|
||||
placement?: Placement;
|
||||
delay?: number | [number, number];
|
||||
}
|
||||
|
||||
export function Tooltip({
|
||||
children,
|
||||
content,
|
||||
placement = "bottom",
|
||||
delay = [500, 0],
|
||||
}: TooltipProps) {
|
||||
const triggerRef = useRef<HTMLDivElement>(null);
|
||||
const rootRef = useRef<Root | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!triggerRef.current) return;
|
||||
|
||||
const container = document.createElement("div");
|
||||
const root = createRoot(container);
|
||||
rootRef.current = root;
|
||||
root.render(content);
|
||||
|
||||
const instance = tippy(triggerRef.current, {
|
||||
content: container,
|
||||
placement,
|
||||
delay,
|
||||
interactive: false,
|
||||
theme: "tooltip",
|
||||
});
|
||||
|
||||
return () => {
|
||||
instance.destroy();
|
||||
rootRef.current?.unmount();
|
||||
};
|
||||
}, [content, placement, delay]);
|
||||
|
||||
return (
|
||||
<div ref={triggerRef} className="inline-flex">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import { twMerge } from "tailwind-merge";
|
||||
import { authClient } from "@kan/auth/client";
|
||||
|
||||
import { useIsMobile } from "~/hooks/useMediaQuery";
|
||||
import { useKeyboardShortcuts } from "~/providers/keyboard-shortcuts";
|
||||
import { useModal } from "~/providers/modal";
|
||||
import { getAvatarUrl } from "~/utils/helpers";
|
||||
|
||||
@@ -31,6 +32,7 @@ export default function UserMenu({
|
||||
const router = useRouter();
|
||||
const { theme, setTheme } = useTheme();
|
||||
const { openModal } = useModal();
|
||||
const { openLegend } = useKeyboardShortcuts();
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const handleLogout = async () => {
|
||||
@@ -169,6 +171,19 @@ export default function UserMenu({
|
||||
</Menu.Item>
|
||||
</div>
|
||||
<div className="light-border-600 border-t-[1px] p-1 dark:border-dark-600">
|
||||
<Menu.Item>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (onCloseSideNav && isMobile) {
|
||||
onCloseSideNav();
|
||||
}
|
||||
openLegend();
|
||||
}}
|
||||
className="flex w-full items-center rounded-[5px] px-3 py-2 text-left text-xs hover:bg-light-200 dark:hover:bg-dark-400"
|
||||
>
|
||||
{t`Shortcuts`}
|
||||
</button>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<Link
|
||||
href="mailto:support@kan.bn"
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { Button, Menu, Transition } from "@headlessui/react";
|
||||
import { t } from "@lingui/core/macro";
|
||||
import { Fragment, useEffect, useState } from "react";
|
||||
import { Fragment, useState } from "react";
|
||||
import { HiCheck, HiMagnifyingGlass } from "react-icons/hi2";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
|
||||
import { useModal } from "~/providers/modal";
|
||||
import { useWorkspace } from "~/providers/workspace";
|
||||
import CommandPallette from "./CommandPallette";
|
||||
import { Tooltip } from "./Tooltip";
|
||||
|
||||
export default function WorkspaceMenu({
|
||||
isCollapsed = false,
|
||||
@@ -18,17 +20,17 @@ export default function WorkspaceMenu({
|
||||
const { openModal } = useModal();
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if ((event.metaKey || event.ctrlKey) && event.key === "k") {
|
||||
event.preventDefault();
|
||||
setIsOpen(true);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
return () => document.removeEventListener("keydown", handleKeyDown);
|
||||
}, []);
|
||||
const { tooltipContent: commandPaletteShortcutTooltipContent } =
|
||||
useKeyboardShortcut({
|
||||
type: "PRESS",
|
||||
stroke: {
|
||||
key: "k",
|
||||
modifiers: ["META"],
|
||||
},
|
||||
action: () => setIsOpen(true),
|
||||
description: t`Open command menu`,
|
||||
group: "GENERAL",
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -84,15 +86,17 @@ export default function WorkspaceMenu({
|
||||
</span>
|
||||
)}
|
||||
</Menu.Button>
|
||||
<Button
|
||||
className={twMerge(
|
||||
"mb-1 h-[34px] w-[34px] flex-shrink-0 rounded-lg bg-light-200 p-2 hover:bg-light-300 focus:outline-none dark:bg-dark-200 dark:hover:bg-dark-300",
|
||||
isCollapsed && "md:mb-2 md:h-9 md:w-9",
|
||||
)}
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
<HiMagnifyingGlass className="h-4 w-4" aria-hidden="true" />
|
||||
</Button>
|
||||
<Tooltip content={commandPaletteShortcutTooltipContent}>
|
||||
<Button
|
||||
className={twMerge(
|
||||
"mb-1 h-[34px] w-[34px] flex-shrink-0 rounded-lg bg-light-200 p-2 hover:bg-light-300 focus:outline-none dark:bg-dark-200 dark:hover:bg-dark-300",
|
||||
isCollapsed && "md:mb-2 md:h-9 md:w-9",
|
||||
)}
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
<HiMagnifyingGlass className="h-4 w-4" aria-hidden="true" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -51,6 +51,8 @@ export const env = createEnv({
|
||||
VK_CLIENT_SECRET: z.string().optional(),
|
||||
LINKEDIN_CLIENT_ID: z.string().optional(),
|
||||
LINKEDIN_CLIENT_SECRET: z.string().optional(),
|
||||
NOVU_API_KEY: z.string().optional(),
|
||||
EMAIL_UNSUBSCRIBE_SECRET: z.string().optional(),
|
||||
// Generic OIDC Provider
|
||||
OIDC_CLIENT_ID: z.string().optional(),
|
||||
OIDC_CLIENT_SECRET: z.string().optional(),
|
||||
@@ -87,7 +89,7 @@ export const env = createEnv({
|
||||
NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(),
|
||||
NEXT_PUBLIC_POSTHOG_HOST: z.string().optional(),
|
||||
NEXT_PUBLIC_USE_STANDALONE_OUTPUT: z.string().optional(),
|
||||
NEXT_PUBLIC_BASE_URL: z.string().url(),
|
||||
NEXT_PUBLIC_BASE_URL: z.string().url().optional(),
|
||||
NEXT_PUBLIC_STORAGE_URL: z.string().url().optional(),
|
||||
NEXT_PUBLIC_AVATAR_BUCKET_NAME: z.string().optional(),
|
||||
NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME: z.string().optional(),
|
||||
|
||||
@@ -22,7 +22,7 @@ msgid ", or see our"
|
||||
msgstr ", oder besuche unsere"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#: src/views/boards/index.tsx:38
|
||||
#: src/views/boards/index.tsx:27
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
|
||||
@@ -30,7 +30,7 @@ msgstr "{0}"
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#. placeholder {1}: board?.name ?? t`Board`
|
||||
#. placeholder {1}: workspace.name ?? t`Workspace`
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/card/index.tsx:229
|
||||
msgid "{0} | {1}"
|
||||
msgstr "{0} | {1}"
|
||||
@@ -41,7 +41,7 @@ msgid "{0} labels"
|
||||
msgstr "{0} Labels"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Template" : "Board"
|
||||
#: src/views/board/index.tsx:400
|
||||
#: src/views/board/index.tsx:389
|
||||
msgid "{0} not found"
|
||||
msgstr "{0} nicht gefunden"
|
||||
|
||||
@@ -79,10 +79,6 @@ msgstr "Konto"
|
||||
msgid "Account deleted"
|
||||
msgstr "Konto gelöscht"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:55
|
||||
msgid "Actions"
|
||||
msgstr "Aktionen"
|
||||
|
||||
#: src/views/card/index.tsx:343
|
||||
#: src/views/public/board/CardModal.tsx:157
|
||||
msgid "Activity"
|
||||
@@ -312,7 +308,7 @@ msgstr "Abrechnungsportal"
|
||||
msgid "Blog Post"
|
||||
msgstr "Blogbeitrag"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/card/index.tsx:229
|
||||
#: src/views/public/board/index.tsx:101
|
||||
msgid "Board"
|
||||
@@ -364,7 +360,7 @@ msgstr "Board-Sichtbarkeit"
|
||||
msgid "Board visibility updated"
|
||||
msgstr "Board-Sichtbarkeit aktualisiert"
|
||||
|
||||
#: src/components/SideNavigation.tsx:97
|
||||
#: src/components/SideNavigation.tsx:91
|
||||
msgid "Boards"
|
||||
msgstr "Boards"
|
||||
|
||||
@@ -498,6 +494,10 @@ msgstr "hat ein Checklistenelement abgeschlossen"
|
||||
msgid "completed checklist item <0>{0}</0>"
|
||||
msgstr "hat Checklistenelement <0>{0}</0> abgeschlossen"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:81
|
||||
msgid "Confirm your email preferences:"
|
||||
msgstr "Bestätigen sie ihre e-mail-einstellungen:"
|
||||
|
||||
#: src/views/settings/components/ChangePasswordConfirmation.tsx:150
|
||||
msgid "Confirm your new password"
|
||||
msgstr "Bestätigen Sie Ihr neues Passwort"
|
||||
@@ -582,7 +582,6 @@ msgstr "Liste erstellen"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "template" : "board"
|
||||
#: src/views/boards/components/BoardsList.tsx:45
|
||||
#: src/views/boards/index.tsx:26
|
||||
msgid "Create new {0}"
|
||||
msgstr "Neue(n) {0} erstellen"
|
||||
|
||||
@@ -595,8 +594,7 @@ msgstr "Neuen Schlüssel erstellen"
|
||||
msgid "Create new label"
|
||||
msgstr "Neues Label erstellen"
|
||||
|
||||
#: src/views/board/index.tsx:64
|
||||
#: src/views/board/index.tsx:491
|
||||
#: src/views/board/index.tsx:478
|
||||
msgid "Create new list"
|
||||
msgstr "Neue Liste erstellen"
|
||||
|
||||
@@ -605,7 +603,7 @@ msgid "Create template"
|
||||
msgstr "Vorlage erstellen"
|
||||
|
||||
#: src/components/NewWorkspaceForm.tsx:387
|
||||
#: src/components/WorkspaceMenu.tsx:153
|
||||
#: src/components/WorkspaceMenu.tsx:149
|
||||
msgid "Create workspace"
|
||||
msgstr "Arbeitsbereich erstellen"
|
||||
|
||||
@@ -655,7 +653,7 @@ msgstr "Benutzerdefinierte Workspace-URL"
|
||||
msgid "Customer Support"
|
||||
msgstr "Kundensupport"
|
||||
|
||||
#: src/components/UserMenu.tsx:155
|
||||
#: src/components/UserMenu.tsx:153
|
||||
msgid "Dark"
|
||||
msgstr "Dunkel"
|
||||
|
||||
@@ -754,6 +752,10 @@ msgstr "Anzeigename aktualisiert"
|
||||
msgid "Do you offer a free plan?"
|
||||
msgstr "Bietet ihr einen kostenlosen Plan an?"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:78
|
||||
msgid "Do you want to unsubscribe?"
|
||||
msgstr "Möchten sie sich abmelden?"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:109
|
||||
msgid "docs"
|
||||
msgstr "Dokumente"
|
||||
@@ -762,7 +764,7 @@ msgstr "Dokumente"
|
||||
msgid "Docs"
|
||||
msgstr "Dokumente"
|
||||
|
||||
#: src/components/UserMenu.tsx:206
|
||||
#: src/components/UserMenu.tsx:191
|
||||
#: src/views/boards/components/TemplateBoards.tsx:24
|
||||
#: src/views/home/components/Footer.tsx:78
|
||||
#: src/views/home/components/Header.tsx:36
|
||||
@@ -986,7 +988,7 @@ msgid "Features"
|
||||
msgstr "Features"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:59
|
||||
#: src/components/UserMenu.tsx:214
|
||||
#: src/components/UserMenu.tsx:199
|
||||
msgid "Feedback"
|
||||
msgstr "Feedback"
|
||||
|
||||
@@ -1029,10 +1031,6 @@ msgstr "Vollzeit"
|
||||
msgid "Fun"
|
||||
msgstr "Spaß"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:53
|
||||
msgid "General"
|
||||
msgstr "Allgemein"
|
||||
|
||||
#: src/views/auth/signup/index.tsx:69
|
||||
#: src/views/home/components/Cta.tsx:61
|
||||
#: src/views/home/components/Header.tsx:106
|
||||
@@ -1052,7 +1050,7 @@ msgstr "Loslegen"
|
||||
msgid "Get started by creating a new {0}"
|
||||
msgstr "Beginnen Sie, indem Sie eine(n) neue(n) {0} erstellen"
|
||||
|
||||
#: src/views/board/index.tsx:483
|
||||
#: src/views/board/index.tsx:470
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Beginne mit dem Erstellen einer neuen Liste"
|
||||
|
||||
@@ -1086,22 +1084,6 @@ msgstr "Zur Startseite"
|
||||
msgid "Go to app"
|
||||
msgstr "Zur App"
|
||||
|
||||
#: src/components/SideNavigation.tsx:105
|
||||
msgid "Go to boards"
|
||||
msgstr "Zu Boards gehen"
|
||||
|
||||
#: src/components/SideNavigation.tsx:129
|
||||
msgid "Go to members"
|
||||
msgstr "Zu Mitgliedern gehen"
|
||||
|
||||
#: src/components/SideNavigation.tsx:141
|
||||
msgid "Go to settings"
|
||||
msgstr "Zu Einstellungen gehen"
|
||||
|
||||
#: src/components/SideNavigation.tsx:117
|
||||
msgid "Go to templates"
|
||||
msgstr "Zu Vorlagen gehen"
|
||||
|
||||
#: src/views/boards/components/TemplateBoards.tsx:18
|
||||
msgid "High Priority"
|
||||
msgstr "Hohe Priorität"
|
||||
@@ -1151,7 +1133,7 @@ msgstr "Ideen"
|
||||
msgid "Ideas to improve this page..."
|
||||
msgstr "Ideen zur Verbesserung dieser Seite..."
|
||||
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/boards/index.tsx:39
|
||||
msgid "Import"
|
||||
msgstr "Importieren"
|
||||
|
||||
@@ -1282,10 +1264,6 @@ msgstr "Kanban neu gedacht"
|
||||
msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Beachten Sie, dass diese Aktion nicht rückgängig gemacht werden kann."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:320
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Tastaturkürzel"
|
||||
|
||||
#: src/views/board/components/Filters.tsx:115
|
||||
#: src/views/board/components/NewCardForm.tsx:409
|
||||
#: src/views/card/index.tsx:119
|
||||
@@ -1334,7 +1312,7 @@ msgstr "Rechtliches"
|
||||
msgid "License"
|
||||
msgstr "Lizenz"
|
||||
|
||||
#: src/components/UserMenu.tsx:169
|
||||
#: src/components/UserMenu.tsx:167
|
||||
msgid "Light"
|
||||
msgstr "Hell"
|
||||
|
||||
@@ -1358,7 +1336,7 @@ msgstr "Listen"
|
||||
msgid "Login | kan.bn"
|
||||
msgstr "Login | kan.bn"
|
||||
|
||||
#: src/components/UserMenu.tsx:224
|
||||
#: src/components/UserMenu.tsx:209
|
||||
msgid "Logout"
|
||||
msgstr "Abmelden"
|
||||
|
||||
@@ -1395,7 +1373,7 @@ msgstr "hat Checklistenelement <0>{0}</0> als unvollständig markiert"
|
||||
msgid "Medium Priority"
|
||||
msgstr "Mittlere Priorität"
|
||||
|
||||
#: src/components/SideNavigation.tsx:121
|
||||
#: src/components/SideNavigation.tsx:101
|
||||
#: src/views/board/components/Filters.tsx:107
|
||||
#: src/views/board/components/NewCardForm.tsx:367
|
||||
#: src/views/card/index.tsx:128
|
||||
@@ -1433,15 +1411,11 @@ msgstr "hat die Karte in eine andere Liste verschoben"
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:54
|
||||
msgid "Navigation"
|
||||
msgstr "Navigation"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:95
|
||||
msgid "Need help?"
|
||||
msgstr "Brauchst du Hilfe?"
|
||||
|
||||
#: src/views/boards/index.tsx:62
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/home/components/Features.tsx:73
|
||||
msgid "New"
|
||||
msgstr "Neu"
|
||||
@@ -1472,7 +1446,7 @@ msgid "New label"
|
||||
msgstr "Neues Label"
|
||||
|
||||
#: src/views/board/components/NewListForm.tsx:113
|
||||
#: src/views/board/index.tsx:454
|
||||
#: src/views/board/index.tsx:442
|
||||
msgid "New list"
|
||||
msgstr "Neue Liste"
|
||||
|
||||
@@ -1525,11 +1499,7 @@ msgstr "Keine Kreditkarte erforderlich"
|
||||
msgid "No download URL available for this attachment."
|
||||
msgstr "Für diesen Anhang ist keine Download-URL verfügbar."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:333
|
||||
msgid "No keyboard shortcuts registered."
|
||||
msgstr "Keine Tastaturkürzel registriert."
|
||||
|
||||
#: src/views/board/index.tsx:480
|
||||
#: src/views/board/index.tsx:467
|
||||
msgid "No lists"
|
||||
msgstr "Keine Listen"
|
||||
|
||||
@@ -1553,14 +1523,6 @@ msgstr "Sobald Sie Ihr Konto löschen, gibt es kein Zurück mehr. Diese Aktion k
|
||||
msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
|
||||
msgstr "Sobald Sie Ihren Arbeitsbereich löschen, gibt es kein Zurück mehr. Diese Aktion kann nicht rückgängig gemacht werden."
|
||||
|
||||
#: src/components/WorkspaceMenu.tsx:31
|
||||
msgid "Open command menu"
|
||||
msgstr "Befehlsmenü öffnen"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:171
|
||||
msgid "Open keyboard shortcuts"
|
||||
msgstr "Tastaturkürzel öffnen"
|
||||
|
||||
#: src/views/pricing/components/FeatureComparisonTable.tsx:150
|
||||
msgid "Open source"
|
||||
msgstr "Open Source"
|
||||
@@ -1676,8 +1638,8 @@ msgstr "Bitte wähle eine Datei zum Hochladen aus."
|
||||
#: src/views/board/components/NewTemplateForm.tsx:77
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:73
|
||||
#: src/views/board/components/VisibilityButton.tsx:54
|
||||
#: src/views/board/index.tsx:162
|
||||
#: src/views/board/index.tsx:218
|
||||
#: src/views/board/index.tsx:151
|
||||
#: src/views/board/index.tsx:207
|
||||
#: src/views/boards/components/ImportBoardsForm.tsx:205
|
||||
#: src/views/card/components/AttachmentThumbnails.tsx:73
|
||||
#: src/views/card/components/ChecklistItemRow.tsx:60
|
||||
@@ -1910,7 +1872,7 @@ msgid "Senior"
|
||||
msgstr "Senior"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:82
|
||||
#: src/components/SideNavigation.tsx:133
|
||||
#: src/components/SideNavigation.tsx:106
|
||||
msgid "Settings"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
@@ -1934,10 +1896,6 @@ msgstr "Einstellungen | Integrationen"
|
||||
msgid "Settings | Workspace"
|
||||
msgstr "Einstellungen | Arbeitsbereich"
|
||||
|
||||
#: src/components/UserMenu.tsx:184
|
||||
msgid "Shortcuts"
|
||||
msgstr "Kürzel"
|
||||
|
||||
#: src/views/home/components/Header.tsx:104
|
||||
msgid "Sign in"
|
||||
msgstr "Anmelden"
|
||||
@@ -2006,7 +1964,7 @@ msgstr "Erfolg"
|
||||
msgid "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
msgstr "Optimiere deinen Workspace für nur $29/Monat. Das bekommst du dafür:"
|
||||
|
||||
#: src/components/UserMenu.tsx:195
|
||||
#: src/components/UserMenu.tsx:180
|
||||
msgid "Support"
|
||||
msgstr "Support"
|
||||
|
||||
@@ -2015,7 +1973,7 @@ msgstr "Support"
|
||||
msgid "Support the development of the project"
|
||||
msgstr "Unterstütze die Entwicklung des Projekts"
|
||||
|
||||
#: src/components/UserMenu.tsx:141
|
||||
#: src/components/UserMenu.tsx:139
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
@@ -2030,8 +1988,8 @@ msgstr "Team-Plan"
|
||||
msgid "Teams"
|
||||
msgstr "Teams"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:409
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/board/index.tsx:398
|
||||
msgid "Template"
|
||||
msgstr "Vorlage"
|
||||
|
||||
@@ -2051,7 +2009,7 @@ msgstr "Vorlagenname darf 100 Zeichen nicht überschreiten"
|
||||
msgid "Template name is required"
|
||||
msgstr "Vorlagenname ist erforderlich"
|
||||
|
||||
#: src/components/SideNavigation.tsx:109
|
||||
#: src/components/SideNavigation.tsx:96
|
||||
#: src/views/home/components/Features.tsx:115
|
||||
msgid "Templates"
|
||||
msgstr "Vorlagen"
|
||||
@@ -2085,7 +2043,7 @@ msgstr "Die open source <0/> alternative zu Trello"
|
||||
msgid "The visibility of your board has been set to {0}."
|
||||
msgstr "Die Sichtbarkeit deines Boards wurde auf {0} gesetzt."
|
||||
|
||||
#: src/components/UserMenu.tsx:128
|
||||
#: src/components/UserMenu.tsx:126
|
||||
msgid "Theme"
|
||||
msgstr "Design"
|
||||
|
||||
@@ -2236,7 +2194,7 @@ msgstr "Board-URL kann nicht aktualisiert werden"
|
||||
msgid "Unable to update board visibility"
|
||||
msgstr "Board-Sichtbarkeit konnte nicht aktualisiert werden"
|
||||
|
||||
#: src/views/board/index.tsx:217
|
||||
#: src/views/board/index.tsx:206
|
||||
#: src/views/card/index.tsx:176
|
||||
msgid "Unable to update card"
|
||||
msgstr "Karte konnte nicht aktualisiert werden"
|
||||
@@ -2257,7 +2215,7 @@ msgstr "Kommentar konnte nicht aktualisiert werden"
|
||||
msgid "Unable to update labels"
|
||||
msgstr "Labels konnten nicht aktualisiert werden"
|
||||
|
||||
#: src/views/board/index.tsx:161
|
||||
#: src/views/board/index.tsx:150
|
||||
#: src/views/card/components/ListSelector.tsx:51
|
||||
msgid "Unable to update list"
|
||||
msgstr "Liste konnte nicht aktualisiert werden"
|
||||
@@ -2313,6 +2271,11 @@ msgstr "Unbegrenzte Mitglieder"
|
||||
msgid "Unlimited workspaces"
|
||||
msgstr "Unbegrenzte Workspaces"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:68
|
||||
#: src/pages/unsubscribe/index.tsx:93
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Abmelden"
|
||||
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:175
|
||||
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
|
||||
@@ -2342,7 +2305,7 @@ msgstr "hat den Titel aktualisiert"
|
||||
msgid "updated the title to <0>{0}</0>"
|
||||
msgstr "hat den Titel in <0>{0}</0> geändert"
|
||||
|
||||
#: src/components/SideNavigation.tsx:237
|
||||
#: src/components/SideNavigation.tsx:202
|
||||
#: src/views/settings/components/UpgradeToProConfirmation.tsx:53
|
||||
#: src/views/settings/WorkspaceSettings.tsx:90
|
||||
msgid "Upgrade to Pro"
|
||||
@@ -2426,6 +2389,10 @@ msgstr "Sichtbarkeit"
|
||||
msgid "We are using the <0>AGPL-3.0 license</0>."
|
||||
msgstr "Wir verwenden die <0>AGPL-3.0 lizenz</0>."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:63
|
||||
msgid "We couldn't update your preferences. Please try again."
|
||||
msgstr "Wir konnten ihre einstellungen nicht aktualisieren. Bitte versuchen sie es erneut."
|
||||
|
||||
#: src/views/home/components/Features.tsx:152
|
||||
msgid "We're just getting started. "
|
||||
msgstr "Wir stehen erst am anfang. "
|
||||
@@ -2455,8 +2422,8 @@ msgid "Why make an open source Trello?"
|
||||
msgstr "Warum ein open source Trello entwickeln?"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:39
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/members/index.tsx:173
|
||||
#: src/views/public/board/index.tsx:101
|
||||
#: src/views/public/boards/index.tsx:66
|
||||
@@ -2564,6 +2531,10 @@ msgstr "Sie haben sich erfolgreich angemeldet."
|
||||
msgid "You have been signed up successfully."
|
||||
msgstr "Sie haben sich erfolgreich registriert."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:98
|
||||
msgid "You have been unsubscribed!"
|
||||
msgstr "Sie wurden abgemeldet!"
|
||||
|
||||
#: src/views/members/components/InviteMemberForm.tsx:326
|
||||
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
msgstr "Sie haben unbegrenzte Plätze mit Ihrem Pro-Plan. Für neue Mitglieder fallen keine zusätzlichen Kosten an!"
|
||||
@@ -2608,6 +2579,10 @@ msgstr "Dein Trello-Konto wurde getrennt."
|
||||
msgid "Your Trello account is connected."
|
||||
msgstr "Dein Trello-Konto ist verbunden."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:33
|
||||
msgid "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
msgstr "Ihrem abmeldelink fehlt ein token. Bitte öffnen sie die neueste e-mail und versuchen sie es erneut."
|
||||
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
|
||||
msgid "Your workspace description has been updated."
|
||||
msgstr "Deine Workspace-Beschreibung wurde aktualisiert."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,7 +22,7 @@ msgid ", or see our"
|
||||
msgstr ", or see our"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#: src/views/boards/index.tsx:38
|
||||
#: src/views/boards/index.tsx:27
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
|
||||
@@ -30,7 +30,7 @@ msgstr "{0}"
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#. placeholder {1}: board?.name ?? t`Board`
|
||||
#. placeholder {1}: workspace.name ?? t`Workspace`
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/card/index.tsx:229
|
||||
msgid "{0} | {1}"
|
||||
msgstr "{0} | {1}"
|
||||
@@ -41,7 +41,7 @@ msgid "{0} labels"
|
||||
msgstr "{0} labels"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Template" : "Board"
|
||||
#: src/views/board/index.tsx:400
|
||||
#: src/views/board/index.tsx:389
|
||||
msgid "{0} not found"
|
||||
msgstr "{0} not found"
|
||||
|
||||
@@ -92,8 +92,8 @@ msgid "Account deleted"
|
||||
msgstr "Account deleted"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:55
|
||||
msgid "Actions"
|
||||
msgstr "Actions"
|
||||
#~ msgid "Actions"
|
||||
#~ msgstr "Actions"
|
||||
|
||||
#: src/views/card/index.tsx:343
|
||||
#: src/views/public/board/CardModal.tsx:157
|
||||
@@ -352,7 +352,7 @@ msgstr "Billing portal"
|
||||
msgid "Blog Post"
|
||||
msgstr "Blog Post"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/card/index.tsx:229
|
||||
#: src/views/public/board/index.tsx:101
|
||||
msgid "Board"
|
||||
@@ -413,7 +413,7 @@ msgstr "Board visibility"
|
||||
msgid "Board visibility updated"
|
||||
msgstr "Board visibility updated"
|
||||
|
||||
#: src/components/SideNavigation.tsx:97
|
||||
#: src/components/SideNavigation.tsx:91
|
||||
msgid "Boards"
|
||||
msgstr "Boards"
|
||||
|
||||
@@ -563,6 +563,10 @@ msgstr "completed checklist item <0>{0}</0>"
|
||||
#~ msgid "Confirm URL change"
|
||||
#~ msgstr "Confirm URL change"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:81
|
||||
msgid "Confirm your email preferences:"
|
||||
msgstr "Confirm your email preferences:"
|
||||
|
||||
#: src/views/settings/components/ChangePasswordConfirmation.tsx:150
|
||||
msgid "Confirm your new password"
|
||||
msgstr "Confirm your new password"
|
||||
@@ -655,7 +659,6 @@ msgstr "Create list"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "template" : "board"
|
||||
#: src/views/boards/components/BoardsList.tsx:45
|
||||
#: src/views/boards/index.tsx:26
|
||||
msgid "Create new {0}"
|
||||
msgstr "Create new {0}"
|
||||
|
||||
@@ -672,8 +675,7 @@ msgstr "Create new key"
|
||||
msgid "Create new label"
|
||||
msgstr "Create new label"
|
||||
|
||||
#: src/views/board/index.tsx:64
|
||||
#: src/views/board/index.tsx:491
|
||||
#: src/views/board/index.tsx:478
|
||||
msgid "Create new list"
|
||||
msgstr "Create new list"
|
||||
|
||||
@@ -686,7 +688,7 @@ msgid "Create template"
|
||||
msgstr "Create template"
|
||||
|
||||
#: src/components/NewWorkspaceForm.tsx:387
|
||||
#: src/components/WorkspaceMenu.tsx:153
|
||||
#: src/components/WorkspaceMenu.tsx:149
|
||||
msgid "Create workspace"
|
||||
msgstr "Create workspace"
|
||||
|
||||
@@ -744,7 +746,7 @@ msgstr "Custom workspace URL"
|
||||
msgid "Customer Support"
|
||||
msgstr "Customer Support"
|
||||
|
||||
#: src/components/UserMenu.tsx:155
|
||||
#: src/components/UserMenu.tsx:153
|
||||
msgid "Dark"
|
||||
msgstr "Dark"
|
||||
|
||||
@@ -843,6 +845,10 @@ msgstr "Display name updated"
|
||||
msgid "Do you offer a free plan?"
|
||||
msgstr "Do you offer a free plan?"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:78
|
||||
msgid "Do you want to unsubscribe?"
|
||||
msgstr "Do you want to unsubscribe?"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:109
|
||||
msgid "docs"
|
||||
msgstr "docs"
|
||||
@@ -851,7 +857,7 @@ msgstr "docs"
|
||||
msgid "Docs"
|
||||
msgstr "Docs"
|
||||
|
||||
#: src/components/UserMenu.tsx:206
|
||||
#: src/components/UserMenu.tsx:191
|
||||
#: src/views/boards/components/TemplateBoards.tsx:24
|
||||
#: src/views/home/components/Footer.tsx:78
|
||||
#: src/views/home/components/Header.tsx:36
|
||||
@@ -1075,7 +1081,7 @@ msgid "Features"
|
||||
msgstr "Features"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:59
|
||||
#: src/components/UserMenu.tsx:214
|
||||
#: src/components/UserMenu.tsx:199
|
||||
msgid "Feedback"
|
||||
msgstr "Feedback"
|
||||
|
||||
@@ -1129,8 +1135,8 @@ msgid "Fun"
|
||||
msgstr "Fun"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:53
|
||||
msgid "General"
|
||||
msgstr "General"
|
||||
#~ msgid "General"
|
||||
#~ msgstr "General"
|
||||
|
||||
#: src/views/auth/signup/index.tsx:69
|
||||
#: src/views/home/components/Cta.tsx:61
|
||||
@@ -1155,7 +1161,7 @@ msgstr "Get started by creating a new {0}"
|
||||
#~ msgid "Get started by creating a new board"
|
||||
#~ msgstr "Get started by creating a new board"
|
||||
|
||||
#: src/views/board/index.tsx:483
|
||||
#: src/views/board/index.tsx:470
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Get started by creating a new list"
|
||||
|
||||
@@ -1190,20 +1196,20 @@ msgid "Go to app"
|
||||
msgstr "Go to app"
|
||||
|
||||
#: src/components/SideNavigation.tsx:105
|
||||
msgid "Go to boards"
|
||||
msgstr "Go to boards"
|
||||
#~ msgid "Go to boards"
|
||||
#~ msgstr "Go to boards"
|
||||
|
||||
#: src/components/SideNavigation.tsx:129
|
||||
msgid "Go to members"
|
||||
msgstr "Go to members"
|
||||
#~ msgid "Go to members"
|
||||
#~ msgstr "Go to members"
|
||||
|
||||
#: src/components/SideNavigation.tsx:141
|
||||
msgid "Go to settings"
|
||||
msgstr "Go to settings"
|
||||
#~ msgid "Go to settings"
|
||||
#~ msgstr "Go to settings"
|
||||
|
||||
#: src/components/SideNavigation.tsx:117
|
||||
msgid "Go to templates"
|
||||
msgstr "Go to templates"
|
||||
#~ msgid "Go to templates"
|
||||
#~ msgstr "Go to templates"
|
||||
|
||||
#: src/views/boards/components/TemplateBoards.tsx:18
|
||||
msgid "High Priority"
|
||||
@@ -1258,7 +1264,7 @@ msgstr "Ideas to improve this page..."
|
||||
#~ msgid "Ideas, Research, Planning, Execution, Review, Next Steps, Complete"
|
||||
#~ msgstr "Ideas, Research, Planning, Execution, Review, Next Steps, Complete"
|
||||
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/boards/index.tsx:39
|
||||
msgid "Import"
|
||||
msgstr "Import"
|
||||
|
||||
@@ -1394,8 +1400,8 @@ msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Keep in mind that this action is irreversible."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:320
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Keyboard Shortcuts"
|
||||
#~ msgid "Keyboard Shortcuts"
|
||||
#~ msgstr "Keyboard Shortcuts"
|
||||
|
||||
#: src/views/board/components/Filters.tsx:115
|
||||
#: src/views/board/components/NewCardForm.tsx:409
|
||||
@@ -1445,7 +1451,7 @@ msgstr "Legal"
|
||||
msgid "License"
|
||||
msgstr "License"
|
||||
|
||||
#: src/components/UserMenu.tsx:169
|
||||
#: src/components/UserMenu.tsx:167
|
||||
msgid "Light"
|
||||
msgstr "Light"
|
||||
|
||||
@@ -1469,7 +1475,7 @@ msgstr "Lists"
|
||||
msgid "Login | kan.bn"
|
||||
msgstr "Login | kan.bn"
|
||||
|
||||
#: src/components/UserMenu.tsx:224
|
||||
#: src/components/UserMenu.tsx:209
|
||||
msgid "Logout"
|
||||
msgstr "Logout"
|
||||
|
||||
@@ -1506,7 +1512,7 @@ msgstr "marked checklist item <0>{0}</0> as incomplete"
|
||||
msgid "Medium Priority"
|
||||
msgstr "Medium Priority"
|
||||
|
||||
#: src/components/SideNavigation.tsx:121
|
||||
#: src/components/SideNavigation.tsx:101
|
||||
#: src/views/board/components/Filters.tsx:107
|
||||
#: src/views/board/components/NewCardForm.tsx:367
|
||||
#: src/views/card/index.tsx:128
|
||||
@@ -1553,14 +1559,14 @@ msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:54
|
||||
msgid "Navigation"
|
||||
msgstr "Navigation"
|
||||
#~ msgid "Navigation"
|
||||
#~ msgstr "Navigation"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:95
|
||||
msgid "Need help?"
|
||||
msgstr "Need help?"
|
||||
|
||||
#: src/views/boards/index.tsx:62
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/home/components/Features.tsx:73
|
||||
msgid "New"
|
||||
msgstr "New"
|
||||
@@ -1595,7 +1601,7 @@ msgid "New label"
|
||||
msgstr "New label"
|
||||
|
||||
#: src/views/board/components/NewListForm.tsx:113
|
||||
#: src/views/board/index.tsx:454
|
||||
#: src/views/board/index.tsx:442
|
||||
msgid "New list"
|
||||
msgstr "New list"
|
||||
|
||||
@@ -1657,10 +1663,10 @@ msgid "No download URL available for this attachment."
|
||||
msgstr "No download URL available for this attachment."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:333
|
||||
msgid "No keyboard shortcuts registered."
|
||||
msgstr "No keyboard shortcuts registered."
|
||||
#~ msgid "No keyboard shortcuts registered."
|
||||
#~ msgstr "No keyboard shortcuts registered."
|
||||
|
||||
#: src/views/board/index.tsx:480
|
||||
#: src/views/board/index.tsx:467
|
||||
msgid "No lists"
|
||||
msgstr "No lists"
|
||||
|
||||
@@ -1685,12 +1691,12 @@ msgid "Once you delete your workspace, there is no going back. This action canno
|
||||
msgstr "Once you delete your workspace, there is no going back. This action cannot be undone."
|
||||
|
||||
#: src/components/WorkspaceMenu.tsx:31
|
||||
msgid "Open command menu"
|
||||
msgstr "Open command menu"
|
||||
#~ msgid "Open command menu"
|
||||
#~ msgstr "Open command menu"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:171
|
||||
msgid "Open keyboard shortcuts"
|
||||
msgstr "Open keyboard shortcuts"
|
||||
#~ msgid "Open keyboard shortcuts"
|
||||
#~ msgstr "Open keyboard shortcuts"
|
||||
|
||||
#: src/views/pricing/components/FeatureComparisonTable.tsx:150
|
||||
msgid "Open source"
|
||||
@@ -1807,8 +1813,8 @@ msgstr "Please select a file to upload."
|
||||
#: src/views/board/components/NewTemplateForm.tsx:77
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:73
|
||||
#: src/views/board/components/VisibilityButton.tsx:54
|
||||
#: src/views/board/index.tsx:162
|
||||
#: src/views/board/index.tsx:218
|
||||
#: src/views/board/index.tsx:151
|
||||
#: src/views/board/index.tsx:207
|
||||
#: src/views/boards/components/ImportBoardsForm.tsx:205
|
||||
#: src/views/card/components/AttachmentThumbnails.tsx:73
|
||||
#: src/views/card/components/ChecklistItemRow.tsx:60
|
||||
@@ -2053,7 +2059,7 @@ msgid "Senior"
|
||||
msgstr "Senior"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:82
|
||||
#: src/components/SideNavigation.tsx:133
|
||||
#: src/components/SideNavigation.tsx:106
|
||||
msgid "Settings"
|
||||
msgstr "Settings"
|
||||
|
||||
@@ -2086,8 +2092,8 @@ msgstr "Settings | Workspace"
|
||||
#~ msgstr "Share invite link"
|
||||
|
||||
#: src/components/UserMenu.tsx:184
|
||||
msgid "Shortcuts"
|
||||
msgstr "Shortcuts"
|
||||
#~ msgid "Shortcuts"
|
||||
#~ msgstr "Shortcuts"
|
||||
|
||||
#: src/views/home/components/Header.tsx:104
|
||||
msgid "Sign in"
|
||||
@@ -2157,7 +2163,7 @@ msgstr "Success"
|
||||
msgid "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
msgstr "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
|
||||
#: src/components/UserMenu.tsx:195
|
||||
#: src/components/UserMenu.tsx:180
|
||||
msgid "Support"
|
||||
msgstr "Support"
|
||||
|
||||
@@ -2166,7 +2172,7 @@ msgstr "Support"
|
||||
msgid "Support the development of the project"
|
||||
msgstr "Support the development of the project"
|
||||
|
||||
#: src/components/UserMenu.tsx:141
|
||||
#: src/components/UserMenu.tsx:139
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
@@ -2181,8 +2187,8 @@ msgstr "Team Plan"
|
||||
msgid "Teams"
|
||||
msgstr "Teams"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:409
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/board/index.tsx:398
|
||||
msgid "Template"
|
||||
msgstr "Template"
|
||||
|
||||
@@ -2202,7 +2208,7 @@ msgstr "Template name cannot exceed 100 characters"
|
||||
msgid "Template name is required"
|
||||
msgstr "Template name is required"
|
||||
|
||||
#: src/components/SideNavigation.tsx:109
|
||||
#: src/components/SideNavigation.tsx:96
|
||||
#: src/views/home/components/Features.tsx:115
|
||||
msgid "Templates"
|
||||
msgstr "Templates"
|
||||
@@ -2236,7 +2242,7 @@ msgstr "The open source <0/> alternative to Trello"
|
||||
msgid "The visibility of your board has been set to {0}."
|
||||
msgstr "The visibility of your board has been set to {0}."
|
||||
|
||||
#: src/components/UserMenu.tsx:128
|
||||
#: src/components/UserMenu.tsx:126
|
||||
msgid "Theme"
|
||||
msgstr "Theme"
|
||||
|
||||
@@ -2395,7 +2401,7 @@ msgstr "Unable to update board URL"
|
||||
msgid "Unable to update board visibility"
|
||||
msgstr "Unable to update board visibility"
|
||||
|
||||
#: src/views/board/index.tsx:217
|
||||
#: src/views/board/index.tsx:206
|
||||
#: src/views/card/index.tsx:176
|
||||
msgid "Unable to update card"
|
||||
msgstr "Unable to update card"
|
||||
@@ -2416,7 +2422,7 @@ msgstr "Unable to update comment"
|
||||
msgid "Unable to update labels"
|
||||
msgstr "Unable to update labels"
|
||||
|
||||
#: src/views/board/index.tsx:161
|
||||
#: src/views/board/index.tsx:150
|
||||
#: src/views/card/components/ListSelector.tsx:51
|
||||
msgid "Unable to update list"
|
||||
msgstr "Unable to update list"
|
||||
@@ -2476,6 +2482,11 @@ msgstr "Unlimited members"
|
||||
msgid "Unlimited workspaces"
|
||||
msgstr "Unlimited workspaces"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:68
|
||||
#: src/pages/unsubscribe/index.tsx:93
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Unsubscribe"
|
||||
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:175
|
||||
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
|
||||
@@ -2513,7 +2524,7 @@ msgstr "updated the title to <0>{0}</0>"
|
||||
#~ msgid "Upgrade"
|
||||
#~ msgstr "Upgrade"
|
||||
|
||||
#: src/components/SideNavigation.tsx:237
|
||||
#: src/components/SideNavigation.tsx:202
|
||||
#: src/views/settings/components/UpgradeToProConfirmation.tsx:53
|
||||
#: src/views/settings/WorkspaceSettings.tsx:90
|
||||
msgid "Upgrade to Pro"
|
||||
@@ -2601,6 +2612,10 @@ msgstr "Visibility"
|
||||
msgid "We are using the <0>AGPL-3.0 license</0>."
|
||||
msgstr "We are using the <0>AGPL-3.0 license</0>."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:63
|
||||
msgid "We couldn't update your preferences. Please try again."
|
||||
msgstr "We couldn't update your preferences. Please try again."
|
||||
|
||||
#: src/views/home/components/Features.tsx:152
|
||||
msgid "We're just getting started. "
|
||||
msgstr "We're just getting started. "
|
||||
@@ -2638,8 +2653,8 @@ msgid "Why make an open source Trello?"
|
||||
msgstr "Why make an open source Trello?"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:39
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/members/index.tsx:173
|
||||
#: src/views/public/board/index.tsx:101
|
||||
#: src/views/public/boards/index.tsx:66
|
||||
@@ -2751,6 +2766,10 @@ msgstr "You have been logged in successfully."
|
||||
msgid "You have been signed up successfully."
|
||||
msgstr "You have been signed up successfully."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:98
|
||||
msgid "You have been unsubscribed!"
|
||||
msgstr "You have been unsubscribed!"
|
||||
|
||||
#: src/views/members/components/InviteMemberForm.tsx:326
|
||||
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
msgstr "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
@@ -2795,6 +2814,10 @@ msgstr "Your Trello account has been disconnected."
|
||||
msgid "Your Trello account is connected."
|
||||
msgstr "Your Trello account is connected."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:33
|
||||
msgid "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
msgstr "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
|
||||
msgid "Your workspace description has been updated."
|
||||
msgstr "Your workspace description has been updated."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,7 +22,7 @@ msgid ", or see our"
|
||||
msgstr ", o consulta nuestra"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#: src/views/boards/index.tsx:38
|
||||
#: src/views/boards/index.tsx:27
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
|
||||
@@ -30,7 +30,7 @@ msgstr "{0}"
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#. placeholder {1}: board?.name ?? t`Board`
|
||||
#. placeholder {1}: workspace.name ?? t`Workspace`
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/card/index.tsx:229
|
||||
msgid "{0} | {1}"
|
||||
msgstr "{0} | {1}"
|
||||
@@ -41,7 +41,7 @@ msgid "{0} labels"
|
||||
msgstr "{0} etiquetas"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Template" : "Board"
|
||||
#: src/views/board/index.tsx:400
|
||||
#: src/views/board/index.tsx:389
|
||||
msgid "{0} not found"
|
||||
msgstr "{0} no encontrado"
|
||||
|
||||
@@ -79,10 +79,6 @@ msgstr "Cuenta"
|
||||
msgid "Account deleted"
|
||||
msgstr "Cuenta eliminada"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:55
|
||||
msgid "Actions"
|
||||
msgstr "Acciones"
|
||||
|
||||
#: src/views/card/index.tsx:343
|
||||
#: src/views/public/board/CardModal.tsx:157
|
||||
msgid "Activity"
|
||||
@@ -312,7 +308,7 @@ msgstr "Portal de facturación"
|
||||
msgid "Blog Post"
|
||||
msgstr "Entrada de blog"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/card/index.tsx:229
|
||||
#: src/views/public/board/index.tsx:101
|
||||
msgid "Board"
|
||||
@@ -364,7 +360,7 @@ msgstr "Visibilidad del tablero"
|
||||
msgid "Board visibility updated"
|
||||
msgstr "Visibilidad del tablero actualizada"
|
||||
|
||||
#: src/components/SideNavigation.tsx:97
|
||||
#: src/components/SideNavigation.tsx:91
|
||||
msgid "Boards"
|
||||
msgstr "Tableros"
|
||||
|
||||
@@ -498,6 +494,10 @@ msgstr "completó un elemento de la lista de verificación"
|
||||
msgid "completed checklist item <0>{0}</0>"
|
||||
msgstr "completó el elemento <0>{0}</0> de la lista de verificación"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:81
|
||||
msgid "Confirm your email preferences:"
|
||||
msgstr "Confirma tus preferencias de correo electrónico:"
|
||||
|
||||
#: src/views/settings/components/ChangePasswordConfirmation.tsx:150
|
||||
msgid "Confirm your new password"
|
||||
msgstr "Confirma tu nueva contraseña"
|
||||
@@ -582,7 +582,6 @@ msgstr "Crear lista"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "template" : "board"
|
||||
#: src/views/boards/components/BoardsList.tsx:45
|
||||
#: src/views/boards/index.tsx:26
|
||||
msgid "Create new {0}"
|
||||
msgstr "Crear nuevo {0}"
|
||||
|
||||
@@ -595,8 +594,7 @@ msgstr "Crear nueva clave"
|
||||
msgid "Create new label"
|
||||
msgstr "Crear nueva etiqueta"
|
||||
|
||||
#: src/views/board/index.tsx:64
|
||||
#: src/views/board/index.tsx:491
|
||||
#: src/views/board/index.tsx:478
|
||||
msgid "Create new list"
|
||||
msgstr "Crear nueva lista"
|
||||
|
||||
@@ -605,7 +603,7 @@ msgid "Create template"
|
||||
msgstr "Crear plantilla"
|
||||
|
||||
#: src/components/NewWorkspaceForm.tsx:387
|
||||
#: src/components/WorkspaceMenu.tsx:153
|
||||
#: src/components/WorkspaceMenu.tsx:149
|
||||
msgid "Create workspace"
|
||||
msgstr "Crear espacio de trabajo"
|
||||
|
||||
@@ -655,7 +653,7 @@ msgstr "URL personalizada del espacio de trabajo"
|
||||
msgid "Customer Support"
|
||||
msgstr "Atención al cliente"
|
||||
|
||||
#: src/components/UserMenu.tsx:155
|
||||
#: src/components/UserMenu.tsx:153
|
||||
msgid "Dark"
|
||||
msgstr "Oscuro"
|
||||
|
||||
@@ -754,6 +752,10 @@ msgstr "Nombre visible actualizado"
|
||||
msgid "Do you offer a free plan?"
|
||||
msgstr "¿Ofrecen un plan gratuito?"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:78
|
||||
msgid "Do you want to unsubscribe?"
|
||||
msgstr "¿Quieres darte de baja?"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:109
|
||||
msgid "docs"
|
||||
msgstr "documentos"
|
||||
@@ -762,7 +764,7 @@ msgstr "documentos"
|
||||
msgid "Docs"
|
||||
msgstr "Documentos"
|
||||
|
||||
#: src/components/UserMenu.tsx:206
|
||||
#: src/components/UserMenu.tsx:191
|
||||
#: src/views/boards/components/TemplateBoards.tsx:24
|
||||
#: src/views/home/components/Footer.tsx:78
|
||||
#: src/views/home/components/Header.tsx:36
|
||||
@@ -986,7 +988,7 @@ msgid "Features"
|
||||
msgstr "Características"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:59
|
||||
#: src/components/UserMenu.tsx:214
|
||||
#: src/components/UserMenu.tsx:199
|
||||
msgid "Feedback"
|
||||
msgstr "Comentarios"
|
||||
|
||||
@@ -1029,10 +1031,6 @@ msgstr "Tiempo completo"
|
||||
msgid "Fun"
|
||||
msgstr "Diversión"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:53
|
||||
msgid "General"
|
||||
msgstr "General"
|
||||
|
||||
#: src/views/auth/signup/index.tsx:69
|
||||
#: src/views/home/components/Cta.tsx:61
|
||||
#: src/views/home/components/Header.tsx:106
|
||||
@@ -1052,7 +1050,7 @@ msgstr "Comenzar"
|
||||
msgid "Get started by creating a new {0}"
|
||||
msgstr "Comienza creando un nuevo {0}"
|
||||
|
||||
#: src/views/board/index.tsx:483
|
||||
#: src/views/board/index.tsx:470
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Comienza creando una nueva lista"
|
||||
|
||||
@@ -1086,22 +1084,6 @@ msgstr "Ir a inicio"
|
||||
msgid "Go to app"
|
||||
msgstr "Ir a la aplicación"
|
||||
|
||||
#: src/components/SideNavigation.tsx:105
|
||||
msgid "Go to boards"
|
||||
msgstr "Ir a tableros"
|
||||
|
||||
#: src/components/SideNavigation.tsx:129
|
||||
msgid "Go to members"
|
||||
msgstr "Ir a miembros"
|
||||
|
||||
#: src/components/SideNavigation.tsx:141
|
||||
msgid "Go to settings"
|
||||
msgstr "Ir a configuración"
|
||||
|
||||
#: src/components/SideNavigation.tsx:117
|
||||
msgid "Go to templates"
|
||||
msgstr "Ir a plantillas"
|
||||
|
||||
#: src/views/boards/components/TemplateBoards.tsx:18
|
||||
msgid "High Priority"
|
||||
msgstr "Alta prioridad"
|
||||
@@ -1151,7 +1133,7 @@ msgstr "Ideas"
|
||||
msgid "Ideas to improve this page..."
|
||||
msgstr "Ideas para mejorar esta página..."
|
||||
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/boards/index.tsx:39
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
@@ -1282,10 +1264,6 @@ msgstr "Kanban reinventado"
|
||||
msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Ten en cuenta que esta acción es irreversible."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:320
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Atajos de teclado"
|
||||
|
||||
#: src/views/board/components/Filters.tsx:115
|
||||
#: src/views/board/components/NewCardForm.tsx:409
|
||||
#: src/views/card/index.tsx:119
|
||||
@@ -1334,7 +1312,7 @@ msgstr "Legal"
|
||||
msgid "License"
|
||||
msgstr "Licencia"
|
||||
|
||||
#: src/components/UserMenu.tsx:169
|
||||
#: src/components/UserMenu.tsx:167
|
||||
msgid "Light"
|
||||
msgstr "Claro"
|
||||
|
||||
@@ -1358,7 +1336,7 @@ msgstr "Listas"
|
||||
msgid "Login | kan.bn"
|
||||
msgstr "Iniciar sesión | kan.bn"
|
||||
|
||||
#: src/components/UserMenu.tsx:224
|
||||
#: src/components/UserMenu.tsx:209
|
||||
msgid "Logout"
|
||||
msgstr "Cerrar sesión"
|
||||
|
||||
@@ -1395,7 +1373,7 @@ msgstr "marcó el elemento <0>{0}</0> de la lista de verificación como incomple
|
||||
msgid "Medium Priority"
|
||||
msgstr "Prioridad media"
|
||||
|
||||
#: src/components/SideNavigation.tsx:121
|
||||
#: src/components/SideNavigation.tsx:101
|
||||
#: src/views/board/components/Filters.tsx:107
|
||||
#: src/views/board/components/NewCardForm.tsx:367
|
||||
#: src/views/card/index.tsx:128
|
||||
@@ -1433,15 +1411,11 @@ msgstr "movió la tarjeta a otra lista"
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:54
|
||||
msgid "Navigation"
|
||||
msgstr "Navegación"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:95
|
||||
msgid "Need help?"
|
||||
msgstr "¿Necesitas ayuda?"
|
||||
|
||||
#: src/views/boards/index.tsx:62
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/home/components/Features.tsx:73
|
||||
msgid "New"
|
||||
msgstr "Nuevo"
|
||||
@@ -1472,7 +1446,7 @@ msgid "New label"
|
||||
msgstr "Nueva etiqueta"
|
||||
|
||||
#: src/views/board/components/NewListForm.tsx:113
|
||||
#: src/views/board/index.tsx:454
|
||||
#: src/views/board/index.tsx:442
|
||||
msgid "New list"
|
||||
msgstr "Nueva lista"
|
||||
|
||||
@@ -1525,11 +1499,7 @@ msgstr "No se requiere tarjeta de crédito"
|
||||
msgid "No download URL available for this attachment."
|
||||
msgstr "No hay URL de descarga disponible para este archivo adjunto."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:333
|
||||
msgid "No keyboard shortcuts registered."
|
||||
msgstr "No hay atajos de teclado registrados."
|
||||
|
||||
#: src/views/board/index.tsx:480
|
||||
#: src/views/board/index.tsx:467
|
||||
msgid "No lists"
|
||||
msgstr "Sin listas"
|
||||
|
||||
@@ -1553,14 +1523,6 @@ msgstr "Una vez que elimines tu cuenta, no hay vuelta atrás. Esta acción no se
|
||||
msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
|
||||
msgstr "Una vez que elimines tu espacio de trabajo, no hay vuelta atrás. Esta acción no se puede deshacer."
|
||||
|
||||
#: src/components/WorkspaceMenu.tsx:31
|
||||
msgid "Open command menu"
|
||||
msgstr "Abrir menú de comandos"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:171
|
||||
msgid "Open keyboard shortcuts"
|
||||
msgstr "Abrir atajos de teclado"
|
||||
|
||||
#: src/views/pricing/components/FeatureComparisonTable.tsx:150
|
||||
msgid "Open source"
|
||||
msgstr "Código abierto"
|
||||
@@ -1676,8 +1638,8 @@ msgstr "Por favor selecciona un archivo para subir."
|
||||
#: src/views/board/components/NewTemplateForm.tsx:77
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:73
|
||||
#: src/views/board/components/VisibilityButton.tsx:54
|
||||
#: src/views/board/index.tsx:162
|
||||
#: src/views/board/index.tsx:218
|
||||
#: src/views/board/index.tsx:151
|
||||
#: src/views/board/index.tsx:207
|
||||
#: src/views/boards/components/ImportBoardsForm.tsx:205
|
||||
#: src/views/card/components/AttachmentThumbnails.tsx:73
|
||||
#: src/views/card/components/ChecklistItemRow.tsx:60
|
||||
@@ -1910,7 +1872,7 @@ msgid "Senior"
|
||||
msgstr "Senior"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:82
|
||||
#: src/components/SideNavigation.tsx:133
|
||||
#: src/components/SideNavigation.tsx:106
|
||||
msgid "Settings"
|
||||
msgstr "Configuración"
|
||||
|
||||
@@ -1934,10 +1896,6 @@ msgstr "Configuración | Integraciones"
|
||||
msgid "Settings | Workspace"
|
||||
msgstr "Configuración | Espacio de trabajo"
|
||||
|
||||
#: src/components/UserMenu.tsx:184
|
||||
msgid "Shortcuts"
|
||||
msgstr "Atajos"
|
||||
|
||||
#: src/views/home/components/Header.tsx:104
|
||||
msgid "Sign in"
|
||||
msgstr "Iniciar sesión"
|
||||
@@ -2006,7 +1964,7 @@ msgstr "Éxito"
|
||||
msgid "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
msgstr "Potencia tu espacio de trabajo por solo $29/mes. Esto es lo que obtendrás:"
|
||||
|
||||
#: src/components/UserMenu.tsx:195
|
||||
#: src/components/UserMenu.tsx:180
|
||||
msgid "Support"
|
||||
msgstr "Soporte"
|
||||
|
||||
@@ -2015,7 +1973,7 @@ msgstr "Soporte"
|
||||
msgid "Support the development of the project"
|
||||
msgstr "Apoya el desarrollo del proyecto"
|
||||
|
||||
#: src/components/UserMenu.tsx:141
|
||||
#: src/components/UserMenu.tsx:139
|
||||
msgid "System"
|
||||
msgstr "Sistema"
|
||||
|
||||
@@ -2030,8 +1988,8 @@ msgstr "Plan de Equipo"
|
||||
msgid "Teams"
|
||||
msgstr "Equipos"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:409
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/board/index.tsx:398
|
||||
msgid "Template"
|
||||
msgstr "Plantilla"
|
||||
|
||||
@@ -2051,7 +2009,7 @@ msgstr "El nombre de la plantilla no puede exceder los 100 caracteres"
|
||||
msgid "Template name is required"
|
||||
msgstr "El nombre de la plantilla es obligatorio"
|
||||
|
||||
#: src/components/SideNavigation.tsx:109
|
||||
#: src/components/SideNavigation.tsx:96
|
||||
#: src/views/home/components/Features.tsx:115
|
||||
msgid "Templates"
|
||||
msgstr "Plantillas"
|
||||
@@ -2085,7 +2043,7 @@ msgstr "La alternativa de código abierto <0/> a Trello"
|
||||
msgid "The visibility of your board has been set to {0}."
|
||||
msgstr "La visibilidad de tu tablero ha sido establecida a {0}."
|
||||
|
||||
#: src/components/UserMenu.tsx:128
|
||||
#: src/components/UserMenu.tsx:126
|
||||
msgid "Theme"
|
||||
msgstr "Tema"
|
||||
|
||||
@@ -2236,7 +2194,7 @@ msgstr "No se puede actualizar la URL del tablero"
|
||||
msgid "Unable to update board visibility"
|
||||
msgstr "No se puede actualizar la visibilidad del tablero"
|
||||
|
||||
#: src/views/board/index.tsx:217
|
||||
#: src/views/board/index.tsx:206
|
||||
#: src/views/card/index.tsx:176
|
||||
msgid "Unable to update card"
|
||||
msgstr "No se puede actualizar la tarjeta"
|
||||
@@ -2257,7 +2215,7 @@ msgstr "No se puede actualizar el comentario"
|
||||
msgid "Unable to update labels"
|
||||
msgstr "No se pueden actualizar las etiquetas"
|
||||
|
||||
#: src/views/board/index.tsx:161
|
||||
#: src/views/board/index.tsx:150
|
||||
#: src/views/card/components/ListSelector.tsx:51
|
||||
msgid "Unable to update list"
|
||||
msgstr "No se puede actualizar la lista"
|
||||
@@ -2313,6 +2271,11 @@ msgstr "Miembros ilimitados"
|
||||
msgid "Unlimited workspaces"
|
||||
msgstr "Espacios de trabajo ilimitados"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:68
|
||||
#: src/pages/unsubscribe/index.tsx:93
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Darse de baja"
|
||||
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:175
|
||||
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
|
||||
@@ -2342,7 +2305,7 @@ msgstr "actualizó el título"
|
||||
msgid "updated the title to <0>{0}</0>"
|
||||
msgstr "actualizó el título a <0>{0}</0>"
|
||||
|
||||
#: src/components/SideNavigation.tsx:237
|
||||
#: src/components/SideNavigation.tsx:202
|
||||
#: src/views/settings/components/UpgradeToProConfirmation.tsx:53
|
||||
#: src/views/settings/WorkspaceSettings.tsx:90
|
||||
msgid "Upgrade to Pro"
|
||||
@@ -2426,6 +2389,10 @@ msgstr "Visibilidad"
|
||||
msgid "We are using the <0>AGPL-3.0 license</0>."
|
||||
msgstr "Estamos usando la <0>licencia AGPL-3.0</0>."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:63
|
||||
msgid "We couldn't update your preferences. Please try again."
|
||||
msgstr "No pudimos actualizar tus preferencias. Por favor, inténtalo de nuevo."
|
||||
|
||||
#: src/views/home/components/Features.tsx:152
|
||||
msgid "We're just getting started. "
|
||||
msgstr "Apenas estamos comenzando. "
|
||||
@@ -2455,8 +2422,8 @@ msgid "Why make an open source Trello?"
|
||||
msgstr "¿Por qué crear un Trello de código abierto?"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:39
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/members/index.tsx:173
|
||||
#: src/views/public/board/index.tsx:101
|
||||
#: src/views/public/boards/index.tsx:66
|
||||
@@ -2564,6 +2531,10 @@ msgstr "Has iniciado sesión correctamente."
|
||||
msgid "You have been signed up successfully."
|
||||
msgstr "Te has registrado correctamente."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:98
|
||||
msgid "You have been unsubscribed!"
|
||||
msgstr "¡Te has dado de baja!"
|
||||
|
||||
#: src/views/members/components/InviteMemberForm.tsx:326
|
||||
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
msgstr "Tienes plazas ilimitadas con tu Plan Pro. ¡No hay cargos adicionales por nuevos miembros!"
|
||||
@@ -2608,6 +2579,10 @@ msgstr "Tu cuenta de Trello ha sido desconectada."
|
||||
msgid "Your Trello account is connected."
|
||||
msgstr "Tu cuenta de Trello está conectada."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:33
|
||||
msgid "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
msgstr "A tu enlace de baja le falta un token. Por favor, abre el último correo electrónico e inténtalo de nuevo."
|
||||
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
|
||||
msgid "Your workspace description has been updated."
|
||||
msgstr "La descripción de tu espacio de trabajo ha sido actualizada."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,7 +22,7 @@ msgid ", or see our"
|
||||
msgstr ", ou consultez notre"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#: src/views/boards/index.tsx:38
|
||||
#: src/views/boards/index.tsx:27
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
|
||||
@@ -30,7 +30,7 @@ msgstr "{0}"
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#. placeholder {1}: board?.name ?? t`Board`
|
||||
#. placeholder {1}: workspace.name ?? t`Workspace`
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/card/index.tsx:229
|
||||
msgid "{0} | {1}"
|
||||
msgstr "{0} | {1}"
|
||||
@@ -41,7 +41,7 @@ msgid "{0} labels"
|
||||
msgstr "{0} étiquettes"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Template" : "Board"
|
||||
#: src/views/board/index.tsx:400
|
||||
#: src/views/board/index.tsx:389
|
||||
msgid "{0} not found"
|
||||
msgstr "{0} introuvable"
|
||||
|
||||
@@ -79,10 +79,6 @@ msgstr "Compte"
|
||||
msgid "Account deleted"
|
||||
msgstr "Compte supprimé"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:55
|
||||
msgid "Actions"
|
||||
msgstr "Actions"
|
||||
|
||||
#: src/views/card/index.tsx:343
|
||||
#: src/views/public/board/CardModal.tsx:157
|
||||
msgid "Activity"
|
||||
@@ -312,7 +308,7 @@ msgstr "Portail de facturation"
|
||||
msgid "Blog Post"
|
||||
msgstr "Article de blog"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/card/index.tsx:229
|
||||
#: src/views/public/board/index.tsx:101
|
||||
msgid "Board"
|
||||
@@ -364,7 +360,7 @@ msgstr "Visibilité du tableau"
|
||||
msgid "Board visibility updated"
|
||||
msgstr "Visibilité du tableau mise à jour"
|
||||
|
||||
#: src/components/SideNavigation.tsx:97
|
||||
#: src/components/SideNavigation.tsx:91
|
||||
msgid "Boards"
|
||||
msgstr "Tableaux"
|
||||
|
||||
@@ -498,6 +494,10 @@ msgstr "a terminé un élément de la checklist"
|
||||
msgid "completed checklist item <0>{0}</0>"
|
||||
msgstr "a terminé l'élément <0>{0}</0> de la checklist"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:81
|
||||
msgid "Confirm your email preferences:"
|
||||
msgstr "Confirmez vos préférences d'e-mail :"
|
||||
|
||||
#: src/views/settings/components/ChangePasswordConfirmation.tsx:150
|
||||
msgid "Confirm your new password"
|
||||
msgstr "Confirmez votre nouveau mot de passe"
|
||||
@@ -582,7 +582,6 @@ msgstr "Créer une liste"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "template" : "board"
|
||||
#: src/views/boards/components/BoardsList.tsx:45
|
||||
#: src/views/boards/index.tsx:26
|
||||
msgid "Create new {0}"
|
||||
msgstr "Créer un nouveau {0}"
|
||||
|
||||
@@ -595,8 +594,7 @@ msgstr "Créer une nouvelle clé"
|
||||
msgid "Create new label"
|
||||
msgstr "Créer une nouvelle étiquette"
|
||||
|
||||
#: src/views/board/index.tsx:64
|
||||
#: src/views/board/index.tsx:491
|
||||
#: src/views/board/index.tsx:478
|
||||
msgid "Create new list"
|
||||
msgstr "Créer une nouvelle liste"
|
||||
|
||||
@@ -605,7 +603,7 @@ msgid "Create template"
|
||||
msgstr "Créer un modèle"
|
||||
|
||||
#: src/components/NewWorkspaceForm.tsx:387
|
||||
#: src/components/WorkspaceMenu.tsx:153
|
||||
#: src/components/WorkspaceMenu.tsx:149
|
||||
msgid "Create workspace"
|
||||
msgstr "Créer un espace de travail"
|
||||
|
||||
@@ -655,7 +653,7 @@ msgstr "URL d'espace de travail personnalisée"
|
||||
msgid "Customer Support"
|
||||
msgstr "Support client"
|
||||
|
||||
#: src/components/UserMenu.tsx:155
|
||||
#: src/components/UserMenu.tsx:153
|
||||
msgid "Dark"
|
||||
msgstr "Sombre"
|
||||
|
||||
@@ -754,6 +752,10 @@ msgstr "Nom d'affichage mis à jour"
|
||||
msgid "Do you offer a free plan?"
|
||||
msgstr "Proposez-vous un plan gratuit ?"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:78
|
||||
msgid "Do you want to unsubscribe?"
|
||||
msgstr "Voulez-vous vous désabonner ?"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:109
|
||||
msgid "docs"
|
||||
msgstr "documentation"
|
||||
@@ -762,7 +764,7 @@ msgstr "documentation"
|
||||
msgid "Docs"
|
||||
msgstr "Documentation"
|
||||
|
||||
#: src/components/UserMenu.tsx:206
|
||||
#: src/components/UserMenu.tsx:191
|
||||
#: src/views/boards/components/TemplateBoards.tsx:24
|
||||
#: src/views/home/components/Footer.tsx:78
|
||||
#: src/views/home/components/Header.tsx:36
|
||||
@@ -986,7 +988,7 @@ msgid "Features"
|
||||
msgstr "Fonctionnalités"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:59
|
||||
#: src/components/UserMenu.tsx:214
|
||||
#: src/components/UserMenu.tsx:199
|
||||
msgid "Feedback"
|
||||
msgstr "Commentaires"
|
||||
|
||||
@@ -1029,10 +1031,6 @@ msgstr "Temps plein"
|
||||
msgid "Fun"
|
||||
msgstr "Amusant"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:53
|
||||
msgid "General"
|
||||
msgstr "Général"
|
||||
|
||||
#: src/views/auth/signup/index.tsx:69
|
||||
#: src/views/home/components/Cta.tsx:61
|
||||
#: src/views/home/components/Header.tsx:106
|
||||
@@ -1052,7 +1050,7 @@ msgstr "Commencer"
|
||||
msgid "Get started by creating a new {0}"
|
||||
msgstr "Commencez par créer un nouveau {0}"
|
||||
|
||||
#: src/views/board/index.tsx:483
|
||||
#: src/views/board/index.tsx:470
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Commencez par créer une nouvelle liste"
|
||||
|
||||
@@ -1086,22 +1084,6 @@ msgstr "Aller à l'accueil"
|
||||
msgid "Go to app"
|
||||
msgstr "Accéder à l'application"
|
||||
|
||||
#: src/components/SideNavigation.tsx:105
|
||||
msgid "Go to boards"
|
||||
msgstr "Aller aux tableaux"
|
||||
|
||||
#: src/components/SideNavigation.tsx:129
|
||||
msgid "Go to members"
|
||||
msgstr "Aller aux membres"
|
||||
|
||||
#: src/components/SideNavigation.tsx:141
|
||||
msgid "Go to settings"
|
||||
msgstr "Aller aux paramètres"
|
||||
|
||||
#: src/components/SideNavigation.tsx:117
|
||||
msgid "Go to templates"
|
||||
msgstr "Aller aux modèles"
|
||||
|
||||
#: src/views/boards/components/TemplateBoards.tsx:18
|
||||
msgid "High Priority"
|
||||
msgstr "Haute priorité"
|
||||
@@ -1151,7 +1133,7 @@ msgstr "Idées"
|
||||
msgid "Ideas to improve this page..."
|
||||
msgstr "Idées pour améliorer cette page..."
|
||||
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/boards/index.tsx:39
|
||||
msgid "Import"
|
||||
msgstr "Importer"
|
||||
|
||||
@@ -1282,10 +1264,6 @@ msgstr "Kanban réinventé"
|
||||
msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Gardez à l'esprit que cette action est irréversible."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:320
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Raccourcis clavier"
|
||||
|
||||
#: src/views/board/components/Filters.tsx:115
|
||||
#: src/views/board/components/NewCardForm.tsx:409
|
||||
#: src/views/card/index.tsx:119
|
||||
@@ -1334,7 +1312,7 @@ msgstr "Mentions légales"
|
||||
msgid "License"
|
||||
msgstr "Licence"
|
||||
|
||||
#: src/components/UserMenu.tsx:169
|
||||
#: src/components/UserMenu.tsx:167
|
||||
msgid "Light"
|
||||
msgstr "Clair"
|
||||
|
||||
@@ -1358,7 +1336,7 @@ msgstr "Listes"
|
||||
msgid "Login | kan.bn"
|
||||
msgstr "Connexion | kan.bn"
|
||||
|
||||
#: src/components/UserMenu.tsx:224
|
||||
#: src/components/UserMenu.tsx:209
|
||||
msgid "Logout"
|
||||
msgstr "Déconnexion"
|
||||
|
||||
@@ -1395,7 +1373,7 @@ msgstr "a marqué l'élément <0>{0}</0> de la checklist comme incomplet"
|
||||
msgid "Medium Priority"
|
||||
msgstr "Priorité moyenne"
|
||||
|
||||
#: src/components/SideNavigation.tsx:121
|
||||
#: src/components/SideNavigation.tsx:101
|
||||
#: src/views/board/components/Filters.tsx:107
|
||||
#: src/views/board/components/NewCardForm.tsx:367
|
||||
#: src/views/card/index.tsx:128
|
||||
@@ -1433,15 +1411,11 @@ msgstr "a déplacé la carte vers une autre liste"
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:54
|
||||
msgid "Navigation"
|
||||
msgstr "Navigation"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:95
|
||||
msgid "Need help?"
|
||||
msgstr "Besoin d'aide ?"
|
||||
|
||||
#: src/views/boards/index.tsx:62
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/home/components/Features.tsx:73
|
||||
msgid "New"
|
||||
msgstr "Nouveau"
|
||||
@@ -1472,7 +1446,7 @@ msgid "New label"
|
||||
msgstr "Nouvelle étiquette"
|
||||
|
||||
#: src/views/board/components/NewListForm.tsx:113
|
||||
#: src/views/board/index.tsx:454
|
||||
#: src/views/board/index.tsx:442
|
||||
msgid "New list"
|
||||
msgstr "Nouvelle liste"
|
||||
|
||||
@@ -1525,11 +1499,7 @@ msgstr "Aucune carte de crédit requise"
|
||||
msgid "No download URL available for this attachment."
|
||||
msgstr "Aucune URL de téléchargement disponible pour cette pièce jointe."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:333
|
||||
msgid "No keyboard shortcuts registered."
|
||||
msgstr "Aucun raccourci clavier enregistré."
|
||||
|
||||
#: src/views/board/index.tsx:480
|
||||
#: src/views/board/index.tsx:467
|
||||
msgid "No lists"
|
||||
msgstr "Aucune liste"
|
||||
|
||||
@@ -1553,14 +1523,6 @@ msgstr "Une fois que vous supprimez votre compte, il n'y a pas de retour possibl
|
||||
msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
|
||||
msgstr "Une fois que vous supprimez votre espace de travail, il n'y a pas de retour possible. Cette action ne peut pas être annulée."
|
||||
|
||||
#: src/components/WorkspaceMenu.tsx:31
|
||||
msgid "Open command menu"
|
||||
msgstr "Ouvrir le menu de commandes"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:171
|
||||
msgid "Open keyboard shortcuts"
|
||||
msgstr "Ouvrir les raccourcis clavier"
|
||||
|
||||
#: src/views/pricing/components/FeatureComparisonTable.tsx:150
|
||||
msgid "Open source"
|
||||
msgstr "Open source"
|
||||
@@ -1676,8 +1638,8 @@ msgstr "Veuillez sélectionner un fichier à télécharger."
|
||||
#: src/views/board/components/NewTemplateForm.tsx:77
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:73
|
||||
#: src/views/board/components/VisibilityButton.tsx:54
|
||||
#: src/views/board/index.tsx:162
|
||||
#: src/views/board/index.tsx:218
|
||||
#: src/views/board/index.tsx:151
|
||||
#: src/views/board/index.tsx:207
|
||||
#: src/views/boards/components/ImportBoardsForm.tsx:205
|
||||
#: src/views/card/components/AttachmentThumbnails.tsx:73
|
||||
#: src/views/card/components/ChecklistItemRow.tsx:60
|
||||
@@ -1910,7 +1872,7 @@ msgid "Senior"
|
||||
msgstr "Senior"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:82
|
||||
#: src/components/SideNavigation.tsx:133
|
||||
#: src/components/SideNavigation.tsx:106
|
||||
msgid "Settings"
|
||||
msgstr "Paramètres"
|
||||
|
||||
@@ -1934,10 +1896,6 @@ msgstr "Paramètres | Intégrations"
|
||||
msgid "Settings | Workspace"
|
||||
msgstr "Paramètres | Espace de travail"
|
||||
|
||||
#: src/components/UserMenu.tsx:184
|
||||
msgid "Shortcuts"
|
||||
msgstr "Raccourcis"
|
||||
|
||||
#: src/views/home/components/Header.tsx:104
|
||||
msgid "Sign in"
|
||||
msgstr "Se connecter"
|
||||
@@ -2006,7 +1964,7 @@ msgstr "Succès"
|
||||
msgid "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
msgstr "Optimisez votre espace de travail pour seulement 29 $/mois. Voici ce que vous obtiendrez :"
|
||||
|
||||
#: src/components/UserMenu.tsx:195
|
||||
#: src/components/UserMenu.tsx:180
|
||||
msgid "Support"
|
||||
msgstr "Assistance"
|
||||
|
||||
@@ -2015,7 +1973,7 @@ msgstr "Assistance"
|
||||
msgid "Support the development of the project"
|
||||
msgstr "Soutenir le développement du projet"
|
||||
|
||||
#: src/components/UserMenu.tsx:141
|
||||
#: src/components/UserMenu.tsx:139
|
||||
msgid "System"
|
||||
msgstr "Système"
|
||||
|
||||
@@ -2030,8 +1988,8 @@ msgstr "Forfait d'équipe"
|
||||
msgid "Teams"
|
||||
msgstr "Équipes"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:409
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/board/index.tsx:398
|
||||
msgid "Template"
|
||||
msgstr "Modèle"
|
||||
|
||||
@@ -2051,7 +2009,7 @@ msgstr "Le nom du modèle ne peut pas dépasser 100 caractères"
|
||||
msgid "Template name is required"
|
||||
msgstr "Le nom du modèle est requis"
|
||||
|
||||
#: src/components/SideNavigation.tsx:109
|
||||
#: src/components/SideNavigation.tsx:96
|
||||
#: src/views/home/components/Features.tsx:115
|
||||
msgid "Templates"
|
||||
msgstr "Modèles"
|
||||
@@ -2085,7 +2043,7 @@ msgstr "L'alternative open source <0/> à Trello"
|
||||
msgid "The visibility of your board has been set to {0}."
|
||||
msgstr "La visibilité de votre tableau a été définie sur {0}."
|
||||
|
||||
#: src/components/UserMenu.tsx:128
|
||||
#: src/components/UserMenu.tsx:126
|
||||
msgid "Theme"
|
||||
msgstr "Thème"
|
||||
|
||||
@@ -2236,7 +2194,7 @@ msgstr "Impossible de mettre à jour l'URL du tableau"
|
||||
msgid "Unable to update board visibility"
|
||||
msgstr "Impossible de mettre à jour la visibilité du tableau"
|
||||
|
||||
#: src/views/board/index.tsx:217
|
||||
#: src/views/board/index.tsx:206
|
||||
#: src/views/card/index.tsx:176
|
||||
msgid "Unable to update card"
|
||||
msgstr "Impossible de mettre à jour la carte"
|
||||
@@ -2257,7 +2215,7 @@ msgstr "Impossible de mettre à jour le commentaire"
|
||||
msgid "Unable to update labels"
|
||||
msgstr "Impossible de mettre à jour les étiquettes"
|
||||
|
||||
#: src/views/board/index.tsx:161
|
||||
#: src/views/board/index.tsx:150
|
||||
#: src/views/card/components/ListSelector.tsx:51
|
||||
msgid "Unable to update list"
|
||||
msgstr "Impossible de mettre à jour la liste"
|
||||
@@ -2313,6 +2271,11 @@ msgstr "Membres illimités"
|
||||
msgid "Unlimited workspaces"
|
||||
msgstr "Espaces de travail illimités"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:68
|
||||
#: src/pages/unsubscribe/index.tsx:93
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Se désabonner"
|
||||
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:175
|
||||
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
|
||||
@@ -2342,7 +2305,7 @@ msgstr "a mis à jour le titre"
|
||||
msgid "updated the title to <0>{0}</0>"
|
||||
msgstr "a mis à jour le titre en <0>{0}</0>"
|
||||
|
||||
#: src/components/SideNavigation.tsx:237
|
||||
#: src/components/SideNavigation.tsx:202
|
||||
#: src/views/settings/components/UpgradeToProConfirmation.tsx:53
|
||||
#: src/views/settings/WorkspaceSettings.tsx:90
|
||||
msgid "Upgrade to Pro"
|
||||
@@ -2426,6 +2389,10 @@ msgstr "Visibilité"
|
||||
msgid "We are using the <0>AGPL-3.0 license</0>."
|
||||
msgstr "Nous utilisons la <0>licence AGPL-3.0</0>."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:63
|
||||
msgid "We couldn't update your preferences. Please try again."
|
||||
msgstr "Nous n'avons pas pu mettre à jour vos préférences. Veuillez réessayer."
|
||||
|
||||
#: src/views/home/components/Features.tsx:152
|
||||
msgid "We're just getting started. "
|
||||
msgstr "Nous ne faisons que commencer. "
|
||||
@@ -2455,8 +2422,8 @@ msgid "Why make an open source Trello?"
|
||||
msgstr "Pourquoi créer un Trello open source ?"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:39
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/members/index.tsx:173
|
||||
#: src/views/public/board/index.tsx:101
|
||||
#: src/views/public/boards/index.tsx:66
|
||||
@@ -2564,6 +2531,10 @@ msgstr "Vous vous êtes connecté avec succès."
|
||||
msgid "You have been signed up successfully."
|
||||
msgstr "Vous vous êtes inscrit avec succès."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:98
|
||||
msgid "You have been unsubscribed!"
|
||||
msgstr "Vous avez été désabonné !"
|
||||
|
||||
#: src/views/members/components/InviteMemberForm.tsx:326
|
||||
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
msgstr "Vous disposez de places illimitées avec votre Plan Pro. Il n'y a pas de frais supplémentaires pour les nouveaux membres !"
|
||||
@@ -2608,6 +2579,10 @@ msgstr "Votre compte Trello a été déconnecté."
|
||||
msgid "Your Trello account is connected."
|
||||
msgstr "Votre compte Trello est connecté."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:33
|
||||
msgid "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
msgstr "Votre lien de désabonnement ne contient pas de jeton. Veuillez ouvrir le dernier e-mail reçu et réessayer."
|
||||
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
|
||||
msgid "Your workspace description has been updated."
|
||||
msgstr "La description de votre espace de travail a été mise à jour."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,7 +22,7 @@ msgid ", or see our"
|
||||
msgstr ", o consulta i nostri"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#: src/views/boards/index.tsx:38
|
||||
#: src/views/boards/index.tsx:27
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
|
||||
@@ -30,7 +30,7 @@ msgstr "{0}"
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#. placeholder {1}: board?.name ?? t`Board`
|
||||
#. placeholder {1}: workspace.name ?? t`Workspace`
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/card/index.tsx:229
|
||||
msgid "{0} | {1}"
|
||||
msgstr "{0} | {1}"
|
||||
@@ -41,7 +41,7 @@ msgid "{0} labels"
|
||||
msgstr "{0} etichette"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Template" : "Board"
|
||||
#: src/views/board/index.tsx:400
|
||||
#: src/views/board/index.tsx:389
|
||||
msgid "{0} not found"
|
||||
msgstr "{0} non trovato"
|
||||
|
||||
@@ -79,10 +79,6 @@ msgstr "Account"
|
||||
msgid "Account deleted"
|
||||
msgstr "Account eliminato"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:55
|
||||
msgid "Actions"
|
||||
msgstr "Azioni"
|
||||
|
||||
#: src/views/card/index.tsx:343
|
||||
#: src/views/public/board/CardModal.tsx:157
|
||||
msgid "Activity"
|
||||
@@ -312,7 +308,7 @@ msgstr "Portale di fatturazione"
|
||||
msgid "Blog Post"
|
||||
msgstr "Post del blog"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/card/index.tsx:229
|
||||
#: src/views/public/board/index.tsx:101
|
||||
msgid "Board"
|
||||
@@ -364,7 +360,7 @@ msgstr "Visibilità bacheca"
|
||||
msgid "Board visibility updated"
|
||||
msgstr "Visibilità della bacheca aggiornata"
|
||||
|
||||
#: src/components/SideNavigation.tsx:97
|
||||
#: src/components/SideNavigation.tsx:91
|
||||
msgid "Boards"
|
||||
msgstr "Bacheche"
|
||||
|
||||
@@ -498,6 +494,10 @@ msgstr "ha completato un elemento della checklist"
|
||||
msgid "completed checklist item <0>{0}</0>"
|
||||
msgstr "ha completato l'elemento <0>{0}</0> della checklist"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:81
|
||||
msgid "Confirm your email preferences:"
|
||||
msgstr "Conferma le tue preferenze email:"
|
||||
|
||||
#: src/views/settings/components/ChangePasswordConfirmation.tsx:150
|
||||
msgid "Confirm your new password"
|
||||
msgstr "Conferma la tua nuova password"
|
||||
@@ -582,7 +582,6 @@ msgstr "Crea lista"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "template" : "board"
|
||||
#: src/views/boards/components/BoardsList.tsx:45
|
||||
#: src/views/boards/index.tsx:26
|
||||
msgid "Create new {0}"
|
||||
msgstr "Crea nuovo {0}"
|
||||
|
||||
@@ -595,8 +594,7 @@ msgstr "Crea nuova chiave"
|
||||
msgid "Create new label"
|
||||
msgstr "Crea nuova etichetta"
|
||||
|
||||
#: src/views/board/index.tsx:64
|
||||
#: src/views/board/index.tsx:491
|
||||
#: src/views/board/index.tsx:478
|
||||
msgid "Create new list"
|
||||
msgstr "Crea nuova lista"
|
||||
|
||||
@@ -605,7 +603,7 @@ msgid "Create template"
|
||||
msgstr "Crea template"
|
||||
|
||||
#: src/components/NewWorkspaceForm.tsx:387
|
||||
#: src/components/WorkspaceMenu.tsx:153
|
||||
#: src/components/WorkspaceMenu.tsx:149
|
||||
msgid "Create workspace"
|
||||
msgstr "Crea spazio di lavoro"
|
||||
|
||||
@@ -655,7 +653,7 @@ msgstr "URL personalizzato dell'area di lavoro"
|
||||
msgid "Customer Support"
|
||||
msgstr "Assistenza clienti"
|
||||
|
||||
#: src/components/UserMenu.tsx:155
|
||||
#: src/components/UserMenu.tsx:153
|
||||
msgid "Dark"
|
||||
msgstr "Scuro"
|
||||
|
||||
@@ -754,6 +752,10 @@ msgstr "Nome visualizzato aggiornato"
|
||||
msgid "Do you offer a free plan?"
|
||||
msgstr "Offrite un piano gratuito?"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:78
|
||||
msgid "Do you want to unsubscribe?"
|
||||
msgstr "Vuoi annullare l'iscrizione?"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:109
|
||||
msgid "docs"
|
||||
msgstr "documenti"
|
||||
@@ -762,7 +764,7 @@ msgstr "documenti"
|
||||
msgid "Docs"
|
||||
msgstr "Documenti"
|
||||
|
||||
#: src/components/UserMenu.tsx:206
|
||||
#: src/components/UserMenu.tsx:191
|
||||
#: src/views/boards/components/TemplateBoards.tsx:24
|
||||
#: src/views/home/components/Footer.tsx:78
|
||||
#: src/views/home/components/Header.tsx:36
|
||||
@@ -986,7 +988,7 @@ msgid "Features"
|
||||
msgstr "Funzionalità"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:59
|
||||
#: src/components/UserMenu.tsx:214
|
||||
#: src/components/UserMenu.tsx:199
|
||||
msgid "Feedback"
|
||||
msgstr "Feedback"
|
||||
|
||||
@@ -1029,10 +1031,6 @@ msgstr "Tempo pieno"
|
||||
msgid "Fun"
|
||||
msgstr "Divertimento"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:53
|
||||
msgid "General"
|
||||
msgstr "Generale"
|
||||
|
||||
#: src/views/auth/signup/index.tsx:69
|
||||
#: src/views/home/components/Cta.tsx:61
|
||||
#: src/views/home/components/Header.tsx:106
|
||||
@@ -1052,7 +1050,7 @@ msgstr "Inizia ora"
|
||||
msgid "Get started by creating a new {0}"
|
||||
msgstr "Inizia creando un nuovo {0}"
|
||||
|
||||
#: src/views/board/index.tsx:483
|
||||
#: src/views/board/index.tsx:470
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Inizia creando una nuova lista"
|
||||
|
||||
@@ -1086,22 +1084,6 @@ msgstr "Vai alla home"
|
||||
msgid "Go to app"
|
||||
msgstr "Vai all'app"
|
||||
|
||||
#: src/components/SideNavigation.tsx:105
|
||||
msgid "Go to boards"
|
||||
msgstr "Vai alle bacheche"
|
||||
|
||||
#: src/components/SideNavigation.tsx:129
|
||||
msgid "Go to members"
|
||||
msgstr "Vai ai membri"
|
||||
|
||||
#: src/components/SideNavigation.tsx:141
|
||||
msgid "Go to settings"
|
||||
msgstr "Vai alle impostazioni"
|
||||
|
||||
#: src/components/SideNavigation.tsx:117
|
||||
msgid "Go to templates"
|
||||
msgstr "Vai ai modelli"
|
||||
|
||||
#: src/views/boards/components/TemplateBoards.tsx:18
|
||||
msgid "High Priority"
|
||||
msgstr "Alta priorità"
|
||||
@@ -1151,7 +1133,7 @@ msgstr "Idee"
|
||||
msgid "Ideas to improve this page..."
|
||||
msgstr "Idee per migliorare questa pagina..."
|
||||
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/boards/index.tsx:39
|
||||
msgid "Import"
|
||||
msgstr "Importa"
|
||||
|
||||
@@ -1282,10 +1264,6 @@ msgstr "Kanban reinventato"
|
||||
msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Tieni presente che questa azione è irreversibile."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:320
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Scorciatoie da tastiera"
|
||||
|
||||
#: src/views/board/components/Filters.tsx:115
|
||||
#: src/views/board/components/NewCardForm.tsx:409
|
||||
#: src/views/card/index.tsx:119
|
||||
@@ -1334,7 +1312,7 @@ msgstr "Legale"
|
||||
msgid "License"
|
||||
msgstr "Licenza"
|
||||
|
||||
#: src/components/UserMenu.tsx:169
|
||||
#: src/components/UserMenu.tsx:167
|
||||
msgid "Light"
|
||||
msgstr "Chiaro"
|
||||
|
||||
@@ -1358,7 +1336,7 @@ msgstr "Liste"
|
||||
msgid "Login | kan.bn"
|
||||
msgstr "Login | kan.bn"
|
||||
|
||||
#: src/components/UserMenu.tsx:224
|
||||
#: src/components/UserMenu.tsx:209
|
||||
msgid "Logout"
|
||||
msgstr "Esci"
|
||||
|
||||
@@ -1395,7 +1373,7 @@ msgstr "ha segnato l'elemento <0>{0}</0> della checklist come incompleto"
|
||||
msgid "Medium Priority"
|
||||
msgstr "Media priorità"
|
||||
|
||||
#: src/components/SideNavigation.tsx:121
|
||||
#: src/components/SideNavigation.tsx:101
|
||||
#: src/views/board/components/Filters.tsx:107
|
||||
#: src/views/board/components/NewCardForm.tsx:367
|
||||
#: src/views/card/index.tsx:128
|
||||
@@ -1433,15 +1411,11 @@ msgstr "ha spostato la scheda in un'altra lista"
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:54
|
||||
msgid "Navigation"
|
||||
msgstr "Navigazione"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:95
|
||||
msgid "Need help?"
|
||||
msgstr "Hai bisogno di aiuto?"
|
||||
|
||||
#: src/views/boards/index.tsx:62
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/home/components/Features.tsx:73
|
||||
msgid "New"
|
||||
msgstr "Nuovo"
|
||||
@@ -1472,7 +1446,7 @@ msgid "New label"
|
||||
msgstr "Nuova etichetta"
|
||||
|
||||
#: src/views/board/components/NewListForm.tsx:113
|
||||
#: src/views/board/index.tsx:454
|
||||
#: src/views/board/index.tsx:442
|
||||
msgid "New list"
|
||||
msgstr "Nuova lista"
|
||||
|
||||
@@ -1525,11 +1499,7 @@ msgstr "Nessuna carta di credito richiesta"
|
||||
msgid "No download URL available for this attachment."
|
||||
msgstr "Nessun URL di download disponibile per questo allegato."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:333
|
||||
msgid "No keyboard shortcuts registered."
|
||||
msgstr "Nessuna scorciatoia da tastiera registrata."
|
||||
|
||||
#: src/views/board/index.tsx:480
|
||||
#: src/views/board/index.tsx:467
|
||||
msgid "No lists"
|
||||
msgstr "Nessuna lista"
|
||||
|
||||
@@ -1553,14 +1523,6 @@ msgstr "Una volta eliminato il tuo account, non si può tornare indietro. Questa
|
||||
msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
|
||||
msgstr "Una volta eliminata l'area di lavoro, non si può tornare indietro. Questa azione non può essere annullata."
|
||||
|
||||
#: src/components/WorkspaceMenu.tsx:31
|
||||
msgid "Open command menu"
|
||||
msgstr "Apri menu dei comandi"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:171
|
||||
msgid "Open keyboard shortcuts"
|
||||
msgstr "Apri scorciatoie da tastiera"
|
||||
|
||||
#: src/views/pricing/components/FeatureComparisonTable.tsx:150
|
||||
msgid "Open source"
|
||||
msgstr "Open source"
|
||||
@@ -1676,8 +1638,8 @@ msgstr "Seleziona un file da caricare."
|
||||
#: src/views/board/components/NewTemplateForm.tsx:77
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:73
|
||||
#: src/views/board/components/VisibilityButton.tsx:54
|
||||
#: src/views/board/index.tsx:162
|
||||
#: src/views/board/index.tsx:218
|
||||
#: src/views/board/index.tsx:151
|
||||
#: src/views/board/index.tsx:207
|
||||
#: src/views/boards/components/ImportBoardsForm.tsx:205
|
||||
#: src/views/card/components/AttachmentThumbnails.tsx:73
|
||||
#: src/views/card/components/ChecklistItemRow.tsx:60
|
||||
@@ -1910,7 +1872,7 @@ msgid "Senior"
|
||||
msgstr "Senior"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:82
|
||||
#: src/components/SideNavigation.tsx:133
|
||||
#: src/components/SideNavigation.tsx:106
|
||||
msgid "Settings"
|
||||
msgstr "Impostazioni"
|
||||
|
||||
@@ -1934,10 +1896,6 @@ msgstr "Impostazioni | Integrazioni"
|
||||
msgid "Settings | Workspace"
|
||||
msgstr "Impostazioni | Area di lavoro"
|
||||
|
||||
#: src/components/UserMenu.tsx:184
|
||||
msgid "Shortcuts"
|
||||
msgstr "Scorciatoie"
|
||||
|
||||
#: src/views/home/components/Header.tsx:104
|
||||
msgid "Sign in"
|
||||
msgstr "Accedi"
|
||||
@@ -2006,7 +1964,7 @@ msgstr "Operazione riuscita"
|
||||
msgid "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
msgstr "Potenzia la tua area di lavoro per soli $29/mese. Ecco cosa otterrai:"
|
||||
|
||||
#: src/components/UserMenu.tsx:195
|
||||
#: src/components/UserMenu.tsx:180
|
||||
msgid "Support"
|
||||
msgstr "Supporto"
|
||||
|
||||
@@ -2015,7 +1973,7 @@ msgstr "Supporto"
|
||||
msgid "Support the development of the project"
|
||||
msgstr "Sostieni lo sviluppo del progetto"
|
||||
|
||||
#: src/components/UserMenu.tsx:141
|
||||
#: src/components/UserMenu.tsx:139
|
||||
msgid "System"
|
||||
msgstr "Sistema"
|
||||
|
||||
@@ -2030,8 +1988,8 @@ msgstr "Piano Team"
|
||||
msgid "Teams"
|
||||
msgstr "Team"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:409
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/board/index.tsx:398
|
||||
msgid "Template"
|
||||
msgstr "Template"
|
||||
|
||||
@@ -2051,7 +2009,7 @@ msgstr "Il nome del template non può superare i 100 caratteri"
|
||||
msgid "Template name is required"
|
||||
msgstr "Il nome del template è obbligatorio"
|
||||
|
||||
#: src/components/SideNavigation.tsx:109
|
||||
#: src/components/SideNavigation.tsx:96
|
||||
#: src/views/home/components/Features.tsx:115
|
||||
msgid "Templates"
|
||||
msgstr "Template"
|
||||
@@ -2085,7 +2043,7 @@ msgstr "L'alternativa open source <0/> a Trello"
|
||||
msgid "The visibility of your board has been set to {0}."
|
||||
msgstr "La visibilità della tua bacheca è stata impostata su {0}."
|
||||
|
||||
#: src/components/UserMenu.tsx:128
|
||||
#: src/components/UserMenu.tsx:126
|
||||
msgid "Theme"
|
||||
msgstr "Tema"
|
||||
|
||||
@@ -2236,7 +2194,7 @@ msgstr "Impossibile aggiornare l'URL della bacheca"
|
||||
msgid "Unable to update board visibility"
|
||||
msgstr "Impossibile aggiornare la visibilità della bacheca"
|
||||
|
||||
#: src/views/board/index.tsx:217
|
||||
#: src/views/board/index.tsx:206
|
||||
#: src/views/card/index.tsx:176
|
||||
msgid "Unable to update card"
|
||||
msgstr "Impossibile aggiornare la scheda"
|
||||
@@ -2257,7 +2215,7 @@ msgstr "Impossibile aggiornare il commento"
|
||||
msgid "Unable to update labels"
|
||||
msgstr "Impossibile aggiornare le etichette"
|
||||
|
||||
#: src/views/board/index.tsx:161
|
||||
#: src/views/board/index.tsx:150
|
||||
#: src/views/card/components/ListSelector.tsx:51
|
||||
msgid "Unable to update list"
|
||||
msgstr "Impossibile aggiornare la lista"
|
||||
@@ -2313,6 +2271,11 @@ msgstr "Membri illimitati"
|
||||
msgid "Unlimited workspaces"
|
||||
msgstr "Aree di lavoro illimitate"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:68
|
||||
#: src/pages/unsubscribe/index.tsx:93
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Annulla iscrizione"
|
||||
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:175
|
||||
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
|
||||
@@ -2342,7 +2305,7 @@ msgstr "ha aggiornato il titolo"
|
||||
msgid "updated the title to <0>{0}</0>"
|
||||
msgstr "ha aggiornato il titolo in <0>{0}</0>"
|
||||
|
||||
#: src/components/SideNavigation.tsx:237
|
||||
#: src/components/SideNavigation.tsx:202
|
||||
#: src/views/settings/components/UpgradeToProConfirmation.tsx:53
|
||||
#: src/views/settings/WorkspaceSettings.tsx:90
|
||||
msgid "Upgrade to Pro"
|
||||
@@ -2426,6 +2389,10 @@ msgstr "Visibilità"
|
||||
msgid "We are using the <0>AGPL-3.0 license</0>."
|
||||
msgstr "Utilizziamo la <0>licenza AGPL-3.0</0>."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:63
|
||||
msgid "We couldn't update your preferences. Please try again."
|
||||
msgstr "Non siamo riusciti ad aggiornare le tue preferenze. Riprova."
|
||||
|
||||
#: src/views/home/components/Features.tsx:152
|
||||
msgid "We're just getting started. "
|
||||
msgstr "Siamo solo all'inizio. "
|
||||
@@ -2455,8 +2422,8 @@ msgid "Why make an open source Trello?"
|
||||
msgstr "Perché creare un Trello open source?"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:39
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/members/index.tsx:173
|
||||
#: src/views/public/board/index.tsx:101
|
||||
#: src/views/public/boards/index.tsx:66
|
||||
@@ -2564,6 +2531,10 @@ msgstr "Hai effettuato l'accesso con successo."
|
||||
msgid "You have been signed up successfully."
|
||||
msgstr "Ti sei registrato con successo."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:98
|
||||
msgid "You have been unsubscribed!"
|
||||
msgstr "La tua iscrizione è stata annullata!"
|
||||
|
||||
#: src/views/members/components/InviteMemberForm.tsx:326
|
||||
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
msgstr "Hai posti illimitati con il tuo Piano Pro. Non ci sono costi aggiuntivi per i nuovi membri!"
|
||||
@@ -2608,6 +2579,10 @@ msgstr "Il tuo account Trello è stato disconnesso."
|
||||
msgid "Your Trello account is connected."
|
||||
msgstr "Il tuo account Trello è connesso."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:33
|
||||
msgid "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
msgstr "Il tuo link per annullare l'iscrizione non contiene un token. Apri l'email più recente e riprova."
|
||||
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
|
||||
msgid "Your workspace description has been updated."
|
||||
msgstr "La descrizione della tua area di lavoro è stata aggiornata."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,7 +22,7 @@ msgid ", or see our"
|
||||
msgstr ", of bekijk onze"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#: src/views/boards/index.tsx:38
|
||||
#: src/views/boards/index.tsx:27
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
|
||||
@@ -30,7 +30,7 @@ msgstr "{0}"
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#. placeholder {1}: board?.name ?? t`Board`
|
||||
#. placeholder {1}: workspace.name ?? t`Workspace`
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/card/index.tsx:229
|
||||
msgid "{0} | {1}"
|
||||
msgstr "{0} | {1}"
|
||||
@@ -41,7 +41,7 @@ msgid "{0} labels"
|
||||
msgstr "{0} labels"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Template" : "Board"
|
||||
#: src/views/board/index.tsx:400
|
||||
#: src/views/board/index.tsx:389
|
||||
msgid "{0} not found"
|
||||
msgstr "{0} niet gevonden"
|
||||
|
||||
@@ -79,10 +79,6 @@ msgstr "Account"
|
||||
msgid "Account deleted"
|
||||
msgstr "Account verwijderd"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:55
|
||||
msgid "Actions"
|
||||
msgstr "Acties"
|
||||
|
||||
#: src/views/card/index.tsx:343
|
||||
#: src/views/public/board/CardModal.tsx:157
|
||||
msgid "Activity"
|
||||
@@ -312,7 +308,7 @@ msgstr "Factureringsportaal"
|
||||
msgid "Blog Post"
|
||||
msgstr "Blogbericht"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/card/index.tsx:229
|
||||
#: src/views/public/board/index.tsx:101
|
||||
msgid "Board"
|
||||
@@ -364,7 +360,7 @@ msgstr "Bordzichtbaarheid"
|
||||
msgid "Board visibility updated"
|
||||
msgstr "Zichtbaarheid van bord bijgewerkt"
|
||||
|
||||
#: src/components/SideNavigation.tsx:97
|
||||
#: src/components/SideNavigation.tsx:91
|
||||
msgid "Boards"
|
||||
msgstr "Borden"
|
||||
|
||||
@@ -498,6 +494,10 @@ msgstr "heeft een checklistitem voltooid"
|
||||
msgid "completed checklist item <0>{0}</0>"
|
||||
msgstr "heeft checklistitem <0>{0}</0> voltooid"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:81
|
||||
msgid "Confirm your email preferences:"
|
||||
msgstr "Bevestig je e-mailvoorkeuren:"
|
||||
|
||||
#: src/views/settings/components/ChangePasswordConfirmation.tsx:150
|
||||
msgid "Confirm your new password"
|
||||
msgstr "Bevestig je nieuwe wachtwoord"
|
||||
@@ -582,7 +582,6 @@ msgstr "Lijst maken"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "template" : "board"
|
||||
#: src/views/boards/components/BoardsList.tsx:45
|
||||
#: src/views/boards/index.tsx:26
|
||||
msgid "Create new {0}"
|
||||
msgstr "Nieuwe {0} maken"
|
||||
|
||||
@@ -595,8 +594,7 @@ msgstr "Nieuwe sleutel aanmaken"
|
||||
msgid "Create new label"
|
||||
msgstr "Maak nieuw label"
|
||||
|
||||
#: src/views/board/index.tsx:64
|
||||
#: src/views/board/index.tsx:491
|
||||
#: src/views/board/index.tsx:478
|
||||
msgid "Create new list"
|
||||
msgstr "Maak nieuwe lijst"
|
||||
|
||||
@@ -605,7 +603,7 @@ msgid "Create template"
|
||||
msgstr "Sjabloon maken"
|
||||
|
||||
#: src/components/NewWorkspaceForm.tsx:387
|
||||
#: src/components/WorkspaceMenu.tsx:153
|
||||
#: src/components/WorkspaceMenu.tsx:149
|
||||
msgid "Create workspace"
|
||||
msgstr "Werkruimte maken"
|
||||
|
||||
@@ -655,7 +653,7 @@ msgstr "Aangepaste werkruimte-URL"
|
||||
msgid "Customer Support"
|
||||
msgstr "Klantenservice"
|
||||
|
||||
#: src/components/UserMenu.tsx:155
|
||||
#: src/components/UserMenu.tsx:153
|
||||
msgid "Dark"
|
||||
msgstr "Donker"
|
||||
|
||||
@@ -754,6 +752,10 @@ msgstr "Weergavenaam bijgewerkt"
|
||||
msgid "Do you offer a free plan?"
|
||||
msgstr "Bieden jullie een gratis abonnement aan?"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:78
|
||||
msgid "Do you want to unsubscribe?"
|
||||
msgstr "Wil je je uitschrijven?"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:109
|
||||
msgid "docs"
|
||||
msgstr "docs"
|
||||
@@ -762,7 +764,7 @@ msgstr "docs"
|
||||
msgid "Docs"
|
||||
msgstr "Docs"
|
||||
|
||||
#: src/components/UserMenu.tsx:206
|
||||
#: src/components/UserMenu.tsx:191
|
||||
#: src/views/boards/components/TemplateBoards.tsx:24
|
||||
#: src/views/home/components/Footer.tsx:78
|
||||
#: src/views/home/components/Header.tsx:36
|
||||
@@ -986,7 +988,7 @@ msgid "Features"
|
||||
msgstr "Functies"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:59
|
||||
#: src/components/UserMenu.tsx:214
|
||||
#: src/components/UserMenu.tsx:199
|
||||
msgid "Feedback"
|
||||
msgstr "Feedback"
|
||||
|
||||
@@ -1029,10 +1031,6 @@ msgstr "Fulltime"
|
||||
msgid "Fun"
|
||||
msgstr "Leuk"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:53
|
||||
msgid "General"
|
||||
msgstr "Algemeen"
|
||||
|
||||
#: src/views/auth/signup/index.tsx:69
|
||||
#: src/views/home/components/Cta.tsx:61
|
||||
#: src/views/home/components/Header.tsx:106
|
||||
@@ -1052,7 +1050,7 @@ msgstr "Aan de slag"
|
||||
msgid "Get started by creating a new {0}"
|
||||
msgstr "Begin door een nieuwe {0} te maken"
|
||||
|
||||
#: src/views/board/index.tsx:483
|
||||
#: src/views/board/index.tsx:470
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Begin door een nieuwe lijst te maken"
|
||||
|
||||
@@ -1086,22 +1084,6 @@ msgstr "Naar startpagina"
|
||||
msgid "Go to app"
|
||||
msgstr "Naar de app"
|
||||
|
||||
#: src/components/SideNavigation.tsx:105
|
||||
msgid "Go to boards"
|
||||
msgstr "Ga naar borden"
|
||||
|
||||
#: src/components/SideNavigation.tsx:129
|
||||
msgid "Go to members"
|
||||
msgstr "Ga naar leden"
|
||||
|
||||
#: src/components/SideNavigation.tsx:141
|
||||
msgid "Go to settings"
|
||||
msgstr "Ga naar instellingen"
|
||||
|
||||
#: src/components/SideNavigation.tsx:117
|
||||
msgid "Go to templates"
|
||||
msgstr "Ga naar sjablonen"
|
||||
|
||||
#: src/views/boards/components/TemplateBoards.tsx:18
|
||||
msgid "High Priority"
|
||||
msgstr "Hoge prioriteit"
|
||||
@@ -1151,7 +1133,7 @@ msgstr "Ideeën"
|
||||
msgid "Ideas to improve this page..."
|
||||
msgstr "Ideeën om deze pagina te verbeteren..."
|
||||
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/boards/index.tsx:39
|
||||
msgid "Import"
|
||||
msgstr "Importeren"
|
||||
|
||||
@@ -1282,10 +1264,6 @@ msgstr "Kanban opnieuw uitgevonden"
|
||||
msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Houd er rekening mee dat deze actie onomkeerbaar is."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:320
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Sneltoetsen"
|
||||
|
||||
#: src/views/board/components/Filters.tsx:115
|
||||
#: src/views/board/components/NewCardForm.tsx:409
|
||||
#: src/views/card/index.tsx:119
|
||||
@@ -1334,7 +1312,7 @@ msgstr "Juridisch"
|
||||
msgid "License"
|
||||
msgstr "Licentie"
|
||||
|
||||
#: src/components/UserMenu.tsx:169
|
||||
#: src/components/UserMenu.tsx:167
|
||||
msgid "Light"
|
||||
msgstr "Licht"
|
||||
|
||||
@@ -1358,7 +1336,7 @@ msgstr "Lijsten"
|
||||
msgid "Login | kan.bn"
|
||||
msgstr "Login | kan.bn"
|
||||
|
||||
#: src/components/UserMenu.tsx:224
|
||||
#: src/components/UserMenu.tsx:209
|
||||
msgid "Logout"
|
||||
msgstr "Uitloggen"
|
||||
|
||||
@@ -1395,7 +1373,7 @@ msgstr "heeft checklistitem <0>{0}</0> als onvoltooid gemarkeerd"
|
||||
msgid "Medium Priority"
|
||||
msgstr "Gemiddelde prioriteit"
|
||||
|
||||
#: src/components/SideNavigation.tsx:121
|
||||
#: src/components/SideNavigation.tsx:101
|
||||
#: src/views/board/components/Filters.tsx:107
|
||||
#: src/views/board/components/NewCardForm.tsx:367
|
||||
#: src/views/card/index.tsx:128
|
||||
@@ -1433,15 +1411,11 @@ msgstr "heeft de kaart naar een andere lijst verplaatst"
|
||||
msgid "Name"
|
||||
msgstr "Naam"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:54
|
||||
msgid "Navigation"
|
||||
msgstr "Navigatie"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:95
|
||||
msgid "Need help?"
|
||||
msgstr "Hulp nodig?"
|
||||
|
||||
#: src/views/boards/index.tsx:62
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/home/components/Features.tsx:73
|
||||
msgid "New"
|
||||
msgstr "Nieuw"
|
||||
@@ -1472,7 +1446,7 @@ msgid "New label"
|
||||
msgstr "Nieuw label"
|
||||
|
||||
#: src/views/board/components/NewListForm.tsx:113
|
||||
#: src/views/board/index.tsx:454
|
||||
#: src/views/board/index.tsx:442
|
||||
msgid "New list"
|
||||
msgstr "Nieuwe lijst"
|
||||
|
||||
@@ -1525,11 +1499,7 @@ msgstr "Geen creditcard vereist"
|
||||
msgid "No download URL available for this attachment."
|
||||
msgstr "Geen download-URL beschikbaar voor deze bijlage."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:333
|
||||
msgid "No keyboard shortcuts registered."
|
||||
msgstr "Geen sneltoetsen geregistreerd."
|
||||
|
||||
#: src/views/board/index.tsx:480
|
||||
#: src/views/board/index.tsx:467
|
||||
msgid "No lists"
|
||||
msgstr "Geen lijsten"
|
||||
|
||||
@@ -1553,14 +1523,6 @@ msgstr "Zodra je je account verwijdert, is er geen weg terug. Deze actie kan nie
|
||||
msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
|
||||
msgstr "Zodra je je werkruimte verwijdert, is er geen weg terug. Deze actie kan niet ongedaan worden gemaakt."
|
||||
|
||||
#: src/components/WorkspaceMenu.tsx:31
|
||||
msgid "Open command menu"
|
||||
msgstr "Open opdrachtmenu"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:171
|
||||
msgid "Open keyboard shortcuts"
|
||||
msgstr "Open sneltoetsen"
|
||||
|
||||
#: src/views/pricing/components/FeatureComparisonTable.tsx:150
|
||||
msgid "Open source"
|
||||
msgstr "Open source"
|
||||
@@ -1676,8 +1638,8 @@ msgstr "Selecteer een bestand om te uploaden."
|
||||
#: src/views/board/components/NewTemplateForm.tsx:77
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:73
|
||||
#: src/views/board/components/VisibilityButton.tsx:54
|
||||
#: src/views/board/index.tsx:162
|
||||
#: src/views/board/index.tsx:218
|
||||
#: src/views/board/index.tsx:151
|
||||
#: src/views/board/index.tsx:207
|
||||
#: src/views/boards/components/ImportBoardsForm.tsx:205
|
||||
#: src/views/card/components/AttachmentThumbnails.tsx:73
|
||||
#: src/views/card/components/ChecklistItemRow.tsx:60
|
||||
@@ -1910,7 +1872,7 @@ msgid "Senior"
|
||||
msgstr "Senior"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:82
|
||||
#: src/components/SideNavigation.tsx:133
|
||||
#: src/components/SideNavigation.tsx:106
|
||||
msgid "Settings"
|
||||
msgstr "Instellingen"
|
||||
|
||||
@@ -1934,10 +1896,6 @@ msgstr "Instellingen | Integraties"
|
||||
msgid "Settings | Workspace"
|
||||
msgstr "Instellingen | Werkruimte"
|
||||
|
||||
#: src/components/UserMenu.tsx:184
|
||||
msgid "Shortcuts"
|
||||
msgstr "Snelkoppelingen"
|
||||
|
||||
#: src/views/home/components/Header.tsx:104
|
||||
msgid "Sign in"
|
||||
msgstr "Inloggen"
|
||||
@@ -2006,7 +1964,7 @@ msgstr "Geslaagd"
|
||||
msgid "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
msgstr "Geef je werkruimte een boost voor slechts $29/maand. Dit krijg je:"
|
||||
|
||||
#: src/components/UserMenu.tsx:195
|
||||
#: src/components/UserMenu.tsx:180
|
||||
msgid "Support"
|
||||
msgstr "Ondersteuning"
|
||||
|
||||
@@ -2015,7 +1973,7 @@ msgstr "Ondersteuning"
|
||||
msgid "Support the development of the project"
|
||||
msgstr "Ondersteun de ontwikkeling van het project"
|
||||
|
||||
#: src/components/UserMenu.tsx:141
|
||||
#: src/components/UserMenu.tsx:139
|
||||
msgid "System"
|
||||
msgstr "Systeem"
|
||||
|
||||
@@ -2030,8 +1988,8 @@ msgstr "Teamplan"
|
||||
msgid "Teams"
|
||||
msgstr "Teams"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:409
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/board/index.tsx:398
|
||||
msgid "Template"
|
||||
msgstr "Sjabloon"
|
||||
|
||||
@@ -2051,7 +2009,7 @@ msgstr "Sjabloonnaam mag niet langer zijn dan 100 tekens"
|
||||
msgid "Template name is required"
|
||||
msgstr "Sjabloonnaam is verplicht"
|
||||
|
||||
#: src/components/SideNavigation.tsx:109
|
||||
#: src/components/SideNavigation.tsx:96
|
||||
#: src/views/home/components/Features.tsx:115
|
||||
msgid "Templates"
|
||||
msgstr "Sjablonen"
|
||||
@@ -2085,7 +2043,7 @@ msgstr "Het open source <0/> alternatief voor Trello"
|
||||
msgid "The visibility of your board has been set to {0}."
|
||||
msgstr "De zichtbaarheid van je bord is ingesteld op {0}."
|
||||
|
||||
#: src/components/UserMenu.tsx:128
|
||||
#: src/components/UserMenu.tsx:126
|
||||
msgid "Theme"
|
||||
msgstr "Thema"
|
||||
|
||||
@@ -2236,7 +2194,7 @@ msgstr "Kan board URL niet bijwerken"
|
||||
msgid "Unable to update board visibility"
|
||||
msgstr "Kan bordzichtbaarheid niet bijwerken"
|
||||
|
||||
#: src/views/board/index.tsx:217
|
||||
#: src/views/board/index.tsx:206
|
||||
#: src/views/card/index.tsx:176
|
||||
msgid "Unable to update card"
|
||||
msgstr "Kan kaart niet bijwerken"
|
||||
@@ -2257,7 +2215,7 @@ msgstr "Kan reactie niet bijwerken"
|
||||
msgid "Unable to update labels"
|
||||
msgstr "Kan labels niet bijwerken"
|
||||
|
||||
#: src/views/board/index.tsx:161
|
||||
#: src/views/board/index.tsx:150
|
||||
#: src/views/card/components/ListSelector.tsx:51
|
||||
msgid "Unable to update list"
|
||||
msgstr "Kan lijst niet bijwerken"
|
||||
@@ -2313,6 +2271,11 @@ msgstr "Onbeperkt aantal leden"
|
||||
msgid "Unlimited workspaces"
|
||||
msgstr "Onbeperkte werkruimtes"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:68
|
||||
#: src/pages/unsubscribe/index.tsx:93
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Uitschrijven"
|
||||
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:175
|
||||
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
|
||||
@@ -2342,7 +2305,7 @@ msgstr "titel bijgewerkt"
|
||||
msgid "updated the title to <0>{0}</0>"
|
||||
msgstr "titel bijgewerkt naar <0>{0}</0>"
|
||||
|
||||
#: src/components/SideNavigation.tsx:237
|
||||
#: src/components/SideNavigation.tsx:202
|
||||
#: src/views/settings/components/UpgradeToProConfirmation.tsx:53
|
||||
#: src/views/settings/WorkspaceSettings.tsx:90
|
||||
msgid "Upgrade to Pro"
|
||||
@@ -2426,6 +2389,10 @@ msgstr "Zichtbaarheid"
|
||||
msgid "We are using the <0>AGPL-3.0 license</0>."
|
||||
msgstr "We gebruiken de <0>AGPL-3.0 licentie</0>."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:63
|
||||
msgid "We couldn't update your preferences. Please try again."
|
||||
msgstr "We konden je voorkeuren niet bijwerken. Probeer het opnieuw."
|
||||
|
||||
#: src/views/home/components/Features.tsx:152
|
||||
msgid "We're just getting started. "
|
||||
msgstr "We zijn nog maar net begonnen. "
|
||||
@@ -2455,8 +2422,8 @@ msgid "Why make an open source Trello?"
|
||||
msgstr "Waarom een open source Trello maken?"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:39
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/members/index.tsx:173
|
||||
#: src/views/public/board/index.tsx:101
|
||||
#: src/views/public/boards/index.tsx:66
|
||||
@@ -2564,6 +2531,10 @@ msgstr "Je bent succesvol ingelogd."
|
||||
msgid "You have been signed up successfully."
|
||||
msgstr "Je bent succesvol geregistreerd."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:98
|
||||
msgid "You have been unsubscribed!"
|
||||
msgstr "Je bent uitgeschreven!"
|
||||
|
||||
#: src/views/members/components/InviteMemberForm.tsx:326
|
||||
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
msgstr "Je hebt onbeperkte plaatsen met je Pro Plan. Er zijn geen extra kosten voor nieuwe leden!"
|
||||
@@ -2608,6 +2579,10 @@ msgstr "Je Trello-account is ontkoppeld."
|
||||
msgid "Your Trello account is connected."
|
||||
msgstr "Je Trello-account is verbonden."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:33
|
||||
msgid "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
msgstr "Je uitschrijflink mist een token. Open de meest recente e-mail en probeer het opnieuw."
|
||||
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
|
||||
msgid "Your workspace description has been updated."
|
||||
msgstr "Je werkruimtebeschrijving is bijgewerkt."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -27,7 +27,7 @@ msgid ", or see our"
|
||||
msgstr ", lub zobacz nasze"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#: src/views/boards/index.tsx:38
|
||||
#: src/views/boards/index.tsx:27
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
|
||||
@@ -35,7 +35,7 @@ msgstr "{0}"
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#. placeholder {1}: board?.name ?? t`Board`
|
||||
#. placeholder {1}: workspace.name ?? t`Workspace`
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/card/index.tsx:229
|
||||
msgid "{0} | {1}"
|
||||
msgstr "{0} | {1}"
|
||||
@@ -46,7 +46,7 @@ msgid "{0} labels"
|
||||
msgstr "{0} etykiety"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Template" : "Board"
|
||||
#: src/views/board/index.tsx:400
|
||||
#: src/views/board/index.tsx:389
|
||||
msgid "{0} not found"
|
||||
msgstr "{0} nie znaleziono"
|
||||
|
||||
@@ -84,10 +84,6 @@ msgstr "Konto"
|
||||
msgid "Account deleted"
|
||||
msgstr "Konto zostało usunięte"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:55
|
||||
msgid "Actions"
|
||||
msgstr "Akcje"
|
||||
|
||||
#: src/views/card/index.tsx:343
|
||||
#: src/views/public/board/CardModal.tsx:157
|
||||
msgid "Activity"
|
||||
@@ -317,7 +313,7 @@ msgstr "Portal rozliczeniowy"
|
||||
msgid "Blog Post"
|
||||
msgstr "Post na blogu"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/card/index.tsx:229
|
||||
#: src/views/public/board/index.tsx:101
|
||||
msgid "Board"
|
||||
@@ -369,7 +365,7 @@ msgstr "Widoczność tablicy"
|
||||
msgid "Board visibility updated"
|
||||
msgstr "Widoczność tablicy została zaktualizowana"
|
||||
|
||||
#: src/components/SideNavigation.tsx:97
|
||||
#: src/components/SideNavigation.tsx:91
|
||||
msgid "Boards"
|
||||
msgstr "Tablice"
|
||||
|
||||
@@ -503,6 +499,10 @@ msgstr "ukończono element listy kontrolnej"
|
||||
msgid "completed checklist item <0>{0}</0>"
|
||||
msgstr "ukończono element listy kontrolnej <0>{0}</0>"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:81
|
||||
msgid "Confirm your email preferences:"
|
||||
msgstr "Potwierdź swoje preferencje dotyczące e-maili:"
|
||||
|
||||
#: src/views/settings/components/ChangePasswordConfirmation.tsx:150
|
||||
msgid "Confirm your new password"
|
||||
msgstr "Potwierdź swoje nowe hasło"
|
||||
@@ -587,7 +587,6 @@ msgstr "Utwórz listę"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "template" : "board"
|
||||
#: src/views/boards/components/BoardsList.tsx:45
|
||||
#: src/views/boards/index.tsx:26
|
||||
msgid "Create new {0}"
|
||||
msgstr "Utwórz nowy {0}"
|
||||
|
||||
@@ -600,8 +599,7 @@ msgstr "Utwórz nowy klucz"
|
||||
msgid "Create new label"
|
||||
msgstr "Utwórz nową etykietę"
|
||||
|
||||
#: src/views/board/index.tsx:64
|
||||
#: src/views/board/index.tsx:491
|
||||
#: src/views/board/index.tsx:478
|
||||
msgid "Create new list"
|
||||
msgstr "Utwórz nową listę"
|
||||
|
||||
@@ -610,7 +608,7 @@ msgid "Create template"
|
||||
msgstr "Utwórz szablon"
|
||||
|
||||
#: src/components/NewWorkspaceForm.tsx:387
|
||||
#: src/components/WorkspaceMenu.tsx:153
|
||||
#: src/components/WorkspaceMenu.tsx:149
|
||||
msgid "Create workspace"
|
||||
msgstr "Utwórz przestrzeń roboczą"
|
||||
|
||||
@@ -660,7 +658,7 @@ msgstr "Niestandardowy adres URL przestrzeni roboczej"
|
||||
msgid "Customer Support"
|
||||
msgstr "Obsługa klienta"
|
||||
|
||||
#: src/components/UserMenu.tsx:155
|
||||
#: src/components/UserMenu.tsx:153
|
||||
msgid "Dark"
|
||||
msgstr "Ciemny"
|
||||
|
||||
@@ -759,6 +757,10 @@ msgstr "Zaktualizowano wyświetlaną nazwę"
|
||||
msgid "Do you offer a free plan?"
|
||||
msgstr "Czy oferujecie darmowy plan?"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:78
|
||||
msgid "Do you want to unsubscribe?"
|
||||
msgstr "Czy chcesz się wypisać?"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:109
|
||||
msgid "docs"
|
||||
msgstr "dokumentacja"
|
||||
@@ -767,7 +769,7 @@ msgstr "dokumentacja"
|
||||
msgid "Docs"
|
||||
msgstr "Dokumentacja"
|
||||
|
||||
#: src/components/UserMenu.tsx:206
|
||||
#: src/components/UserMenu.tsx:191
|
||||
#: src/views/boards/components/TemplateBoards.tsx:24
|
||||
#: src/views/home/components/Footer.tsx:78
|
||||
#: src/views/home/components/Header.tsx:36
|
||||
@@ -991,7 +993,7 @@ msgid "Features"
|
||||
msgstr "Funkcje"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:59
|
||||
#: src/components/UserMenu.tsx:214
|
||||
#: src/components/UserMenu.tsx:199
|
||||
msgid "Feedback"
|
||||
msgstr "Opinie"
|
||||
|
||||
@@ -1034,10 +1036,6 @@ msgstr "Pełny etat"
|
||||
msgid "Fun"
|
||||
msgstr "Zabawa"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:53
|
||||
msgid "General"
|
||||
msgstr "Ogólne"
|
||||
|
||||
#: src/views/auth/signup/index.tsx:69
|
||||
#: src/views/home/components/Cta.tsx:61
|
||||
#: src/views/home/components/Header.tsx:106
|
||||
@@ -1057,7 +1055,7 @@ msgstr "Rozpocznij"
|
||||
msgid "Get started by creating a new {0}"
|
||||
msgstr "Rozpocznij, tworząc nowy {0}"
|
||||
|
||||
#: src/views/board/index.tsx:483
|
||||
#: src/views/board/index.tsx:470
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Rozpocznij, tworząc nową listę"
|
||||
|
||||
@@ -1091,22 +1089,6 @@ msgstr "Wróć do strony głównej"
|
||||
msgid "Go to app"
|
||||
msgstr "Przejdź do aplikacji"
|
||||
|
||||
#: src/components/SideNavigation.tsx:105
|
||||
msgid "Go to boards"
|
||||
msgstr "Przejdź do tablic"
|
||||
|
||||
#: src/components/SideNavigation.tsx:129
|
||||
msgid "Go to members"
|
||||
msgstr "Przejdź do członków"
|
||||
|
||||
#: src/components/SideNavigation.tsx:141
|
||||
msgid "Go to settings"
|
||||
msgstr "Przejdź do ustawień"
|
||||
|
||||
#: src/components/SideNavigation.tsx:117
|
||||
msgid "Go to templates"
|
||||
msgstr "Przejdź do szablonów"
|
||||
|
||||
#: src/views/boards/components/TemplateBoards.tsx:18
|
||||
msgid "High Priority"
|
||||
msgstr "Wysoki priorytet"
|
||||
@@ -1156,7 +1138,7 @@ msgstr "Pomysły"
|
||||
msgid "Ideas to improve this page..."
|
||||
msgstr "Pomysły na ulepszenie tej strony..."
|
||||
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/boards/index.tsx:39
|
||||
msgid "Import"
|
||||
msgstr "Importuj"
|
||||
|
||||
@@ -1287,10 +1269,6 @@ msgstr "Kanban wymyślony na nowo"
|
||||
msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Pamiętaj, że ta akcja jest nieodwracalna."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:320
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Skróty klawiaturowe"
|
||||
|
||||
#: src/views/board/components/Filters.tsx:115
|
||||
#: src/views/board/components/NewCardForm.tsx:409
|
||||
#: src/views/card/index.tsx:119
|
||||
@@ -1339,7 +1317,7 @@ msgstr "Prawne"
|
||||
msgid "License"
|
||||
msgstr "Licencja"
|
||||
|
||||
#: src/components/UserMenu.tsx:169
|
||||
#: src/components/UserMenu.tsx:167
|
||||
msgid "Light"
|
||||
msgstr "Jasny"
|
||||
|
||||
@@ -1363,7 +1341,7 @@ msgstr "Listy"
|
||||
msgid "Login | kan.bn"
|
||||
msgstr "Zaloguj się | kan.bn"
|
||||
|
||||
#: src/components/UserMenu.tsx:224
|
||||
#: src/components/UserMenu.tsx:209
|
||||
msgid "Logout"
|
||||
msgstr "Wyloguj się"
|
||||
|
||||
@@ -1400,7 +1378,7 @@ msgstr "oznaczył element listy kontrolnej <0>{0}</0> jako nieukończony"
|
||||
msgid "Medium Priority"
|
||||
msgstr "Średni priorytet"
|
||||
|
||||
#: src/components/SideNavigation.tsx:121
|
||||
#: src/components/SideNavigation.tsx:101
|
||||
#: src/views/board/components/Filters.tsx:107
|
||||
#: src/views/board/components/NewCardForm.tsx:367
|
||||
#: src/views/card/index.tsx:128
|
||||
@@ -1438,15 +1416,11 @@ msgstr "przeniesiono kartę do innej listy"
|
||||
msgid "Name"
|
||||
msgstr "Nazwa"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:54
|
||||
msgid "Navigation"
|
||||
msgstr "Nawigacja"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:95
|
||||
msgid "Need help?"
|
||||
msgstr "Potrzebujesz pomocy?"
|
||||
|
||||
#: src/views/boards/index.tsx:62
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/home/components/Features.tsx:73
|
||||
msgid "New"
|
||||
msgstr "Nowy"
|
||||
@@ -1477,7 +1451,7 @@ msgid "New label"
|
||||
msgstr "Nowa etykieta"
|
||||
|
||||
#: src/views/board/components/NewListForm.tsx:113
|
||||
#: src/views/board/index.tsx:454
|
||||
#: src/views/board/index.tsx:442
|
||||
msgid "New list"
|
||||
msgstr "Nowa lista"
|
||||
|
||||
@@ -1530,11 +1504,7 @@ msgstr "Nie wymagana karta kredytowa"
|
||||
msgid "No download URL available for this attachment."
|
||||
msgstr "Brak dostępnego URL do pobrania tego załącznika."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:333
|
||||
msgid "No keyboard shortcuts registered."
|
||||
msgstr "Brak zarejestrowanych skrótów klawiaturowych."
|
||||
|
||||
#: src/views/board/index.tsx:480
|
||||
#: src/views/board/index.tsx:467
|
||||
msgid "No lists"
|
||||
msgstr "Brak list"
|
||||
|
||||
@@ -1558,14 +1528,6 @@ msgstr "Po usunięciu konta nie będzie możliwości jego przywrócenia. Tej ope
|
||||
msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
|
||||
msgstr "Po usunięciu przestrzeni roboczej nie będzie możliwości jej przywrócenia. Tej operacji nie można cofnąć."
|
||||
|
||||
#: src/components/WorkspaceMenu.tsx:31
|
||||
msgid "Open command menu"
|
||||
msgstr "Otwórz menu poleceń"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:171
|
||||
msgid "Open keyboard shortcuts"
|
||||
msgstr "Otwórz skróty klawiaturowe"
|
||||
|
||||
#: src/views/pricing/components/FeatureComparisonTable.tsx:150
|
||||
msgid "Open source"
|
||||
msgstr "Otwartoźródłowe"
|
||||
@@ -1681,8 +1643,8 @@ msgstr "Proszę wybrać plik do przesłania."
|
||||
#: src/views/board/components/NewTemplateForm.tsx:77
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:73
|
||||
#: src/views/board/components/VisibilityButton.tsx:54
|
||||
#: src/views/board/index.tsx:162
|
||||
#: src/views/board/index.tsx:218
|
||||
#: src/views/board/index.tsx:151
|
||||
#: src/views/board/index.tsx:207
|
||||
#: src/views/boards/components/ImportBoardsForm.tsx:205
|
||||
#: src/views/card/components/AttachmentThumbnails.tsx:73
|
||||
#: src/views/card/components/ChecklistItemRow.tsx:60
|
||||
@@ -1915,7 +1877,7 @@ msgid "Senior"
|
||||
msgstr "Starszy"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:82
|
||||
#: src/components/SideNavigation.tsx:133
|
||||
#: src/components/SideNavigation.tsx:106
|
||||
msgid "Settings"
|
||||
msgstr "Ustawienia"
|
||||
|
||||
@@ -1939,10 +1901,6 @@ msgstr "Ustawienia | Integracje"
|
||||
msgid "Settings | Workspace"
|
||||
msgstr "Ustawienia | Obszar roboczy"
|
||||
|
||||
#: src/components/UserMenu.tsx:184
|
||||
msgid "Shortcuts"
|
||||
msgstr "Skróty"
|
||||
|
||||
#: src/views/home/components/Header.tsx:104
|
||||
msgid "Sign in"
|
||||
msgstr "Zaloguj się"
|
||||
@@ -2011,7 +1969,7 @@ msgstr "Sukces"
|
||||
msgid "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
msgstr "Zwiększ możliwości swojego obszaru roboczego za jedyne 29 USD/miesiąc. Oto, co otrzymasz:"
|
||||
|
||||
#: src/components/UserMenu.tsx:195
|
||||
#: src/components/UserMenu.tsx:180
|
||||
msgid "Support"
|
||||
msgstr "Wsparcie"
|
||||
|
||||
@@ -2020,7 +1978,7 @@ msgstr "Wsparcie"
|
||||
msgid "Support the development of the project"
|
||||
msgstr "Wspieraj rozwój projektu"
|
||||
|
||||
#: src/components/UserMenu.tsx:141
|
||||
#: src/components/UserMenu.tsx:139
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
@@ -2035,8 +1993,8 @@ msgstr "Plan zespołowy"
|
||||
msgid "Teams"
|
||||
msgstr "Zespoły"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:409
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/board/index.tsx:398
|
||||
msgid "Template"
|
||||
msgstr "Szablon"
|
||||
|
||||
@@ -2056,7 +2014,7 @@ msgstr "Nazwa szablonu nie może przekraczać 100 znaków"
|
||||
msgid "Template name is required"
|
||||
msgstr "Nazwa szablonu jest wymagana"
|
||||
|
||||
#: src/components/SideNavigation.tsx:109
|
||||
#: src/components/SideNavigation.tsx:96
|
||||
#: src/views/home/components/Features.tsx:115
|
||||
msgid "Templates"
|
||||
msgstr "Szablony"
|
||||
@@ -2090,7 +2048,7 @@ msgstr "Otwarta alternatywa <0/> dla Trello"
|
||||
msgid "The visibility of your board has been set to {0}."
|
||||
msgstr "Widoczność Twojej tablicy została ustawiona na {0}."
|
||||
|
||||
#: src/components/UserMenu.tsx:128
|
||||
#: src/components/UserMenu.tsx:126
|
||||
msgid "Theme"
|
||||
msgstr "Motyw"
|
||||
|
||||
@@ -2241,7 +2199,7 @@ msgstr "Nie można zaktualizować adresu URL tablicy"
|
||||
msgid "Unable to update board visibility"
|
||||
msgstr "Nie można zaktualizować widoczności tablicy"
|
||||
|
||||
#: src/views/board/index.tsx:217
|
||||
#: src/views/board/index.tsx:206
|
||||
#: src/views/card/index.tsx:176
|
||||
msgid "Unable to update card"
|
||||
msgstr "Nie można zaktualizować karty"
|
||||
@@ -2262,7 +2220,7 @@ msgstr "Nie można zaktualizować komentarza"
|
||||
msgid "Unable to update labels"
|
||||
msgstr "Nie można zaktualizować etykiet"
|
||||
|
||||
#: src/views/board/index.tsx:161
|
||||
#: src/views/board/index.tsx:150
|
||||
#: src/views/card/components/ListSelector.tsx:51
|
||||
msgid "Unable to update list"
|
||||
msgstr "Nie można zaktualizować listy"
|
||||
@@ -2318,6 +2276,11 @@ msgstr "Nieograniczona liczba członków"
|
||||
msgid "Unlimited workspaces"
|
||||
msgstr "Nieograniczona liczba przestrzeni roboczych"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:68
|
||||
#: src/pages/unsubscribe/index.tsx:93
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Wypisz się"
|
||||
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:175
|
||||
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
|
||||
@@ -2347,7 +2310,7 @@ msgstr "zaktualizowano tytuł"
|
||||
msgid "updated the title to <0>{0}</0>"
|
||||
msgstr "zaktualizowano tytuł na <0>{0}</0>"
|
||||
|
||||
#: src/components/SideNavigation.tsx:237
|
||||
#: src/components/SideNavigation.tsx:202
|
||||
#: src/views/settings/components/UpgradeToProConfirmation.tsx:53
|
||||
#: src/views/settings/WorkspaceSettings.tsx:90
|
||||
msgid "Upgrade to Pro"
|
||||
@@ -2431,6 +2394,10 @@ msgstr "Widoczność"
|
||||
msgid "We are using the <0>AGPL-3.0 license</0>."
|
||||
msgstr "Używamy licencji <0>AGPL-3.0</0>."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:63
|
||||
msgid "We couldn't update your preferences. Please try again."
|
||||
msgstr "Nie udało się zaktualizować twoich preferencji. Spróbuj ponownie."
|
||||
|
||||
#: src/views/home/components/Features.tsx:152
|
||||
msgid "We're just getting started. "
|
||||
msgstr "Dopiero zaczynamy. "
|
||||
@@ -2460,8 +2427,8 @@ msgid "Why make an open source Trello?"
|
||||
msgstr "Dlaczego próbujecie stworzyć Trello w wersji otwartoźródłowej?"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:39
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/members/index.tsx:173
|
||||
#: src/views/public/board/index.tsx:101
|
||||
#: src/views/public/boards/index.tsx:66
|
||||
@@ -2569,6 +2536,10 @@ msgstr "Zostałeś pomyślnie zalogowany."
|
||||
msgid "You have been signed up successfully."
|
||||
msgstr "Zostałeś pomyślnie zarejestrowany."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:98
|
||||
msgid "You have been unsubscribed!"
|
||||
msgstr "Zostałeś wypisany!"
|
||||
|
||||
#: src/views/members/components/InviteMemberForm.tsx:326
|
||||
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
msgstr "Masz nielimitowaną liczbę miejsc w swoim planie Pro. Nie ma dodatkowych opłat za nowych członków!"
|
||||
@@ -2613,6 +2584,10 @@ msgstr "Twoje konto Trello zostało odłączone."
|
||||
msgid "Your Trello account is connected."
|
||||
msgstr "Twoje konto Trello jest połączone."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:33
|
||||
msgid "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
msgstr "Twój link do wypisania się nie zawiera tokena. Otwórz najnowszy e-mail i spróbuj ponownie."
|
||||
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
|
||||
msgid "Your workspace description has been updated."
|
||||
msgstr "Opis twojej przestrzeni roboczej został zaktualizowany."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,7 +22,7 @@ msgid ", or see our"
|
||||
msgstr ", или посмотрите наши"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#: src/views/boards/index.tsx:38
|
||||
#: src/views/boards/index.tsx:27
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
|
||||
@@ -30,7 +30,7 @@ msgstr "{0}"
|
||||
#. placeholder {0}: isTemplate ? "Templates" : "Boards"
|
||||
#. placeholder {1}: board?.name ?? t`Board`
|
||||
#. placeholder {1}: workspace.name ?? t`Workspace`
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/card/index.tsx:229
|
||||
msgid "{0} | {1}"
|
||||
msgstr "{0} | {1}"
|
||||
@@ -41,7 +41,7 @@ msgid "{0} labels"
|
||||
msgstr "{0} метки"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "Template" : "Board"
|
||||
#: src/views/board/index.tsx:400
|
||||
#: src/views/board/index.tsx:389
|
||||
msgid "{0} not found"
|
||||
msgstr "{0} не найден"
|
||||
|
||||
@@ -79,10 +79,6 @@ msgstr "Аккаунт"
|
||||
msgid "Account deleted"
|
||||
msgstr "Аккаунт удалён"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:55
|
||||
msgid "Actions"
|
||||
msgstr "Действия"
|
||||
|
||||
#: src/views/card/index.tsx:343
|
||||
#: src/views/public/board/CardModal.tsx:157
|
||||
msgid "Activity"
|
||||
@@ -312,7 +308,7 @@ msgstr "Портал выставления счетов"
|
||||
msgid "Blog Post"
|
||||
msgstr "Пост в блоге"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/card/index.tsx:229
|
||||
#: src/views/public/board/index.tsx:101
|
||||
msgid "Board"
|
||||
@@ -364,7 +360,7 @@ msgstr "Видимость доски"
|
||||
msgid "Board visibility updated"
|
||||
msgstr "Видимость доски обновлена"
|
||||
|
||||
#: src/components/SideNavigation.tsx:97
|
||||
#: src/components/SideNavigation.tsx:91
|
||||
msgid "Boards"
|
||||
msgstr "Доски"
|
||||
|
||||
@@ -498,6 +494,10 @@ msgstr "завершил элемент контрольного списка"
|
||||
msgid "completed checklist item <0>{0}</0>"
|
||||
msgstr "завершил элемент контрольного списка <0>{0}</0>"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:81
|
||||
msgid "Confirm your email preferences:"
|
||||
msgstr "Подтвердите ваши настройки электронной почты:"
|
||||
|
||||
#: src/views/settings/components/ChangePasswordConfirmation.tsx:150
|
||||
msgid "Confirm your new password"
|
||||
msgstr "Подтвердите ваш новый пароль"
|
||||
@@ -582,7 +582,6 @@ msgstr "Создать список"
|
||||
|
||||
#. placeholder {0}: isTemplate ? "template" : "board"
|
||||
#: src/views/boards/components/BoardsList.tsx:45
|
||||
#: src/views/boards/index.tsx:26
|
||||
msgid "Create new {0}"
|
||||
msgstr "Создать новый {0}"
|
||||
|
||||
@@ -595,8 +594,7 @@ msgstr "Создать новый ключ"
|
||||
msgid "Create new label"
|
||||
msgstr "Создать новую метку"
|
||||
|
||||
#: src/views/board/index.tsx:64
|
||||
#: src/views/board/index.tsx:491
|
||||
#: src/views/board/index.tsx:478
|
||||
msgid "Create new list"
|
||||
msgstr "Создать новый список"
|
||||
|
||||
@@ -605,7 +603,7 @@ msgid "Create template"
|
||||
msgstr "Создать шаблон"
|
||||
|
||||
#: src/components/NewWorkspaceForm.tsx:387
|
||||
#: src/components/WorkspaceMenu.tsx:153
|
||||
#: src/components/WorkspaceMenu.tsx:149
|
||||
msgid "Create workspace"
|
||||
msgstr "Создать рабочее пространство"
|
||||
|
||||
@@ -655,7 +653,7 @@ msgstr "Пользовательский URL рабочего пространс
|
||||
msgid "Customer Support"
|
||||
msgstr "Служба поддержки"
|
||||
|
||||
#: src/components/UserMenu.tsx:155
|
||||
#: src/components/UserMenu.tsx:153
|
||||
msgid "Dark"
|
||||
msgstr "Тёмный"
|
||||
|
||||
@@ -754,6 +752,10 @@ msgstr "Отображаемое имя обновлено"
|
||||
msgid "Do you offer a free plan?"
|
||||
msgstr "Вы предлагаете бесплатный план?"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:78
|
||||
msgid "Do you want to unsubscribe?"
|
||||
msgstr "Вы хотите отписаться?"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:109
|
||||
msgid "docs"
|
||||
msgstr "документы"
|
||||
@@ -762,7 +764,7 @@ msgstr "документы"
|
||||
msgid "Docs"
|
||||
msgstr "Документы"
|
||||
|
||||
#: src/components/UserMenu.tsx:206
|
||||
#: src/components/UserMenu.tsx:191
|
||||
#: src/views/boards/components/TemplateBoards.tsx:24
|
||||
#: src/views/home/components/Footer.tsx:78
|
||||
#: src/views/home/components/Header.tsx:36
|
||||
@@ -986,7 +988,7 @@ msgid "Features"
|
||||
msgstr "Функции"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:59
|
||||
#: src/components/UserMenu.tsx:214
|
||||
#: src/components/UserMenu.tsx:199
|
||||
msgid "Feedback"
|
||||
msgstr "Обратная связь"
|
||||
|
||||
@@ -1029,10 +1031,6 @@ msgstr "Полный рабочий день"
|
||||
msgid "Fun"
|
||||
msgstr "Веселье"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:53
|
||||
msgid "General"
|
||||
msgstr "Общие"
|
||||
|
||||
#: src/views/auth/signup/index.tsx:69
|
||||
#: src/views/home/components/Cta.tsx:61
|
||||
#: src/views/home/components/Header.tsx:106
|
||||
@@ -1052,7 +1050,7 @@ msgstr "Начать"
|
||||
msgid "Get started by creating a new {0}"
|
||||
msgstr "Начните с создания нового {0}"
|
||||
|
||||
#: src/views/board/index.tsx:483
|
||||
#: src/views/board/index.tsx:470
|
||||
msgid "Get started by creating a new list"
|
||||
msgstr "Начните с создания нового списка"
|
||||
|
||||
@@ -1086,22 +1084,6 @@ msgstr "На главную"
|
||||
msgid "Go to app"
|
||||
msgstr "Перейти в приложение"
|
||||
|
||||
#: src/components/SideNavigation.tsx:105
|
||||
msgid "Go to boards"
|
||||
msgstr "Перейти к доскам"
|
||||
|
||||
#: src/components/SideNavigation.tsx:129
|
||||
msgid "Go to members"
|
||||
msgstr "Перейти к участникам"
|
||||
|
||||
#: src/components/SideNavigation.tsx:141
|
||||
msgid "Go to settings"
|
||||
msgstr "Перейти к настройкам"
|
||||
|
||||
#: src/components/SideNavigation.tsx:117
|
||||
msgid "Go to templates"
|
||||
msgstr "Перейти к шаблонам"
|
||||
|
||||
#: src/views/boards/components/TemplateBoards.tsx:18
|
||||
msgid "High Priority"
|
||||
msgstr "Высокий приоритет"
|
||||
@@ -1151,7 +1133,7 @@ msgstr "Идеи"
|
||||
msgid "Ideas to improve this page..."
|
||||
msgstr "Идеи для улучшения этой страницы..."
|
||||
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/boards/index.tsx:39
|
||||
msgid "Import"
|
||||
msgstr "Импорт"
|
||||
|
||||
@@ -1282,10 +1264,6 @@ msgstr "Канбан переосмыслен"
|
||||
msgid "Keep in mind that this action is irreversible."
|
||||
msgstr "Имейте в виду, что это действие необратимо."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:320
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Горячие клавиши"
|
||||
|
||||
#: src/views/board/components/Filters.tsx:115
|
||||
#: src/views/board/components/NewCardForm.tsx:409
|
||||
#: src/views/card/index.tsx:119
|
||||
@@ -1334,7 +1312,7 @@ msgstr "Юридическое"
|
||||
msgid "License"
|
||||
msgstr "Лицензия"
|
||||
|
||||
#: src/components/UserMenu.tsx:169
|
||||
#: src/components/UserMenu.tsx:167
|
||||
msgid "Light"
|
||||
msgstr "Светлый"
|
||||
|
||||
@@ -1358,7 +1336,7 @@ msgstr "Списки"
|
||||
msgid "Login | kan.bn"
|
||||
msgstr "Вход | kan.bn"
|
||||
|
||||
#: src/components/UserMenu.tsx:224
|
||||
#: src/components/UserMenu.tsx:209
|
||||
msgid "Logout"
|
||||
msgstr "Выход"
|
||||
|
||||
@@ -1395,7 +1373,7 @@ msgstr "отметил элемент контрольного списка <0>{
|
||||
msgid "Medium Priority"
|
||||
msgstr "Средний приоритет"
|
||||
|
||||
#: src/components/SideNavigation.tsx:121
|
||||
#: src/components/SideNavigation.tsx:101
|
||||
#: src/views/board/components/Filters.tsx:107
|
||||
#: src/views/board/components/NewCardForm.tsx:367
|
||||
#: src/views/card/index.tsx:128
|
||||
@@ -1433,15 +1411,11 @@ msgstr "переместил карточку в другой список"
|
||||
msgid "Name"
|
||||
msgstr "Имя"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:54
|
||||
msgid "Navigation"
|
||||
msgstr "Навигация"
|
||||
|
||||
#: src/components/FeedbackModal.tsx:95
|
||||
msgid "Need help?"
|
||||
msgstr "Нужна помощь?"
|
||||
|
||||
#: src/views/boards/index.tsx:62
|
||||
#: src/views/boards/index.tsx:50
|
||||
#: src/views/home/components/Features.tsx:73
|
||||
msgid "New"
|
||||
msgstr "Новый"
|
||||
@@ -1472,7 +1446,7 @@ msgid "New label"
|
||||
msgstr "Новая метка"
|
||||
|
||||
#: src/views/board/components/NewListForm.tsx:113
|
||||
#: src/views/board/index.tsx:454
|
||||
#: src/views/board/index.tsx:442
|
||||
msgid "New list"
|
||||
msgstr "Новый список"
|
||||
|
||||
@@ -1525,11 +1499,7 @@ msgstr "Кредитная карта не требуется"
|
||||
msgid "No download URL available for this attachment."
|
||||
msgstr "URL для загрузки этого вложения недоступен."
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:333
|
||||
msgid "No keyboard shortcuts registered."
|
||||
msgstr "Горячие клавиши не зарегистрированы."
|
||||
|
||||
#: src/views/board/index.tsx:480
|
||||
#: src/views/board/index.tsx:467
|
||||
msgid "No lists"
|
||||
msgstr "Нет списков"
|
||||
|
||||
@@ -1553,14 +1523,6 @@ msgstr "После удаления аккаунта возврат будет
|
||||
msgid "Once you delete your workspace, there is no going back. This action cannot be undone."
|
||||
msgstr "После удаления рабочего пространства возврат будет невозможен. Это действие необратимо."
|
||||
|
||||
#: src/components/WorkspaceMenu.tsx:31
|
||||
msgid "Open command menu"
|
||||
msgstr "Открыть меню команд"
|
||||
|
||||
#: src/providers/keyboard-shortcuts.tsx:171
|
||||
msgid "Open keyboard shortcuts"
|
||||
msgstr "Открыть горячие клавиши"
|
||||
|
||||
#: src/views/pricing/components/FeatureComparisonTable.tsx:150
|
||||
msgid "Open source"
|
||||
msgstr "С открытым исходным кодом"
|
||||
@@ -1676,8 +1638,8 @@ msgstr "Пожалуйста, выберите файл для загрузки.
|
||||
#: src/views/board/components/NewTemplateForm.tsx:77
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:73
|
||||
#: src/views/board/components/VisibilityButton.tsx:54
|
||||
#: src/views/board/index.tsx:162
|
||||
#: src/views/board/index.tsx:218
|
||||
#: src/views/board/index.tsx:151
|
||||
#: src/views/board/index.tsx:207
|
||||
#: src/views/boards/components/ImportBoardsForm.tsx:205
|
||||
#: src/views/card/components/AttachmentThumbnails.tsx:73
|
||||
#: src/views/card/components/ChecklistItemRow.tsx:60
|
||||
@@ -1910,7 +1872,7 @@ msgid "Senior"
|
||||
msgstr "Старший"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:82
|
||||
#: src/components/SideNavigation.tsx:133
|
||||
#: src/components/SideNavigation.tsx:106
|
||||
msgid "Settings"
|
||||
msgstr "Настройки"
|
||||
|
||||
@@ -1934,10 +1896,6 @@ msgstr "Настройки | Интеграции"
|
||||
msgid "Settings | Workspace"
|
||||
msgstr "Настройки | Рабочая область"
|
||||
|
||||
#: src/components/UserMenu.tsx:184
|
||||
msgid "Shortcuts"
|
||||
msgstr "Сочетания клавиш"
|
||||
|
||||
#: src/views/home/components/Header.tsx:104
|
||||
msgid "Sign in"
|
||||
msgstr "Войти"
|
||||
@@ -2006,7 +1964,7 @@ msgstr "Успех"
|
||||
msgid "Supercharge your workspace for just $29/month. Here's what you'll get:"
|
||||
msgstr "Улучшите свою рабочую область всего за $29/месяц. Вот что вы получите:"
|
||||
|
||||
#: src/components/UserMenu.tsx:195
|
||||
#: src/components/UserMenu.tsx:180
|
||||
msgid "Support"
|
||||
msgstr "Поддержка"
|
||||
|
||||
@@ -2015,7 +1973,7 @@ msgstr "Поддержка"
|
||||
msgid "Support the development of the project"
|
||||
msgstr "Поддержите развитие проекта"
|
||||
|
||||
#: src/components/UserMenu.tsx:141
|
||||
#: src/components/UserMenu.tsx:139
|
||||
msgid "System"
|
||||
msgstr "Система"
|
||||
|
||||
@@ -2030,8 +1988,8 @@ msgstr "Командный план"
|
||||
msgid "Teams"
|
||||
msgstr "Команды"
|
||||
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/board/index.tsx:409
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/board/index.tsx:398
|
||||
msgid "Template"
|
||||
msgstr "Шаблон"
|
||||
|
||||
@@ -2051,7 +2009,7 @@ msgstr "Имя шаблона не может превышать 100 симво
|
||||
msgid "Template name is required"
|
||||
msgstr "Имя шаблона обязательно"
|
||||
|
||||
#: src/components/SideNavigation.tsx:109
|
||||
#: src/components/SideNavigation.tsx:96
|
||||
#: src/views/home/components/Features.tsx:115
|
||||
msgid "Templates"
|
||||
msgstr "Шаблоны"
|
||||
@@ -2085,7 +2043,7 @@ msgstr "Альтернатива Trello с открытым исходным к
|
||||
msgid "The visibility of your board has been set to {0}."
|
||||
msgstr "Видимость вашей доски установлена на {0}."
|
||||
|
||||
#: src/components/UserMenu.tsx:128
|
||||
#: src/components/UserMenu.tsx:126
|
||||
msgid "Theme"
|
||||
msgstr "Тема"
|
||||
|
||||
@@ -2236,7 +2194,7 @@ msgstr "Не удалось обновить URL доски"
|
||||
msgid "Unable to update board visibility"
|
||||
msgstr "Не удалось обновить видимость доски"
|
||||
|
||||
#: src/views/board/index.tsx:217
|
||||
#: src/views/board/index.tsx:206
|
||||
#: src/views/card/index.tsx:176
|
||||
msgid "Unable to update card"
|
||||
msgstr "Не удалось обновить карточку"
|
||||
@@ -2257,7 +2215,7 @@ msgstr "Не удалось обновить комментарий"
|
||||
msgid "Unable to update labels"
|
||||
msgstr "Не удалось обновить метки"
|
||||
|
||||
#: src/views/board/index.tsx:161
|
||||
#: src/views/board/index.tsx:150
|
||||
#: src/views/card/components/ListSelector.tsx:51
|
||||
msgid "Unable to update list"
|
||||
msgstr "Не удалось обновить список"
|
||||
@@ -2313,6 +2271,11 @@ msgstr "Неограниченное количество участников"
|
||||
msgid "Unlimited workspaces"
|
||||
msgstr "Неограниченное количество рабочих пространств"
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:68
|
||||
#: src/pages/unsubscribe/index.tsx:93
|
||||
msgid "Unsubscribe"
|
||||
msgstr "Отписаться"
|
||||
|
||||
#: src/views/board/components/UpdateBoardSlugForm.tsx:175
|
||||
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
|
||||
@@ -2342,7 +2305,7 @@ msgstr "обновлен заголовок"
|
||||
msgid "updated the title to <0>{0}</0>"
|
||||
msgstr "обновлен заголовок на <0>{0}</0>"
|
||||
|
||||
#: src/components/SideNavigation.tsx:237
|
||||
#: src/components/SideNavigation.tsx:202
|
||||
#: src/views/settings/components/UpgradeToProConfirmation.tsx:53
|
||||
#: src/views/settings/WorkspaceSettings.tsx:90
|
||||
msgid "Upgrade to Pro"
|
||||
@@ -2426,6 +2389,10 @@ msgstr "Видимость"
|
||||
msgid "We are using the <0>AGPL-3.0 license</0>."
|
||||
msgstr "Мы используем лицензию <0>AGPL-3.0</0>."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:63
|
||||
msgid "We couldn't update your preferences. Please try again."
|
||||
msgstr "Мы не смогли обновить ваши настройки. Пожалуйста, попробуйте снова."
|
||||
|
||||
#: src/views/home/components/Features.tsx:152
|
||||
msgid "We're just getting started. "
|
||||
msgstr "Мы только начинаем. "
|
||||
@@ -2455,8 +2422,8 @@ msgid "Why make an open source Trello?"
|
||||
msgstr "Зачем создавать Trello с открытым исходным кодом?"
|
||||
|
||||
#: src/components/SettingsLayout.tsx:39
|
||||
#: src/views/board/index.tsx:374
|
||||
#: src/views/boards/index.tsx:33
|
||||
#: src/views/board/index.tsx:363
|
||||
#: src/views/boards/index.tsx:22
|
||||
#: src/views/members/index.tsx:173
|
||||
#: src/views/public/board/index.tsx:101
|
||||
#: src/views/public/boards/index.tsx:66
|
||||
@@ -2564,6 +2531,10 @@ msgstr "Вы успешно вошли в систему."
|
||||
msgid "You have been signed up successfully."
|
||||
msgstr "Вы успешно зарегистрировались."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:98
|
||||
msgid "You have been unsubscribed!"
|
||||
msgstr "Вы успешно отписались!"
|
||||
|
||||
#: src/views/members/components/InviteMemberForm.tsx:326
|
||||
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
|
||||
msgstr "В вашем профессиональном плане неограниченное количество мест. За новых участников дополнительная плата не взимается!"
|
||||
@@ -2608,6 +2579,10 @@ msgstr "Ваш аккаунт Trello был отключён."
|
||||
msgid "Your Trello account is connected."
|
||||
msgstr "Ваш аккаунт Trello подключён."
|
||||
|
||||
#: src/pages/unsubscribe/index.tsx:33
|
||||
msgid "Your unsubscribe link is missing a token. Please open the latest email and try again."
|
||||
msgstr "В вашей ссылке для отписки отсутствует токен. Пожалуйста, откройте последнее письмо и попробуйте снова."
|
||||
|
||||
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
|
||||
msgid "Your workspace description has been updated."
|
||||
msgstr "Описание вашего рабочего пространства было обновлено."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -12,6 +12,7 @@ import posthog from "posthog-js";
|
||||
import { PostHogProvider } from "posthog-js/react";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { KeyboardShortcutProvider } from "~/providers/keyboard-shortcuts";
|
||||
import { LinguiProviderWrapper } from "~/providers/lingui";
|
||||
import { ModalProvider } from "~/providers/modal";
|
||||
import { PopupProvider } from "~/providers/popup";
|
||||
@@ -80,21 +81,23 @@ const MyApp: AppType = ({ Component, pageProps }: AppPropsWithLayout) => {
|
||||
)}
|
||||
<script src="/__ENV.js" />
|
||||
<main className="font-sans">
|
||||
<LinguiProviderWrapper>
|
||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
<ModalProvider>
|
||||
<PopupProvider>
|
||||
{posthogKey ? (
|
||||
<PostHogProvider client={posthog}>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</PostHogProvider>
|
||||
) : (
|
||||
getLayout(<Component {...pageProps} />)
|
||||
)}
|
||||
</PopupProvider>
|
||||
</ModalProvider>
|
||||
</ThemeProvider>
|
||||
</LinguiProviderWrapper>
|
||||
<KeyboardShortcutProvider>
|
||||
<LinguiProviderWrapper>
|
||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
<ModalProvider>
|
||||
<PopupProvider>
|
||||
{posthogKey ? (
|
||||
<PostHogProvider client={posthog}>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</PostHogProvider>
|
||||
) : (
|
||||
getLayout(<Component {...pageProps} />)
|
||||
)}
|
||||
</PopupProvider>
|
||||
</ModalProvider>
|
||||
</ThemeProvider>
|
||||
</LinguiProviderWrapper>
|
||||
</KeyboardShortcutProvider>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -17,12 +17,11 @@ export default async function handler(
|
||||
}
|
||||
|
||||
try {
|
||||
const downloadUrl = decodeURIComponent(url);
|
||||
const downloadFilename =
|
||||
(typeof filename === "string" ? decodeURIComponent(filename) : null) ??
|
||||
"attachment";
|
||||
const downloadFilename = typeof filename === "string"
|
||||
? encodeURIComponent(filename)
|
||||
: "attachment";
|
||||
|
||||
const upstream = await fetch(downloadUrl);
|
||||
const upstream = await fetch(url);
|
||||
|
||||
if (!upstream.ok) {
|
||||
return res.status(upstream.status).json({
|
||||
@@ -36,7 +35,7 @@ export default async function handler(
|
||||
res.setHeader("Content-Type", contentType);
|
||||
res.setHeader(
|
||||
"Content-Disposition",
|
||||
`attachment; filename="${downloadFilename}"`,
|
||||
`attachment; filename="${downloadFilename}"; filename*=UTF-8''${downloadFilename}`,
|
||||
);
|
||||
|
||||
const buffer = await upstream.arrayBuffer();
|
||||
|
||||
104
apps/web/src/pages/api/unsubscribe.ts
Normal file
104
apps/web/src/pages/api/unsubscribe.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { Novu } from "@novu/api";
|
||||
import { jwtVerify } from "jose";
|
||||
import { z } from "zod";
|
||||
|
||||
import { env } from "~/env";
|
||||
|
||||
const requestSchema = z.object({
|
||||
token: z.string().min(1),
|
||||
});
|
||||
|
||||
const tokenPayloadSchema = z.object({
|
||||
subscriberId: z.string(),
|
||||
});
|
||||
|
||||
type ResponseData =
|
||||
| { success: true }
|
||||
| { success: false; error: string; code?: string };
|
||||
|
||||
const textEncoder = new TextEncoder();
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<ResponseData>,
|
||||
) {
|
||||
if (process.env.NEXT_PUBLIC_KAN_ENV !== "cloud") {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: "Unsubscribe endpoint is not available.",
|
||||
code: "UNAVAILABLE",
|
||||
});
|
||||
}
|
||||
|
||||
if (req.method !== "POST") {
|
||||
res.setHeader("Allow", "POST");
|
||||
return res.status(405).json({
|
||||
success: false,
|
||||
error: "Method not allowed.",
|
||||
code: "METHOD_NOT_ALLOWED",
|
||||
});
|
||||
}
|
||||
|
||||
const parsedBody = requestSchema.safeParse(req.body);
|
||||
|
||||
if (!parsedBody.success) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: "Invalid request payload.",
|
||||
code: "BAD_REQUEST",
|
||||
});
|
||||
}
|
||||
|
||||
if (!env.EMAIL_UNSUBSCRIBE_SECRET || !env.NOVU_API_KEY) {
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
error: "Unsubscribe service is not configured.",
|
||||
code: "NOT_CONFIGURED",
|
||||
});
|
||||
}
|
||||
|
||||
let payload: z.infer<typeof tokenPayloadSchema>;
|
||||
|
||||
try {
|
||||
const verified = await jwtVerify(
|
||||
parsedBody.data.token,
|
||||
textEncoder.encode(env.EMAIL_UNSUBSCRIBE_SECRET),
|
||||
{
|
||||
// We intentionally do not use exp/iat claims –
|
||||
// tokens are long-lived and validated only by signature + payload.
|
||||
clockTolerance: "0s",
|
||||
},
|
||||
);
|
||||
payload = tokenPayloadSchema.parse(verified.payload);
|
||||
} catch {
|
||||
return res.status(401).json({
|
||||
success: false,
|
||||
error: "Your unsubscribe link is invalid or has expired.",
|
||||
code: "INVALID_TOKEN",
|
||||
});
|
||||
}
|
||||
|
||||
const novu = new Novu({ secretKey: env.NOVU_API_KEY });
|
||||
|
||||
try {
|
||||
await novu.subscribers.preferences.update(
|
||||
{
|
||||
channels: {
|
||||
email: false,
|
||||
},
|
||||
},
|
||||
payload.subscriberId,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Failed to update Novu preferences", error);
|
||||
return res.status(502).json({
|
||||
success: false,
|
||||
error:
|
||||
"We could not update your email preferences right now. Please try again later.",
|
||||
code: "NOVU_ERROR",
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).json({ success: true });
|
||||
}
|
||||
110
apps/web/src/pages/unsubscribe/index.tsx
Normal file
110
apps/web/src/pages/unsubscribe/index.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { t } from "@lingui/core/macro";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import Button from "~/components/Button";
|
||||
import { PageHead } from "~/components/PageHead";
|
||||
import PatternedBackground from "~/components/PatternedBackground";
|
||||
|
||||
type UnsubscribeStatus = "idle" | "processing" | "success" | "error";
|
||||
|
||||
export default function UnsubscribePage() {
|
||||
const router = useRouter();
|
||||
const [token, setToken] = useState("");
|
||||
const [status, setStatus] = useState<UnsubscribeStatus>("idle");
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!router.isReady) return;
|
||||
const value = router.query.token;
|
||||
if (typeof value === "string") {
|
||||
setToken(value);
|
||||
} else if (Array.isArray(value)) {
|
||||
setToken(value[0] ?? "");
|
||||
} else {
|
||||
setToken("");
|
||||
}
|
||||
}, [router.isReady, router.query.token]);
|
||||
|
||||
const handleUnsubscribe = async () => {
|
||||
if (!token) {
|
||||
setStatus("error");
|
||||
setErrorMessage(
|
||||
t`Your unsubscribe link is missing a token. Please open the latest email and try again.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus("processing");
|
||||
setErrorMessage(null);
|
||||
|
||||
try {
|
||||
const response = await fetch("/api/unsubscribe", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ token }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = (await response.json().catch(() => null)) as {
|
||||
error?: string;
|
||||
} | null;
|
||||
|
||||
throw new Error(
|
||||
payload?.error ??
|
||||
"We couldn't update your preferences. Please try again.",
|
||||
);
|
||||
}
|
||||
|
||||
setStatus("success");
|
||||
} catch (error) {
|
||||
setStatus("error");
|
||||
setErrorMessage(
|
||||
t`We couldn't update your preferences. Please try again.`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const title = t`Unsubscribe`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHead title={`${title} | kan.bn`} />
|
||||
<div className="relative flex min-h-screen items-center justify-center px-4 py-12 sm:px-6 lg:px-8">
|
||||
<PatternedBackground />
|
||||
<div className="z-10 w-full max-w-md space-y-6">
|
||||
<div>
|
||||
<h1 className="mt-6 text-center text-3xl font-bold tracking-tight text-light-1000 dark:text-dark-1000">
|
||||
{t`Do you want to unsubscribe?`}
|
||||
</h1>
|
||||
<p className="mt-4 text-center text-sm text-light-900 dark:text-dark-800">
|
||||
{t`Confirm your email preferences:`}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Button
|
||||
onClick={handleUnsubscribe}
|
||||
disabled={status === "success"}
|
||||
isLoading={status === "processing"}
|
||||
variant="primary"
|
||||
size="md"
|
||||
>
|
||||
{t`Unsubscribe`}
|
||||
</Button>
|
||||
</div>
|
||||
{status === "success" && (
|
||||
<p className="text-center text-sm text-light-900 dark:text-dark-800">
|
||||
{t`You have been unsubscribed!`}
|
||||
</p>
|
||||
)}
|
||||
{status === "error" && (
|
||||
<p className="mx-auto max-w-[300px] text-center text-sm font-medium text-red-600 dark:text-red-400">
|
||||
{errorMessage}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
592
apps/web/src/providers/keyboard-shortcuts.tsx
Normal file
592
apps/web/src/providers/keyboard-shortcuts.tsx
Normal file
@@ -0,0 +1,592 @@
|
||||
import type { ReactNode } from "react";
|
||||
import {
|
||||
Dialog,
|
||||
DialogBackdrop,
|
||||
DialogPanel,
|
||||
DialogTitle,
|
||||
} from "@headlessui/react";
|
||||
import { t } from "@lingui/core/macro";
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { HiXMark } from "react-icons/hi2";
|
||||
|
||||
import { env } from "~/env";
|
||||
import { useEventListener } from "~/hooks/useEventListener";
|
||||
|
||||
const ModifierKey = {
|
||||
CONTROL: "CONTROL",
|
||||
META: "META",
|
||||
ALT: "ALT",
|
||||
SHIFT: "SHIFT",
|
||||
} as const;
|
||||
type ModifierKey = (typeof ModifierKey)[keyof typeof ModifierKey];
|
||||
|
||||
const ModifierKeyInfo: Record<
|
||||
ModifierKey,
|
||||
{
|
||||
macSymbol: string;
|
||||
winName: string;
|
||||
linuxName: string;
|
||||
}
|
||||
> = {
|
||||
CONTROL: { macSymbol: "⌃", winName: "Ctrl", linuxName: "Ctrl" },
|
||||
META: { macSymbol: "⌘", winName: "Win", linuxName: "Super" },
|
||||
ALT: { macSymbol: "⌥", winName: "Alt", linuxName: "Alt" },
|
||||
SHIFT: { macSymbol: "⇧", winName: "Shift", linuxName: "Shift" },
|
||||
};
|
||||
|
||||
const ShortcutGroup = {
|
||||
GENERAL: "GENERAL",
|
||||
NAVIGATION: "NAVIGATION",
|
||||
ACTIONS: "ACTIONS",
|
||||
} as const;
|
||||
type ShortcutGroup = (typeof ShortcutGroup)[keyof typeof ShortcutGroup];
|
||||
|
||||
const getShortcutGroupInfo = (): Record<ShortcutGroup, { label: string }> => ({
|
||||
GENERAL: { label: t`General` },
|
||||
NAVIGATION: { label: t`Navigation` },
|
||||
ACTIONS: { label: t`Actions` },
|
||||
});
|
||||
|
||||
interface KeyStroke {
|
||||
key: string;
|
||||
modifiers?: ModifierKey[];
|
||||
}
|
||||
|
||||
interface Press {
|
||||
type: "PRESS";
|
||||
stroke: KeyStroke;
|
||||
}
|
||||
|
||||
interface Sequence {
|
||||
type: "SEQUENCE";
|
||||
strokes: KeyStroke[];
|
||||
}
|
||||
|
||||
export type KeyboardShortcut = {
|
||||
action: () => void;
|
||||
description: string;
|
||||
group: ShortcutGroup;
|
||||
} & (Press | Sequence);
|
||||
|
||||
interface ShortcutTreeStepNode {
|
||||
type: "STEP";
|
||||
children: ShortcutTreeLevel;
|
||||
}
|
||||
interface ShortcutTreeActionNode {
|
||||
type: "ACTION";
|
||||
shortcut: KeyboardShortcut;
|
||||
}
|
||||
type ShortcutTreeNode = ShortcutTreeStepNode | ShortcutTreeActionNode;
|
||||
type ShortcutTreeLevel = Record<string, ShortcutTreeNode>;
|
||||
|
||||
const SEQUENCE_TIMEOUT_MS = 1000;
|
||||
|
||||
const ShortcutConflictCode = {
|
||||
ACTION_ON_SEQUENCE: "ACTION_ON_SEQUENCE",
|
||||
DUPLICATE_ACTION: "DUPLICATE_ACTION",
|
||||
SEQUENCE_ON_ACTION: "SEQUENCE_ON_ACTION",
|
||||
} as const;
|
||||
type ShortcutConflictCode = keyof typeof ShortcutConflictCode;
|
||||
|
||||
interface ShortcutConflictErrorOptions {
|
||||
code: ShortcutConflictCode;
|
||||
shortcut: KeyboardShortcut;
|
||||
conflictPath: string;
|
||||
existingShortcut?: KeyboardShortcut;
|
||||
}
|
||||
|
||||
class ShortcutConflictError extends Error {
|
||||
public readonly code: ShortcutConflictCode;
|
||||
public readonly shortcut: KeyboardShortcut;
|
||||
public readonly conflictPath: string;
|
||||
public readonly existingShortcut?: KeyboardShortcut;
|
||||
|
||||
constructor(options: ShortcutConflictErrorOptions) {
|
||||
super(ShortcutConflictError.formatMessage(options));
|
||||
this.name = "ShortcutConflictError";
|
||||
this.code = options.code;
|
||||
this.shortcut = options.shortcut;
|
||||
this.conflictPath = options.conflictPath;
|
||||
this.existingShortcut = options.existingShortcut;
|
||||
}
|
||||
|
||||
private static stringifyShortcut(shortcut: KeyboardShortcut): string {
|
||||
if (shortcut.type === "SEQUENCE") {
|
||||
return shortcut.strokes.map(serializeKeyStroke).join(" → ");
|
||||
}
|
||||
return serializeKeyStroke(shortcut.stroke);
|
||||
}
|
||||
|
||||
private static formatMessage(options: ShortcutConflictErrorOptions): string {
|
||||
const formatted = ShortcutConflictError.stringifyShortcut(options.shortcut);
|
||||
switch (options.code) {
|
||||
case ShortcutConflictCode.ACTION_ON_SEQUENCE:
|
||||
return `Cannot register "${formatted}": desired action conflicts with existing sequence at "${options.conflictPath}"`;
|
||||
case ShortcutConflictCode.DUPLICATE_ACTION:
|
||||
return `Cannot register "${formatted}": action already registered`;
|
||||
case ShortcutConflictCode.SEQUENCE_ON_ACTION:
|
||||
return `Cannot register "${formatted}": desired sequence conflicts with existing action at "${options.conflictPath}"`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface KeyboardShortcutContextType {
|
||||
registerShortcut: (shortcut: KeyboardShortcut) => () => void;
|
||||
openLegend: () => void;
|
||||
openLegendKeys: ReactNode;
|
||||
}
|
||||
|
||||
const KeyboardShortcutContext = createContext<
|
||||
KeyboardShortcutContextType | undefined
|
||||
>(undefined);
|
||||
|
||||
export function KeyboardShortcutProvider({
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const treeRootRef = useRef<ShortcutTreeLevel>({});
|
||||
const currentNodeRef = useRef<ShortcutTreeLevel>(treeRootRef.current);
|
||||
const shortcutsRef = useRef<Map<string, KeyboardShortcut>>(new Map());
|
||||
const sequenceTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const [isLegendOpen, setIsLegendOpen] = useState(false);
|
||||
|
||||
const openLegendShortcut: KeyboardShortcut = useMemo(
|
||||
() => ({
|
||||
type: "PRESS",
|
||||
stroke: {
|
||||
key: "/",
|
||||
modifiers: ["META"],
|
||||
},
|
||||
action: () => setIsLegendOpen(true),
|
||||
description: t`Open keyboard shortcuts`,
|
||||
group: ShortcutGroup.GENERAL,
|
||||
}),
|
||||
[setIsLegendOpen],
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback((event: KeyboardEvent) => {
|
||||
if (isTypingInInput(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sequenceTimeoutRef.current) {
|
||||
clearTimeout(sequenceTimeoutRef.current);
|
||||
sequenceTimeoutRef.current = null;
|
||||
}
|
||||
|
||||
const serializedKey = serializeEvent(event);
|
||||
const node = currentNodeRef.current[serializedKey];
|
||||
|
||||
if (!node) {
|
||||
currentNodeRef.current = treeRootRef.current;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
case "STEP":
|
||||
event.preventDefault();
|
||||
currentNodeRef.current = node.children;
|
||||
sequenceTimeoutRef.current = setTimeout(() => {
|
||||
currentNodeRef.current = treeRootRef.current;
|
||||
}, SEQUENCE_TIMEOUT_MS);
|
||||
return;
|
||||
case "ACTION":
|
||||
event.preventDefault();
|
||||
node.shortcut.action();
|
||||
currentNodeRef.current = treeRootRef.current;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const registerShortcut = useCallback(
|
||||
(shortcut: KeyboardShortcut): (() => void) => {
|
||||
const strokes =
|
||||
shortcut.type === "SEQUENCE" ? shortcut.strokes : [shortcut.stroke];
|
||||
|
||||
const path = strokes.map(serializeKeyStroke);
|
||||
const pathKey = path.join(" → ");
|
||||
|
||||
path.reduce((currentLevel, key, i) => {
|
||||
const isLast = i === path.length - 1;
|
||||
const existingNode = currentLevel[key];
|
||||
|
||||
if (env.NODE_ENV === "development" && existingNode) {
|
||||
const conflictPath = path.slice(0, i + 1).join(" → ");
|
||||
validateNoConflict(existingNode, isLast, shortcut, conflictPath);
|
||||
}
|
||||
|
||||
if (isLast) {
|
||||
currentLevel[key] = {
|
||||
type: "ACTION",
|
||||
shortcut,
|
||||
};
|
||||
return currentLevel;
|
||||
}
|
||||
|
||||
if (existingNode?.type === "STEP") {
|
||||
return existingNode.children;
|
||||
}
|
||||
|
||||
const newNode: ShortcutTreeStepNode = {
|
||||
type: "STEP",
|
||||
children: {},
|
||||
};
|
||||
currentLevel[key] = newNode;
|
||||
return newNode.children;
|
||||
}, treeRootRef.current);
|
||||
|
||||
shortcutsRef.current.set(pathKey, shortcut);
|
||||
|
||||
return () => {
|
||||
removePathAndPrune(treeRootRef.current, path);
|
||||
shortcutsRef.current.delete(pathKey);
|
||||
};
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
useEventListener("keydown", handleKeyDown);
|
||||
|
||||
// Register built-in shortcut to open legend
|
||||
useEffect(() => {
|
||||
const cleanup = registerShortcut(openLegendShortcut);
|
||||
return cleanup;
|
||||
}, [registerShortcut, openLegendShortcut]);
|
||||
|
||||
// Cleanup timeout on unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (sequenceTimeoutRef.current) {
|
||||
clearTimeout(sequenceTimeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const shortcutsArray = Array.from(shortcutsRef.current.values());
|
||||
const groupedShortcuts = shortcutsArray.reduce<
|
||||
Partial<Record<ShortcutGroup, KeyboardShortcut[]>>
|
||||
>((acc, shortcut) => {
|
||||
const group = shortcut.group;
|
||||
acc[group] ??= [];
|
||||
acc[group].push(shortcut);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const openLegend = useCallback(() => {
|
||||
setIsLegendOpen(true);
|
||||
}, []);
|
||||
|
||||
const openLegendKeys = useMemo(
|
||||
() => <FormattedShortcut shortcut={openLegendShortcut} />,
|
||||
[openLegendShortcut],
|
||||
);
|
||||
|
||||
return (
|
||||
<KeyboardShortcutContext.Provider
|
||||
value={{ registerShortcut, openLegend, openLegendKeys }}
|
||||
>
|
||||
{children}
|
||||
|
||||
{/* Shortcut Legend */}
|
||||
<Dialog
|
||||
className="relative z-50"
|
||||
open={isLegendOpen}
|
||||
onClose={() => setIsLegendOpen(false)}
|
||||
>
|
||||
<DialogBackdrop
|
||||
transition
|
||||
className="data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in fixed inset-0 bg-light-50 bg-opacity-40 transition-opacity dark:bg-dark-50 dark:bg-opacity-40"
|
||||
/>
|
||||
|
||||
<div className="fixed inset-0 flex min-h-full w-screen items-center justify-center overflow-y-auto p-4">
|
||||
<DialogPanel
|
||||
transition
|
||||
className="relative w-full max-w-sm transform overflow-hidden rounded-lg border border-light-600 bg-white shadow-3xl-light dark:border-dark-600 dark:bg-dark-100 dark:shadow-3xl-dark"
|
||||
>
|
||||
<div className="flex items-center justify-between border-b border-light-300 px-6 py-4 dark:border-dark-300">
|
||||
<DialogTitle className="text-[14px] font-semibold text-neutral-900 dark:text-dark-1000">
|
||||
{t`Keyboard Shortcuts`}
|
||||
</DialogTitle>
|
||||
<button
|
||||
onClick={() => setIsLegendOpen(false)}
|
||||
className="rounded p-1 hover:bg-light-200 dark:hover:bg-dark-200"
|
||||
>
|
||||
<HiXMark className="h-5 w-5 text-neutral-700 dark:text-dark-700" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="max-h-[60vh] overflow-y-auto p-6">
|
||||
{shortcutsArray.length === 0 ? (
|
||||
<p className="text-center text-sm text-neutral-600 dark:text-dark-600">
|
||||
{t`No keyboard shortcuts registered.`}
|
||||
</p>
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
{Object.values(ShortcutGroup).map((group, idx) => {
|
||||
const shortcuts = groupedShortcuts[group];
|
||||
if (!shortcuts?.length) return null;
|
||||
const groupInfo = getShortcutGroupInfo();
|
||||
return (
|
||||
<div key={`${group}-${idx}`}>
|
||||
<h3 className="mb-3 text-xs font-semibold uppercase tracking-wide text-light-1000 dark:text-dark-1000">
|
||||
{groupInfo[group].label}
|
||||
</h3>
|
||||
<div className="flex flex-col gap-y-2">
|
||||
{shortcuts.map((shortcut) => (
|
||||
<ShortcutListItem
|
||||
key={shortcut.description}
|
||||
shortcut={shortcut}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</DialogPanel>
|
||||
</div>
|
||||
</Dialog>
|
||||
</KeyboardShortcutContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to register a keyboard shortcut. Cleanup is handled automatically.
|
||||
* Returns both formatted keys and pre-built tooltip content.
|
||||
*
|
||||
* IMPORTANT: The shortcut object reference must be stable. If it changes
|
||||
* on every render, the shortcut will be continuously registered and unregistered.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* const { keys, tooltipContent } = useKeyboardShortcut({
|
||||
* type: "PRESS",
|
||||
* stroke: { key: "k", modifiers: ["META"] },
|
||||
* action: () => openCommandPalette(),
|
||||
* description: "Open command palette",
|
||||
* group: "GENERAL"
|
||||
* });
|
||||
*
|
||||
* // Use tooltip for Tooltip component
|
||||
* <Tooltip content={tooltipContent}>
|
||||
* <button>Search</button>
|
||||
* </Tooltip>
|
||||
*
|
||||
* // Or use keys directly for custom formatting
|
||||
* <span>Press {keys} to search</span>
|
||||
* ```
|
||||
*/
|
||||
export function useKeyboardShortcuts(): KeyboardShortcutContextType {
|
||||
const context = useContext(KeyboardShortcutContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"useKeyboardShortcuts must be used within KeyboardShortcutProvider",
|
||||
);
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
export function useKeyboardShortcut(shortcut: KeyboardShortcut): {
|
||||
keys: ReactNode;
|
||||
tooltipContent: ReactNode;
|
||||
} {
|
||||
const context = useContext(KeyboardShortcutContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"useKeyboardShortcut must be used within KeyboardShortcutProvider",
|
||||
);
|
||||
}
|
||||
|
||||
const { registerShortcut } = context;
|
||||
|
||||
useEffect(() => {
|
||||
const cleanup = registerShortcut(shortcut);
|
||||
return cleanup;
|
||||
}, [shortcut, registerShortcut]);
|
||||
|
||||
const keys = <FormattedShortcut shortcut={shortcut} />;
|
||||
const tooltipContent = (
|
||||
<div className="flex flex-row items-center gap-2 text-[11px]">
|
||||
{shortcut.description} {keys}
|
||||
</div>
|
||||
);
|
||||
|
||||
return { keys, tooltipContent };
|
||||
}
|
||||
|
||||
function ShortcutListItem({ shortcut }: { shortcut: KeyboardShortcut }) {
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="text-sm text-dark-50 dark:text-dark-900">
|
||||
{shortcut.description}
|
||||
</span>
|
||||
<FormattedShortcut shortcut={shortcut} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FormattedShortcut({ shortcut }: { shortcut: KeyboardShortcut }) {
|
||||
const kbdClassName =
|
||||
"inline-flex h-5 w-5 items-center justify-center rounded border border-light-400 bg-light-200 px-1.5 py-0.5 font-mono text-[8px] font-semibold text-center text-neutral-900 dark:border-dark-400 dark:bg-dark-200 dark:text-dark-950";
|
||||
|
||||
const stringifyModifier = (modifier: ModifierKey): string => {
|
||||
const isMac =
|
||||
typeof navigator !== "undefined" && navigator.userAgent.includes("Mac");
|
||||
const isLinux =
|
||||
typeof navigator !== "undefined" && navigator.userAgent.includes("Linux");
|
||||
|
||||
const info = ModifierKeyInfo[modifier];
|
||||
if (isMac) return info.macSymbol;
|
||||
if (isLinux) return info.linuxName;
|
||||
return info.winName;
|
||||
};
|
||||
|
||||
const formatStroke = (stroke: KeyStroke): ReactNode[] => {
|
||||
const parts: ReactNode[] = [];
|
||||
const modifierStrings = stroke.modifiers
|
||||
? stroke.modifiers.map(stringifyModifier)
|
||||
: [];
|
||||
|
||||
modifierStrings.forEach((mod) => {
|
||||
parts.push(<kbd className={kbdClassName}>{mod}</kbd>);
|
||||
});
|
||||
|
||||
parts.push(<kbd className={kbdClassName}>{stroke.key.toUpperCase()}</kbd>);
|
||||
|
||||
return parts;
|
||||
};
|
||||
|
||||
if (shortcut.type === "SEQUENCE") {
|
||||
const parts: ReactNode[] = [];
|
||||
shortcut.strokes.forEach((stroke) => {
|
||||
parts.push(...formatStroke(stroke));
|
||||
});
|
||||
return <span className="flex items-center gap-1 text-[11px]">{parts}</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="inline-flex flex-shrink-0 items-center gap-1 text-[11px]">
|
||||
{formatStroke(shortcut.stroke)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
/** Checks for conflicts given existing nodes and current path
|
||||
* Throws an error if conflict is found
|
||||
*
|
||||
*/
|
||||
function validateNoConflict(
|
||||
existingNode: ShortcutTreeNode,
|
||||
isLastKey: boolean,
|
||||
shortcut: KeyboardShortcut,
|
||||
conflictPath: string,
|
||||
): void {
|
||||
if (isLastKey) {
|
||||
if (existingNode.type === "STEP") {
|
||||
throw new ShortcutConflictError({
|
||||
code: ShortcutConflictCode.ACTION_ON_SEQUENCE,
|
||||
shortcut,
|
||||
conflictPath,
|
||||
});
|
||||
} else {
|
||||
throw new ShortcutConflictError({
|
||||
code: ShortcutConflictCode.DUPLICATE_ACTION,
|
||||
shortcut,
|
||||
conflictPath,
|
||||
existingShortcut: existingNode.shortcut,
|
||||
});
|
||||
}
|
||||
} else if (existingNode.type === "ACTION") {
|
||||
throw new ShortcutConflictError({
|
||||
code: ShortcutConflictCode.SEQUENCE_ON_ACTION,
|
||||
shortcut,
|
||||
conflictPath,
|
||||
existingShortcut: existingNode.shortcut,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user is currently typing in an input field
|
||||
*/
|
||||
function isTypingInInput(event: KeyboardEvent): boolean {
|
||||
if (!event.target) return false;
|
||||
|
||||
const target = event.target as HTMLElement;
|
||||
const tagName = target.tagName.toLowerCase();
|
||||
const isInput = tagName === "input" || tagName === "textarea";
|
||||
const isContentEditable = target.isContentEditable;
|
||||
|
||||
return isInput || isContentEditable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes a KeyStroke to a consistent string format
|
||||
* Returns lowercase string like "ctrl+shift+k" with alphabetically sorted modifiers
|
||||
*/
|
||||
function serializeKeyStroke(stroke: KeyStroke): string {
|
||||
const key = stroke.key.toLowerCase();
|
||||
if (!stroke.modifiers || stroke.modifiers.length === 0) return key;
|
||||
const sorted = [...stroke.modifiers].sort();
|
||||
return `${sorted.join("+")}+${key}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a keyboard event to a KeyStroke
|
||||
*/
|
||||
function eventToKeyStroke(event: KeyboardEvent): KeyStroke {
|
||||
const modifiers: ModifierKey[] = [];
|
||||
if (event.altKey) modifiers.push(ModifierKey.ALT);
|
||||
if (event.ctrlKey) modifiers.push(ModifierKey.CONTROL);
|
||||
if (event.metaKey) modifiers.push(ModifierKey.META);
|
||||
// Only include shift if the key is a letter (shift wasn't consumed to produce the character)
|
||||
if (event.shiftKey && /^[a-zA-Z]$/.test(event.key))
|
||||
modifiers.push(ModifierKey.SHIFT);
|
||||
return { key: event.key, modifiers };
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes a keyboard event to a consistent string format
|
||||
*/
|
||||
function serializeEvent(event: KeyboardEvent): string {
|
||||
return serializeKeyStroke(eventToKeyStroke(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a path from the tree and prunes empty branches
|
||||
*/
|
||||
function removePathAndPrune(tree: ShortcutTreeLevel, path: string[]): void {
|
||||
const [first, ...rest] = path;
|
||||
if (!first) return;
|
||||
|
||||
if (rest.length === 0) {
|
||||
delete tree[first];
|
||||
return;
|
||||
}
|
||||
|
||||
const node = tree[first];
|
||||
if (!node || node.type !== "STEP") return;
|
||||
|
||||
removePathAndPrune(node.children, rest);
|
||||
|
||||
if (Object.keys(node.children).length === 0) {
|
||||
delete tree[first];
|
||||
}
|
||||
}
|
||||
@@ -39,3 +39,17 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Tippy.js tooltip theme */
|
||||
.tippy-box[data-theme~="tooltip"] {
|
||||
@apply rounded-md border border-light-600 bg-white px-2 py-1 text-sm text-neutral-900 shadow-lg dark:border-dark-600 dark:bg-dark-100 dark:text-dark-1000;
|
||||
}
|
||||
|
||||
.tippy-box[data-theme~="tooltip"] > .tippy-arrow::before {
|
||||
@apply border-t-light-600 dark:border-t-dark-600;
|
||||
}
|
||||
|
||||
.tippy-box[data-theme~="tooltip"][data-placement^="bottom"]
|
||||
> .tippy-arrow::before {
|
||||
@apply border-b-light-600 dark:border-b-dark-600;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
|
||||
import { PageHead } from "~/components/PageHead";
|
||||
import PatternedBackground from "~/components/PatternedBackground";
|
||||
import { StrictModeDroppable as Droppable } from "~/components/StrictModeDroppable";
|
||||
import { Tooltip } from "~/components/Tooltip";
|
||||
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
|
||||
import { useModal } from "~/providers/modal";
|
||||
import { usePopup } from "~/providers/popup";
|
||||
import { useWorkspace } from "~/providers/workspace";
|
||||
@@ -54,6 +56,15 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
|
||||
useState<PublicListId>("");
|
||||
const [isInitialLoading, setIsInitialLoading] = useState(true);
|
||||
|
||||
const { tooltipContent: createListShortcutTooltipContent } =
|
||||
useKeyboardShortcut({
|
||||
type: "PRESS",
|
||||
stroke: { key: "C" },
|
||||
action: () => boardId && openNewListForm(boardId),
|
||||
description: t`Create new list`,
|
||||
group: "ACTIONS",
|
||||
});
|
||||
|
||||
const boardId = params?.boardId
|
||||
? Array.isArray(params.boardId)
|
||||
? params.boardId[0]
|
||||
@@ -427,20 +438,22 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
iconLeft={
|
||||
<HiOutlinePlusSmall
|
||||
className="-mr-0.5 h-5 w-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
}
|
||||
onClick={() => {
|
||||
if (boardId) openNewListForm(boardId);
|
||||
}}
|
||||
disabled={!boardData}
|
||||
>
|
||||
{t`New list`}
|
||||
</Button>
|
||||
<Tooltip content={createListShortcutTooltipContent}>
|
||||
<Button
|
||||
iconLeft={
|
||||
<HiOutlinePlusSmall
|
||||
className="-mr-0.5 h-5 w-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
}
|
||||
onClick={() => {
|
||||
if (boardId) openNewListForm(boardId);
|
||||
}}
|
||||
disabled={!boardData}
|
||||
>
|
||||
{t`New list`}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<BoardDropdown
|
||||
isTemplate={!!isTemplate}
|
||||
isLoading={!boardData}
|
||||
|
||||
@@ -6,6 +6,8 @@ import FeedbackModal from "~/components/FeedbackModal";
|
||||
import Modal from "~/components/modal";
|
||||
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
|
||||
import { PageHead } from "~/components/PageHead";
|
||||
import { Tooltip } from "~/components/Tooltip";
|
||||
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
|
||||
import { useModal } from "~/providers/modal";
|
||||
import { useWorkspace } from "~/providers/workspace";
|
||||
import { BoardsList } from "./components/BoardsList";
|
||||
@@ -16,6 +18,15 @@ export default function BoardsPage({ isTemplate }: { isTemplate?: boolean }) {
|
||||
const { openModal, modalContentType, isOpen } = useModal();
|
||||
const { workspace } = useWorkspace();
|
||||
|
||||
const { tooltipContent: createModalShortcutTooltipContent } =
|
||||
useKeyboardShortcut({
|
||||
type: "PRESS",
|
||||
stroke: { key: "C" },
|
||||
action: () => openModal("NEW_BOARD"),
|
||||
description: t`Create new ${isTemplate ? "template" : "board"}`,
|
||||
group: "ACTIONS",
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHead
|
||||
@@ -39,16 +50,18 @@ export default function BoardsPage({ isTemplate }: { isTemplate?: boolean }) {
|
||||
{t`Import`}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
variant="primary"
|
||||
onClick={() => openModal("NEW_BOARD")}
|
||||
iconLeft={
|
||||
<HiOutlinePlusSmall aria-hidden="true" className="h-4 w-4" />
|
||||
}
|
||||
>
|
||||
{t`New`}
|
||||
</Button>
|
||||
<Tooltip content={createModalShortcutTooltipContent}>
|
||||
<Button
|
||||
type="button"
|
||||
variant="primary"
|
||||
onClick={() => openModal("NEW_BOARD")}
|
||||
iconLeft={
|
||||
<HiOutlinePlusSmall aria-hidden="true" className="h-4 w-4" />
|
||||
}
|
||||
>
|
||||
{t`New`}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -67,22 +67,23 @@ export function CardModal({
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<button
|
||||
className="absolute right-[2rem] top-[2rem] rounded p-1 hover:bg-light-300 focus:outline-none dark:hover:bg-dark-300"
|
||||
onClick={async (e) => {
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
closeModal();
|
||||
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
await router.replace(
|
||||
`/${workspaceSlug}/${boardSlug}`,
|
||||
undefined,
|
||||
{
|
||||
shallow: true,
|
||||
setTimeout(() => {
|
||||
void router.replace(
|
||||
{
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
workspaceSlug,
|
||||
boardSlug: [boardSlug],
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
{ shallow: true },
|
||||
);
|
||||
}, 400);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -76,7 +76,8 @@ export default function PublicBoardView() {
|
||||
);
|
||||
};
|
||||
|
||||
const splitPath = router.asPath.split("/");
|
||||
const pathWithoutQuery = router.asPath.split("?")[0];
|
||||
const splitPath = pathWithoutQuery.split("/");
|
||||
const cardPublicId = splitPath.length > 3 ? splitPath[3] : null;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -172,27 +173,36 @@ export default function PublicBoardView() {
|
||||
</span>
|
||||
</div>
|
||||
<div className="scrollbar-track-rounded-[4px] scrollbar-thumb-rounded-[4px] scrollbar-w-[8px] z-10 h-full max-h-[calc(100vh-265px)] min-h-[2rem] overflow-y-auto pr-1 scrollbar dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-600">
|
||||
{list.cards.map((card) => (
|
||||
<Link
|
||||
key={card.publicId}
|
||||
href={`/${data.workspace.slug}/${data.slug}/${card.publicId}`}
|
||||
className={`mb-2 flex !cursor-pointer flex-col`}
|
||||
shallow={true}
|
||||
onClick={() => {
|
||||
openModal("CARD");
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
title={card.title}
|
||||
labels={card.labels}
|
||||
checklists={card.checklists ?? []}
|
||||
members={[]}
|
||||
description={card.description}
|
||||
comments={card.comments ?? []}
|
||||
attachments={card.attachments}
|
||||
/>
|
||||
</Link>
|
||||
))}
|
||||
{list.cards.map((card) => {
|
||||
return (
|
||||
<Link
|
||||
key={card.publicId}
|
||||
href={{
|
||||
pathname: router.pathname,
|
||||
query: {
|
||||
...router.query,
|
||||
workspaceSlug: data.workspace.slug,
|
||||
boardSlug: [data.slug, card.publicId],
|
||||
},
|
||||
}}
|
||||
className={`mb-2 flex !cursor-pointer flex-col`}
|
||||
shallow={true}
|
||||
onClick={() => {
|
||||
openModal("CARD");
|
||||
}}
|
||||
>
|
||||
<Card
|
||||
title={card.title}
|
||||
labels={card.labels}
|
||||
checklists={card.checklists ?? []}
|
||||
members={[]}
|
||||
description={card.description}
|
||||
comments={card.comments ?? []}
|
||||
attachments={card.attachments}
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -35,10 +35,12 @@ services:
|
||||
- SMTP_PASSWORD=${SMTP_PASSWORD}
|
||||
- SMTP_SECURE=${SMTP_SECURE}
|
||||
- EMAIL_FROM=${EMAIL_FROM}
|
||||
- SMTP_REJECT_UNAUTHORIZED=${SMTP_REJECT_UNAUTHORIZED}
|
||||
|
||||
# Notifications
|
||||
- NOVU_API_KEY=${NOVU_API_KEY}
|
||||
- DISCORD_WEBHOOK_URL=${DISCORD_WEBHOOK_URL}
|
||||
- EMAIL_UNSUBSCRIBE_SECRET=${EMAIL_UNSUBSCRIBE_SECRET}
|
||||
|
||||
# S3 storage
|
||||
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
|
||||
|
||||
@@ -24,6 +24,7 @@ services:
|
||||
- SMTP_USER=${SMTP_USER}
|
||||
- SMTP_PASSWORD=${SMTP_PASSWORD}
|
||||
- EMAIL_FROM=${EMAIL_FROM}
|
||||
- SMTP_REJECT_UNAUTHORIZED=${SMTP_REJECT_UNAUTHORIZED}
|
||||
|
||||
# Disable email features entirely (optional)
|
||||
- NEXT_PUBLIC_DISABLE_EMAIL=${NEXT_PUBLIC_DISABLE_EMAIL}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { env } from "next-runtime-env";
|
||||
import { z } from "zod";
|
||||
|
||||
import * as inviteLinkRepo from "@kan/db/repository/inviteLink.repo";
|
||||
@@ -307,7 +308,7 @@ export const memberRouter = createTRPCRouter({
|
||||
return {
|
||||
id: activeInviteLink.id,
|
||||
inviteCode: activeInviteLink.code,
|
||||
inviteLink: `${process.env.NEXT_PUBLIC_BASE_URL}/invite/${activeInviteLink.code}`,
|
||||
inviteLink: `${env("NEXT_PUBLIC_BASE_URL")}/invite/${activeInviteLink.code}`,
|
||||
isActive: true,
|
||||
expiresAt: activeInviteLink.expiresAt ?? undefined,
|
||||
};
|
||||
@@ -415,7 +416,7 @@ export const memberRouter = createTRPCRouter({
|
||||
return {
|
||||
publicId: inviteLink.publicId,
|
||||
inviteCode: inviteLink.code,
|
||||
inviteLink: `${process.env.NEXT_PUBLIC_BASE_URL}/invite/${inviteLink.code}`,
|
||||
inviteLink: `${env("NEXT_PUBLIC_BASE_URL")}/invite/${inviteLink.code}`,
|
||||
expiresAt: inviteLink.expiresAt,
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -18,6 +18,7 @@ import * as userRepo from "@kan/db/repository/user.repo";
|
||||
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
|
||||
import * as schema from "@kan/db/schema";
|
||||
import { notificationClient, sendEmail } from "@kan/email";
|
||||
import { createEmailUnsubscribeLink } from "@kan/shared";
|
||||
import { createStripeClient } from "@kan/stripe";
|
||||
|
||||
export const configuredProviders = socialProviderList.reduce<
|
||||
@@ -401,6 +402,10 @@ export const initAuth = (db: dbClient) => {
|
||||
? `${env("NEXT_PUBLIC_STORAGE_URL")}/${env("NEXT_PUBLIC_AVATAR_BUCKET_NAME")}/${avatarKey}`
|
||||
: undefined;
|
||||
|
||||
const unsubscribeUrl = await createEmailUnsubscribeLink(
|
||||
user.id,
|
||||
);
|
||||
|
||||
await notificationClient.trigger({
|
||||
to: {
|
||||
subscriberId: user.id,
|
||||
@@ -415,6 +420,9 @@ export const initAuth = (db: dbClient) => {
|
||||
updatedAt: user.updatedAt,
|
||||
},
|
||||
},
|
||||
payload: {
|
||||
emailUnsubscribeUrl: unsubscribeUrl,
|
||||
},
|
||||
workflowId: "user-signup",
|
||||
});
|
||||
|
||||
@@ -489,6 +497,8 @@ async function triggerWorkflow(
|
||||
|
||||
if (!user || !notificationClient) return;
|
||||
|
||||
const unsubscribeUrl = await createEmailUnsubscribeLink(user.id);
|
||||
|
||||
await notificationClient.trigger({
|
||||
to: {
|
||||
subscriberId: user.id,
|
||||
@@ -496,6 +506,7 @@ async function triggerWorkflow(
|
||||
payload: {
|
||||
...subscription,
|
||||
cancellationDetails,
|
||||
emailUnsubscribeUrl: unsubscribeUrl,
|
||||
},
|
||||
workflowId,
|
||||
});
|
||||
|
||||
@@ -16,7 +16,17 @@ const emailTemplates: Record<Templates, React.FC> = {
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: process.env.SMTP_HOST,
|
||||
port: Number(process.env.SMTP_PORT),
|
||||
secure: process.env.SMTP_SECURE !== "false",
|
||||
secure:
|
||||
process.env.SMTP_SECURE === undefined
|
||||
? true
|
||||
: process.env.SMTP_SECURE?.toLowerCase() === "true",
|
||||
tls: {
|
||||
// do not fail on invalid certs
|
||||
rejectUnauthorized:
|
||||
process.env.SMTP_REJECT_UNAUTHORIZED === undefined
|
||||
? true
|
||||
: process.env.SMTP_REJECT_UNAUTHORIZED?.toLowerCase() === "true",
|
||||
},
|
||||
...(process.env.SMTP_USER &&
|
||||
process.env.SMTP_PASSWORD && {
|
||||
auth: {
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
},
|
||||
"prettier": "@kan/prettier-config",
|
||||
"dependencies": {
|
||||
"nanoid": "^5.0.9"
|
||||
"jose": "^6.1.2",
|
||||
"nanoid": "^5.0.9",
|
||||
"next-runtime-env": "^1.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
32
packages/shared/src/utils/email.ts
Normal file
32
packages/shared/src/utils/email.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { SignJWT } from "jose";
|
||||
import { env } from "next-runtime-env";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
/**
|
||||
* Creates a long‑lived unsubscribe link for a given user/subscriber.
|
||||
*
|
||||
* `${NEXT_PUBLIC_BASE_URL}/unsubscribe?token=<jwt>`
|
||||
*
|
||||
* The JWT payload only contains the subscriberId. There is no expiry
|
||||
* on purpose – unsubscribe links should remain valid indefinitely.
|
||||
*
|
||||
*/
|
||||
export async function createEmailUnsubscribeLink(
|
||||
userId: string,
|
||||
): Promise<string | null> {
|
||||
const baseUrl = env("NEXT_PUBLIC_BASE_URL");
|
||||
const secret = process.env.EMAIL_UNSUBSCRIBE_SECRET;
|
||||
|
||||
if (!baseUrl || !secret) {
|
||||
// Environment not configured for unsubscribe links.
|
||||
return null;
|
||||
}
|
||||
|
||||
const token = await new SignJWT({ subscriberId: userId })
|
||||
.setProtectedHeader({ alg: "HS256" })
|
||||
// No expiration on purpose; unsubscribe links are long‑lived.
|
||||
.sign(encoder.encode(secret));
|
||||
|
||||
return `${baseUrl}/unsubscribe?token=${encodeURIComponent(token)}`;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./generateUID";
|
||||
export * from "./generateSlug";
|
||||
export * from "./subscriptions";
|
||||
export * from "./email";
|
||||
|
||||
17
pnpm-lock.yaml
generated
17
pnpm-lock.yaml
generated
@@ -115,6 +115,9 @@ importers:
|
||||
'@lingui/react':
|
||||
specifier: ^5.3.2
|
||||
version: 5.4.1(@lingui/babel-plugin-lingui-macro@5.4.1(typescript@5.9.2))(react@18.3.1)
|
||||
'@novu/api':
|
||||
specifier: ^3.11.0
|
||||
version: 3.11.0
|
||||
'@t3-oss/env-nextjs':
|
||||
specifier: ^0.11.1
|
||||
version: 0.11.1(typescript@5.9.2)(zod@3.25.76)
|
||||
@@ -166,6 +169,9 @@ importers:
|
||||
geist:
|
||||
specifier: ^1.3.1
|
||||
version: 1.4.2(next@15.5.2(@babel/core@7.28.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||
jose:
|
||||
specifier: ^6.1.2
|
||||
version: 6.1.2
|
||||
next:
|
||||
specifier: ^15.3.4
|
||||
version: 15.5.2(@babel/core@7.28.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@@ -477,9 +483,15 @@ importers:
|
||||
|
||||
packages/shared:
|
||||
dependencies:
|
||||
jose:
|
||||
specifier: ^6.1.2
|
||||
version: 6.1.2
|
||||
nanoid:
|
||||
specifier: ^5.0.9
|
||||
version: 5.1.5
|
||||
next-runtime-env:
|
||||
specifier: ^1.7.2
|
||||
version: 1.8.0
|
||||
devDependencies:
|
||||
'@kan/eslint-config':
|
||||
specifier: workspace:*
|
||||
@@ -5554,6 +5566,9 @@ packages:
|
||||
jose@5.10.0:
|
||||
resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==}
|
||||
|
||||
jose@6.1.2:
|
||||
resolution: {integrity: sha512-MpcPtHLE5EmztuFIqB0vzHAWJPpmN1E6L4oo+kze56LIs3MyXIj9ZHMDxqOvkP38gBR7K1v3jqd4WU2+nrfONQ==}
|
||||
|
||||
joycon@3.1.1:
|
||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -13649,6 +13664,8 @@ snapshots:
|
||||
|
||||
jose@5.10.0: {}
|
||||
|
||||
jose@6.1.2: {}
|
||||
|
||||
joycon@3.1.1: {}
|
||||
|
||||
js-beautify@1.15.4:
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
"SMTP_USER",
|
||||
"SMTP_PASSWORD",
|
||||
"SMTP_SECURE",
|
||||
"SMTP_REJECT_UNAUTHORIZED",
|
||||
"NEXT_PUBLIC_KAN_ENV",
|
||||
"NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY",
|
||||
"STRIPE_SECRET_KEY",
|
||||
@@ -121,7 +122,8 @@
|
||||
"PORT",
|
||||
"BETTER_AUTH_SECRET",
|
||||
"BETTER_AUTH_TRUSTED_ORIGINS",
|
||||
"NOVU_API_KEY"
|
||||
"NOVU_API_KEY",
|
||||
"EMAIL_UNSUBSCRIBE_SECRET"
|
||||
],
|
||||
"globalPassThroughEnv": [
|
||||
"NODE_ENV",
|
||||
|
||||
Reference in New Issue
Block a user