Compare commits

...

26 Commits

Author SHA1 Message Date
Henry
a55c8cd52b fix: update checklist when pressing enter on edit (#292)
* fix: update checklist when pressing enter on edit

* feat: open new checklist item form on enter
2025-12-19 21:40:24 +00:00
Henry
cca8a9d424 feat: health check and stats endpoints (#290) 2025-12-18 08:08:30 +00:00
Ridham Khandar
57186b6b4d feat: paginate and merge frequent activities (#274)
* feat: paginate and merge frequent activities

* feat: due date activities

* fix: requested changes fixes

* refactor: slight reshuffle and improve types

* chore: translations

---------

Co-authored-by: Henry <henry_ball@hotmail.co.uk>
2025-12-16 09:07:08 +00:00
Eliott Herbert-Byrnes
3cb40d0f9a feat: implement drag-and-drop reordering for checklist items (#275)
* feat: implement drag-and-drop reordering for checklist items

* WIP: Changes before syncing with main

* feat: update drag icon and positioning

* refactor: consolidate checklist item updates into single endpoint

- Remove standalone reorderItem route (now part of updateItem)
- Add optional index parameter to updateItem for reordering
- Change updateItem from PUT to PATCH method
- Add deletedAt IS NULL filter to reorderItem SQL queries
- Follows existing pattern from card.update route

* feat: add optimistic updates

* chore: translations

---------

Co-authored-by: Henry <henry_ball@hotmail.co.uk>
2025-12-15 10:01:04 +00:00
Henry
6ebab28606 feat(cloud): force payment method collection for subscription checkout (#285) 2025-12-14 21:55:03 +00:00
Henry
5765c71ebf feat: update logos (#284) 2025-12-13 23:14:25 +00:00
Henry
86ecdca7f1 fix: enable sessions for API keys (#283)
* fix: enable sessions for API keys

* chore: remove old due date filters

* chore: update lockfile

* fix: temp ignore eslint errors on build
2025-12-13 22:19:16 +00:00
Henry
bcd20b58c6 chore: remove instrumentation (#279)
* chore: remove instrumentation

* chore: clean apk cache after installation

* chore: fix docker builds
2025-12-10 22:16:38 +00:00
Henry
36675604f9 chore: upgrade next, react-email and better-auth (#278)
* feat: upgrade next and react-email

* chore: upgrade better-auth
2025-12-10 20:34:10 +00:00
Jovânio Júnior
94760f1e4c Add Brazilian Portuguese (pt-BR) translation support to Kan (#276)
* adding Brazilian Portuguese translation; added a repository on Docker Hub to use in Umbrel — version ptbr jovaniojunior/kan-ptbr:latest

* add notes to changelog.md

* adjust pt-BR date format in date-fns

* improve Portuguese integration across code functions and other small pt-BR tweaks

* chore: gen missing translations

---------

Co-authored-by: Henry <henry_ball@hotmail.co.uk>
2025-12-09 20:24:30 +00:00
Henry
38f477bb5a fix: delete attachment from s3 (#272) 2025-12-05 22:04:53 +00:00
Henry
d208952d15 feat: card due dates (#271)
* feat: add card due dates to schema

* feat: update repo funcs

* feat: update card router to support due dates

* chore: update migration journal

* feat: add date selector

* feat: display date icon and label on cards

* feat: add due date filters

* feat: add due date to new card form

* feat: light mode tweaks

* feat: improve text eligibility on light mode

* feat: reduce selector font size

* feat: display date updates in card activity

* chore: gen translations
2025-12-05 21:49:45 +00:00
Eliott Herbert-Byrnes
88f1aa0ec4 feat: implemented addOrRemoveLabel mutation on CardPage #266 (#270)
* feat: implemented addOrRemoveLabel mutation on CardPage to automatically add new labels #266

* Remove .env.backup
2025-12-05 19:39:18 +00:00
Owais Rizvi
06ca6e38b3 feat: add IRSA support for S3 authentication (#265) 2025-12-01 19:54:58 +00:00
Patrick McEvoy
915877b8e6 feat: limit oidc domains (#263) 2025-12-01 19:51:08 +00:00
Henry
bb8f3de0ad feat: add env var to allow invalid SSL certs (#262)
* feat: add env var to allow invalid SSL certs

* Update readme
2025-11-30 23:00:55 +00:00
Henry
d3c8cbd6c0 fix: persist filters when opening card modal (#261) 2025-11-30 22:32:59 +00:00
Henry
6c3dbaefd3 Update README.md 2025-11-30 22:13:44 +00:00
Ivan Shelepugin
f938723d9a fix(api): correct values of Content-Disposition attributes (#260) 2025-11-30 21:58:40 +00:00
Henry
0928709173 chore: revert hardcoded baseUrl 2025-11-27 23:34:01 +00:00
Henry
ade9aad4bf feat: set next public base url as optional 2025-11-27 23:25:50 +00:00
Henry
5fbaf26707 fix: add missing dependency 2025-11-27 23:15:54 +00:00
Henry
b69835f7de fix: hardcode baseUrl 2025-11-27 23:11:48 +00:00
Henry
58ff6ad041 fix: use next-runtime-env for baseUrl 2025-11-27 22:37:26 +00:00
Spencer Simpson
adbc945ed6 feat: add support for keyboard shortcuts (#255)
* feat: add support for keyboard shortcuts

* fix: recenter icons on button

* feat: extend tooltip delay

* chore: add translations

* refactor: tweak kbd styling

* feat: move shortcuts to user menu

---------

Co-authored-by: Henry <henry_ball@hotmail.co.uk>
2025-11-27 22:09:37 +00:00
Henry
c5d85cdb2d feat(cloud): email unsubscribe (#258)
* feat(cloud): add email unsubscribe

* chore: add translations
2025-11-27 21:44:51 +00:00
122 changed files with 12687 additions and 2781 deletions

View File

@@ -17,6 +17,7 @@ SMTP_USER=
SMTP_PASSWORD= SMTP_PASSWORD=
EMAIL_FROM= # e.g. "Kan <hello@mail.kan.bn>" EMAIL_FROM= # e.g. "Kan <hello@mail.kan.bn>"
SMTP_SECURE= # set to "false" to use port 587 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) # Switch email features off entirely (optional)
NEXT_PUBLIC_DISABLE_EMAIL= NEXT_PUBLIC_DISABLE_EMAIL=
@@ -42,6 +43,8 @@ TRELLO_APP_SECRET=
# OAuth providers (optional) # OAuth providers (optional)
BETTER_AUTH_TRUSTED_ORIGINS= BETTER_AUTH_TRUSTED_ORIGINS=
# Optional: Restrict OIDC/Social sign-ins to specific email domains (comma-separated)
BETTER_AUTH_ALLOWED_DOMAINS=
GOOGLE_CLIENT_ID= GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET= GOOGLE_CLIENT_SECRET=
DISCORD_CLIENT_ID= DISCORD_CLIENT_ID=
@@ -79,4 +82,3 @@ TWITCH_CLIENT_SECRET=
APPLE_CLIENT_ID= APPLE_CLIENT_ID=
APPLE_CLIENT_SECRET= APPLE_CLIENT_SECRET=
APPLE_APP_BUNDLE_IDENTIFIER= APPLE_APP_BUNDLE_IDENTIFIER=

1
.gitignore vendored
View File

@@ -34,6 +34,7 @@ yarn-error.log*
.env .env
.env*.local .env*.local
# vercel # vercel
.vercel .vercel

View File

@@ -34,7 +34,7 @@ See our [roadmap](https://kan.bn/kan/roadmap) for upcoming features.
## Screenshot 👁️ ## 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 🛠️ ## Made With 🛠️
@@ -138,42 +138,45 @@ pnpm dev
## Environment Variables 🔐 ## Environment Variables 🔐
| Variable | Description | Required | Example | | Variable | Description | Required | Example |
| ----------------------------------------- | -------------------------------------------------------- | ------------------------ | ----------------------------------------------------------- | | ----------------------------------------- | --------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------- |
| `POSTGRES_URL` | PostgreSQL connection URL | To use external database | `postgres://user:pass@localhost:5432/db` | | `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>"` | | `EMAIL_FROM` | Sender email address | For Email | `"Kan <hello@mail.kan.bn>"` |
| `SMTP_HOST` | SMTP server hostname | For Email | `smtp.resend.com` | | `SMTP_HOST` | SMTP server hostname | For Email | `smtp.resend.com` |
| `SMTP_PORT` | SMTP server port | For Email | `465` | | `SMTP_PORT` | SMTP server port | For Email | `465` |
| `SMTP_USER` | SMTP username/email | No | `resend` | | `SMTP_USER` | SMTP username/email | No | `resend` |
| `SMTP_PASSWORD` | SMTP password/token | No | `re_xxxx` | | `SMTP_PASSWORD` | SMTP password/token | No | `re_xxxx` |
| `SMTP_SECURE` | Use secure SMTP connection (defaults to true if not set) | For Email | `true` | | `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` | | `SMTP_REJECT_UNAUTHORIZED` | Reject invalid certificates (defaults to true if not set) | For Email | `false` |
| `NEXT_PUBLIC_BASE_URL` | Base URL of your installation | Yes | `http://localhost:3000` | | `NEXT_PUBLIC_DISABLE_EMAIL` | To disable all email features | For Email | `true` |
| `BETTER_AUTH_SECRET` | Auth encryption secret | Yes | Random 32+ char string | | `NEXT_PUBLIC_BASE_URL` | Base URL of your installation | Yes | `http://localhost:3000` |
| `BETTER_AUTH_TRUSTED_ORIGINS` | Allowed callback origins | No | `http://localhost:3000,http://localhost:3001` | | `BETTER_AUTH_ALLOWED_DOMAINS` | Comma-separated list of allowed domains for OIDC logins | For OIDC/Social login | `example.com,subsidiary.com` |
| `GOOGLE_CLIENT_ID` | Google OAuth client ID | For Google login | `xxx.apps.googleusercontent.com` | | `BETTER_AUTH_SECRET` | Auth encryption secret | Yes | Random 32+ char string |
| `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | For Google login | `xxx` | | `BETTER_AUTH_TRUSTED_ORIGINS` | Allowed callback origins | No | `http://localhost:3000,http://localhost:3001` |
| `DISCORD_CLIENT_ID` | Discord OAuth client ID | For Discord login | `xxx` | | `GOOGLE_CLIENT_ID` | Google OAuth client ID | For Google login | `xxx.apps.googleusercontent.com` |
| `DISCORD_CLIENT_SECRET` | Discord OAuth client secret | For Discord login | `xxx` | | `GOOGLE_CLIENT_SECRET` | Google OAuth client secret | For Google login | `xxx` |
| `GITHUB_CLIENT_ID` | GitHub OAuth client ID | For GitHub login | `xxx` | | `DISCORD_CLIENT_ID` | Discord OAuth client ID | For Discord login | `xxx` |
| `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | For GitHub login | `xxx` | | `DISCORD_CLIENT_SECRET` | Discord OAuth client secret | For Discord login | `xxx` |
| `OIDC_CLIENT_ID` | Generic OIDC client ID | For OIDC login | `xxx` | | `GITHUB_CLIENT_ID` | GitHub OAuth client ID | For GitHub login | `xxx` |
| `OIDC_CLIENT_SECRET` | Generic OIDC client secret | For OIDC login | `xxx` | | `GITHUB_CLIENT_SECRET` | GitHub OAuth client secret | For GitHub login | `xxx` |
| `OIDC_DISCOVERY_URL` | OIDC discovery URL | For OIDC login | `https://auth.example.com/.well-known/openid-configuration` | | `OIDC_CLIENT_ID` | Generic OIDC client ID | For OIDC login | `xxx` |
| `TRELLO_APP_API_KEY` | Trello app API key | For Trello import | `xxx` | | `OIDC_CLIENT_SECRET` | Generic OIDC client secret | For OIDC login | `xxx` |
| `TRELLO_APP_API_SECRET` | Trello app API secret | For Trello import | `xxx` | | `OIDC_DISCOVERY_URL` | OIDC discovery URL | For OIDC login | `https://auth.example.com/.well-known/openid-configuration` |
| `S3_REGION` | S3 storage region | For file uploads | `WEUR` | | `TRELLO_APP_API_KEY` | Trello app API key | For Trello import | `xxx` |
| `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` | | `TRELLO_APP_API_SECRET` | Trello app API secret | For Trello import | `xxx` |
| `S3_ACCESS_KEY_ID` | S3 access key | For file uploads | `xxx` | | `S3_REGION` | S3 storage region | For file uploads | `WEUR` |
| `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads | `xxx` | | `S3_ENDPOINT` | S3 endpoint URL | For file uploads | `https://xxx.r2.cloudflarestorage.com` |
| `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` | | `S3_ACCESS_KEY_ID` | S3 access key | For file uploads (optional with IRSA) | `xxx` |
| `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` | | `S3_SECRET_ACCESS_KEY` | S3 secret key | For file uploads (optional with IRSA) | `xxx` |
| `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` | | `S3_FORCE_PATH_STYLE` | Use path-style URLs for S3 | For file uploads | `true` |
| `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` | | `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` |
| `NEXT_PUBLIC_ATTATCHMENTS_BUCKET_NAME` | S3 bucket name for attatchments | For file uploads | `attatchments` | | `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` |
| `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` | | `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` |
| `NEXT_PUBLIC_DISABLE_SIGN_UP` | Disable sign up | For authentication | `false` | | `NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME` | S3 bucket name for attachments | For file uploads | `attachments` |
| `NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY` | Hide “Powered by kan.bn” on public boards (self-host) | For white labelling | `true` | | `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` |
| `KAN_ADMIN_API_KEY` | Admin API key for stats and admin endpoints | For admin/monitoring | `your-secret-admin-key` |
See `.env.example` for a complete list of supported environment variables. See `.env.example` for a complete list of supported environment variables.

View File

@@ -4,8 +4,9 @@ ARG PROJECT=@kan/web
# 1. Alpine image # 1. Alpine image
FROM node:${NODE_VERSION}-alpine AS alpine FROM node:${NODE_VERSION}-alpine AS alpine
RUN apk update RUN apk update && \
RUN apk add --no-cache libc6-compat python3 make g++ apk add --no-cache --virtual .build-deps libc6-compat python3 make g++ && \
rm -rf /var/cache/apk/* /tmp/* || true
# Setup pnpm and turbo on the alpine base # Setup pnpm and turbo on the alpine base
FROM alpine AS base FROM alpine AS base

View File

@@ -2,7 +2,7 @@
"version": 0, "version": 0,
"locale": { "locale": {
"source": "en", "source": "en",
"targets": ["fr", "de", "es", "it", "nl", "ru", "pl"] "targets": ["fr", "de", "es", "it", "nl", "ru", "pl", "ptbr"]
}, },
"buckets": { "buckets": {
"po": { "po": {

View File

@@ -27,6 +27,7 @@ checksums:
Add%20details.../singular: 2f42547fd5d199f173aa7a88c8a9b19a Add%20details.../singular: 2f42547fd5d199f173aa7a88c8a9b19a
Add%20label/singular: 0be732d46df263265935fda342097a08 Add%20label/singular: 0be732d46df263265935fda342097a08
Add%20member/singular: 11979625770516ca287e929381778e02 Add%20member/singular: 11979625770516ca287e929381778e02
added%20%7B0%7D%20labels%3A%20%3C0%3E%7BlabelList%7D%3C%2F0%3E/singular: 42b0488d570626dc887c58ff669c953c
added%20a%20checklist/singular: 44304f4a5ef3a46378eea243b5d2df79 added%20a%20checklist/singular: 44304f4a5ef3a46378eea243b5d2df79
added%20a%20checklist%20item/singular: 20bc0330dba5a9ec978e04bec174365a added%20a%20checklist%20item/singular: 20bc0330dba5a9ec978e04bec174365a
added%20a%20label%20to%20the%20card/singular: 04c5e4ee9b7b7e77ef089d2ac473d235 added%20a%20label%20to%20the%20card/singular: 04c5e4ee9b7b7e77ef089d2ac473d235
@@ -92,6 +93,7 @@ checksums:
Card%20title/singular: 7c34f59f4005e6cb3a6ff546ea0b96e3 Card%20title/singular: 7c34f59f4005e6cb3a6ff546ea0b96e3
Change%20Password/singular: a552fc5c4189ebc3e2e6018edda7d18f Change%20Password/singular: a552fc5c4189ebc3e2e6018edda7d18f
Change%20your%20language%20preferences./singular: 293d49fc3c75e9c425b64bd7126e6b46 Change%20your%20language%20preferences./singular: 293d49fc3c75e9c425b64bd7126e6b46
changed%20the%20due%20date%20to%20%3C0%3E%7BformattedDate%7D%3C%2F0%3E/singular: 32189aa87452ab18f90f02742bfa9910
Check%20out%20some%20of%20our%20favorite%20open%20source%20projects./singular: b0d0be4f63c16552b3aa795af29240d1 Check%20out%20some%20of%20our%20favorite%20open%20source%20projects./singular: b0d0be4f63c16552b3aa795af29240d1
Check%20your%20inbox/singular: e9a430fcd298def74212238df0f680d6 Check%20your%20inbox/singular: e9a430fcd298def74212238df0f680d6
Checklist%20name/singular: 5eb5de823f7ca5a4d97bb41e6a3f675a Checklist%20name/singular: 5eb5de823f7ca5a4d97bb41e6a3f675a
@@ -110,6 +112,7 @@ checksums:
Complete%20control%20and%20ownership%3A/singular: 0d8b682ba873272217425ccfc96aa9cd Complete%20control%20and%20ownership%3A/singular: 0d8b682ba873272217425ccfc96aa9cd
completed%20a%20checklist%20item/singular: 757b04c6c80cc927e1c597c0ad4fda33 completed%20a%20checklist%20item/singular: 757b04c6c80cc927e1c597c0ad4fda33
completed%20checklist%20item%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 71ec18acf051fc909a48a07ca3578673 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 Confirm%20your%20new%20password/singular: a0d2935d7b63f8dd19d7c0de47524416
Connect%20Trello/singular: 4440a0b9e387ef7136e3958e7a089213 Connect%20Trello/singular: 4440a0b9e387ef7136e3958e7a089213
Connect%20your%20favorite%20tools%20to%20streamline%20your%20workflow./singular: 033c5dcdb059ccb634aef7fe63f2f45d Connect%20your%20favorite%20tools%20to%20streamline%20your%20workflow./singular: 033c5dcdb059ccb634aef7fe63f2f45d
@@ -168,12 +171,18 @@ checksums:
Display%20name%20must%20be%20at%20least%203%20characters%20long/singular: 84178b79845a70937af5e26020403052 Display%20name%20must%20be%20at%20least%203%20characters%20long/singular: 84178b79845a70937af5e26020403052
Display%20name%20updated/singular: 4e27503ca24ef5f009713951ca9e5b97 Display%20name%20updated/singular: 4e27503ca24ef5f009713951ca9e5b97
Do%20you%20offer%20a%20free%20plan%3F/singular: 3ef16b0994f0d9ae17067782ca9bed1b Do%20you%20offer%20a%20free%20plan%3F/singular: 3ef16b0994f0d9ae17067782ca9bed1b
Do%20you%20want%20to%20unsubscribe%3F/singular: 8173b82c731ba885939d223eeef2e40b
docs/singular: 307bff5678ada918da1f1ec3edc76cac docs/singular: 307bff5678ada918da1f1ec3edc76cac
Docs/singular: 55fea190a0c0fb32acd3dc986cd3cc91 Docs/singular: 55fea190a0c0fb32acd3dc986cd3cc91
Documentation/singular: 1563fcb5ddb5037b0709ccd3dd384a92 Documentation/singular: 1563fcb5ddb5037b0709ccd3dd384a92
Don't%20have%20an%20account%3F%20%3C0%3E%3C1%3ESign%20up%3C%2F1%3E%3C%2F0%3E/singular: 6ae8282ab8b4a01b4ce87b119e13714b Don't%20have%20an%20account%3F%20%3C0%3E%3C1%3ESign%20up%3C%2F1%3E%3C%2F0%3E/singular: 6ae8282ab8b4a01b4ce87b119e13714b
Done/singular: ffd408fa29d5bc9039ef8ea1b9b699bb Done/singular: ffd408fa29d5bc9039ef8ea1b9b699bb
Download%20failed/singular: 142b391cca3e05f2af9617092f7358c5 Download%20failed/singular: 142b391cca3e05f2af9617092f7358c5
Due%20date/singular: b098b52aff38516c5838c2ac4419f958
Due%20next%20month/singular: 223ab6f1211e1dfdf39ea68d25fe380b
Due%20next%20week/singular: 2f8fac5719df18d25a466ee913dc6487
Due%20today/singular: a14cb9dd0003485894d328bb803c80e5
Due%20tomorrow/singular: 0b6c8ad7aba0873b7e212d5f1949ca97
Edit%20board%20URL/singular: d8276dfc0189f371ec7d80a2047c07aa Edit%20board%20URL/singular: d8276dfc0189f371ec7d80a2047c07aa
Edit%20comment/singular: 7e4b46525fcb6b47b71798e31c46e374 Edit%20comment/singular: 7e4b46525fcb6b47b71798e31c46e374
Edit%20label/singular: 0309e0be1512b1e0b0ceb87c69a53d03 Edit%20label/singular: 0309e0be1512b1e0b0ceb87c69a53d03
@@ -306,6 +315,8 @@ checksums:
List/singular: 94f13e7ef909a4de9db7abaa1f9f0b61 List/singular: 94f13e7ef909a4de9db7abaa1f9f0b61
List%20name/singular: e925e2e6ccaf0eb4064a888aaea8d3c2 List%20name/singular: e925e2e6ccaf0eb4064a888aaea8d3c2
Lists/singular: 9f4a73afc8de321175d71935134ef066 Lists/singular: 9f4a73afc8de321175d71935134ef066
Load%20more%20activities/singular: f32d40a739ffaa700051c4c7d70055cf
Loading.../singular: 82b4ea7ed1439094d7c4be13aaba9a66
Login%20%7C%20kan.bn/singular: 42a6c8dcd73e0d46e652646dc86871eb Login%20%7C%20kan.bn/singular: 42a6c8dcd73e0d46e652646dc86871eb
Logout/singular: 07948fdf20705e04a7bf68ab197512bf Logout/singular: 07948fdf20705e04a7bf68ab197512bf
Long-term/singular: 51cb6f0b112250c5a091ca5f0866904b Long-term/singular: 51cb6f0b112250c5a091ca5f0866904b
@@ -344,6 +355,7 @@ checksums:
No%20authentication%20methods%20are%20currently%20available/singular: f718c896810da3612202887f9a4374fa No%20authentication%20methods%20are%20currently%20available/singular: f718c896810da3612202887f9a4374fa
No%20boards%20found/singular: e044088d2c51b6bdf660fafa86ee1e17 No%20boards%20found/singular: e044088d2c51b6bdf660fafa86ee1e17
No%20credit%20card%20required/singular: 2090aa4171dc0b60735069f89b592883 No%20credit%20card%20required/singular: 2090aa4171dc0b60735069f89b592883
No%20dates/singular: bd0ec82b3b1f4a5fa89d362b71f8141d
No%20download%20URL%20available%20for%20this%20attachment./singular: e367d39420b2242f9d2fd749c87f446a No%20download%20URL%20available%20for%20this%20attachment./singular: e367d39420b2242f9d2fd749c87f446a
No%20keyboard%20shortcuts%20registered./singular: 7f1ed5d777cade7d62303e9e591bbf63 No%20keyboard%20shortcuts%20registered./singular: 7f1ed5d777cade7d62303e9e591bbf63
No%20lists/singular: cedf633d99c77ff4356e089f2d98c0a6 No%20lists/singular: cedf633d99c77ff4356e089f2d98c0a6
@@ -359,6 +371,7 @@ checksums:
or/singular: 7b133c38bec0d5ee23cc6bcf9a8de50b or/singular: 7b133c38bec0d5ee23cc6bcf9a8de50b
Organize%20and%20find%20cards%20quickly%20with%20powerful%20filtering%20tools./singular: 1b9898c4b21e9dff413b4f76dc59db56 Organize%20and%20find%20cards%20quickly%20with%20powerful%20filtering%20tools./singular: 1b9898c4b21e9dff413b4f76dc59db56
OSS%20Friends/singular: 706e10666dfe26130c17fedb5366a25d OSS%20Friends/singular: 706e10666dfe26130c17fedb5366a25d
Overdue/singular: 24caaa2b5d7a2447ab7664e3771cf98c
Own%20your%20data/singular: cc2178dac4bdf6b07f030cfc2a7510e6 Own%20your%20data/singular: cc2178dac4bdf6b07f030cfc2a7510e6
Owned%20by%20Atlassian/singular: ace4ed076a5318ad48c296fa09afed69 Owned%20by%20Atlassian/singular: ace4ed076a5318ad48c296fa09afed69
Part-time/singular: 213d63da450f35dabb3ab0e35e29feed Part-time/singular: 213d63da450f35dabb3ab0e35e29feed
@@ -399,9 +412,11 @@ checksums:
Remote/singular: dc3e4280dfe5c455b38ba6c8884999cf Remote/singular: dc3e4280dfe5c455b38ba6c8884999cf
Remove/singular: dba2fe5fe9f83f8078c687f28cba4b52 Remove/singular: dba2fe5fe9f83f8078c687f28cba4b52
Remove%20member/singular: 1d77c2ca3768e486fd1fb5df30cb60d9 Remove%20member/singular: 1d77c2ca3768e486fd1fb5df30cb60d9
removed%20%7B0%7D%20labels%3A%20%3C0%3E%7BlabelList%7D%3C%2F0%3E/singular: 612fcfd4aca6818fc870f81d9687d63f
removed%20a%20label%20from%20the%20card/singular: f83ec18850a2a8a3f8242a740a04df06 removed%20a%20label%20from%20the%20card/singular: f83ec18850a2a8a3f8242a740a04df06
removed%20a%20member%20from%20the%20card/singular: 0bd7561bb79358fde3d595c3e60a315a removed%20a%20member%20from%20the%20card/singular: 0bd7561bb79358fde3d595c3e60a315a
removed%20label%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 7e0936b15831e65754588b8512f62fcb removed%20label%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 7e0936b15831e65754588b8512f62fcb
removed%20the%20due%20date/singular: 000c084844718540fcad542dd8caf8b4
renamed%20a%20checklist/singular: 4d208de1857740e63469007c5b8b491a renamed%20a%20checklist/singular: 4d208de1857740e63469007c5b8b491a
renamed%20checklist%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: e95d119ef65b0af6c0a96bef182be671 renamed%20checklist%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: e95d119ef65b0af6c0a96bef182be671
renamed%20checklist%20item%20to%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 50f55f71f9245890afee434d7adc2140 renamed%20checklist%20item%20to%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: 50f55f71f9245890afee434d7adc2140
@@ -426,6 +441,8 @@ checksums:
Self-hostable/singular: 3e3597145cc17f03b8b5646b80d59592 Self-hostable/singular: 3e3597145cc17f03b8b5646b80d59592
Send%20feedback/singular: 9631cc08d49da04475b30a0d320ce97c Send%20feedback/singular: 9631cc08d49da04475b30a0d320ce97c
Senior/singular: 3fff865dc00435f82896fc302ea45630 Senior/singular: 3fff865dc00435f82896fc302ea45630
Set%20due%20date/singular: 3cb81c4829857556f5d117c9a23f7bcc
set%20the%20due%20date/singular: b5d9a1edd988f455041aee9fa7fb3d63
Settings/singular: 8df6777277469c1fd88cc18dde2f1cc3 Settings/singular: 8df6777277469c1fd88cc18dde2f1cc3
Settings%20%7C%20Account/singular: 050e18406849ec057edac877c297c3e1 Settings%20%7C%20Account/singular: 050e18406849ec057edac877c297c3e1
Settings%20%7C%20API/singular: 85101e4b802a09ad9e3f01ff116f0894 Settings%20%7C%20API/singular: 85101e4b802a09ad9e3f01ff116f0894
@@ -489,6 +506,7 @@ checksums:
Trusted%20by%20fast-moving%20teams%3C0%2F%3Earound%20the%20world/singular: b065575df380536df9541a91ca9b37bf Trusted%20by%20fast-moving%20teams%3C0%2F%3Earound%20the%20world/singular: b065575df380536df9541a91ca9b37bf
Unable%20to%20add%20checklist%20item/singular: 4c4c3eaaf10b348b39ae97eb5dc455df Unable%20to%20add%20checklist%20item/singular: 4c4c3eaaf10b348b39ae97eb5dc455df
Unable%20to%20add%20comment/singular: 49bb435880817434698f31a6069564d6 Unable%20to%20add%20comment/singular: 49bb435880817434698f31a6069564d6
Unable%20to%20add%20label/singular: b09fda6420ea1dc10dbea0b1dc373f29
Unable%20to%20create%20card/singular: 90112ea12ec6fa42097a6e022ae048a4 Unable%20to%20create%20card/singular: 90112ea12ec6fa42097a6e022ae048a4
Unable%20to%20create%20checklist/singular: 94eed122e42e0951cd08b9ec62f5eeb6 Unable%20to%20create%20checklist/singular: 94eed122e42e0951cd08b9ec62f5eeb6
Unable%20to%20create%20list/singular: 7fbbf8314f8d08a4123c7daef09fed05 Unable%20to%20create%20list/singular: 7fbbf8314f8d08a4123c7daef09fed05
@@ -500,6 +518,7 @@ checksums:
Unable%20to%20delete%20checklist%20item/singular: a74144593b625e4d8d7ecf734462c60d Unable%20to%20delete%20checklist%20item/singular: a74144593b625e4d8d7ecf734462c60d
Unable%20to%20delete%20comment/singular: 550198b2c87f06726a843c79c1026ed9 Unable%20to%20delete%20comment/singular: 550198b2c87f06726a843c79c1026ed9
Unable%20to%20remove%20member/singular: 39025a0c53818438829603d213baef06 Unable%20to%20remove%20member/singular: 39025a0c53818438829603d213baef06
Unable%20to%20reorder%20checklist%20item/singular: dcc238c72b85daf74ebd46adcd914473
Unable%20to%20send%20feedback/singular: 656c93265d7e2bef1245b17d85f85ae5 Unable%20to%20send%20feedback/singular: 656c93265d7e2bef1245b17d85f85ae5
Unable%20to%20update%20board%20URL/singular: 080746884059142358b58d9a44ff7d93 Unable%20to%20update%20board%20URL/singular: 080746884059142358b58d9a44ff7d93
Unable%20to%20update%20board%20visibility/singular: a76a21d561b8943e9276e027a1e3f70d Unable%20to%20update%20board%20visibility/singular: a76a21d561b8943e9276e027a1e3f70d
@@ -507,6 +526,7 @@ checksums:
Unable%20to%20update%20checklist/singular: 44c10f49f448909ceca481ed9b4b07e7 Unable%20to%20update%20checklist/singular: 44c10f49f448909ceca481ed9b4b07e7
Unable%20to%20update%20checklist%20item/singular: 5c86b3523531c30d58856e3ecde0cb55 Unable%20to%20update%20checklist%20item/singular: 5c86b3523531c30d58856e3ecde0cb55
Unable%20to%20update%20comment/singular: 05e798ed6b0f3fee41f3e8832eb699ea Unable%20to%20update%20comment/singular: 05e798ed6b0f3fee41f3e8832eb699ea
Unable%20to%20update%20due%20date/singular: af20d7482cb639a8c8264c681a18abed
Unable%20to%20update%20labels/singular: dca2bdc3dcf74bc9d95e05156039a291 Unable%20to%20update%20labels/singular: dca2bdc3dcf74bc9d95e05156039a291
Unable%20to%20update%20list/singular: 14aa802f91b9b4c05236c8c75afb33da Unable%20to%20update%20list/singular: 14aa802f91b9b4c05236c8c75afb33da
Unable%20to%20update%20members/singular: 9a851a6b0c75ee16d25cf2ff4b67b255 Unable%20to%20update%20members/singular: 9a851a6b0c75ee16d25cf2ff4b67b255
@@ -520,10 +540,12 @@ checksums:
Unlimited%20lists/singular: 5c418701b27b9acbc5dd199719007362 Unlimited%20lists/singular: 5c418701b27b9acbc5dd199719007362
Unlimited%20members/singular: f2949ca2dc18b0063af92e60779abb65 Unlimited%20members/singular: f2949ca2dc18b0063af92e60779abb65
Unlimited%20workspaces/singular: b504d01997bf908af1d486d9942fed36 Unlimited%20workspaces/singular: b504d01997bf908af1d486d9942fed36
Unsubscribe/singular: d1a0b07295687d1f08d4df1c411072dd
Update/singular: 079fc039262fd31b10532929685c2d1b Update/singular: 079fc039262fd31b10532929685c2d1b
Update%20label/singular: 97880b503dfe956941c5f23025a1c102 Update%20label/singular: 97880b503dfe956941c5f23025a1c102
updated%20a%20checklist%20item/singular: 198e1d1d503f4b69b752dd84d0cc0e9d updated%20a%20checklist%20item/singular: 198e1d1d503f4b69b752dd84d0cc0e9d
updated%20the%20description/singular: 70fd604b6dc957a75be90ea77572d76d updated%20the%20description/singular: 70fd604b6dc957a75be90ea77572d76d
updated%20the%20due%20date/singular: 7636c200d50fed58a4295ed1e9b5c1e0
updated%20the%20title/singular: 98cf8f12923ec1a58e767e3a40863b21 updated%20the%20title/singular: 98cf8f12923ec1a58e767e3a40863b21
updated%20the%20title%20to%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: aca196d729401d8adc5c8ca9d558840e updated%20the%20title%20to%20%3C0%3E%7B0%7D%3C%2F0%3E/singular: aca196d729401d8adc5c8ca9d558840e
Upgrade%20to%20Pro/singular: 972773025e763ddf53273df6d37a729a Upgrade%20to%20Pro/singular: 972773025e763ddf53273df6d37a729a
@@ -545,6 +567,7 @@ checksums:
View%20workspace/singular: c9e4b789330b08c18ca8db7044409e5f View%20workspace/singular: c9e4b789330b08c18ca8db7044409e5f
Visibility/singular: 1ff412f8fcde0f460acbf11153649646 Visibility/singular: 1ff412f8fcde0f460acbf11153649646
We%20are%20using%20the%20%3C0%3EAGPL-3.0%20license%3C%2F0%3E./singular: 08c5ddd938a2a70f61d684e41e18697a 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 We're%20just%20getting%20started.%20/singular: 2dfa121e0ff1914e08068308a81973c0
Welcome%20back/singular: 4928884739ba559e6e4b960e80fe1452 Welcome%20back/singular: 4928884739ba559e6e4b960e80fe1452
What%20license%20are%20you%20using%3F/singular: 59d00e1bf28edc21b77fec94875f57ca What%20license%20are%20you%20using%3F/singular: 59d00e1bf28edc21b77fec94875f57ca
@@ -577,6 +600,7 @@ checksums:
You%20can%20self-host%20by%20following%20the%20instructions%20in%20our%20%3C0%3Erepo%3C%2F0%3E./singular: a6152a41b2d8f64d5a657e5b8bc808a9 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%20logged%20in%20successfully./singular: ef8fad1dce13ae4112f17c5258655fea
You%20have%20been%20signed%20up%20successfully./singular: f614a6e3b45f5ffb9a3b0fb420fef84b 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%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%20on%20kan.bn./singular: 257b840726f972f384243a72767f880f
You've%20been%20invited%20to%20join%20a%20workspace./singular: 24fc6cdc8740f37a83df85f582f03293 You've%20been%20invited%20to%20join%20a%20workspace./singular: 24fc6cdc8740f37a83df85f582f03293
@@ -588,6 +612,7 @@ checksums:
Your%20profile%20image%20has%20been%20updated./singular: 099e1780348cd7bf617721344371a430 Your%20profile%20image%20has%20been%20updated./singular: 099e1780348cd7bf617721344371a430
Your%20Trello%20account%20has%20been%20disconnected./singular: 126aeeb73f7e4cad338056e4c933f39b Your%20Trello%20account%20has%20been%20disconnected./singular: 126aeeb73f7e4cad338056e4c933f39b
Your%20Trello%20account%20is%20connected./singular: 0499d193001fce2fbec445ae034ce512 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%20description%20has%20been%20updated./singular: 98de6f65c567c6654cc0adce3c9d5656
Your%20workspace%20has%20been%20deleted./singular: e7a3efcfc7dd18cb3e917acb67498292 Your%20workspace%20has%20been%20deleted./singular: e7a3efcfc7dd18cb3e917acb67498292
Your%20workspace%20name%20has%20been%20updated./singular: a87ea3b0d71e6dc5dd525d77114a9322 Your%20workspace%20name%20has%20been%20updated./singular: a87ea3b0d71e6dc5dd525d77114a9322

View File

@@ -1,7 +1,7 @@
import type { LinguiConfig } from "@lingui/conf"; import type { LinguiConfig } from "@lingui/conf";
const config: LinguiConfig = { const config: LinguiConfig = {
locales: ["en", "fr", "de", "es", "it", "nl", "ru", "pl"], locales: ["en", "fr", "de", "es", "it", "nl", "ru", "pl","ptbr"],
sourceLocale: "en", sourceLocale: "en",
catalogs: [ catalogs: [
{ {

View File

@@ -26,9 +26,11 @@ const config = {
], ],
/** We already do linting and typechecking as separate tasks in CI */ /** We already do linting and typechecking as separate tasks in CI */
eslint: { ignoreDuringBuilds: true },
typescript: { ignoreBuildErrors: true }, typescript: { ignoreBuildErrors: true },
// temporarily ignore eslint errors during build until we fix all the errors sigh
eslint: { ignoreDuringBuilds: true },
images: { images: {
remotePatterns: (() => { remotePatterns: (() => {
/** @type {Array<{protocol: "http" | "https", hostname: string}>} */ /** @type {Array<{protocol: "http" | "https", hostname: string}>} */
@@ -75,12 +77,13 @@ const config = {
return patterns; return patterns;
})(), })(),
}, },
webpack(config) { turbopack: {
config.module.rules.push({ rules: {
test: /\.svg$/, "*.svg": {
use: ["@svgr/webpack"], loaders: ["@svgr/webpack"],
}); as: "*.js",
return config; },
},
}, },
experimental: { experimental: {
// instrumentationHook: true, // instrumentationHook: true,

View File

@@ -4,9 +4,9 @@
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "pnpm with-env next build", "build": "pnpm with-env next build --turbo",
"clean": "git clean -xdf .cache .next .turbo node_modules", "clean": "git clean -xdf .cache .next .turbo node_modules",
"dev": "pnpm with-env next dev", "dev": "pnpm with-env next dev --turbo",
"format": "prettier --check . --ignore-path ../../.gitignore", "format": "prettier --check . --ignore-path ../../.gitignore",
"lint": "eslint", "lint": "eslint",
"start": "pnpm with-env next start", "start": "pnpm with-env next start",
@@ -29,6 +29,7 @@
"@lingui/conf": "^5.3.2", "@lingui/conf": "^5.3.2",
"@lingui/macro": "^5.3.2", "@lingui/macro": "^5.3.2",
"@lingui/react": "^5.3.2", "@lingui/react": "^5.3.2",
"@novu/api": "^3.11.0",
"@t3-oss/env-nextjs": "^0.11.1", "@t3-oss/env-nextjs": "^0.11.1",
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@tanstack/react-query": "catalog:", "@tanstack/react-query": "catalog:",
@@ -43,15 +44,13 @@
"@trpc/next": "^11.0.0-rc.660", "@trpc/next": "^11.0.0-rc.660",
"@trpc/react-query": "catalog:", "@trpc/react-query": "catalog:",
"@trpc/server": "catalog:", "@trpc/server": "catalog:",
"aws-sdk": "^2.1692.0",
"date-fns": "^4.1.0", "date-fns": "^4.1.0",
"geist": "^1.3.1", "geist": "^1.3.1",
"next": "^15.3.4", "jose": "^6.1.2",
"next-logger": "^5.0.1", "next": "15.5.9",
"next-runtime-env": "^1.7.2", "next-runtime-env": "^1.7.2",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
"nextjs-cors": "^2.2.0", "nextjs-cors": "^2.2.0",
"pino": "^9.6.0",
"posthog-js": "^1.254.0", "posthog-js": "^1.254.0",
"react": "catalog:react18", "react": "catalog:react18",
"react-beautiful-dnd": "^13.1.1", "react-beautiful-dnd": "^13.1.1",
@@ -85,7 +84,6 @@
"dotenv-cli": "^7.4.4", "dotenv-cli": "^7.4.4",
"eslint": "catalog:", "eslint": "catalog:",
"jiti": "^1.21.6", "jiti": "^1.21.6",
"pino-pretty": "^13.0.0",
"prettier": "catalog:", "prettier": "catalog:",
"tailwindcss": "catalog:", "tailwindcss": "catalog:",
"typescript": "catalog:" "typescript": "catalog:"

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,136 @@
import {
addMonths,
eachDayOfInterval,
endOfMonth,
endOfWeek,
format,
isSameDay,
isToday,
startOfMonth,
startOfWeek,
subMonths,
} from "date-fns";
import { useMemo, useState } from "react";
import { HiChevronLeft, HiChevronRight } from "react-icons/hi2";
import { twMerge } from "tailwind-merge";
interface DateSelectorProps {
selectedDate?: Date | null;
onDateSelect?: (date: Date | undefined) => void;
}
const DateSelector = ({ selectedDate, onDateSelect }: DateSelectorProps) => {
const [currentMonth, setCurrentMonth] = useState(() => {
return selectedDate ? startOfMonth(selectedDate) : startOfMonth(new Date());
});
const monthName = format(currentMonth, "MMMM");
const year = format(currentMonth, "yyyy");
const dayHeaders = useMemo(() => {
const weekStart = startOfWeek(new Date(), { weekStartsOn: 1 }); // Monday
return eachDayOfInterval({
start: weekStart,
end: new Date(weekStart.getTime() + 6 * 24 * 60 * 60 * 1000),
}).map((date) => format(date, "EEEEEE")); // Shortest localized day name
}, []);
const days = useMemo(() => {
const monthStart = startOfMonth(currentMonth);
const monthEnd = endOfMonth(currentMonth);
const calendarStart = startOfWeek(monthStart, { weekStartsOn: 1 }); // Monday
const calendarEnd = endOfWeek(monthEnd, { weekStartsOn: 1 }); // Monday
return eachDayOfInterval({ start: calendarStart, end: calendarEnd }).map(
(date) => {
const dateString = format(date, "yyyy-MM-dd");
return {
date: dateString,
isToday: isToday(date),
isSelected: selectedDate ? isSameDay(date, selectedDate) : false,
isCurrentMonth: date >= monthStart && date <= monthEnd,
dateObj: date,
};
},
);
}, [currentMonth, selectedDate]);
const handlePreviousMonth = () => {
setCurrentMonth(subMonths(currentMonth, 1));
};
const handleNextMonth = () => {
setCurrentMonth(addMonths(currentMonth, 1));
};
const handleDateClick = (date: Date, e: React.MouseEvent) => {
e.stopPropagation();
// If clicking the same date that's already selected, unselect it
if (selectedDate && isSameDay(date, selectedDate)) {
onDateSelect?.(undefined);
} else {
onDateSelect?.(date);
}
};
return (
<div className="w-[250px] p-4">
<div className="flex items-center text-light-1000 dark:text-dark-1000">
<button
type="button"
onClick={handlePreviousMonth}
className="flex flex-none items-center justify-center p-1.5 text-light-700 hover:text-light-900 dark:text-dark-700 dark:hover:text-dark-1000"
>
<span className="sr-only">Previous month</span>
<HiChevronLeft aria-hidden="true" className="h-4 w-4" />
</button>
<div className="flex-1 text-center text-sm font-semibold">
{monthName} {year}
</div>
<button
type="button"
onClick={handleNextMonth}
className="flex flex-none items-center justify-center p-1.5 text-light-700 hover:text-light-900 dark:text-dark-700 dark:hover:text-dark-1000"
>
<span className="sr-only">Next month</span>
<HiChevronRight aria-hidden="true" className="h-4 w-4" />
</button>
</div>
<div className="mt-6 grid grid-cols-7 text-center text-xs/6 text-light-950 dark:text-dark-950">
{dayHeaders.map((day, index) => (
<div key={index}>{day}</div>
))}
</div>
<div className="isolate mt-2 grid grid-cols-7 text-sm">
{days.map((day) => (
<button
key={day.date}
type="button"
onClick={(e) => handleDateClick(day.dateObj, e)}
className={twMerge(
"flex aspect-square items-center justify-center rounded-lg focus:z-10",
day.isSelected
? "bg-light-1000 hover:bg-light-1000 dark:bg-dark-1000 dark:hover:bg-dark-1000"
: "bg-transparent hover:bg-light-200 dark:bg-transparent dark:hover:bg-dark-200",
)}
>
<time
dateTime={day.date}
className={twMerge(
"mx-auto flex size-7 items-center justify-center rounded-full text-light-900 dark:text-dark-900",
day.isCurrentMonth
? "text-light-900 dark:text-dark-900"
: "text-light-700 dark:text-dark-600",
day.isSelected && "text-light-50 dark:text-dark-50",
)}
>
{day.date.split("-").pop()?.replace(/^0/, "")}
</time>
</button>
))}
</div>
</div>
);
};
export default DateSelector;

View File

@@ -2,8 +2,10 @@ import Link from "next/link";
import { useState } from "react"; import { useState } from "react";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
import type { KeyboardShortcut } from "~/providers/keyboard-shortcuts";
import LottieIcon from "~/components/LottieIcon"; import LottieIcon from "~/components/LottieIcon";
import { useIsMobile } from "~/hooks/useMediaQuery"; import { useIsMobile } from "~/hooks/useMediaQuery";
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
const Button: React.FC<{ const Button: React.FC<{
href: string; href: string;
@@ -12,10 +14,20 @@ const Button: React.FC<{
json: object; json: object;
isCollapsed?: boolean; isCollapsed?: boolean;
onCloseSideNav?: () => void; 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 [isHovered, setIsHovered] = useState(false);
const [index, setIndex] = useState(0); const [index, setIndex] = useState(0);
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { keys: shortcutKeys } = useKeyboardShortcut(keyboardShortcut);
const handleMouseEnter = () => { const handleMouseEnter = () => {
setIsHovered(true); setIsHovered(true);
@@ -34,18 +46,27 @@ const Button: React.FC<{
onMouseEnter={handleMouseEnter} onMouseEnter={handleMouseEnter}
onClick={handleClick} onClick={handleClick}
className={twMerge( 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 current
? "bg-light-200 text-light-1000 dark:bg-dark-200 dark:text-dark-1000" ? "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", : "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} title={isCollapsed ? name : undefined}
> >
<LottieIcon index={index} json={json} isPlaying={isHovered} /> <div
<span className={twMerge(isCollapsed && "md:hidden")}>{name}</span> 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> </Link>
); );
}; };

View File

@@ -15,6 +15,7 @@ import { twMerge } from "tailwind-merge";
import type { Subscription } from "@kan/shared/utils"; import type { Subscription } from "@kan/shared/utils";
import { hasActiveSubscription } 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 boardsIconDark from "~/assets/boards-dark.json";
import boardsIconLight from "~/assets/boards-light.json"; import boardsIconLight from "~/assets/boards-light.json";
import membersIconDark from "~/assets/members-dark.json"; import membersIconDark from "~/assets/members-dark.json";
@@ -86,26 +87,59 @@ export default function SideNavigation({
const isDarkMode = resolvedTheme === "dark"; const isDarkMode = resolvedTheme === "dark";
const navigation = [ const navigation: {
name: string;
href: string;
icon: object;
keyboardShortcut: KeyboardShortcut;
}[] = [
{ {
name: t`Boards`, name: t`Boards`,
href: "/boards", href: "/boards",
icon: isDarkMode ? boardsIconDark : boardsIconLight, 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`, name: t`Templates`,
href: "/templates", href: "/templates",
icon: isDarkMode ? templatesIconDark : templatesIconLight, 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`, name: t`Members`,
href: "/members", href: "/members",
icon: isDarkMode ? membersIconDark : membersIconLight, 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`, name: t`Settings`,
href: "/settings", href: "/settings",
icon: isDarkMode ? settingsIconDark : settingsIconLight, 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} json={item.icon}
isCollapsed={isCollapsed} isCollapsed={isCollapsed}
onCloseSideNav={onCloseSideNav} onCloseSideNav={onCloseSideNav}
keyboardShortcut={item.keyboardShortcut}
/> />
</li> </li>
))} ))}

View 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>
);
}

View File

@@ -10,6 +10,7 @@ import { twMerge } from "tailwind-merge";
import { authClient } from "@kan/auth/client"; import { authClient } from "@kan/auth/client";
import { useIsMobile } from "~/hooks/useMediaQuery"; import { useIsMobile } from "~/hooks/useMediaQuery";
import { useKeyboardShortcuts } from "~/providers/keyboard-shortcuts";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { getAvatarUrl } from "~/utils/helpers"; import { getAvatarUrl } from "~/utils/helpers";
@@ -31,6 +32,7 @@ export default function UserMenu({
const router = useRouter(); const router = useRouter();
const { theme, setTheme } = useTheme(); const { theme, setTheme } = useTheme();
const { openModal } = useModal(); const { openModal } = useModal();
const { openLegend } = useKeyboardShortcuts();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const handleLogout = async () => { const handleLogout = async () => {
@@ -169,6 +171,19 @@ export default function UserMenu({
</Menu.Item> </Menu.Item>
</div> </div>
<div className="light-border-600 border-t-[1px] p-1 dark:border-dark-600"> <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> <Menu.Item>
<Link <Link
href="mailto:support@kan.bn" href="mailto:support@kan.bn"

View File

@@ -1,12 +1,14 @@
import { Button, Menu, Transition } from "@headlessui/react"; import { Button, Menu, Transition } from "@headlessui/react";
import { t } from "@lingui/core/macro"; 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 { HiCheck, HiMagnifyingGlass } from "react-icons/hi2";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { useWorkspace } from "~/providers/workspace"; import { useWorkspace } from "~/providers/workspace";
import CommandPallette from "./CommandPallette"; import CommandPallette from "./CommandPallette";
import { Tooltip } from "./Tooltip";
export default function WorkspaceMenu({ export default function WorkspaceMenu({
isCollapsed = false, isCollapsed = false,
@@ -18,17 +20,17 @@ export default function WorkspaceMenu({
const { openModal } = useModal(); const { openModal } = useModal();
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
useEffect(() => { const { tooltipContent: commandPaletteShortcutTooltipContent } =
const handleKeyDown = (event: KeyboardEvent) => { useKeyboardShortcut({
if ((event.metaKey || event.ctrlKey) && event.key === "k") { type: "PRESS",
event.preventDefault(); stroke: {
setIsOpen(true); key: "k",
} modifiers: ["META"],
}; },
action: () => setIsOpen(true),
document.addEventListener("keydown", handleKeyDown); description: t`Open command menu`,
return () => document.removeEventListener("keydown", handleKeyDown); group: "GENERAL",
}, []); });
return ( return (
<> <>
@@ -84,15 +86,17 @@ export default function WorkspaceMenu({
</span> </span>
)} )}
</Menu.Button> </Menu.Button>
<Button <Tooltip content={commandPaletteShortcutTooltipContent}>
className={twMerge( <Button
"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", className={twMerge(
isCollapsed && "md:mb-2 md:h-9 md:w-9", "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)} )}
> onClick={() => setIsOpen(true)}
<HiMagnifyingGlass className="h-4 w-4" aria-hidden="true" /> >
</Button> <HiMagnifyingGlass className="h-4 w-4" aria-hidden="true" />
</Button>
</Tooltip>
</div> </div>
)} )}
</div> </div>

View File

@@ -14,6 +14,7 @@ export const env = createEnv({
* This way you can ensure the app isn't built with invalid env vars. * This way you can ensure the app isn't built with invalid env vars.
*/ */
server: { server: {
KAN_ADMIN_API_KEY: z.string().optional(),
BETTER_AUTH_SECRET: z.string(), BETTER_AUTH_SECRET: z.string(),
BETTER_AUTH_TRUSTED_ORIGINS: z BETTER_AUTH_TRUSTED_ORIGINS: z
.string() .string()
@@ -51,6 +52,8 @@ export const env = createEnv({
VK_CLIENT_SECRET: z.string().optional(), VK_CLIENT_SECRET: z.string().optional(),
LINKEDIN_CLIENT_ID: z.string().optional(), LINKEDIN_CLIENT_ID: z.string().optional(),
LINKEDIN_CLIENT_SECRET: z.string().optional(), LINKEDIN_CLIENT_SECRET: z.string().optional(),
NOVU_API_KEY: z.string().optional(),
EMAIL_UNSUBSCRIBE_SECRET: z.string().optional(),
// Generic OIDC Provider // Generic OIDC Provider
OIDC_CLIENT_ID: z.string().optional(), OIDC_CLIENT_ID: z.string().optional(),
OIDC_CLIENT_SECRET: z.string().optional(), OIDC_CLIENT_SECRET: z.string().optional(),
@@ -87,7 +90,7 @@ export const env = createEnv({
NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(), NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(),
NEXT_PUBLIC_POSTHOG_HOST: z.string().optional(), NEXT_PUBLIC_POSTHOG_HOST: z.string().optional(),
NEXT_PUBLIC_USE_STANDALONE_OUTPUT: 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_STORAGE_URL: z.string().url().optional(),
NEXT_PUBLIC_AVATAR_BUCKET_NAME: z.string().optional(), NEXT_PUBLIC_AVATAR_BUCKET_NAME: z.string().optional(),
NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME: z.string().optional(), NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME: z.string().optional(),

View File

@@ -1,4 +1,6 @@
import type { Locale as DateFnsLocale } from "date-fns";
import { useLingui } from "@lingui/react"; import { useLingui } from "@lingui/react";
import { de, enGB, es, fr, it, nl, pl, ru, ptBR} from "date-fns/locale";
import type { Locale } from "~/locales"; import type { Locale } from "~/locales";
import { useLinguiContext } from "~/providers/lingui"; import { useLinguiContext } from "~/providers/lingui";
@@ -8,6 +10,20 @@ export function useLocalisation() {
const { i18n } = useLingui(); const { i18n } = useLingui();
const { locale, setLocale, availableLocales } = useLinguiContext(); const { locale, setLocale, availableLocales } = useLinguiContext();
const dateLocaleMap: Partial<Record<Locale, DateFnsLocale>> = {
en: enGB,
fr,
de,
es,
it,
nl,
ru,
pl,
ptbr: ptBR,
};
const currentDateLocale = dateLocaleMap[locale] ?? enGB;
const handleSetLocale = async (newLocale: Locale) => { const handleSetLocale = async (newLocale: Locale) => {
await activateLocale(newLocale); await activateLocale(newLocale);
setLocale(newLocale); setLocale(newLocale);
@@ -15,9 +31,9 @@ export function useLocalisation() {
return { return {
locale, locale,
dateLocale: currentDateLocale,
setLocale: handleSetLocale, setLocale: handleSetLocale,
availableLocales, availableLocales,
formatDate: i18n.date,
formatNumber: i18n.number, formatNumber: i18n.number,
}; };
} }

View File

@@ -1,6 +0,0 @@
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
await require("pino");
await require("next-logger");
}
}

View File

@@ -13,7 +13,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:123 #: src/views/card/components/Comment.tsx:124
msgid " (edited)" msgid " (edited)"
msgstr " (bearbeitet)" msgstr " (bearbeitet)"
@@ -31,17 +31,17 @@ msgstr "{0}"
#. placeholder {1}: board?.name ?? t`Board` #. placeholder {1}: board?.name ?? t`Board`
#. placeholder {1}: workspace.name ?? t`Workspace` #. placeholder {1}: workspace.name ?? t`Workspace`
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:443 #: src/views/board/components/NewCardForm.tsx:452
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} Labels" msgstr "{0} Labels"
#. placeholder {0}: isTemplate ? "Template" : "Board" #. placeholder {0}: isTemplate ? "Template" : "Board"
#: src/views/board/index.tsx:400 #: src/views/board/index.tsx:408
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} nicht gefunden" msgstr "{0} nicht gefunden"
@@ -83,8 +83,8 @@ msgstr "Konto gelöscht"
msgid "Actions" msgid "Actions"
msgstr "Aktionen" msgstr "Aktionen"
#: src/views/card/index.tsx:343 #: src/views/card/index.tsx:386
#: src/views/public/board/CardModal.tsx:157 #: src/views/public/board/CardModal.tsx:158
msgid "Activity" msgid "Activity"
msgstr "Aktivität" msgstr "Aktivität"
@@ -100,12 +100,12 @@ msgstr "Aktivitätsprotokolle"
msgid "Add a card" msgid "Add a card"
msgstr "Karte hinzufügen" msgstr "Karte hinzufügen"
#: src/views/card/components/Comment.tsx:146 #: src/views/card/components/Comment.tsx:147
#: src/views/card/components/NewCommentForm.tsx:57 #: src/views/card/components/NewCommentForm.tsx:55
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Kommentar hinzufügen..." msgstr "Kommentar hinzufügen..."
#: src/views/card/components/NewChecklistItemForm.tsx:140 #: src/views/card/components/NewChecklistItemForm.tsx:141
msgid "Add an item..." msgid "Add an item..."
msgstr "Element hinzufügen..." msgstr "Element hinzufügen..."
@@ -117,48 +117,53 @@ msgstr "Checkliste hinzufügen"
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Beschreibung hinzufügen... (tippe '/' um Befehle zu öffnen oder '@' um jemanden zu erwähnen)" msgstr "Beschreibung hinzufügen... (tippe '/' um Befehle zu öffnen oder '@' um jemanden zu erwähnen)"
#: src/views/card/components/ChecklistItemRow.tsx:172 #: src/views/card/components/ChecklistItemRow.tsx:195
msgid "Add details..." msgid "Add details..."
msgstr "Details hinzufügen..." msgstr "Details hinzufügen..."
#: src/views/card/components/LabelSelector.tsx:109 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:114 #: src/views/card/components/LabelSelector.tsx:115
msgid "Add label" msgid "Add label"
msgstr "Label hinzufügen" msgstr "Label hinzufügen"
#: src/views/card/components/MemberSelector.tsx:130 #: src/views/card/components/MemberSelector.tsx:131
#: src/views/members/components/InviteMemberForm.tsx:257 #: src/views/members/components/InviteMemberForm.tsx:257
msgid "Add member" msgid "Add member"
msgstr "Mitglied hinzufügen" msgstr "Mitglied hinzufügen"
#: src/views/card/components/ActivityList.tsx:69 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:77
msgid "added {0} labels: <0>{labelList}</0>"
msgstr "{0} Labels hinzugefügt: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:107
msgid "added a checklist" msgid "added a checklist"
msgstr "hat eine Checkliste hinzugefügt" msgstr "hat eine Checkliste hinzugefügt"
#: src/views/card/components/ActivityList.tsx:72 #: src/views/card/components/ActivityList.tsx:110
msgid "added a checklist item" msgid "added a checklist item"
msgstr "hat ein Checklistenelement hinzugefügt" msgstr "hat ein Checklistenelement hinzugefügt"
#: src/views/card/components/ActivityList.tsx:65 #: src/views/card/components/ActivityList.tsx:103
msgid "added a label to the card" msgid "added a label to the card"
msgstr "hat ein Label zur Karte hinzugefügt" msgstr "hat ein Label zur Karte hinzugefügt"
#: src/views/card/components/ActivityList.tsx:67 #: src/views/card/components/ActivityList.tsx:105
msgid "added a member to the card" msgid "added a member to the card"
msgstr "hat ein Mitglied zur Karte hinzugefügt" msgstr "hat ein Mitglied zur Karte hinzugefügt"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146 #: src/views/card/components/ActivityList.tsx:181
msgid "added checklist <0>{0}</0>" msgid "added checklist <0>{0}</0>"
msgstr "hat Checkliste <0>{0}</0> hinzugefügt" msgstr "hat Checkliste <0>{0}</0> hinzugefügt"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170 #: src/views/card/components/ActivityList.tsx:205
msgid "added checklist item <0>{0}</0>" msgid "added checklist item <0>{0}</0>"
msgstr "hat Checklistenelement <0>{0}</0> hinzugefügt" msgstr "hat Checklistenelement <0>{0}</0> hinzugefügt"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130 #: src/views/card/components/ActivityList.tsx:165
msgid "added label <0>{0}</0>" msgid "added label <0>{0}</0>"
msgstr "hat Label <0>{0}</0> hinzugefügt" msgstr "hat Label <0>{0}</0> hinzugefügt"
@@ -249,11 +254,11 @@ msgstr "Sind Sie sicher, dass Sie diese(n) {0} löschen möchten?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Bist du sicher, dass du diese Karte löschen möchtest?" msgstr "Bist du sicher, dass du diese Karte löschen möchtest?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55 #: src/views/card/components/DeleteChecklistConfirmation.tsx:56
msgid "Are you sure you want to delete this checklist?" msgid "Are you sure you want to delete this checklist?"
msgstr "Sind Sie sicher, dass Sie diese Checkliste löschen möchten?" msgstr "Sind Sie sicher, dass Sie diese Checkliste löschen möchten?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:66
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Bist du sicher, dass du diesen Kommentar löschen möchtest?" msgstr "Bist du sicher, dass du diesen Kommentar löschen möchtest?"
@@ -266,7 +271,7 @@ msgid "Are you sure you want to delete your account?"
msgstr "Bist du sicher, dass du dein Konto löschen möchtest?" msgstr "Bist du sicher, dass du dein Konto löschen möchtest?"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:145
msgid "assigned <0>{0}</0> to the card" msgid "assigned <0>{0}</0> to the card"
msgstr "hat <0>{0}</0> der Karte zugewiesen" msgstr "hat <0>{0}</0> der Karte zugewiesen"
@@ -274,7 +279,7 @@ msgstr "hat <0>{0}</0> der Karte zugewiesen"
msgid "Assignees" msgid "Assignees"
msgstr "Zugewiesene Personen" msgstr "Zugewiesene Personen"
#: src/views/card/components/AttachmentUpload.tsx:25 #: src/views/card/components/AttachmentUpload.tsx:26
msgid "Attachment uploaded" msgid "Attachment uploaded"
msgstr "Anhang hochgeladen" msgstr "Anhang hochgeladen"
@@ -312,9 +317,9 @@ msgstr "Abrechnungsportal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blogbeitrag" msgstr "Blogbeitrag"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
msgid "Board" msgid "Board"
msgstr "Board" msgstr "Board"
@@ -331,7 +336,7 @@ msgstr "Der Name des Boards darf 100 Zeichen nicht überschreiten"
msgid "Board name is required" msgid "Board name is required"
msgstr "Boardname ist erforderlich" msgstr "Boardname ist erforderlich"
#: src/views/public/board/index.tsx:153 #: src/views/public/board/index.tsx:166
msgid "Board not found" msgid "Board not found"
msgstr "Board nicht gefunden" msgstr "Board nicht gefunden"
@@ -347,7 +352,7 @@ msgstr "Board-URL darf nur Buchstaben, Zahlen und Bindestriche enthalten"
msgid "Board URL cannot exceed 60 characters" msgid "Board URL cannot exceed 60 characters"
msgstr "Board-URL darf 60 Zeichen nicht überschreiten" msgstr "Board-URL darf 60 Zeichen nicht überschreiten"
#: src/views/public/board/index.tsx:68 #: src/views/public/board/index.tsx:80
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "Board-URL in die Zwischenablage kopiert" msgstr "Board-URL in die Zwischenablage kopiert"
@@ -382,10 +387,10 @@ msgstr "Fehlerbericht"
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:49
#: src/views/board/components/DeleteBoardConfirmation.tsx:44 #: src/views/board/components/DeleteBoardConfirmation.tsx:44
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:159
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63 #: src/views/card/components/DeleteChecklistConfirmation.tsx:64
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:77
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/settings/components/Avatar.tsx:306 #: src/views/settings/components/Avatar.tsx:306
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168 #: src/views/settings/components/ChangePasswordConfirmation.tsx:168
@@ -395,16 +400,16 @@ msgstr "Fehlerbericht"
msgid "Cancel" msgid "Cancel"
msgstr "Abbrechen" msgstr "Abbrechen"
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "Card" msgid "Card"
msgstr "Karte" msgstr "Karte"
#: src/views/card/index.tsx:263 #: src/views/card/index.tsx:306
#: src/views/card/index.tsx:299 #: src/views/card/index.tsx:342
msgid "Card not found" msgid "Card not found"
msgstr "Karte nicht gefunden" msgstr "Karte nicht gefunden"
#: src/views/board/components/NewCardForm.tsx:310 #: src/views/board/components/NewCardForm.tsx:319
msgid "Card title" msgid "Card title"
msgstr "Kartentitel" msgstr "Kartentitel"
@@ -419,6 +424,11 @@ msgstr "Passwort ändern"
msgid "Change your language preferences." msgid "Change your language preferences."
msgstr "Ändern Sie Ihre Spracheinstellungen." msgstr "Ändern Sie Ihre Spracheinstellungen."
#: src/views/card/components/ActivityList.tsx:255
#: src/views/card/components/ActivityList.tsx:269
msgid "changed the due date to <0>{formattedDate}</0>"
msgstr "hat den Fälligkeitstermin auf <0>{formattedDate}</0> geändert"
#: src/views/oss-friends/index.tsx:61 #: src/views/oss-friends/index.tsx:61
msgid "Check out some of our favorite open source projects." msgid "Check out some of our favorite open source projects."
msgstr "Entdecken Sie einige unserer liebsten Open-Source-Projekte." msgstr "Entdecken Sie einige unserer liebsten Open-Source-Projekte."
@@ -428,7 +438,7 @@ msgstr "Entdecken Sie einige unserer liebsten Open-Source-Projekte."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Überprüfe deinen Posteingang" msgstr "Überprüfe deinen Posteingang"
#: src/views/card/components/NewChecklistForm.tsx:118 #: src/views/card/components/NewChecklistForm.tsx:119
msgid "Checklist name" msgid "Checklist name"
msgstr "Checklistenname" msgstr "Checklistenname"
@@ -437,7 +447,7 @@ msgstr "Checklistenname"
msgid "Checklists" msgid "Checklists"
msgstr "Checklisten" msgstr "Checklisten"
#: src/views/board/components/Filters.tsx:180 #: src/views/board/components/Filters.tsx:227
msgid "Clear filters" msgid "Clear filters"
msgstr "Filter löschen" msgstr "Filter löschen"
@@ -489,15 +499,19 @@ msgstr "Abgeschlossen"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Vollständige Kontrolle und Eigentum:" msgstr "Vollständige Kontrolle und Eigentum:"
#: src/views/card/components/ActivityList.tsx:74 #: src/views/card/components/ActivityList.tsx:112
msgid "completed a checklist item" msgid "completed a checklist item"
msgstr "hat ein Checklistenelement abgeschlossen" msgstr "hat ein Checklistenelement abgeschlossen"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187 #: src/views/card/components/ActivityList.tsx:222
msgid "completed checklist item <0>{0}</0>" msgid "completed checklist item <0>{0}</0>"
msgstr "hat Checklistenelement <0>{0}</0> abgeschlossen" 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 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password" msgid "Confirm your new password"
msgstr "Bestätigen Sie Ihr neues Passwort" msgstr "Bestätigen Sie Ihr neues Passwort"
@@ -551,7 +565,7 @@ msgid "Create {0}"
msgstr "{0} erstellen" msgstr "{0} erstellen"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:469 #: src/views/board/components/NewCardForm.tsx:516
#: src/views/board/components/NewListForm.tsx:141 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Weitere erstellen" msgstr "Weitere erstellen"
@@ -560,11 +574,11 @@ msgstr "Weitere erstellen"
msgid "Create API key" msgid "Create API key"
msgstr "API-Schlüssel erstellen" msgstr "API-Schlüssel erstellen"
#: src/views/board/components/NewCardForm.tsx:479 #: src/views/board/components/NewCardForm.tsx:526
msgid "Create card" msgid "Create card"
msgstr "Karte erstellen" msgstr "Karte erstellen"
#: src/views/card/components/NewChecklistForm.tsx:134 #: src/views/card/components/NewChecklistForm.tsx:135
msgid "Create checklist" msgid "Create checklist"
msgstr "Checkliste erstellen" msgstr "Checkliste erstellen"
@@ -590,13 +604,13 @@ msgstr "Neue(n) {0} erstellen"
msgid "Create new key" msgid "Create new key"
msgstr "Neuen Schlüssel erstellen" msgstr "Neuen Schlüssel erstellen"
#: src/views/board/components/NewCardForm.tsx:405 #: src/views/board/components/NewCardForm.tsx:414
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:98
msgid "Create new label" msgid "Create new label"
msgstr "Neues Label erstellen" msgstr "Neues Label erstellen"
#: src/views/board/index.tsx:64 #: src/views/board/index.tsx:64
#: src/views/board/index.tsx:491 #: src/views/board/index.tsx:499
msgid "Create new list" msgid "Create new list"
msgstr "Neue Liste erstellen" msgstr "Neue Liste erstellen"
@@ -609,7 +623,7 @@ msgstr "Vorlage erstellen"
msgid "Create workspace" msgid "Create workspace"
msgstr "Arbeitsbereich erstellen" msgstr "Arbeitsbereich erstellen"
#: src/views/card/components/ActivityList.tsx:61 #: src/views/card/components/ActivityList.tsx:99
msgid "created the card" msgid "created the card"
msgstr "hat die Karte erstellt" msgstr "hat die Karte erstellt"
@@ -667,8 +681,8 @@ msgstr "Einladungslink deaktivieren"
#: src/components/LabelForm.tsx:228 #: src/components/LabelForm.tsx:228
#: src/views/board/components/DeleteBoardConfirmation.tsx:47 #: src/views/board/components/DeleteBoardConfirmation.tsx:47
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66 #: src/views/card/components/DeleteChecklistConfirmation.tsx:67
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:83
msgid "Delete" msgid "Delete"
msgstr "Löschen" msgstr "Löschen"
@@ -686,7 +700,7 @@ msgstr "Board löschen"
msgid "Delete card" msgid "Delete card"
msgstr "Karte löschen" msgstr "Karte löschen"
#: src/views/card/components/Comment.tsx:91 #: src/views/card/components/Comment.tsx:92
msgid "Delete comment" msgid "Delete comment"
msgstr "Kommentar löschen" msgstr "Kommentar löschen"
@@ -704,21 +718,21 @@ msgstr "Vorlage löschen"
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Workspace löschen" msgstr "Workspace löschen"
#: src/views/card/components/ActivityList.tsx:71 #: src/views/card/components/ActivityList.tsx:109
msgid "deleted a checklist" msgid "deleted a checklist"
msgstr "hat eine Checkliste gelöscht" msgstr "hat eine Checkliste gelöscht"
#: src/views/card/components/ActivityList.tsx:76 #: src/views/card/components/ActivityList.tsx:114
msgid "deleted a checklist item" msgid "deleted a checklist item"
msgstr "hat ein Checklistenelement gelöscht" msgstr "hat ein Checklistenelement gelöscht"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162 #: src/views/card/components/ActivityList.tsx:197
msgid "deleted checklist <0>{0}</0>" msgid "deleted checklist <0>{0}</0>"
msgstr "hat Checkliste <0>{0}</0> gelöscht" msgstr "hat Checkliste <0>{0}</0> gelöscht"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205 #: src/views/card/components/ActivityList.tsx:240
msgid "deleted checklist item <0>{0}</0>" msgid "deleted checklist item <0>{0}</0>"
msgstr "hat Checklistenelement <0>{0}</0> gelöscht" msgstr "hat Checklistenelement <0>{0}</0> gelöscht"
@@ -754,6 +768,10 @@ msgstr "Anzeigename aktualisiert"
msgid "Do you offer a free plan?" msgid "Do you offer a free plan?"
msgstr "Bietet ihr einen kostenlosen Plan an?" 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 #: src/components/FeedbackModal.tsx:109
msgid "docs" msgid "docs"
msgstr "Dokumente" msgstr "Dokumente"
@@ -780,16 +798,38 @@ msgstr "Du hast noch kein Konto? <0><1>Registrieren</1></0>"
msgid "Done" msgid "Done"
msgstr "Erledigt" msgstr "Erledigt"
#: src/views/card/components/AttachmentThumbnails.tsx:141 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "Download failed" msgid "Download failed"
msgstr "Download fehlgeschlagen" msgstr "Download fehlgeschlagen"
#: src/views/board/components/Filters.tsx:171
#: src/views/board/components/NewCardForm.tsx:469
#: src/views/card/index.tsx:139
msgid "Due date"
msgstr "Fälligkeitsdatum"
#: src/views/board/components/Filters.tsx:132
msgid "Due next month"
msgstr "Fällig nächsten Monat"
#: src/views/board/components/Filters.tsx:127
msgid "Due next week"
msgstr "Fällig nächste Woche"
#: src/views/board/components/Filters.tsx:117
msgid "Due today"
msgstr "Heute fällig"
#: src/views/board/components/Filters.tsx:122
msgid "Due tomorrow"
msgstr "Morgen fällig"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:116 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Board-URL bearbeiten" msgstr "Board-URL bearbeiten"
#: src/views/card/components/Comment.tsx:82 #: src/views/card/components/Comment.tsx:83
msgid "Edit comment" msgid "Edit comment"
msgstr "Kommentar bearbeiten" msgstr "Kommentar bearbeiten"
@@ -946,8 +986,8 @@ msgstr "Board konnte nicht erstellt werden"
msgid "Failed to login with {0}. Please try again." msgid "Failed to login with {0}. Please try again."
msgstr "Anmeldung mit {0} fehlgeschlagen. Bitte versuche es erneut." msgstr "Anmeldung mit {0} fehlgeschlagen. Bitte versuche es erneut."
#: src/views/card/components/AttachmentUpload.tsx:33 #: src/views/card/components/AttachmentUpload.tsx:34
#: src/views/card/components/AttachmentUpload.tsx:79 #: src/views/card/components/AttachmentUpload.tsx:80
msgid "Failed to upload attachment. Please try again." msgid "Failed to upload attachment. Please try again."
msgstr "Fehler beim Hochladen des Anhangs. Bitte versuchen Sie es erneut." msgstr "Fehler beim Hochladen des Anhangs. Bitte versuchen Sie es erneut."
@@ -994,7 +1034,7 @@ msgstr "Feedback"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Feedback gesendet" msgstr "Feedback gesendet"
#: src/views/board/components/Filters.tsx:174 #: src/views/board/components/Filters.tsx:221
msgid "Filter" msgid "Filter"
msgstr "Filter" msgstr "Filter"
@@ -1052,7 +1092,7 @@ msgstr "Loslegen"
msgid "Get started by creating a new {0}" msgid "Get started by creating a new {0}"
msgstr "Beginnen Sie, indem Sie eine(n) neue(n) {0} erstellen" msgstr "Beginnen Sie, indem Sie eine(n) neue(n) {0} erstellen"
#: src/views/board/index.tsx:483 #: src/views/board/index.tsx:491
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Beginne mit dem Erstellen einer neuen Liste" msgstr "Beginne mit dem Erstellen einer neuen Liste"
@@ -1239,7 +1279,7 @@ msgstr "Einladungslinks"
msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace."
msgstr "Einladungslinks erfordern ein Team- oder Pro-Abonnement. Bitte upgraden Sie Ihren Workspace." msgstr "Einladungslinks erfordern ein Team- oder Pro-Abonnement. Bitte upgraden Sie Ihren Workspace."
#: src/views/card/components/MemberSelector.tsx:111 #: src/views/card/components/MemberSelector.tsx:112
#: src/views/members/components/InviteMemberForm.tsx:367 #: src/views/members/components/InviteMemberForm.tsx:367
msgid "Invite member" msgid "Invite member"
msgstr "Mitglied einladen" msgstr "Mitglied einladen"
@@ -1286,9 +1326,9 @@ msgstr "Beachten Sie, dass diese Aktion nicht rückgängig gemacht werden kann."
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "Tastaturkürzel" msgstr "Tastaturkürzel"
#: src/views/board/components/Filters.tsx:115 #: src/views/board/components/Filters.tsx:155
#: src/views/board/components/NewCardForm.tsx:409 #: src/views/board/components/NewCardForm.tsx:418
#: src/views/card/index.tsx:119 #: src/views/card/index.tsx:121
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -1338,11 +1378,11 @@ msgstr "Lizenz"
msgid "Light" msgid "Light"
msgstr "Hell" msgstr "Hell"
#: src/views/public/board/index.tsx:66 #: src/views/public/board/index.tsx:78
msgid "Link copied" msgid "Link copied"
msgstr "Link kopiert" msgstr "Link kopiert"
#: src/views/card/index.tsx:111 #: src/views/card/index.tsx:113
msgid "List" msgid "List"
msgstr "Liste" msgstr "Liste"
@@ -1350,10 +1390,18 @@ msgstr "Liste"
msgid "List name" msgid "List name"
msgstr "Listenname" msgstr "Listenname"
#: src/views/board/components/Filters.tsx:123 #: src/views/board/components/Filters.tsx:163
msgid "Lists" msgid "Lists"
msgstr "Listen" msgstr "Listen"
#: src/views/card/components/ActivityList.tsx:530
msgid "Load more activities"
msgstr "Weitere Aktivitäten laden"
#: src/views/card/components/ActivityList.tsx:530
msgid "Loading..."
msgstr "Wird geladen..."
#: src/views/auth/login/index.tsx:33 #: src/views/auth/login/index.tsx:33
msgid "Login | kan.bn" msgid "Login | kan.bn"
msgstr "Login | kan.bn" msgstr "Login | kan.bn"
@@ -1382,12 +1430,12 @@ msgstr "Magic Link"
msgid "Make template" msgid "Make template"
msgstr "Als Vorlage speichern" msgstr "Als Vorlage speichern"
#: src/views/card/components/ActivityList.tsx:75 #: src/views/card/components/ActivityList.tsx:113
msgid "marked a checklist item as incomplete" msgid "marked a checklist item as incomplete"
msgstr "hat ein Checklistenelement als unvollständig markiert" msgstr "hat ein Checklistenelement als unvollständig markiert"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196 #: src/views/card/components/ActivityList.tsx:231
msgid "marked checklist item <0>{0}</0> as incomplete" msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "hat Checklistenelement <0>{0}</0> als unvollständig markiert" msgstr "hat Checklistenelement <0>{0}</0> als unvollständig markiert"
@@ -1396,9 +1444,9 @@ msgid "Medium Priority"
msgstr "Mittlere Priorität" msgstr "Mittlere Priorität"
#: src/components/SideNavigation.tsx:121 #: src/components/SideNavigation.tsx:121
#: src/views/board/components/Filters.tsx:107 #: src/views/board/components/Filters.tsx:147
#: src/views/board/components/NewCardForm.tsx:367 #: src/views/board/components/NewCardForm.tsx:376
#: src/views/card/index.tsx:128 #: src/views/card/index.tsx:130
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Mitglieder" msgstr "Mitglieder"
@@ -1419,11 +1467,11 @@ msgstr "monatliche Abrechnung"
#. placeholder {0}: truncate(fromList) #. placeholder {0}: truncate(fromList)
#. placeholder {1}: truncate(toList) #. placeholder {1}: truncate(toList)
#: src/views/card/components/ActivityList.tsx:98 #: src/views/card/components/ActivityList.tsx:133
msgid "moved the card from <0>{0}</0> to<1>{1}</1>" msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "hat die Karte von <0>{0}</0> nach <1>{1}</1> verschoben" msgstr "hat die Karte von <0>{0}</0> nach <1>{1}</1> verschoben"
#: src/views/card/components/ActivityList.tsx:64 #: src/views/card/components/ActivityList.tsx:102
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "hat die Karte in eine andere Liste verschoben" msgstr "hat die Karte in eine andere Liste verschoben"
@@ -1455,11 +1503,11 @@ msgstr "Neue(r) {0}"
msgid "New API key" msgid "New API key"
msgstr "Neuer API-Schlüssel" msgstr "Neuer API-Schlüssel"
#: src/views/board/components/NewCardForm.tsx:293 #: src/views/board/components/NewCardForm.tsx:302
msgid "New card" msgid "New card"
msgstr "Neue Karte" msgstr "Neue Karte"
#: src/views/card/components/NewChecklistForm.tsx:102 #: src/views/card/components/NewChecklistForm.tsx:103
msgid "New checklist" msgid "New checklist"
msgstr "Neue Checkliste" msgstr "Neue Checkliste"
@@ -1472,7 +1520,7 @@ msgid "New label"
msgstr "Neues Label" msgstr "Neues Label"
#: src/views/board/components/NewListForm.tsx:113 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:454 #: src/views/board/index.tsx:462
msgid "New list" msgid "New list"
msgstr "Neue Liste" msgstr "Neue Liste"
@@ -1521,7 +1569,11 @@ msgstr "Keine Boards gefunden"
msgid "No credit card required" msgid "No credit card required"
msgstr "Keine Kreditkarte erforderlich" msgstr "Keine Kreditkarte erforderlich"
#: src/views/card/components/AttachmentThumbnails.tsx:142 #: src/views/board/components/Filters.tsx:137
msgid "No dates"
msgstr "Keine Termine"
#: src/views/card/components/AttachmentThumbnails.tsx:143
msgid "No download URL available for this attachment." msgid "No download URL available for this attachment."
msgstr "Für diesen Anhang ist keine Download-URL verfügbar." msgstr "Für diesen Anhang ist keine Download-URL verfügbar."
@@ -1529,7 +1581,7 @@ msgstr "Für diesen Anhang ist keine Download-URL verfügbar."
msgid "No keyboard shortcuts registered." msgid "No keyboard shortcuts registered."
msgstr "Keine Tastaturkürzel registriert." msgstr "Keine Tastaturkürzel registriert."
#: src/views/board/index.tsx:480 #: src/views/board/index.tsx:488
msgid "No lists" msgid "No lists"
msgstr "Keine Listen" msgstr "Keine Listen"
@@ -1582,6 +1634,10 @@ msgstr "Organisiere und finde Karten schnell mit leistungsstarken Filterwerkzeug
msgid "OSS Friends" msgid "OSS Friends"
msgstr "OSS-Freunde" msgstr "OSS-Freunde"
#: src/views/board/components/Filters.tsx:112
msgid "Overdue"
msgstr "Überfällig"
#: src/views/pricing/components/Pricing.tsx:73 #: src/views/pricing/components/Pricing.tsx:73
#: src/views/pricing/components/PricingTiers.tsx:70 #: src/views/pricing/components/PricingTiers.tsx:70
msgid "Own your data" msgid "Own your data"
@@ -1670,30 +1726,33 @@ msgstr "Bitte wähle eine Datei zum Hochladen aus."
#: src/components/DeleteLabelConfirmation.tsx:26 #: src/components/DeleteLabelConfirmation.tsx:26
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/NewWorkspaceForm.tsx:158 #: src/components/NewWorkspaceForm.tsx:158
#: src/views/board/components/NewCardForm.tsx:177 #: src/views/board/components/NewCardForm.tsx:184
#: src/views/board/components/NewListForm.tsx:79 #: src/views/board/components/NewListForm.tsx:79
#: src/views/board/components/NewTemplateForm.tsx:61 #: src/views/board/components/NewTemplateForm.tsx:61
#: src/views/board/components/NewTemplateForm.tsx:77 #: src/views/board/components/NewTemplateForm.tsx:77
#: src/views/board/components/UpdateBoardSlugForm.tsx:73 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:54 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:162 #: src/views/board/index.tsx:170
#: src/views/board/index.tsx:218 #: src/views/board/index.tsx:226
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/card/components/AttachmentThumbnails.tsx:73 #: src/views/card/components/AttachmentThumbnails.tsx:74
#: src/views/card/components/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:67
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:95
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:47
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Checklists.tsx:81
#: src/views/card/components/Comment.tsx:65
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37 #: src/views/card/components/DeleteChecklistConfirmation.tsx:38
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:46
#: src/views/card/components/LabelSelector.tsx:72 #: src/views/card/components/DueDateSelector.tsx:60
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/MemberSelector.tsx:79 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistForm.tsx:71
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewChecklistItemForm.tsx:90
#: src/views/card/index.tsx:177 #: src/views/card/components/NewCommentForm.tsx:32
#: src/views/card/index.tsx:187
#: src/views/card/index.tsx:200
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/members/components/InviteMemberForm.tsx:104 #: src/views/members/components/InviteMemberForm.tsx:104
#: src/views/members/components/InviteMemberForm.tsx:241 #: src/views/members/components/InviteMemberForm.tsx:241
@@ -1793,30 +1852,40 @@ msgstr "Entfernen"
msgid "Remove member" msgid "Remove member"
msgstr "Mitglied entfernen" msgstr "Mitglied entfernen"
#: src/views/card/components/ActivityList.tsx:66 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:91
msgid "removed {0} labels: <0>{labelList}</0>"
msgstr "{0} Labels entfernt: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:104
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "hat ein Label von der Karte entfernt" msgstr "hat ein Label von der Karte entfernt"
#: src/views/card/components/ActivityList.tsx:68 #: src/views/card/components/ActivityList.tsx:106
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "hat ein Mitglied von der Karte entfernt" msgstr "hat ein Mitglied von der Karte entfernt"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138 #: src/views/card/components/ActivityList.tsx:173
msgid "removed label <0>{0}</0>" msgid "removed label <0>{0}</0>"
msgstr "hat Label <0>{0}</0> entfernt" msgstr "hat Label <0>{0}</0> entfernt"
#: src/views/card/components/ActivityList.tsx:70 #: src/views/card/components/ActivityList.tsx:117
#: src/views/card/components/ActivityList.tsx:276
msgid "removed the due date"
msgstr "hat den Fälligkeitstermin entfernt"
#: src/views/card/components/ActivityList.tsx:108
msgid "renamed a checklist" msgid "renamed a checklist"
msgstr "hat eine Checkliste umbenannt" msgstr "hat eine Checkliste umbenannt"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154 #: src/views/card/components/ActivityList.tsx:189
msgid "renamed checklist <0>{0}</0>" msgid "renamed checklist <0>{0}</0>"
msgstr "hat Checkliste <0>{0}</0> umbenannt" msgstr "hat Checkliste <0>{0}</0> umbenannt"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178 #: src/views/card/components/ActivityList.tsx:213
msgid "renamed checklist item to <0>{0}</0>" msgid "renamed checklist item to <0>{0}</0>"
msgstr "hat Checklistenelement in <0>{0}</0> umbenannt" msgstr "hat Checklistenelement in <0>{0}</0> umbenannt"
@@ -1855,7 +1924,7 @@ msgstr "Rolle"
msgid "Run on your own infrastructure" msgid "Run on your own infrastructure"
msgstr "Auf eigener Infrastruktur betreiben" msgstr "Auf eigener Infrastruktur betreiben"
#: src/views/card/components/Comment.tsx:165 #: src/views/card/components/Comment.tsx:166
#: src/views/settings/components/Avatar.tsx:309 #: src/views/settings/components/Avatar.tsx:309
msgid "Save" msgid "Save"
msgstr "Speichern" msgstr "Speichern"
@@ -1893,7 +1962,7 @@ msgstr "Selbst hosten"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Selbst hosten mit Github" msgstr "Selbst hosten mit Github"
#: src/views/card/components/ActivityList.tsx:107 #: src/views/card/components/ActivityList.tsx:142
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "hat sich selbst die Karte zugewiesen" msgstr "hat sich selbst die Karte zugewiesen"
@@ -1909,6 +1978,14 @@ msgstr "Feedback senden"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/card/components/DueDateSelector.tsx:117
msgid "Set due date"
msgstr "Fälligkeitsdatum festlegen"
#: src/views/card/components/ActivityList.tsx:115
msgid "set the due date"
msgstr "hat den Fälligkeitstermin festgelegt"
#: src/components/SettingsLayout.tsx:82 #: src/components/SettingsLayout.tsx:82
#: src/components/SideNavigation.tsx:133 #: src/components/SideNavigation.tsx:133
msgid "Settings" msgid "Settings"
@@ -2030,8 +2107,8 @@ msgstr "Team-Plan"
msgid "Teams" msgid "Teams"
msgstr "Teams" msgstr "Teams"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/board/index.tsx:409 #: src/views/board/index.tsx:417
msgid "Template" msgid "Template"
msgstr "Vorlage" msgstr "Vorlage"
@@ -2096,8 +2173,8 @@ msgstr "Sie werden keinen Zugriff mehr auf diesen Workspace haben."
#: src/components/DeleteLabelConfirmation.tsx:44 #: src/components/DeleteLabelConfirmation.tsx:44
#: src/views/board/components/DeleteBoardConfirmation.tsx:39 #: src/views/board/components/DeleteBoardConfirmation.tsx:39
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58 #: src/views/card/components/DeleteChecklistConfirmation.tsx:59
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:69
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Diese Aktion kann nicht rückgängig gemacht werden." msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
@@ -2105,7 +2182,7 @@ msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
msgid "This API key will only be shown once. Please save it in a secure location." msgid "This API key will only be shown once. Please save it in a secure location."
msgstr "Dieser API-Schlüssel wird nur einmal angezeigt. Bitte speichern Sie ihn an einem sicheren Ort." msgstr "Dieser API-Schlüssel wird nur einmal angezeigt. Bitte speichern Sie ihn an einem sicheren Ort."
#: src/views/public/board/index.tsx:156 #: src/views/public/board/index.tsx:169
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "Dieses Board ist privat oder existiert nicht" msgstr "Dieses Board ist privat oder existiert nicht"
@@ -2167,23 +2244,27 @@ msgstr "Trello-importe"
msgid "Triaging" msgid "Triaging"
msgstr "Priorisierung" msgstr "Priorisierung"
#: src/views/home/components/Logos.tsx:73 #: src/views/home/components/Logos.tsx:67
msgid "Trusted by fast-moving teams<0/>around the world" msgid "Trusted by fast-moving teams<0/>around the world"
msgstr "Von schnell agierenden Teams<0/>weltweit vertraut" msgstr "Von schnell agierenden Teams<0/>weltweit vertraut"
#: src/views/card/components/NewChecklistItemForm.tsx:88 #: src/views/card/components/NewChecklistItemForm.tsx:89
msgid "Unable to add checklist item" msgid "Unable to add checklist item"
msgstr "Checklistenelement kann nicht hinzugefügt werden" msgstr "Checklistenelement kann nicht hinzugefügt werden"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:31
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Kommentar konnte nicht hinzugefügt werden" msgstr "Kommentar konnte nicht hinzugefügt werden"
#: src/views/board/components/NewCardForm.tsx:174 #: src/views/card/index.tsx:199
msgid "Unable to add label"
msgstr "Label konnte nicht hinzugefügt werden"
#: src/views/board/components/NewCardForm.tsx:181
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Karte konnte nicht erstellt werden" msgstr "Karte konnte nicht erstellt werden"
#: src/views/card/components/NewChecklistForm.tsx:69 #: src/views/card/components/NewChecklistForm.tsx:70
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Checkliste kann nicht erstellt werden" msgstr "Checkliste kann nicht erstellt werden"
@@ -2200,7 +2281,7 @@ msgstr "Vorlage konnte nicht erstellt werden"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "Workspace konnte nicht erstellt werden" msgstr "Workspace konnte nicht erstellt werden"
#: src/views/card/components/AttachmentThumbnails.tsx:72 #: src/views/card/components/AttachmentThumbnails.tsx:73
msgid "Unable to delete attachment" msgid "Unable to delete attachment"
msgstr "Anhang kann nicht gelöscht werden" msgstr "Anhang kann nicht gelöscht werden"
@@ -2208,15 +2289,15 @@ msgstr "Anhang kann nicht gelöscht werden"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Karte konnte nicht gelöscht werden" msgstr "Karte konnte nicht gelöscht werden"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36 #: src/views/card/components/DeleteChecklistConfirmation.tsx:37
msgid "Unable to delete checklist" msgid "Unable to delete checklist"
msgstr "Checkliste kann nicht gelöscht werden" msgstr "Checkliste kann nicht gelöscht werden"
#: src/views/card/components/ChecklistItemRow.tsx:87 #: src/views/card/components/ChecklistItemRow.tsx:94
msgid "Unable to delete checklist item" msgid "Unable to delete checklist item"
msgstr "Checklistenelement kann nicht gelöscht werden" msgstr "Checklistenelement kann nicht gelöscht werden"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Kommentar konnte nicht gelöscht werden" msgstr "Kommentar konnte nicht gelöscht werden"
@@ -2224,6 +2305,10 @@ msgstr "Kommentar konnte nicht gelöscht werden"
msgid "Unable to remove member" msgid "Unable to remove member"
msgstr "Mitglied konnte nicht entfernt werden" msgstr "Mitglied konnte nicht entfernt werden"
#: src/views/card/components/Checklists.tsx:80
msgid "Unable to reorder checklist item"
msgstr "Checklisten-Element konnte nicht neu angeordnet werden"
#: src/components/FeedbackModal.tsx:40 #: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Feedback konnte nicht gesendet werden" msgstr "Feedback konnte nicht gesendet werden"
@@ -2236,42 +2321,46 @@ msgstr "Board-URL kann nicht aktualisiert werden"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Board-Sichtbarkeit konnte nicht aktualisiert werden" msgstr "Board-Sichtbarkeit konnte nicht aktualisiert werden"
#: src/views/board/index.tsx:217 #: src/views/board/index.tsx:225
#: src/views/card/index.tsx:176 #: src/views/card/index.tsx:186
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Karte konnte nicht aktualisiert werden" msgstr "Karte konnte nicht aktualisiert werden"
#: src/views/card/components/ChecklistNameInput.tsx:45 #: src/views/card/components/ChecklistNameInput.tsx:46
msgid "Unable to update checklist" msgid "Unable to update checklist"
msgstr "Checkliste kann nicht aktualisiert werden" msgstr "Checkliste kann nicht aktualisiert werden"
#: src/views/card/components/ChecklistItemRow.tsx:59 #: src/views/card/components/ChecklistItemRow.tsx:66
msgid "Unable to update checklist item" msgid "Unable to update checklist item"
msgstr "Checklistenelement kann nicht aktualisiert werden" msgstr "Checklistenelement kann nicht aktualisiert werden"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:64
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Kommentar konnte nicht aktualisiert werden" msgstr "Kommentar konnte nicht aktualisiert werden"
#: src/views/card/components/LabelSelector.tsx:71 #: src/views/card/components/DueDateSelector.tsx:59
msgid "Unable to update due date"
msgstr "Fälligkeitsdatum konnte nicht aktualisiert werden"
#: src/views/card/components/LabelSelector.tsx:72
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "Labels konnten nicht aktualisiert werden" msgstr "Labels konnten nicht aktualisiert werden"
#: src/views/board/index.tsx:161 #: src/views/board/index.tsx:169
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:52
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Liste konnte nicht aktualisiert werden" msgstr "Liste konnte nicht aktualisiert werden"
#: src/views/card/components/MemberSelector.tsx:78 #: src/views/card/components/MemberSelector.tsx:79
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Mitglieder konnten nicht aktualisiert werden" msgstr "Mitglieder konnten nicht aktualisiert werden"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:121 #: src/views/card/components/ActivityList.tsx:156
msgid "unassigned <0>{0}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "hat <0>{0}</0> von der Karte entfernt" msgstr "hat <0>{0}</0> von der Karte entfernt"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:153
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "hat sich selbst von der Karte entfernt" msgstr "hat sich selbst von der Karte entfernt"
@@ -2313,6 +2402,11 @@ msgstr "Unbegrenzte Mitglieder"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Unbegrenzte 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/board/components/UpdateBoardSlugForm.tsx:175
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80 #: src/views/settings/components/UpdateDisplayNameForm.tsx:80
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
@@ -2325,20 +2419,24 @@ msgstr "Aktualisieren"
msgid "Update label" msgid "Update label"
msgstr "Label aktualisieren" msgstr "Label aktualisieren"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:111
msgid "updated a checklist item" msgid "updated a checklist item"
msgstr "hat ein Checklistenelement aktualisiert" msgstr "hat ein Checklistenelement aktualisiert"
#: src/views/card/components/ActivityList.tsx:63 #: src/views/card/components/ActivityList.tsx:101
msgid "updated the description" msgid "updated the description"
msgstr "hat die Beschreibung aktualisiert" msgstr "hat die Beschreibung aktualisiert"
#: src/views/card/components/ActivityList.tsx:62 #: src/views/card/components/ActivityList.tsx:116
msgid "updated the due date"
msgstr "hat den Fälligkeitstermin aktualisiert"
#: src/views/card/components/ActivityList.tsx:100
msgid "updated the title" msgid "updated the title"
msgstr "hat den Titel aktualisiert" msgstr "hat den Titel aktualisiert"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90 #: src/views/card/components/ActivityList.tsx:125
msgid "updated the title to <0>{0}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "hat den Titel in <0>{0}</0> geändert" msgstr "hat den Titel in <0>{0}</0> geändert"
@@ -2352,8 +2450,8 @@ msgstr "Upgrade auf Pro"
msgid "Upgrade to Pro ($29/month)" msgid "Upgrade to Pro ($29/month)"
msgstr "Upgrade auf Pro ($29/Monat)" msgstr "Upgrade auf Pro ($29/Monat)"
#: src/views/card/components/AttachmentUpload.tsx:32 #: src/views/card/components/AttachmentUpload.tsx:33
#: src/views/card/components/AttachmentUpload.tsx:78 #: src/views/card/components/AttachmentUpload.tsx:79
msgid "Upload failed" msgid "Upload failed"
msgstr "Hochladen fehlgeschlagen" msgstr "Hochladen fehlgeschlagen"
@@ -2406,7 +2504,7 @@ msgstr "Verwalte deine Abrechnung und dein Abonnement."
msgid "View docs" msgid "View docs"
msgstr "Dokumentation ansehen" msgstr "Dokumentation ansehen"
#: src/views/public/board/index.tsx:129 #: src/views/public/board/index.tsx:142
msgid "View only" msgid "View only"
msgstr "Nur ansehen" msgstr "Nur ansehen"
@@ -2414,7 +2512,7 @@ msgstr "Nur ansehen"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "Sieh dir unsere roadmap an." msgstr "Sieh dir unsere roadmap an."
#: src/views/public/board/index.tsx:159 #: src/views/public/board/index.tsx:172
msgid "View workspace" msgid "View workspace"
msgstr "Workspace anzeigen" msgstr "Workspace anzeigen"
@@ -2426,6 +2524,10 @@ msgstr "Sichtbarkeit"
msgid "We are using the <0>AGPL-3.0 license</0>." msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "Wir verwenden die <0>AGPL-3.0 lizenz</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 #: src/views/home/components/Features.tsx:152
msgid "We're just getting started. " msgid "We're just getting started. "
msgstr "Wir stehen erst am anfang. " msgstr "Wir stehen erst am anfang. "
@@ -2455,10 +2557,10 @@ msgid "Why make an open source Trello?"
msgstr "Warum ein open source Trello entwickeln?" msgstr "Warum ein open source Trello entwickeln?"
#: src/components/SettingsLayout.tsx:39 #: src/components/SettingsLayout.tsx:39
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Arbeitsbereich" msgstr "Arbeitsbereich"
@@ -2564,6 +2666,10 @@ msgstr "Sie haben sich erfolgreich angemeldet."
msgid "You have been signed up successfully." msgid "You have been signed up successfully."
msgstr "Sie haben sich erfolgreich registriert." 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 #: src/views/members/components/InviteMemberForm.tsx:326
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!" 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!" msgstr "Sie haben unbegrenzte Plätze mit Ihrem Pro-Plan. Für neue Mitglieder fallen keine zusätzlichen Kosten an!"
@@ -2588,7 +2694,7 @@ msgstr "Deine Boards wurden importiert."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Dein Anzeigename wurde aktualisiert." msgstr "Dein Anzeigename wurde aktualisiert."
#: src/views/card/components/AttachmentUpload.tsx:26 #: src/views/card/components/AttachmentUpload.tsx:27
msgid "Your file has been uploaded successfully." msgid "Your file has been uploaded successfully."
msgstr "Ihre Datei wurde erfolgreich hochgeladen." msgstr "Ihre Datei wurde erfolgreich hochgeladen."
@@ -2608,6 +2714,10 @@ msgstr "Dein Trello-Konto wurde getrennt."
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Dein Trello-Konto ist verbunden." 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 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
msgid "Your workspace description has been updated." msgid "Your workspace description has been updated."
msgstr "Deine Workspace-Beschreibung wurde aktualisiert." msgstr "Deine Workspace-Beschreibung wurde aktualisiert."

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:123 #: src/views/card/components/Comment.tsx:124
msgid " (edited)" msgid " (edited)"
msgstr " (edited)" msgstr " (edited)"
@@ -31,17 +31,17 @@ msgstr "{0}"
#. placeholder {1}: board?.name ?? t`Board` #. placeholder {1}: board?.name ?? t`Board`
#. placeholder {1}: workspace.name ?? t`Workspace` #. placeholder {1}: workspace.name ?? t`Workspace`
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:443 #: src/views/board/components/NewCardForm.tsx:452
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} labels" msgstr "{0} labels"
#. placeholder {0}: isTemplate ? "Template" : "Board" #. placeholder {0}: isTemplate ? "Template" : "Board"
#: src/views/board/index.tsx:400 #: src/views/board/index.tsx:408
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} not found" msgstr "{0} not found"
@@ -95,8 +95,8 @@ msgstr "Account deleted"
msgid "Actions" msgid "Actions"
msgstr "Actions" msgstr "Actions"
#: src/views/card/index.tsx:343 #: src/views/card/index.tsx:386
#: src/views/public/board/CardModal.tsx:157 #: src/views/public/board/CardModal.tsx:158
msgid "Activity" msgid "Activity"
msgstr "Activity" msgstr "Activity"
@@ -112,12 +112,12 @@ msgstr "Activity logs"
msgid "Add a card" msgid "Add a card"
msgstr "Add a card" msgstr "Add a card"
#: src/views/card/components/Comment.tsx:146 #: src/views/card/components/Comment.tsx:147
#: src/views/card/components/NewCommentForm.tsx:57 #: src/views/card/components/NewCommentForm.tsx:55
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Add a comment..." msgstr "Add a comment..."
#: src/views/card/components/NewChecklistItemForm.tsx:140 #: src/views/card/components/NewChecklistItemForm.tsx:141
msgid "Add an item..." msgid "Add an item..."
msgstr "Add an item..." msgstr "Add an item..."
@@ -133,48 +133,53 @@ msgstr "Add description... (type '/' to open commands or '@' to mention)"
#~ msgid "Add description... (type '/' to open commands)" #~ msgid "Add description... (type '/' to open commands)"
#~ msgstr "Add description... (type '/' to open commands)" #~ msgstr "Add description... (type '/' to open commands)"
#: src/views/card/components/ChecklistItemRow.tsx:172 #: src/views/card/components/ChecklistItemRow.tsx:195
msgid "Add details..." msgid "Add details..."
msgstr "Add details..." msgstr "Add details..."
#: src/views/card/components/LabelSelector.tsx:109 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:114 #: src/views/card/components/LabelSelector.tsx:115
msgid "Add label" msgid "Add label"
msgstr "Add label" msgstr "Add label"
#: src/views/card/components/MemberSelector.tsx:130 #: src/views/card/components/MemberSelector.tsx:131
#: src/views/members/components/InviteMemberForm.tsx:257 #: src/views/members/components/InviteMemberForm.tsx:257
msgid "Add member" msgid "Add member"
msgstr "Add member" msgstr "Add member"
#: src/views/card/components/ActivityList.tsx:69 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:77
msgid "added {0} labels: <0>{labelList}</0>"
msgstr "added {0} labels: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:107
msgid "added a checklist" msgid "added a checklist"
msgstr "added a checklist" msgstr "added a checklist"
#: src/views/card/components/ActivityList.tsx:72 #: src/views/card/components/ActivityList.tsx:110
msgid "added a checklist item" msgid "added a checklist item"
msgstr "added a checklist item" msgstr "added a checklist item"
#: src/views/card/components/ActivityList.tsx:65 #: src/views/card/components/ActivityList.tsx:103
msgid "added a label to the card" msgid "added a label to the card"
msgstr "added a label to the card" msgstr "added a label to the card"
#: src/views/card/components/ActivityList.tsx:67 #: src/views/card/components/ActivityList.tsx:105
msgid "added a member to the card" msgid "added a member to the card"
msgstr "added a member to the card" msgstr "added a member to the card"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146 #: src/views/card/components/ActivityList.tsx:181
msgid "added checklist <0>{0}</0>" msgid "added checklist <0>{0}</0>"
msgstr "added checklist <0>{0}</0>" msgstr "added checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170 #: src/views/card/components/ActivityList.tsx:205
msgid "added checklist item <0>{0}</0>" msgid "added checklist item <0>{0}</0>"
msgstr "added checklist item <0>{0}</0>" msgstr "added checklist item <0>{0}</0>"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130 #: src/views/card/components/ActivityList.tsx:165
msgid "added label <0>{0}</0>" msgid "added label <0>{0}</0>"
msgstr "added label <0>{0}</0>" msgstr "added label <0>{0}</0>"
@@ -277,11 +282,11 @@ msgstr "Are you sure you want to delete this {0}?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Are you sure you want to delete this card?" msgstr "Are you sure you want to delete this card?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55 #: src/views/card/components/DeleteChecklistConfirmation.tsx:56
msgid "Are you sure you want to delete this checklist?" msgid "Are you sure you want to delete this checklist?"
msgstr "Are you sure you want to delete this checklist?" msgstr "Are you sure you want to delete this checklist?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:66
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Are you sure you want to delete this comment?" msgstr "Are you sure you want to delete this comment?"
@@ -298,7 +303,7 @@ msgstr "Are you sure you want to delete your account?"
#~ msgstr "around the world" #~ msgstr "around the world"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:145
msgid "assigned <0>{0}</0> to the card" msgid "assigned <0>{0}</0> to the card"
msgstr "assigned <0>{0}</0> to the card" msgstr "assigned <0>{0}</0> to the card"
@@ -310,7 +315,7 @@ msgstr "assigned <0>{0}</0> to the card"
msgid "Assignees" msgid "Assignees"
msgstr "Assignees" msgstr "Assignees"
#: src/views/card/components/AttachmentUpload.tsx:25 #: src/views/card/components/AttachmentUpload.tsx:26
msgid "Attachment uploaded" msgid "Attachment uploaded"
msgstr "Attachment uploaded" msgstr "Attachment uploaded"
@@ -352,9 +357,9 @@ msgstr "Billing portal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blog Post" msgstr "Blog Post"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
msgid "Board" msgid "Board"
msgstr "Board" msgstr "Board"
@@ -380,7 +385,7 @@ msgstr "Board name cannot exceed 100 characters"
msgid "Board name is required" msgid "Board name is required"
msgstr "Board name is required" msgstr "Board name is required"
#: src/views/public/board/index.tsx:153 #: src/views/public/board/index.tsx:166
msgid "Board not found" msgid "Board not found"
msgstr "Board not found" msgstr "Board not found"
@@ -396,7 +401,7 @@ msgstr "Board URL can only contain letters, numbers, and hyphens"
msgid "Board URL cannot exceed 60 characters" msgid "Board URL cannot exceed 60 characters"
msgstr "Board URL cannot exceed 60 characters" msgstr "Board URL cannot exceed 60 characters"
#: src/views/public/board/index.tsx:68 #: src/views/public/board/index.tsx:80
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "Board URL copied to clipboard" msgstr "Board URL copied to clipboard"
@@ -439,10 +444,10 @@ msgstr "Bug Report"
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:49
#: src/views/board/components/DeleteBoardConfirmation.tsx:44 #: src/views/board/components/DeleteBoardConfirmation.tsx:44
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:159
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63 #: src/views/card/components/DeleteChecklistConfirmation.tsx:64
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:77
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/settings/components/Avatar.tsx:306 #: src/views/settings/components/Avatar.tsx:306
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168 #: src/views/settings/components/ChangePasswordConfirmation.tsx:168
@@ -452,16 +457,16 @@ msgstr "Bug Report"
msgid "Cancel" msgid "Cancel"
msgstr "Cancel" msgstr "Cancel"
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "Card" msgid "Card"
msgstr "Card" msgstr "Card"
#: src/views/card/index.tsx:263 #: src/views/card/index.tsx:306
#: src/views/card/index.tsx:299 #: src/views/card/index.tsx:342
msgid "Card not found" msgid "Card not found"
msgstr "Card not found" msgstr "Card not found"
#: src/views/board/components/NewCardForm.tsx:310 #: src/views/board/components/NewCardForm.tsx:319
msgid "Card title" msgid "Card title"
msgstr "Card title" msgstr "Card title"
@@ -480,6 +485,11 @@ msgstr "Change Password"
msgid "Change your language preferences." msgid "Change your language preferences."
msgstr "Change your language preferences." msgstr "Change your language preferences."
#: src/views/card/components/ActivityList.tsx:255
#: src/views/card/components/ActivityList.tsx:269
msgid "changed the due date to <0>{formattedDate}</0>"
msgstr "changed the due date to <0>{formattedDate}</0>"
#: src/views/oss-friends/index.tsx:61 #: src/views/oss-friends/index.tsx:61
msgid "Check out some of our favorite open source projects." msgid "Check out some of our favorite open source projects."
msgstr "Check out some of our favorite open source projects." msgstr "Check out some of our favorite open source projects."
@@ -489,7 +499,7 @@ msgstr "Check out some of our favorite open source projects."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Check your inbox" msgstr "Check your inbox"
#: src/views/card/components/NewChecklistForm.tsx:118 #: src/views/card/components/NewChecklistForm.tsx:119
msgid "Checklist name" msgid "Checklist name"
msgstr "Checklist name" msgstr "Checklist name"
@@ -498,7 +508,7 @@ msgstr "Checklist name"
msgid "Checklists" msgid "Checklists"
msgstr "Checklists" msgstr "Checklists"
#: src/views/board/components/Filters.tsx:180 #: src/views/board/components/Filters.tsx:227
msgid "Clear filters" msgid "Clear filters"
msgstr "Clear filters" msgstr "Clear filters"
@@ -550,12 +560,12 @@ msgstr "Complete"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Complete control and ownership:" msgstr "Complete control and ownership:"
#: src/views/card/components/ActivityList.tsx:74 #: src/views/card/components/ActivityList.tsx:112
msgid "completed a checklist item" msgid "completed a checklist item"
msgstr "completed a checklist item" msgstr "completed a checklist item"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187 #: src/views/card/components/ActivityList.tsx:222
msgid "completed checklist item <0>{0}</0>" msgid "completed checklist item <0>{0}</0>"
msgstr "completed checklist item <0>{0}</0>" msgstr "completed checklist item <0>{0}</0>"
@@ -563,6 +573,10 @@ msgstr "completed checklist item <0>{0}</0>"
#~ msgid "Confirm URL change" #~ msgid "Confirm URL change"
#~ msgstr "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 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password" msgid "Confirm your new password"
msgstr "Confirm your new password" msgstr "Confirm your new password"
@@ -616,7 +630,7 @@ msgid "Create {0}"
msgstr "Create {0}" msgstr "Create {0}"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:469 #: src/views/board/components/NewCardForm.tsx:516
#: src/views/board/components/NewListForm.tsx:141 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Create another" msgstr "Create another"
@@ -633,11 +647,11 @@ msgstr "Create API key"
#~ msgid "Create board" #~ msgid "Create board"
#~ msgstr "Create board" #~ msgstr "Create board"
#: src/views/board/components/NewCardForm.tsx:479 #: src/views/board/components/NewCardForm.tsx:526
msgid "Create card" msgid "Create card"
msgstr "Create card" msgstr "Create card"
#: src/views/card/components/NewChecklistForm.tsx:134 #: src/views/card/components/NewChecklistForm.tsx:135
msgid "Create checklist" msgid "Create checklist"
msgstr "Create checklist" msgstr "Create checklist"
@@ -667,13 +681,13 @@ msgstr "Create new {0}"
msgid "Create new key" msgid "Create new key"
msgstr "Create new key" msgstr "Create new key"
#: src/views/board/components/NewCardForm.tsx:405 #: src/views/board/components/NewCardForm.tsx:414
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:98
msgid "Create new label" msgid "Create new label"
msgstr "Create new label" msgstr "Create new label"
#: src/views/board/index.tsx:64 #: src/views/board/index.tsx:64
#: src/views/board/index.tsx:491 #: src/views/board/index.tsx:499
msgid "Create new list" msgid "Create new list"
msgstr "Create new list" msgstr "Create new list"
@@ -690,7 +704,7 @@ msgstr "Create template"
msgid "Create workspace" msgid "Create workspace"
msgstr "Create workspace" msgstr "Create workspace"
#: src/views/card/components/ActivityList.tsx:61 #: src/views/card/components/ActivityList.tsx:99
msgid "created the card" msgid "created the card"
msgstr "created the card" msgstr "created the card"
@@ -756,8 +770,8 @@ msgstr "Deactivate invite link"
#: src/components/LabelForm.tsx:228 #: src/components/LabelForm.tsx:228
#: src/views/board/components/DeleteBoardConfirmation.tsx:47 #: src/views/board/components/DeleteBoardConfirmation.tsx:47
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66 #: src/views/card/components/DeleteChecklistConfirmation.tsx:67
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:83
msgid "Delete" msgid "Delete"
msgstr "Delete" msgstr "Delete"
@@ -775,7 +789,7 @@ msgstr "Delete board"
msgid "Delete card" msgid "Delete card"
msgstr "Delete card" msgstr "Delete card"
#: src/views/card/components/Comment.tsx:91 #: src/views/card/components/Comment.tsx:92
msgid "Delete comment" msgid "Delete comment"
msgstr "Delete comment" msgstr "Delete comment"
@@ -793,21 +807,21 @@ msgstr "Delete template"
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Delete workspace" msgstr "Delete workspace"
#: src/views/card/components/ActivityList.tsx:71 #: src/views/card/components/ActivityList.tsx:109
msgid "deleted a checklist" msgid "deleted a checklist"
msgstr "deleted a checklist" msgstr "deleted a checklist"
#: src/views/card/components/ActivityList.tsx:76 #: src/views/card/components/ActivityList.tsx:114
msgid "deleted a checklist item" msgid "deleted a checklist item"
msgstr "deleted a checklist item" msgstr "deleted a checklist item"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162 #: src/views/card/components/ActivityList.tsx:197
msgid "deleted checklist <0>{0}</0>" msgid "deleted checklist <0>{0}</0>"
msgstr "deleted checklist <0>{0}</0>" msgstr "deleted checklist <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205 #: src/views/card/components/ActivityList.tsx:240
msgid "deleted checklist item <0>{0}</0>" msgid "deleted checklist item <0>{0}</0>"
msgstr "deleted checklist item <0>{0}</0>" msgstr "deleted checklist item <0>{0}</0>"
@@ -843,6 +857,10 @@ msgstr "Display name updated"
msgid "Do you offer a free plan?" msgid "Do you offer a free plan?"
msgstr "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 #: src/components/FeedbackModal.tsx:109
msgid "docs" msgid "docs"
msgstr "docs" msgstr "docs"
@@ -869,16 +887,38 @@ msgstr "Don't have an account? <0><1>Sign up</1></0>"
msgid "Done" msgid "Done"
msgstr "Done" msgstr "Done"
#: src/views/card/components/AttachmentThumbnails.tsx:141 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "Download failed" msgid "Download failed"
msgstr "Download failed" msgstr "Download failed"
#: src/views/board/components/Filters.tsx:171
#: src/views/board/components/NewCardForm.tsx:469
#: src/views/card/index.tsx:139
msgid "Due date"
msgstr "Due date"
#: src/views/board/components/Filters.tsx:132
msgid "Due next month"
msgstr "Due next month"
#: src/views/board/components/Filters.tsx:127
msgid "Due next week"
msgstr "Due next week"
#: src/views/board/components/Filters.tsx:117
msgid "Due today"
msgstr "Due today"
#: src/views/board/components/Filters.tsx:122
msgid "Due tomorrow"
msgstr "Due tomorrow"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:116 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Edit board URL" msgstr "Edit board URL"
#: src/views/card/components/Comment.tsx:82 #: src/views/card/components/Comment.tsx:83
msgid "Edit comment" msgid "Edit comment"
msgstr "Edit comment" msgstr "Edit comment"
@@ -1035,8 +1075,8 @@ msgstr "Failed to create board"
msgid "Failed to login with {0}. Please try again." msgid "Failed to login with {0}. Please try again."
msgstr "Failed to login with {0}. Please try again." msgstr "Failed to login with {0}. Please try again."
#: src/views/card/components/AttachmentUpload.tsx:33 #: src/views/card/components/AttachmentUpload.tsx:34
#: src/views/card/components/AttachmentUpload.tsx:79 #: src/views/card/components/AttachmentUpload.tsx:80
msgid "Failed to upload attachment. Please try again." msgid "Failed to upload attachment. Please try again."
msgstr "Failed to upload attachment. Please try again." msgstr "Failed to upload attachment. Please try again."
@@ -1083,7 +1123,7 @@ msgstr "Feedback"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Feedback sent" msgstr "Feedback sent"
#: src/views/board/components/Filters.tsx:174 #: src/views/board/components/Filters.tsx:221
msgid "Filter" msgid "Filter"
msgstr "Filter" msgstr "Filter"
@@ -1155,7 +1195,7 @@ msgstr "Get started by creating a new {0}"
#~ msgid "Get started by creating a new board" #~ msgid "Get started by creating a new board"
#~ msgstr "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:491
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Get started by creating a new list" msgstr "Get started by creating a new list"
@@ -1350,7 +1390,7 @@ msgstr "Invite links"
msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace."
msgstr "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgstr "Invite links require a Team or Pro subscription. Please upgrade your workspace."
#: src/views/card/components/MemberSelector.tsx:111 #: src/views/card/components/MemberSelector.tsx:112
#: src/views/members/components/InviteMemberForm.tsx:367 #: src/views/members/components/InviteMemberForm.tsx:367
msgid "Invite member" msgid "Invite member"
msgstr "Invite member" msgstr "Invite member"
@@ -1397,9 +1437,9 @@ msgstr "Keep in mind that this action is irreversible."
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "Keyboard Shortcuts" msgstr "Keyboard Shortcuts"
#: src/views/board/components/Filters.tsx:115 #: src/views/board/components/Filters.tsx:155
#: src/views/board/components/NewCardForm.tsx:409 #: src/views/board/components/NewCardForm.tsx:418
#: src/views/card/index.tsx:119 #: src/views/card/index.tsx:121
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -1449,11 +1489,11 @@ msgstr "License"
msgid "Light" msgid "Light"
msgstr "Light" msgstr "Light"
#: src/views/public/board/index.tsx:66 #: src/views/public/board/index.tsx:78
msgid "Link copied" msgid "Link copied"
msgstr "Link copied" msgstr "Link copied"
#: src/views/card/index.tsx:111 #: src/views/card/index.tsx:113
msgid "List" msgid "List"
msgstr "List" msgstr "List"
@@ -1461,10 +1501,18 @@ msgstr "List"
msgid "List name" msgid "List name"
msgstr "List name" msgstr "List name"
#: src/views/board/components/Filters.tsx:123 #: src/views/board/components/Filters.tsx:163
msgid "Lists" msgid "Lists"
msgstr "Lists" msgstr "Lists"
#: src/views/card/components/ActivityList.tsx:530
msgid "Load more activities"
msgstr "Load more activities"
#: src/views/card/components/ActivityList.tsx:530
msgid "Loading..."
msgstr "Loading..."
#: src/views/auth/login/index.tsx:33 #: src/views/auth/login/index.tsx:33
msgid "Login | kan.bn" msgid "Login | kan.bn"
msgstr "Login | kan.bn" msgstr "Login | kan.bn"
@@ -1493,12 +1541,12 @@ msgstr "magic link"
msgid "Make template" msgid "Make template"
msgstr "Make template" msgstr "Make template"
#: src/views/card/components/ActivityList.tsx:75 #: src/views/card/components/ActivityList.tsx:113
msgid "marked a checklist item as incomplete" msgid "marked a checklist item as incomplete"
msgstr "marked a checklist item as incomplete" msgstr "marked a checklist item as incomplete"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196 #: src/views/card/components/ActivityList.tsx:231
msgid "marked checklist item <0>{0}</0> as incomplete" msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "marked checklist item <0>{0}</0> as incomplete" msgstr "marked checklist item <0>{0}</0> as incomplete"
@@ -1507,9 +1555,9 @@ msgid "Medium Priority"
msgstr "Medium Priority" msgstr "Medium Priority"
#: src/components/SideNavigation.tsx:121 #: src/components/SideNavigation.tsx:121
#: src/views/board/components/Filters.tsx:107 #: src/views/board/components/Filters.tsx:147
#: src/views/board/components/NewCardForm.tsx:367 #: src/views/board/components/NewCardForm.tsx:376
#: src/views/card/index.tsx:128 #: src/views/card/index.tsx:130
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Members" msgstr "Members"
@@ -1530,7 +1578,7 @@ msgstr "monthly billing"
#. placeholder {0}: truncate(fromList) #. placeholder {0}: truncate(fromList)
#. placeholder {1}: truncate(toList) #. placeholder {1}: truncate(toList)
#: src/views/card/components/ActivityList.tsx:98 #: src/views/card/components/ActivityList.tsx:133
msgid "moved the card from <0>{0}</0> to<1>{1}</1>" msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "moved the card from <0>{0}</0> to<1>{1}</1>" msgstr "moved the card from <0>{0}</0> to<1>{1}</1>"
@@ -1538,7 +1586,7 @@ msgstr "moved the card from <0>{0}</0> to<1>{1}</1>"
#~ msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #~ msgid "moved the card from <0>{fromList}</0> to<1>{toList}</1>"
#~ msgstr "moved the card from <0>{fromList}</0> to<1>{toList}</1>" #~ msgstr "moved the card from <0>{fromList}</0> to<1>{toList}</1>"
#: src/views/card/components/ActivityList.tsx:64 #: src/views/card/components/ActivityList.tsx:102
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "moved the card to another list" msgstr "moved the card to another list"
@@ -1578,11 +1626,11 @@ msgstr "New API key"
#~ msgid "New board" #~ msgid "New board"
#~ msgstr "New board" #~ msgstr "New board"
#: src/views/board/components/NewCardForm.tsx:293 #: src/views/board/components/NewCardForm.tsx:302
msgid "New card" msgid "New card"
msgstr "New card" msgstr "New card"
#: src/views/card/components/NewChecklistForm.tsx:102 #: src/views/card/components/NewChecklistForm.tsx:103
msgid "New checklist" msgid "New checklist"
msgstr "New checklist" msgstr "New checklist"
@@ -1595,7 +1643,7 @@ msgid "New label"
msgstr "New label" msgstr "New label"
#: src/views/board/components/NewListForm.tsx:113 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:454 #: src/views/board/index.tsx:462
msgid "New list" msgid "New list"
msgstr "New list" msgstr "New list"
@@ -1652,7 +1700,11 @@ msgstr "No boards found"
msgid "No credit card required" msgid "No credit card required"
msgstr "No credit card required" msgstr "No credit card required"
#: src/views/card/components/AttachmentThumbnails.tsx:142 #: src/views/board/components/Filters.tsx:137
msgid "No dates"
msgstr "No dates"
#: src/views/card/components/AttachmentThumbnails.tsx:143
msgid "No download URL available for this attachment." msgid "No download URL available for this attachment."
msgstr "No download URL available for this attachment." msgstr "No download URL available for this attachment."
@@ -1660,7 +1712,7 @@ msgstr "No download URL available for this attachment."
msgid "No keyboard shortcuts registered." msgid "No keyboard shortcuts registered."
msgstr "No keyboard shortcuts registered." msgstr "No keyboard shortcuts registered."
#: src/views/board/index.tsx:480 #: src/views/board/index.tsx:488
msgid "No lists" msgid "No lists"
msgstr "No lists" msgstr "No lists"
@@ -1713,6 +1765,10 @@ msgstr "Organize and find cards quickly with powerful filtering tools."
msgid "OSS Friends" msgid "OSS Friends"
msgstr "OSS Friends" msgstr "OSS Friends"
#: src/views/board/components/Filters.tsx:112
msgid "Overdue"
msgstr "Overdue"
#: src/views/pricing/components/Pricing.tsx:73 #: src/views/pricing/components/Pricing.tsx:73
#: src/views/pricing/components/PricingTiers.tsx:70 #: src/views/pricing/components/PricingTiers.tsx:70
msgid "Own your data" msgid "Own your data"
@@ -1801,30 +1857,33 @@ msgstr "Please select a file to upload."
#: src/components/DeleteLabelConfirmation.tsx:26 #: src/components/DeleteLabelConfirmation.tsx:26
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/NewWorkspaceForm.tsx:158 #: src/components/NewWorkspaceForm.tsx:158
#: src/views/board/components/NewCardForm.tsx:177 #: src/views/board/components/NewCardForm.tsx:184
#: src/views/board/components/NewListForm.tsx:79 #: src/views/board/components/NewListForm.tsx:79
#: src/views/board/components/NewTemplateForm.tsx:61 #: src/views/board/components/NewTemplateForm.tsx:61
#: src/views/board/components/NewTemplateForm.tsx:77 #: src/views/board/components/NewTemplateForm.tsx:77
#: src/views/board/components/UpdateBoardSlugForm.tsx:73 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:54 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:162 #: src/views/board/index.tsx:170
#: src/views/board/index.tsx:218 #: src/views/board/index.tsx:226
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/card/components/AttachmentThumbnails.tsx:73 #: src/views/card/components/AttachmentThumbnails.tsx:74
#: src/views/card/components/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:67
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:95
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:47
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Checklists.tsx:81
#: src/views/card/components/Comment.tsx:65
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37 #: src/views/card/components/DeleteChecklistConfirmation.tsx:38
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:46
#: src/views/card/components/LabelSelector.tsx:72 #: src/views/card/components/DueDateSelector.tsx:60
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/MemberSelector.tsx:79 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistForm.tsx:71
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewChecklistItemForm.tsx:90
#: src/views/card/index.tsx:177 #: src/views/card/components/NewCommentForm.tsx:32
#: src/views/card/index.tsx:187
#: src/views/card/index.tsx:200
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/members/components/InviteMemberForm.tsx:104 #: src/views/members/components/InviteMemberForm.tsx:104
#: src/views/members/components/InviteMemberForm.tsx:241 #: src/views/members/components/InviteMemberForm.tsx:241
@@ -1924,16 +1983,21 @@ msgstr "Remove"
msgid "Remove member" msgid "Remove member"
msgstr "Remove member" msgstr "Remove member"
#: src/views/card/components/ActivityList.tsx:66 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:91
msgid "removed {0} labels: <0>{labelList}</0>"
msgstr "removed {0} labels: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:104
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "removed a label from the card" msgstr "removed a label from the card"
#: src/views/card/components/ActivityList.tsx:68 #: src/views/card/components/ActivityList.tsx:106
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "removed a member from the card" msgstr "removed a member from the card"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138 #: src/views/card/components/ActivityList.tsx:173
msgid "removed label <0>{0}</0>" msgid "removed label <0>{0}</0>"
msgstr "removed label <0>{0}</0>" msgstr "removed label <0>{0}</0>"
@@ -1941,17 +2005,22 @@ msgstr "removed label <0>{0}</0>"
#~ msgid "removed label <0>{label}</0>" #~ msgid "removed label <0>{label}</0>"
#~ msgstr "removed label <0>{label}</0>" #~ msgstr "removed label <0>{label}</0>"
#: src/views/card/components/ActivityList.tsx:70 #: src/views/card/components/ActivityList.tsx:117
#: src/views/card/components/ActivityList.tsx:276
msgid "removed the due date"
msgstr "removed the due date"
#: src/views/card/components/ActivityList.tsx:108
msgid "renamed a checklist" msgid "renamed a checklist"
msgstr "renamed a checklist" msgstr "renamed a checklist"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154 #: src/views/card/components/ActivityList.tsx:189
msgid "renamed checklist <0>{0}</0>" msgid "renamed checklist <0>{0}</0>"
msgstr "renamed checklist <0>{0}</0>" msgstr "renamed checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178 #: src/views/card/components/ActivityList.tsx:213
msgid "renamed checklist item to <0>{0}</0>" msgid "renamed checklist item to <0>{0}</0>"
msgstr "renamed checklist item to <0>{0}</0>" msgstr "renamed checklist item to <0>{0}</0>"
@@ -1994,7 +2063,7 @@ msgstr "Role"
msgid "Run on your own infrastructure" msgid "Run on your own infrastructure"
msgstr "Run on your own infrastructure" msgstr "Run on your own infrastructure"
#: src/views/card/components/Comment.tsx:165 #: src/views/card/components/Comment.tsx:166
#: src/views/settings/components/Avatar.tsx:309 #: src/views/settings/components/Avatar.tsx:309
msgid "Save" msgid "Save"
msgstr "Save" msgstr "Save"
@@ -2032,7 +2101,7 @@ msgstr "Self Host"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Self host with Github" msgstr "Self host with Github"
#: src/views/card/components/ActivityList.tsx:107 #: src/views/card/components/ActivityList.tsx:142
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "self-assigned the card" msgstr "self-assigned the card"
@@ -2052,6 +2121,14 @@ msgstr "Send feedback"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/card/components/DueDateSelector.tsx:117
msgid "Set due date"
msgstr "Set due date"
#: src/views/card/components/ActivityList.tsx:115
msgid "set the due date"
msgstr "set the due date"
#: src/components/SettingsLayout.tsx:82 #: src/components/SettingsLayout.tsx:82
#: src/components/SideNavigation.tsx:133 #: src/components/SideNavigation.tsx:133
msgid "Settings" msgid "Settings"
@@ -2181,8 +2258,8 @@ msgstr "Team Plan"
msgid "Teams" msgid "Teams"
msgstr "Teams" msgstr "Teams"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/board/index.tsx:409 #: src/views/board/index.tsx:417
msgid "Template" msgid "Template"
msgstr "Template" msgstr "Template"
@@ -2247,8 +2324,8 @@ msgstr "They won't be able to access this workspace."
#: src/components/DeleteLabelConfirmation.tsx:44 #: src/components/DeleteLabelConfirmation.tsx:44
#: src/views/board/components/DeleteBoardConfirmation.tsx:39 #: src/views/board/components/DeleteBoardConfirmation.tsx:39
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58 #: src/views/card/components/DeleteChecklistConfirmation.tsx:59
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:69
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "This action can't be undone." msgstr "This action can't be undone."
@@ -2256,7 +2333,7 @@ msgstr "This action can't be undone."
msgid "This API key will only be shown once. Please save it in a secure location." msgid "This API key will only be shown once. Please save it in a secure location."
msgstr "This API key will only be shown once. Please save it in a secure location." msgstr "This API key will only be shown once. Please save it in a secure location."
#: src/views/public/board/index.tsx:156 #: src/views/public/board/index.tsx:169
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "This board is private or does not exist" msgstr "This board is private or does not exist"
@@ -2326,23 +2403,27 @@ msgstr "Triaging"
#~ msgid "Trusted by fast-moving teams" #~ msgid "Trusted by fast-moving teams"
#~ msgstr "Trusted by fast-moving teams" #~ msgstr "Trusted by fast-moving teams"
#: src/views/home/components/Logos.tsx:73 #: src/views/home/components/Logos.tsx:67
msgid "Trusted by fast-moving teams<0/>around the world" msgid "Trusted by fast-moving teams<0/>around the world"
msgstr "Trusted by fast-moving teams<0/>around the world" msgstr "Trusted by fast-moving teams<0/>around the world"
#: src/views/card/components/NewChecklistItemForm.tsx:88 #: src/views/card/components/NewChecklistItemForm.tsx:89
msgid "Unable to add checklist item" msgid "Unable to add checklist item"
msgstr "Unable to add checklist item" msgstr "Unable to add checklist item"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:31
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Unable to add comment" msgstr "Unable to add comment"
#: src/views/board/components/NewCardForm.tsx:174 #: src/views/card/index.tsx:199
msgid "Unable to add label"
msgstr "Unable to add label"
#: src/views/board/components/NewCardForm.tsx:181
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Unable to create card" msgstr "Unable to create card"
#: src/views/card/components/NewChecklistForm.tsx:69 #: src/views/card/components/NewChecklistForm.tsx:70
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Unable to create checklist" msgstr "Unable to create checklist"
@@ -2359,7 +2440,7 @@ msgstr "Unable to create template"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "Unable to create workspace" msgstr "Unable to create workspace"
#: src/views/card/components/AttachmentThumbnails.tsx:72 #: src/views/card/components/AttachmentThumbnails.tsx:73
msgid "Unable to delete attachment" msgid "Unable to delete attachment"
msgstr "Unable to delete attachment" msgstr "Unable to delete attachment"
@@ -2367,15 +2448,15 @@ msgstr "Unable to delete attachment"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Unable to delete card" msgstr "Unable to delete card"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36 #: src/views/card/components/DeleteChecklistConfirmation.tsx:37
msgid "Unable to delete checklist" msgid "Unable to delete checklist"
msgstr "Unable to delete checklist" msgstr "Unable to delete checklist"
#: src/views/card/components/ChecklistItemRow.tsx:87 #: src/views/card/components/ChecklistItemRow.tsx:94
msgid "Unable to delete checklist item" msgid "Unable to delete checklist item"
msgstr "Unable to delete checklist item" msgstr "Unable to delete checklist item"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Unable to delete comment" msgstr "Unable to delete comment"
@@ -2383,6 +2464,10 @@ msgstr "Unable to delete comment"
msgid "Unable to remove member" msgid "Unable to remove member"
msgstr "Unable to remove member" msgstr "Unable to remove member"
#: src/views/card/components/Checklists.tsx:80
msgid "Unable to reorder checklist item"
msgstr "Unable to reorder checklist item"
#: src/components/FeedbackModal.tsx:40 #: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Unable to send feedback" msgstr "Unable to send feedback"
@@ -2395,38 +2480,42 @@ msgstr "Unable to update board URL"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Unable to update board visibility" msgstr "Unable to update board visibility"
#: src/views/board/index.tsx:217 #: src/views/board/index.tsx:225
#: src/views/card/index.tsx:176 #: src/views/card/index.tsx:186
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Unable to update card" msgstr "Unable to update card"
#: src/views/card/components/ChecklistNameInput.tsx:45 #: src/views/card/components/ChecklistNameInput.tsx:46
msgid "Unable to update checklist" msgid "Unable to update checklist"
msgstr "Unable to update checklist" msgstr "Unable to update checklist"
#: src/views/card/components/ChecklistItemRow.tsx:59 #: src/views/card/components/ChecklistItemRow.tsx:66
msgid "Unable to update checklist item" msgid "Unable to update checklist item"
msgstr "Unable to update checklist item" msgstr "Unable to update checklist item"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:64
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Unable to update comment" msgstr "Unable to update comment"
#: src/views/card/components/LabelSelector.tsx:71 #: src/views/card/components/DueDateSelector.tsx:59
msgid "Unable to update due date"
msgstr "Unable to update due date"
#: src/views/card/components/LabelSelector.tsx:72
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "Unable to update labels" msgstr "Unable to update labels"
#: src/views/board/index.tsx:161 #: src/views/board/index.tsx:169
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:52
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Unable to update list" msgstr "Unable to update list"
#: src/views/card/components/MemberSelector.tsx:78 #: src/views/card/components/MemberSelector.tsx:79
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Unable to update members" msgstr "Unable to update members"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:121 #: src/views/card/components/ActivityList.tsx:156
msgid "unassigned <0>{0}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "unassigned <0>{0}</0> from the card" msgstr "unassigned <0>{0}</0> from the card"
@@ -2434,7 +2523,7 @@ msgstr "unassigned <0>{0}</0> from the card"
#~ msgid "unassigned <0>{memberName}</0> from the card" #~ msgid "unassigned <0>{memberName}</0> from the card"
#~ msgstr "unassigned <0>{memberName}</0> from the card" #~ msgstr "unassigned <0>{memberName}</0> from the card"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:153
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "unassigned themselves from the card" msgstr "unassigned themselves from the card"
@@ -2476,6 +2565,11 @@ msgstr "Unlimited members"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "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/board/components/UpdateBoardSlugForm.tsx:175
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80 #: src/views/settings/components/UpdateDisplayNameForm.tsx:80
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
@@ -2488,20 +2582,24 @@ msgstr "Update"
msgid "Update label" msgid "Update label"
msgstr "Update label" msgstr "Update label"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:111
msgid "updated a checklist item" msgid "updated a checklist item"
msgstr "updated a checklist item" msgstr "updated a checklist item"
#: src/views/card/components/ActivityList.tsx:63 #: src/views/card/components/ActivityList.tsx:101
msgid "updated the description" msgid "updated the description"
msgstr "updated the description" msgstr "updated the description"
#: src/views/card/components/ActivityList.tsx:62 #: src/views/card/components/ActivityList.tsx:116
msgid "updated the due date"
msgstr "updated the due date"
#: src/views/card/components/ActivityList.tsx:100
msgid "updated the title" msgid "updated the title"
msgstr "updated the title" msgstr "updated the title"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90 #: src/views/card/components/ActivityList.tsx:125
msgid "updated the title to <0>{0}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "updated the title to <0>{0}</0>" msgstr "updated the title to <0>{0}</0>"
@@ -2527,8 +2625,8 @@ msgstr "Upgrade to Pro ($29/month)"
#~ msgid "Upgrade to Team Plan" #~ msgid "Upgrade to Team Plan"
#~ msgstr "Upgrade to Team Plan" #~ msgstr "Upgrade to Team Plan"
#: src/views/card/components/AttachmentUpload.tsx:32 #: src/views/card/components/AttachmentUpload.tsx:33
#: src/views/card/components/AttachmentUpload.tsx:78 #: src/views/card/components/AttachmentUpload.tsx:79
msgid "Upload failed" msgid "Upload failed"
msgstr "Upload failed" msgstr "Upload failed"
@@ -2581,7 +2679,7 @@ msgstr "View and manage your billing and subscription."
msgid "View docs" msgid "View docs"
msgstr "View docs" msgstr "View docs"
#: src/views/public/board/index.tsx:129 #: src/views/public/board/index.tsx:142
msgid "View only" msgid "View only"
msgstr "View only" msgstr "View only"
@@ -2589,7 +2687,7 @@ msgstr "View only"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "View our roadmap." msgstr "View our roadmap."
#: src/views/public/board/index.tsx:159 #: src/views/public/board/index.tsx:172
msgid "View workspace" msgid "View workspace"
msgstr "View workspace" msgstr "View workspace"
@@ -2601,6 +2699,10 @@ msgstr "Visibility"
msgid "We are using the <0>AGPL-3.0 license</0>." msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "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 #: src/views/home/components/Features.tsx:152
msgid "We're just getting started. " msgid "We're just getting started. "
msgstr "We're just getting started. " msgstr "We're just getting started. "
@@ -2638,10 +2740,10 @@ msgid "Why make an open source Trello?"
msgstr "Why make an open source Trello?" msgstr "Why make an open source Trello?"
#: src/components/SettingsLayout.tsx:39 #: src/components/SettingsLayout.tsx:39
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Workspace" msgstr "Workspace"
@@ -2751,6 +2853,10 @@ msgstr "You have been logged in successfully."
msgid "You have been signed up successfully." msgid "You have been signed up successfully."
msgstr "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 #: src/views/members/components/InviteMemberForm.tsx:326
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!" 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!" msgstr "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
@@ -2775,7 +2881,7 @@ msgstr "Your boards have been imported."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Your display name has been updated." msgstr "Your display name has been updated."
#: src/views/card/components/AttachmentUpload.tsx:26 #: src/views/card/components/AttachmentUpload.tsx:27
msgid "Your file has been uploaded successfully." msgid "Your file has been uploaded successfully."
msgstr "Your file has been uploaded successfully." msgstr "Your file has been uploaded successfully."
@@ -2795,6 +2901,10 @@ msgstr "Your Trello account has been disconnected."
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "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 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
msgid "Your workspace description has been updated." msgid "Your workspace description has been updated."
msgstr "Your workspace description has been updated." msgstr "Your workspace description has been updated."

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:123 #: src/views/card/components/Comment.tsx:124
msgid " (edited)" msgid " (edited)"
msgstr " (editado)" msgstr " (editado)"
@@ -31,17 +31,17 @@ msgstr "{0}"
#. placeholder {1}: board?.name ?? t`Board` #. placeholder {1}: board?.name ?? t`Board`
#. placeholder {1}: workspace.name ?? t`Workspace` #. placeholder {1}: workspace.name ?? t`Workspace`
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:443 #: src/views/board/components/NewCardForm.tsx:452
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} etiquetas" msgstr "{0} etiquetas"
#. placeholder {0}: isTemplate ? "Template" : "Board" #. placeholder {0}: isTemplate ? "Template" : "Board"
#: src/views/board/index.tsx:400 #: src/views/board/index.tsx:408
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} no encontrado" msgstr "{0} no encontrado"
@@ -83,8 +83,8 @@ msgstr "Cuenta eliminada"
msgid "Actions" msgid "Actions"
msgstr "Acciones" msgstr "Acciones"
#: src/views/card/index.tsx:343 #: src/views/card/index.tsx:386
#: src/views/public/board/CardModal.tsx:157 #: src/views/public/board/CardModal.tsx:158
msgid "Activity" msgid "Activity"
msgstr "Actividad" msgstr "Actividad"
@@ -100,12 +100,12 @@ msgstr "Registros de actividad"
msgid "Add a card" msgid "Add a card"
msgstr "Añadir una tarjeta" msgstr "Añadir una tarjeta"
#: src/views/card/components/Comment.tsx:146 #: src/views/card/components/Comment.tsx:147
#: src/views/card/components/NewCommentForm.tsx:57 #: src/views/card/components/NewCommentForm.tsx:55
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Añadir un comentario..." msgstr "Añadir un comentario..."
#: src/views/card/components/NewChecklistItemForm.tsx:140 #: src/views/card/components/NewChecklistItemForm.tsx:141
msgid "Add an item..." msgid "Add an item..."
msgstr "Añadir un elemento..." msgstr "Añadir un elemento..."
@@ -117,48 +117,53 @@ msgstr "Añadir lista de verificación"
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Añadir descripción... (escribe '/' para abrir comandos o '@' para mencionar)" msgstr "Añadir descripción... (escribe '/' para abrir comandos o '@' para mencionar)"
#: src/views/card/components/ChecklistItemRow.tsx:172 #: src/views/card/components/ChecklistItemRow.tsx:195
msgid "Add details..." msgid "Add details..."
msgstr "Añadir detalles..." msgstr "Añadir detalles..."
#: src/views/card/components/LabelSelector.tsx:109 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:114 #: src/views/card/components/LabelSelector.tsx:115
msgid "Add label" msgid "Add label"
msgstr "Añadir etiqueta" msgstr "Añadir etiqueta"
#: src/views/card/components/MemberSelector.tsx:130 #: src/views/card/components/MemberSelector.tsx:131
#: src/views/members/components/InviteMemberForm.tsx:257 #: src/views/members/components/InviteMemberForm.tsx:257
msgid "Add member" msgid "Add member"
msgstr "Añadir miembro" msgstr "Añadir miembro"
#: src/views/card/components/ActivityList.tsx:69 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:77
msgid "added {0} labels: <0>{labelList}</0>"
msgstr "añadió {0} etiquetas: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:107
msgid "added a checklist" msgid "added a checklist"
msgstr "añadió una lista de verificación" msgstr "añadió una lista de verificación"
#: src/views/card/components/ActivityList.tsx:72 #: src/views/card/components/ActivityList.tsx:110
msgid "added a checklist item" msgid "added a checklist item"
msgstr "añadió un elemento a la lista de verificación" msgstr "añadió un elemento a la lista de verificación"
#: src/views/card/components/ActivityList.tsx:65 #: src/views/card/components/ActivityList.tsx:103
msgid "added a label to the card" msgid "added a label to the card"
msgstr "añadió una etiqueta a la tarjeta" msgstr "añadió una etiqueta a la tarjeta"
#: src/views/card/components/ActivityList.tsx:67 #: src/views/card/components/ActivityList.tsx:105
msgid "added a member to the card" msgid "added a member to the card"
msgstr "añadió un miembro a la tarjeta" msgstr "añadió un miembro a la tarjeta"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146 #: src/views/card/components/ActivityList.tsx:181
msgid "added checklist <0>{0}</0>" msgid "added checklist <0>{0}</0>"
msgstr "añadió la lista de verificación <0>{0}</0>" msgstr "añadió la lista de verificación <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170 #: src/views/card/components/ActivityList.tsx:205
msgid "added checklist item <0>{0}</0>" msgid "added checklist item <0>{0}</0>"
msgstr "añadió el elemento <0>{0}</0> a la lista de verificación" msgstr "añadió el elemento <0>{0}</0> a la lista de verificación"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130 #: src/views/card/components/ActivityList.tsx:165
msgid "added label <0>{0}</0>" msgid "added label <0>{0}</0>"
msgstr "añadió la etiqueta <0>{0}</0>" msgstr "añadió la etiqueta <0>{0}</0>"
@@ -249,11 +254,11 @@ msgstr "¿Estás seguro de que quieres eliminar este {0}?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "¿Estás seguro de que quieres eliminar esta tarjeta?" msgstr "¿Estás seguro de que quieres eliminar esta tarjeta?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55 #: src/views/card/components/DeleteChecklistConfirmation.tsx:56
msgid "Are you sure you want to delete this checklist?" msgid "Are you sure you want to delete this checklist?"
msgstr "¿Estás seguro de que quieres eliminar esta lista de verificación?" msgstr "¿Estás seguro de que quieres eliminar esta lista de verificación?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:66
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "¿Estás seguro de que quieres eliminar este comentario?" msgstr "¿Estás seguro de que quieres eliminar este comentario?"
@@ -266,7 +271,7 @@ msgid "Are you sure you want to delete your account?"
msgstr "¿Estás seguro de que quieres eliminar tu cuenta?" msgstr "¿Estás seguro de que quieres eliminar tu cuenta?"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:145
msgid "assigned <0>{0}</0> to the card" msgid "assigned <0>{0}</0> to the card"
msgstr "asignó <0>{0}</0> a la tarjeta" msgstr "asignó <0>{0}</0> a la tarjeta"
@@ -274,7 +279,7 @@ msgstr "asignó <0>{0}</0> a la tarjeta"
msgid "Assignees" msgid "Assignees"
msgstr "Asignados" msgstr "Asignados"
#: src/views/card/components/AttachmentUpload.tsx:25 #: src/views/card/components/AttachmentUpload.tsx:26
msgid "Attachment uploaded" msgid "Attachment uploaded"
msgstr "Archivo adjunto subido" msgstr "Archivo adjunto subido"
@@ -312,9 +317,9 @@ msgstr "Portal de facturación"
msgid "Blog Post" msgid "Blog Post"
msgstr "Entrada de blog" msgstr "Entrada de blog"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
msgid "Board" msgid "Board"
msgstr "Tablero" msgstr "Tablero"
@@ -331,7 +336,7 @@ msgstr "El nombre del tablero no puede exceder los 100 caracteres"
msgid "Board name is required" msgid "Board name is required"
msgstr "El nombre del tablero es obligatorio" msgstr "El nombre del tablero es obligatorio"
#: src/views/public/board/index.tsx:153 #: src/views/public/board/index.tsx:166
msgid "Board not found" msgid "Board not found"
msgstr "Tablero no encontrado" msgstr "Tablero no encontrado"
@@ -347,7 +352,7 @@ msgstr "La URL del tablero solo puede contener letras, números y guiones"
msgid "Board URL cannot exceed 60 characters" msgid "Board URL cannot exceed 60 characters"
msgstr "La URL del tablero no puede exceder los 60 caracteres" msgstr "La URL del tablero no puede exceder los 60 caracteres"
#: src/views/public/board/index.tsx:68 #: src/views/public/board/index.tsx:80
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "URL del tablero copiada al portapapeles" msgstr "URL del tablero copiada al portapapeles"
@@ -382,10 +387,10 @@ msgstr "Informe de error"
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:49
#: src/views/board/components/DeleteBoardConfirmation.tsx:44 #: src/views/board/components/DeleteBoardConfirmation.tsx:44
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:159
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63 #: src/views/card/components/DeleteChecklistConfirmation.tsx:64
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:77
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/settings/components/Avatar.tsx:306 #: src/views/settings/components/Avatar.tsx:306
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168 #: src/views/settings/components/ChangePasswordConfirmation.tsx:168
@@ -395,16 +400,16 @@ msgstr "Informe de error"
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "Card" msgid "Card"
msgstr "Tarjeta" msgstr "Tarjeta"
#: src/views/card/index.tsx:263 #: src/views/card/index.tsx:306
#: src/views/card/index.tsx:299 #: src/views/card/index.tsx:342
msgid "Card not found" msgid "Card not found"
msgstr "Tarjeta no encontrada" msgstr "Tarjeta no encontrada"
#: src/views/board/components/NewCardForm.tsx:310 #: src/views/board/components/NewCardForm.tsx:319
msgid "Card title" msgid "Card title"
msgstr "Título de la tarjeta" msgstr "Título de la tarjeta"
@@ -419,6 +424,11 @@ msgstr "Cambiar contraseña"
msgid "Change your language preferences." msgid "Change your language preferences."
msgstr "Cambia tus preferencias de idioma." msgstr "Cambia tus preferencias de idioma."
#: src/views/card/components/ActivityList.tsx:255
#: src/views/card/components/ActivityList.tsx:269
msgid "changed the due date to <0>{formattedDate}</0>"
msgstr "cambió la fecha de vencimiento a <0>{formattedDate}</0>"
#: src/views/oss-friends/index.tsx:61 #: src/views/oss-friends/index.tsx:61
msgid "Check out some of our favorite open source projects." msgid "Check out some of our favorite open source projects."
msgstr "Descubre algunos de nuestros proyectos de código abierto favoritos." msgstr "Descubre algunos de nuestros proyectos de código abierto favoritos."
@@ -428,7 +438,7 @@ msgstr "Descubre algunos de nuestros proyectos de código abierto favoritos."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Revisa tu bandeja de entrada" msgstr "Revisa tu bandeja de entrada"
#: src/views/card/components/NewChecklistForm.tsx:118 #: src/views/card/components/NewChecklistForm.tsx:119
msgid "Checklist name" msgid "Checklist name"
msgstr "Nombre de la lista de verificación" msgstr "Nombre de la lista de verificación"
@@ -437,7 +447,7 @@ msgstr "Nombre de la lista de verificación"
msgid "Checklists" msgid "Checklists"
msgstr "Listas de verificación" msgstr "Listas de verificación"
#: src/views/board/components/Filters.tsx:180 #: src/views/board/components/Filters.tsx:227
msgid "Clear filters" msgid "Clear filters"
msgstr "Borrar filtros" msgstr "Borrar filtros"
@@ -489,15 +499,19 @@ msgstr "Completado"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Control y propiedad completos:" msgstr "Control y propiedad completos:"
#: src/views/card/components/ActivityList.tsx:74 #: src/views/card/components/ActivityList.tsx:112
msgid "completed a checklist item" msgid "completed a checklist item"
msgstr "completó un elemento de la lista de verificación" msgstr "completó un elemento de la lista de verificación"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187 #: src/views/card/components/ActivityList.tsx:222
msgid "completed checklist item <0>{0}</0>" msgid "completed checklist item <0>{0}</0>"
msgstr "completó el elemento <0>{0}</0> de la lista de verificación" 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 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password" msgid "Confirm your new password"
msgstr "Confirma tu nueva contraseña" msgstr "Confirma tu nueva contraseña"
@@ -551,7 +565,7 @@ msgid "Create {0}"
msgstr "Crear {0}" msgstr "Crear {0}"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:469 #: src/views/board/components/NewCardForm.tsx:516
#: src/views/board/components/NewListForm.tsx:141 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Crear otro" msgstr "Crear otro"
@@ -560,11 +574,11 @@ msgstr "Crear otro"
msgid "Create API key" msgid "Create API key"
msgstr "Crear clave API" msgstr "Crear clave API"
#: src/views/board/components/NewCardForm.tsx:479 #: src/views/board/components/NewCardForm.tsx:526
msgid "Create card" msgid "Create card"
msgstr "Crear tarjeta" msgstr "Crear tarjeta"
#: src/views/card/components/NewChecklistForm.tsx:134 #: src/views/card/components/NewChecklistForm.tsx:135
msgid "Create checklist" msgid "Create checklist"
msgstr "Crear lista de verificación" msgstr "Crear lista de verificación"
@@ -590,13 +604,13 @@ msgstr "Crear nuevo {0}"
msgid "Create new key" msgid "Create new key"
msgstr "Crear nueva clave" msgstr "Crear nueva clave"
#: src/views/board/components/NewCardForm.tsx:405 #: src/views/board/components/NewCardForm.tsx:414
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:98
msgid "Create new label" msgid "Create new label"
msgstr "Crear nueva etiqueta" msgstr "Crear nueva etiqueta"
#: src/views/board/index.tsx:64 #: src/views/board/index.tsx:64
#: src/views/board/index.tsx:491 #: src/views/board/index.tsx:499
msgid "Create new list" msgid "Create new list"
msgstr "Crear nueva lista" msgstr "Crear nueva lista"
@@ -609,7 +623,7 @@ msgstr "Crear plantilla"
msgid "Create workspace" msgid "Create workspace"
msgstr "Crear espacio de trabajo" msgstr "Crear espacio de trabajo"
#: src/views/card/components/ActivityList.tsx:61 #: src/views/card/components/ActivityList.tsx:99
msgid "created the card" msgid "created the card"
msgstr "creó la tarjeta" msgstr "creó la tarjeta"
@@ -667,8 +681,8 @@ msgstr "Desactivar enlace de invitación"
#: src/components/LabelForm.tsx:228 #: src/components/LabelForm.tsx:228
#: src/views/board/components/DeleteBoardConfirmation.tsx:47 #: src/views/board/components/DeleteBoardConfirmation.tsx:47
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66 #: src/views/card/components/DeleteChecklistConfirmation.tsx:67
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:83
msgid "Delete" msgid "Delete"
msgstr "Eliminar" msgstr "Eliminar"
@@ -686,7 +700,7 @@ msgstr "Eliminar tablero"
msgid "Delete card" msgid "Delete card"
msgstr "Eliminar tarjeta" msgstr "Eliminar tarjeta"
#: src/views/card/components/Comment.tsx:91 #: src/views/card/components/Comment.tsx:92
msgid "Delete comment" msgid "Delete comment"
msgstr "Eliminar comentario" msgstr "Eliminar comentario"
@@ -704,21 +718,21 @@ msgstr "Eliminar plantilla"
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Eliminar espacio de trabajo" msgstr "Eliminar espacio de trabajo"
#: src/views/card/components/ActivityList.tsx:71 #: src/views/card/components/ActivityList.tsx:109
msgid "deleted a checklist" msgid "deleted a checklist"
msgstr "eliminó una lista de verificación" msgstr "eliminó una lista de verificación"
#: src/views/card/components/ActivityList.tsx:76 #: src/views/card/components/ActivityList.tsx:114
msgid "deleted a checklist item" msgid "deleted a checklist item"
msgstr "eliminó un elemento de la lista de verificación" msgstr "eliminó un elemento de la lista de verificación"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162 #: src/views/card/components/ActivityList.tsx:197
msgid "deleted checklist <0>{0}</0>" msgid "deleted checklist <0>{0}</0>"
msgstr "eliminó la lista de verificación <0>{0}</0>" msgstr "eliminó la lista de verificación <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205 #: src/views/card/components/ActivityList.tsx:240
msgid "deleted checklist item <0>{0}</0>" msgid "deleted checklist item <0>{0}</0>"
msgstr "eliminó el elemento <0>{0}</0> de la lista de verificación" msgstr "eliminó el elemento <0>{0}</0> de la lista de verificación"
@@ -754,6 +768,10 @@ msgstr "Nombre visible actualizado"
msgid "Do you offer a free plan?" msgid "Do you offer a free plan?"
msgstr "¿Ofrecen un plan gratuito?" 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 #: src/components/FeedbackModal.tsx:109
msgid "docs" msgid "docs"
msgstr "documentos" msgstr "documentos"
@@ -780,16 +798,38 @@ msgstr "¿No tienes una cuenta? <0><1>Regístrate</1></0>"
msgid "Done" msgid "Done"
msgstr "Terminado" msgstr "Terminado"
#: src/views/card/components/AttachmentThumbnails.tsx:141 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "Download failed" msgid "Download failed"
msgstr "Error en la descarga" msgstr "Error en la descarga"
#: src/views/board/components/Filters.tsx:171
#: src/views/board/components/NewCardForm.tsx:469
#: src/views/card/index.tsx:139
msgid "Due date"
msgstr "Fecha de vencimiento"
#: src/views/board/components/Filters.tsx:132
msgid "Due next month"
msgstr "Vence el próximo mes"
#: src/views/board/components/Filters.tsx:127
msgid "Due next week"
msgstr "Vence la próxima semana"
#: src/views/board/components/Filters.tsx:117
msgid "Due today"
msgstr "Vence hoy"
#: src/views/board/components/Filters.tsx:122
msgid "Due tomorrow"
msgstr "Vence mañana"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:116 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Editar URL del tablero" msgstr "Editar URL del tablero"
#: src/views/card/components/Comment.tsx:82 #: src/views/card/components/Comment.tsx:83
msgid "Edit comment" msgid "Edit comment"
msgstr "Editar comentario" msgstr "Editar comentario"
@@ -946,8 +986,8 @@ msgstr "Error al crear el tablero"
msgid "Failed to login with {0}. Please try again." msgid "Failed to login with {0}. Please try again."
msgstr "Error al iniciar sesión con {0}. Por favor, inténtalo de nuevo." msgstr "Error al iniciar sesión con {0}. Por favor, inténtalo de nuevo."
#: src/views/card/components/AttachmentUpload.tsx:33 #: src/views/card/components/AttachmentUpload.tsx:34
#: src/views/card/components/AttachmentUpload.tsx:79 #: src/views/card/components/AttachmentUpload.tsx:80
msgid "Failed to upload attachment. Please try again." msgid "Failed to upload attachment. Please try again."
msgstr "Error al subir el archivo adjunto. Por favor, inténtalo de nuevo." msgstr "Error al subir el archivo adjunto. Por favor, inténtalo de nuevo."
@@ -994,7 +1034,7 @@ msgstr "Comentarios"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Comentarios enviados" msgstr "Comentarios enviados"
#: src/views/board/components/Filters.tsx:174 #: src/views/board/components/Filters.tsx:221
msgid "Filter" msgid "Filter"
msgstr "Filtrar" msgstr "Filtrar"
@@ -1052,7 +1092,7 @@ msgstr "Comenzar"
msgid "Get started by creating a new {0}" msgid "Get started by creating a new {0}"
msgstr "Comienza creando un nuevo {0}" msgstr "Comienza creando un nuevo {0}"
#: src/views/board/index.tsx:483 #: src/views/board/index.tsx:491
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Comienza creando una nueva lista" msgstr "Comienza creando una nueva lista"
@@ -1239,7 +1279,7 @@ msgstr "Enlaces de invitación"
msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace."
msgstr "Los enlaces de invitación requieren una suscripción de Equipo o Pro. Por favor, actualiza tu espacio de trabajo." msgstr "Los enlaces de invitación requieren una suscripción de Equipo o Pro. Por favor, actualiza tu espacio de trabajo."
#: src/views/card/components/MemberSelector.tsx:111 #: src/views/card/components/MemberSelector.tsx:112
#: src/views/members/components/InviteMemberForm.tsx:367 #: src/views/members/components/InviteMemberForm.tsx:367
msgid "Invite member" msgid "Invite member"
msgstr "Invitar miembro" msgstr "Invitar miembro"
@@ -1286,9 +1326,9 @@ msgstr "Ten en cuenta que esta acción es irreversible."
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "Atajos de teclado" msgstr "Atajos de teclado"
#: src/views/board/components/Filters.tsx:115 #: src/views/board/components/Filters.tsx:155
#: src/views/board/components/NewCardForm.tsx:409 #: src/views/board/components/NewCardForm.tsx:418
#: src/views/card/index.tsx:119 #: src/views/card/index.tsx:121
msgid "Labels" msgid "Labels"
msgstr "Etiquetas" msgstr "Etiquetas"
@@ -1338,11 +1378,11 @@ msgstr "Licencia"
msgid "Light" msgid "Light"
msgstr "Claro" msgstr "Claro"
#: src/views/public/board/index.tsx:66 #: src/views/public/board/index.tsx:78
msgid "Link copied" msgid "Link copied"
msgstr "Enlace copiado" msgstr "Enlace copiado"
#: src/views/card/index.tsx:111 #: src/views/card/index.tsx:113
msgid "List" msgid "List"
msgstr "Lista" msgstr "Lista"
@@ -1350,10 +1390,18 @@ msgstr "Lista"
msgid "List name" msgid "List name"
msgstr "Nombre de la lista" msgstr "Nombre de la lista"
#: src/views/board/components/Filters.tsx:123 #: src/views/board/components/Filters.tsx:163
msgid "Lists" msgid "Lists"
msgstr "Listas" msgstr "Listas"
#: src/views/card/components/ActivityList.tsx:530
msgid "Load more activities"
msgstr "Cargar más actividades"
#: src/views/card/components/ActivityList.tsx:530
msgid "Loading..."
msgstr "Cargando..."
#: src/views/auth/login/index.tsx:33 #: src/views/auth/login/index.tsx:33
msgid "Login | kan.bn" msgid "Login | kan.bn"
msgstr "Iniciar sesión | kan.bn" msgstr "Iniciar sesión | kan.bn"
@@ -1382,12 +1430,12 @@ msgstr "enlace mágico"
msgid "Make template" msgid "Make template"
msgstr "Crear plantilla" msgstr "Crear plantilla"
#: src/views/card/components/ActivityList.tsx:75 #: src/views/card/components/ActivityList.tsx:113
msgid "marked a checklist item as incomplete" msgid "marked a checklist item as incomplete"
msgstr "marcó un elemento de la lista de verificación como incompleto" msgstr "marcó un elemento de la lista de verificación como incompleto"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196 #: src/views/card/components/ActivityList.tsx:231
msgid "marked checklist item <0>{0}</0> as incomplete" msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "marcó el elemento <0>{0}</0> de la lista de verificación como incompleto" msgstr "marcó el elemento <0>{0}</0> de la lista de verificación como incompleto"
@@ -1396,9 +1444,9 @@ msgid "Medium Priority"
msgstr "Prioridad media" msgstr "Prioridad media"
#: src/components/SideNavigation.tsx:121 #: src/components/SideNavigation.tsx:121
#: src/views/board/components/Filters.tsx:107 #: src/views/board/components/Filters.tsx:147
#: src/views/board/components/NewCardForm.tsx:367 #: src/views/board/components/NewCardForm.tsx:376
#: src/views/card/index.tsx:128 #: src/views/card/index.tsx:130
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Miembros" msgstr "Miembros"
@@ -1419,11 +1467,11 @@ msgstr "facturación mensual"
#. placeholder {0}: truncate(fromList) #. placeholder {0}: truncate(fromList)
#. placeholder {1}: truncate(toList) #. placeholder {1}: truncate(toList)
#: src/views/card/components/ActivityList.tsx:98 #: src/views/card/components/ActivityList.tsx:133
msgid "moved the card from <0>{0}</0> to<1>{1}</1>" msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "movió la tarjeta de <0>{0}</0> a<1>{1}</1>" msgstr "movió la tarjeta de <0>{0}</0> a<1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:64 #: src/views/card/components/ActivityList.tsx:102
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "movió la tarjeta a otra lista" msgstr "movió la tarjeta a otra lista"
@@ -1455,11 +1503,11 @@ msgstr "Nuevo {0}"
msgid "New API key" msgid "New API key"
msgstr "Nueva clave API" msgstr "Nueva clave API"
#: src/views/board/components/NewCardForm.tsx:293 #: src/views/board/components/NewCardForm.tsx:302
msgid "New card" msgid "New card"
msgstr "Nueva tarjeta" msgstr "Nueva tarjeta"
#: src/views/card/components/NewChecklistForm.tsx:102 #: src/views/card/components/NewChecklistForm.tsx:103
msgid "New checklist" msgid "New checklist"
msgstr "Nueva lista de verificación" msgstr "Nueva lista de verificación"
@@ -1472,7 +1520,7 @@ msgid "New label"
msgstr "Nueva etiqueta" msgstr "Nueva etiqueta"
#: src/views/board/components/NewListForm.tsx:113 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:454 #: src/views/board/index.tsx:462
msgid "New list" msgid "New list"
msgstr "Nueva lista" msgstr "Nueva lista"
@@ -1521,7 +1569,11 @@ msgstr "No se encontraron tableros"
msgid "No credit card required" msgid "No credit card required"
msgstr "No se requiere tarjeta de crédito" msgstr "No se requiere tarjeta de crédito"
#: src/views/card/components/AttachmentThumbnails.tsx:142 #: src/views/board/components/Filters.tsx:137
msgid "No dates"
msgstr "Sin fechas"
#: src/views/card/components/AttachmentThumbnails.tsx:143
msgid "No download URL available for this attachment." msgid "No download URL available for this attachment."
msgstr "No hay URL de descarga disponible para este archivo adjunto." msgstr "No hay URL de descarga disponible para este archivo adjunto."
@@ -1529,7 +1581,7 @@ msgstr "No hay URL de descarga disponible para este archivo adjunto."
msgid "No keyboard shortcuts registered." msgid "No keyboard shortcuts registered."
msgstr "No hay atajos de teclado registrados." msgstr "No hay atajos de teclado registrados."
#: src/views/board/index.tsx:480 #: src/views/board/index.tsx:488
msgid "No lists" msgid "No lists"
msgstr "Sin listas" msgstr "Sin listas"
@@ -1582,6 +1634,10 @@ msgstr "Organiza y encuentra tarjetas rápidamente con potentes herramientas de
msgid "OSS Friends" msgid "OSS Friends"
msgstr "Amigos OSS" msgstr "Amigos OSS"
#: src/views/board/components/Filters.tsx:112
msgid "Overdue"
msgstr "Vencido"
#: src/views/pricing/components/Pricing.tsx:73 #: src/views/pricing/components/Pricing.tsx:73
#: src/views/pricing/components/PricingTiers.tsx:70 #: src/views/pricing/components/PricingTiers.tsx:70
msgid "Own your data" msgid "Own your data"
@@ -1670,30 +1726,33 @@ msgstr "Por favor selecciona un archivo para subir."
#: src/components/DeleteLabelConfirmation.tsx:26 #: src/components/DeleteLabelConfirmation.tsx:26
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/NewWorkspaceForm.tsx:158 #: src/components/NewWorkspaceForm.tsx:158
#: src/views/board/components/NewCardForm.tsx:177 #: src/views/board/components/NewCardForm.tsx:184
#: src/views/board/components/NewListForm.tsx:79 #: src/views/board/components/NewListForm.tsx:79
#: src/views/board/components/NewTemplateForm.tsx:61 #: src/views/board/components/NewTemplateForm.tsx:61
#: src/views/board/components/NewTemplateForm.tsx:77 #: src/views/board/components/NewTemplateForm.tsx:77
#: src/views/board/components/UpdateBoardSlugForm.tsx:73 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:54 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:162 #: src/views/board/index.tsx:170
#: src/views/board/index.tsx:218 #: src/views/board/index.tsx:226
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/card/components/AttachmentThumbnails.tsx:73 #: src/views/card/components/AttachmentThumbnails.tsx:74
#: src/views/card/components/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:67
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:95
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:47
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Checklists.tsx:81
#: src/views/card/components/Comment.tsx:65
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37 #: src/views/card/components/DeleteChecklistConfirmation.tsx:38
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:46
#: src/views/card/components/LabelSelector.tsx:72 #: src/views/card/components/DueDateSelector.tsx:60
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/MemberSelector.tsx:79 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistForm.tsx:71
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewChecklistItemForm.tsx:90
#: src/views/card/index.tsx:177 #: src/views/card/components/NewCommentForm.tsx:32
#: src/views/card/index.tsx:187
#: src/views/card/index.tsx:200
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/members/components/InviteMemberForm.tsx:104 #: src/views/members/components/InviteMemberForm.tsx:104
#: src/views/members/components/InviteMemberForm.tsx:241 #: src/views/members/components/InviteMemberForm.tsx:241
@@ -1793,30 +1852,40 @@ msgstr "Eliminar"
msgid "Remove member" msgid "Remove member"
msgstr "Eliminar miembro" msgstr "Eliminar miembro"
#: src/views/card/components/ActivityList.tsx:66 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:91
msgid "removed {0} labels: <0>{labelList}</0>"
msgstr "eliminó {0} etiquetas: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:104
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "eliminó una etiqueta de la tarjeta" msgstr "eliminó una etiqueta de la tarjeta"
#: src/views/card/components/ActivityList.tsx:68 #: src/views/card/components/ActivityList.tsx:106
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "eliminó un miembro de la tarjeta" msgstr "eliminó un miembro de la tarjeta"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138 #: src/views/card/components/ActivityList.tsx:173
msgid "removed label <0>{0}</0>" msgid "removed label <0>{0}</0>"
msgstr "eliminó la etiqueta <0>{0}</0>" msgstr "eliminó la etiqueta <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:70 #: src/views/card/components/ActivityList.tsx:117
#: src/views/card/components/ActivityList.tsx:276
msgid "removed the due date"
msgstr "eliminó la fecha de vencimiento"
#: src/views/card/components/ActivityList.tsx:108
msgid "renamed a checklist" msgid "renamed a checklist"
msgstr "renombró una lista de verificación" msgstr "renombró una lista de verificación"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154 #: src/views/card/components/ActivityList.tsx:189
msgid "renamed checklist <0>{0}</0>" msgid "renamed checklist <0>{0}</0>"
msgstr "renombró la lista de verificación <0>{0}</0>" msgstr "renombró la lista de verificación <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178 #: src/views/card/components/ActivityList.tsx:213
msgid "renamed checklist item to <0>{0}</0>" msgid "renamed checklist item to <0>{0}</0>"
msgstr "renombró el elemento de la lista de verificación a <0>{0}</0>" msgstr "renombró el elemento de la lista de verificación a <0>{0}</0>"
@@ -1855,7 +1924,7 @@ msgstr "Rol"
msgid "Run on your own infrastructure" msgid "Run on your own infrastructure"
msgstr "Ejecuta en tu propia infraestructura" msgstr "Ejecuta en tu propia infraestructura"
#: src/views/card/components/Comment.tsx:165 #: src/views/card/components/Comment.tsx:166
#: src/views/settings/components/Avatar.tsx:309 #: src/views/settings/components/Avatar.tsx:309
msgid "Save" msgid "Save"
msgstr "Guardar" msgstr "Guardar"
@@ -1893,7 +1962,7 @@ msgstr "Autoalojamiento"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Autoalojamiento con Github" msgstr "Autoalojamiento con Github"
#: src/views/card/components/ActivityList.tsx:107 #: src/views/card/components/ActivityList.tsx:142
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "se autoasignó la tarjeta" msgstr "se autoasignó la tarjeta"
@@ -1909,6 +1978,14 @@ msgstr "Enviar comentarios"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/card/components/DueDateSelector.tsx:117
msgid "Set due date"
msgstr "Establecer fecha de vencimiento"
#: src/views/card/components/ActivityList.tsx:115
msgid "set the due date"
msgstr "estableció la fecha de vencimiento"
#: src/components/SettingsLayout.tsx:82 #: src/components/SettingsLayout.tsx:82
#: src/components/SideNavigation.tsx:133 #: src/components/SideNavigation.tsx:133
msgid "Settings" msgid "Settings"
@@ -2030,8 +2107,8 @@ msgstr "Plan de Equipo"
msgid "Teams" msgid "Teams"
msgstr "Equipos" msgstr "Equipos"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/board/index.tsx:409 #: src/views/board/index.tsx:417
msgid "Template" msgid "Template"
msgstr "Plantilla" msgstr "Plantilla"
@@ -2096,8 +2173,8 @@ msgstr "No podrán acceder a este espacio de trabajo."
#: src/components/DeleteLabelConfirmation.tsx:44 #: src/components/DeleteLabelConfirmation.tsx:44
#: src/views/board/components/DeleteBoardConfirmation.tsx:39 #: src/views/board/components/DeleteBoardConfirmation.tsx:39
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58 #: src/views/card/components/DeleteChecklistConfirmation.tsx:59
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:69
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Esta acción no se puede deshacer." msgstr "Esta acción no se puede deshacer."
@@ -2105,7 +2182,7 @@ msgstr "Esta acción no se puede deshacer."
msgid "This API key will only be shown once. Please save it in a secure location." msgid "This API key will only be shown once. Please save it in a secure location."
msgstr "Esta clave API solo se mostrará una vez. Por favor, guárdala en un lugar seguro." msgstr "Esta clave API solo se mostrará una vez. Por favor, guárdala en un lugar seguro."
#: src/views/public/board/index.tsx:156 #: src/views/public/board/index.tsx:169
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "Este tablero es privado o no existe" msgstr "Este tablero es privado o no existe"
@@ -2167,23 +2244,27 @@ msgstr "Importaciones de Trello"
msgid "Triaging" msgid "Triaging"
msgstr "Clasificación" msgstr "Clasificación"
#: src/views/home/components/Logos.tsx:73 #: src/views/home/components/Logos.tsx:67
msgid "Trusted by fast-moving teams<0/>around the world" msgid "Trusted by fast-moving teams<0/>around the world"
msgstr "Equipos ágiles de todo el mundo<0/>confían en nosotros" msgstr "Equipos ágiles de todo el mundo<0/>confían en nosotros"
#: src/views/card/components/NewChecklistItemForm.tsx:88 #: src/views/card/components/NewChecklistItemForm.tsx:89
msgid "Unable to add checklist item" msgid "Unable to add checklist item"
msgstr "No se puede añadir el elemento a la lista de verificación" msgstr "No se puede añadir el elemento a la lista de verificación"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:31
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "No se puede añadir el comentario" msgstr "No se puede añadir el comentario"
#: src/views/board/components/NewCardForm.tsx:174 #: src/views/card/index.tsx:199
msgid "Unable to add label"
msgstr "No se puede añadir etiqueta"
#: src/views/board/components/NewCardForm.tsx:181
msgid "Unable to create card" msgid "Unable to create card"
msgstr "No se puede crear la tarjeta" msgstr "No se puede crear la tarjeta"
#: src/views/card/components/NewChecklistForm.tsx:69 #: src/views/card/components/NewChecklistForm.tsx:70
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "No se puede crear la lista de verificación" msgstr "No se puede crear la lista de verificación"
@@ -2200,7 +2281,7 @@ msgstr "No se puede crear la plantilla"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "No se puede crear el espacio de trabajo" msgstr "No se puede crear el espacio de trabajo"
#: src/views/card/components/AttachmentThumbnails.tsx:72 #: src/views/card/components/AttachmentThumbnails.tsx:73
msgid "Unable to delete attachment" msgid "Unable to delete attachment"
msgstr "No se puede eliminar el archivo adjunto" msgstr "No se puede eliminar el archivo adjunto"
@@ -2208,15 +2289,15 @@ msgstr "No se puede eliminar el archivo adjunto"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "No se puede eliminar la tarjeta" msgstr "No se puede eliminar la tarjeta"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36 #: src/views/card/components/DeleteChecklistConfirmation.tsx:37
msgid "Unable to delete checklist" msgid "Unable to delete checklist"
msgstr "No se puede eliminar la lista de verificación" msgstr "No se puede eliminar la lista de verificación"
#: src/views/card/components/ChecklistItemRow.tsx:87 #: src/views/card/components/ChecklistItemRow.tsx:94
msgid "Unable to delete checklist item" msgid "Unable to delete checklist item"
msgstr "No se puede eliminar el elemento de la lista de verificación" msgstr "No se puede eliminar el elemento de la lista de verificación"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "No se puede eliminar el comentario" msgstr "No se puede eliminar el comentario"
@@ -2224,6 +2305,10 @@ msgstr "No se puede eliminar el comentario"
msgid "Unable to remove member" msgid "Unable to remove member"
msgstr "No se puede eliminar al miembro" msgstr "No se puede eliminar al miembro"
#: src/views/card/components/Checklists.tsx:80
msgid "Unable to reorder checklist item"
msgstr "No se puede reordenar el elemento de la lista de verificación"
#: src/components/FeedbackModal.tsx:40 #: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "No se pudieron enviar los comentarios" msgstr "No se pudieron enviar los comentarios"
@@ -2236,42 +2321,46 @@ msgstr "No se puede actualizar la URL del tablero"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "No se puede actualizar la visibilidad del tablero" msgstr "No se puede actualizar la visibilidad del tablero"
#: src/views/board/index.tsx:217 #: src/views/board/index.tsx:225
#: src/views/card/index.tsx:176 #: src/views/card/index.tsx:186
msgid "Unable to update card" msgid "Unable to update card"
msgstr "No se puede actualizar la tarjeta" msgstr "No se puede actualizar la tarjeta"
#: src/views/card/components/ChecklistNameInput.tsx:45 #: src/views/card/components/ChecklistNameInput.tsx:46
msgid "Unable to update checklist" msgid "Unable to update checklist"
msgstr "No se puede actualizar la lista de verificación" msgstr "No se puede actualizar la lista de verificación"
#: src/views/card/components/ChecklistItemRow.tsx:59 #: src/views/card/components/ChecklistItemRow.tsx:66
msgid "Unable to update checklist item" msgid "Unable to update checklist item"
msgstr "No se puede actualizar el elemento de la lista de verificación" msgstr "No se puede actualizar el elemento de la lista de verificación"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:64
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "No se puede actualizar el comentario" msgstr "No se puede actualizar el comentario"
#: src/views/card/components/LabelSelector.tsx:71 #: src/views/card/components/DueDateSelector.tsx:59
msgid "Unable to update due date"
msgstr "No se puede actualizar la fecha de vencimiento"
#: src/views/card/components/LabelSelector.tsx:72
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "No se pueden actualizar las etiquetas" msgstr "No se pueden actualizar las etiquetas"
#: src/views/board/index.tsx:161 #: src/views/board/index.tsx:169
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:52
msgid "Unable to update list" msgid "Unable to update list"
msgstr "No se puede actualizar la lista" msgstr "No se puede actualizar la lista"
#: src/views/card/components/MemberSelector.tsx:78 #: src/views/card/components/MemberSelector.tsx:79
msgid "Unable to update members" msgid "Unable to update members"
msgstr "No se pueden actualizar los miembros" msgstr "No se pueden actualizar los miembros"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:121 #: src/views/card/components/ActivityList.tsx:156
msgid "unassigned <0>{0}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "desasignó <0>{0}</0> de la tarjeta" msgstr "desasignó <0>{0}</0> de la tarjeta"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:153
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "se desasignó de la tarjeta" msgstr "se desasignó de la tarjeta"
@@ -2313,6 +2402,11 @@ msgstr "Miembros ilimitados"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Espacios de trabajo ilimitados" 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/board/components/UpdateBoardSlugForm.tsx:175
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80 #: src/views/settings/components/UpdateDisplayNameForm.tsx:80
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
@@ -2325,20 +2419,24 @@ msgstr "Actualizar"
msgid "Update label" msgid "Update label"
msgstr "Actualizar etiqueta" msgstr "Actualizar etiqueta"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:111
msgid "updated a checklist item" msgid "updated a checklist item"
msgstr "actualizó un elemento de la lista de verificación" msgstr "actualizó un elemento de la lista de verificación"
#: src/views/card/components/ActivityList.tsx:63 #: src/views/card/components/ActivityList.tsx:101
msgid "updated the description" msgid "updated the description"
msgstr "actualizó la descripción" msgstr "actualizó la descripción"
#: src/views/card/components/ActivityList.tsx:62 #: src/views/card/components/ActivityList.tsx:116
msgid "updated the due date"
msgstr "actualizó la fecha de vencimiento"
#: src/views/card/components/ActivityList.tsx:100
msgid "updated the title" msgid "updated the title"
msgstr "actualizó el título" msgstr "actualizó el título"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90 #: src/views/card/components/ActivityList.tsx:125
msgid "updated the title to <0>{0}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "actualizó el título a <0>{0}</0>" msgstr "actualizó el título a <0>{0}</0>"
@@ -2352,8 +2450,8 @@ msgstr "Actualizar a Pro"
msgid "Upgrade to Pro ($29/month)" msgid "Upgrade to Pro ($29/month)"
msgstr "Actualizar a Pro ($29/mes)" msgstr "Actualizar a Pro ($29/mes)"
#: src/views/card/components/AttachmentUpload.tsx:32 #: src/views/card/components/AttachmentUpload.tsx:33
#: src/views/card/components/AttachmentUpload.tsx:78 #: src/views/card/components/AttachmentUpload.tsx:79
msgid "Upload failed" msgid "Upload failed"
msgstr "Error al subir" msgstr "Error al subir"
@@ -2406,7 +2504,7 @@ msgstr "Ver y gestionar tu facturación y suscripción."
msgid "View docs" msgid "View docs"
msgstr "Ver documentación" msgstr "Ver documentación"
#: src/views/public/board/index.tsx:129 #: src/views/public/board/index.tsx:142
msgid "View only" msgid "View only"
msgstr "Solo visualización" msgstr "Solo visualización"
@@ -2414,7 +2512,7 @@ msgstr "Solo visualización"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "Ver nuestra hoja de ruta." msgstr "Ver nuestra hoja de ruta."
#: src/views/public/board/index.tsx:159 #: src/views/public/board/index.tsx:172
msgid "View workspace" msgid "View workspace"
msgstr "Ver espacio de trabajo" msgstr "Ver espacio de trabajo"
@@ -2426,6 +2524,10 @@ msgstr "Visibilidad"
msgid "We are using the <0>AGPL-3.0 license</0>." msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "Estamos usando la <0>licencia AGPL-3.0</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 #: src/views/home/components/Features.tsx:152
msgid "We're just getting started. " msgid "We're just getting started. "
msgstr "Apenas estamos comenzando. " msgstr "Apenas estamos comenzando. "
@@ -2455,10 +2557,10 @@ msgid "Why make an open source Trello?"
msgstr "¿Por qué crear un Trello de código abierto?" msgstr "¿Por qué crear un Trello de código abierto?"
#: src/components/SettingsLayout.tsx:39 #: src/components/SettingsLayout.tsx:39
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Espacio de trabajo" msgstr "Espacio de trabajo"
@@ -2564,6 +2666,10 @@ msgstr "Has iniciado sesión correctamente."
msgid "You have been signed up successfully." msgid "You have been signed up successfully."
msgstr "Te has registrado correctamente." 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 #: src/views/members/components/InviteMemberForm.tsx:326
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!" 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!" msgstr "Tienes plazas ilimitadas con tu Plan Pro. ¡No hay cargos adicionales por nuevos miembros!"
@@ -2588,7 +2694,7 @@ msgstr "Tus tableros han sido importados."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Tu nombre de visualización ha sido actualizado." msgstr "Tu nombre de visualización ha sido actualizado."
#: src/views/card/components/AttachmentUpload.tsx:26 #: src/views/card/components/AttachmentUpload.tsx:27
msgid "Your file has been uploaded successfully." msgid "Your file has been uploaded successfully."
msgstr "Tu archivo se ha subido correctamente." msgstr "Tu archivo se ha subido correctamente."
@@ -2608,6 +2714,10 @@ msgstr "Tu cuenta de Trello ha sido desconectada."
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Tu cuenta de Trello está conectada." 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 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
msgid "Your workspace description has been updated." msgid "Your workspace description has been updated."
msgstr "La descripción de tu espacio de trabajo ha sido actualizada." msgstr "La descripción de tu espacio de trabajo ha sido actualizada."

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:123 #: src/views/card/components/Comment.tsx:124
msgid " (edited)" msgid " (edited)"
msgstr " (modifié)" msgstr " (modifié)"
@@ -31,17 +31,17 @@ msgstr "{0}"
#. placeholder {1}: board?.name ?? t`Board` #. placeholder {1}: board?.name ?? t`Board`
#. placeholder {1}: workspace.name ?? t`Workspace` #. placeholder {1}: workspace.name ?? t`Workspace`
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:443 #: src/views/board/components/NewCardForm.tsx:452
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} étiquettes" msgstr "{0} étiquettes"
#. placeholder {0}: isTemplate ? "Template" : "Board" #. placeholder {0}: isTemplate ? "Template" : "Board"
#: src/views/board/index.tsx:400 #: src/views/board/index.tsx:408
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} introuvable" msgstr "{0} introuvable"
@@ -83,8 +83,8 @@ msgstr "Compte supprimé"
msgid "Actions" msgid "Actions"
msgstr "Actions" msgstr "Actions"
#: src/views/card/index.tsx:343 #: src/views/card/index.tsx:386
#: src/views/public/board/CardModal.tsx:157 #: src/views/public/board/CardModal.tsx:158
msgid "Activity" msgid "Activity"
msgstr "Activité" msgstr "Activité"
@@ -100,12 +100,12 @@ msgstr "Journaux d'activité"
msgid "Add a card" msgid "Add a card"
msgstr "Ajouter une carte" msgstr "Ajouter une carte"
#: src/views/card/components/Comment.tsx:146 #: src/views/card/components/Comment.tsx:147
#: src/views/card/components/NewCommentForm.tsx:57 #: src/views/card/components/NewCommentForm.tsx:55
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Ajouter un commentaire..." msgstr "Ajouter un commentaire..."
#: src/views/card/components/NewChecklistItemForm.tsx:140 #: src/views/card/components/NewChecklistItemForm.tsx:141
msgid "Add an item..." msgid "Add an item..."
msgstr "Ajouter un élément..." msgstr "Ajouter un élément..."
@@ -117,48 +117,53 @@ msgstr "Ajouter une checklist"
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Ajouter une description... (tapez '/' pour ouvrir les commandes ou '@' pour mentionner)" msgstr "Ajouter une description... (tapez '/' pour ouvrir les commandes ou '@' pour mentionner)"
#: src/views/card/components/ChecklistItemRow.tsx:172 #: src/views/card/components/ChecklistItemRow.tsx:195
msgid "Add details..." msgid "Add details..."
msgstr "Ajouter des détails..." msgstr "Ajouter des détails..."
#: src/views/card/components/LabelSelector.tsx:109 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:114 #: src/views/card/components/LabelSelector.tsx:115
msgid "Add label" msgid "Add label"
msgstr "Ajouter une étiquette" msgstr "Ajouter une étiquette"
#: src/views/card/components/MemberSelector.tsx:130 #: src/views/card/components/MemberSelector.tsx:131
#: src/views/members/components/InviteMemberForm.tsx:257 #: src/views/members/components/InviteMemberForm.tsx:257
msgid "Add member" msgid "Add member"
msgstr "Ajouter un membre" msgstr "Ajouter un membre"
#: src/views/card/components/ActivityList.tsx:69 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:77
msgid "added {0} labels: <0>{labelList}</0>"
msgstr "a ajouté {0} étiquettes : <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:107
msgid "added a checklist" msgid "added a checklist"
msgstr "a ajouté une checklist" msgstr "a ajouté une checklist"
#: src/views/card/components/ActivityList.tsx:72 #: src/views/card/components/ActivityList.tsx:110
msgid "added a checklist item" msgid "added a checklist item"
msgstr "a ajouté un élément à la checklist" msgstr "a ajouté un élément à la checklist"
#: src/views/card/components/ActivityList.tsx:65 #: src/views/card/components/ActivityList.tsx:103
msgid "added a label to the card" msgid "added a label to the card"
msgstr "a ajouté une étiquette à la carte" msgstr "a ajouté une étiquette à la carte"
#: src/views/card/components/ActivityList.tsx:67 #: src/views/card/components/ActivityList.tsx:105
msgid "added a member to the card" msgid "added a member to the card"
msgstr "a ajouté un membre à la carte" msgstr "a ajouté un membre à la carte"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146 #: src/views/card/components/ActivityList.tsx:181
msgid "added checklist <0>{0}</0>" msgid "added checklist <0>{0}</0>"
msgstr "a ajouté la checklist <0>{0}</0>" msgstr "a ajouté la checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170 #: src/views/card/components/ActivityList.tsx:205
msgid "added checklist item <0>{0}</0>" msgid "added checklist item <0>{0}</0>"
msgstr "a ajouté l'élément <0>{0}</0> à la checklist" msgstr "a ajouté l'élément <0>{0}</0> à la checklist"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130 #: src/views/card/components/ActivityList.tsx:165
msgid "added label <0>{0}</0>" msgid "added label <0>{0}</0>"
msgstr "a ajouté l'étiquette <0>{0}</0>" msgstr "a ajouté l'étiquette <0>{0}</0>"
@@ -249,11 +254,11 @@ msgstr "Êtes-vous sûr de vouloir supprimer ce {0} ?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Êtes-vous sûr de vouloir supprimer cette carte ?" msgstr "Êtes-vous sûr de vouloir supprimer cette carte ?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55 #: src/views/card/components/DeleteChecklistConfirmation.tsx:56
msgid "Are you sure you want to delete this checklist?" msgid "Are you sure you want to delete this checklist?"
msgstr "Êtes-vous sûr de vouloir supprimer cette checklist ?" msgstr "Êtes-vous sûr de vouloir supprimer cette checklist ?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:66
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Êtes-vous sûr de vouloir supprimer ce commentaire ?" msgstr "Êtes-vous sûr de vouloir supprimer ce commentaire ?"
@@ -266,7 +271,7 @@ msgid "Are you sure you want to delete your account?"
msgstr "Êtes-vous sûr de vouloir supprimer votre compte ?" msgstr "Êtes-vous sûr de vouloir supprimer votre compte ?"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:145
msgid "assigned <0>{0}</0> to the card" msgid "assigned <0>{0}</0> to the card"
msgstr "a assigné <0>{0}</0> à la carte" msgstr "a assigné <0>{0}</0> à la carte"
@@ -274,7 +279,7 @@ msgstr "a assigné <0>{0}</0> à la carte"
msgid "Assignees" msgid "Assignees"
msgstr "Assignés" msgstr "Assignés"
#: src/views/card/components/AttachmentUpload.tsx:25 #: src/views/card/components/AttachmentUpload.tsx:26
msgid "Attachment uploaded" msgid "Attachment uploaded"
msgstr "Pièce jointe téléversée" msgstr "Pièce jointe téléversée"
@@ -312,9 +317,9 @@ msgstr "Portail de facturation"
msgid "Blog Post" msgid "Blog Post"
msgstr "Article de blog" msgstr "Article de blog"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
msgid "Board" msgid "Board"
msgstr "Tableau" msgstr "Tableau"
@@ -331,7 +336,7 @@ msgstr "Le nom du tableau ne peut pas dépasser 100 caractères"
msgid "Board name is required" msgid "Board name is required"
msgstr "Le nom du tableau est requis" msgstr "Le nom du tableau est requis"
#: src/views/public/board/index.tsx:153 #: src/views/public/board/index.tsx:166
msgid "Board not found" msgid "Board not found"
msgstr "Tableau introuvable" msgstr "Tableau introuvable"
@@ -347,7 +352,7 @@ msgstr "L'URL du tableau ne peut contenir que des lettres, des chiffres et des t
msgid "Board URL cannot exceed 60 characters" msgid "Board URL cannot exceed 60 characters"
msgstr "L'URL du tableau ne peut pas dépasser 60 caractères" msgstr "L'URL du tableau ne peut pas dépasser 60 caractères"
#: src/views/public/board/index.tsx:68 #: src/views/public/board/index.tsx:80
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "URL du tableau copiée dans le presse-papiers" msgstr "URL du tableau copiée dans le presse-papiers"
@@ -382,10 +387,10 @@ msgstr "Rapport de bug"
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:49
#: src/views/board/components/DeleteBoardConfirmation.tsx:44 #: src/views/board/components/DeleteBoardConfirmation.tsx:44
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:159
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63 #: src/views/card/components/DeleteChecklistConfirmation.tsx:64
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:77
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/settings/components/Avatar.tsx:306 #: src/views/settings/components/Avatar.tsx:306
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168 #: src/views/settings/components/ChangePasswordConfirmation.tsx:168
@@ -395,16 +400,16 @@ msgstr "Rapport de bug"
msgid "Cancel" msgid "Cancel"
msgstr "Annuler" msgstr "Annuler"
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "Card" msgid "Card"
msgstr "Carte" msgstr "Carte"
#: src/views/card/index.tsx:263 #: src/views/card/index.tsx:306
#: src/views/card/index.tsx:299 #: src/views/card/index.tsx:342
msgid "Card not found" msgid "Card not found"
msgstr "Carte introuvable" msgstr "Carte introuvable"
#: src/views/board/components/NewCardForm.tsx:310 #: src/views/board/components/NewCardForm.tsx:319
msgid "Card title" msgid "Card title"
msgstr "Titre de la carte" msgstr "Titre de la carte"
@@ -419,6 +424,11 @@ msgstr "Modifier le mot de passe"
msgid "Change your language preferences." msgid "Change your language preferences."
msgstr "Modifiez vos préférences linguistiques." msgstr "Modifiez vos préférences linguistiques."
#: src/views/card/components/ActivityList.tsx:255
#: src/views/card/components/ActivityList.tsx:269
msgid "changed the due date to <0>{formattedDate}</0>"
msgstr "a modifié la date d'échéance pour <0>{formattedDate}</0>"
#: src/views/oss-friends/index.tsx:61 #: src/views/oss-friends/index.tsx:61
msgid "Check out some of our favorite open source projects." msgid "Check out some of our favorite open source projects."
msgstr "Découvrez certains de nos projets open source préférés." msgstr "Découvrez certains de nos projets open source préférés."
@@ -428,7 +438,7 @@ msgstr "Découvrez certains de nos projets open source préférés."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Vérifiez votre boîte de réception" msgstr "Vérifiez votre boîte de réception"
#: src/views/card/components/NewChecklistForm.tsx:118 #: src/views/card/components/NewChecklistForm.tsx:119
msgid "Checklist name" msgid "Checklist name"
msgstr "Nom de la checklist" msgstr "Nom de la checklist"
@@ -437,7 +447,7 @@ msgstr "Nom de la checklist"
msgid "Checklists" msgid "Checklists"
msgstr "Listes de contrôle" msgstr "Listes de contrôle"
#: src/views/board/components/Filters.tsx:180 #: src/views/board/components/Filters.tsx:227
msgid "Clear filters" msgid "Clear filters"
msgstr "Effacer les filtres" msgstr "Effacer les filtres"
@@ -489,15 +499,19 @@ msgstr "Terminé"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Contrôle et propriété complets :" msgstr "Contrôle et propriété complets :"
#: src/views/card/components/ActivityList.tsx:74 #: src/views/card/components/ActivityList.tsx:112
msgid "completed a checklist item" msgid "completed a checklist item"
msgstr "a terminé un élément de la checklist" msgstr "a terminé un élément de la checklist"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187 #: src/views/card/components/ActivityList.tsx:222
msgid "completed checklist item <0>{0}</0>" msgid "completed checklist item <0>{0}</0>"
msgstr "a terminé l'élément <0>{0}</0> de la checklist" 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 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password" msgid "Confirm your new password"
msgstr "Confirmez votre nouveau mot de passe" msgstr "Confirmez votre nouveau mot de passe"
@@ -551,7 +565,7 @@ msgid "Create {0}"
msgstr "Créer {0}" msgstr "Créer {0}"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:469 #: src/views/board/components/NewCardForm.tsx:516
#: src/views/board/components/NewListForm.tsx:141 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Créer un autre" msgstr "Créer un autre"
@@ -560,11 +574,11 @@ msgstr "Créer un autre"
msgid "Create API key" msgid "Create API key"
msgstr "Créer une clé API" msgstr "Créer une clé API"
#: src/views/board/components/NewCardForm.tsx:479 #: src/views/board/components/NewCardForm.tsx:526
msgid "Create card" msgid "Create card"
msgstr "Créer une carte" msgstr "Créer une carte"
#: src/views/card/components/NewChecklistForm.tsx:134 #: src/views/card/components/NewChecklistForm.tsx:135
msgid "Create checklist" msgid "Create checklist"
msgstr "Créer une checklist" msgstr "Créer une checklist"
@@ -590,13 +604,13 @@ msgstr "Créer un nouveau {0}"
msgid "Create new key" msgid "Create new key"
msgstr "Créer une nouvelle clé" msgstr "Créer une nouvelle clé"
#: src/views/board/components/NewCardForm.tsx:405 #: src/views/board/components/NewCardForm.tsx:414
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:98
msgid "Create new label" msgid "Create new label"
msgstr "Créer une nouvelle étiquette" msgstr "Créer une nouvelle étiquette"
#: src/views/board/index.tsx:64 #: src/views/board/index.tsx:64
#: src/views/board/index.tsx:491 #: src/views/board/index.tsx:499
msgid "Create new list" msgid "Create new list"
msgstr "Créer une nouvelle liste" msgstr "Créer une nouvelle liste"
@@ -609,7 +623,7 @@ msgstr "Créer un modèle"
msgid "Create workspace" msgid "Create workspace"
msgstr "Créer un espace de travail" msgstr "Créer un espace de travail"
#: src/views/card/components/ActivityList.tsx:61 #: src/views/card/components/ActivityList.tsx:99
msgid "created the card" msgid "created the card"
msgstr "a créé la carte" msgstr "a créé la carte"
@@ -667,8 +681,8 @@ msgstr "Désactiver le lien d'invitation"
#: src/components/LabelForm.tsx:228 #: src/components/LabelForm.tsx:228
#: src/views/board/components/DeleteBoardConfirmation.tsx:47 #: src/views/board/components/DeleteBoardConfirmation.tsx:47
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66 #: src/views/card/components/DeleteChecklistConfirmation.tsx:67
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:83
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
@@ -686,7 +700,7 @@ msgstr "Supprimer le tableau"
msgid "Delete card" msgid "Delete card"
msgstr "Supprimer la carte" msgstr "Supprimer la carte"
#: src/views/card/components/Comment.tsx:91 #: src/views/card/components/Comment.tsx:92
msgid "Delete comment" msgid "Delete comment"
msgstr "Supprimer le commentaire" msgstr "Supprimer le commentaire"
@@ -704,21 +718,21 @@ msgstr "Supprimer le modèle"
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Supprimer l'espace de travail" msgstr "Supprimer l'espace de travail"
#: src/views/card/components/ActivityList.tsx:71 #: src/views/card/components/ActivityList.tsx:109
msgid "deleted a checklist" msgid "deleted a checklist"
msgstr "a supprimé une checklist" msgstr "a supprimé une checklist"
#: src/views/card/components/ActivityList.tsx:76 #: src/views/card/components/ActivityList.tsx:114
msgid "deleted a checklist item" msgid "deleted a checklist item"
msgstr "a supprimé un élément de la checklist" msgstr "a supprimé un élément de la checklist"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162 #: src/views/card/components/ActivityList.tsx:197
msgid "deleted checklist <0>{0}</0>" msgid "deleted checklist <0>{0}</0>"
msgstr "a supprimé la checklist <0>{0}</0>" msgstr "a supprimé la checklist <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205 #: src/views/card/components/ActivityList.tsx:240
msgid "deleted checklist item <0>{0}</0>" msgid "deleted checklist item <0>{0}</0>"
msgstr "a supprimé l'élément <0>{0}</0> de la checklist" msgstr "a supprimé l'élément <0>{0}</0> de la checklist"
@@ -754,6 +768,10 @@ msgstr "Nom d'affichage mis à jour"
msgid "Do you offer a free plan?" msgid "Do you offer a free plan?"
msgstr "Proposez-vous un plan gratuit ?" 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 #: src/components/FeedbackModal.tsx:109
msgid "docs" msgid "docs"
msgstr "documentation" msgstr "documentation"
@@ -780,16 +798,38 @@ msgstr "Vous n'avez pas de compte ? <0><1>Inscrivez-vous</1></0>"
msgid "Done" msgid "Done"
msgstr "Fait" msgstr "Fait"
#: src/views/card/components/AttachmentThumbnails.tsx:141 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "Download failed" msgid "Download failed"
msgstr "Échec du téléchargement" msgstr "Échec du téléchargement"
#: src/views/board/components/Filters.tsx:171
#: src/views/board/components/NewCardForm.tsx:469
#: src/views/card/index.tsx:139
msgid "Due date"
msgstr "Date d'échéance"
#: src/views/board/components/Filters.tsx:132
msgid "Due next month"
msgstr "Échéance le mois prochain"
#: src/views/board/components/Filters.tsx:127
msgid "Due next week"
msgstr "Échéance la semaine prochaine"
#: src/views/board/components/Filters.tsx:117
msgid "Due today"
msgstr "Échéance aujourd'hui"
#: src/views/board/components/Filters.tsx:122
msgid "Due tomorrow"
msgstr "Échéance demain"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:116 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Modifier l'URL du tableau" msgstr "Modifier l'URL du tableau"
#: src/views/card/components/Comment.tsx:82 #: src/views/card/components/Comment.tsx:83
msgid "Edit comment" msgid "Edit comment"
msgstr "Modifier le commentaire" msgstr "Modifier le commentaire"
@@ -946,8 +986,8 @@ msgstr "Échec de la création du tableau"
msgid "Failed to login with {0}. Please try again." msgid "Failed to login with {0}. Please try again."
msgstr "Échec de connexion avec {0}. Veuillez réessayer." msgstr "Échec de connexion avec {0}. Veuillez réessayer."
#: src/views/card/components/AttachmentUpload.tsx:33 #: src/views/card/components/AttachmentUpload.tsx:34
#: src/views/card/components/AttachmentUpload.tsx:79 #: src/views/card/components/AttachmentUpload.tsx:80
msgid "Failed to upload attachment. Please try again." msgid "Failed to upload attachment. Please try again."
msgstr "Échec du téléversement de la pièce jointe. Veuillez réessayer." msgstr "Échec du téléversement de la pièce jointe. Veuillez réessayer."
@@ -994,7 +1034,7 @@ msgstr "Commentaires"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Commentaires envoyés" msgstr "Commentaires envoyés"
#: src/views/board/components/Filters.tsx:174 #: src/views/board/components/Filters.tsx:221
msgid "Filter" msgid "Filter"
msgstr "Filtrer" msgstr "Filtrer"
@@ -1052,7 +1092,7 @@ msgstr "Commencer"
msgid "Get started by creating a new {0}" msgid "Get started by creating a new {0}"
msgstr "Commencez par créer un nouveau {0}" msgstr "Commencez par créer un nouveau {0}"
#: src/views/board/index.tsx:483 #: src/views/board/index.tsx:491
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Commencez par créer une nouvelle liste" msgstr "Commencez par créer une nouvelle liste"
@@ -1239,7 +1279,7 @@ msgstr "Liens d'invitation"
msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace."
msgstr "Les liens d'invitation nécessitent un abonnement Team ou Pro. Veuillez mettre à niveau votre espace de travail." msgstr "Les liens d'invitation nécessitent un abonnement Team ou Pro. Veuillez mettre à niveau votre espace de travail."
#: src/views/card/components/MemberSelector.tsx:111 #: src/views/card/components/MemberSelector.tsx:112
#: src/views/members/components/InviteMemberForm.tsx:367 #: src/views/members/components/InviteMemberForm.tsx:367
msgid "Invite member" msgid "Invite member"
msgstr "Inviter un membre" msgstr "Inviter un membre"
@@ -1286,9 +1326,9 @@ msgstr "Gardez à l'esprit que cette action est irréversible."
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "Raccourcis clavier" msgstr "Raccourcis clavier"
#: src/views/board/components/Filters.tsx:115 #: src/views/board/components/Filters.tsx:155
#: src/views/board/components/NewCardForm.tsx:409 #: src/views/board/components/NewCardForm.tsx:418
#: src/views/card/index.tsx:119 #: src/views/card/index.tsx:121
msgid "Labels" msgid "Labels"
msgstr "Étiquettes" msgstr "Étiquettes"
@@ -1338,11 +1378,11 @@ msgstr "Licence"
msgid "Light" msgid "Light"
msgstr "Clair" msgstr "Clair"
#: src/views/public/board/index.tsx:66 #: src/views/public/board/index.tsx:78
msgid "Link copied" msgid "Link copied"
msgstr "Lien copié" msgstr "Lien copié"
#: src/views/card/index.tsx:111 #: src/views/card/index.tsx:113
msgid "List" msgid "List"
msgstr "Liste" msgstr "Liste"
@@ -1350,10 +1390,18 @@ msgstr "Liste"
msgid "List name" msgid "List name"
msgstr "Nom de la liste" msgstr "Nom de la liste"
#: src/views/board/components/Filters.tsx:123 #: src/views/board/components/Filters.tsx:163
msgid "Lists" msgid "Lists"
msgstr "Listes" msgstr "Listes"
#: src/views/card/components/ActivityList.tsx:530
msgid "Load more activities"
msgstr "Charger plus d'activités"
#: src/views/card/components/ActivityList.tsx:530
msgid "Loading..."
msgstr "Chargement..."
#: src/views/auth/login/index.tsx:33 #: src/views/auth/login/index.tsx:33
msgid "Login | kan.bn" msgid "Login | kan.bn"
msgstr "Connexion | kan.bn" msgstr "Connexion | kan.bn"
@@ -1382,12 +1430,12 @@ msgstr "lien magique"
msgid "Make template" msgid "Make template"
msgstr "Créer un modèle" msgstr "Créer un modèle"
#: src/views/card/components/ActivityList.tsx:75 #: src/views/card/components/ActivityList.tsx:113
msgid "marked a checklist item as incomplete" msgid "marked a checklist item as incomplete"
msgstr "a marqué un élément de la checklist comme incomplet" msgstr "a marqué un élément de la checklist comme incomplet"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196 #: src/views/card/components/ActivityList.tsx:231
msgid "marked checklist item <0>{0}</0> as incomplete" msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "a marqué l'élément <0>{0}</0> de la checklist comme incomplet" msgstr "a marqué l'élément <0>{0}</0> de la checklist comme incomplet"
@@ -1396,9 +1444,9 @@ msgid "Medium Priority"
msgstr "Priorité moyenne" msgstr "Priorité moyenne"
#: src/components/SideNavigation.tsx:121 #: src/components/SideNavigation.tsx:121
#: src/views/board/components/Filters.tsx:107 #: src/views/board/components/Filters.tsx:147
#: src/views/board/components/NewCardForm.tsx:367 #: src/views/board/components/NewCardForm.tsx:376
#: src/views/card/index.tsx:128 #: src/views/card/index.tsx:130
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Membres" msgstr "Membres"
@@ -1419,11 +1467,11 @@ msgstr "facturation mensuelle"
#. placeholder {0}: truncate(fromList) #. placeholder {0}: truncate(fromList)
#. placeholder {1}: truncate(toList) #. placeholder {1}: truncate(toList)
#: src/views/card/components/ActivityList.tsx:98 #: src/views/card/components/ActivityList.tsx:133
msgid "moved the card from <0>{0}</0> to<1>{1}</1>" msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "a déplacé la carte de <0>{0}</0> vers <1>{1}</1>" msgstr "a déplacé la carte de <0>{0}</0> vers <1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:64 #: src/views/card/components/ActivityList.tsx:102
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "a déplacé la carte vers une autre liste" msgstr "a déplacé la carte vers une autre liste"
@@ -1455,11 +1503,11 @@ msgstr "Nouveau {0}"
msgid "New API key" msgid "New API key"
msgstr "Nouvelle clé API" msgstr "Nouvelle clé API"
#: src/views/board/components/NewCardForm.tsx:293 #: src/views/board/components/NewCardForm.tsx:302
msgid "New card" msgid "New card"
msgstr "Nouvelle carte" msgstr "Nouvelle carte"
#: src/views/card/components/NewChecklistForm.tsx:102 #: src/views/card/components/NewChecklistForm.tsx:103
msgid "New checklist" msgid "New checklist"
msgstr "Nouvelle checklist" msgstr "Nouvelle checklist"
@@ -1472,7 +1520,7 @@ msgid "New label"
msgstr "Nouvelle étiquette" msgstr "Nouvelle étiquette"
#: src/views/board/components/NewListForm.tsx:113 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:454 #: src/views/board/index.tsx:462
msgid "New list" msgid "New list"
msgstr "Nouvelle liste" msgstr "Nouvelle liste"
@@ -1521,7 +1569,11 @@ msgstr "Aucun tableau trouvé"
msgid "No credit card required" msgid "No credit card required"
msgstr "Aucune carte de crédit requise" msgstr "Aucune carte de crédit requise"
#: src/views/card/components/AttachmentThumbnails.tsx:142 #: src/views/board/components/Filters.tsx:137
msgid "No dates"
msgstr "Aucune date"
#: src/views/card/components/AttachmentThumbnails.tsx:143
msgid "No download URL available for this attachment." msgid "No download URL available for this attachment."
msgstr "Aucune URL de téléchargement disponible pour cette pièce jointe." msgstr "Aucune URL de téléchargement disponible pour cette pièce jointe."
@@ -1529,7 +1581,7 @@ msgstr "Aucune URL de téléchargement disponible pour cette pièce jointe."
msgid "No keyboard shortcuts registered." msgid "No keyboard shortcuts registered."
msgstr "Aucun raccourci clavier enregistré." msgstr "Aucun raccourci clavier enregistré."
#: src/views/board/index.tsx:480 #: src/views/board/index.tsx:488
msgid "No lists" msgid "No lists"
msgstr "Aucune liste" msgstr "Aucune liste"
@@ -1582,6 +1634,10 @@ msgstr "Organisez et trouvez rapidement des cartes avec des outils de filtrage p
msgid "OSS Friends" msgid "OSS Friends"
msgstr "Amis OSS" msgstr "Amis OSS"
#: src/views/board/components/Filters.tsx:112
msgid "Overdue"
msgstr "En retard"
#: src/views/pricing/components/Pricing.tsx:73 #: src/views/pricing/components/Pricing.tsx:73
#: src/views/pricing/components/PricingTiers.tsx:70 #: src/views/pricing/components/PricingTiers.tsx:70
msgid "Own your data" msgid "Own your data"
@@ -1670,30 +1726,33 @@ msgstr "Veuillez sélectionner un fichier à télécharger."
#: src/components/DeleteLabelConfirmation.tsx:26 #: src/components/DeleteLabelConfirmation.tsx:26
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/NewWorkspaceForm.tsx:158 #: src/components/NewWorkspaceForm.tsx:158
#: src/views/board/components/NewCardForm.tsx:177 #: src/views/board/components/NewCardForm.tsx:184
#: src/views/board/components/NewListForm.tsx:79 #: src/views/board/components/NewListForm.tsx:79
#: src/views/board/components/NewTemplateForm.tsx:61 #: src/views/board/components/NewTemplateForm.tsx:61
#: src/views/board/components/NewTemplateForm.tsx:77 #: src/views/board/components/NewTemplateForm.tsx:77
#: src/views/board/components/UpdateBoardSlugForm.tsx:73 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:54 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:162 #: src/views/board/index.tsx:170
#: src/views/board/index.tsx:218 #: src/views/board/index.tsx:226
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/card/components/AttachmentThumbnails.tsx:73 #: src/views/card/components/AttachmentThumbnails.tsx:74
#: src/views/card/components/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:67
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:95
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:47
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Checklists.tsx:81
#: src/views/card/components/Comment.tsx:65
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37 #: src/views/card/components/DeleteChecklistConfirmation.tsx:38
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:46
#: src/views/card/components/LabelSelector.tsx:72 #: src/views/card/components/DueDateSelector.tsx:60
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/MemberSelector.tsx:79 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistForm.tsx:71
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewChecklistItemForm.tsx:90
#: src/views/card/index.tsx:177 #: src/views/card/components/NewCommentForm.tsx:32
#: src/views/card/index.tsx:187
#: src/views/card/index.tsx:200
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/members/components/InviteMemberForm.tsx:104 #: src/views/members/components/InviteMemberForm.tsx:104
#: src/views/members/components/InviteMemberForm.tsx:241 #: src/views/members/components/InviteMemberForm.tsx:241
@@ -1793,30 +1852,40 @@ msgstr "Supprimer"
msgid "Remove member" msgid "Remove member"
msgstr "Supprimer le membre" msgstr "Supprimer le membre"
#: src/views/card/components/ActivityList.tsx:66 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:91
msgid "removed {0} labels: <0>{labelList}</0>"
msgstr "a supprimé {0} étiquettes : <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:104
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "a supprimé une étiquette de la carte" msgstr "a supprimé une étiquette de la carte"
#: src/views/card/components/ActivityList.tsx:68 #: src/views/card/components/ActivityList.tsx:106
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "a retiré un membre de la carte" msgstr "a retiré un membre de la carte"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138 #: src/views/card/components/ActivityList.tsx:173
msgid "removed label <0>{0}</0>" msgid "removed label <0>{0}</0>"
msgstr "a supprimé l'étiquette <0>{0}</0>" msgstr "a supprimé l'étiquette <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:70 #: src/views/card/components/ActivityList.tsx:117
#: src/views/card/components/ActivityList.tsx:276
msgid "removed the due date"
msgstr "a supprimé la date d'échéance"
#: src/views/card/components/ActivityList.tsx:108
msgid "renamed a checklist" msgid "renamed a checklist"
msgstr "a renommé une checklist" msgstr "a renommé une checklist"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154 #: src/views/card/components/ActivityList.tsx:189
msgid "renamed checklist <0>{0}</0>" msgid "renamed checklist <0>{0}</0>"
msgstr "a renommé la checklist <0>{0}</0>" msgstr "a renommé la checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178 #: src/views/card/components/ActivityList.tsx:213
msgid "renamed checklist item to <0>{0}</0>" msgid "renamed checklist item to <0>{0}</0>"
msgstr "a renommé l'élément de la liste de contrôle en <0>{0}</0>" msgstr "a renommé l'élément de la liste de contrôle en <0>{0}</0>"
@@ -1855,7 +1924,7 @@ msgstr "Rôle"
msgid "Run on your own infrastructure" msgid "Run on your own infrastructure"
msgstr "Exécutez sur votre propre infrastructure" msgstr "Exécutez sur votre propre infrastructure"
#: src/views/card/components/Comment.tsx:165 #: src/views/card/components/Comment.tsx:166
#: src/views/settings/components/Avatar.tsx:309 #: src/views/settings/components/Avatar.tsx:309
msgid "Save" msgid "Save"
msgstr "Enregistrer" msgstr "Enregistrer"
@@ -1893,7 +1962,7 @@ msgstr "Auto-hébergement"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Auto-hébergement avec Github" msgstr "Auto-hébergement avec Github"
#: src/views/card/components/ActivityList.tsx:107 #: src/views/card/components/ActivityList.tsx:142
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "s'est auto-assigné la carte" msgstr "s'est auto-assigné la carte"
@@ -1909,6 +1978,14 @@ msgstr "Envoyer des commentaires"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/card/components/DueDateSelector.tsx:117
msgid "Set due date"
msgstr "Définir la date d'échéance"
#: src/views/card/components/ActivityList.tsx:115
msgid "set the due date"
msgstr "a défini la date d'échéance"
#: src/components/SettingsLayout.tsx:82 #: src/components/SettingsLayout.tsx:82
#: src/components/SideNavigation.tsx:133 #: src/components/SideNavigation.tsx:133
msgid "Settings" msgid "Settings"
@@ -2030,8 +2107,8 @@ msgstr "Forfait d'équipe"
msgid "Teams" msgid "Teams"
msgstr "Équipes" msgstr "Équipes"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/board/index.tsx:409 #: src/views/board/index.tsx:417
msgid "Template" msgid "Template"
msgstr "Modèle" msgstr "Modèle"
@@ -2096,8 +2173,8 @@ msgstr "Ils ne pourront plus accéder à cet espace de travail."
#: src/components/DeleteLabelConfirmation.tsx:44 #: src/components/DeleteLabelConfirmation.tsx:44
#: src/views/board/components/DeleteBoardConfirmation.tsx:39 #: src/views/board/components/DeleteBoardConfirmation.tsx:39
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58 #: src/views/card/components/DeleteChecklistConfirmation.tsx:59
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:69
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Cette action ne peut pas être annulée." msgstr "Cette action ne peut pas être annulée."
@@ -2105,7 +2182,7 @@ msgstr "Cette action ne peut pas être annulée."
msgid "This API key will only be shown once. Please save it in a secure location." msgid "This API key will only be shown once. Please save it in a secure location."
msgstr "Cette clé API ne sera affichée qu'une seule fois. Veuillez la sauvegarder dans un emplacement sécurisé." msgstr "Cette clé API ne sera affichée qu'une seule fois. Veuillez la sauvegarder dans un emplacement sécurisé."
#: src/views/public/board/index.tsx:156 #: src/views/public/board/index.tsx:169
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "Ce tableau est privé ou n'existe pas" msgstr "Ce tableau est privé ou n'existe pas"
@@ -2167,23 +2244,27 @@ msgstr "Importations Trello"
msgid "Triaging" msgid "Triaging"
msgstr "Triage" msgstr "Triage"
#: src/views/home/components/Logos.tsx:73 #: src/views/home/components/Logos.tsx:67
msgid "Trusted by fast-moving teams<0/>around the world" msgid "Trusted by fast-moving teams<0/>around the world"
msgstr "Approuvé par des équipes dynamiques<0/>du monde entier" msgstr "Approuvé par des équipes dynamiques<0/>du monde entier"
#: src/views/card/components/NewChecklistItemForm.tsx:88 #: src/views/card/components/NewChecklistItemForm.tsx:89
msgid "Unable to add checklist item" msgid "Unable to add checklist item"
msgstr "Impossible d'ajouter l'élément à la liste de contrôle" msgstr "Impossible d'ajouter l'élément à la liste de contrôle"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:31
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Impossible d'ajouter un commentaire" msgstr "Impossible d'ajouter un commentaire"
#: src/views/board/components/NewCardForm.tsx:174 #: src/views/card/index.tsx:199
msgid "Unable to add label"
msgstr "Impossible d'ajouter l'étiquette"
#: src/views/board/components/NewCardForm.tsx:181
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Impossible de créer la carte" msgstr "Impossible de créer la carte"
#: src/views/card/components/NewChecklistForm.tsx:69 #: src/views/card/components/NewChecklistForm.tsx:70
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Impossible de créer la liste de contrôle" msgstr "Impossible de créer la liste de contrôle"
@@ -2200,7 +2281,7 @@ msgstr "Impossible de créer le modèle"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "Impossible de créer l'espace de travail" msgstr "Impossible de créer l'espace de travail"
#: src/views/card/components/AttachmentThumbnails.tsx:72 #: src/views/card/components/AttachmentThumbnails.tsx:73
msgid "Unable to delete attachment" msgid "Unable to delete attachment"
msgstr "Impossible de supprimer la pièce jointe" msgstr "Impossible de supprimer la pièce jointe"
@@ -2208,15 +2289,15 @@ msgstr "Impossible de supprimer la pièce jointe"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Impossible de supprimer la carte" msgstr "Impossible de supprimer la carte"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36 #: src/views/card/components/DeleteChecklistConfirmation.tsx:37
msgid "Unable to delete checklist" msgid "Unable to delete checklist"
msgstr "Impossible de supprimer la liste de contrôle" msgstr "Impossible de supprimer la liste de contrôle"
#: src/views/card/components/ChecklistItemRow.tsx:87 #: src/views/card/components/ChecklistItemRow.tsx:94
msgid "Unable to delete checklist item" msgid "Unable to delete checklist item"
msgstr "Impossible de supprimer l'élément de la liste de contrôle" msgstr "Impossible de supprimer l'élément de la liste de contrôle"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Impossible de supprimer le commentaire" msgstr "Impossible de supprimer le commentaire"
@@ -2224,6 +2305,10 @@ msgstr "Impossible de supprimer le commentaire"
msgid "Unable to remove member" msgid "Unable to remove member"
msgstr "Impossible de supprimer le membre" msgstr "Impossible de supprimer le membre"
#: src/views/card/components/Checklists.tsx:80
msgid "Unable to reorder checklist item"
msgstr "Impossible de réorganiser l'élément de la liste de contrôle"
#: src/components/FeedbackModal.tsx:40 #: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Impossible d'envoyer les commentaires" msgstr "Impossible d'envoyer les commentaires"
@@ -2236,42 +2321,46 @@ msgstr "Impossible de mettre à jour l'URL du tableau"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Impossible de mettre à jour la visibilité du tableau" msgstr "Impossible de mettre à jour la visibilité du tableau"
#: src/views/board/index.tsx:217 #: src/views/board/index.tsx:225
#: src/views/card/index.tsx:176 #: src/views/card/index.tsx:186
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Impossible de mettre à jour la carte" msgstr "Impossible de mettre à jour la carte"
#: src/views/card/components/ChecklistNameInput.tsx:45 #: src/views/card/components/ChecklistNameInput.tsx:46
msgid "Unable to update checklist" msgid "Unable to update checklist"
msgstr "Impossible de mettre à jour la liste de contrôle" msgstr "Impossible de mettre à jour la liste de contrôle"
#: src/views/card/components/ChecklistItemRow.tsx:59 #: src/views/card/components/ChecklistItemRow.tsx:66
msgid "Unable to update checklist item" msgid "Unable to update checklist item"
msgstr "Impossible de mettre à jour l'élément de la liste de contrôle" msgstr "Impossible de mettre à jour l'élément de la liste de contrôle"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:64
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Impossible de mettre à jour le commentaire" msgstr "Impossible de mettre à jour le commentaire"
#: src/views/card/components/LabelSelector.tsx:71 #: src/views/card/components/DueDateSelector.tsx:59
msgid "Unable to update due date"
msgstr "Impossible de mettre à jour la date d'échéance"
#: src/views/card/components/LabelSelector.tsx:72
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "Impossible de mettre à jour les étiquettes" msgstr "Impossible de mettre à jour les étiquettes"
#: src/views/board/index.tsx:161 #: src/views/board/index.tsx:169
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:52
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Impossible de mettre à jour la liste" msgstr "Impossible de mettre à jour la liste"
#: src/views/card/components/MemberSelector.tsx:78 #: src/views/card/components/MemberSelector.tsx:79
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Impossible de mettre à jour les membres" msgstr "Impossible de mettre à jour les membres"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:121 #: src/views/card/components/ActivityList.tsx:156
msgid "unassigned <0>{0}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "a désassigné <0>{0}</0> de la carte" msgstr "a désassigné <0>{0}</0> de la carte"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:153
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "s'est retiré de la carte" msgstr "s'est retiré de la carte"
@@ -2313,6 +2402,11 @@ msgstr "Membres illimités"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Espaces de travail illimités" 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/board/components/UpdateBoardSlugForm.tsx:175
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80 #: src/views/settings/components/UpdateDisplayNameForm.tsx:80
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
@@ -2325,20 +2419,24 @@ msgstr "Mettre à jour"
msgid "Update label" msgid "Update label"
msgstr "Mettre à jour l'étiquette" msgstr "Mettre à jour l'étiquette"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:111
msgid "updated a checklist item" msgid "updated a checklist item"
msgstr "a mis à jour un élément de la liste de contrôle" msgstr "a mis à jour un élément de la liste de contrôle"
#: src/views/card/components/ActivityList.tsx:63 #: src/views/card/components/ActivityList.tsx:101
msgid "updated the description" msgid "updated the description"
msgstr "a mis à jour la description" msgstr "a mis à jour la description"
#: src/views/card/components/ActivityList.tsx:62 #: src/views/card/components/ActivityList.tsx:116
msgid "updated the due date"
msgstr "a mis à jour la date d'échéance"
#: src/views/card/components/ActivityList.tsx:100
msgid "updated the title" msgid "updated the title"
msgstr "a mis à jour le titre" msgstr "a mis à jour le titre"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90 #: src/views/card/components/ActivityList.tsx:125
msgid "updated the title to <0>{0}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "a mis à jour le titre en <0>{0}</0>" msgstr "a mis à jour le titre en <0>{0}</0>"
@@ -2352,8 +2450,8 @@ msgstr "Passer à Pro"
msgid "Upgrade to Pro ($29/month)" msgid "Upgrade to Pro ($29/month)"
msgstr "Passer à Pro (29 $/mois)" msgstr "Passer à Pro (29 $/mois)"
#: src/views/card/components/AttachmentUpload.tsx:32 #: src/views/card/components/AttachmentUpload.tsx:33
#: src/views/card/components/AttachmentUpload.tsx:78 #: src/views/card/components/AttachmentUpload.tsx:79
msgid "Upload failed" msgid "Upload failed"
msgstr "Échec du téléversement" msgstr "Échec du téléversement"
@@ -2406,7 +2504,7 @@ msgstr "Consultez et gérez votre facturation et votre abonnement."
msgid "View docs" msgid "View docs"
msgstr "Voir la documentation" msgstr "Voir la documentation"
#: src/views/public/board/index.tsx:129 #: src/views/public/board/index.tsx:142
msgid "View only" msgid "View only"
msgstr "Affichage uniquement" msgstr "Affichage uniquement"
@@ -2414,7 +2512,7 @@ msgstr "Affichage uniquement"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "Consultez notre feuille de route." msgstr "Consultez notre feuille de route."
#: src/views/public/board/index.tsx:159 #: src/views/public/board/index.tsx:172
msgid "View workspace" msgid "View workspace"
msgstr "Voir l'espace de travail" msgstr "Voir l'espace de travail"
@@ -2426,6 +2524,10 @@ msgstr "Visibilité"
msgid "We are using the <0>AGPL-3.0 license</0>." msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "Nous utilisons la <0>licence AGPL-3.0</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 #: src/views/home/components/Features.tsx:152
msgid "We're just getting started. " msgid "We're just getting started. "
msgstr "Nous ne faisons que commencer. " msgstr "Nous ne faisons que commencer. "
@@ -2455,10 +2557,10 @@ msgid "Why make an open source Trello?"
msgstr "Pourquoi créer un Trello open source ?" msgstr "Pourquoi créer un Trello open source ?"
#: src/components/SettingsLayout.tsx:39 #: src/components/SettingsLayout.tsx:39
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Espace de travail" msgstr "Espace de travail"
@@ -2564,6 +2666,10 @@ msgstr "Vous vous êtes connecté avec succès."
msgid "You have been signed up successfully." msgid "You have been signed up successfully."
msgstr "Vous vous êtes inscrit avec succès." 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 #: src/views/members/components/InviteMemberForm.tsx:326
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!" 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 !" msgstr "Vous disposez de places illimitées avec votre Plan Pro. Il n'y a pas de frais supplémentaires pour les nouveaux membres !"
@@ -2588,7 +2694,7 @@ msgstr "Vos tableaux ont été importés."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Votre nom d'affichage a été mis à jour." msgstr "Votre nom d'affichage a été mis à jour."
#: src/views/card/components/AttachmentUpload.tsx:26 #: src/views/card/components/AttachmentUpload.tsx:27
msgid "Your file has been uploaded successfully." msgid "Your file has been uploaded successfully."
msgstr "Votre fichier a été téléversé avec succès." msgstr "Votre fichier a été téléversé avec succès."
@@ -2608,6 +2714,10 @@ msgstr "Votre compte Trello a été déconnecté."
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Votre compte Trello est connecté." 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 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
msgid "Your workspace description has been updated." msgid "Your workspace description has been updated."
msgstr "La description de votre espace de travail a été mise à jour." msgstr "La description de votre espace de travail a été mise à jour."

File diff suppressed because one or more lines are too long

View File

@@ -7,6 +7,7 @@ export const locales = [
"nl", "nl",
"ru", "ru",
"pl", "pl",
"ptbr"
] as const; ] as const;
export type Locale = (typeof locales)[number]; export type Locale = (typeof locales)[number];
@@ -22,4 +23,5 @@ export const localeNames: Record<Locale, string> = {
nl: "Nederlands", nl: "Nederlands",
ru: "Русский", ru: "Русский",
pl: "Polski", pl: "Polski",
ptbr: "Português",
}; };

View File

@@ -13,7 +13,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:123 #: src/views/card/components/Comment.tsx:124
msgid " (edited)" msgid " (edited)"
msgstr " (modificato)" msgstr " (modificato)"
@@ -31,17 +31,17 @@ msgstr "{0}"
#. placeholder {1}: board?.name ?? t`Board` #. placeholder {1}: board?.name ?? t`Board`
#. placeholder {1}: workspace.name ?? t`Workspace` #. placeholder {1}: workspace.name ?? t`Workspace`
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:443 #: src/views/board/components/NewCardForm.tsx:452
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} etichette" msgstr "{0} etichette"
#. placeholder {0}: isTemplate ? "Template" : "Board" #. placeholder {0}: isTemplate ? "Template" : "Board"
#: src/views/board/index.tsx:400 #: src/views/board/index.tsx:408
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} non trovato" msgstr "{0} non trovato"
@@ -83,8 +83,8 @@ msgstr "Account eliminato"
msgid "Actions" msgid "Actions"
msgstr "Azioni" msgstr "Azioni"
#: src/views/card/index.tsx:343 #: src/views/card/index.tsx:386
#: src/views/public/board/CardModal.tsx:157 #: src/views/public/board/CardModal.tsx:158
msgid "Activity" msgid "Activity"
msgstr "Attività" msgstr "Attività"
@@ -100,12 +100,12 @@ msgstr "Registri attività"
msgid "Add a card" msgid "Add a card"
msgstr "Aggiungi una carta" msgstr "Aggiungi una carta"
#: src/views/card/components/Comment.tsx:146 #: src/views/card/components/Comment.tsx:147
#: src/views/card/components/NewCommentForm.tsx:57 #: src/views/card/components/NewCommentForm.tsx:55
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Aggiungi un commento..." msgstr "Aggiungi un commento..."
#: src/views/card/components/NewChecklistItemForm.tsx:140 #: src/views/card/components/NewChecklistItemForm.tsx:141
msgid "Add an item..." msgid "Add an item..."
msgstr "Aggiungi un elemento..." msgstr "Aggiungi un elemento..."
@@ -117,48 +117,53 @@ msgstr "Aggiungi checklist"
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Aggiungi descrizione... (digita '/' per aprire i comandi o '@' per menzionare)" msgstr "Aggiungi descrizione... (digita '/' per aprire i comandi o '@' per menzionare)"
#: src/views/card/components/ChecklistItemRow.tsx:172 #: src/views/card/components/ChecklistItemRow.tsx:195
msgid "Add details..." msgid "Add details..."
msgstr "Aggiungi dettagli..." msgstr "Aggiungi dettagli..."
#: src/views/card/components/LabelSelector.tsx:109 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:114 #: src/views/card/components/LabelSelector.tsx:115
msgid "Add label" msgid "Add label"
msgstr "Aggiungi etichetta" msgstr "Aggiungi etichetta"
#: src/views/card/components/MemberSelector.tsx:130 #: src/views/card/components/MemberSelector.tsx:131
#: src/views/members/components/InviteMemberForm.tsx:257 #: src/views/members/components/InviteMemberForm.tsx:257
msgid "Add member" msgid "Add member"
msgstr "Aggiungi membro" msgstr "Aggiungi membro"
#: src/views/card/components/ActivityList.tsx:69 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:77
msgid "added {0} labels: <0>{labelList}</0>"
msgstr "ha aggiunto {0} etichette: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:107
msgid "added a checklist" msgid "added a checklist"
msgstr "ha aggiunto una checklist" msgstr "ha aggiunto una checklist"
#: src/views/card/components/ActivityList.tsx:72 #: src/views/card/components/ActivityList.tsx:110
msgid "added a checklist item" msgid "added a checklist item"
msgstr "ha aggiunto un elemento alla checklist" msgstr "ha aggiunto un elemento alla checklist"
#: src/views/card/components/ActivityList.tsx:65 #: src/views/card/components/ActivityList.tsx:103
msgid "added a label to the card" msgid "added a label to the card"
msgstr "ha aggiunto un'etichetta alla carta" msgstr "ha aggiunto un'etichetta alla carta"
#: src/views/card/components/ActivityList.tsx:67 #: src/views/card/components/ActivityList.tsx:105
msgid "added a member to the card" msgid "added a member to the card"
msgstr "ha aggiunto un membro alla carta" msgstr "ha aggiunto un membro alla carta"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146 #: src/views/card/components/ActivityList.tsx:181
msgid "added checklist <0>{0}</0>" msgid "added checklist <0>{0}</0>"
msgstr "ha aggiunto la checklist <0>{0}</0>" msgstr "ha aggiunto la checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170 #: src/views/card/components/ActivityList.tsx:205
msgid "added checklist item <0>{0}</0>" msgid "added checklist item <0>{0}</0>"
msgstr "ha aggiunto l'elemento <0>{0}</0> alla checklist" msgstr "ha aggiunto l'elemento <0>{0}</0> alla checklist"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130 #: src/views/card/components/ActivityList.tsx:165
msgid "added label <0>{0}</0>" msgid "added label <0>{0}</0>"
msgstr "ha aggiunto l'etichetta <0>{0}</0>" msgstr "ha aggiunto l'etichetta <0>{0}</0>"
@@ -249,11 +254,11 @@ msgstr "Sei sicuro di voler eliminare questo {0}?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Sei sicuro di voler eliminare questa carta?" msgstr "Sei sicuro di voler eliminare questa carta?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55 #: src/views/card/components/DeleteChecklistConfirmation.tsx:56
msgid "Are you sure you want to delete this checklist?" msgid "Are you sure you want to delete this checklist?"
msgstr "Sei sicuro di voler eliminare questa checklist?" msgstr "Sei sicuro di voler eliminare questa checklist?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:66
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Sei sicuro di voler eliminare questo commento?" msgstr "Sei sicuro di voler eliminare questo commento?"
@@ -266,7 +271,7 @@ msgid "Are you sure you want to delete your account?"
msgstr "Sei sicuro di voler eliminare il tuo account?" msgstr "Sei sicuro di voler eliminare il tuo account?"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:145
msgid "assigned <0>{0}</0> to the card" msgid "assigned <0>{0}</0> to the card"
msgstr "ha assegnato <0>{0}</0> alla scheda" msgstr "ha assegnato <0>{0}</0> alla scheda"
@@ -274,7 +279,7 @@ msgstr "ha assegnato <0>{0}</0> alla scheda"
msgid "Assignees" msgid "Assignees"
msgstr "Assegnatari" msgstr "Assegnatari"
#: src/views/card/components/AttachmentUpload.tsx:25 #: src/views/card/components/AttachmentUpload.tsx:26
msgid "Attachment uploaded" msgid "Attachment uploaded"
msgstr "Allegato caricato" msgstr "Allegato caricato"
@@ -312,9 +317,9 @@ msgstr "Portale di fatturazione"
msgid "Blog Post" msgid "Blog Post"
msgstr "Post del blog" msgstr "Post del blog"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
msgid "Board" msgid "Board"
msgstr "Bacheca" msgstr "Bacheca"
@@ -331,7 +336,7 @@ msgstr "Il nome della bacheca non può superare i 100 caratteri"
msgid "Board name is required" msgid "Board name is required"
msgstr "Il nome della bacheca è obbligatorio" msgstr "Il nome della bacheca è obbligatorio"
#: src/views/public/board/index.tsx:153 #: src/views/public/board/index.tsx:166
msgid "Board not found" msgid "Board not found"
msgstr "Bacheca non trovata" msgstr "Bacheca non trovata"
@@ -347,7 +352,7 @@ msgstr "L'URL della bacheca può contenere solo lettere, numeri e trattini"
msgid "Board URL cannot exceed 60 characters" msgid "Board URL cannot exceed 60 characters"
msgstr "L'URL della bacheca non può superare i 60 caratteri" msgstr "L'URL della bacheca non può superare i 60 caratteri"
#: src/views/public/board/index.tsx:68 #: src/views/public/board/index.tsx:80
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "URL della bacheca copiato negli appunti" msgstr "URL della bacheca copiato negli appunti"
@@ -382,10 +387,10 @@ msgstr "Segnalazione bug"
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:49
#: src/views/board/components/DeleteBoardConfirmation.tsx:44 #: src/views/board/components/DeleteBoardConfirmation.tsx:44
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:159
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63 #: src/views/card/components/DeleteChecklistConfirmation.tsx:64
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:77
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/settings/components/Avatar.tsx:306 #: src/views/settings/components/Avatar.tsx:306
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168 #: src/views/settings/components/ChangePasswordConfirmation.tsx:168
@@ -395,16 +400,16 @@ msgstr "Segnalazione bug"
msgid "Cancel" msgid "Cancel"
msgstr "Annulla" msgstr "Annulla"
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "Card" msgid "Card"
msgstr "Carta" msgstr "Carta"
#: src/views/card/index.tsx:263 #: src/views/card/index.tsx:306
#: src/views/card/index.tsx:299 #: src/views/card/index.tsx:342
msgid "Card not found" msgid "Card not found"
msgstr "Carta non trovata" msgstr "Carta non trovata"
#: src/views/board/components/NewCardForm.tsx:310 #: src/views/board/components/NewCardForm.tsx:319
msgid "Card title" msgid "Card title"
msgstr "Titolo della carta" msgstr "Titolo della carta"
@@ -419,6 +424,11 @@ msgstr "Cambia password"
msgid "Change your language preferences." msgid "Change your language preferences."
msgstr "Modifica le tue preferenze di lingua." msgstr "Modifica le tue preferenze di lingua."
#: src/views/card/components/ActivityList.tsx:255
#: src/views/card/components/ActivityList.tsx:269
msgid "changed the due date to <0>{formattedDate}</0>"
msgstr "ha cambiato la data di scadenza a <0>{formattedDate}</0>"
#: src/views/oss-friends/index.tsx:61 #: src/views/oss-friends/index.tsx:61
msgid "Check out some of our favorite open source projects." msgid "Check out some of our favorite open source projects."
msgstr "Dai un'occhiata ad alcuni dei nostri progetti open source preferiti." msgstr "Dai un'occhiata ad alcuni dei nostri progetti open source preferiti."
@@ -428,7 +438,7 @@ msgstr "Dai un'occhiata ad alcuni dei nostri progetti open source preferiti."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Controlla la tua casella di posta" msgstr "Controlla la tua casella di posta"
#: src/views/card/components/NewChecklistForm.tsx:118 #: src/views/card/components/NewChecklistForm.tsx:119
msgid "Checklist name" msgid "Checklist name"
msgstr "Nome della checklist" msgstr "Nome della checklist"
@@ -437,7 +447,7 @@ msgstr "Nome della checklist"
msgid "Checklists" msgid "Checklists"
msgstr "Checklist" msgstr "Checklist"
#: src/views/board/components/Filters.tsx:180 #: src/views/board/components/Filters.tsx:227
msgid "Clear filters" msgid "Clear filters"
msgstr "Cancella filtri" msgstr "Cancella filtri"
@@ -489,15 +499,19 @@ msgstr "Completato"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Controllo e proprietà completi:" msgstr "Controllo e proprietà completi:"
#: src/views/card/components/ActivityList.tsx:74 #: src/views/card/components/ActivityList.tsx:112
msgid "completed a checklist item" msgid "completed a checklist item"
msgstr "ha completato un elemento della checklist" msgstr "ha completato un elemento della checklist"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187 #: src/views/card/components/ActivityList.tsx:222
msgid "completed checklist item <0>{0}</0>" msgid "completed checklist item <0>{0}</0>"
msgstr "ha completato l'elemento <0>{0}</0> della checklist" 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 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password" msgid "Confirm your new password"
msgstr "Conferma la tua nuova password" msgstr "Conferma la tua nuova password"
@@ -551,7 +565,7 @@ msgid "Create {0}"
msgstr "Crea {0}" msgstr "Crea {0}"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:469 #: src/views/board/components/NewCardForm.tsx:516
#: src/views/board/components/NewListForm.tsx:141 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Crea un altro" msgstr "Crea un altro"
@@ -560,11 +574,11 @@ msgstr "Crea un altro"
msgid "Create API key" msgid "Create API key"
msgstr "Crea chiave API" msgstr "Crea chiave API"
#: src/views/board/components/NewCardForm.tsx:479 #: src/views/board/components/NewCardForm.tsx:526
msgid "Create card" msgid "Create card"
msgstr "Crea carta" msgstr "Crea carta"
#: src/views/card/components/NewChecklistForm.tsx:134 #: src/views/card/components/NewChecklistForm.tsx:135
msgid "Create checklist" msgid "Create checklist"
msgstr "Crea checklist" msgstr "Crea checklist"
@@ -590,13 +604,13 @@ msgstr "Crea nuovo {0}"
msgid "Create new key" msgid "Create new key"
msgstr "Crea nuova chiave" msgstr "Crea nuova chiave"
#: src/views/board/components/NewCardForm.tsx:405 #: src/views/board/components/NewCardForm.tsx:414
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:98
msgid "Create new label" msgid "Create new label"
msgstr "Crea nuova etichetta" msgstr "Crea nuova etichetta"
#: src/views/board/index.tsx:64 #: src/views/board/index.tsx:64
#: src/views/board/index.tsx:491 #: src/views/board/index.tsx:499
msgid "Create new list" msgid "Create new list"
msgstr "Crea nuova lista" msgstr "Crea nuova lista"
@@ -609,7 +623,7 @@ msgstr "Crea template"
msgid "Create workspace" msgid "Create workspace"
msgstr "Crea spazio di lavoro" msgstr "Crea spazio di lavoro"
#: src/views/card/components/ActivityList.tsx:61 #: src/views/card/components/ActivityList.tsx:99
msgid "created the card" msgid "created the card"
msgstr "ha creato la carta" msgstr "ha creato la carta"
@@ -667,8 +681,8 @@ msgstr "Disattiva link di invito"
#: src/components/LabelForm.tsx:228 #: src/components/LabelForm.tsx:228
#: src/views/board/components/DeleteBoardConfirmation.tsx:47 #: src/views/board/components/DeleteBoardConfirmation.tsx:47
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66 #: src/views/card/components/DeleteChecklistConfirmation.tsx:67
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:83
msgid "Delete" msgid "Delete"
msgstr "Elimina" msgstr "Elimina"
@@ -686,7 +700,7 @@ msgstr "Elimina bacheca"
msgid "Delete card" msgid "Delete card"
msgstr "Elimina carta" msgstr "Elimina carta"
#: src/views/card/components/Comment.tsx:91 #: src/views/card/components/Comment.tsx:92
msgid "Delete comment" msgid "Delete comment"
msgstr "Elimina commento" msgstr "Elimina commento"
@@ -704,21 +718,21 @@ msgstr "Elimina template"
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Elimina spazio di lavoro" msgstr "Elimina spazio di lavoro"
#: src/views/card/components/ActivityList.tsx:71 #: src/views/card/components/ActivityList.tsx:109
msgid "deleted a checklist" msgid "deleted a checklist"
msgstr "ha eliminato una checklist" msgstr "ha eliminato una checklist"
#: src/views/card/components/ActivityList.tsx:76 #: src/views/card/components/ActivityList.tsx:114
msgid "deleted a checklist item" msgid "deleted a checklist item"
msgstr "ha eliminato un elemento della checklist" msgstr "ha eliminato un elemento della checklist"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162 #: src/views/card/components/ActivityList.tsx:197
msgid "deleted checklist <0>{0}</0>" msgid "deleted checklist <0>{0}</0>"
msgstr "ha eliminato la checklist <0>{0}</0>" msgstr "ha eliminato la checklist <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205 #: src/views/card/components/ActivityList.tsx:240
msgid "deleted checklist item <0>{0}</0>" msgid "deleted checklist item <0>{0}</0>"
msgstr "ha eliminato l'elemento <0>{0}</0> della checklist" msgstr "ha eliminato l'elemento <0>{0}</0> della checklist"
@@ -754,6 +768,10 @@ msgstr "Nome visualizzato aggiornato"
msgid "Do you offer a free plan?" msgid "Do you offer a free plan?"
msgstr "Offrite un piano gratuito?" 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 #: src/components/FeedbackModal.tsx:109
msgid "docs" msgid "docs"
msgstr "documenti" msgstr "documenti"
@@ -780,16 +798,38 @@ msgstr "Non hai un account? <0><1>Registrati</1></0>"
msgid "Done" msgid "Done"
msgstr "Fatto" msgstr "Fatto"
#: src/views/card/components/AttachmentThumbnails.tsx:141 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "Download failed" msgid "Download failed"
msgstr "Download fallito" msgstr "Download fallito"
#: src/views/board/components/Filters.tsx:171
#: src/views/board/components/NewCardForm.tsx:469
#: src/views/card/index.tsx:139
msgid "Due date"
msgstr "Data di scadenza"
#: src/views/board/components/Filters.tsx:132
msgid "Due next month"
msgstr "Scade il mese prossimo"
#: src/views/board/components/Filters.tsx:127
msgid "Due next week"
msgstr "Scade la prossima settimana"
#: src/views/board/components/Filters.tsx:117
msgid "Due today"
msgstr "Scade oggi"
#: src/views/board/components/Filters.tsx:122
msgid "Due tomorrow"
msgstr "Scade domani"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:116 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Modifica URL della bacheca" msgstr "Modifica URL della bacheca"
#: src/views/card/components/Comment.tsx:82 #: src/views/card/components/Comment.tsx:83
msgid "Edit comment" msgid "Edit comment"
msgstr "Modifica commento" msgstr "Modifica commento"
@@ -946,8 +986,8 @@ msgstr "Impossibile creare la bacheca"
msgid "Failed to login with {0}. Please try again." msgid "Failed to login with {0}. Please try again."
msgstr "Accesso con {0} fallito. Riprova." msgstr "Accesso con {0} fallito. Riprova."
#: src/views/card/components/AttachmentUpload.tsx:33 #: src/views/card/components/AttachmentUpload.tsx:34
#: src/views/card/components/AttachmentUpload.tsx:79 #: src/views/card/components/AttachmentUpload.tsx:80
msgid "Failed to upload attachment. Please try again." msgid "Failed to upload attachment. Please try again."
msgstr "Impossibile caricare l'allegato. Riprova." msgstr "Impossibile caricare l'allegato. Riprova."
@@ -994,7 +1034,7 @@ msgstr "Feedback"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Feedback inviato" msgstr "Feedback inviato"
#: src/views/board/components/Filters.tsx:174 #: src/views/board/components/Filters.tsx:221
msgid "Filter" msgid "Filter"
msgstr "Filtra" msgstr "Filtra"
@@ -1052,7 +1092,7 @@ msgstr "Inizia ora"
msgid "Get started by creating a new {0}" msgid "Get started by creating a new {0}"
msgstr "Inizia creando un nuovo {0}" msgstr "Inizia creando un nuovo {0}"
#: src/views/board/index.tsx:483 #: src/views/board/index.tsx:491
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Inizia creando una nuova lista" msgstr "Inizia creando una nuova lista"
@@ -1239,7 +1279,7 @@ msgstr "Link di invito"
msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace."
msgstr "I link di invito richiedono un abbonamento Team o Pro. Per favore aggiorna il tuo spazio di lavoro." msgstr "I link di invito richiedono un abbonamento Team o Pro. Per favore aggiorna il tuo spazio di lavoro."
#: src/views/card/components/MemberSelector.tsx:111 #: src/views/card/components/MemberSelector.tsx:112
#: src/views/members/components/InviteMemberForm.tsx:367 #: src/views/members/components/InviteMemberForm.tsx:367
msgid "Invite member" msgid "Invite member"
msgstr "Invita membro" msgstr "Invita membro"
@@ -1286,9 +1326,9 @@ msgstr "Tieni presente che questa azione è irreversibile."
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "Scorciatoie da tastiera" msgstr "Scorciatoie da tastiera"
#: src/views/board/components/Filters.tsx:115 #: src/views/board/components/Filters.tsx:155
#: src/views/board/components/NewCardForm.tsx:409 #: src/views/board/components/NewCardForm.tsx:418
#: src/views/card/index.tsx:119 #: src/views/card/index.tsx:121
msgid "Labels" msgid "Labels"
msgstr "Etichette" msgstr "Etichette"
@@ -1338,11 +1378,11 @@ msgstr "Licenza"
msgid "Light" msgid "Light"
msgstr "Chiaro" msgstr "Chiaro"
#: src/views/public/board/index.tsx:66 #: src/views/public/board/index.tsx:78
msgid "Link copied" msgid "Link copied"
msgstr "Link copiato" msgstr "Link copiato"
#: src/views/card/index.tsx:111 #: src/views/card/index.tsx:113
msgid "List" msgid "List"
msgstr "Lista" msgstr "Lista"
@@ -1350,10 +1390,18 @@ msgstr "Lista"
msgid "List name" msgid "List name"
msgstr "Nome lista" msgstr "Nome lista"
#: src/views/board/components/Filters.tsx:123 #: src/views/board/components/Filters.tsx:163
msgid "Lists" msgid "Lists"
msgstr "Liste" msgstr "Liste"
#: src/views/card/components/ActivityList.tsx:530
msgid "Load more activities"
msgstr "Carica altre attività"
#: src/views/card/components/ActivityList.tsx:530
msgid "Loading..."
msgstr "Caricamento in corso..."
#: src/views/auth/login/index.tsx:33 #: src/views/auth/login/index.tsx:33
msgid "Login | kan.bn" msgid "Login | kan.bn"
msgstr "Login | kan.bn" msgstr "Login | kan.bn"
@@ -1382,12 +1430,12 @@ msgstr "link magico"
msgid "Make template" msgid "Make template"
msgstr "Crea template" msgstr "Crea template"
#: src/views/card/components/ActivityList.tsx:75 #: src/views/card/components/ActivityList.tsx:113
msgid "marked a checklist item as incomplete" msgid "marked a checklist item as incomplete"
msgstr "ha segnato un elemento della checklist come incompleto" msgstr "ha segnato un elemento della checklist come incompleto"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196 #: src/views/card/components/ActivityList.tsx:231
msgid "marked checklist item <0>{0}</0> as incomplete" msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "ha segnato l'elemento <0>{0}</0> della checklist come incompleto" msgstr "ha segnato l'elemento <0>{0}</0> della checklist come incompleto"
@@ -1396,9 +1444,9 @@ msgid "Medium Priority"
msgstr "Media priorità" msgstr "Media priorità"
#: src/components/SideNavigation.tsx:121 #: src/components/SideNavigation.tsx:121
#: src/views/board/components/Filters.tsx:107 #: src/views/board/components/Filters.tsx:147
#: src/views/board/components/NewCardForm.tsx:367 #: src/views/board/components/NewCardForm.tsx:376
#: src/views/card/index.tsx:128 #: src/views/card/index.tsx:130
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Membri" msgstr "Membri"
@@ -1419,11 +1467,11 @@ msgstr "fatturazione mensile"
#. placeholder {0}: truncate(fromList) #. placeholder {0}: truncate(fromList)
#. placeholder {1}: truncate(toList) #. placeholder {1}: truncate(toList)
#: src/views/card/components/ActivityList.tsx:98 #: src/views/card/components/ActivityList.tsx:133
msgid "moved the card from <0>{0}</0> to<1>{1}</1>" msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "ha spostato la scheda da <0>{0}</0> a<1>{1}</1>" msgstr "ha spostato la scheda da <0>{0}</0> a<1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:64 #: src/views/card/components/ActivityList.tsx:102
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "ha spostato la scheda in un'altra lista" msgstr "ha spostato la scheda in un'altra lista"
@@ -1455,11 +1503,11 @@ msgstr "Nuovo {0}"
msgid "New API key" msgid "New API key"
msgstr "Nuova chiave API" msgstr "Nuova chiave API"
#: src/views/board/components/NewCardForm.tsx:293 #: src/views/board/components/NewCardForm.tsx:302
msgid "New card" msgid "New card"
msgstr "Nuova carta" msgstr "Nuova carta"
#: src/views/card/components/NewChecklistForm.tsx:102 #: src/views/card/components/NewChecklistForm.tsx:103
msgid "New checklist" msgid "New checklist"
msgstr "Nuova checklist" msgstr "Nuova checklist"
@@ -1472,7 +1520,7 @@ msgid "New label"
msgstr "Nuova etichetta" msgstr "Nuova etichetta"
#: src/views/board/components/NewListForm.tsx:113 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:454 #: src/views/board/index.tsx:462
msgid "New list" msgid "New list"
msgstr "Nuova lista" msgstr "Nuova lista"
@@ -1521,7 +1569,11 @@ msgstr "Nessuna bacheca trovata"
msgid "No credit card required" msgid "No credit card required"
msgstr "Nessuna carta di credito richiesta" msgstr "Nessuna carta di credito richiesta"
#: src/views/card/components/AttachmentThumbnails.tsx:142 #: src/views/board/components/Filters.tsx:137
msgid "No dates"
msgstr "Nessuna data"
#: src/views/card/components/AttachmentThumbnails.tsx:143
msgid "No download URL available for this attachment." msgid "No download URL available for this attachment."
msgstr "Nessun URL di download disponibile per questo allegato." msgstr "Nessun URL di download disponibile per questo allegato."
@@ -1529,7 +1581,7 @@ msgstr "Nessun URL di download disponibile per questo allegato."
msgid "No keyboard shortcuts registered." msgid "No keyboard shortcuts registered."
msgstr "Nessuna scorciatoia da tastiera registrata." msgstr "Nessuna scorciatoia da tastiera registrata."
#: src/views/board/index.tsx:480 #: src/views/board/index.tsx:488
msgid "No lists" msgid "No lists"
msgstr "Nessuna lista" msgstr "Nessuna lista"
@@ -1582,6 +1634,10 @@ msgstr "Organizza e trova le schede rapidamente con potenti strumenti di filtrag
msgid "OSS Friends" msgid "OSS Friends"
msgstr "Amici OSS" msgstr "Amici OSS"
#: src/views/board/components/Filters.tsx:112
msgid "Overdue"
msgstr "In ritardo"
#: src/views/pricing/components/Pricing.tsx:73 #: src/views/pricing/components/Pricing.tsx:73
#: src/views/pricing/components/PricingTiers.tsx:70 #: src/views/pricing/components/PricingTiers.tsx:70
msgid "Own your data" msgid "Own your data"
@@ -1670,30 +1726,33 @@ msgstr "Seleziona un file da caricare."
#: src/components/DeleteLabelConfirmation.tsx:26 #: src/components/DeleteLabelConfirmation.tsx:26
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/NewWorkspaceForm.tsx:158 #: src/components/NewWorkspaceForm.tsx:158
#: src/views/board/components/NewCardForm.tsx:177 #: src/views/board/components/NewCardForm.tsx:184
#: src/views/board/components/NewListForm.tsx:79 #: src/views/board/components/NewListForm.tsx:79
#: src/views/board/components/NewTemplateForm.tsx:61 #: src/views/board/components/NewTemplateForm.tsx:61
#: src/views/board/components/NewTemplateForm.tsx:77 #: src/views/board/components/NewTemplateForm.tsx:77
#: src/views/board/components/UpdateBoardSlugForm.tsx:73 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:54 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:162 #: src/views/board/index.tsx:170
#: src/views/board/index.tsx:218 #: src/views/board/index.tsx:226
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/card/components/AttachmentThumbnails.tsx:73 #: src/views/card/components/AttachmentThumbnails.tsx:74
#: src/views/card/components/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:67
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:95
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:47
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Checklists.tsx:81
#: src/views/card/components/Comment.tsx:65
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37 #: src/views/card/components/DeleteChecklistConfirmation.tsx:38
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:46
#: src/views/card/components/LabelSelector.tsx:72 #: src/views/card/components/DueDateSelector.tsx:60
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/MemberSelector.tsx:79 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistForm.tsx:71
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewChecklistItemForm.tsx:90
#: src/views/card/index.tsx:177 #: src/views/card/components/NewCommentForm.tsx:32
#: src/views/card/index.tsx:187
#: src/views/card/index.tsx:200
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/members/components/InviteMemberForm.tsx:104 #: src/views/members/components/InviteMemberForm.tsx:104
#: src/views/members/components/InviteMemberForm.tsx:241 #: src/views/members/components/InviteMemberForm.tsx:241
@@ -1793,30 +1852,40 @@ msgstr "Rimuovi"
msgid "Remove member" msgid "Remove member"
msgstr "Rimuovi membro" msgstr "Rimuovi membro"
#: src/views/card/components/ActivityList.tsx:66 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:91
msgid "removed {0} labels: <0>{labelList}</0>"
msgstr "ha rimosso {0} etichette: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:104
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "ha rimosso un'etichetta dalla scheda" msgstr "ha rimosso un'etichetta dalla scheda"
#: src/views/card/components/ActivityList.tsx:68 #: src/views/card/components/ActivityList.tsx:106
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "ha rimosso un membro dalla scheda" msgstr "ha rimosso un membro dalla scheda"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138 #: src/views/card/components/ActivityList.tsx:173
msgid "removed label <0>{0}</0>" msgid "removed label <0>{0}</0>"
msgstr "ha rimosso l'etichetta <0>{0}</0>" msgstr "ha rimosso l'etichetta <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:70 #: src/views/card/components/ActivityList.tsx:117
#: src/views/card/components/ActivityList.tsx:276
msgid "removed the due date"
msgstr "ha rimosso la data di scadenza"
#: src/views/card/components/ActivityList.tsx:108
msgid "renamed a checklist" msgid "renamed a checklist"
msgstr "ha rinominato una checklist" msgstr "ha rinominato una checklist"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154 #: src/views/card/components/ActivityList.tsx:189
msgid "renamed checklist <0>{0}</0>" msgid "renamed checklist <0>{0}</0>"
msgstr "ha rinominato la checklist <0>{0}</0>" msgstr "ha rinominato la checklist <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178 #: src/views/card/components/ActivityList.tsx:213
msgid "renamed checklist item to <0>{0}</0>" msgid "renamed checklist item to <0>{0}</0>"
msgstr "ha rinominato l'elemento della checklist in <0>{0}</0>" msgstr "ha rinominato l'elemento della checklist in <0>{0}</0>"
@@ -1855,7 +1924,7 @@ msgstr "Ruolo"
msgid "Run on your own infrastructure" msgid "Run on your own infrastructure"
msgstr "Esegui sulla tua infrastruttura" msgstr "Esegui sulla tua infrastruttura"
#: src/views/card/components/Comment.tsx:165 #: src/views/card/components/Comment.tsx:166
#: src/views/settings/components/Avatar.tsx:309 #: src/views/settings/components/Avatar.tsx:309
msgid "Save" msgid "Save"
msgstr "Salva" msgstr "Salva"
@@ -1893,7 +1962,7 @@ msgstr "Self Host"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Self host con Github" msgstr "Self host con Github"
#: src/views/card/components/ActivityList.tsx:107 #: src/views/card/components/ActivityList.tsx:142
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "si è auto-assegnato la scheda" msgstr "si è auto-assegnato la scheda"
@@ -1909,6 +1978,14 @@ msgstr "Invia feedback"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/card/components/DueDateSelector.tsx:117
msgid "Set due date"
msgstr "Imposta data di scadenza"
#: src/views/card/components/ActivityList.tsx:115
msgid "set the due date"
msgstr "ha impostato la data di scadenza"
#: src/components/SettingsLayout.tsx:82 #: src/components/SettingsLayout.tsx:82
#: src/components/SideNavigation.tsx:133 #: src/components/SideNavigation.tsx:133
msgid "Settings" msgid "Settings"
@@ -2030,8 +2107,8 @@ msgstr "Piano Team"
msgid "Teams" msgid "Teams"
msgstr "Team" msgstr "Team"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/board/index.tsx:409 #: src/views/board/index.tsx:417
msgid "Template" msgid "Template"
msgstr "Template" msgstr "Template"
@@ -2096,8 +2173,8 @@ msgstr "Non potranno accedere a questo spazio di lavoro."
#: src/components/DeleteLabelConfirmation.tsx:44 #: src/components/DeleteLabelConfirmation.tsx:44
#: src/views/board/components/DeleteBoardConfirmation.tsx:39 #: src/views/board/components/DeleteBoardConfirmation.tsx:39
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58 #: src/views/card/components/DeleteChecklistConfirmation.tsx:59
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:69
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Questa azione non può essere annullata." msgstr "Questa azione non può essere annullata."
@@ -2105,7 +2182,7 @@ msgstr "Questa azione non può essere annullata."
msgid "This API key will only be shown once. Please save it in a secure location." msgid "This API key will only be shown once. Please save it in a secure location."
msgstr "Questa chiave API verrà mostrata una sola volta. Salvala in un luogo sicuro." msgstr "Questa chiave API verrà mostrata una sola volta. Salvala in un luogo sicuro."
#: src/views/public/board/index.tsx:156 #: src/views/public/board/index.tsx:169
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "Questa bacheca è privata o non esiste" msgstr "Questa bacheca è privata o non esiste"
@@ -2167,23 +2244,27 @@ msgstr "Importazioni da Trello"
msgid "Triaging" msgid "Triaging"
msgstr "Smistamento" msgstr "Smistamento"
#: src/views/home/components/Logos.tsx:73 #: src/views/home/components/Logos.tsx:67
msgid "Trusted by fast-moving teams<0/>around the world" msgid "Trusted by fast-moving teams<0/>around the world"
msgstr "Team dinamici di tutto il mondo<0/>si fidano di noi" msgstr "Team dinamici di tutto il mondo<0/>si fidano di noi"
#: src/views/card/components/NewChecklistItemForm.tsx:88 #: src/views/card/components/NewChecklistItemForm.tsx:89
msgid "Unable to add checklist item" msgid "Unable to add checklist item"
msgstr "Impossibile aggiungere l'elemento della checklist" msgstr "Impossibile aggiungere l'elemento della checklist"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:31
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Impossibile aggiungere il commento" msgstr "Impossibile aggiungere il commento"
#: src/views/board/components/NewCardForm.tsx:174 #: src/views/card/index.tsx:199
msgid "Unable to add label"
msgstr "Impossibile aggiungere etichetta"
#: src/views/board/components/NewCardForm.tsx:181
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Impossibile creare la scheda" msgstr "Impossibile creare la scheda"
#: src/views/card/components/NewChecklistForm.tsx:69 #: src/views/card/components/NewChecklistForm.tsx:70
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Impossibile creare la checklist" msgstr "Impossibile creare la checklist"
@@ -2200,7 +2281,7 @@ msgstr "Impossibile creare il template"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "Impossibile creare lo spazio di lavoro" msgstr "Impossibile creare lo spazio di lavoro"
#: src/views/card/components/AttachmentThumbnails.tsx:72 #: src/views/card/components/AttachmentThumbnails.tsx:73
msgid "Unable to delete attachment" msgid "Unable to delete attachment"
msgstr "Impossibile eliminare l'allegato" msgstr "Impossibile eliminare l'allegato"
@@ -2208,15 +2289,15 @@ msgstr "Impossibile eliminare l'allegato"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Impossibile eliminare la scheda" msgstr "Impossibile eliminare la scheda"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36 #: src/views/card/components/DeleteChecklistConfirmation.tsx:37
msgid "Unable to delete checklist" msgid "Unable to delete checklist"
msgstr "Impossibile eliminare la checklist" msgstr "Impossibile eliminare la checklist"
#: src/views/card/components/ChecklistItemRow.tsx:87 #: src/views/card/components/ChecklistItemRow.tsx:94
msgid "Unable to delete checklist item" msgid "Unable to delete checklist item"
msgstr "Impossibile eliminare l'elemento della checklist" msgstr "Impossibile eliminare l'elemento della checklist"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Impossibile eliminare il commento" msgstr "Impossibile eliminare il commento"
@@ -2224,6 +2305,10 @@ msgstr "Impossibile eliminare il commento"
msgid "Unable to remove member" msgid "Unable to remove member"
msgstr "Impossibile rimuovere il membro" msgstr "Impossibile rimuovere il membro"
#: src/views/card/components/Checklists.tsx:80
msgid "Unable to reorder checklist item"
msgstr "Impossibile riordinare elemento della checklist"
#: src/components/FeedbackModal.tsx:40 #: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Impossibile inviare feedback" msgstr "Impossibile inviare feedback"
@@ -2236,42 +2321,46 @@ msgstr "Impossibile aggiornare l'URL della bacheca"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Impossibile aggiornare la visibilità della bacheca" msgstr "Impossibile aggiornare la visibilità della bacheca"
#: src/views/board/index.tsx:217 #: src/views/board/index.tsx:225
#: src/views/card/index.tsx:176 #: src/views/card/index.tsx:186
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Impossibile aggiornare la scheda" msgstr "Impossibile aggiornare la scheda"
#: src/views/card/components/ChecklistNameInput.tsx:45 #: src/views/card/components/ChecklistNameInput.tsx:46
msgid "Unable to update checklist" msgid "Unable to update checklist"
msgstr "Impossibile aggiornare la checklist" msgstr "Impossibile aggiornare la checklist"
#: src/views/card/components/ChecklistItemRow.tsx:59 #: src/views/card/components/ChecklistItemRow.tsx:66
msgid "Unable to update checklist item" msgid "Unable to update checklist item"
msgstr "Impossibile aggiornare l'elemento della checklist" msgstr "Impossibile aggiornare l'elemento della checklist"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:64
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Impossibile aggiornare il commento" msgstr "Impossibile aggiornare il commento"
#: src/views/card/components/LabelSelector.tsx:71 #: src/views/card/components/DueDateSelector.tsx:59
msgid "Unable to update due date"
msgstr "Impossibile aggiornare la data di scadenza"
#: src/views/card/components/LabelSelector.tsx:72
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "Impossibile aggiornare le etichette" msgstr "Impossibile aggiornare le etichette"
#: src/views/board/index.tsx:161 #: src/views/board/index.tsx:169
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:52
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Impossibile aggiornare la lista" msgstr "Impossibile aggiornare la lista"
#: src/views/card/components/MemberSelector.tsx:78 #: src/views/card/components/MemberSelector.tsx:79
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Impossibile aggiornare i membri" msgstr "Impossibile aggiornare i membri"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:121 #: src/views/card/components/ActivityList.tsx:156
msgid "unassigned <0>{0}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "ha rimosso l'assegnazione di <0>{0}</0> dalla scheda" msgstr "ha rimosso l'assegnazione di <0>{0}</0> dalla scheda"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:153
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "si è rimosso dall'assegnazione della scheda" msgstr "si è rimosso dall'assegnazione della scheda"
@@ -2313,6 +2402,11 @@ msgstr "Membri illimitati"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Aree di lavoro illimitate" 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/board/components/UpdateBoardSlugForm.tsx:175
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80 #: src/views/settings/components/UpdateDisplayNameForm.tsx:80
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
@@ -2325,20 +2419,24 @@ msgstr "Aggiorna"
msgid "Update label" msgid "Update label"
msgstr "Aggiorna etichetta" msgstr "Aggiorna etichetta"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:111
msgid "updated a checklist item" msgid "updated a checklist item"
msgstr "ha aggiornato un elemento della checklist" msgstr "ha aggiornato un elemento della checklist"
#: src/views/card/components/ActivityList.tsx:63 #: src/views/card/components/ActivityList.tsx:101
msgid "updated the description" msgid "updated the description"
msgstr "ha aggiornato la descrizione" msgstr "ha aggiornato la descrizione"
#: src/views/card/components/ActivityList.tsx:62 #: src/views/card/components/ActivityList.tsx:116
msgid "updated the due date"
msgstr "ha aggiornato la data di scadenza"
#: src/views/card/components/ActivityList.tsx:100
msgid "updated the title" msgid "updated the title"
msgstr "ha aggiornato il titolo" msgstr "ha aggiornato il titolo"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90 #: src/views/card/components/ActivityList.tsx:125
msgid "updated the title to <0>{0}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "ha aggiornato il titolo in <0>{0}</0>" msgstr "ha aggiornato il titolo in <0>{0}</0>"
@@ -2352,8 +2450,8 @@ msgstr "Passa a Pro"
msgid "Upgrade to Pro ($29/month)" msgid "Upgrade to Pro ($29/month)"
msgstr "Passa a Pro ($29/mese)" msgstr "Passa a Pro ($29/mese)"
#: src/views/card/components/AttachmentUpload.tsx:32 #: src/views/card/components/AttachmentUpload.tsx:33
#: src/views/card/components/AttachmentUpload.tsx:78 #: src/views/card/components/AttachmentUpload.tsx:79
msgid "Upload failed" msgid "Upload failed"
msgstr "Caricamento fallito" msgstr "Caricamento fallito"
@@ -2406,7 +2504,7 @@ msgstr "Visualizza e gestisci la tua fatturazione e abbonamento."
msgid "View docs" msgid "View docs"
msgstr "Visualizza documenti" msgstr "Visualizza documenti"
#: src/views/public/board/index.tsx:129 #: src/views/public/board/index.tsx:142
msgid "View only" msgid "View only"
msgstr "Solo visualizzazione" msgstr "Solo visualizzazione"
@@ -2414,7 +2512,7 @@ msgstr "Solo visualizzazione"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "Visualizza la nostra roadmap." msgstr "Visualizza la nostra roadmap."
#: src/views/public/board/index.tsx:159 #: src/views/public/board/index.tsx:172
msgid "View workspace" msgid "View workspace"
msgstr "Visualizza spazio di lavoro" msgstr "Visualizza spazio di lavoro"
@@ -2426,6 +2524,10 @@ msgstr "Visibilità"
msgid "We are using the <0>AGPL-3.0 license</0>." msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "Utilizziamo la <0>licenza AGPL-3.0</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 #: src/views/home/components/Features.tsx:152
msgid "We're just getting started. " msgid "We're just getting started. "
msgstr "Siamo solo all'inizio. " msgstr "Siamo solo all'inizio. "
@@ -2455,10 +2557,10 @@ msgid "Why make an open source Trello?"
msgstr "Perché creare un Trello open source?" msgstr "Perché creare un Trello open source?"
#: src/components/SettingsLayout.tsx:39 #: src/components/SettingsLayout.tsx:39
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Spazio di lavoro" msgstr "Spazio di lavoro"
@@ -2564,6 +2666,10 @@ msgstr "Hai effettuato l'accesso con successo."
msgid "You have been signed up successfully." msgid "You have been signed up successfully."
msgstr "Ti sei registrato con successo." 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 #: src/views/members/components/InviteMemberForm.tsx:326
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!" 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!" msgstr "Hai posti illimitati con il tuo Piano Pro. Non ci sono costi aggiuntivi per i nuovi membri!"
@@ -2588,7 +2694,7 @@ msgstr "Le tue bacheche sono state importate."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Il tuo nome visualizzato è stato aggiornato." msgstr "Il tuo nome visualizzato è stato aggiornato."
#: src/views/card/components/AttachmentUpload.tsx:26 #: src/views/card/components/AttachmentUpload.tsx:27
msgid "Your file has been uploaded successfully." msgid "Your file has been uploaded successfully."
msgstr "Il tuo file è stato caricato con successo." msgstr "Il tuo file è stato caricato con successo."
@@ -2608,6 +2714,10 @@ msgstr "Il tuo account Trello è stato disconnesso."
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Il tuo account Trello è connesso." 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 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
msgid "Your workspace description has been updated." msgid "Your workspace description has been updated."
msgstr "La descrizione della tua area di lavoro è stata aggiornata." msgstr "La descrizione della tua area di lavoro è stata aggiornata."

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:123 #: src/views/card/components/Comment.tsx:124
msgid " (edited)" msgid " (edited)"
msgstr " (bewerkt)" msgstr " (bewerkt)"
@@ -31,17 +31,17 @@ msgstr "{0}"
#. placeholder {1}: board?.name ?? t`Board` #. placeholder {1}: board?.name ?? t`Board`
#. placeholder {1}: workspace.name ?? t`Workspace` #. placeholder {1}: workspace.name ?? t`Workspace`
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:443 #: src/views/board/components/NewCardForm.tsx:452
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} labels" msgstr "{0} labels"
#. placeholder {0}: isTemplate ? "Template" : "Board" #. placeholder {0}: isTemplate ? "Template" : "Board"
#: src/views/board/index.tsx:400 #: src/views/board/index.tsx:408
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} niet gevonden" msgstr "{0} niet gevonden"
@@ -83,8 +83,8 @@ msgstr "Account verwijderd"
msgid "Actions" msgid "Actions"
msgstr "Acties" msgstr "Acties"
#: src/views/card/index.tsx:343 #: src/views/card/index.tsx:386
#: src/views/public/board/CardModal.tsx:157 #: src/views/public/board/CardModal.tsx:158
msgid "Activity" msgid "Activity"
msgstr "Activiteit" msgstr "Activiteit"
@@ -100,12 +100,12 @@ msgstr "Activiteitenlogboeken"
msgid "Add a card" msgid "Add a card"
msgstr "Voeg een kaart toe" msgstr "Voeg een kaart toe"
#: src/views/card/components/Comment.tsx:146 #: src/views/card/components/Comment.tsx:147
#: src/views/card/components/NewCommentForm.tsx:57 #: src/views/card/components/NewCommentForm.tsx:55
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Voeg een reactie toe..." msgstr "Voeg een reactie toe..."
#: src/views/card/components/NewChecklistItemForm.tsx:140 #: src/views/card/components/NewChecklistItemForm.tsx:141
msgid "Add an item..." msgid "Add an item..."
msgstr "Voeg een item toe..." msgstr "Voeg een item toe..."
@@ -117,48 +117,53 @@ msgstr "Checklist toevoegen"
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Beschrijving toevoegen... (typ '/' om commando's te openen of '@' om te vermelden)" msgstr "Beschrijving toevoegen... (typ '/' om commando's te openen of '@' om te vermelden)"
#: src/views/card/components/ChecklistItemRow.tsx:172 #: src/views/card/components/ChecklistItemRow.tsx:195
msgid "Add details..." msgid "Add details..."
msgstr "Details toevoegen..." msgstr "Details toevoegen..."
#: src/views/card/components/LabelSelector.tsx:109 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:114 #: src/views/card/components/LabelSelector.tsx:115
msgid "Add label" msgid "Add label"
msgstr "Label toevoegen" msgstr "Label toevoegen"
#: src/views/card/components/MemberSelector.tsx:130 #: src/views/card/components/MemberSelector.tsx:131
#: src/views/members/components/InviteMemberForm.tsx:257 #: src/views/members/components/InviteMemberForm.tsx:257
msgid "Add member" msgid "Add member"
msgstr "Lid toevoegen" msgstr "Lid toevoegen"
#: src/views/card/components/ActivityList.tsx:69 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:77
msgid "added {0} labels: <0>{labelList}</0>"
msgstr "{0} labels toegevoegd: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:107
msgid "added a checklist" msgid "added a checklist"
msgstr "heeft een checklist toegevoegd" msgstr "heeft een checklist toegevoegd"
#: src/views/card/components/ActivityList.tsx:72 #: src/views/card/components/ActivityList.tsx:110
msgid "added a checklist item" msgid "added a checklist item"
msgstr "heeft een checklistitem toegevoegd" msgstr "heeft een checklistitem toegevoegd"
#: src/views/card/components/ActivityList.tsx:65 #: src/views/card/components/ActivityList.tsx:103
msgid "added a label to the card" msgid "added a label to the card"
msgstr "heeft een label aan de kaart toegevoegd" msgstr "heeft een label aan de kaart toegevoegd"
#: src/views/card/components/ActivityList.tsx:67 #: src/views/card/components/ActivityList.tsx:105
msgid "added a member to the card" msgid "added a member to the card"
msgstr "heeft een lid aan de kaart toegevoegd" msgstr "heeft een lid aan de kaart toegevoegd"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146 #: src/views/card/components/ActivityList.tsx:181
msgid "added checklist <0>{0}</0>" msgid "added checklist <0>{0}</0>"
msgstr "heeft checklist <0>{0}</0> toegevoegd" msgstr "heeft checklist <0>{0}</0> toegevoegd"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170 #: src/views/card/components/ActivityList.tsx:205
msgid "added checklist item <0>{0}</0>" msgid "added checklist item <0>{0}</0>"
msgstr "heeft checklistitem <0>{0}</0> toegevoegd" msgstr "heeft checklistitem <0>{0}</0> toegevoegd"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130 #: src/views/card/components/ActivityList.tsx:165
msgid "added label <0>{0}</0>" msgid "added label <0>{0}</0>"
msgstr "heeft label <0>{0}</0> toegevoegd" msgstr "heeft label <0>{0}</0> toegevoegd"
@@ -249,11 +254,11 @@ msgstr "Weet je zeker dat je deze {0} wilt verwijderen?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Weet je zeker dat je deze kaart wilt verwijderen?" msgstr "Weet je zeker dat je deze kaart wilt verwijderen?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55 #: src/views/card/components/DeleteChecklistConfirmation.tsx:56
msgid "Are you sure you want to delete this checklist?" msgid "Are you sure you want to delete this checklist?"
msgstr "Weet je zeker dat je deze checklist wilt verwijderen?" msgstr "Weet je zeker dat je deze checklist wilt verwijderen?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:66
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Weet je zeker dat je deze opmerking wilt verwijderen?" msgstr "Weet je zeker dat je deze opmerking wilt verwijderen?"
@@ -266,7 +271,7 @@ msgid "Are you sure you want to delete your account?"
msgstr "Weet je zeker dat je je account wilt verwijderen?" msgstr "Weet je zeker dat je je account wilt verwijderen?"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:145
msgid "assigned <0>{0}</0> to the card" msgid "assigned <0>{0}</0> to the card"
msgstr "heeft <0>{0}</0> aan de kaart toegewezen" msgstr "heeft <0>{0}</0> aan de kaart toegewezen"
@@ -274,7 +279,7 @@ msgstr "heeft <0>{0}</0> aan de kaart toegewezen"
msgid "Assignees" msgid "Assignees"
msgstr "Toegewezen personen" msgstr "Toegewezen personen"
#: src/views/card/components/AttachmentUpload.tsx:25 #: src/views/card/components/AttachmentUpload.tsx:26
msgid "Attachment uploaded" msgid "Attachment uploaded"
msgstr "Bijlage geüpload" msgstr "Bijlage geüpload"
@@ -312,9 +317,9 @@ msgstr "Factureringsportaal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blogbericht" msgstr "Blogbericht"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
msgid "Board" msgid "Board"
msgstr "Bord" msgstr "Bord"
@@ -331,7 +336,7 @@ msgstr "Bordnaam mag niet langer zijn dan 100 tekens"
msgid "Board name is required" msgid "Board name is required"
msgstr "Bordnaam is verplicht" msgstr "Bordnaam is verplicht"
#: src/views/public/board/index.tsx:153 #: src/views/public/board/index.tsx:166
msgid "Board not found" msgid "Board not found"
msgstr "Bord niet gevonden" msgstr "Bord niet gevonden"
@@ -347,7 +352,7 @@ msgstr "Board URL kan alleen letters, cijfers en koppeltekens bevatten"
msgid "Board URL cannot exceed 60 characters" msgid "Board URL cannot exceed 60 characters"
msgstr "Board URL mag niet langer zijn dan 60 tekens" msgstr "Board URL mag niet langer zijn dan 60 tekens"
#: src/views/public/board/index.tsx:68 #: src/views/public/board/index.tsx:80
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "Board URL gekopieerd naar klembord" msgstr "Board URL gekopieerd naar klembord"
@@ -382,10 +387,10 @@ msgstr "Bugrapport"
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:49
#: src/views/board/components/DeleteBoardConfirmation.tsx:44 #: src/views/board/components/DeleteBoardConfirmation.tsx:44
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:159
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63 #: src/views/card/components/DeleteChecklistConfirmation.tsx:64
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:77
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/settings/components/Avatar.tsx:306 #: src/views/settings/components/Avatar.tsx:306
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168 #: src/views/settings/components/ChangePasswordConfirmation.tsx:168
@@ -395,16 +400,16 @@ msgstr "Bugrapport"
msgid "Cancel" msgid "Cancel"
msgstr "Annuleren" msgstr "Annuleren"
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "Card" msgid "Card"
msgstr "Kaart" msgstr "Kaart"
#: src/views/card/index.tsx:263 #: src/views/card/index.tsx:306
#: src/views/card/index.tsx:299 #: src/views/card/index.tsx:342
msgid "Card not found" msgid "Card not found"
msgstr "Kaart niet gevonden" msgstr "Kaart niet gevonden"
#: src/views/board/components/NewCardForm.tsx:310 #: src/views/board/components/NewCardForm.tsx:319
msgid "Card title" msgid "Card title"
msgstr "Kaarttitel" msgstr "Kaarttitel"
@@ -419,6 +424,11 @@ msgstr "Wachtwoord wijzigen"
msgid "Change your language preferences." msgid "Change your language preferences."
msgstr "Wijzig je taalvoorkeuren." msgstr "Wijzig je taalvoorkeuren."
#: src/views/card/components/ActivityList.tsx:255
#: src/views/card/components/ActivityList.tsx:269
msgid "changed the due date to <0>{formattedDate}</0>"
msgstr "heeft de vervaldatum gewijzigd naar <0>{formattedDate}</0>"
#: src/views/oss-friends/index.tsx:61 #: src/views/oss-friends/index.tsx:61
msgid "Check out some of our favorite open source projects." msgid "Check out some of our favorite open source projects."
msgstr "Bekijk enkele van onze favoriete open source projecten." msgstr "Bekijk enkele van onze favoriete open source projecten."
@@ -428,7 +438,7 @@ msgstr "Bekijk enkele van onze favoriete open source projecten."
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Controleer je inbox" msgstr "Controleer je inbox"
#: src/views/card/components/NewChecklistForm.tsx:118 #: src/views/card/components/NewChecklistForm.tsx:119
msgid "Checklist name" msgid "Checklist name"
msgstr "Naam checklist" msgstr "Naam checklist"
@@ -437,7 +447,7 @@ msgstr "Naam checklist"
msgid "Checklists" msgid "Checklists"
msgstr "Checklists" msgstr "Checklists"
#: src/views/board/components/Filters.tsx:180 #: src/views/board/components/Filters.tsx:227
msgid "Clear filters" msgid "Clear filters"
msgstr "Filters wissen" msgstr "Filters wissen"
@@ -489,15 +499,19 @@ msgstr "Voltooid"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Volledige controle en eigendom:" msgstr "Volledige controle en eigendom:"
#: src/views/card/components/ActivityList.tsx:74 #: src/views/card/components/ActivityList.tsx:112
msgid "completed a checklist item" msgid "completed a checklist item"
msgstr "heeft een checklistitem voltooid" msgstr "heeft een checklistitem voltooid"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187 #: src/views/card/components/ActivityList.tsx:222
msgid "completed checklist item <0>{0}</0>" msgid "completed checklist item <0>{0}</0>"
msgstr "heeft checklistitem <0>{0}</0> voltooid" 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 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password" msgid "Confirm your new password"
msgstr "Bevestig je nieuwe wachtwoord" msgstr "Bevestig je nieuwe wachtwoord"
@@ -551,7 +565,7 @@ msgid "Create {0}"
msgstr "{0} maken" msgstr "{0} maken"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:469 #: src/views/board/components/NewCardForm.tsx:516
#: src/views/board/components/NewListForm.tsx:141 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Maak nog een" msgstr "Maak nog een"
@@ -560,11 +574,11 @@ msgstr "Maak nog een"
msgid "Create API key" msgid "Create API key"
msgstr "API-sleutel aanmaken" msgstr "API-sleutel aanmaken"
#: src/views/board/components/NewCardForm.tsx:479 #: src/views/board/components/NewCardForm.tsx:526
msgid "Create card" msgid "Create card"
msgstr "Maak kaart" msgstr "Maak kaart"
#: src/views/card/components/NewChecklistForm.tsx:134 #: src/views/card/components/NewChecklistForm.tsx:135
msgid "Create checklist" msgid "Create checklist"
msgstr "Checklist maken" msgstr "Checklist maken"
@@ -590,13 +604,13 @@ msgstr "Nieuwe {0} maken"
msgid "Create new key" msgid "Create new key"
msgstr "Nieuwe sleutel aanmaken" msgstr "Nieuwe sleutel aanmaken"
#: src/views/board/components/NewCardForm.tsx:405 #: src/views/board/components/NewCardForm.tsx:414
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:98
msgid "Create new label" msgid "Create new label"
msgstr "Maak nieuw label" msgstr "Maak nieuw label"
#: src/views/board/index.tsx:64 #: src/views/board/index.tsx:64
#: src/views/board/index.tsx:491 #: src/views/board/index.tsx:499
msgid "Create new list" msgid "Create new list"
msgstr "Maak nieuwe lijst" msgstr "Maak nieuwe lijst"
@@ -609,7 +623,7 @@ msgstr "Sjabloon maken"
msgid "Create workspace" msgid "Create workspace"
msgstr "Werkruimte maken" msgstr "Werkruimte maken"
#: src/views/card/components/ActivityList.tsx:61 #: src/views/card/components/ActivityList.tsx:99
msgid "created the card" msgid "created the card"
msgstr "heeft de kaart aangemaakt" msgstr "heeft de kaart aangemaakt"
@@ -667,8 +681,8 @@ msgstr "Uitnodigingslink deactiveren"
#: src/components/LabelForm.tsx:228 #: src/components/LabelForm.tsx:228
#: src/views/board/components/DeleteBoardConfirmation.tsx:47 #: src/views/board/components/DeleteBoardConfirmation.tsx:47
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66 #: src/views/card/components/DeleteChecklistConfirmation.tsx:67
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:83
msgid "Delete" msgid "Delete"
msgstr "Verwijderen" msgstr "Verwijderen"
@@ -686,7 +700,7 @@ msgstr "Board verwijderen"
msgid "Delete card" msgid "Delete card"
msgstr "Kaart verwijderen" msgstr "Kaart verwijderen"
#: src/views/card/components/Comment.tsx:91 #: src/views/card/components/Comment.tsx:92
msgid "Delete comment" msgid "Delete comment"
msgstr "Reactie verwijderen" msgstr "Reactie verwijderen"
@@ -704,21 +718,21 @@ msgstr "Sjabloon verwijderen"
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Werkruimte verwijderen" msgstr "Werkruimte verwijderen"
#: src/views/card/components/ActivityList.tsx:71 #: src/views/card/components/ActivityList.tsx:109
msgid "deleted a checklist" msgid "deleted a checklist"
msgstr "heeft een checklist verwijderd" msgstr "heeft een checklist verwijderd"
#: src/views/card/components/ActivityList.tsx:76 #: src/views/card/components/ActivityList.tsx:114
msgid "deleted a checklist item" msgid "deleted a checklist item"
msgstr "heeft een checklistitem verwijderd" msgstr "heeft een checklistitem verwijderd"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162 #: src/views/card/components/ActivityList.tsx:197
msgid "deleted checklist <0>{0}</0>" msgid "deleted checklist <0>{0}</0>"
msgstr "heeft checklist <0>{0}</0> verwijderd" msgstr "heeft checklist <0>{0}</0> verwijderd"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205 #: src/views/card/components/ActivityList.tsx:240
msgid "deleted checklist item <0>{0}</0>" msgid "deleted checklist item <0>{0}</0>"
msgstr "heeft checklistitem <0>{0}</0> verwijderd" msgstr "heeft checklistitem <0>{0}</0> verwijderd"
@@ -754,6 +768,10 @@ msgstr "Weergavenaam bijgewerkt"
msgid "Do you offer a free plan?" msgid "Do you offer a free plan?"
msgstr "Bieden jullie een gratis abonnement aan?" 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 #: src/components/FeedbackModal.tsx:109
msgid "docs" msgid "docs"
msgstr "docs" msgstr "docs"
@@ -780,16 +798,38 @@ msgstr "Heb je geen account? <0><1>Registreer je</1></0>"
msgid "Done" msgid "Done"
msgstr "Klaar" msgstr "Klaar"
#: src/views/card/components/AttachmentThumbnails.tsx:141 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "Download failed" msgid "Download failed"
msgstr "Download mislukt" msgstr "Download mislukt"
#: src/views/board/components/Filters.tsx:171
#: src/views/board/components/NewCardForm.tsx:469
#: src/views/card/index.tsx:139
msgid "Due date"
msgstr "Vervaldatum"
#: src/views/board/components/Filters.tsx:132
msgid "Due next month"
msgstr "Vervalt volgende maand"
#: src/views/board/components/Filters.tsx:127
msgid "Due next week"
msgstr "Vervalt volgende week"
#: src/views/board/components/Filters.tsx:117
msgid "Due today"
msgstr "Vervalt vandaag"
#: src/views/board/components/Filters.tsx:122
msgid "Due tomorrow"
msgstr "Vervalt morgen"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:116 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Board URL bewerken" msgstr "Board URL bewerken"
#: src/views/card/components/Comment.tsx:82 #: src/views/card/components/Comment.tsx:83
msgid "Edit comment" msgid "Edit comment"
msgstr "Reactie bewerken" msgstr "Reactie bewerken"
@@ -946,8 +986,8 @@ msgstr "Bord maken mislukt"
msgid "Failed to login with {0}. Please try again." msgid "Failed to login with {0}. Please try again."
msgstr "Inloggen met {0} is mislukt. Probeer het opnieuw." msgstr "Inloggen met {0} is mislukt. Probeer het opnieuw."
#: src/views/card/components/AttachmentUpload.tsx:33 #: src/views/card/components/AttachmentUpload.tsx:34
#: src/views/card/components/AttachmentUpload.tsx:79 #: src/views/card/components/AttachmentUpload.tsx:80
msgid "Failed to upload attachment. Please try again." msgid "Failed to upload attachment. Please try again."
msgstr "Bijlage uploaden mislukt. Probeer het opnieuw." msgstr "Bijlage uploaden mislukt. Probeer het opnieuw."
@@ -994,7 +1034,7 @@ msgstr "Feedback"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Feedback verzonden" msgstr "Feedback verzonden"
#: src/views/board/components/Filters.tsx:174 #: src/views/board/components/Filters.tsx:221
msgid "Filter" msgid "Filter"
msgstr "Filter" msgstr "Filter"
@@ -1052,7 +1092,7 @@ msgstr "Aan de slag"
msgid "Get started by creating a new {0}" msgid "Get started by creating a new {0}"
msgstr "Begin door een nieuwe {0} te maken" msgstr "Begin door een nieuwe {0} te maken"
#: src/views/board/index.tsx:483 #: src/views/board/index.tsx:491
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Begin door een nieuwe lijst te maken" msgstr "Begin door een nieuwe lijst te maken"
@@ -1239,7 +1279,7 @@ msgstr "Uitnodigingslinks"
msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace."
msgstr "Uitnodigingslinks vereisen een Team- of Pro-abonnement. Upgrade je werkruimte." msgstr "Uitnodigingslinks vereisen een Team- of Pro-abonnement. Upgrade je werkruimte."
#: src/views/card/components/MemberSelector.tsx:111 #: src/views/card/components/MemberSelector.tsx:112
#: src/views/members/components/InviteMemberForm.tsx:367 #: src/views/members/components/InviteMemberForm.tsx:367
msgid "Invite member" msgid "Invite member"
msgstr "Lid uitnodigen" msgstr "Lid uitnodigen"
@@ -1286,9 +1326,9 @@ msgstr "Houd er rekening mee dat deze actie onomkeerbaar is."
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "Sneltoetsen" msgstr "Sneltoetsen"
#: src/views/board/components/Filters.tsx:115 #: src/views/board/components/Filters.tsx:155
#: src/views/board/components/NewCardForm.tsx:409 #: src/views/board/components/NewCardForm.tsx:418
#: src/views/card/index.tsx:119 #: src/views/card/index.tsx:121
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -1338,11 +1378,11 @@ msgstr "Licentie"
msgid "Light" msgid "Light"
msgstr "Licht" msgstr "Licht"
#: src/views/public/board/index.tsx:66 #: src/views/public/board/index.tsx:78
msgid "Link copied" msgid "Link copied"
msgstr "Link gekopieerd" msgstr "Link gekopieerd"
#: src/views/card/index.tsx:111 #: src/views/card/index.tsx:113
msgid "List" msgid "List"
msgstr "Lijst" msgstr "Lijst"
@@ -1350,10 +1390,18 @@ msgstr "Lijst"
msgid "List name" msgid "List name"
msgstr "Lijstnaam" msgstr "Lijstnaam"
#: src/views/board/components/Filters.tsx:123 #: src/views/board/components/Filters.tsx:163
msgid "Lists" msgid "Lists"
msgstr "Lijsten" msgstr "Lijsten"
#: src/views/card/components/ActivityList.tsx:530
msgid "Load more activities"
msgstr "Meer activiteiten laden"
#: src/views/card/components/ActivityList.tsx:530
msgid "Loading..."
msgstr "Laden..."
#: src/views/auth/login/index.tsx:33 #: src/views/auth/login/index.tsx:33
msgid "Login | kan.bn" msgid "Login | kan.bn"
msgstr "Login | kan.bn" msgstr "Login | kan.bn"
@@ -1382,12 +1430,12 @@ msgstr "magische link"
msgid "Make template" msgid "Make template"
msgstr "Sjabloon maken" msgstr "Sjabloon maken"
#: src/views/card/components/ActivityList.tsx:75 #: src/views/card/components/ActivityList.tsx:113
msgid "marked a checklist item as incomplete" msgid "marked a checklist item as incomplete"
msgstr "heeft een checklistitem als onvoltooid gemarkeerd" msgstr "heeft een checklistitem als onvoltooid gemarkeerd"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196 #: src/views/card/components/ActivityList.tsx:231
msgid "marked checklist item <0>{0}</0> as incomplete" msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "heeft checklistitem <0>{0}</0> als onvoltooid gemarkeerd" msgstr "heeft checklistitem <0>{0}</0> als onvoltooid gemarkeerd"
@@ -1396,9 +1444,9 @@ msgid "Medium Priority"
msgstr "Gemiddelde prioriteit" msgstr "Gemiddelde prioriteit"
#: src/components/SideNavigation.tsx:121 #: src/components/SideNavigation.tsx:121
#: src/views/board/components/Filters.tsx:107 #: src/views/board/components/Filters.tsx:147
#: src/views/board/components/NewCardForm.tsx:367 #: src/views/board/components/NewCardForm.tsx:376
#: src/views/card/index.tsx:128 #: src/views/card/index.tsx:130
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Leden" msgstr "Leden"
@@ -1419,11 +1467,11 @@ msgstr "maandelijkse facturering"
#. placeholder {0}: truncate(fromList) #. placeholder {0}: truncate(fromList)
#. placeholder {1}: truncate(toList) #. placeholder {1}: truncate(toList)
#: src/views/card/components/ActivityList.tsx:98 #: src/views/card/components/ActivityList.tsx:133
msgid "moved the card from <0>{0}</0> to<1>{1}</1>" msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "heeft de kaart verplaatst van <0>{0}</0> naar<1>{1}</1>" msgstr "heeft de kaart verplaatst van <0>{0}</0> naar<1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:64 #: src/views/card/components/ActivityList.tsx:102
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "heeft de kaart naar een andere lijst verplaatst" msgstr "heeft de kaart naar een andere lijst verplaatst"
@@ -1455,11 +1503,11 @@ msgstr "Nieuwe {0}"
msgid "New API key" msgid "New API key"
msgstr "Nieuwe API-sleutel" msgstr "Nieuwe API-sleutel"
#: src/views/board/components/NewCardForm.tsx:293 #: src/views/board/components/NewCardForm.tsx:302
msgid "New card" msgid "New card"
msgstr "Nieuwe kaart" msgstr "Nieuwe kaart"
#: src/views/card/components/NewChecklistForm.tsx:102 #: src/views/card/components/NewChecklistForm.tsx:103
msgid "New checklist" msgid "New checklist"
msgstr "Nieuwe checklist" msgstr "Nieuwe checklist"
@@ -1472,7 +1520,7 @@ msgid "New label"
msgstr "Nieuw label" msgstr "Nieuw label"
#: src/views/board/components/NewListForm.tsx:113 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:454 #: src/views/board/index.tsx:462
msgid "New list" msgid "New list"
msgstr "Nieuwe lijst" msgstr "Nieuwe lijst"
@@ -1521,7 +1569,11 @@ msgstr "Geen borden gevonden"
msgid "No credit card required" msgid "No credit card required"
msgstr "Geen creditcard vereist" msgstr "Geen creditcard vereist"
#: src/views/card/components/AttachmentThumbnails.tsx:142 #: src/views/board/components/Filters.tsx:137
msgid "No dates"
msgstr "Geen datums"
#: src/views/card/components/AttachmentThumbnails.tsx:143
msgid "No download URL available for this attachment." msgid "No download URL available for this attachment."
msgstr "Geen download-URL beschikbaar voor deze bijlage." msgstr "Geen download-URL beschikbaar voor deze bijlage."
@@ -1529,7 +1581,7 @@ msgstr "Geen download-URL beschikbaar voor deze bijlage."
msgid "No keyboard shortcuts registered." msgid "No keyboard shortcuts registered."
msgstr "Geen sneltoetsen geregistreerd." msgstr "Geen sneltoetsen geregistreerd."
#: src/views/board/index.tsx:480 #: src/views/board/index.tsx:488
msgid "No lists" msgid "No lists"
msgstr "Geen lijsten" msgstr "Geen lijsten"
@@ -1555,11 +1607,11 @@ msgstr "Zodra je je werkruimte verwijdert, is er geen weg terug. Deze actie kan
#: src/components/WorkspaceMenu.tsx:31 #: src/components/WorkspaceMenu.tsx:31
msgid "Open command menu" msgid "Open command menu"
msgstr "Open opdrachtmenu" msgstr "Opdrachtmenu openen"
#: src/providers/keyboard-shortcuts.tsx:171 #: src/providers/keyboard-shortcuts.tsx:171
msgid "Open keyboard shortcuts" msgid "Open keyboard shortcuts"
msgstr "Open sneltoetsen" msgstr "Sneltoetsen openen"
#: src/views/pricing/components/FeatureComparisonTable.tsx:150 #: src/views/pricing/components/FeatureComparisonTable.tsx:150
msgid "Open source" msgid "Open source"
@@ -1582,6 +1634,10 @@ msgstr "Organiseer en vind kaarten snel met krachtige filtertools."
msgid "OSS Friends" msgid "OSS Friends"
msgstr "OSS Vrienden" msgstr "OSS Vrienden"
#: src/views/board/components/Filters.tsx:112
msgid "Overdue"
msgstr "Achterstallig"
#: src/views/pricing/components/Pricing.tsx:73 #: src/views/pricing/components/Pricing.tsx:73
#: src/views/pricing/components/PricingTiers.tsx:70 #: src/views/pricing/components/PricingTiers.tsx:70
msgid "Own your data" msgid "Own your data"
@@ -1670,30 +1726,33 @@ msgstr "Selecteer een bestand om te uploaden."
#: src/components/DeleteLabelConfirmation.tsx:26 #: src/components/DeleteLabelConfirmation.tsx:26
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/NewWorkspaceForm.tsx:158 #: src/components/NewWorkspaceForm.tsx:158
#: src/views/board/components/NewCardForm.tsx:177 #: src/views/board/components/NewCardForm.tsx:184
#: src/views/board/components/NewListForm.tsx:79 #: src/views/board/components/NewListForm.tsx:79
#: src/views/board/components/NewTemplateForm.tsx:61 #: src/views/board/components/NewTemplateForm.tsx:61
#: src/views/board/components/NewTemplateForm.tsx:77 #: src/views/board/components/NewTemplateForm.tsx:77
#: src/views/board/components/UpdateBoardSlugForm.tsx:73 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:54 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:162 #: src/views/board/index.tsx:170
#: src/views/board/index.tsx:218 #: src/views/board/index.tsx:226
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/card/components/AttachmentThumbnails.tsx:73 #: src/views/card/components/AttachmentThumbnails.tsx:74
#: src/views/card/components/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:67
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:95
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:47
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Checklists.tsx:81
#: src/views/card/components/Comment.tsx:65
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37 #: src/views/card/components/DeleteChecklistConfirmation.tsx:38
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:46
#: src/views/card/components/LabelSelector.tsx:72 #: src/views/card/components/DueDateSelector.tsx:60
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/MemberSelector.tsx:79 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistForm.tsx:71
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewChecklistItemForm.tsx:90
#: src/views/card/index.tsx:177 #: src/views/card/components/NewCommentForm.tsx:32
#: src/views/card/index.tsx:187
#: src/views/card/index.tsx:200
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/members/components/InviteMemberForm.tsx:104 #: src/views/members/components/InviteMemberForm.tsx:104
#: src/views/members/components/InviteMemberForm.tsx:241 #: src/views/members/components/InviteMemberForm.tsx:241
@@ -1793,30 +1852,40 @@ msgstr "Verwijderen"
msgid "Remove member" msgid "Remove member"
msgstr "Lid verwijderen" msgstr "Lid verwijderen"
#: src/views/card/components/ActivityList.tsx:66 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:91
msgid "removed {0} labels: <0>{labelList}</0>"
msgstr "{0} labels verwijderd: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:104
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "heeft een label van de kaart verwijderd" msgstr "heeft een label van de kaart verwijderd"
#: src/views/card/components/ActivityList.tsx:68 #: src/views/card/components/ActivityList.tsx:106
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "heeft een lid van de kaart verwijderd" msgstr "heeft een lid van de kaart verwijderd"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138 #: src/views/card/components/ActivityList.tsx:173
msgid "removed label <0>{0}</0>" msgid "removed label <0>{0}</0>"
msgstr "heeft label <0>{0}</0> verwijderd" msgstr "heeft label <0>{0}</0> verwijderd"
#: src/views/card/components/ActivityList.tsx:70 #: src/views/card/components/ActivityList.tsx:117
#: src/views/card/components/ActivityList.tsx:276
msgid "removed the due date"
msgstr "heeft de vervaldatum verwijderd"
#: src/views/card/components/ActivityList.tsx:108
msgid "renamed a checklist" msgid "renamed a checklist"
msgstr "heeft een checklist hernoemd" msgstr "heeft een checklist hernoemd"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154 #: src/views/card/components/ActivityList.tsx:189
msgid "renamed checklist <0>{0}</0>" msgid "renamed checklist <0>{0}</0>"
msgstr "heeft checklist <0>{0}</0> hernoemd" msgstr "heeft checklist <0>{0}</0> hernoemd"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178 #: src/views/card/components/ActivityList.tsx:213
msgid "renamed checklist item to <0>{0}</0>" msgid "renamed checklist item to <0>{0}</0>"
msgstr "checklistitem hernoemd naar <0>{0}</0>" msgstr "checklistitem hernoemd naar <0>{0}</0>"
@@ -1855,7 +1924,7 @@ msgstr "Rol"
msgid "Run on your own infrastructure" msgid "Run on your own infrastructure"
msgstr "Draai op je eigen infrastructuur" msgstr "Draai op je eigen infrastructuur"
#: src/views/card/components/Comment.tsx:165 #: src/views/card/components/Comment.tsx:166
#: src/views/settings/components/Avatar.tsx:309 #: src/views/settings/components/Avatar.tsx:309
msgid "Save" msgid "Save"
msgstr "Opslaan" msgstr "Opslaan"
@@ -1893,7 +1962,7 @@ msgstr "Zelf hosten"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Zelf hosten met Github" msgstr "Zelf hosten met Github"
#: src/views/card/components/ActivityList.tsx:107 #: src/views/card/components/ActivityList.tsx:142
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "heeft de kaart aan zichzelf toegewezen" msgstr "heeft de kaart aan zichzelf toegewezen"
@@ -1909,6 +1978,14 @@ msgstr "Feedback versturen"
msgid "Senior" msgid "Senior"
msgstr "Senior" msgstr "Senior"
#: src/views/card/components/DueDateSelector.tsx:117
msgid "Set due date"
msgstr "Vervaldatum instellen"
#: src/views/card/components/ActivityList.tsx:115
msgid "set the due date"
msgstr "heeft de vervaldatum ingesteld"
#: src/components/SettingsLayout.tsx:82 #: src/components/SettingsLayout.tsx:82
#: src/components/SideNavigation.tsx:133 #: src/components/SideNavigation.tsx:133
msgid "Settings" msgid "Settings"
@@ -2030,8 +2107,8 @@ msgstr "Teamplan"
msgid "Teams" msgid "Teams"
msgstr "Teams" msgstr "Teams"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/board/index.tsx:409 #: src/views/board/index.tsx:417
msgid "Template" msgid "Template"
msgstr "Sjabloon" msgstr "Sjabloon"
@@ -2096,8 +2173,8 @@ msgstr "Ze zullen geen toegang meer hebben tot deze werkruimte."
#: src/components/DeleteLabelConfirmation.tsx:44 #: src/components/DeleteLabelConfirmation.tsx:44
#: src/views/board/components/DeleteBoardConfirmation.tsx:39 #: src/views/board/components/DeleteBoardConfirmation.tsx:39
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58 #: src/views/card/components/DeleteChecklistConfirmation.tsx:59
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:69
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Deze actie kan niet ongedaan worden gemaakt." msgstr "Deze actie kan niet ongedaan worden gemaakt."
@@ -2105,7 +2182,7 @@ msgstr "Deze actie kan niet ongedaan worden gemaakt."
msgid "This API key will only be shown once. Please save it in a secure location." msgid "This API key will only be shown once. Please save it in a secure location."
msgstr "Deze API-sleutel wordt slechts één keer getoond. Bewaar deze op een veilige plaats." msgstr "Deze API-sleutel wordt slechts één keer getoond. Bewaar deze op een veilige plaats."
#: src/views/public/board/index.tsx:156 #: src/views/public/board/index.tsx:169
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "Dit bord is privé of bestaat niet" msgstr "Dit bord is privé of bestaat niet"
@@ -2167,23 +2244,27 @@ msgstr "Trello-imports"
msgid "Triaging" msgid "Triaging"
msgstr "Triage" msgstr "Triage"
#: src/views/home/components/Logos.tsx:73 #: src/views/home/components/Logos.tsx:67
msgid "Trusted by fast-moving teams<0/>around the world" msgid "Trusted by fast-moving teams<0/>around the world"
msgstr "Vertrouwd door snelbewegende teams<0/>over de hele wereld" msgstr "Vertrouwd door snelbewegende teams<0/>over de hele wereld"
#: src/views/card/components/NewChecklistItemForm.tsx:88 #: src/views/card/components/NewChecklistItemForm.tsx:89
msgid "Unable to add checklist item" msgid "Unable to add checklist item"
msgstr "Kan checklistitem niet toevoegen" msgstr "Kan checklistitem niet toevoegen"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:31
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Kan geen reactie toevoegen" msgstr "Kan geen reactie toevoegen"
#: src/views/board/components/NewCardForm.tsx:174 #: src/views/card/index.tsx:199
msgid "Unable to add label"
msgstr "Kan label niet toevoegen"
#: src/views/board/components/NewCardForm.tsx:181
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Kan kaart niet aanmaken" msgstr "Kan kaart niet aanmaken"
#: src/views/card/components/NewChecklistForm.tsx:69 #: src/views/card/components/NewChecklistForm.tsx:70
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Kan checklist niet maken" msgstr "Kan checklist niet maken"
@@ -2200,7 +2281,7 @@ msgstr "Kan sjabloon niet maken"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "Kan werkruimte niet aanmaken" msgstr "Kan werkruimte niet aanmaken"
#: src/views/card/components/AttachmentThumbnails.tsx:72 #: src/views/card/components/AttachmentThumbnails.tsx:73
msgid "Unable to delete attachment" msgid "Unable to delete attachment"
msgstr "Kan bijlage niet verwijderen" msgstr "Kan bijlage niet verwijderen"
@@ -2208,15 +2289,15 @@ msgstr "Kan bijlage niet verwijderen"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Kan kaart niet verwijderen" msgstr "Kan kaart niet verwijderen"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36 #: src/views/card/components/DeleteChecklistConfirmation.tsx:37
msgid "Unable to delete checklist" msgid "Unable to delete checklist"
msgstr "Kan checklist niet verwijderen" msgstr "Kan checklist niet verwijderen"
#: src/views/card/components/ChecklistItemRow.tsx:87 #: src/views/card/components/ChecklistItemRow.tsx:94
msgid "Unable to delete checklist item" msgid "Unable to delete checklist item"
msgstr "Kan checklistitem niet verwijderen" msgstr "Kan checklistitem niet verwijderen"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Kan opmerking niet verwijderen" msgstr "Kan opmerking niet verwijderen"
@@ -2224,6 +2305,10 @@ msgstr "Kan opmerking niet verwijderen"
msgid "Unable to remove member" msgid "Unable to remove member"
msgstr "Kan lid niet verwijderen" msgstr "Kan lid niet verwijderen"
#: src/views/card/components/Checklists.tsx:80
msgid "Unable to reorder checklist item"
msgstr "Kan checklistitem niet opnieuw ordenen"
#: src/components/FeedbackModal.tsx:40 #: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Feedback kon niet worden verzonden" msgstr "Feedback kon niet worden verzonden"
@@ -2236,42 +2321,46 @@ msgstr "Kan board URL niet bijwerken"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Kan bordzichtbaarheid niet bijwerken" msgstr "Kan bordzichtbaarheid niet bijwerken"
#: src/views/board/index.tsx:217 #: src/views/board/index.tsx:225
#: src/views/card/index.tsx:176 #: src/views/card/index.tsx:186
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Kan kaart niet bijwerken" msgstr "Kan kaart niet bijwerken"
#: src/views/card/components/ChecklistNameInput.tsx:45 #: src/views/card/components/ChecklistNameInput.tsx:46
msgid "Unable to update checklist" msgid "Unable to update checklist"
msgstr "Kan checklist niet bijwerken" msgstr "Kan checklist niet bijwerken"
#: src/views/card/components/ChecklistItemRow.tsx:59 #: src/views/card/components/ChecklistItemRow.tsx:66
msgid "Unable to update checklist item" msgid "Unable to update checklist item"
msgstr "Kan checklistitem niet bijwerken" msgstr "Kan checklistitem niet bijwerken"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:64
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Kan reactie niet bijwerken" msgstr "Kan reactie niet bijwerken"
#: src/views/card/components/LabelSelector.tsx:71 #: src/views/card/components/DueDateSelector.tsx:59
msgid "Unable to update due date"
msgstr "Kan vervaldatum niet bijwerken"
#: src/views/card/components/LabelSelector.tsx:72
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "Kan labels niet bijwerken" msgstr "Kan labels niet bijwerken"
#: src/views/board/index.tsx:161 #: src/views/board/index.tsx:169
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:52
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Kan lijst niet bijwerken" msgstr "Kan lijst niet bijwerken"
#: src/views/card/components/MemberSelector.tsx:78 #: src/views/card/components/MemberSelector.tsx:79
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Kan leden niet bijwerken" msgstr "Kan leden niet bijwerken"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:121 #: src/views/card/components/ActivityList.tsx:156
msgid "unassigned <0>{0}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "<0>{0}</0> van de kaart verwijderd" msgstr "<0>{0}</0> van de kaart verwijderd"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:153
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "zichzelf van de kaart verwijderd" msgstr "zichzelf van de kaart verwijderd"
@@ -2313,6 +2402,11 @@ msgstr "Onbeperkt aantal leden"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Onbeperkte werkruimtes" 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/board/components/UpdateBoardSlugForm.tsx:175
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80 #: src/views/settings/components/UpdateDisplayNameForm.tsx:80
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
@@ -2325,20 +2419,24 @@ msgstr "Bijwerken"
msgid "Update label" msgid "Update label"
msgstr "Label bijwerken" msgstr "Label bijwerken"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:111
msgid "updated a checklist item" msgid "updated a checklist item"
msgstr "een checklistitem bijgewerkt" msgstr "een checklistitem bijgewerkt"
#: src/views/card/components/ActivityList.tsx:63 #: src/views/card/components/ActivityList.tsx:101
msgid "updated the description" msgid "updated the description"
msgstr "beschrijving bijgewerkt" msgstr "beschrijving bijgewerkt"
#: src/views/card/components/ActivityList.tsx:62 #: src/views/card/components/ActivityList.tsx:116
msgid "updated the due date"
msgstr "heeft de vervaldatum bijgewerkt"
#: src/views/card/components/ActivityList.tsx:100
msgid "updated the title" msgid "updated the title"
msgstr "titel bijgewerkt" msgstr "titel bijgewerkt"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90 #: src/views/card/components/ActivityList.tsx:125
msgid "updated the title to <0>{0}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "titel bijgewerkt naar <0>{0}</0>" msgstr "titel bijgewerkt naar <0>{0}</0>"
@@ -2352,8 +2450,8 @@ msgstr "Upgraden naar Pro"
msgid "Upgrade to Pro ($29/month)" msgid "Upgrade to Pro ($29/month)"
msgstr "Upgrade naar Pro ($29/maand)" msgstr "Upgrade naar Pro ($29/maand)"
#: src/views/card/components/AttachmentUpload.tsx:32 #: src/views/card/components/AttachmentUpload.tsx:33
#: src/views/card/components/AttachmentUpload.tsx:78 #: src/views/card/components/AttachmentUpload.tsx:79
msgid "Upload failed" msgid "Upload failed"
msgstr "Uploaden mislukt" msgstr "Uploaden mislukt"
@@ -2406,7 +2504,7 @@ msgstr "Bekijk en beheer je facturering en abonnement."
msgid "View docs" msgid "View docs"
msgstr "Bekijk documentatie" msgstr "Bekijk documentatie"
#: src/views/public/board/index.tsx:129 #: src/views/public/board/index.tsx:142
msgid "View only" msgid "View only"
msgstr "Alleen bekijken" msgstr "Alleen bekijken"
@@ -2414,7 +2512,7 @@ msgstr "Alleen bekijken"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "Bekijk onze roadmap." msgstr "Bekijk onze roadmap."
#: src/views/public/board/index.tsx:159 #: src/views/public/board/index.tsx:172
msgid "View workspace" msgid "View workspace"
msgstr "Werkruimte bekijken" msgstr "Werkruimte bekijken"
@@ -2426,6 +2524,10 @@ msgstr "Zichtbaarheid"
msgid "We are using the <0>AGPL-3.0 license</0>." msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "We gebruiken de <0>AGPL-3.0 licentie</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 #: src/views/home/components/Features.tsx:152
msgid "We're just getting started. " msgid "We're just getting started. "
msgstr "We zijn nog maar net begonnen. " msgstr "We zijn nog maar net begonnen. "
@@ -2455,10 +2557,10 @@ msgid "Why make an open source Trello?"
msgstr "Waarom een open source Trello maken?" msgstr "Waarom een open source Trello maken?"
#: src/components/SettingsLayout.tsx:39 #: src/components/SettingsLayout.tsx:39
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Werkruimte" msgstr "Werkruimte"
@@ -2564,6 +2666,10 @@ msgstr "Je bent succesvol ingelogd."
msgid "You have been signed up successfully." msgid "You have been signed up successfully."
msgstr "Je bent succesvol geregistreerd." 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 #: src/views/members/components/InviteMemberForm.tsx:326
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!" 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!" msgstr "Je hebt onbeperkte plaatsen met je Pro Plan. Er zijn geen extra kosten voor nieuwe leden!"
@@ -2588,7 +2694,7 @@ msgstr "Je borden zijn geïmporteerd."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Je weergavenaam is bijgewerkt." msgstr "Je weergavenaam is bijgewerkt."
#: src/views/card/components/AttachmentUpload.tsx:26 #: src/views/card/components/AttachmentUpload.tsx:27
msgid "Your file has been uploaded successfully." msgid "Your file has been uploaded successfully."
msgstr "Je bestand is succesvol geüpload." msgstr "Je bestand is succesvol geüpload."
@@ -2608,6 +2714,10 @@ msgstr "Je Trello-account is ontkoppeld."
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Je Trello-account is verbonden." 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 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
msgid "Your workspace description has been updated." msgid "Your workspace description has been updated."
msgstr "Je werkruimtebeschrijving is bijgewerkt." msgstr "Je werkruimtebeschrijving is bijgewerkt."

File diff suppressed because one or more lines are too long

View File

@@ -18,7 +18,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:123 #: src/views/card/components/Comment.tsx:124
msgid " (edited)" msgid " (edited)"
msgstr " (edytowano)" msgstr " (edytowano)"
@@ -36,17 +36,17 @@ msgstr "{0}"
#. placeholder {1}: board?.name ?? t`Board` #. placeholder {1}: board?.name ?? t`Board`
#. placeholder {1}: workspace.name ?? t`Workspace` #. placeholder {1}: workspace.name ?? t`Workspace`
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:443 #: src/views/board/components/NewCardForm.tsx:452
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} etykiety" msgstr "{0} etykiety"
#. placeholder {0}: isTemplate ? "Template" : "Board" #. placeholder {0}: isTemplate ? "Template" : "Board"
#: src/views/board/index.tsx:400 #: src/views/board/index.tsx:408
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} nie znaleziono" msgstr "{0} nie znaleziono"
@@ -86,10 +86,10 @@ msgstr "Konto zostało usunięte"
#: src/providers/keyboard-shortcuts.tsx:55 #: src/providers/keyboard-shortcuts.tsx:55
msgid "Actions" msgid "Actions"
msgstr "Akcje" msgstr "Działania"
#: src/views/card/index.tsx:343 #: src/views/card/index.tsx:386
#: src/views/public/board/CardModal.tsx:157 #: src/views/public/board/CardModal.tsx:158
msgid "Activity" msgid "Activity"
msgstr "Aktywność" msgstr "Aktywność"
@@ -105,12 +105,12 @@ msgstr "Dzienniki aktywności"
msgid "Add a card" msgid "Add a card"
msgstr "Dodaj kartę" msgstr "Dodaj kartę"
#: src/views/card/components/Comment.tsx:146 #: src/views/card/components/Comment.tsx:147
#: src/views/card/components/NewCommentForm.tsx:57 #: src/views/card/components/NewCommentForm.tsx:55
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Dodaj komentarz..." msgstr "Dodaj komentarz..."
#: src/views/card/components/NewChecklistItemForm.tsx:140 #: src/views/card/components/NewChecklistItemForm.tsx:141
msgid "Add an item..." msgid "Add an item..."
msgstr "Dodaj element..." msgstr "Dodaj element..."
@@ -122,48 +122,53 @@ msgstr "Dodaj listę kontrolną"
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Dodaj opis... (wpisz '/' aby otworzyć polecenia lub '@' aby wspomnieć)" msgstr "Dodaj opis... (wpisz '/' aby otworzyć polecenia lub '@' aby wspomnieć)"
#: src/views/card/components/ChecklistItemRow.tsx:172 #: src/views/card/components/ChecklistItemRow.tsx:195
msgid "Add details..." msgid "Add details..."
msgstr "Dodaj szczegóły..." msgstr "Dodaj szczegóły..."
#: src/views/card/components/LabelSelector.tsx:109 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:114 #: src/views/card/components/LabelSelector.tsx:115
msgid "Add label" msgid "Add label"
msgstr "Dodaj etykietę" msgstr "Dodaj etykietę"
#: src/views/card/components/MemberSelector.tsx:130 #: src/views/card/components/MemberSelector.tsx:131
#: src/views/members/components/InviteMemberForm.tsx:257 #: src/views/members/components/InviteMemberForm.tsx:257
msgid "Add member" msgid "Add member"
msgstr "Dodaj członka" msgstr "Dodaj członka"
#: src/views/card/components/ActivityList.tsx:69 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:77
msgid "added {0} labels: <0>{labelList}</0>"
msgstr "dodano {0} etykiety: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:107
msgid "added a checklist" msgid "added a checklist"
msgstr "dodał listę kontrolną" msgstr "dodał listę kontrolną"
#: src/views/card/components/ActivityList.tsx:72 #: src/views/card/components/ActivityList.tsx:110
msgid "added a checklist item" msgid "added a checklist item"
msgstr "dodał(a) element listy kontrolnej" msgstr "dodał(a) element listy kontrolnej"
#: src/views/card/components/ActivityList.tsx:65 #: src/views/card/components/ActivityList.tsx:103
msgid "added a label to the card" msgid "added a label to the card"
msgstr "dodał(a) etykietę do karty" msgstr "dodał(a) etykietę do karty"
#: src/views/card/components/ActivityList.tsx:67 #: src/views/card/components/ActivityList.tsx:105
msgid "added a member to the card" msgid "added a member to the card"
msgstr "dodał(a) członka do karty" msgstr "dodał(a) członka do karty"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146 #: src/views/card/components/ActivityList.tsx:181
msgid "added checklist <0>{0}</0>" msgid "added checklist <0>{0}</0>"
msgstr "dodał(a) listę kontrolną <0>{0}</0>" msgstr "dodał(a) listę kontrolną <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170 #: src/views/card/components/ActivityList.tsx:205
msgid "added checklist item <0>{0}</0>" msgid "added checklist item <0>{0}</0>"
msgstr "dodał(a) element listy kontrolnej <0>{0}</0>" msgstr "dodał(a) element listy kontrolnej <0>{0}</0>"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130 #: src/views/card/components/ActivityList.tsx:165
msgid "added label <0>{0}</0>" msgid "added label <0>{0}</0>"
msgstr "dodał(a) etykietę <0>{0}</0>" msgstr "dodał(a) etykietę <0>{0}</0>"
@@ -254,11 +259,11 @@ msgstr "Czy na pewno chcesz usunąć ten {0}?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Czy na pewno chcesz usunąć tę kartę?" msgstr "Czy na pewno chcesz usunąć tę kartę?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55 #: src/views/card/components/DeleteChecklistConfirmation.tsx:56
msgid "Are you sure you want to delete this checklist?" msgid "Are you sure you want to delete this checklist?"
msgstr "Czy na pewno chcesz usunąć tę listę kontrolną?" msgstr "Czy na pewno chcesz usunąć tę listę kontrolną?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:66
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Czy na pewno chcesz usunąć ten komentarz?" msgstr "Czy na pewno chcesz usunąć ten komentarz?"
@@ -271,7 +276,7 @@ msgid "Are you sure you want to delete your account?"
msgstr "Czy na pewno chcesz usunąć swoje konto?" msgstr "Czy na pewno chcesz usunąć swoje konto?"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:145
msgid "assigned <0>{0}</0> to the card" msgid "assigned <0>{0}</0> to the card"
msgstr "przypisano <0>{0}</0> do karty" msgstr "przypisano <0>{0}</0> do karty"
@@ -279,7 +284,7 @@ msgstr "przypisano <0>{0}</0> do karty"
msgid "Assignees" msgid "Assignees"
msgstr "Osoby przypisane" msgstr "Osoby przypisane"
#: src/views/card/components/AttachmentUpload.tsx:25 #: src/views/card/components/AttachmentUpload.tsx:26
msgid "Attachment uploaded" msgid "Attachment uploaded"
msgstr "Załącznik został przesłany" msgstr "Załącznik został przesłany"
@@ -317,9 +322,9 @@ msgstr "Portal rozliczeniowy"
msgid "Blog Post" msgid "Blog Post"
msgstr "Post na blogu" msgstr "Post na blogu"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
msgid "Board" msgid "Board"
msgstr "Tablica" msgstr "Tablica"
@@ -336,7 +341,7 @@ msgstr "Nazwa tablicy nie może przekraczać 100 znaków"
msgid "Board name is required" msgid "Board name is required"
msgstr "Nazwa tablicy jest wymagana" msgstr "Nazwa tablicy jest wymagana"
#: src/views/public/board/index.tsx:153 #: src/views/public/board/index.tsx:166
msgid "Board not found" msgid "Board not found"
msgstr "Tablica nie została znaleziona" msgstr "Tablica nie została znaleziona"
@@ -352,7 +357,7 @@ msgstr "Adres URL tablicy może zawierać tylko litery, cyfry i myślniki"
msgid "Board URL cannot exceed 60 characters" msgid "Board URL cannot exceed 60 characters"
msgstr "Adres URL tablicy nie może przekraczać 60 znaków" msgstr "Adres URL tablicy nie może przekraczać 60 znaków"
#: src/views/public/board/index.tsx:68 #: src/views/public/board/index.tsx:80
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "Adres URL tablicy został skopiowany do schowka" msgstr "Adres URL tablicy został skopiowany do schowka"
@@ -387,10 +392,10 @@ msgstr "Zgłoszenie błędu"
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:49
#: src/views/board/components/DeleteBoardConfirmation.tsx:44 #: src/views/board/components/DeleteBoardConfirmation.tsx:44
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:159
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63 #: src/views/card/components/DeleteChecklistConfirmation.tsx:64
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:77
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/settings/components/Avatar.tsx:306 #: src/views/settings/components/Avatar.tsx:306
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168 #: src/views/settings/components/ChangePasswordConfirmation.tsx:168
@@ -400,16 +405,16 @@ msgstr "Zgłoszenie błędu"
msgid "Cancel" msgid "Cancel"
msgstr "Anuluj" msgstr "Anuluj"
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "Card" msgid "Card"
msgstr "Karta" msgstr "Karta"
#: src/views/card/index.tsx:263 #: src/views/card/index.tsx:306
#: src/views/card/index.tsx:299 #: src/views/card/index.tsx:342
msgid "Card not found" msgid "Card not found"
msgstr "Nie można było znaleźć karty" msgstr "Nie można było znaleźć karty"
#: src/views/board/components/NewCardForm.tsx:310 #: src/views/board/components/NewCardForm.tsx:319
msgid "Card title" msgid "Card title"
msgstr "Tytuł karty" msgstr "Tytuł karty"
@@ -424,6 +429,11 @@ msgstr "Zmień hasło"
msgid "Change your language preferences." msgid "Change your language preferences."
msgstr "Zmień swoje preferencje językowe." msgstr "Zmień swoje preferencje językowe."
#: src/views/card/components/ActivityList.tsx:255
#: src/views/card/components/ActivityList.tsx:269
msgid "changed the due date to <0>{formattedDate}</0>"
msgstr "zmieniono termin na <0>{formattedDate}</0>"
#: src/views/oss-friends/index.tsx:61 #: src/views/oss-friends/index.tsx:61
msgid "Check out some of our favorite open source projects." msgid "Check out some of our favorite open source projects."
msgstr "Sprawdź niektóre z naszych ulubionych projektów otwartoźródłowych." msgstr "Sprawdź niektóre z naszych ulubionych projektów otwartoźródłowych."
@@ -433,7 +443,7 @@ msgstr "Sprawdź niektóre z naszych ulubionych projektów otwartoźródłowych.
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Sprawdź swoją skrzynkę odbiorczą" msgstr "Sprawdź swoją skrzynkę odbiorczą"
#: src/views/card/components/NewChecklistForm.tsx:118 #: src/views/card/components/NewChecklistForm.tsx:119
msgid "Checklist name" msgid "Checklist name"
msgstr "Nazwa listy kontrolnej" msgstr "Nazwa listy kontrolnej"
@@ -442,7 +452,7 @@ msgstr "Nazwa listy kontrolnej"
msgid "Checklists" msgid "Checklists"
msgstr "Listy kontrolne" msgstr "Listy kontrolne"
#: src/views/board/components/Filters.tsx:180 #: src/views/board/components/Filters.tsx:227
msgid "Clear filters" msgid "Clear filters"
msgstr "Wyczyść filtry" msgstr "Wyczyść filtry"
@@ -494,15 +504,19 @@ msgstr "Zakończ"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Pełna kontrola i własność:" msgstr "Pełna kontrola i własność:"
#: src/views/card/components/ActivityList.tsx:74 #: src/views/card/components/ActivityList.tsx:112
msgid "completed a checklist item" msgid "completed a checklist item"
msgstr "ukończono element listy kontrolnej" msgstr "ukończono element listy kontrolnej"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187 #: src/views/card/components/ActivityList.tsx:222
msgid "completed checklist item <0>{0}</0>" msgid "completed checklist item <0>{0}</0>"
msgstr "ukończono element listy kontrolnej <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 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password" msgid "Confirm your new password"
msgstr "Potwierdź swoje nowe hasło" msgstr "Potwierdź swoje nowe hasło"
@@ -556,7 +570,7 @@ msgid "Create {0}"
msgstr "Utwórz {0}" msgstr "Utwórz {0}"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:469 #: src/views/board/components/NewCardForm.tsx:516
#: src/views/board/components/NewListForm.tsx:141 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Utwórz kolejny" msgstr "Utwórz kolejny"
@@ -565,11 +579,11 @@ msgstr "Utwórz kolejny"
msgid "Create API key" msgid "Create API key"
msgstr "Utwórz klucz API" msgstr "Utwórz klucz API"
#: src/views/board/components/NewCardForm.tsx:479 #: src/views/board/components/NewCardForm.tsx:526
msgid "Create card" msgid "Create card"
msgstr "Utwórz kartę" msgstr "Utwórz kartę"
#: src/views/card/components/NewChecklistForm.tsx:134 #: src/views/card/components/NewChecklistForm.tsx:135
msgid "Create checklist" msgid "Create checklist"
msgstr "Utwórz listę kontrolną" msgstr "Utwórz listę kontrolną"
@@ -595,13 +609,13 @@ msgstr "Utwórz nowy {0}"
msgid "Create new key" msgid "Create new key"
msgstr "Utwórz nowy klucz" msgstr "Utwórz nowy klucz"
#: src/views/board/components/NewCardForm.tsx:405 #: src/views/board/components/NewCardForm.tsx:414
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:98
msgid "Create new label" msgid "Create new label"
msgstr "Utwórz nową etykietę" msgstr "Utwórz nową etykietę"
#: src/views/board/index.tsx:64 #: src/views/board/index.tsx:64
#: src/views/board/index.tsx:491 #: src/views/board/index.tsx:499
msgid "Create new list" msgid "Create new list"
msgstr "Utwórz nową listę" msgstr "Utwórz nową listę"
@@ -614,7 +628,7 @@ msgstr "Utwórz szablon"
msgid "Create workspace" msgid "Create workspace"
msgstr "Utwórz przestrzeń roboczą" msgstr "Utwórz przestrzeń roboczą"
#: src/views/card/components/ActivityList.tsx:61 #: src/views/card/components/ActivityList.tsx:99
msgid "created the card" msgid "created the card"
msgstr "utworzył(a) kartę" msgstr "utworzył(a) kartę"
@@ -672,8 +686,8 @@ msgstr "Dezaktywuj link zaproszenia"
#: src/components/LabelForm.tsx:228 #: src/components/LabelForm.tsx:228
#: src/views/board/components/DeleteBoardConfirmation.tsx:47 #: src/views/board/components/DeleteBoardConfirmation.tsx:47
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66 #: src/views/card/components/DeleteChecklistConfirmation.tsx:67
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:83
msgid "Delete" msgid "Delete"
msgstr "Usuń" msgstr "Usuń"
@@ -691,7 +705,7 @@ msgstr "Usuń tablicę"
msgid "Delete card" msgid "Delete card"
msgstr "Usuń kartę" msgstr "Usuń kartę"
#: src/views/card/components/Comment.tsx:91 #: src/views/card/components/Comment.tsx:92
msgid "Delete comment" msgid "Delete comment"
msgstr "Usuń komentarz" msgstr "Usuń komentarz"
@@ -709,21 +723,21 @@ msgstr "Usuń szablon"
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Usuń przestrzeń roboczą" msgstr "Usuń przestrzeń roboczą"
#: src/views/card/components/ActivityList.tsx:71 #: src/views/card/components/ActivityList.tsx:109
msgid "deleted a checklist" msgid "deleted a checklist"
msgstr "usunięto listę kontrolną" msgstr "usunięto listę kontrolną"
#: src/views/card/components/ActivityList.tsx:76 #: src/views/card/components/ActivityList.tsx:114
msgid "deleted a checklist item" msgid "deleted a checklist item"
msgstr "usunięto element listy kontrolnej" msgstr "usunięto element listy kontrolnej"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162 #: src/views/card/components/ActivityList.tsx:197
msgid "deleted checklist <0>{0}</0>" msgid "deleted checklist <0>{0}</0>"
msgstr "usunięto listę kontrolną <0>{0}</0>" msgstr "usunięto listę kontrolną <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205 #: src/views/card/components/ActivityList.tsx:240
msgid "deleted checklist item <0>{0}</0>" msgid "deleted checklist item <0>{0}</0>"
msgstr "usunięto element listy kontrolnej <0>{0}</0>" msgstr "usunięto element listy kontrolnej <0>{0}</0>"
@@ -759,6 +773,10 @@ msgstr "Zaktualizowano wyświetlaną nazwę"
msgid "Do you offer a free plan?" msgid "Do you offer a free plan?"
msgstr "Czy oferujecie darmowy 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 #: src/components/FeedbackModal.tsx:109
msgid "docs" msgid "docs"
msgstr "dokumentacja" msgstr "dokumentacja"
@@ -785,16 +803,38 @@ msgstr "Nie masz konta? <0><1>Zarejestruj się</1></0>"
msgid "Done" msgid "Done"
msgstr "Gotowe" msgstr "Gotowe"
#: src/views/card/components/AttachmentThumbnails.tsx:141 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "Download failed" msgid "Download failed"
msgstr "Pobieranie nie powiodło się" msgstr "Pobieranie nie powiodło się"
#: src/views/board/components/Filters.tsx:171
#: src/views/board/components/NewCardForm.tsx:469
#: src/views/card/index.tsx:139
msgid "Due date"
msgstr "Termin"
#: src/views/board/components/Filters.tsx:132
msgid "Due next month"
msgstr "Termin w przyszłym miesiącu"
#: src/views/board/components/Filters.tsx:127
msgid "Due next week"
msgstr "Termin w przyszłym tygodniu"
#: src/views/board/components/Filters.tsx:117
msgid "Due today"
msgstr "Termin na dziś"
#: src/views/board/components/Filters.tsx:122
msgid "Due tomorrow"
msgstr "Termin na jutro"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:116 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Edytuj URL tablicy" msgstr "Edytuj URL tablicy"
#: src/views/card/components/Comment.tsx:82 #: src/views/card/components/Comment.tsx:83
msgid "Edit comment" msgid "Edit comment"
msgstr "Edytuj komentarz" msgstr "Edytuj komentarz"
@@ -951,8 +991,8 @@ msgstr "Nie udało się utworzyć tablicy"
msgid "Failed to login with {0}. Please try again." msgid "Failed to login with {0}. Please try again."
msgstr "Nie udało się zalogować za pomocą {0}. Spróbuj ponownie." msgstr "Nie udało się zalogować za pomocą {0}. Spróbuj ponownie."
#: src/views/card/components/AttachmentUpload.tsx:33 #: src/views/card/components/AttachmentUpload.tsx:34
#: src/views/card/components/AttachmentUpload.tsx:79 #: src/views/card/components/AttachmentUpload.tsx:80
msgid "Failed to upload attachment. Please try again." msgid "Failed to upload attachment. Please try again."
msgstr "Nie udało się przesłać załącznika. Proszę spróbować ponownie." msgstr "Nie udało się przesłać załącznika. Proszę spróbować ponownie."
@@ -999,7 +1039,7 @@ msgstr "Opinie"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Opinia wysłana" msgstr "Opinia wysłana"
#: src/views/board/components/Filters.tsx:174 #: src/views/board/components/Filters.tsx:221
msgid "Filter" msgid "Filter"
msgstr "Filtr" msgstr "Filtr"
@@ -1057,7 +1097,7 @@ msgstr "Rozpocznij"
msgid "Get started by creating a new {0}" msgid "Get started by creating a new {0}"
msgstr "Rozpocznij, tworząc nowy {0}" msgstr "Rozpocznij, tworząc nowy {0}"
#: src/views/board/index.tsx:483 #: src/views/board/index.tsx:491
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Rozpocznij, tworząc nową listę" msgstr "Rozpocznij, tworząc nową listę"
@@ -1244,7 +1284,7 @@ msgstr "Linki zaproszeń"
msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace."
msgstr "Linki zaproszeń wymagają subskrypcji Team lub Pro. Proszę ulepszyć swoje środowisko pracy." msgstr "Linki zaproszeń wymagają subskrypcji Team lub Pro. Proszę ulepszyć swoje środowisko pracy."
#: src/views/card/components/MemberSelector.tsx:111 #: src/views/card/components/MemberSelector.tsx:112
#: src/views/members/components/InviteMemberForm.tsx:367 #: src/views/members/components/InviteMemberForm.tsx:367
msgid "Invite member" msgid "Invite member"
msgstr "Zaproś członka" msgstr "Zaproś członka"
@@ -1291,9 +1331,9 @@ msgstr "Pamiętaj, że ta akcja jest nieodwracalna."
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "Skróty klawiaturowe" msgstr "Skróty klawiaturowe"
#: src/views/board/components/Filters.tsx:115 #: src/views/board/components/Filters.tsx:155
#: src/views/board/components/NewCardForm.tsx:409 #: src/views/board/components/NewCardForm.tsx:418
#: src/views/card/index.tsx:119 #: src/views/card/index.tsx:121
msgid "Labels" msgid "Labels"
msgstr "Etykiety" msgstr "Etykiety"
@@ -1343,11 +1383,11 @@ msgstr "Licencja"
msgid "Light" msgid "Light"
msgstr "Jasny" msgstr "Jasny"
#: src/views/public/board/index.tsx:66 #: src/views/public/board/index.tsx:78
msgid "Link copied" msgid "Link copied"
msgstr "Link skopiowany" msgstr "Link skopiowany"
#: src/views/card/index.tsx:111 #: src/views/card/index.tsx:113
msgid "List" msgid "List"
msgstr "Lista" msgstr "Lista"
@@ -1355,10 +1395,18 @@ msgstr "Lista"
msgid "List name" msgid "List name"
msgstr "Nazwa listy" msgstr "Nazwa listy"
#: src/views/board/components/Filters.tsx:123 #: src/views/board/components/Filters.tsx:163
msgid "Lists" msgid "Lists"
msgstr "Listy" msgstr "Listy"
#: src/views/card/components/ActivityList.tsx:530
msgid "Load more activities"
msgstr "Załaduj więcej aktywności"
#: src/views/card/components/ActivityList.tsx:530
msgid "Loading..."
msgstr "Ładowanie..."
#: src/views/auth/login/index.tsx:33 #: src/views/auth/login/index.tsx:33
msgid "Login | kan.bn" msgid "Login | kan.bn"
msgstr "Zaloguj się | kan.bn" msgstr "Zaloguj się | kan.bn"
@@ -1387,12 +1435,12 @@ msgstr "magiczny link"
msgid "Make template" msgid "Make template"
msgstr "Utwórz szablon" msgstr "Utwórz szablon"
#: src/views/card/components/ActivityList.tsx:75 #: src/views/card/components/ActivityList.tsx:113
msgid "marked a checklist item as incomplete" msgid "marked a checklist item as incomplete"
msgstr "oznaczył element listy kontrolnej jako nieukończony" msgstr "oznaczył element listy kontrolnej jako nieukończony"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196 #: src/views/card/components/ActivityList.tsx:231
msgid "marked checklist item <0>{0}</0> as incomplete" msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "oznaczył element listy kontrolnej <0>{0}</0> jako nieukończony" msgstr "oznaczył element listy kontrolnej <0>{0}</0> jako nieukończony"
@@ -1401,9 +1449,9 @@ msgid "Medium Priority"
msgstr "Średni priorytet" msgstr "Średni priorytet"
#: src/components/SideNavigation.tsx:121 #: src/components/SideNavigation.tsx:121
#: src/views/board/components/Filters.tsx:107 #: src/views/board/components/Filters.tsx:147
#: src/views/board/components/NewCardForm.tsx:367 #: src/views/board/components/NewCardForm.tsx:376
#: src/views/card/index.tsx:128 #: src/views/card/index.tsx:130
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Członkowie" msgstr "Członkowie"
@@ -1424,11 +1472,11 @@ msgstr "rozliczenie miesięczne"
#. placeholder {0}: truncate(fromList) #. placeholder {0}: truncate(fromList)
#. placeholder {1}: truncate(toList) #. placeholder {1}: truncate(toList)
#: src/views/card/components/ActivityList.tsx:98 #: src/views/card/components/ActivityList.tsx:133
msgid "moved the card from <0>{0}</0> to<1>{1}</1>" msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "przeniesiono kartę z <0>{0}</0> do<1>{1}</1>" msgstr "przeniesiono kartę z <0>{0}</0> do<1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:64 #: src/views/card/components/ActivityList.tsx:102
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "przeniesiono kartę do innej listy" msgstr "przeniesiono kartę do innej listy"
@@ -1460,11 +1508,11 @@ msgstr "Nowy {0}"
msgid "New API key" msgid "New API key"
msgstr "Nowy klucz API" msgstr "Nowy klucz API"
#: src/views/board/components/NewCardForm.tsx:293 #: src/views/board/components/NewCardForm.tsx:302
msgid "New card" msgid "New card"
msgstr "Nowa karta" msgstr "Nowa karta"
#: src/views/card/components/NewChecklistForm.tsx:102 #: src/views/card/components/NewChecklistForm.tsx:103
msgid "New checklist" msgid "New checklist"
msgstr "Nowa lista kontrolna" msgstr "Nowa lista kontrolna"
@@ -1477,7 +1525,7 @@ msgid "New label"
msgstr "Nowa etykieta" msgstr "Nowa etykieta"
#: src/views/board/components/NewListForm.tsx:113 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:454 #: src/views/board/index.tsx:462
msgid "New list" msgid "New list"
msgstr "Nowa lista" msgstr "Nowa lista"
@@ -1526,7 +1574,11 @@ msgstr "Nie znaleziono tablic"
msgid "No credit card required" msgid "No credit card required"
msgstr "Nie wymagana karta kredytowa" msgstr "Nie wymagana karta kredytowa"
#: src/views/card/components/AttachmentThumbnails.tsx:142 #: src/views/board/components/Filters.tsx:137
msgid "No dates"
msgstr "Brak terminów"
#: src/views/card/components/AttachmentThumbnails.tsx:143
msgid "No download URL available for this attachment." msgid "No download URL available for this attachment."
msgstr "Brak dostępnego URL do pobrania tego załącznika." msgstr "Brak dostępnego URL do pobrania tego załącznika."
@@ -1534,7 +1586,7 @@ msgstr "Brak dostępnego URL do pobrania tego załącznika."
msgid "No keyboard shortcuts registered." msgid "No keyboard shortcuts registered."
msgstr "Brak zarejestrowanych skrótów klawiaturowych." msgstr "Brak zarejestrowanych skrótów klawiaturowych."
#: src/views/board/index.tsx:480 #: src/views/board/index.tsx:488
msgid "No lists" msgid "No lists"
msgstr "Brak list" msgstr "Brak list"
@@ -1587,6 +1639,10 @@ msgstr "Organizuj i znajduj karty szybko dzięki zaawansowanym narzędziom filtr
msgid "OSS Friends" msgid "OSS Friends"
msgstr "Przyjaciele OSS" msgstr "Przyjaciele OSS"
#: src/views/board/components/Filters.tsx:112
msgid "Overdue"
msgstr "Zaległe"
#: src/views/pricing/components/Pricing.tsx:73 #: src/views/pricing/components/Pricing.tsx:73
#: src/views/pricing/components/PricingTiers.tsx:70 #: src/views/pricing/components/PricingTiers.tsx:70
msgid "Own your data" msgid "Own your data"
@@ -1675,30 +1731,33 @@ msgstr "Proszę wybrać plik do przesłania."
#: src/components/DeleteLabelConfirmation.tsx:26 #: src/components/DeleteLabelConfirmation.tsx:26
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/NewWorkspaceForm.tsx:158 #: src/components/NewWorkspaceForm.tsx:158
#: src/views/board/components/NewCardForm.tsx:177 #: src/views/board/components/NewCardForm.tsx:184
#: src/views/board/components/NewListForm.tsx:79 #: src/views/board/components/NewListForm.tsx:79
#: src/views/board/components/NewTemplateForm.tsx:61 #: src/views/board/components/NewTemplateForm.tsx:61
#: src/views/board/components/NewTemplateForm.tsx:77 #: src/views/board/components/NewTemplateForm.tsx:77
#: src/views/board/components/UpdateBoardSlugForm.tsx:73 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:54 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:162 #: src/views/board/index.tsx:170
#: src/views/board/index.tsx:218 #: src/views/board/index.tsx:226
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/card/components/AttachmentThumbnails.tsx:73 #: src/views/card/components/AttachmentThumbnails.tsx:74
#: src/views/card/components/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:67
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:95
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:47
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Checklists.tsx:81
#: src/views/card/components/Comment.tsx:65
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37 #: src/views/card/components/DeleteChecklistConfirmation.tsx:38
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:46
#: src/views/card/components/LabelSelector.tsx:72 #: src/views/card/components/DueDateSelector.tsx:60
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/MemberSelector.tsx:79 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistForm.tsx:71
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewChecklistItemForm.tsx:90
#: src/views/card/index.tsx:177 #: src/views/card/components/NewCommentForm.tsx:32
#: src/views/card/index.tsx:187
#: src/views/card/index.tsx:200
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/members/components/InviteMemberForm.tsx:104 #: src/views/members/components/InviteMemberForm.tsx:104
#: src/views/members/components/InviteMemberForm.tsx:241 #: src/views/members/components/InviteMemberForm.tsx:241
@@ -1798,30 +1857,40 @@ msgstr "Usuń"
msgid "Remove member" msgid "Remove member"
msgstr "Usuń członka" msgstr "Usuń członka"
#: src/views/card/components/ActivityList.tsx:66 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:91
msgid "removed {0} labels: <0>{labelList}</0>"
msgstr "usunięto {0} etykiety: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:104
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "usunął etykietę z karty" msgstr "usunął etykietę z karty"
#: src/views/card/components/ActivityList.tsx:68 #: src/views/card/components/ActivityList.tsx:106
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "usunął członka z karty" msgstr "usunął członka z karty"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138 #: src/views/card/components/ActivityList.tsx:173
msgid "removed label <0>{0}</0>" msgid "removed label <0>{0}</0>"
msgstr "usunięto etykietę <0>{0}</0>" msgstr "usunięto etykietę <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:70 #: src/views/card/components/ActivityList.tsx:117
#: src/views/card/components/ActivityList.tsx:276
msgid "removed the due date"
msgstr "usunięto termin"
#: src/views/card/components/ActivityList.tsx:108
msgid "renamed a checklist" msgid "renamed a checklist"
msgstr "zmieniono nazwę listy kontrolnej" msgstr "zmieniono nazwę listy kontrolnej"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154 #: src/views/card/components/ActivityList.tsx:189
msgid "renamed checklist <0>{0}</0>" msgid "renamed checklist <0>{0}</0>"
msgstr "zmieniono nazwę listy kontrolnej <0>{0}</0>" msgstr "zmieniono nazwę listy kontrolnej <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178 #: src/views/card/components/ActivityList.tsx:213
msgid "renamed checklist item to <0>{0}</0>" msgid "renamed checklist item to <0>{0}</0>"
msgstr "zmieniono nazwę elementu listy kontrolnej na <0>{0}</0>" msgstr "zmieniono nazwę elementu listy kontrolnej na <0>{0}</0>"
@@ -1860,7 +1929,7 @@ msgstr "Rola"
msgid "Run on your own infrastructure" msgid "Run on your own infrastructure"
msgstr "Uruchom na własnej infrastrukturze" msgstr "Uruchom na własnej infrastrukturze"
#: src/views/card/components/Comment.tsx:165 #: src/views/card/components/Comment.tsx:166
#: src/views/settings/components/Avatar.tsx:309 #: src/views/settings/components/Avatar.tsx:309
msgid "Save" msgid "Save"
msgstr "Zapisz" msgstr "Zapisz"
@@ -1898,7 +1967,7 @@ msgstr "Hostuj samodzielnie"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Hostuj samodzielnie z Github" msgstr "Hostuj samodzielnie z Github"
#: src/views/card/components/ActivityList.tsx:107 #: src/views/card/components/ActivityList.tsx:142
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "przypisał(a) sobie kartę" msgstr "przypisał(a) sobie kartę"
@@ -1914,6 +1983,14 @@ msgstr "Prześlij opinię"
msgid "Senior" msgid "Senior"
msgstr "Starszy" msgstr "Starszy"
#: src/views/card/components/DueDateSelector.tsx:117
msgid "Set due date"
msgstr "Ustaw termin"
#: src/views/card/components/ActivityList.tsx:115
msgid "set the due date"
msgstr "ustawiono termin"
#: src/components/SettingsLayout.tsx:82 #: src/components/SettingsLayout.tsx:82
#: src/components/SideNavigation.tsx:133 #: src/components/SideNavigation.tsx:133
msgid "Settings" msgid "Settings"
@@ -2035,8 +2112,8 @@ msgstr "Plan zespołowy"
msgid "Teams" msgid "Teams"
msgstr "Zespoły" msgstr "Zespoły"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/board/index.tsx:409 #: src/views/board/index.tsx:417
msgid "Template" msgid "Template"
msgstr "Szablon" msgstr "Szablon"
@@ -2101,8 +2178,8 @@ msgstr "Nie będą mieli dostępu do tego obszaru roboczego."
#: src/components/DeleteLabelConfirmation.tsx:44 #: src/components/DeleteLabelConfirmation.tsx:44
#: src/views/board/components/DeleteBoardConfirmation.tsx:39 #: src/views/board/components/DeleteBoardConfirmation.tsx:39
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58 #: src/views/card/components/DeleteChecklistConfirmation.tsx:59
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:69
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Tej akcji nie można cofnąć." msgstr "Tej akcji nie można cofnąć."
@@ -2110,7 +2187,7 @@ msgstr "Tej akcji nie można cofnąć."
msgid "This API key will only be shown once. Please save it in a secure location." msgid "This API key will only be shown once. Please save it in a secure location."
msgstr "Ten klucz API zostanie wyświetlony tylko raz. Proszę zapisać go w bezpiecznym miejscu." msgstr "Ten klucz API zostanie wyświetlony tylko raz. Proszę zapisać go w bezpiecznym miejscu."
#: src/views/public/board/index.tsx:156 #: src/views/public/board/index.tsx:169
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "Ta tablica jest prywatna lub nie istnieje" msgstr "Ta tablica jest prywatna lub nie istnieje"
@@ -2172,23 +2249,27 @@ msgstr "Importy Trello"
msgid "Triaging" msgid "Triaging"
msgstr "Sortowanie" msgstr "Sortowanie"
#: src/views/home/components/Logos.tsx:73 #: src/views/home/components/Logos.tsx:67
msgid "Trusted by fast-moving teams<0/>around the world" msgid "Trusted by fast-moving teams<0/>around the world"
msgstr "Zaufany przez dynamiczne zespoły<0/>na całym świecie" msgstr "Zaufany przez dynamiczne zespoły<0/>na całym świecie"
#: src/views/card/components/NewChecklistItemForm.tsx:88 #: src/views/card/components/NewChecklistItemForm.tsx:89
msgid "Unable to add checklist item" msgid "Unable to add checklist item"
msgstr "Nie można dodać elementu listy kontrolnej" msgstr "Nie można dodać elementu listy kontrolnej"
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:31
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Nie można dodać komentarza" msgstr "Nie można dodać komentarza"
#: src/views/board/components/NewCardForm.tsx:174 #: src/views/card/index.tsx:199
msgid "Unable to add label"
msgstr "Nie można dodać etykiety"
#: src/views/board/components/NewCardForm.tsx:181
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Nie można utworzyć karty" msgstr "Nie można utworzyć karty"
#: src/views/card/components/NewChecklistForm.tsx:69 #: src/views/card/components/NewChecklistForm.tsx:70
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Nie można utworzyć listy kontrolnej" msgstr "Nie można utworzyć listy kontrolnej"
@@ -2205,7 +2286,7 @@ msgstr "Nie można utworzyć szablonu"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "Nie można utworzyć przestrzeni roboczej" msgstr "Nie można utworzyć przestrzeni roboczej"
#: src/views/card/components/AttachmentThumbnails.tsx:72 #: src/views/card/components/AttachmentThumbnails.tsx:73
msgid "Unable to delete attachment" msgid "Unable to delete attachment"
msgstr "Nie można usunąć załącznika" msgstr "Nie można usunąć załącznika"
@@ -2213,15 +2294,15 @@ msgstr "Nie można usunąć załącznika"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Nie można usunąć karty" msgstr "Nie można usunąć karty"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36 #: src/views/card/components/DeleteChecklistConfirmation.tsx:37
msgid "Unable to delete checklist" msgid "Unable to delete checklist"
msgstr "Nie można usunąć listy kontrolnej" msgstr "Nie można usunąć listy kontrolnej"
#: src/views/card/components/ChecklistItemRow.tsx:87 #: src/views/card/components/ChecklistItemRow.tsx:94
msgid "Unable to delete checklist item" msgid "Unable to delete checklist item"
msgstr "Nie można usunąć elementu listy kontrolnej" msgstr "Nie można usunąć elementu listy kontrolnej"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Nie można usunąć komentarza" msgstr "Nie można usunąć komentarza"
@@ -2229,6 +2310,10 @@ msgstr "Nie można usunąć komentarza"
msgid "Unable to remove member" msgid "Unable to remove member"
msgstr "Nie można usunąć członka" msgstr "Nie można usunąć członka"
#: src/views/card/components/Checklists.tsx:80
msgid "Unable to reorder checklist item"
msgstr "Nie można zmienić kolejności elementu listy kontrolnej"
#: src/components/FeedbackModal.tsx:40 #: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Nie można wysłać opinii" msgstr "Nie można wysłać opinii"
@@ -2241,42 +2326,46 @@ msgstr "Nie można zaktualizować adresu URL tablicy"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Nie można zaktualizować widoczności tablicy" msgstr "Nie można zaktualizować widoczności tablicy"
#: src/views/board/index.tsx:217 #: src/views/board/index.tsx:225
#: src/views/card/index.tsx:176 #: src/views/card/index.tsx:186
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Nie można zaktualizować karty" msgstr "Nie można zaktualizować karty"
#: src/views/card/components/ChecklistNameInput.tsx:45 #: src/views/card/components/ChecklistNameInput.tsx:46
msgid "Unable to update checklist" msgid "Unable to update checklist"
msgstr "Nie można zaktualizować listy kontrolnej" msgstr "Nie można zaktualizować listy kontrolnej"
#: src/views/card/components/ChecklistItemRow.tsx:59 #: src/views/card/components/ChecklistItemRow.tsx:66
msgid "Unable to update checklist item" msgid "Unable to update checklist item"
msgstr "Nie można zaktualizować elementu listy kontrolnej" msgstr "Nie można zaktualizować elementu listy kontrolnej"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:64
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Nie można zaktualizować komentarza" msgstr "Nie można zaktualizować komentarza"
#: src/views/card/components/LabelSelector.tsx:71 #: src/views/card/components/DueDateSelector.tsx:59
msgid "Unable to update due date"
msgstr "Nie można zaktualizować terminu"
#: src/views/card/components/LabelSelector.tsx:72
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "Nie można zaktualizować etykiet" msgstr "Nie można zaktualizować etykiet"
#: src/views/board/index.tsx:161 #: src/views/board/index.tsx:169
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:52
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Nie można zaktualizować listy" msgstr "Nie można zaktualizować listy"
#: src/views/card/components/MemberSelector.tsx:78 #: src/views/card/components/MemberSelector.tsx:79
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Nie można zaktualizować członków" msgstr "Nie można zaktualizować członków"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:121 #: src/views/card/components/ActivityList.tsx:156
msgid "unassigned <0>{0}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "usunięto przypisanie <0>{0}</0> z karty" msgstr "usunięto przypisanie <0>{0}</0> z karty"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:153
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "usunęli swoje przypisanie z karty" msgstr "usunęli swoje przypisanie z karty"
@@ -2318,6 +2407,11 @@ msgstr "Nieograniczona liczba członków"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Nieograniczona liczba przestrzeni roboczych" 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/board/components/UpdateBoardSlugForm.tsx:175
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80 #: src/views/settings/components/UpdateDisplayNameForm.tsx:80
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
@@ -2330,20 +2424,24 @@ msgstr "Aktualizuj"
msgid "Update label" msgid "Update label"
msgstr "Zaktualizuj etykietę" msgstr "Zaktualizuj etykietę"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:111
msgid "updated a checklist item" msgid "updated a checklist item"
msgstr "zaktualizowano element listy kontrolnej" msgstr "zaktualizowano element listy kontrolnej"
#: src/views/card/components/ActivityList.tsx:63 #: src/views/card/components/ActivityList.tsx:101
msgid "updated the description" msgid "updated the description"
msgstr "zaktualizowano opis" msgstr "zaktualizowano opis"
#: src/views/card/components/ActivityList.tsx:62 #: src/views/card/components/ActivityList.tsx:116
msgid "updated the due date"
msgstr "zaktualizowano termin"
#: src/views/card/components/ActivityList.tsx:100
msgid "updated the title" msgid "updated the title"
msgstr "zaktualizowano tytuł" msgstr "zaktualizowano tytuł"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90 #: src/views/card/components/ActivityList.tsx:125
msgid "updated the title to <0>{0}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "zaktualizowano tytuł na <0>{0}</0>" msgstr "zaktualizowano tytuł na <0>{0}</0>"
@@ -2357,8 +2455,8 @@ msgstr "Ulepsz do planu Pro"
msgid "Upgrade to Pro ($29/month)" msgid "Upgrade to Pro ($29/month)"
msgstr "Ulepsz do planu Pro (29 USD/miesiąc)" msgstr "Ulepsz do planu Pro (29 USD/miesiąc)"
#: src/views/card/components/AttachmentUpload.tsx:32 #: src/views/card/components/AttachmentUpload.tsx:33
#: src/views/card/components/AttachmentUpload.tsx:78 #: src/views/card/components/AttachmentUpload.tsx:79
msgid "Upload failed" msgid "Upload failed"
msgstr "Przesyłanie nie powiodło się" msgstr "Przesyłanie nie powiodło się"
@@ -2411,7 +2509,7 @@ msgstr "Zobacz i zarządzaj swoimi płatnościami i subskrypcją."
msgid "View docs" msgid "View docs"
msgstr "Zobacz dokumentację" msgstr "Zobacz dokumentację"
#: src/views/public/board/index.tsx:129 #: src/views/public/board/index.tsx:142
msgid "View only" msgid "View only"
msgstr "Tylko podgląd" msgstr "Tylko podgląd"
@@ -2419,7 +2517,7 @@ msgstr "Tylko podgląd"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "Zobacz nasz plan ulepszeń." msgstr "Zobacz nasz plan ulepszeń."
#: src/views/public/board/index.tsx:159 #: src/views/public/board/index.tsx:172
msgid "View workspace" msgid "View workspace"
msgstr "Zobacz obszar roboczy" msgstr "Zobacz obszar roboczy"
@@ -2431,6 +2529,10 @@ msgstr "Widoczność"
msgid "We are using the <0>AGPL-3.0 license</0>." msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "Używamy licencji <0>AGPL-3.0</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 #: src/views/home/components/Features.tsx:152
msgid "We're just getting started. " msgid "We're just getting started. "
msgstr "Dopiero zaczynamy. " msgstr "Dopiero zaczynamy. "
@@ -2460,10 +2562,10 @@ msgid "Why make an open source Trello?"
msgstr "Dlaczego próbujecie stworzyć Trello w wersji otwartoźródłowej?" msgstr "Dlaczego próbujecie stworzyć Trello w wersji otwartoźródłowej?"
#: src/components/SettingsLayout.tsx:39 #: src/components/SettingsLayout.tsx:39
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Obszar roboczy" msgstr "Obszar roboczy"
@@ -2569,6 +2671,10 @@ msgstr "Zostałeś pomyślnie zalogowany."
msgid "You have been signed up successfully." msgid "You have been signed up successfully."
msgstr "Zostałeś pomyślnie zarejestrowany." 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 #: src/views/members/components/InviteMemberForm.tsx:326
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!" 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!" msgstr "Masz nielimitowaną liczbę miejsc w swoim planie Pro. Nie ma dodatkowych opłat za nowych członków!"
@@ -2593,7 +2699,7 @@ msgstr "Twoje tablice zostały zaimportowane."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Twoja nazwa wyświetlana została zaktualizowana." msgstr "Twoja nazwa wyświetlana została zaktualizowana."
#: src/views/card/components/AttachmentUpload.tsx:26 #: src/views/card/components/AttachmentUpload.tsx:27
msgid "Your file has been uploaded successfully." msgid "Your file has been uploaded successfully."
msgstr "Twój plik został pomyślnie przesłany." msgstr "Twój plik został pomyślnie przesłany."
@@ -2613,6 +2719,10 @@ msgstr "Twoje konto Trello zostało odłączone."
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Twoje konto Trello jest połączone." 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 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
msgid "Your workspace description has been updated." msgid "Your workspace description has been updated."
msgstr "Opis twojej przestrzeni roboczej został zaktualizowany." msgstr "Opis twojej przestrzeni roboczej został zaktualizowany."

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: src/views/card/components/Comment.tsx:123 #: src/views/card/components/Comment.tsx:124
msgid " (edited)" msgid " (edited)"
msgstr " (отредактировано)" msgstr " (отредактировано)"
@@ -31,17 +31,17 @@ msgstr "{0}"
#. placeholder {1}: board?.name ?? t`Board` #. placeholder {1}: board?.name ?? t`Board`
#. placeholder {1}: workspace.name ?? t`Workspace` #. placeholder {1}: workspace.name ?? t`Workspace`
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "{0} | {1}" msgid "{0} | {1}"
msgstr "{0} | {1}" msgstr "{0} | {1}"
#. placeholder {0}: labelPublicIds.length #. placeholder {0}: labelPublicIds.length
#: src/views/board/components/NewCardForm.tsx:443 #: src/views/board/components/NewCardForm.tsx:452
msgid "{0} labels" msgid "{0} labels"
msgstr "{0} метки" msgstr "{0} метки"
#. placeholder {0}: isTemplate ? "Template" : "Board" #. placeholder {0}: isTemplate ? "Template" : "Board"
#: src/views/board/index.tsx:400 #: src/views/board/index.tsx:408
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} не найден" msgstr "{0} не найден"
@@ -83,8 +83,8 @@ msgstr "Аккаунт удалён"
msgid "Actions" msgid "Actions"
msgstr "Действия" msgstr "Действия"
#: src/views/card/index.tsx:343 #: src/views/card/index.tsx:386
#: src/views/public/board/CardModal.tsx:157 #: src/views/public/board/CardModal.tsx:158
msgid "Activity" msgid "Activity"
msgstr "Активность" msgstr "Активность"
@@ -100,12 +100,12 @@ msgstr "Журналы активности"
msgid "Add a card" msgid "Add a card"
msgstr "Добавить карточку" msgstr "Добавить карточку"
#: src/views/card/components/Comment.tsx:146 #: src/views/card/components/Comment.tsx:147
#: src/views/card/components/NewCommentForm.tsx:57 #: src/views/card/components/NewCommentForm.tsx:55
msgid "Add a comment..." msgid "Add a comment..."
msgstr "Добавить комментарий..." msgstr "Добавить комментарий..."
#: src/views/card/components/NewChecklistItemForm.tsx:140 #: src/views/card/components/NewChecklistItemForm.tsx:141
msgid "Add an item..." msgid "Add an item..."
msgstr "Добавить элемент..." msgstr "Добавить элемент..."
@@ -117,48 +117,53 @@ msgstr "Добавить чек-лист"
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Добавить описание... (введите '/' для открытия команд или '@' для упоминания)" msgstr "Добавить описание... (введите '/' для открытия команд или '@' для упоминания)"
#: src/views/card/components/ChecklistItemRow.tsx:172 #: src/views/card/components/ChecklistItemRow.tsx:195
msgid "Add details..." msgid "Add details..."
msgstr "Добавить детали..." msgstr "Добавить детали..."
#: src/views/card/components/LabelSelector.tsx:109 #: src/views/card/components/LabelSelector.tsx:110
#: src/views/card/components/LabelSelector.tsx:114 #: src/views/card/components/LabelSelector.tsx:115
msgid "Add label" msgid "Add label"
msgstr "Добавить метку" msgstr "Добавить метку"
#: src/views/card/components/MemberSelector.tsx:130 #: src/views/card/components/MemberSelector.tsx:131
#: src/views/members/components/InviteMemberForm.tsx:257 #: src/views/members/components/InviteMemberForm.tsx:257
msgid "Add member" msgid "Add member"
msgstr "Добавить участника" msgstr "Добавить участника"
#: src/views/card/components/ActivityList.tsx:69 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:77
msgid "added {0} labels: <0>{labelList}</0>"
msgstr "добавил {0} метки: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:107
msgid "added a checklist" msgid "added a checklist"
msgstr "добавил(а) чек-лист" msgstr "добавил(а) чек-лист"
#: src/views/card/components/ActivityList.tsx:72 #: src/views/card/components/ActivityList.tsx:110
msgid "added a checklist item" msgid "added a checklist item"
msgstr "добавил(а) элемент чек-листа" msgstr "добавил(а) элемент чек-листа"
#: src/views/card/components/ActivityList.tsx:65 #: src/views/card/components/ActivityList.tsx:103
msgid "added a label to the card" msgid "added a label to the card"
msgstr "добавил(а) метку к карточке" msgstr "добавил(а) метку к карточке"
#: src/views/card/components/ActivityList.tsx:67 #: src/views/card/components/ActivityList.tsx:105
msgid "added a member to the card" msgid "added a member to the card"
msgstr "добавил(а) участника к карточке" msgstr "добавил(а) участника к карточке"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:146 #: src/views/card/components/ActivityList.tsx:181
msgid "added checklist <0>{0}</0>" msgid "added checklist <0>{0}</0>"
msgstr "добавлен контрольный список <0>{0}</0>" msgstr "добавлен контрольный список <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:170 #: src/views/card/components/ActivityList.tsx:205
msgid "added checklist item <0>{0}</0>" msgid "added checklist item <0>{0}</0>"
msgstr "добавлен элемент контрольного списка <0>{0}</0>" msgstr "добавлен элемент контрольного списка <0>{0}</0>"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:130 #: src/views/card/components/ActivityList.tsx:165
msgid "added label <0>{0}</0>" msgid "added label <0>{0}</0>"
msgstr "добавлена метка <0>{0}</0>" msgstr "добавлена метка <0>{0}</0>"
@@ -249,11 +254,11 @@ msgstr "Вы уверены, что хотите удалить этот {0}?"
msgid "Are you sure you want to delete this card?" msgid "Are you sure you want to delete this card?"
msgstr "Вы уверены, что хотите удалить эту карточку?" msgstr "Вы уверены, что хотите удалить эту карточку?"
#: src/views/card/components/DeleteChecklistConfirmation.tsx:55 #: src/views/card/components/DeleteChecklistConfirmation.tsx:56
msgid "Are you sure you want to delete this checklist?" msgid "Are you sure you want to delete this checklist?"
msgstr "Вы уверены, что хотите удалить этот контрольный список?" msgstr "Вы уверены, что хотите удалить этот контрольный список?"
#: src/views/card/components/DeleteCommentConfirmation.tsx:65 #: src/views/card/components/DeleteCommentConfirmation.tsx:66
msgid "Are you sure you want to delete this comment?" msgid "Are you sure you want to delete this comment?"
msgstr "Вы уверены, что хотите удалить этот комментарий?" msgstr "Вы уверены, что хотите удалить этот комментарий?"
@@ -266,7 +271,7 @@ msgid "Are you sure you want to delete your account?"
msgstr "Вы уверены, что хотите удалить свой аккаунт?" msgstr "Вы уверены, что хотите удалить свой аккаунт?"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:110 #: src/views/card/components/ActivityList.tsx:145
msgid "assigned <0>{0}</0> to the card" msgid "assigned <0>{0}</0> to the card"
msgstr "назначено <0>{0}</0> к карточке" msgstr "назначено <0>{0}</0> к карточке"
@@ -274,7 +279,7 @@ msgstr "назначено <0>{0}</0> к карточке"
msgid "Assignees" msgid "Assignees"
msgstr "Исполнители" msgstr "Исполнители"
#: src/views/card/components/AttachmentUpload.tsx:25 #: src/views/card/components/AttachmentUpload.tsx:26
msgid "Attachment uploaded" msgid "Attachment uploaded"
msgstr "Вложение загружено" msgstr "Вложение загружено"
@@ -312,9 +317,9 @@ msgstr "Портал выставления счетов"
msgid "Blog Post" msgid "Blog Post"
msgstr "Пост в блоге" msgstr "Пост в блоге"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
msgid "Board" msgid "Board"
msgstr "Доска" msgstr "Доска"
@@ -331,7 +336,7 @@ msgstr "Название доски не может превышать 100 си
msgid "Board name is required" msgid "Board name is required"
msgstr "Название доски обязательно" msgstr "Название доски обязательно"
#: src/views/public/board/index.tsx:153 #: src/views/public/board/index.tsx:166
msgid "Board not found" msgid "Board not found"
msgstr "Доска не найдена" msgstr "Доска не найдена"
@@ -347,7 +352,7 @@ msgstr "URL доски может содержать только буквы, ц
msgid "Board URL cannot exceed 60 characters" msgid "Board URL cannot exceed 60 characters"
msgstr "URL доски не может превышать 60 символов" msgstr "URL доски не может превышать 60 символов"
#: src/views/public/board/index.tsx:68 #: src/views/public/board/index.tsx:80
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "URL доски скопирован в буфер обмена" msgstr "URL доски скопирован в буфер обмена"
@@ -382,10 +387,10 @@ msgstr "Отчет об ошибке"
#: src/components/DeleteLabelConfirmation.tsx:49 #: src/components/DeleteLabelConfirmation.tsx:49
#: src/views/board/components/DeleteBoardConfirmation.tsx:44 #: src/views/board/components/DeleteBoardConfirmation.tsx:44
#: src/views/card/components/Comment.tsx:158 #: src/views/card/components/Comment.tsx:159
#: src/views/card/components/DeleteCardConfirmation.tsx:86 #: src/views/card/components/DeleteCardConfirmation.tsx:86
#: src/views/card/components/DeleteChecklistConfirmation.tsx:63 #: src/views/card/components/DeleteChecklistConfirmation.tsx:64
#: src/views/card/components/DeleteCommentConfirmation.tsx:76 #: src/views/card/components/DeleteCommentConfirmation.tsx:77
#: src/views/members/components/DeleteMemberConfirmation.tsx:55 #: src/views/members/components/DeleteMemberConfirmation.tsx:55
#: src/views/settings/components/Avatar.tsx:306 #: src/views/settings/components/Avatar.tsx:306
#: src/views/settings/components/ChangePasswordConfirmation.tsx:168 #: src/views/settings/components/ChangePasswordConfirmation.tsx:168
@@ -395,16 +400,16 @@ msgstr "Отчет об ошибке"
msgid "Cancel" msgid "Cancel"
msgstr "Отмена" msgstr "Отмена"
#: src/views/card/index.tsx:229 #: src/views/card/index.tsx:272
msgid "Card" msgid "Card"
msgstr "Карточка" msgstr "Карточка"
#: src/views/card/index.tsx:263 #: src/views/card/index.tsx:306
#: src/views/card/index.tsx:299 #: src/views/card/index.tsx:342
msgid "Card not found" msgid "Card not found"
msgstr "Карточка не найдена" msgstr "Карточка не найдена"
#: src/views/board/components/NewCardForm.tsx:310 #: src/views/board/components/NewCardForm.tsx:319
msgid "Card title" msgid "Card title"
msgstr "Название карточки" msgstr "Название карточки"
@@ -419,6 +424,11 @@ msgstr "Изменить пароль"
msgid "Change your language preferences." msgid "Change your language preferences."
msgstr "Измените настройки языка." msgstr "Измените настройки языка."
#: src/views/card/components/ActivityList.tsx:255
#: src/views/card/components/ActivityList.tsx:269
msgid "changed the due date to <0>{formattedDate}</0>"
msgstr "изменил(а) дату выполнения на <0>{formattedDate}</0>"
#: src/views/oss-friends/index.tsx:61 #: src/views/oss-friends/index.tsx:61
msgid "Check out some of our favorite open source projects." msgid "Check out some of our favorite open source projects."
msgstr "Ознакомьтесь с некоторыми из наших любимых проектов с открытым исходным кодом." msgstr "Ознакомьтесь с некоторыми из наших любимых проектов с открытым исходным кодом."
@@ -428,7 +438,7 @@ msgstr "Ознакомьтесь с некоторыми из наших люб
msgid "Check your inbox" msgid "Check your inbox"
msgstr "Проверьте ваш почтовый ящик" msgstr "Проверьте ваш почтовый ящик"
#: src/views/card/components/NewChecklistForm.tsx:118 #: src/views/card/components/NewChecklistForm.tsx:119
msgid "Checklist name" msgid "Checklist name"
msgstr "Название контрольного списка" msgstr "Название контрольного списка"
@@ -437,7 +447,7 @@ msgstr "Название контрольного списка"
msgid "Checklists" msgid "Checklists"
msgstr "Контрольные списки" msgstr "Контрольные списки"
#: src/views/board/components/Filters.tsx:180 #: src/views/board/components/Filters.tsx:227
msgid "Clear filters" msgid "Clear filters"
msgstr "Очистить фильтры" msgstr "Очистить фильтры"
@@ -489,15 +499,19 @@ msgstr "Завершить"
msgid "Complete control and ownership:" msgid "Complete control and ownership:"
msgstr "Полный контроль и владение:" msgstr "Полный контроль и владение:"
#: src/views/card/components/ActivityList.tsx:74 #: src/views/card/components/ActivityList.tsx:112
msgid "completed a checklist item" msgid "completed a checklist item"
msgstr "завершил элемент контрольного списка" msgstr "завершил элемент контрольного списка"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:187 #: src/views/card/components/ActivityList.tsx:222
msgid "completed checklist item <0>{0}</0>" msgid "completed checklist item <0>{0}</0>"
msgstr "завершил элемент контрольного списка <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 #: src/views/settings/components/ChangePasswordConfirmation.tsx:150
msgid "Confirm your new password" msgid "Confirm your new password"
msgstr "Подтвердите ваш новый пароль" msgstr "Подтвердите ваш новый пароль"
@@ -551,7 +565,7 @@ msgid "Create {0}"
msgstr "Создать {0}" msgstr "Создать {0}"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:469 #: src/views/board/components/NewCardForm.tsx:516
#: src/views/board/components/NewListForm.tsx:141 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Создать ещё одну" msgstr "Создать ещё одну"
@@ -560,11 +574,11 @@ msgstr "Создать ещё одну"
msgid "Create API key" msgid "Create API key"
msgstr "Создать API-ключ" msgstr "Создать API-ключ"
#: src/views/board/components/NewCardForm.tsx:479 #: src/views/board/components/NewCardForm.tsx:526
msgid "Create card" msgid "Create card"
msgstr "Создать карточку" msgstr "Создать карточку"
#: src/views/card/components/NewChecklistForm.tsx:134 #: src/views/card/components/NewChecklistForm.tsx:135
msgid "Create checklist" msgid "Create checklist"
msgstr "Создать чек-лист" msgstr "Создать чек-лист"
@@ -590,13 +604,13 @@ msgstr "Создать новый {0}"
msgid "Create new key" msgid "Create new key"
msgstr "Создать новый ключ" msgstr "Создать новый ключ"
#: src/views/board/components/NewCardForm.tsx:405 #: src/views/board/components/NewCardForm.tsx:414
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:98
msgid "Create new label" msgid "Create new label"
msgstr "Создать новую метку" msgstr "Создать новую метку"
#: src/views/board/index.tsx:64 #: src/views/board/index.tsx:64
#: src/views/board/index.tsx:491 #: src/views/board/index.tsx:499
msgid "Create new list" msgid "Create new list"
msgstr "Создать новый список" msgstr "Создать новый список"
@@ -609,7 +623,7 @@ msgstr "Создать шаблон"
msgid "Create workspace" msgid "Create workspace"
msgstr "Создать рабочее пространство" msgstr "Создать рабочее пространство"
#: src/views/card/components/ActivityList.tsx:61 #: src/views/card/components/ActivityList.tsx:99
msgid "created the card" msgid "created the card"
msgstr "создал(а) карточку" msgstr "создал(а) карточку"
@@ -667,8 +681,8 @@ msgstr "Деактивировать ссылку-приглашение"
#: src/components/LabelForm.tsx:228 #: src/components/LabelForm.tsx:228
#: src/views/board/components/DeleteBoardConfirmation.tsx:47 #: src/views/board/components/DeleteBoardConfirmation.tsx:47
#: src/views/card/components/DeleteCardConfirmation.tsx:92 #: src/views/card/components/DeleteCardConfirmation.tsx:92
#: src/views/card/components/DeleteChecklistConfirmation.tsx:66 #: src/views/card/components/DeleteChecklistConfirmation.tsx:67
#: src/views/card/components/DeleteCommentConfirmation.tsx:82 #: src/views/card/components/DeleteCommentConfirmation.tsx:83
msgid "Delete" msgid "Delete"
msgstr "Удалить" msgstr "Удалить"
@@ -686,7 +700,7 @@ msgstr "Удалить доску"
msgid "Delete card" msgid "Delete card"
msgstr "Удалить карточку" msgstr "Удалить карточку"
#: src/views/card/components/Comment.tsx:91 #: src/views/card/components/Comment.tsx:92
msgid "Delete comment" msgid "Delete comment"
msgstr "Удалить комментарий" msgstr "Удалить комментарий"
@@ -704,21 +718,21 @@ msgstr "Удалить шаблон"
msgid "Delete workspace" msgid "Delete workspace"
msgstr "Удалить рабочее пространство" msgstr "Удалить рабочее пространство"
#: src/views/card/components/ActivityList.tsx:71 #: src/views/card/components/ActivityList.tsx:109
msgid "deleted a checklist" msgid "deleted a checklist"
msgstr "удалил контрольный список" msgstr "удалил контрольный список"
#: src/views/card/components/ActivityList.tsx:76 #: src/views/card/components/ActivityList.tsx:114
msgid "deleted a checklist item" msgid "deleted a checklist item"
msgstr "удалил элемент контрольного списка" msgstr "удалил элемент контрольного списка"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:162 #: src/views/card/components/ActivityList.tsx:197
msgid "deleted checklist <0>{0}</0>" msgid "deleted checklist <0>{0}</0>"
msgstr "удалил контрольный список <0>{0}</0>" msgstr "удалил контрольный список <0>{0}</0>"
#. placeholder {0}: truncate(fromTitle) #. placeholder {0}: truncate(fromTitle)
#: src/views/card/components/ActivityList.tsx:205 #: src/views/card/components/ActivityList.tsx:240
msgid "deleted checklist item <0>{0}</0>" msgid "deleted checklist item <0>{0}</0>"
msgstr "удалил элемент контрольного списка <0>{0}</0>" msgstr "удалил элемент контрольного списка <0>{0}</0>"
@@ -754,6 +768,10 @@ msgstr "Отображаемое имя обновлено"
msgid "Do you offer a free plan?" msgid "Do you offer a free plan?"
msgstr "Вы предлагаете бесплатный план?" msgstr "Вы предлагаете бесплатный план?"
#: src/pages/unsubscribe/index.tsx:78
msgid "Do you want to unsubscribe?"
msgstr "Вы хотите отписаться?"
#: src/components/FeedbackModal.tsx:109 #: src/components/FeedbackModal.tsx:109
msgid "docs" msgid "docs"
msgstr "документы" msgstr "документы"
@@ -780,16 +798,38 @@ msgstr "Нет аккаунта? <0><1>Зарегистрируйтесь</1></0
msgid "Done" msgid "Done"
msgstr "Готово" msgstr "Готово"
#: src/views/card/components/AttachmentThumbnails.tsx:141 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "Download failed" msgid "Download failed"
msgstr "Не удалось загрузить" msgstr "Не удалось загрузить"
#: src/views/board/components/Filters.tsx:171
#: src/views/board/components/NewCardForm.tsx:469
#: src/views/card/index.tsx:139
msgid "Due date"
msgstr "Дата выполнения"
#: src/views/board/components/Filters.tsx:132
msgid "Due next month"
msgstr "Срок в следующем месяце"
#: src/views/board/components/Filters.tsx:127
msgid "Due next week"
msgstr "Срок на следующей неделе"
#: src/views/board/components/Filters.tsx:117
msgid "Due today"
msgstr "Срок сегодня"
#: src/views/board/components/Filters.tsx:122
msgid "Due tomorrow"
msgstr "Срок завтра"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:116 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Изменить URL доски" msgstr "Изменить URL доски"
#: src/views/card/components/Comment.tsx:82 #: src/views/card/components/Comment.tsx:83
msgid "Edit comment" msgid "Edit comment"
msgstr "Редактировать комментарий" msgstr "Редактировать комментарий"
@@ -946,8 +986,8 @@ msgstr "Не удалось создать доску"
msgid "Failed to login with {0}. Please try again." msgid "Failed to login with {0}. Please try again."
msgstr "Не удалось войти с {0}. Пожалуйста, попробуйте снова." msgstr "Не удалось войти с {0}. Пожалуйста, попробуйте снова."
#: src/views/card/components/AttachmentUpload.tsx:33 #: src/views/card/components/AttachmentUpload.tsx:34
#: src/views/card/components/AttachmentUpload.tsx:79 #: src/views/card/components/AttachmentUpload.tsx:80
msgid "Failed to upload attachment. Please try again." msgid "Failed to upload attachment. Please try again."
msgstr "Не удалось загрузить вложение. Пожалуйста, попробуйте еще раз." msgstr "Не удалось загрузить вложение. Пожалуйста, попробуйте еще раз."
@@ -994,7 +1034,7 @@ msgstr "Обратная связь"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Обратная связь отправлена" msgstr "Обратная связь отправлена"
#: src/views/board/components/Filters.tsx:174 #: src/views/board/components/Filters.tsx:221
msgid "Filter" msgid "Filter"
msgstr "Фильтр" msgstr "Фильтр"
@@ -1031,7 +1071,7 @@ msgstr "Веселье"
#: src/providers/keyboard-shortcuts.tsx:53 #: src/providers/keyboard-shortcuts.tsx:53
msgid "General" msgid "General"
msgstr "Общие" msgstr "Общее"
#: src/views/auth/signup/index.tsx:69 #: src/views/auth/signup/index.tsx:69
#: src/views/home/components/Cta.tsx:61 #: src/views/home/components/Cta.tsx:61
@@ -1052,7 +1092,7 @@ msgstr "Начать"
msgid "Get started by creating a new {0}" msgid "Get started by creating a new {0}"
msgstr "Начните с создания нового {0}" msgstr "Начните с создания нового {0}"
#: src/views/board/index.tsx:483 #: src/views/board/index.tsx:491
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Начните с создания нового списка" msgstr "Начните с создания нового списка"
@@ -1239,7 +1279,7 @@ msgstr "Ссылки-приглашения"
msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace." msgid "Invite links require a Team or Pro subscription. Please upgrade your workspace."
msgstr "Ссылки для приглашений требуют подписки Team или Pro. Пожалуйста, обновите ваше рабочее пространство." msgstr "Ссылки для приглашений требуют подписки Team или Pro. Пожалуйста, обновите ваше рабочее пространство."
#: src/views/card/components/MemberSelector.tsx:111 #: src/views/card/components/MemberSelector.tsx:112
#: src/views/members/components/InviteMemberForm.tsx:367 #: src/views/members/components/InviteMemberForm.tsx:367
msgid "Invite member" msgid "Invite member"
msgstr "Пригласить участника" msgstr "Пригласить участника"
@@ -1286,9 +1326,9 @@ msgstr "Имейте в виду, что это действие необрат
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "Горячие клавиши" msgstr "Горячие клавиши"
#: src/views/board/components/Filters.tsx:115 #: src/views/board/components/Filters.tsx:155
#: src/views/board/components/NewCardForm.tsx:409 #: src/views/board/components/NewCardForm.tsx:418
#: src/views/card/index.tsx:119 #: src/views/card/index.tsx:121
msgid "Labels" msgid "Labels"
msgstr "Метки" msgstr "Метки"
@@ -1338,11 +1378,11 @@ msgstr "Лицензия"
msgid "Light" msgid "Light"
msgstr "Светлый" msgstr "Светлый"
#: src/views/public/board/index.tsx:66 #: src/views/public/board/index.tsx:78
msgid "Link copied" msgid "Link copied"
msgstr "Ссылка скопирована" msgstr "Ссылка скопирована"
#: src/views/card/index.tsx:111 #: src/views/card/index.tsx:113
msgid "List" msgid "List"
msgstr "Список" msgstr "Список"
@@ -1350,10 +1390,18 @@ msgstr "Список"
msgid "List name" msgid "List name"
msgstr "Название списка" msgstr "Название списка"
#: src/views/board/components/Filters.tsx:123 #: src/views/board/components/Filters.tsx:163
msgid "Lists" msgid "Lists"
msgstr "Списки" msgstr "Списки"
#: src/views/card/components/ActivityList.tsx:530
msgid "Load more activities"
msgstr "Загрузить больше действий"
#: src/views/card/components/ActivityList.tsx:530
msgid "Loading..."
msgstr "Загрузка..."
#: src/views/auth/login/index.tsx:33 #: src/views/auth/login/index.tsx:33
msgid "Login | kan.bn" msgid "Login | kan.bn"
msgstr "Вход | kan.bn" msgstr "Вход | kan.bn"
@@ -1382,12 +1430,12 @@ msgstr "магическая ссылка"
msgid "Make template" msgid "Make template"
msgstr "Создать шаблон" msgstr "Создать шаблон"
#: src/views/card/components/ActivityList.tsx:75 #: src/views/card/components/ActivityList.tsx:113
msgid "marked a checklist item as incomplete" msgid "marked a checklist item as incomplete"
msgstr "отметил элемент контрольного списка как незавершённый" msgstr "отметил элемент контрольного списка как незавершённый"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:196 #: src/views/card/components/ActivityList.tsx:231
msgid "marked checklist item <0>{0}</0> as incomplete" msgid "marked checklist item <0>{0}</0> as incomplete"
msgstr "отметил элемент контрольного списка <0>{0}</0> как незавершённый" msgstr "отметил элемент контрольного списка <0>{0}</0> как незавершённый"
@@ -1396,9 +1444,9 @@ msgid "Medium Priority"
msgstr "Средний приоритет" msgstr "Средний приоритет"
#: src/components/SideNavigation.tsx:121 #: src/components/SideNavigation.tsx:121
#: src/views/board/components/Filters.tsx:107 #: src/views/board/components/Filters.tsx:147
#: src/views/board/components/NewCardForm.tsx:367 #: src/views/board/components/NewCardForm.tsx:376
#: src/views/card/index.tsx:128 #: src/views/card/index.tsx:130
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Участники" msgstr "Участники"
@@ -1419,11 +1467,11 @@ msgstr "ежемесячная оплата"
#. placeholder {0}: truncate(fromList) #. placeholder {0}: truncate(fromList)
#. placeholder {1}: truncate(toList) #. placeholder {1}: truncate(toList)
#: src/views/card/components/ActivityList.tsx:98 #: src/views/card/components/ActivityList.tsx:133
msgid "moved the card from <0>{0}</0> to<1>{1}</1>" msgid "moved the card from <0>{0}</0> to<1>{1}</1>"
msgstr "переместил карточку из <0>{0}</0> в <1>{1}</1>" msgstr "переместил карточку из <0>{0}</0> в <1>{1}</1>"
#: src/views/card/components/ActivityList.tsx:64 #: src/views/card/components/ActivityList.tsx:102
msgid "moved the card to another list" msgid "moved the card to another list"
msgstr "переместил карточку в другой список" msgstr "переместил карточку в другой список"
@@ -1455,11 +1503,11 @@ msgstr "Новый {0}"
msgid "New API key" msgid "New API key"
msgstr "Новый API-ключ" msgstr "Новый API-ключ"
#: src/views/board/components/NewCardForm.tsx:293 #: src/views/board/components/NewCardForm.tsx:302
msgid "New card" msgid "New card"
msgstr "Новая карточка" msgstr "Новая карточка"
#: src/views/card/components/NewChecklistForm.tsx:102 #: src/views/card/components/NewChecklistForm.tsx:103
msgid "New checklist" msgid "New checklist"
msgstr "Новый контрольный список" msgstr "Новый контрольный список"
@@ -1472,7 +1520,7 @@ msgid "New label"
msgstr "Новая метка" msgstr "Новая метка"
#: src/views/board/components/NewListForm.tsx:113 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:454 #: src/views/board/index.tsx:462
msgid "New list" msgid "New list"
msgstr "Новый список" msgstr "Новый список"
@@ -1521,7 +1569,11 @@ msgstr "Доски не найдены"
msgid "No credit card required" msgid "No credit card required"
msgstr "Кредитная карта не требуется" msgstr "Кредитная карта не требуется"
#: src/views/card/components/AttachmentThumbnails.tsx:142 #: src/views/board/components/Filters.tsx:137
msgid "No dates"
msgstr "Нет дат"
#: src/views/card/components/AttachmentThumbnails.tsx:143
msgid "No download URL available for this attachment." msgid "No download URL available for this attachment."
msgstr "URL для загрузки этого вложения недоступен." msgstr "URL для загрузки этого вложения недоступен."
@@ -1529,7 +1581,7 @@ msgstr "URL для загрузки этого вложения недоступ
msgid "No keyboard shortcuts registered." msgid "No keyboard shortcuts registered."
msgstr "Горячие клавиши не зарегистрированы." msgstr "Горячие клавиши не зарегистрированы."
#: src/views/board/index.tsx:480 #: src/views/board/index.tsx:488
msgid "No lists" msgid "No lists"
msgstr "Нет списков" msgstr "Нет списков"
@@ -1582,6 +1634,10 @@ msgstr "Организуйте и находите карточки быстро
msgid "OSS Friends" msgid "OSS Friends"
msgstr "Друзья OSS" msgstr "Друзья OSS"
#: src/views/board/components/Filters.tsx:112
msgid "Overdue"
msgstr "Просрочено"
#: src/views/pricing/components/Pricing.tsx:73 #: src/views/pricing/components/Pricing.tsx:73
#: src/views/pricing/components/PricingTiers.tsx:70 #: src/views/pricing/components/PricingTiers.tsx:70
msgid "Own your data" msgid "Own your data"
@@ -1670,30 +1726,33 @@ msgstr "Пожалуйста, выберите файл для загрузки.
#: src/components/DeleteLabelConfirmation.tsx:26 #: src/components/DeleteLabelConfirmation.tsx:26
#: src/components/FeedbackModal.tsx:41 #: src/components/FeedbackModal.tsx:41
#: src/components/NewWorkspaceForm.tsx:158 #: src/components/NewWorkspaceForm.tsx:158
#: src/views/board/components/NewCardForm.tsx:177 #: src/views/board/components/NewCardForm.tsx:184
#: src/views/board/components/NewListForm.tsx:79 #: src/views/board/components/NewListForm.tsx:79
#: src/views/board/components/NewTemplateForm.tsx:61 #: src/views/board/components/NewTemplateForm.tsx:61
#: src/views/board/components/NewTemplateForm.tsx:77 #: src/views/board/components/NewTemplateForm.tsx:77
#: src/views/board/components/UpdateBoardSlugForm.tsx:73 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:54 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:162 #: src/views/board/index.tsx:170
#: src/views/board/index.tsx:218 #: src/views/board/index.tsx:226
#: src/views/boards/components/ImportBoardsForm.tsx:205 #: src/views/boards/components/ImportBoardsForm.tsx:205
#: src/views/card/components/AttachmentThumbnails.tsx:73 #: src/views/card/components/AttachmentThumbnails.tsx:74
#: src/views/card/components/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:67
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:95
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:47
#: src/views/card/components/Comment.tsx:64 #: src/views/card/components/Checklists.tsx:81
#: src/views/card/components/Comment.tsx:65
#: src/views/card/components/DeleteCardConfirmation.tsx:52 #: src/views/card/components/DeleteCardConfirmation.tsx:52
#: src/views/card/components/DeleteChecklistConfirmation.tsx:37 #: src/views/card/components/DeleteChecklistConfirmation.tsx:38
#: src/views/card/components/DeleteCommentConfirmation.tsx:45 #: src/views/card/components/DeleteCommentConfirmation.tsx:46
#: src/views/card/components/LabelSelector.tsx:72 #: src/views/card/components/DueDateSelector.tsx:60
#: src/views/card/components/ListSelector.tsx:52 #: src/views/card/components/LabelSelector.tsx:73
#: src/views/card/components/MemberSelector.tsx:79 #: src/views/card/components/ListSelector.tsx:53
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/MemberSelector.tsx:80
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistForm.tsx:71
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewChecklistItemForm.tsx:90
#: src/views/card/index.tsx:177 #: src/views/card/components/NewCommentForm.tsx:32
#: src/views/card/index.tsx:187
#: src/views/card/index.tsx:200
#: src/views/members/components/DeleteMemberConfirmation.tsx:28 #: src/views/members/components/DeleteMemberConfirmation.tsx:28
#: src/views/members/components/InviteMemberForm.tsx:104 #: src/views/members/components/InviteMemberForm.tsx:104
#: src/views/members/components/InviteMemberForm.tsx:241 #: src/views/members/components/InviteMemberForm.tsx:241
@@ -1793,30 +1852,40 @@ msgstr "Удалить"
msgid "Remove member" msgid "Remove member"
msgstr "Удалить участника" msgstr "Удалить участника"
#: src/views/card/components/ActivityList.tsx:66 #. placeholder {0}: mergedLabels.length
#: src/views/card/components/ActivityList.tsx:91
msgid "removed {0} labels: <0>{labelList}</0>"
msgstr "удалил {0} метки: <0>{labelList}</0>"
#: src/views/card/components/ActivityList.tsx:104
msgid "removed a label from the card" msgid "removed a label from the card"
msgstr "удалил метку с карточки" msgstr "удалил метку с карточки"
#: src/views/card/components/ActivityList.tsx:68 #: src/views/card/components/ActivityList.tsx:106
msgid "removed a member from the card" msgid "removed a member from the card"
msgstr "удалил участника из карточки" msgstr "удалил участника из карточки"
#. placeholder {0}: truncate(label) #. placeholder {0}: truncate(label)
#: src/views/card/components/ActivityList.tsx:138 #: src/views/card/components/ActivityList.tsx:173
msgid "removed label <0>{0}</0>" msgid "removed label <0>{0}</0>"
msgstr "удалил метку <0>{0}</0>" msgstr "удалил метку <0>{0}</0>"
#: src/views/card/components/ActivityList.tsx:70 #: src/views/card/components/ActivityList.tsx:117
#: src/views/card/components/ActivityList.tsx:276
msgid "removed the due date"
msgstr "удалил(а) дату выполнения"
#: src/views/card/components/ActivityList.tsx:108
msgid "renamed a checklist" msgid "renamed a checklist"
msgstr "переименовал контрольный список" msgstr "переименовал контрольный список"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:154 #: src/views/card/components/ActivityList.tsx:189
msgid "renamed checklist <0>{0}</0>" msgid "renamed checklist <0>{0}</0>"
msgstr "переименовал контрольный список <0>{0}</0>" msgstr "переименовал контрольный список <0>{0}</0>"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:178 #: src/views/card/components/ActivityList.tsx:213
msgid "renamed checklist item to <0>{0}</0>" msgid "renamed checklist item to <0>{0}</0>"
msgstr "переименовал элемент контрольного списка в <0>{0}</0>" msgstr "переименовал элемент контрольного списка в <0>{0}</0>"
@@ -1855,7 +1924,7 @@ msgstr "Роль"
msgid "Run on your own infrastructure" msgid "Run on your own infrastructure"
msgstr "Запустите на своей инфраструктуре" msgstr "Запустите на своей инфраструктуре"
#: src/views/card/components/Comment.tsx:165 #: src/views/card/components/Comment.tsx:166
#: src/views/settings/components/Avatar.tsx:309 #: src/views/settings/components/Avatar.tsx:309
msgid "Save" msgid "Save"
msgstr "Сохранить" msgstr "Сохранить"
@@ -1893,7 +1962,7 @@ msgstr "Самостоятельный хостинг"
msgid "Self host with Github" msgid "Self host with Github"
msgstr "Самостоятельный хостинг с Github" msgstr "Самостоятельный хостинг с Github"
#: src/views/card/components/ActivityList.tsx:107 #: src/views/card/components/ActivityList.tsx:142
msgid "self-assigned the card" msgid "self-assigned the card"
msgstr "самостоятельно назначил карточку" msgstr "самостоятельно назначил карточку"
@@ -1909,6 +1978,14 @@ msgstr "Отправить отзыв"
msgid "Senior" msgid "Senior"
msgstr "Старший" msgstr "Старший"
#: src/views/card/components/DueDateSelector.tsx:117
msgid "Set due date"
msgstr "Установить дату выполнения"
#: src/views/card/components/ActivityList.tsx:115
msgid "set the due date"
msgstr "установил(а) дату выполнения"
#: src/components/SettingsLayout.tsx:82 #: src/components/SettingsLayout.tsx:82
#: src/components/SideNavigation.tsx:133 #: src/components/SideNavigation.tsx:133
msgid "Settings" msgid "Settings"
@@ -2030,8 +2107,8 @@ msgstr "Командный план"
msgid "Teams" msgid "Teams"
msgstr "Команды" msgstr "Команды"
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/board/index.tsx:409 #: src/views/board/index.tsx:417
msgid "Template" msgid "Template"
msgstr "Шаблон" msgstr "Шаблон"
@@ -2096,8 +2173,8 @@ msgstr "Они не смогут получить доступ к этому р
#: src/components/DeleteLabelConfirmation.tsx:44 #: src/components/DeleteLabelConfirmation.tsx:44
#: src/views/board/components/DeleteBoardConfirmation.tsx:39 #: src/views/board/components/DeleteBoardConfirmation.tsx:39
#: src/views/card/components/DeleteCardConfirmation.tsx:78 #: src/views/card/components/DeleteCardConfirmation.tsx:78
#: src/views/card/components/DeleteChecklistConfirmation.tsx:58 #: src/views/card/components/DeleteChecklistConfirmation.tsx:59
#: src/views/card/components/DeleteCommentConfirmation.tsx:68 #: src/views/card/components/DeleteCommentConfirmation.tsx:69
msgid "This action can't be undone." msgid "This action can't be undone."
msgstr "Это действие нельзя будет отменить." msgstr "Это действие нельзя будет отменить."
@@ -2105,7 +2182,7 @@ msgstr "Это действие нельзя будет отменить."
msgid "This API key will only be shown once. Please save it in a secure location." msgid "This API key will only be shown once. Please save it in a secure location."
msgstr "Этот API-ключ будет показан только один раз. Пожалуйста, сохраните его в безопасном месте." msgstr "Этот API-ключ будет показан только один раз. Пожалуйста, сохраните его в безопасном месте."
#: src/views/public/board/index.tsx:156 #: src/views/public/board/index.tsx:169
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "Эта доска является приватной или не существует." msgstr "Эта доска является приватной или не существует."
@@ -2167,23 +2244,27 @@ msgstr "Импорт Trello"
msgid "Triaging" msgid "Triaging"
msgstr "Сортировка" msgstr "Сортировка"
#: src/views/home/components/Logos.tsx:73 #: src/views/home/components/Logos.tsx:67
msgid "Trusted by fast-moving teams<0/>around the world" msgid "Trusted by fast-moving teams<0/>around the world"
msgstr "Доверяют динамичным командам<0/>по всему миру" msgstr "Доверяют динамичным командам<0/>по всему миру"
#: src/views/card/components/NewChecklistItemForm.tsx:88 #: src/views/card/components/NewChecklistItemForm.tsx:89
msgid "Unable to add checklist item" msgid "Unable to add checklist item"
msgstr "Не удалось добавить элемент контрольного списка." msgstr "Не удалось добавить элемент контрольного списка."
#: src/views/card/components/NewCommentForm.tsx:30 #: src/views/card/components/NewCommentForm.tsx:31
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Не удалось добавить комментарий." msgstr "Не удалось добавить комментарий."
#: src/views/board/components/NewCardForm.tsx:174 #: src/views/card/index.tsx:199
msgid "Unable to add label"
msgstr "Не удалось добавить метку"
#: src/views/board/components/NewCardForm.tsx:181
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Не удалось создать карточку." msgstr "Не удалось создать карточку."
#: src/views/card/components/NewChecklistForm.tsx:69 #: src/views/card/components/NewChecklistForm.tsx:70
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Не удалось создать контрольный список." msgstr "Не удалось создать контрольный список."
@@ -2200,7 +2281,7 @@ msgstr "Не удалось создать шаблон"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "Не удалось создать рабочее пространство." msgstr "Не удалось создать рабочее пространство."
#: src/views/card/components/AttachmentThumbnails.tsx:72 #: src/views/card/components/AttachmentThumbnails.tsx:73
msgid "Unable to delete attachment" msgid "Unable to delete attachment"
msgstr "Не удалось удалить вложение" msgstr "Не удалось удалить вложение"
@@ -2208,15 +2289,15 @@ msgstr "Не удалось удалить вложение"
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Не удалось удалить карточку." msgstr "Не удалось удалить карточку."
#: src/views/card/components/DeleteChecklistConfirmation.tsx:36 #: src/views/card/components/DeleteChecklistConfirmation.tsx:37
msgid "Unable to delete checklist" msgid "Unable to delete checklist"
msgstr "Не удалось удалить контрольный список" msgstr "Не удалось удалить контрольный список"
#: src/views/card/components/ChecklistItemRow.tsx:87 #: src/views/card/components/ChecklistItemRow.tsx:94
msgid "Unable to delete checklist item" msgid "Unable to delete checklist item"
msgstr "Не удалось удалить элемент контрольного списка" msgstr "Не удалось удалить элемент контрольного списка"
#: src/views/card/components/DeleteCommentConfirmation.tsx:44 #: src/views/card/components/DeleteCommentConfirmation.tsx:45
msgid "Unable to delete comment" msgid "Unable to delete comment"
msgstr "Не удалось удалить комментарий" msgstr "Не удалось удалить комментарий"
@@ -2224,6 +2305,10 @@ msgstr "Не удалось удалить комментарий"
msgid "Unable to remove member" msgid "Unable to remove member"
msgstr "Не удалось удалить участника" msgstr "Не удалось удалить участника"
#: src/views/card/components/Checklists.tsx:80
msgid "Unable to reorder checklist item"
msgstr "Не удалось изменить порядок элемента контрольного списка"
#: src/components/FeedbackModal.tsx:40 #: src/components/FeedbackModal.tsx:40
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Не удалось отправить отзыв" msgstr "Не удалось отправить отзыв"
@@ -2236,42 +2321,46 @@ msgstr "Не удалось обновить URL доски"
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Не удалось обновить видимость доски" msgstr "Не удалось обновить видимость доски"
#: src/views/board/index.tsx:217 #: src/views/board/index.tsx:225
#: src/views/card/index.tsx:176 #: src/views/card/index.tsx:186
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Не удалось обновить карточку" msgstr "Не удалось обновить карточку"
#: src/views/card/components/ChecklistNameInput.tsx:45 #: src/views/card/components/ChecklistNameInput.tsx:46
msgid "Unable to update checklist" msgid "Unable to update checklist"
msgstr "Не удалось обновить контрольный список" msgstr "Не удалось обновить контрольный список"
#: src/views/card/components/ChecklistItemRow.tsx:59 #: src/views/card/components/ChecklistItemRow.tsx:66
msgid "Unable to update checklist item" msgid "Unable to update checklist item"
msgstr "Не удалось обновить элемент контрольного списка" msgstr "Не удалось обновить элемент контрольного списка"
#: src/views/card/components/Comment.tsx:63 #: src/views/card/components/Comment.tsx:64
msgid "Unable to update comment" msgid "Unable to update comment"
msgstr "Не удалось обновить комментарий" msgstr "Не удалось обновить комментарий"
#: src/views/card/components/LabelSelector.tsx:71 #: src/views/card/components/DueDateSelector.tsx:59
msgid "Unable to update due date"
msgstr "Не удалось обновить дату выполнения"
#: src/views/card/components/LabelSelector.tsx:72
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "Не удалось обновить метки" msgstr "Не удалось обновить метки"
#: src/views/board/index.tsx:161 #: src/views/board/index.tsx:169
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:52
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Не удалось обновить список" msgstr "Не удалось обновить список"
#: src/views/card/components/MemberSelector.tsx:78 #: src/views/card/components/MemberSelector.tsx:79
msgid "Unable to update members" msgid "Unable to update members"
msgstr "Не удалось обновить участников" msgstr "Не удалось обновить участников"
#. placeholder {0}: truncate(memberName) #. placeholder {0}: truncate(memberName)
#: src/views/card/components/ActivityList.tsx:121 #: src/views/card/components/ActivityList.tsx:156
msgid "unassigned <0>{0}</0> from the card" msgid "unassigned <0>{0}</0> from the card"
msgstr "удалил(а) <0>{0}</0> из карточки" msgstr "удалил(а) <0>{0}</0> из карточки"
#: src/views/card/components/ActivityList.tsx:118 #: src/views/card/components/ActivityList.tsx:153
msgid "unassigned themselves from the card" msgid "unassigned themselves from the card"
msgstr "удалил(а) себя из карточки" msgstr "удалил(а) себя из карточки"
@@ -2313,6 +2402,11 @@ msgstr "Неограниченное количество участников"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Неограниченное количество рабочих пространств" 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/board/components/UpdateBoardSlugForm.tsx:175
#: src/views/settings/components/UpdateDisplayNameForm.tsx:80 #: src/views/settings/components/UpdateDisplayNameForm.tsx:80
#: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:91
@@ -2325,20 +2419,24 @@ msgstr "Обновить"
msgid "Update label" msgid "Update label"
msgstr "Обновить метку" msgstr "Обновить метку"
#: src/views/card/components/ActivityList.tsx:73 #: src/views/card/components/ActivityList.tsx:111
msgid "updated a checklist item" msgid "updated a checklist item"
msgstr "обновлен элемент контрольного списка" msgstr "обновлен элемент контрольного списка"
#: src/views/card/components/ActivityList.tsx:63 #: src/views/card/components/ActivityList.tsx:101
msgid "updated the description" msgid "updated the description"
msgstr "обновлено описание" msgstr "обновлено описание"
#: src/views/card/components/ActivityList.tsx:62 #: src/views/card/components/ActivityList.tsx:116
msgid "updated the due date"
msgstr "обновил(а) дату выполнения"
#: src/views/card/components/ActivityList.tsx:100
msgid "updated the title" msgid "updated the title"
msgstr "обновлен заголовок" msgstr "обновлен заголовок"
#. placeholder {0}: truncate(toTitle) #. placeholder {0}: truncate(toTitle)
#: src/views/card/components/ActivityList.tsx:90 #: src/views/card/components/ActivityList.tsx:125
msgid "updated the title to <0>{0}</0>" msgid "updated the title to <0>{0}</0>"
msgstr "обновлен заголовок на <0>{0}</0>" msgstr "обновлен заголовок на <0>{0}</0>"
@@ -2352,8 +2450,8 @@ msgstr "Обновить до Pro"
msgid "Upgrade to Pro ($29/month)" msgid "Upgrade to Pro ($29/month)"
msgstr "Обновить до Pro ($29/месяц)" msgstr "Обновить до Pro ($29/месяц)"
#: src/views/card/components/AttachmentUpload.tsx:32 #: src/views/card/components/AttachmentUpload.tsx:33
#: src/views/card/components/AttachmentUpload.tsx:78 #: src/views/card/components/AttachmentUpload.tsx:79
msgid "Upload failed" msgid "Upload failed"
msgstr "Не удалось загрузить" msgstr "Не удалось загрузить"
@@ -2406,7 +2504,7 @@ msgstr "Просмотр и управление вашими счетами и
msgid "View docs" msgid "View docs"
msgstr "Просмотреть документацию" msgstr "Просмотреть документацию"
#: src/views/public/board/index.tsx:129 #: src/views/public/board/index.tsx:142
msgid "View only" msgid "View only"
msgstr "Только просмотр" msgstr "Только просмотр"
@@ -2414,7 +2512,7 @@ msgstr "Только просмотр"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "Просмотреть нашу дорожную карту." msgstr "Просмотреть нашу дорожную карту."
#: src/views/public/board/index.tsx:159 #: src/views/public/board/index.tsx:172
msgid "View workspace" msgid "View workspace"
msgstr "Просмотреть рабочее пространство" msgstr "Просмотреть рабочее пространство"
@@ -2426,6 +2524,10 @@ msgstr "Видимость"
msgid "We are using the <0>AGPL-3.0 license</0>." msgid "We are using the <0>AGPL-3.0 license</0>."
msgstr "Мы используем лицензию <0>AGPL-3.0</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 #: src/views/home/components/Features.tsx:152
msgid "We're just getting started. " msgid "We're just getting started. "
msgstr "Мы только начинаем. " msgstr "Мы только начинаем. "
@@ -2455,10 +2557,10 @@ msgid "Why make an open source Trello?"
msgstr "Зачем создавать Trello с открытым исходным кодом?" msgstr "Зачем создавать Trello с открытым исходным кодом?"
#: src/components/SettingsLayout.tsx:39 #: src/components/SettingsLayout.tsx:39
#: src/views/board/index.tsx:374 #: src/views/board/index.tsx:382
#: src/views/boards/index.tsx:33 #: src/views/boards/index.tsx:33
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:101 #: src/views/public/board/index.tsx:114
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Рабочее пространство" msgstr "Рабочее пространство"
@@ -2564,6 +2666,10 @@ msgstr "Вы успешно вошли в систему."
msgid "You have been signed up successfully." msgid "You have been signed up successfully."
msgstr "Вы успешно зарегистрировались." msgstr "Вы успешно зарегистрировались."
#: src/pages/unsubscribe/index.tsx:98
msgid "You have been unsubscribed!"
msgstr "Вы успешно отписались!"
#: src/views/members/components/InviteMemberForm.tsx:326 #: src/views/members/components/InviteMemberForm.tsx:326
msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!" msgid "You have unlimited seats with your Pro Plan. There is no additional charge for new members!"
msgstr "В вашем профессиональном плане неограниченное количество мест. За новых участников дополнительная плата не взимается!" msgstr "В вашем профессиональном плане неограниченное количество мест. За новых участников дополнительная плата не взимается!"
@@ -2588,7 +2694,7 @@ msgstr "Ваши доски были импортированы."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Ваше отображаемое имя было обновлено." msgstr "Ваше отображаемое имя было обновлено."
#: src/views/card/components/AttachmentUpload.tsx:26 #: src/views/card/components/AttachmentUpload.tsx:27
msgid "Your file has been uploaded successfully." msgid "Your file has been uploaded successfully."
msgstr "Ваш файл успешно загружен." msgstr "Ваш файл успешно загружен."
@@ -2608,6 +2714,10 @@ msgstr "Ваш аккаунт Trello был отключён."
msgid "Your Trello account is connected." msgid "Your Trello account is connected."
msgstr "Ваш аккаунт Trello подключён." 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 #: src/views/settings/components/UpdateWorkspaceDescriptionForm.tsx:49
msgid "Your workspace description has been updated." msgid "Your workspace description has been updated."
msgstr "Описание вашего рабочего пространства было обновлено." msgstr "Описание вашего рабочего пространства было обновлено."

File diff suppressed because one or more lines are too long

View File

@@ -12,6 +12,7 @@ import posthog from "posthog-js";
import { PostHogProvider } from "posthog-js/react"; import { PostHogProvider } from "posthog-js/react";
import { useEffect } from "react"; import { useEffect } from "react";
import { KeyboardShortcutProvider } from "~/providers/keyboard-shortcuts";
import { LinguiProviderWrapper } from "~/providers/lingui"; import { LinguiProviderWrapper } from "~/providers/lingui";
import { ModalProvider } from "~/providers/modal"; import { ModalProvider } from "~/providers/modal";
import { PopupProvider } from "~/providers/popup"; import { PopupProvider } from "~/providers/popup";
@@ -80,21 +81,23 @@ const MyApp: AppType = ({ Component, pageProps }: AppPropsWithLayout) => {
)} )}
<script src="/__ENV.js" /> <script src="/__ENV.js" />
<main className="font-sans"> <main className="font-sans">
<LinguiProviderWrapper> <KeyboardShortcutProvider>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem> <LinguiProviderWrapper>
<ModalProvider> <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<PopupProvider> <ModalProvider>
{posthogKey ? ( <PopupProvider>
<PostHogProvider client={posthog}> {posthogKey ? (
{getLayout(<Component {...pageProps} />)} <PostHogProvider client={posthog}>
</PostHogProvider> {getLayout(<Component {...pageProps} />)}
) : ( </PostHogProvider>
getLayout(<Component {...pageProps} />) ) : (
)} getLayout(<Component {...pageProps} />)
</PopupProvider> )}
</ModalProvider> </PopupProvider>
</ThemeProvider> </ModalProvider>
</LinguiProviderWrapper> </ThemeProvider>
</LinguiProviderWrapper>
</KeyboardShortcutProvider>
</main> </main>
</> </>
); );

View File

@@ -17,12 +17,11 @@ export default async function handler(
} }
try { try {
const downloadUrl = decodeURIComponent(url); const downloadFilename = typeof filename === "string"
const downloadFilename = ? encodeURIComponent(filename)
(typeof filename === "string" ? decodeURIComponent(filename) : null) ?? : "attachment";
"attachment";
const upstream = await fetch(downloadUrl); const upstream = await fetch(url);
if (!upstream.ok) { if (!upstream.ok) {
return res.status(upstream.status).json({ return res.status(upstream.status).json({
@@ -36,7 +35,7 @@ export default async function handler(
res.setHeader("Content-Type", contentType); res.setHeader("Content-Type", contentType);
res.setHeader( res.setHeader(
"Content-Disposition", "Content-Disposition",
`attachment; filename="${downloadFilename}"`, `attachment; filename="${downloadFilename}"; filename*=UTF-8''${downloadFilename}`,
); );
const buffer = await upstream.arrayBuffer(); const buffer = await upstream.arrayBuffer();

View File

@@ -88,6 +88,7 @@ export default async function handler(
const session = await stripe.checkout.sessions.create({ const session = await stripe.checkout.sessions.create({
mode: "subscription", mode: "subscription",
payment_method_collection: "always",
line_items: [ line_items: [
{ {
price: process.env.STRIPE_PRO_PLAN_MONTHLY_PRICE_ID, price: process.env.STRIPE_PRO_PLAN_MONTHLY_PRICE_ID,

View 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 });
}

View File

@@ -43,18 +43,22 @@ export default async function handler(
return res.status(400).json({ error: "Invalid content type" }); return res.status(400).json({ error: "Invalid content type" });
} }
const credentials =
env.S3_ACCESS_KEY_ID && env.S3_SECRET_ACCESS_KEY
? {
accessKeyId: env.S3_ACCESS_KEY_ID,
secretAccessKey: env.S3_SECRET_ACCESS_KEY,
}
: undefined;
const client = new S3Client({ const client = new S3Client({
region: env.S3_REGION ?? "", region: env.S3_REGION ?? "",
endpoint: env.S3_ENDPOINT ?? "", endpoint: env.S3_ENDPOINT ?? "",
forcePathStyle: env.S3_FORCE_PATH_STYLE === "true", forcePathStyle: env.S3_FORCE_PATH_STYLE === "true",
credentials: { credentials,
accessKeyId: env.S3_ACCESS_KEY_ID ?? "",
secretAccessKey: env.S3_SECRET_ACCESS_KEY ?? "",
},
}); });
const signedUrl = await getSignedUrl( const signedUrl = await getSignedUrl(
// @ts-ignore
client, client,
new PutObjectCommand({ new PutObjectCommand({
Bucket: nextRuntimeEnv("NEXT_PUBLIC_AVATAR_BUCKET_NAME") ?? "", Bucket: nextRuntimeEnv("NEXT_PUBLIC_AVATAR_BUCKET_NAME") ?? "",

View 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>
</>
);
}

View 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];
}
}

View File

@@ -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;
}

View File

@@ -0,0 +1,16 @@
import type { api } from "~/utils/api";
/**
* Invalidates all card-related queries for a given card.
* Use this after any mutation that affects card data or activities.
*/
export async function invalidateCard(
utils: ReturnType<typeof api.useUtils>,
cardPublicId: string,
) {
await Promise.all([
utils.card.byId.invalidate({ cardPublicId }),
utils.card.getActivities.invalidate({ cardPublicId }),
]);
}

View File

@@ -22,6 +22,8 @@ const loadMessages = async (locale: Locale) => {
return (await import("~/locales/ru/messages")).messages; return (await import("~/locales/ru/messages")).messages;
case "pl": case "pl":
return (await import("~/locales/pl/messages")).messages; return (await import("~/locales/pl/messages")).messages;
case "ptbr":
return (await import("~/locales/ptbr/messages")).messages;
default: default:
return enMessages; return enMessages;
} }

View File

@@ -1,10 +1,17 @@
import { format, isBefore, isSameYear, startOfDay } from "date-fns";
import { HiOutlinePaperClip } from "react-icons/hi"; import { HiOutlinePaperClip } from "react-icons/hi";
import { HiBars3BottomLeft, HiChatBubbleLeft } from "react-icons/hi2"; import {
HiBars3BottomLeft,
HiChatBubbleLeft,
HiOutlineClock,
} from "react-icons/hi2";
import { twMerge } from "tailwind-merge";
import Avatar from "~/components/Avatar"; import Avatar from "~/components/Avatar";
import Badge from "~/components/Badge"; import Badge from "~/components/Badge";
import CircularProgress from "~/components/CircularProgress"; import CircularProgress from "~/components/CircularProgress";
import LabelIcon from "~/components/LabelIcon"; import LabelIcon from "~/components/LabelIcon";
import { useLocalisation } from "~/hooks/useLocalisation";
import { getAvatarUrl } from "~/utils/helpers"; import { getAvatarUrl } from "~/utils/helpers";
const Card = ({ const Card = ({
@@ -15,6 +22,7 @@ const Card = ({
description, description,
comments, comments,
attachments, attachments,
dueDate,
}: { }: {
title: string; title: string;
labels: { name: string; colourCode: string | null }[]; labels: { name: string; colourCode: string | null }[];
@@ -36,7 +44,11 @@ const Card = ({
description: string | null; description: string | null;
comments: { publicId: string }[]; comments: { publicId: string }[];
attachments?: { publicId: string }[]; attachments?: { publicId: string }[];
dueDate?: Date | null;
}) => { }) => {
const { dateLocale } = useLocalisation();
const showYear = dueDate ? !isSameYear(dueDate, new Date()) : false;
const isOverdue = dueDate ? isBefore(dueDate, startOfDay(new Date())) : false;
const completedItems = checklists.reduce((acc, checklist) => { const completedItems = checklists.reduce((acc, checklist) => {
return acc + checklist.items.filter((item) => item.completed).length; return acc + checklist.items.filter((item) => item.completed).length;
}, 0); }, 0);
@@ -51,6 +63,7 @@ const Card = ({
const hasDescription = const hasDescription =
description && description.replace(/<[^>]*>/g, "").trim().length > 0; description && description.replace(/<[^>]*>/g, "").trim().length > 0;
const hasAttachments = attachments && attachments.length > 0; const hasAttachments = attachments && attachments.length > 0;
const hasDueDate = !!dueDate;
return ( return (
<div className="flex flex-col rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-200 dark:text-dark-1000 dark:hover:bg-dark-300"> <div className="flex flex-col rounded-md border border-light-200 bg-light-50 px-3 py-2 text-sm text-neutral-900 dark:border-dark-200 dark:bg-dark-200 dark:text-dark-1000 dark:hover:bg-dark-300">
@@ -60,6 +73,7 @@ const Card = ({
checklists.length > 0 || checklists.length > 0 ||
hasDescription || hasDescription ||
comments.length > 0 || comments.length > 0 ||
hasDueDate ||
hasAttachments ? ( hasAttachments ? (
<div className="mt-2 flex flex-col justify-end"> <div className="mt-2 flex flex-col justify-end">
<div className="space-x-0.5"> <div className="space-x-0.5">
@@ -77,6 +91,23 @@ const Card = ({
<HiBars3BottomLeft className="h-4 w-4" /> <HiBars3BottomLeft className="h-4 w-4" />
</div> </div>
)} )}
{hasDueDate && dueDate && (
<div
className={twMerge(
"flex items-center gap-1",
isOverdue
? "text-red-600 dark:text-red-400"
: "text-light-800 dark:text-dark-800",
)}
>
<HiOutlineClock className="h-4 w-4" />
<span className="text-[11px]">
{format(dueDate, showYear ? "do MMM yyyy" : "do MMM", {
locale: dateLocale,
})}
</span>
</div>
)}
{comments.length > 0 && ( {comments.length > 0 && (
<div className="flex items-center gap-1 text-light-700 dark:text-dark-800"> <div className="flex items-center gap-1 text-light-700 dark:text-dark-800">
<HiChatBubbleLeft className="h-4 w-4" /> <HiChatBubbleLeft className="h-4 w-4" />

View File

@@ -2,6 +2,7 @@ import { useRouter } from "next/router";
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import { import {
HiMiniXMark, HiMiniXMark,
HiOutlineClock,
HiOutlineSquare3Stack3D, HiOutlineSquare3Stack3D,
HiOutlineTag, HiOutlineTag,
HiOutlineUserCircle, HiOutlineUserCircle,
@@ -60,7 +61,13 @@ const Filters = ({
try { try {
await router.push({ await router.push({
pathname: router.pathname, pathname: router.pathname,
query: { ...router.query, members: [], labels: [], lists: [] }, query: {
...router.query,
members: [],
labels: [],
lists: [],
dueDate: [],
},
}); });
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@@ -99,6 +106,39 @@ const Filters = ({
selected: !!router.query.lists?.includes(list.publicId), selected: !!router.query.lists?.includes(list.publicId),
})); }));
const dueDateItems = [
{
key: "overdue",
value: t`Overdue`,
selected: !!router.query.dueDate?.includes("overdue"),
},
{
key: "today",
value: t`Due today`,
selected: !!router.query.dueDate?.includes("today"),
},
{
key: "tomorrow",
value: t`Due tomorrow`,
selected: !!router.query.dueDate?.includes("tomorrow"),
},
{
key: "next-week",
value: t`Due next week`,
selected: !!router.query.dueDate?.includes("next-week"),
},
{
key: "next-month",
value: t`Due next month`,
selected: !!router.query.dueDate?.includes("next-month"),
},
{
key: "no-due-date",
value: t`No dates`,
selected: !!router.query.dueDate?.includes("no-due-date"),
},
];
const groups = [ const groups = [
...(formattedMembers.length ...(formattedMembers.length
? [ ? [
@@ -126,6 +166,12 @@ const Filters = ({
}, },
] ]
: []), : []),
{
key: "dueDate",
label: t`Due date`,
icon: <HiOutlineClock size={16} />,
items: dueDateItems,
},
]; ];
const handleSelect = async ( const handleSelect = async (
@@ -156,6 +202,7 @@ const Filters = ({
...formatToArray(router.query.members), ...formatToArray(router.query.members),
...formatToArray(router.query.labels), ...formatToArray(router.query.labels),
...formatToArray(router.query.lists), ...formatToArray(router.query.lists),
...formatToArray(router.query.dueDate),
].length; ].length;
return ( return (

View File

@@ -1,6 +1,7 @@
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro"; import { Trans } from "@lingui/react/macro";
import { useEffect } from "react"; import { format } from "date-fns";
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { import {
HiOutlineBarsArrowDown, HiOutlineBarsArrowDown,
@@ -15,6 +16,7 @@ import type { WorkspaceMember } from "~/components/Editor";
import Avatar from "~/components/Avatar"; import Avatar from "~/components/Avatar";
import Button from "~/components/Button"; import Button from "~/components/Button";
import CheckboxDropdown from "~/components/CheckboxDropdown"; import CheckboxDropdown from "~/components/CheckboxDropdown";
import DateSelector from "~/components/DateSelector";
import Editor from "~/components/Editor"; import Editor from "~/components/Editor";
import Input from "~/components/Input"; import Input from "~/components/Input";
import LabelIcon from "~/components/LabelIcon"; import LabelIcon from "~/components/LabelIcon";
@@ -27,6 +29,7 @@ import { formatMemberDisplayName, getAvatarUrl } from "~/utils/helpers";
type NewCardFormInput = NewCardInput & { type NewCardFormInput = NewCardInput & {
isCreateAnotherEnabled: boolean; isCreateAnotherEnabled: boolean;
dueDate?: Date | null;
}; };
interface QueryParams { interface QueryParams {
@@ -65,6 +68,7 @@ export function NewCardForm({
memberPublicIds: [], memberPublicIds: [],
isCreateAnotherEnabled: false, isCreateAnotherEnabled: false,
position: "start", position: "start",
dueDate: null,
}, },
resetOnClose: true, resetOnClose: true,
}); });
@@ -80,6 +84,8 @@ export function NewCardForm({
const position = watch("position"); const position = watch("position");
const title = watch("title"); const title = watch("title");
const description = watch("description"); const description = watch("description");
const dueDate = watch("dueDate");
const [isDateSelectorOpen, setIsDateSelectorOpen] = useState(false);
// saving form state whenever form values change // saving form state whenever form values change
useEffect(() => { useEffect(() => {
@@ -137,6 +143,7 @@ export function NewCardForm({
title: args.title, title: args.title,
listId: 2, listId: 2,
description: "", description: "",
dueDate: args.dueDate ?? null,
labels: oldBoard.labels.filter((label) => labels: oldBoard.labels.filter((label) =>
args.labelPublicIds.includes(label.publicId), args.labelPublicIds.includes(label.publicId),
), ),
@@ -193,6 +200,7 @@ export function NewCardForm({
memberPublicIds: [], memberPublicIds: [],
isCreateAnotherEnabled, isCreateAnotherEnabled,
position, position,
dueDate: null,
}; };
reset(newFormState); reset(newFormState);
saveFormState(newFormState); saveFormState(newFormState);
@@ -242,7 +250,7 @@ export function NewCardForm({
), ),
})) ?? []; })) ?? [];
const onSubmit = (data: NewCardInput) => { const onSubmit = (data: NewCardFormInput) => {
createCard.mutate({ createCard.mutate({
title: data.title, title: data.title,
description: data.description, description: data.description,
@@ -250,6 +258,7 @@ export function NewCardForm({
labelPublicIds: data.labelPublicIds, labelPublicIds: data.labelPublicIds,
memberPublicIds: data.memberPublicIds, memberPublicIds: data.memberPublicIds,
position: data.position, position: data.position,
dueDate: data.dueDate ?? null,
}); });
}; };
@@ -448,6 +457,44 @@ export function NewCardForm({
</div> </div>
</CheckboxDropdown> </CheckboxDropdown>
</div> </div>
<div className="relative w-fit">
<button
type="button"
onClick={() => setIsDateSelectorOpen(!isDateSelectorOpen)}
className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-600 bg-light-200 px-2 py-1 text-left text-xs text-light-800 hover:bg-light-300 dark:border-dark-600 dark:bg-dark-400 dark:text-dark-1000 dark:hover:bg-dark-500"
>
{dueDate ? (
<span>{format(dueDate, "MMM d, yyyy")}</span>
) : (
<>{t`Due date`}</>
)}
</button>
{isDateSelectorOpen && (
<>
<div
className="fixed inset-0 z-10"
onClick={() => setIsDateSelectorOpen(false)}
/>
<div
className="absolute left-0 top-full z-20 mt-2 rounded-md border border-light-200 bg-light-50 shadow-lg dark:border-dark-200 dark:bg-dark-100"
onClick={(e) => {
e.stopPropagation();
}}
onMouseDown={(e) => {
e.stopPropagation();
}}
>
<DateSelector
selectedDate={dueDate ?? undefined}
onDateSelect={(date) => {
setValue("dueDate", date ?? null);
setIsDateSelectorOpen(false);
}}
/>
</div>
</>
)}
</div>
<button <button
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();

View File

@@ -23,6 +23,8 @@ import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
import { PageHead } from "~/components/PageHead"; import { PageHead } from "~/components/PageHead";
import PatternedBackground from "~/components/PatternedBackground"; import PatternedBackground from "~/components/PatternedBackground";
import { StrictModeDroppable as Droppable } from "~/components/StrictModeDroppable"; import { StrictModeDroppable as Droppable } from "~/components/StrictModeDroppable";
import { Tooltip } from "~/components/Tooltip";
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { useWorkspace } from "~/providers/workspace"; import { useWorkspace } from "~/providers/workspace";
@@ -54,6 +56,15 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
useState<PublicListId>(""); useState<PublicListId>("");
const [isInitialLoading, setIsInitialLoading] = useState(true); 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 const boardId = params?.boardId
? Array.isArray(params.boardId) ? Array.isArray(params.boardId)
? params.boardId[0] ? params.boardId[0]
@@ -76,18 +87,26 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
}); });
}; };
const queryParams: { const semanticFilters = formatToArray(router.query.dueDate) as (
boardPublicId: string; | "overdue"
members: string[]; | "today"
labels: string[]; | "tomorrow"
lists: string[]; | "next-week"
type: "regular" | "template"; | "next-month"
} = { | "no-due-date"
)[];
const boardType: "regular" | "template" = isTemplate ? "template" : "regular";
const queryParams = {
boardPublicId: boardId ?? "", boardPublicId: boardId ?? "",
members: formatToArray(router.query.members), members: formatToArray(router.query.members),
labels: formatToArray(router.query.labels), labels: formatToArray(router.query.labels),
lists: formatToArray(router.query.lists), lists: formatToArray(router.query.lists),
type: isTemplate ? "template" : "regular", ...(semanticFilters.length > 0 && {
dueDateFilters: semanticFilters,
}),
type: boardType,
}; };
const { const {
@@ -427,20 +446,22 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
)} )}
</> </>
)} )}
<Button <Tooltip content={createListShortcutTooltipContent}>
iconLeft={ <Button
<HiOutlinePlusSmall iconLeft={
className="-mr-0.5 h-5 w-5" <HiOutlinePlusSmall
aria-hidden="true" className="-mr-0.5 h-5 w-5"
/> aria-hidden="true"
} />
onClick={() => { }
if (boardId) openNewListForm(boardId); onClick={() => {
}} if (boardId) openNewListForm(boardId);
disabled={!boardData} }}
> disabled={!boardData}
{t`New list`} >
</Button> {t`New list`}
</Button>
</Tooltip>
<BoardDropdown <BoardDropdown
isTemplate={!!isTemplate} isTemplate={!!isTemplate}
isLoading={!boardData} isLoading={!boardData}
@@ -554,6 +575,7 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
} }
comments={card.comments ?? []} comments={card.comments ?? []}
attachments={card.attachments} attachments={card.attachments}
dueDate={card.dueDate ?? null}
/> />
</Link> </Link>
)} )}

View File

@@ -6,6 +6,8 @@ import FeedbackModal from "~/components/FeedbackModal";
import Modal from "~/components/modal"; import Modal from "~/components/modal";
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm"; import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
import { PageHead } from "~/components/PageHead"; import { PageHead } from "~/components/PageHead";
import { Tooltip } from "~/components/Tooltip";
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { useWorkspace } from "~/providers/workspace"; import { useWorkspace } from "~/providers/workspace";
import { BoardsList } from "./components/BoardsList"; import { BoardsList } from "./components/BoardsList";
@@ -16,6 +18,15 @@ export default function BoardsPage({ isTemplate }: { isTemplate?: boolean }) {
const { openModal, modalContentType, isOpen } = useModal(); const { openModal, modalContentType, isOpen } = useModal();
const { workspace } = useWorkspace(); 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 ( return (
<> <>
<PageHead <PageHead
@@ -39,16 +50,18 @@ export default function BoardsPage({ isTemplate }: { isTemplate?: boolean }) {
{t`Import`} {t`Import`}
</Button> </Button>
)} )}
<Button <Tooltip content={createModalShortcutTooltipContent}>
type="button" <Button
variant="primary" type="button"
onClick={() => openModal("NEW_BOARD")} variant="primary"
iconLeft={ onClick={() => openModal("NEW_BOARD")}
<HiOutlinePlusSmall aria-hidden="true" className="h-4 w-4" /> iconLeft={
} <HiOutlinePlusSmall aria-hidden="true" className="h-4 w-4" />
> }
{t`New`} >
</Button> {t`New`}
</Button>
</Tooltip>
</div> </div>
</div> </div>

View File

@@ -1,11 +1,13 @@
import type { Locale as DateFnsLocale } from "date-fns";
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import { Trans } from "@lingui/react/macro"; import { Trans } from "@lingui/react/macro";
import { formatDistanceToNow } from "date-fns"; import { format, formatDistanceToNow, isSameYear } from "date-fns";
import { de, enGB, es, fr, it, nl } from "date-fns/locale"; import { useEffect, useRef, useState } from "react";
import { import {
HiOutlineArrowLeft, HiOutlineArrowLeft,
HiOutlineArrowRight, HiOutlineArrowRight,
HiOutlineCheckCircle, HiOutlineCheckCircle,
HiOutlineClock,
HiOutlinePencil, HiOutlinePencil,
HiOutlinePlus, HiOutlinePlus,
HiOutlineTag, HiOutlineTag,
@@ -14,25 +16,20 @@ import {
HiOutlineUserPlus, HiOutlineUserPlus,
} from "react-icons/hi2"; } from "react-icons/hi2";
import type { GetCardByIdOutput } from "@kan/api/types"; import type {
GetCardActivitiesOutput,
GetCardByIdOutput,
} from "@kan/api/types";
import { authClient } from "@kan/auth/client"; import { authClient } from "@kan/auth/client";
import Avatar from "~/components/Avatar"; import Avatar from "~/components/Avatar";
import { useLocalisation } from "~/hooks/useLocalisation"; import { useLocalisation } from "~/hooks/useLocalisation";
import { api } from "~/utils/api";
import Comment from "./Comment"; import Comment from "./Comment";
type ActivityType = type ActivityType =
NonNullable<GetCardByIdOutput>["activities"][number]["type"]; NonNullable<GetCardByIdOutput>["activities"][number]["type"];
const dateLocaleMap = {
en: enGB,
fr: fr,
de: de,
es: es,
it: it,
nl: nl,
} as const;
const truncate = (value: string | null, maxLength = 50) => { const truncate = (value: string | null, maxLength = 50) => {
if (!value) return value; if (!value) return value;
return value.length > maxLength ? `${value.slice(0, maxLength - 1)}` : value; return value.length > maxLength ? `${value.slice(0, maxLength - 1)}` : value;
@@ -47,6 +44,9 @@ const getActivityText = ({
isSelf, isSelf,
label, label,
fromTitle, fromTitle,
toDueDate,
dateLocale,
mergedLabels,
}: { }: {
type: ActivityType; type: ActivityType;
toTitle: string | null; toTitle: string | null;
@@ -56,7 +56,45 @@ const getActivityText = ({
isSelf: boolean; isSelf: boolean;
label: string | null; label: string | null;
fromTitle?: string | null; fromTitle?: string | null;
fromDueDate?: Date | null;
toDueDate?: Date | null;
dateLocale: DateFnsLocale;
mergedLabels?: string[];
}) => { }) => {
const TextHighlight = ({ children }: { children: React.ReactNode }) => (
<span className="font-medium text-light-1000 dark:text-dark-1000">
{children}
</span>
);
if (
type === "card.updated.label.added" &&
mergedLabels &&
mergedLabels.length > 1
) {
const labelList = mergedLabels.join(", ");
return (
<Trans>
added {mergedLabels.length} labels:{" "}
<TextHighlight>{labelList}</TextHighlight>
</Trans>
);
}
if (
type === "card.updated.label.removed" &&
mergedLabels &&
mergedLabels.length > 1
) {
const labelList = mergedLabels.join(", ");
return (
<Trans>
removed {mergedLabels.length} labels:{" "}
<TextHighlight>{labelList}</TextHighlight>
</Trans>
);
}
const ACTIVITY_TYPE_MAP = { const ACTIVITY_TYPE_MAP = {
"card.created": t`created the card`, "card.created": t`created the card`,
"card.updated.title": t`updated the title`, "card.updated.title": t`updated the title`,
@@ -74,17 +112,14 @@ const getActivityText = ({
"card.updated.checklist.item.completed": t`completed a checklist item`, "card.updated.checklist.item.completed": t`completed a checklist item`,
"card.updated.checklist.item.uncompleted": t`marked a checklist item as incomplete`, "card.updated.checklist.item.uncompleted": t`marked a checklist item as incomplete`,
"card.updated.checklist.item.deleted": t`deleted a checklist item`, "card.updated.checklist.item.deleted": t`deleted a checklist item`,
"card.updated.dueDate.added": t`set the due date`,
"card.updated.dueDate.updated": t`updated the due date`,
"card.updated.dueDate.removed": t`removed the due date`,
} as const; } as const;
if (!(type in ACTIVITY_TYPE_MAP)) return null; if (!(type in ACTIVITY_TYPE_MAP)) return null;
const baseText = ACTIVITY_TYPE_MAP[type as keyof typeof ACTIVITY_TYPE_MAP]; const baseText = ACTIVITY_TYPE_MAP[type as keyof typeof ACTIVITY_TYPE_MAP];
const TextHighlight = ({ children }: { children: React.ReactNode }) => (
<span className="font-medium text-light-1000 dark:text-dark-1000">
{children}
</span>
);
if (type === "card.updated.title" && toTitle) { if (type === "card.updated.title" && toTitle) {
return ( return (
<Trans> <Trans>
@@ -209,6 +244,38 @@ const getActivityText = ({
); );
} }
if (type === "card.updated.dueDate.added" && toDueDate) {
const showYear = !isSameYear(toDueDate, new Date());
const formattedDate = format(
toDueDate,
showYear ? "do MMM yyyy" : "do MMM",
{ locale: dateLocale },
);
return (
<Trans>
changed the due date to <TextHighlight>{formattedDate}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.dueDate.updated" && toDueDate) {
const showYear = !isSameYear(toDueDate, new Date());
const formattedDate = format(
toDueDate,
showYear ? "do MMM yyyy" : "do MMM",
{ locale: dateLocale },
);
return (
<Trans>
changed the due date to <TextHighlight>{formattedDate}</TextHighlight>
</Trans>
);
}
if (type === "card.updated.dueDate.removed") {
return <Trans>removed the due date</Trans>;
}
return baseText; return baseText;
}; };
@@ -229,6 +296,9 @@ const ACTIVITY_ICON_MAP: Partial<Record<ActivityType, React.ReactNode | null>> =
"card.updated.checklist.item.completed": <HiOutlineCheckCircle />, "card.updated.checklist.item.completed": <HiOutlineCheckCircle />,
"card.updated.checklist.item.uncompleted": <HiOutlineCheckCircle />, "card.updated.checklist.item.uncompleted": <HiOutlineCheckCircle />,
"card.updated.checklist.item.deleted": <HiOutlineTrash />, "card.updated.checklist.item.deleted": <HiOutlineTrash />,
"card.updated.dueDate.added": <HiOutlineClock />,
"card.updated.dueDate.updated": <HiOutlineClock />,
"card.updated.dueDate.removed": <HiOutlineClock />,
} as const; } as const;
const getActivityIcon = ( const getActivityIcon = (
@@ -246,36 +316,151 @@ const getActivityIcon = (
return ACTIVITY_ICON_MAP[type] ?? null; return ACTIVITY_ICON_MAP[type] ?? null;
}; };
const ACTIVITIES_PAGE_SIZE = 20;
const ActivityList = ({ const ActivityList = ({
activities,
cardPublicId, cardPublicId,
isLoading, isLoading: cardIsLoading,
isAdmin, isAdmin,
isViewOnly, isViewOnly,
}: { }: {
activities: NonNullable<GetCardByIdOutput>["activities"];
cardPublicId: string; cardPublicId: string;
isLoading: boolean; isLoading: boolean;
isAdmin?: boolean; isAdmin?: boolean;
isViewOnly?: boolean; isViewOnly?: boolean;
}) => { }) => {
const { data } = authClient.useSession(); const { dateLocale, locale } = useLocalisation();
const { locale } = useLocalisation(); const { data: sessionData } = authClient.useSession();
const utils = api.useUtils();
const [allActivities, setAllActivities] = useState<
GetCardActivitiesOutput["activities"]
>([]);
const [hasMore, setHasMore] = useState(true);
const [isLoadingMore, setIsLoadingMore] = useState(false);
const currentDateLocale = dateLocaleMap[locale] || enGB; const isFullyExpandedRef = useRef(false);
const lastDataUpdatedAtRef = useRef<number | null>(null);
const {
data: firstPageData,
isFetching: isFetchingFirst,
dataUpdatedAt,
} = api.card.getActivities.useQuery(
{
cardPublicId,
limit: ACTIVITIES_PAGE_SIZE,
},
{
enabled: !!cardPublicId,
},
);
useEffect(() => {
if (firstPageData && dataUpdatedAt !== lastDataUpdatedAtRef.current) {
lastDataUpdatedAtRef.current = dataUpdatedAt;
if (isFullyExpandedRef.current && firstPageData.hasMore) {
setAllActivities(firstPageData.activities);
setHasMore(firstPageData.hasMore);
const fetchAllRemaining = async () => {
let currentActivities = [...firstPageData.activities];
let currentHasMore = firstPageData.hasMore;
while (currentHasMore) {
const lastActivity =
currentActivities[currentActivities.length - 1];
if (!lastActivity) break;
const nextCursor = new Date(lastActivity.createdAt).toISOString();
const nextPage = await utils.card.getActivities.fetch({
cardPublicId,
limit: ACTIVITIES_PAGE_SIZE,
cursor: nextCursor,
});
if (nextPage) {
const existingIds = new Set(
currentActivities.map((a) => a.publicId),
);
const newActivities = nextPage.activities.filter(
(a: { publicId: string }) => !existingIds.has(a.publicId),
);
currentActivities = [...currentActivities, ...newActivities];
currentHasMore = nextPage.hasMore;
} else {
break;
}
}
setAllActivities(currentActivities);
setHasMore(false);
};
fetchAllRemaining();
} else {
setAllActivities(firstPageData.activities);
setHasMore(firstPageData.hasMore);
if (!firstPageData.hasMore) {
isFullyExpandedRef.current = true;
}
}
}
}, [firstPageData, dataUpdatedAt, cardPublicId, utils.card.getActivities]);
const handleLoadMore = async () => {
if (isLoadingMore || !hasMore || allActivities.length === 0) return;
const lastActivity = allActivities[allActivities.length - 1];
if (!lastActivity) return;
setIsLoadingMore(true);
try {
const nextCursor = new Date(lastActivity.createdAt).toISOString();
const nextPage = await utils.card.getActivities.fetch({
cardPublicId,
limit: ACTIVITIES_PAGE_SIZE,
cursor: nextCursor,
});
if (nextPage) {
const existingIds = new Set(allActivities.map((a) => a.publicId));
const newActivities = nextPage.activities.filter(
(a: { publicId: string }) => !existingIds.has(a.publicId),
);
setAllActivities((prev) => [...prev, ...newActivities]);
setHasMore(nextPage.hasMore);
if (!nextPage.hasMore) {
isFullyExpandedRef.current = true;
}
}
} finally {
setIsLoadingMore(false);
}
};
const isFetching = isFetchingFirst || isLoadingMore;
const isLoading =
cardIsLoading || (isFetchingFirst && allActivities.length === 0);
return ( return (
<div className="flex flex-col space-y-4 pt-4"> <div className="flex flex-col space-y-4 pt-4">
{activities.map((activity, index) => { {allActivities.map((activity, index) => {
const activityText = getActivityText({ const activityText = getActivityText({
type: activity.type, type: activity.type,
toTitle: activity.toTitle, toTitle: activity.toTitle,
fromList: activity.fromList?.name ?? null, fromList: activity.fromList?.name ?? null,
toList: activity.toList?.name ?? null, toList: activity.toList?.name ?? null,
memberName: activity.member?.user?.name ?? null, memberName: activity.member?.user?.name ?? null,
isSelf: activity.member?.user?.id === data?.user.id, isSelf: activity.member?.user?.id === sessionData?.user.id,
label: activity.label?.name ?? null, label: activity.label?.name ?? null,
fromTitle: activity.fromTitle ?? null, fromTitle: activity.fromTitle ?? null,
fromDueDate: activity.fromDueDate ?? null,
toDueDate: activity.toDueDate ?? null,
dateLocale: dateLocale,
mergedLabels: (activity as any).mergedLabels,
}); });
if (activity.type === "card.updated.comment.added") if (activity.type === "card.updated.comment.added")
@@ -290,7 +475,7 @@ const ActivityList = ({
createdAt={activity.createdAt.toISOString()} createdAt={activity.createdAt.toISOString()}
comment={activity.comment?.comment} comment={activity.comment?.comment}
isEdited={!!activity.comment?.updatedAt} isEdited={!!activity.comment?.updatedAt}
isAuthor={activity.comment?.createdBy === data?.user.id} isAuthor={activity.comment?.createdBy === sessionData?.user.id}
isAdmin={isAdmin ?? false} isAdmin={isAdmin ?? false}
isViewOnly={!!isViewOnly} isViewOnly={!!isViewOnly}
/> />
@@ -315,11 +500,9 @@ const ActivityList = ({
)} )}
isLoading={isLoading} isLoading={isLoading}
/> />
{index !== activities.length - 1 && {index !== allActivities.length - 1 && (
activities[index + 1]?.type !== <div className="absolute bottom-[-14px] left-1/2 top-[30px] w-0.5 -translate-x-1/2 bg-light-600 dark:bg-dark-600" />
"card.updated.comment.added" && ( )}
<div className="absolute bottom-[-14px] left-1/2 top-[30px] w-0.5 -translate-x-1/2 bg-light-600 dark:bg-dark-600" />
)}
</div> </div>
<p className="text-sm"> <p className="text-sm">
<span className="font-medium dark:text-dark-1000">{`${activity.user?.name} `}</span> <span className="font-medium dark:text-dark-1000">{`${activity.user?.name} `}</span>
@@ -330,13 +513,24 @@ const ActivityList = ({
<span className="space-x-1 text-light-900 dark:text-dark-800"> <span className="space-x-1 text-light-900 dark:text-dark-800">
{formatDistanceToNow(new Date(activity.createdAt), { {formatDistanceToNow(new Date(activity.createdAt), {
addSuffix: true, addSuffix: true,
locale: currentDateLocale, locale: dateLocale,
})} })}
</span> </span>
</p> </p>
</div> </div>
); );
})} })}
{hasMore && (
<div className="flex justify-center pt-4">
<button
onClick={handleLoadMore}
disabled={isFetching}
className="text-sm font-medium text-light-900 hover:text-light-1000 disabled:opacity-50 dark:text-dark-800 dark:hover:text-dark-1000"
>
{isFetching ? t`Loading...` : t`Load more activities`}
</button>
</div>
)}
</div> </div>
); );
}; };

View File

@@ -13,6 +13,7 @@ import {
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface Attachment { interface Attachment {
publicId: string; publicId: string;
@@ -81,7 +82,7 @@ export function AttachmentThumbnails({
}, },
onSettled: async () => { onSettled: async () => {
if (isReadOnly) return; if (isReadOnly) return;
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });

View File

@@ -8,6 +8,7 @@ import Button from "~/components/Button";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
export function AttachmentUpload({ cardPublicId }: { cardPublicId: string }) { export function AttachmentUpload({ cardPublicId }: { cardPublicId: string }) {
const { openModal } = useModal(); const { openModal } = useModal();
@@ -20,7 +21,7 @@ export function AttachmentUpload({ cardPublicId }: { cardPublicId: string }) {
const generateUploadUrl = api.attachment.generateUploadUrl.useMutation(); const generateUploadUrl = api.attachment.generateUploadUrl.useMutation();
const confirmAttachment = api.attachment.confirm.useMutation({ const confirmAttachment = api.attachment.confirm.useMutation({
onSuccess: async () => { onSuccess: async () => {
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
showPopup({ showPopup({
header: t`Attachment uploaded`, header: t`Attachment uploaded`,
message: t`Your file has been uploaded successfully.`, message: t`Your file has been uploaded successfully.`,

View File

@@ -1,11 +1,14 @@
import type { DraggableProvided } from "react-beautiful-dnd";
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import ContentEditable from "react-contenteditable"; import ContentEditable from "react-contenteditable";
import { HiXMark } from "react-icons/hi2"; import { HiXMark } from "react-icons/hi2";
import { RiDraggable } from "react-icons/ri";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface ChecklistItemRowProps { interface ChecklistItemRowProps {
item: { item: {
@@ -14,13 +17,19 @@ interface ChecklistItemRowProps {
completed: boolean; completed: boolean;
}; };
cardPublicId: string; cardPublicId: string;
onCreateNewItem?: () => void;
viewOnly?: boolean; viewOnly?: boolean;
dragHandleProps?: DraggableProvided["dragHandleProps"];
isDragging?: boolean;
} }
export default function ChecklistItemRow({ export default function ChecklistItemRow({
item, item,
cardPublicId, cardPublicId,
onCreateNewItem,
viewOnly = false, viewOnly = false,
dragHandleProps,
isDragging = false,
}: ChecklistItemRowProps) { }: ChecklistItemRowProps) {
const utils = api.useUtils(); const utils = api.useUtils();
const { showPopup } = usePopup(); const { showPopup } = usePopup();
@@ -62,7 +71,7 @@ export default function ChecklistItemRow({
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });
@@ -90,7 +99,7 @@ export default function ChecklistItemRow({
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });
@@ -138,7 +147,23 @@ export default function ChecklistItemRow({
}; };
return ( return (
<div className="group relative flex items-start gap-3 rounded-md py-2 pl-4 hover:bg-light-100 dark:hover:bg-dark-100"> <div
className={twMerge(
"group relative flex items-start gap-3 rounded-md py-2 pl-4 hover:bg-light-100 dark:hover:bg-dark-100",
isDragging && "opacity-80",
)}
>
{!viewOnly && (
<div
{...dragHandleProps}
className="absolute left-0 top-1/2 flex h-[20px] w-[20px] -translate-x-full -translate-y-1/2 cursor-grab items-center justify-center pr-1 opacity-0 transition-opacity group-hover:opacity-75 hover:opacity-100 active:cursor-grabbing"
>
<RiDraggable className="h-4 w-4 text-light-700 dark:text-dark-700" />
</div>
)}
{viewOnly && <div className="w-[20px] flex-shrink-0" />}
<label <label
className={`relative mt-[2px] inline-flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center`} className={`relative mt-[2px] inline-flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center`}
> >
@@ -164,7 +189,10 @@ export default function ChecklistItemRow({
disabled={viewOnly} disabled={viewOnly}
onChange={(e) => setTitle(e.target.value)} onChange={(e) => setTitle(e.target.value)}
// @ts-expect-error - valid event // @ts-expect-error - valid event
onBlur={(e: Event) => commitTitle(e.target.innerHTML as string)} onBlur={(e: Event) => {
const innerHTML = (e.target as HTMLElement).innerHTML;
commitTitle(innerHTML);
}}
className={twMerge( className={twMerge(
"m-0 min-h-[20px] w-full p-0 text-sm leading-[20px] text-light-950 outline-none focus-visible:outline-none dark:text-dark-950", "m-0 min-h-[20px] w-full p-0 text-sm leading-[20px] text-light-950 outline-none focus-visible:outline-none dark:text-dark-950",
viewOnly && "cursor-default", viewOnly && "cursor-default",
@@ -174,7 +202,9 @@ export default function ChecklistItemRow({
if (viewOnly) return; if (viewOnly) return;
if (e.key === "Enter") { if (e.key === "Enter") {
e.preventDefault(); e.preventDefault();
commitTitle(title); const innerHTML = (e.currentTarget as HTMLElement).innerHTML;
commitTitle(innerHTML);
onCreateNewItem?.();
} }
if (e.key === "Escape") { if (e.key === "Escape") {
e.preventDefault(); e.preventDefault();

View File

@@ -4,6 +4,7 @@ import { twMerge } from "tailwind-merge";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
export default function ChecklistNameInput({ export default function ChecklistNameInput({
checklistPublicId, checklistPublicId,
@@ -48,7 +49,7 @@ export default function ChecklistNameInput({
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });

View File

@@ -1,7 +1,13 @@
import type { DropResult } from "react-beautiful-dnd";
import { t } from "@lingui/core/macro";
import { DragDropContext, Draggable } from "react-beautiful-dnd";
import { HiPlus, HiXMark } from "react-icons/hi2"; import { HiPlus, HiXMark } from "react-icons/hi2";
import CircularProgress from "~/components/CircularProgress"; import CircularProgress from "~/components/CircularProgress";
import { StrictModeDroppable as Droppable } from "~/components/StrictModeDroppable";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
import ChecklistItemRow from "./ChecklistItemRow"; import ChecklistItemRow from "./ChecklistItemRow";
import ChecklistNameInput from "./ChecklistNameInput"; import ChecklistNameInput from "./ChecklistNameInput";
import NewChecklistItemForm from "./NewChecklistItemForm"; import NewChecklistItemForm from "./NewChecklistItemForm";
@@ -34,109 +40,206 @@ export default function Checklists({
viewOnly = false, viewOnly = false,
}: ChecklistsProps) { }: ChecklistsProps) {
const { openModal } = useModal(); const { openModal } = useModal();
const { showPopup } = usePopup();
if (!checklists || checklists.length === 0) return null; const utils = api.useUtils();
const reorderItemMutation = api.checklist.updateItem.useMutation({
onMutate: async (vars) => {
await utils.card.byId.cancel({ cardPublicId });
const previous = utils.card.byId.getData({ cardPublicId });
utils.card.byId.setData({ cardPublicId }, (old) => {
if (!old) return old;
const updatedChecklists = old.checklists.map((cl) => {
const itemIndex = cl.items.findIndex(
(item) => item.publicId === vars.checklistItemPublicId,
);
if (itemIndex === -1 || vars.index === undefined) return cl;
const newIndex = vars.index;
const items = Array.from(cl.items);
const [movedItem] = items.splice(itemIndex, 1);
if (!movedItem) return cl;
items.splice(newIndex, 0, movedItem);
return { ...cl, items };
});
return { ...old, checklists: updatedChecklists } as typeof old;
});
return { previous };
},
onError: (_err, _vars, ctx) => {
if (ctx?.previous)
utils.card.byId.setData({ cardPublicId }, ctx.previous);
showPopup({
header: t`Unable to reorder checklist item`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId });
},
});
const onDragEnd = (result: DropResult) => {
if (!result.destination) return;
const { source, destination, draggableId } = result;
if (source.droppableId !== destination.droppableId) return;
if (source.index === destination.index) return;
reorderItemMutation.mutate({
checklistItemPublicId: draggableId,
index: destination.index,
});
};
if (checklists.length === 0) return null;
return ( return (
<div className="border-light-300 pb-4 dark:border-dark-300"> <DragDropContext onDragEnd={onDragEnd}>
<div> <div className="border-light-300 pb-4 dark:border-dark-300">
{checklists.map((checklist) => { <div>
const completedItems = checklist.items.filter( {checklists.map((checklist) => {
(item) => item.completed, const completedItems = checklist.items.filter(
); (item) => item.completed,
const progress = );
checklist.items.length > 0 && completedItems.length > 0 const progress =
? (completedItems.length / checklist.items.length) * 100 checklist.items.length > 0 && completedItems.length > 0
: 2; ? (completedItems.length / checklist.items.length) * 100
: 2;
return ( return (
<div key={checklist.publicId} className="mb-4"> <div key={checklist.publicId} className="mb-4">
<div className="mb-2 flex items-center font-medium text-light-1000 dark:text-dark-1000"> <div className="mb-2 flex items-center font-medium text-light-1000 dark:text-dark-1000">
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<ChecklistNameInput <ChecklistNameInput
checklistPublicId={checklist.publicId} checklistPublicId={checklist.publicId}
initialName={checklist.name} initialName={checklist.name}
cardPublicId={cardPublicId} cardPublicId={cardPublicId}
viewOnly={viewOnly} viewOnly={viewOnly}
/> />
</div>
{!viewOnly && (
<div className="ml-2 flex flex-shrink-0 items-center gap-2">
<div className="flex items-center gap-1 rounded-full border-[1px] border-light-300 px-2 py-1 dark:border-dark-300">
<CircularProgress
progress={progress}
size="sm"
className="flex-shrink-0"
/>
<span className="text-[11px] text-light-900 dark:text-dark-700">
{completedItems.length}/{checklist.items.length}
</span>
</div>
<div>
<button
className="rounded-md p-1 text-light-900 hover:bg-light-100 dark:text-dark-700 dark:hover:bg-dark-100"
onClick={() =>
openModal("DELETE_CHECKLIST", checklist.publicId)
}
>
<HiXMark size={16} />
</button>
<button
onClick={() =>
setActiveChecklistForm?.(checklist.publicId)
}
className="rounded-md p-1 text-light-900 hover:bg-light-100 dark:text-dark-700 dark:hover:bg-dark-100"
>
<HiPlus size={16} />
</button>
</div>
</div> </div>
)} {!viewOnly && (
{viewOnly && ( <div className="ml-2 flex flex-shrink-0 items-center gap-2">
<div className="ml-2 flex flex-shrink-0 items-center gap-2"> <div className="flex items-center gap-1 rounded-full border-[1px] border-light-300 px-2 py-1 dark:border-dark-300">
<div className="flex items-center gap-1 rounded-full border-[1px] border-light-300 px-2 py-1 dark:border-dark-300"> <CircularProgress
<CircularProgress progress={progress}
progress={progress} size="sm"
size="sm" className="flex-shrink-0"
className="flex-shrink-0" />
/> <span className="text-[11px] text-light-900 dark:text-dark-700">
<span className="text-[11px] text-light-900 dark:text-dark-700"> {completedItems.length}/{checklist.items.length}
{completedItems.length}/{checklist.items.length} </span>
</span> </div>
<div>
<button
className="rounded-md p-1 text-light-900 hover:bg-light-100 dark:text-dark-700 dark:hover:bg-dark-100"
onClick={() =>
openModal("DELETE_CHECKLIST", checklist.publicId)
}
>
<HiXMark size={16} />
</button>
<button
onClick={() =>
setActiveChecklistForm?.(checklist.publicId)
}
className="rounded-md p-1 text-light-900 hover:bg-light-100 dark:text-dark-700 dark:hover:bg-dark-100"
>
<HiPlus size={16} />
</button>
</div>
</div> </div>
)}
{viewOnly && (
<div className="ml-2 flex flex-shrink-0 items-center gap-2">
<div className="flex items-center gap-1 rounded-full border-[1px] border-light-300 px-2 py-1 dark:border-dark-300">
<CircularProgress
progress={progress}
size="sm"
className="flex-shrink-0"
/>
<span className="text-[11px] text-light-900 dark:text-dark-700">
{completedItems.length}/{checklist.items.length}
</span>
</div>
</div>
)}
</div>
<Droppable
droppableId={checklist.publicId}
type="CHECKLIST_ITEM"
isDropDisabled={viewOnly}
>
{(provided) => (
<div
ref={provided.innerRef}
{...provided.droppableProps}
className="ml-1"
>
{checklist.items.map((item, index) => (
<Draggable
key={item.publicId}
draggableId={item.publicId}
index={index}
isDragDisabled={viewOnly}
>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
style={{
...provided.draggableProps.style,
opacity: snapshot.isDragging ? 0.8 : 1,
}}
>
<ChecklistItemRow
item={{
publicId: item.publicId,
title: item.title,
completed: item.completed,
}}
cardPublicId={cardPublicId}
onCreateNewItem={() =>
setActiveChecklistForm?.(checklist.publicId)
}
viewOnly={viewOnly}
dragHandleProps={provided.dragHandleProps}
isDragging={snapshot.isDragging}
/>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
{activeChecklistForm === checklist.publicId && !viewOnly && (
<div className="ml-1">
<NewChecklistItemForm
checklistPublicId={checklist.publicId}
cardPublicId={cardPublicId}
onCancel={() => setActiveChecklistForm?.(null)}
readOnly={viewOnly}
/>
</div> </div>
)} )}
</div> </div>
);
<div className="ml-1"> })}
{checklist.items.map((item) => ( </div>
<ChecklistItemRow
key={item.publicId}
item={{
publicId: item.publicId,
title: item.title,
completed: item.completed,
}}
cardPublicId={cardPublicId}
viewOnly={viewOnly}
/>
))}
</div>
{activeChecklistForm === checklist.publicId && !viewOnly && (
<div className="ml-1">
<NewChecklistItemForm
checklistPublicId={checklist.publicId}
cardPublicId={cardPublicId}
onCancel={() => setActiveChecklistForm?.(null)}
readOnly={viewOnly}
/>
</div>
)}
</div>
);
})}
</div> </div>
</div> </DragDropContext>
); );
} }

View File

@@ -11,6 +11,7 @@ import Dropdown from "~/components/Dropdown";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface FormValues { interface FormValues {
comment: string; comment: string;
@@ -55,7 +56,7 @@ const Comment = ({
const updateCommentMutation = api.card.updateComment.useMutation({ const updateCommentMutation = api.card.updateComment.useMutation({
onSuccess: async () => { onSuccess: async () => {
await utils.card.byId.refetch(); await invalidateCard(utils, cardPublicId);
setIsEditing(false); setIsEditing(false);
}, },
onError: () => { onError: () => {

View File

@@ -4,6 +4,7 @@ import Button from "~/components/Button";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
export function DeleteChecklistConfirmation({ export function DeleteChecklistConfirmation({
cardPublicId, cardPublicId,
@@ -40,7 +41,7 @@ export function DeleteChecklistConfirmation({
}, },
onSettled: async () => { onSettled: async () => {
closeModal(); closeModal();
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });

View File

@@ -4,6 +4,7 @@ import Button from "~/components/Button";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface DeleteCommentConfirmationProps { interface DeleteCommentConfirmationProps {
cardPublicId: string; cardPublicId: string;
@@ -47,7 +48,7 @@ export function DeleteCommentConfirmation({
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate(queryParams); await invalidateCard(utils, cardPublicId);
}, },
}); });

View File

@@ -0,0 +1,142 @@
import { t } from "@lingui/core/macro";
import { format } from "date-fns";
import { useEffect, useState } from "react";
import { HiMiniPlus } from "react-icons/hi2";
import DateSelector from "~/components/DateSelector";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface DueDateSelectorProps {
cardPublicId: string;
dueDate: Date | null | undefined;
isLoading?: boolean;
}
export function DueDateSelector({
cardPublicId,
dueDate,
isLoading = false,
}: DueDateSelectorProps) {
const { showPopup } = usePopup();
const utils = api.useUtils();
const [isOpen, setIsOpen] = useState(false);
const [pendingDate, setPendingDate] = useState<Date | null | undefined>(
dueDate,
);
// Sync pendingDate with dueDate when it changes externally
useEffect(() => {
if (!isOpen) {
setPendingDate(dueDate);
}
}, [dueDate, isOpen]);
const updateDueDate = api.card.update.useMutation({
onMutate: async (update) => {
await utils.card.byId.cancel();
const previousCard = utils.card.byId.getData({ cardPublicId });
utils.card.byId.setData({ cardPublicId }, (oldCard) => {
if (!oldCard) return oldCard;
return {
...oldCard,
dueDate:
update.dueDate !== undefined
? (update.dueDate as Date | null)
: oldCard.dueDate,
};
});
return { previousCard };
},
onError: (_error, _update, context) => {
utils.card.byId.setData({ cardPublicId }, context?.previousCard);
showPopup({
header: t`Unable to update due date`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async () => {
await invalidateCard(utils, cardPublicId);
await utils.board.byId.invalidate();
},
});
const handleDateSelect = (date: Date | undefined) => {
// Only update local state, don't fire mutation
setPendingDate(date ?? null);
};
const handleBackdropClick = () => {
// Only fire mutation if date actually changed
const pendingIsNull = pendingDate === null || pendingDate === undefined;
const dueIsNull = dueDate === null || dueDate === undefined;
let dateChanged = false;
if (pendingIsNull && !dueIsNull) {
dateChanged = true;
} else if (!pendingIsNull && dueIsNull) {
dateChanged = true;
} else if (!pendingIsNull && !dueIsNull) {
// Both are non-null at this point
if (pendingDate instanceof Date && dueDate instanceof Date) {
dateChanged = pendingDate.getTime() !== dueDate.getTime();
}
}
// Close popover immediately
setIsOpen(false);
// Fire mutation if date changed (optimistic update will handle UI)
if (dateChanged) {
updateDueDate.mutate({
cardPublicId,
dueDate: pendingDate ?? null,
});
}
};
return (
<div className="relative flex w-full items-center text-left">
<button
type="button"
onClick={() => setIsOpen(!isOpen)}
disabled={isLoading}
className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-50 py-1 pl-2 text-left text-xs text-neutral-900 hover:border-light-300 hover:bg-light-200 dark:border-dark-50 dark:text-dark-1000 dark:hover:border-dark-200 dark:hover:bg-dark-100"
>
{dueDate ? (
<span>{format(dueDate, "MMM d, yyyy")}</span>
) : (
<>
<HiMiniPlus size={22} className="pr-2" />
{t`Set due date`}
</>
)}
</button>
{isOpen && (
<>
<div className="fixed inset-0 z-10" onClick={handleBackdropClick} />
<div
className="absolute -left-8 top-full z-20 mt-2 rounded-md border border-light-200 bg-light-50 shadow-lg dark:border-dark-200 dark:bg-dark-100"
onClick={(e) => {
e.stopPropagation();
}}
onMouseDown={(e) => {
e.stopPropagation();
}}
>
<DateSelector
selectedDate={pendingDate ?? undefined}
onDateSelect={handleDateSelect}
/>
</div>
</>
)}
</div>
);
}

View File

@@ -6,6 +6,7 @@ import CheckboxDropdown from "~/components/CheckboxDropdown";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface LabelSelectorProps { interface LabelSelectorProps {
cardPublicId: string; cardPublicId: string;
@@ -74,7 +75,7 @@ export default function LabelSelector({
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });

View File

@@ -3,6 +3,7 @@ import { t } from "@lingui/core/macro";
import CheckboxDropdown from "~/components/CheckboxDropdown"; import CheckboxDropdown from "~/components/CheckboxDropdown";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface ListSelectorProps { interface ListSelectorProps {
cardPublicId: string; cardPublicId: string;
@@ -54,7 +55,7 @@ export default function ListSelector({
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });
@@ -78,7 +79,7 @@ export default function ListSelector({
}} }}
asChild asChild
> >
<div className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-50 py-1 pl-2 text-left text-sm text-neutral-900 hover:border-light-300 hover:bg-light-200 dark:border-dark-50 dark:text-dark-1000 dark:hover:border-dark-200 dark:hover:bg-dark-100"> <div className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-50 py-1 pl-2 text-left text-xs text-neutral-900 hover:border-light-300 hover:bg-light-200 dark:border-dark-50 dark:text-dark-1000 dark:hover:border-dark-200 dark:hover:bg-dark-100">
{selectedList?.value} {selectedList?.value}
</div> </div>
</CheckboxDropdown> </CheckboxDropdown>

View File

@@ -7,6 +7,7 @@ import CheckboxDropdown from "~/components/CheckboxDropdown";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface MemberSelectorProps { interface MemberSelectorProps {
cardPublicId: string; cardPublicId: string;
@@ -81,7 +82,7 @@ export default function MemberSelector({
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });
@@ -111,7 +112,7 @@ export default function MemberSelector({
createNewItemLabel={t`Invite member`} createNewItemLabel={t`Invite member`}
asChild asChild
> >
<div className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-50 py-1 pl-2 text-left text-sm text-neutral-900 hover:border-light-300 hover:bg-light-200 dark:border-dark-50 dark:text-dark-1000 dark:hover:border-dark-200 dark:hover:bg-dark-100"> <div className="flex h-full w-full items-center rounded-[5px] border-[1px] border-light-50 py-1 pl-2 text-left text-xs text-neutral-900 hover:border-light-300 hover:bg-light-200 dark:border-dark-50 dark:text-dark-1000 dark:hover:border-dark-200 dark:hover:bg-dark-100">
{selectedMembers.length ? ( {selectedMembers.length ? (
<div className="isolate flex justify-end -space-x-1 overflow-hidden"> <div className="isolate flex justify-end -space-x-1 overflow-hidden">
{selectedMembers.map(({ value, imageUrl }) => ( {selectedMembers.map(({ value, imageUrl }) => (

View File

@@ -10,6 +10,7 @@ import Input from "~/components/Input";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface NewChecklistFormInput { interface NewChecklistFormInput {
name: string; name: string;
@@ -72,7 +73,7 @@ export function NewChecklistForm({ cardPublicId }: { cardPublicId: string }) {
}); });
}, },
onSettled: async (_data, _error, vars) => { onSettled: async (_data, _error, vars) => {
await utils.card.byId.invalidate({ cardPublicId: vars.cardPublicId }); await invalidateCard(utils, vars.cardPublicId);
}, },
}); });

View File

@@ -7,6 +7,7 @@ import { generateUID } from "@kan/shared/utils";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface FormValues { interface FormValues {
title: string; title: string;
@@ -91,7 +92,7 @@ const NewChecklistItemForm = ({
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId }); await invalidateCard(utils, cardPublicId);
}, },
}); });

View File

@@ -6,6 +6,7 @@ import { HiOutlineArrowUp } from "react-icons/hi2";
import LoadingSpinner from "~/components/LoadingSpinner"; import LoadingSpinner from "~/components/LoadingSpinner";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
interface FormValues { interface FormValues {
comment: string; comment: string;
@@ -34,10 +35,7 @@ const NewCommentForm = ({ cardPublicId }: { cardPublicId: string }) => {
}, },
onSettled: async () => { onSettled: async () => {
reset(); reset();
await utils.card.byId.invalidate(queryParams); await invalidateCard(utils, cardPublicId);
},
onSuccess: async () => {
await utils.card.byId.refetch();
}, },
}); });

View File

@@ -17,6 +17,7 @@ import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup"; import { usePopup } from "~/providers/popup";
import { useWorkspace } from "~/providers/workspace"; import { useWorkspace } from "~/providers/workspace";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { invalidateCard } from "~/utils/cardInvalidation";
import { formatMemberDisplayName, getAvatarUrl } from "~/utils/helpers"; import { formatMemberDisplayName, getAvatarUrl } from "~/utils/helpers";
import { DeleteLabelConfirmation } from "../../components/DeleteLabelConfirmation"; import { DeleteLabelConfirmation } from "../../components/DeleteLabelConfirmation";
import ActivityList from "./components/ActivityList"; import ActivityList from "./components/ActivityList";
@@ -27,6 +28,7 @@ import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation";
import { DeleteChecklistConfirmation } from "./components/DeleteChecklistConfirmation"; import { DeleteChecklistConfirmation } from "./components/DeleteChecklistConfirmation";
import { DeleteCommentConfirmation } from "./components/DeleteCommentConfirmation"; import { DeleteCommentConfirmation } from "./components/DeleteCommentConfirmation";
import Dropdown from "./components/Dropdown"; import Dropdown from "./components/Dropdown";
import { DueDateSelector } from "./components/DueDateSelector";
import LabelSelector from "./components/LabelSelector"; import LabelSelector from "./components/LabelSelector";
import ListSelector from "./components/ListSelector"; import ListSelector from "./components/ListSelector";
import MemberSelector from "./components/MemberSelector"; import MemberSelector from "./components/MemberSelector";
@@ -124,7 +126,7 @@ export function CardRightPanel({ isTemplate }: { isTemplate?: boolean }) {
/> />
</div> </div>
{!isTemplate && ( {!isTemplate && (
<div className="flex w-full flex-row"> <div className="mb-4 flex w-full flex-row">
<p className="my-2 mb-2 w-[100px] text-sm font-medium">{t`Members`}</p> <p className="my-2 mb-2 w-[100px] text-sm font-medium">{t`Members`}</p>
<MemberSelector <MemberSelector
cardPublicId={cardId ?? ""} cardPublicId={cardId ?? ""}
@@ -133,6 +135,14 @@ export function CardRightPanel({ isTemplate }: { isTemplate?: boolean }) {
/> />
</div> </div>
)} )}
<div className="mb-4 flex w-full flex-row">
<p className="my-2 mb-2 w-[100px] text-sm font-medium">{t`Due date`}</p>
<DueDateSelector
cardPublicId={cardId ?? ""}
dueDate={card?.dueDate}
isLoading={!card}
/>
</div>
</div> </div>
); );
} }
@@ -147,6 +157,7 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
getModalState, getModalState,
clearModalState, clearModalState,
isOpen, isOpen,
modalStates,
} = useModal(); } = useModal();
const { showPopup } = usePopup(); const { showPopup } = usePopup();
const { workspace } = useWorkspace(); const { workspace } = useWorkspace();
@@ -168,7 +179,6 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
const board = card?.list.board; const board = card?.list.board;
const boardId = board?.publicId; const boardId = board?.publicId;
const activities = card?.activities;
const updateCard = api.card.update.useMutation({ const updateCard = api.card.update.useMutation({
onError: () => { onError: () => {
@@ -179,7 +189,22 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
}); });
}, },
onSettled: async () => { onSettled: async () => {
await utils.card.byId.invalidate({ cardPublicId: cardId }); if (cardId) await invalidateCard(utils, cardId);
},
});
const addOrRemoveLabel = api.card.addOrRemoveLabel.useMutation({
onError: () => {
showPopup({
header: t`Unable to add label`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSettled: async () => {
if (cardId) {
await utils.card.byId.invalidate({ cardPublicId: cardId });
}
}, },
}); });
@@ -199,6 +224,24 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
}); });
}; };
// this adds the new created label to selected labels
useEffect(() => {
const newLabelId = modalStates.NEW_LABEL_CREATED;
if (newLabelId && cardId) {
const isAlreadyAdded = card?.labels.some(
(label) => label.publicId === newLabelId,
);
if (!isAlreadyAdded) {
addOrRemoveLabel.mutate({
cardPublicId: cardId,
labelPublicId: newLabelId,
});
}
clearModalState("NEW_LABEL_CREATED");
}
}, [modalStates.NEW_LABEL_CREATED, card, cardId]);
// Open the new item form after creating a new checklist // Open the new item form after creating a new checklist
useEffect(() => { useEffect(() => {
if (!card) return; if (!card) return;
@@ -345,7 +388,6 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
<div> <div>
<ActivityList <ActivityList
cardPublicId={cardId} cardPublicId={cardId}
activities={activities ?? []}
isLoading={!card} isLoading={!card}
isAdmin={workspace.role === "admin"} isAdmin={workspace.role === "admin"}
/> />

View File

@@ -1,15 +1,14 @@
import type { FC, SVGProps } from "react"; import type { FC, SVGProps } from "react";
import { Trans } from "@lingui/react/macro"; import { Trans } from "@lingui/react/macro";
import AirbusLogo from "/public/logos/airbus.svg"; import AirbusLogo from "~/assets/logos/airbus.svg";
import BitwardenLogo from "/public/logos/bitwarden.svg"; import CouchbaseLogo from "~/assets/logos/couchbase.svg";
import CouchbaseLogo from "/public/logos/couchbase.svg"; import DeloitteLogo from "~/assets/logos/deloitte.svg";
import DeloitteLogo from "/public/logos/deloitte.svg"; import FastCompanyLogo from "~/assets/logos/fast_company.svg";
import FastCompanyLogo from "/public/logos/fast_company.svg"; import LegoLogo from "~/assets/logos/lego.svg";
import LegoLogo from "/public/logos/lego.svg"; import LinkedinLogo from "~/assets/logos/linkedin.svg";
import LinkedinLogo from "/public/logos/linkedin.svg"; import SanaLogo from "~/assets/logos/sana.svg";
import SanaLogo from "/public/logos/sana.svg"; import WakamLogo from "~/assets/logos/wakam.svg";
import WakamLogo from "/public/logos/wakam.svg";
type LogoComponent = FC<SVGProps<SVGSVGElement>>; type LogoComponent = FC<SVGProps<SVGSVGElement>>;
@@ -31,36 +30,31 @@ export default function Logos() {
}, },
{ {
id: 3, id: 3,
component: BitwardenLogo as LogoComponent,
alt: "Bitwarden Logo",
},
{
id: 4,
component: CouchbaseLogo as LogoComponent, component: CouchbaseLogo as LogoComponent,
alt: "Couchbase Logo", alt: "Couchbase Logo",
}, },
{ {
id: 5, id: 4,
component: LegoLogo as LogoComponent, component: LegoLogo as LogoComponent,
alt: "Lego Logo", alt: "Lego Logo",
}, },
{ {
id: 6, id: 5,
component: AirbusLogo as LogoComponent, component: AirbusLogo as LogoComponent,
alt: "Airbus Logo", alt: "Airbus Logo",
}, },
{ {
id: 7, id: 6,
component: DeloitteLogo as LogoComponent, component: DeloitteLogo as LogoComponent,
alt: "Deloitte Logo", alt: "Deloitte Logo",
}, },
{ {
id: 8, id: 7,
component: WakamLogo as LogoComponent, component: WakamLogo as LogoComponent,
alt: "Wakam Logo", alt: "Wakam Logo",
}, },
{ {
id: 9, id: 8,
component: LinkedinLogo as LogoComponent, component: LinkedinLogo as LogoComponent,
alt: "Linked In Logo", alt: "Linked In Logo",
}, },
@@ -82,7 +76,7 @@ export default function Logos() {
<div className="absolute left-0 top-0 z-10 h-full w-8 bg-gradient-to-r from-white/60 to-transparent dark:from-dark-50" /> <div className="absolute left-0 top-0 z-10 h-full w-8 bg-gradient-to-r from-white/60 to-transparent dark:from-dark-50" />
<div className="absolute right-0 top-0 z-10 h-full w-8 bg-gradient-to-l from-white/60 to-transparent dark:from-dark-50" /> <div className="absolute right-0 top-0 z-10 h-full w-8 bg-gradient-to-l from-white/60 to-transparent dark:from-dark-50" />
<div className="animate-scroll flex" style={{ width: "max-content" }}> <div className="flex animate-scroll" style={{ width: "max-content" }}>
<div className="flex flex-shrink-0 items-center space-x-12"> <div className="flex flex-shrink-0 items-center space-x-12">
{logos.map((logo) => { {logos.map((logo) => {
const LogoComponent: LogoComponent = logo.component; const LogoComponent: LogoComponent = logo.component;

View File

@@ -67,22 +67,23 @@ export function CardModal({
<div className="flex w-full items-center justify-between"> <div className="flex w-full items-center justify-between">
<button <button
className="absolute right-[2rem] top-[2rem] rounded p-1 hover:bg-light-300 focus:outline-none dark:hover:bg-dark-300" 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(); e.preventDefault();
closeModal(); closeModal();
setTimeout(async () => { setTimeout(() => {
try { void router.replace(
await router.replace( {
`/${workspaceSlug}/${boardSlug}`, pathname: router.pathname,
undefined, query: {
{ ...router.query,
shallow: true, workspaceSlug,
boardSlug: [boardSlug],
}, },
); },
} catch (error) { undefined,
console.error(error); { shallow: true },
} );
}, 400); }, 400);
}} }}
> >
@@ -160,7 +161,6 @@ export function CardModal({
{cardPublicId && ( {cardPublicId && (
<ActivityList <ActivityList
cardPublicId={cardPublicId} cardPublicId={cardPublicId}
activities={data?.activities ?? []}
isLoading={isLoading} isLoading={isLoading}
isViewOnly={true} isViewOnly={true}
/> />

View File

@@ -38,6 +38,15 @@ export default function PublicBoardView() {
? router.query.workspaceSlug[0] ? router.query.workspaceSlug[0]
: router.query.workspaceSlug; : router.query.workspaceSlug;
const dueDateFilters = formatToArray(router.query.dueDate) as (
| "overdue"
| "today"
| "tomorrow"
| "next-week"
| "next-month"
| "no-due-date"
)[];
const { data, isLoading } = api.board.bySlug.useQuery( const { data, isLoading } = api.board.bySlug.useQuery(
{ {
boardSlug: boardSlug ?? "", boardSlug: boardSlug ?? "",
@@ -45,6 +54,9 @@ export default function PublicBoardView() {
members: formatToArray(router.query.members), members: formatToArray(router.query.members),
labels: formatToArray(router.query.labels), labels: formatToArray(router.query.labels),
lists: formatToArray(router.query.lists), lists: formatToArray(router.query.lists),
...(dueDateFilters.length > 0 && {
dueDateFilters: dueDateFilters,
}),
}, },
{ {
enabled: router.isReady && !!boardSlug, enabled: router.isReady && !!boardSlug,
@@ -76,7 +88,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; const cardPublicId = splitPath.length > 3 ? splitPath[3] : null;
useEffect(() => { useEffect(() => {
@@ -172,27 +185,37 @@ export default function PublicBoardView() {
</span> </span>
</div> </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"> <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) => ( {list.cards.map((card) => {
<Link return (
key={card.publicId} <Link
href={`/${data.workspace.slug}/${data.slug}/${card.publicId}`} key={card.publicId}
className={`mb-2 flex !cursor-pointer flex-col`} href={{
shallow={true} pathname: router.pathname,
onClick={() => { query: {
openModal("CARD"); ...router.query,
}} workspaceSlug: data.workspace.slug,
> boardSlug: [data.slug, card.publicId],
<Card },
title={card.title} }}
labels={card.labels} className={`mb-2 flex !cursor-pointer flex-col`}
checklists={card.checklists ?? []} shallow={true}
members={[]} onClick={() => {
description={card.description} openModal("CARD");
comments={card.comments ?? []} }}
attachments={card.attachments} >
/> <Card
</Link> title={card.title}
))} labels={card.labels}
checklists={card.checklists ?? []}
members={[]}
description={card.description}
comments={card.comments ?? []}
attachments={card.attachments}
dueDate={card.dueDate ?? null}
/>
</Link>
);
})}
</div> </div>
</div> </div>
))} ))}

View File

@@ -13,6 +13,7 @@ services:
- .env - .env
restart: unless-stopped restart: unless-stopped
environment: environment:
- KAN_ADMIN_API_KEY=${KAN_ADMIN_API_KEY}
- NEXT_PUBLIC_KAN_ENV=${NEXT_PUBLIC_KAN_ENV} - NEXT_PUBLIC_KAN_ENV=${NEXT_PUBLIC_KAN_ENV}
- NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL} - NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET} - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
@@ -35,10 +36,12 @@ services:
- SMTP_PASSWORD=${SMTP_PASSWORD} - SMTP_PASSWORD=${SMTP_PASSWORD}
- SMTP_SECURE=${SMTP_SECURE} - SMTP_SECURE=${SMTP_SECURE}
- EMAIL_FROM=${EMAIL_FROM} - EMAIL_FROM=${EMAIL_FROM}
- SMTP_REJECT_UNAUTHORIZED=${SMTP_REJECT_UNAUTHORIZED}
# Notifications # Notifications
- NOVU_API_KEY=${NOVU_API_KEY} - NOVU_API_KEY=${NOVU_API_KEY}
- DISCORD_WEBHOOK_URL=${DISCORD_WEBHOOK_URL} - DISCORD_WEBHOOK_URL=${DISCORD_WEBHOOK_URL}
- EMAIL_UNSUBSCRIBE_SECRET=${EMAIL_UNSUBSCRIBE_SECRET}
# S3 storage # S3 storage
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID} - S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
@@ -63,6 +66,7 @@ services:
- BETTER_AUTH_TRUSTED_ORIGINS=${BETTER_AUTH_TRUSTED_ORIGINS} - BETTER_AUTH_TRUSTED_ORIGINS=${BETTER_AUTH_TRUSTED_ORIGINS}
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
- BETTER_AUTH_ALLOWED_DOMAINS=${BETTER_AUTH_ALLOWED_DOMAINS}
# Analytics # Analytics
- NEXT_PUBLIC_UMAMI_ID=${NEXT_PUBLIC_UMAMI_ID} - NEXT_PUBLIC_UMAMI_ID=${NEXT_PUBLIC_UMAMI_ID}

View File

@@ -18,12 +18,16 @@ services:
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET} - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
- POSTGRES_URL=${POSTGRES_URL} - POSTGRES_URL=${POSTGRES_URL}
# Admin API key (optional)
- KAN_ADMIN_API_KEY=${KAN_ADMIN_API_KEY}
# SMTP (optional) # SMTP (optional)
- SMTP_HOST=${SMTP_HOST} - SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=${SMTP_PORT} - SMTP_PORT=${SMTP_PORT}
- SMTP_USER=${SMTP_USER} - SMTP_USER=${SMTP_USER}
- SMTP_PASSWORD=${SMTP_PASSWORD} - SMTP_PASSWORD=${SMTP_PASSWORD}
- EMAIL_FROM=${EMAIL_FROM} - EMAIL_FROM=${EMAIL_FROM}
- SMTP_REJECT_UNAUTHORIZED=${SMTP_REJECT_UNAUTHORIZED}
# Disable email features entirely (optional) # Disable email features entirely (optional)
- NEXT_PUBLIC_DISABLE_EMAIL=${NEXT_PUBLIC_DISABLE_EMAIL} - NEXT_PUBLIC_DISABLE_EMAIL=${NEXT_PUBLIC_DISABLE_EMAIL}
@@ -59,6 +63,7 @@ services:
- BETTER_AUTH_TRUSTED_ORIGINS=${BETTER_AUTH_TRUSTED_ORIGINS} - BETTER_AUTH_TRUSTED_ORIGINS=${BETTER_AUTH_TRUSTED_ORIGINS}
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
- BETTER_AUTH_ALLOWED_DOMAINS=${BETTER_AUTH_ALLOWED_DOMAINS}
- DISCORD_CLIENT_ID=${DISCORD_CLIENT_ID} - DISCORD_CLIENT_ID=${DISCORD_CLIENT_ID}
- DISCORD_CLIENT_SECRET=${DISCORD_CLIENT_SECRET} - DISCORD_CLIENT_SECRET=${DISCORD_CLIENT_SECRET}
- GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID} - GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID}

View File

@@ -9,5 +9,15 @@ export const openApiDocument = generateOpenApiDocument(appRouter, {
version: "1.0.0", version: "1.0.0",
baseUrl: `${env("NEXT_PUBLIC_BASE_URL")}/api/v1`, baseUrl: `${env("NEXT_PUBLIC_BASE_URL")}/api/v1`,
docsUrl: "docs.kan.bn", docsUrl: "docs.kan.bn",
tags: ["Auth", "Users", "Boards", "Lists", "Cards", "Labels", "Imports", "Integrations"], tags: [
"Auth",
"Users",
"Boards",
"Lists",
"Cards",
"Labels",
"Imports",
"Integrations",
"Health",
],
}); });

View File

@@ -3,6 +3,7 @@ import { boardRouter } from "./routers/board";
import { cardRouter } from "./routers/card"; import { cardRouter } from "./routers/card";
import { checklistRouter } from "./routers/checklist"; import { checklistRouter } from "./routers/checklist";
import { feedbackRouter } from "./routers/feedback"; import { feedbackRouter } from "./routers/feedback";
import { healthRouter } from "./routers/health";
import { importRouter } from "./routers/import"; import { importRouter } from "./routers/import";
import { integrationRouter } from "./routers/integration"; import { integrationRouter } from "./routers/integration";
import { labelRouter } from "./routers/label"; import { labelRouter } from "./routers/label";
@@ -18,6 +19,7 @@ export const appRouter = createTRPCRouter({
card: cardRouter, card: cardRouter,
checklist: checklistRouter, checklist: checklistRouter,
feedback: feedbackRouter, feedback: feedbackRouter,
health: healthRouter,
label: labelRouter, label: labelRouter,
list: listRouter, list: listRouter,
member: memberRouter, member: memberRouter,

View File

@@ -9,7 +9,7 @@ import { generateUID } from "@kan/shared/utils";
import { createTRPCRouter, protectedProcedure } from "../trpc"; import { createTRPCRouter, protectedProcedure } from "../trpc";
import { assertUserInWorkspace } from "../utils/auth"; import { assertUserInWorkspace } from "../utils/auth";
import { generateUploadUrl } from "../utils/s3"; import { deleteObject, generateUploadUrl } from "../utils/s3";
export const attachmentRouter = createTRPCRouter({ export const attachmentRouter = createTRPCRouter({
generateUploadUrl: protectedProcedure generateUploadUrl: protectedProcedure
@@ -189,6 +189,18 @@ export const attachmentRouter = createTRPCRouter({
await assertUserInWorkspace(ctx.db, userId, workspaceId); await assertUserInWorkspace(ctx.db, userId, workspaceId);
const bucket = process.env.NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME;
if (bucket) {
try {
await deleteObject(bucket, attachment.s3Key);
} catch (error) {
console.error(
`Failed to delete attachment from S3: ${attachment.s3Key}`,
error,
);
}
}
await cardAttachmentRepo.softDelete(ctx.db, { await cardAttachmentRepo.softDelete(ctx.db, {
attachmentId: attachment.id, attachmentId: attachment.id,
deletedAt: new Date(), deletedAt: new Date(),

View File

@@ -8,7 +8,11 @@ import * as labelRepo from "@kan/db/repository/label.repo";
import * as listRepo from "@kan/db/repository/list.repo"; import * as listRepo from "@kan/db/repository/list.repo";
import * as workspaceRepo from "@kan/db/repository/workspace.repo"; import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import { colours } from "@kan/shared/constants"; import { colours } from "@kan/shared/constants";
import { generateSlug, generateUID } from "@kan/shared/utils"; import {
convertDueDateFiltersToRanges,
generateSlug,
generateUID,
} from "@kan/shared/utils";
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc"; import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
import { assertUserInWorkspace } from "../utils/auth"; import { assertUserInWorkspace } from "../utils/auth";
@@ -79,6 +83,18 @@ export const boardRouter = createTRPCRouter({
members: z.array(z.string().min(12)).optional(), members: z.array(z.string().min(12)).optional(),
labels: z.array(z.string().min(12)).optional(), labels: z.array(z.string().min(12)).optional(),
lists: z.array(z.string().min(12)).optional(), lists: z.array(z.string().min(12)).optional(),
dueDateFilters: z
.array(
z.enum([
"overdue",
"today",
"tomorrow",
"next-week",
"next-month",
"no-due-date",
]),
)
.optional(),
type: z.enum(["regular", "template"]).optional(), type: z.enum(["regular", "template"]).optional(),
}), }),
) )
@@ -105,6 +121,11 @@ export const boardRouter = createTRPCRouter({
await assertUserInWorkspace(ctx.db, userId, board.workspaceId); await assertUserInWorkspace(ctx.db, userId, board.workspaceId);
// Convert semantic string filters to date ranges expected by the repo
const dueDateFilters = input.dueDateFilters
? convertDueDateFiltersToRanges(input.dueDateFilters)
: [];
const result = await boardRepo.getByPublicId( const result = await boardRepo.getByPublicId(
ctx.db, ctx.db,
input.boardPublicId, input.boardPublicId,
@@ -112,6 +133,7 @@ export const boardRouter = createTRPCRouter({
members: input.members ?? [], members: input.members ?? [],
labels: input.labels ?? [], labels: input.labels ?? [],
lists: input.lists ?? [], lists: input.lists ?? [],
dueDate: dueDateFilters,
type: input.type, type: input.type,
}, },
); );
@@ -145,6 +167,18 @@ export const boardRouter = createTRPCRouter({
members: z.array(z.string().min(12)).optional(), members: z.array(z.string().min(12)).optional(),
labels: z.array(z.string().min(12)).optional(), labels: z.array(z.string().min(12)).optional(),
lists: z.array(z.string().min(12)).optional(), lists: z.array(z.string().min(12)).optional(),
dueDateFilters: z
.array(
z.enum([
"overdue",
"today",
"tomorrow",
"next-week",
"next-month",
"no-due-date",
]),
)
.optional(),
}), }),
) )
.output(z.custom<Awaited<ReturnType<typeof boardRepo.getBySlug>>>()) .output(z.custom<Awaited<ReturnType<typeof boardRepo.getBySlug>>>())
@@ -160,6 +194,11 @@ export const boardRouter = createTRPCRouter({
code: "NOT_FOUND", code: "NOT_FOUND",
}); });
// Convert semantic string filters to date ranges expected by the repo
const dueDateFilters = input.dueDateFilters
? convertDueDateFiltersToRanges(input.dueDateFilters)
: [];
const result = await boardRepo.getBySlug( const result = await boardRepo.getBySlug(
ctx.db, ctx.db,
input.boardSlug, input.boardSlug,
@@ -168,6 +207,7 @@ export const boardRouter = createTRPCRouter({
members: input.members ?? [], members: input.members ?? [],
labels: input.labels ?? [], labels: input.labels ?? [],
lists: input.lists ?? [], lists: input.lists ?? [],
dueDate: dueDateFilters,
}, },
); );
@@ -239,6 +279,7 @@ export const boardRouter = createTRPCRouter({
members: [], members: [],
labels: [], labels: [],
lists: [], lists: [],
dueDate: [],
type: sourceBoardInfo.type, type: sourceBoardInfo.type,
}, },
); );
@@ -281,12 +322,6 @@ export const boardRouter = createTRPCRouter({
sourceBoardId: sourceBoardInfo.id, sourceBoardId: sourceBoardInfo.id,
}); });
if (!result)
throw new TRPCError({
message: `Failed to create board from source`,
code: "INTERNAL_SERVER_ERROR",
});
return result; return result;
} }

View File

@@ -9,6 +9,7 @@ import * as listRepo from "@kan/db/repository/list.repo";
import * as workspaceRepo from "@kan/db/repository/workspace.repo"; import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc"; import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
import { mergeActivities } from "../utils/activities";
import { assertUserInWorkspace } from "../utils/auth"; import { assertUserInWorkspace } from "../utils/auth";
import { generateDownloadUrl } from "../utils/s3"; import { generateDownloadUrl } from "../utils/s3";
@@ -32,6 +33,7 @@ export const cardRouter = createTRPCRouter({
labelPublicIds: z.array(z.string().min(12)), labelPublicIds: z.array(z.string().min(12)),
memberPublicIds: z.array(z.string().min(12)), memberPublicIds: z.array(z.string().min(12)),
position: z.enum(["start", "end"]), position: z.enum(["start", "end"]),
dueDate: z.date().nullable().optional(),
}), }),
) )
.output(z.custom<Awaited<ReturnType<typeof cardRepo.create>>>()) .output(z.custom<Awaited<ReturnType<typeof cardRepo.create>>>())
@@ -69,6 +71,7 @@ export const cardRouter = createTRPCRouter({
createdBy: userId, createdBy: userId,
listId: list.id, listId: list.id,
position: input.position, position: input.position,
dueDate: input.dueDate ?? null,
}); });
const newCardId = newCard.id; const newCardId = newCard.id;
@@ -668,6 +671,81 @@ export const cardRouter = createTRPCRouter({
return { ...result, attachments: [] }; return { ...result, attachments: [] };
}), }),
getActivities: publicProcedure
.meta({
openapi: {
summary: "Get paginated card activities",
method: "GET",
path: "/cards/{cardPublicId}/activities",
description:
"Retrieves paginated activities for a card with merged frequent changes",
tags: ["Cards"],
},
})
.input(
z.object({
cardPublicId: z.string().min(12),
limit: z.number().min(1).max(100).optional().default(10),
cursor: z.string().datetime().optional(), // ISO datetime string
}),
)
.output(
z.object({
activities: z.array(
z.custom<
NonNullable<
Awaited<
ReturnType<typeof cardActivityRepo.getPaginatedActivities>
>
>["activities"][number]
>(),
),
hasMore: z.boolean(),
nextCursor: z.string().datetime().nullable(),
}),
)
.query(async ({ ctx, input }) => {
const card = await cardRepo.getWorkspaceAndCardIdByCardPublicId(
ctx.db,
input.cardPublicId,
);
if (!card)
throw new TRPCError({
message: `Card with public ID ${input.cardPublicId} not found`,
code: "NOT_FOUND",
});
if (card.workspaceVisibility === "private") {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
await assertUserInWorkspace(ctx.db, userId, card.workspaceId);
}
const cursor = input.cursor ? new Date(input.cursor) : undefined;
const result = await cardActivityRepo.getPaginatedActivities(
ctx.db,
card.id,
{
limit: input.limit,
cursor,
},
);
const mergedActivities = mergeActivities(result.activities);
return {
activities: mergedActivities,
hasMore: result.hasMore,
nextCursor: result.nextCursor?.toISOString() ?? null,
};
}),
update: protectedProcedure update: protectedProcedure
.meta({ .meta({
openapi: { openapi: {
@@ -686,6 +764,7 @@ export const cardRouter = createTRPCRouter({
description: z.string().optional(), description: z.string().optional(),
index: z.number().optional(), index: z.number().optional(),
listPublicId: z.string().min(12).optional(), listPublicId: z.string().min(12).optional(),
dueDate: z.date().nullable().optional(),
}), }),
) )
.output(z.custom<Awaited<ReturnType<typeof cardRepo.update>>>()) .output(z.custom<Awaited<ReturnType<typeof cardRepo.update>>>())
@@ -746,15 +825,19 @@ export const cardRouter = createTRPCRouter({
title: string; title: string;
description: string | null; description: string | null;
publicId: string; publicId: string;
dueDate: Date | null;
} }
| undefined; | undefined;
if (input.title || input.description) { const previousDueDate = existingCard.dueDate;
if (input.title || input.description || input.dueDate !== undefined) {
result = await cardRepo.update( result = await cardRepo.update(
ctx.db, ctx.db,
{ {
...(input.title && { title: input.title }), ...(input.title && { title: input.title }),
...(input.description && { description: input.description }), ...(input.description && { description: input.description }),
...(input.dueDate !== undefined && { dueDate: input.dueDate }),
}, },
{ cardPublicId: input.cardPublicId }, { cardPublicId: input.cardPublicId },
); );
@@ -796,6 +879,32 @@ export const cardRouter = createTRPCRouter({
}); });
} }
if (
input.dueDate !== undefined &&
previousDueDate?.getTime() !== input.dueDate?.getTime()
) {
let activityType:
| "card.updated.dueDate.added"
| "card.updated.dueDate.updated"
| "card.updated.dueDate.removed";
if (!previousDueDate) {
activityType = "card.updated.dueDate.added";
} else if (!input.dueDate) {
activityType = "card.updated.dueDate.removed";
} else {
activityType = "card.updated.dueDate.updated";
}
activities.push({
type: activityType,
cardId: result.id,
createdBy: userId,
fromDueDate: previousDueDate ?? undefined,
toDueDate: input.dueDate ?? undefined,
});
}
if (newListId && existingCard.listId !== newListId) { if (newListId && existingCard.listId !== newListId) {
activities.push({ activities.push({
type: "card.updated.list" as const, type: "card.updated.list" as const,

View File

@@ -269,7 +269,7 @@ export const checklistRouter = createTRPCRouter({
.meta({ .meta({
openapi: { openapi: {
summary: "Update a checklist item", summary: "Update a checklist item",
method: "PUT", method: "PATCH",
path: "/checklists/items/{checklistItemPublicId}", path: "/checklists/items/{checklistItemPublicId}",
description: "Updates a checklist item (title/completed)", description: "Updates a checklist item (title/completed)",
tags: ["Cards"], tags: ["Cards"],
@@ -281,6 +281,7 @@ export const checklistRouter = createTRPCRouter({
checklistItemPublicId: z.string().length(12), checklistItemPublicId: z.string().length(12),
title: z.string().min(1).max(500).optional(), title: z.string().min(1).max(500).optional(),
completed: z.boolean().optional(), completed: z.boolean().optional(),
index: z.number().int().min(0).optional(),
}), }),
) )
.output(checklistItemSchema) .output(checklistItemSchema)
@@ -312,17 +313,30 @@ export const checklistRouter = createTRPCRouter({
const previousTitle = item.title; const previousTitle = item.title;
const updated = await checklistRepo.updateItemById(ctx.db, { let updatedItem;
id: item.id,
title: input.title, if (input.title !== undefined || input.completed !== undefined) {
completed: input.completed, updatedItem = await checklistRepo.updateItemById(ctx.db, {
}); id: item.id,
title: input.title,
completed: input.completed,
});
}
if (input.index !== undefined) {
updatedItem = await checklistRepo.reorderItem(ctx.db, {
itemId: item.id,
newIndex: input.index,
});
}
if (!updatedItem) {
throw new TRPCError({
message: `Failed to update checklist item`,
code: "INTERNAL_SERVER_ERROR",
});
}
if (!updated)
throw new TRPCError({
message: `Failed to update checklist item`,
code: "INTERNAL_SERVER_ERROR",
});
// Log completion toggle // Log completion toggle
if (input.completed !== undefined) { if (input.completed !== undefined) {
@@ -331,7 +345,7 @@ export const checklistRouter = createTRPCRouter({
? "card.updated.checklist.item.completed" ? "card.updated.checklist.item.completed"
: "card.updated.checklist.item.uncompleted", : "card.updated.checklist.item.uncompleted",
cardId: item.checklist.cardId, cardId: item.checklist.cardId,
toTitle: updated.title, toTitle: updatedItem.title,
createdBy: userId, createdBy: userId,
}); });
} }
@@ -342,12 +356,13 @@ export const checklistRouter = createTRPCRouter({
type: "card.updated.checklist.item.updated", type: "card.updated.checklist.item.updated",
cardId: item.checklist.cardId, cardId: item.checklist.cardId,
fromTitle: previousTitle, fromTitle: previousTitle,
toTitle: updated.title, toTitle: updatedItem.title,
createdBy: userId, createdBy: userId,
}); });
} }
return updated; return updatedItem;
}), }),
deleteItem: protectedProcedure deleteItem: protectedProcedure
.meta({ .meta({

View File

@@ -0,0 +1,203 @@
import { HeadBucketCommand } from "@aws-sdk/client-s3";
import { TRPCError } from "@trpc/server";
import { sql } from "drizzle-orm";
import { env } from "next-runtime-env";
import { z } from "zod";
import type { dbClient } from "@kan/db/client";
import * as boardRepo from "@kan/db/repository/board.repo";
import * as cardRepo from "@kan/db/repository/card.repo";
import * as cardActivityRepo from "@kan/db/repository/cardActivity.repo";
import * as cardAttachmentRepo from "@kan/db/repository/cardAttachment.repo";
import * as cardCommentRepo from "@kan/db/repository/cardComment.repo";
import * as checklistRepo from "@kan/db/repository/checklist.repo";
import * as importRepo from "@kan/db/repository/import.repo";
import * as inviteLinkRepo from "@kan/db/repository/inviteLink.repo";
import * as labelRepo from "@kan/db/repository/label.repo";
import * as listRepo from "@kan/db/repository/list.repo";
import * as memberRepo from "@kan/db/repository/member.repo";
import * as userRepo from "@kan/db/repository/user.repo";
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import {
adminProtectedProcedure,
createTRPCRouter,
publicProcedure,
} from "../trpc";
import { createS3Client } from "../utils/s3";
const checkDatabaseConnection = async (db: dbClient) => {
try {
await db.execute(sql`SELECT 1`);
return true;
} catch {
return false;
}
};
const checkS3Connection = async () => {
try {
// Check if S3 is configured
if (
!process.env.S3_ENDPOINT ||
!process.env.S3_ACCESS_KEY_ID ||
!process.env.S3_SECRET_ACCESS_KEY
) {
// S3 is optional, so return true if not configured
return true;
}
const client = createS3Client();
const avatarBucketName = env("NEXT_PUBLIC_AVATAR_BUCKET_NAME");
const attachmentsBucketName = env("NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME");
await client.send(new HeadBucketCommand({ Bucket: avatarBucketName }));
await client.send(new HeadBucketCommand({ Bucket: attachmentsBucketName }));
return true;
} catch (error) {
console.error(error);
return false;
}
};
export const healthRouter = createTRPCRouter({
health: publicProcedure
.meta({
openapi: {
method: "GET",
path: "/health",
summary: "Health check",
description:
"Returns the health status of the application and its dependencies",
tags: ["Health"],
protect: false,
},
})
.input(z.void())
.output(
z.object({
status: z.enum(["ok", "error"]),
database: z.enum(["ok", "error"]).optional(),
storage: z.enum(["ok", "error", "not_configured"]).optional(),
}),
)
.query(async ({ ctx }) => {
const dbHealthy = await checkDatabaseConnection(ctx.db);
const s3Healthy = await checkS3Connection();
const s3Configured = !!(
process.env.S3_ENDPOINT &&
process.env.S3_ACCESS_KEY_ID &&
process.env.S3_SECRET_ACCESS_KEY
);
const database = dbHealthy ? "ok" : "error";
const storage = !s3Configured
? "not_configured"
: s3Healthy
? "ok"
: "error";
// Overall status is "ok" only if database is healthy and (storage is not configured or storage is healthy)
const status = dbHealthy && (!s3Configured || s3Healthy) ? "ok" : "error";
return {
status,
database,
storage,
};
}),
stats: adminProtectedProcedure
.meta({
openapi: {
method: "GET",
path: "/stats",
summary: "Get statistics",
description:
"Returns statistics about the application (workspaces, users, cards, etc.)",
tags: ["Health"],
protect: true,
},
})
.input(z.void())
.output(
z.object({
users: z.number(),
workspaces: z.number(),
boards: z.number(),
lists: z.number(),
cards: z.number(),
cardComments: z.number(),
cardAttachments: z.number(),
cardActivityLogs: z.number(),
labels: z.number(),
checklists: z.number(),
checklistItems: z.number(),
activeMembers: z.number(),
activeInviteLinks: z.number(),
imports: z.number(),
}),
)
.query(async ({ ctx }) => {
try {
// Execute all count queries in parallel
const [
usersCount,
workspacesCount,
boardsCount,
listsCount,
cardsCount,
cardCommentsCount,
checklistItemsCount,
checklistsCount,
labelsCount,
cardAttachmentsCount,
cardActivitiesCount,
activeMembersCount,
activeInviteLinksCount,
importsCount,
cardActivityLogsCount,
] = await Promise.all([
userRepo.getCount(ctx.db),
workspaceRepo.getCount(ctx.db),
boardRepo.getCount(ctx.db),
listRepo.getCount(ctx.db),
cardRepo.getCount(ctx.db),
cardCommentRepo.getCount(ctx.db),
checklistRepo.getCountItems(ctx.db),
checklistRepo.getCount(ctx.db),
labelRepo.getCount(ctx.db),
cardAttachmentRepo.getCount(ctx.db),
cardActivityRepo.getCount(ctx.db),
memberRepo.getActiveCount(ctx.db),
inviteLinkRepo.getActiveCount(ctx.db),
importRepo.getCount(ctx.db),
memberRepo.getActiveCount(ctx.db),
cardActivityRepo.getCount(ctx.db),
]);
return {
users: usersCount,
workspaces: workspacesCount,
boards: boardsCount,
lists: listsCount,
cards: cardsCount,
cardComments: cardCommentsCount,
checklistItems: checklistItemsCount,
checklists: checklistsCount,
labels: labelsCount,
cardAttachments: cardAttachmentsCount,
cardActivities: cardActivitiesCount,
activeMembers: activeMembersCount,
activeInviteLinks: activeInviteLinksCount,
imports: importsCount,
cardActivityLogs: cardActivityLogsCount,
};
} catch (error) {
throw new TRPCError({
message: `Failed to retrieve statistics: ${error instanceof Error ? error.message : "Unknown error"}`,
code: "INTERNAL_SERVER_ERROR",
});
}
}),
});

View File

@@ -1,4 +1,5 @@
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { env } from "next-runtime-env";
import { z } from "zod"; import { z } from "zod";
import * as inviteLinkRepo from "@kan/db/repository/inviteLink.repo"; import * as inviteLinkRepo from "@kan/db/repository/inviteLink.repo";
@@ -307,7 +308,7 @@ export const memberRouter = createTRPCRouter({
return { return {
id: activeInviteLink.id, id: activeInviteLink.id,
inviteCode: activeInviteLink.code, inviteCode: activeInviteLink.code,
inviteLink: `${process.env.NEXT_PUBLIC_BASE_URL}/invite/${activeInviteLink.code}`, inviteLink: `${env("NEXT_PUBLIC_BASE_URL")}/invite/${activeInviteLink.code}`,
isActive: true, isActive: true,
expiresAt: activeInviteLink.expiresAt ?? undefined, expiresAt: activeInviteLink.expiresAt ?? undefined,
}; };
@@ -415,7 +416,7 @@ export const memberRouter = createTRPCRouter({
return { return {
publicId: inviteLink.publicId, publicId: inviteLink.publicId,
inviteCode: inviteLink.code, 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, expiresAt: inviteLink.expiresAt,
}; };
}), }),

View File

@@ -2,6 +2,7 @@ import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
import type { NextApiRequest } from "next"; import type { NextApiRequest } from "next";
import type { OpenApiMeta } from "trpc-to-openapi"; import type { OpenApiMeta } from "trpc-to-openapi";
import { initTRPC, TRPCError } from "@trpc/server"; import { initTRPC, TRPCError } from "@trpc/server";
import { env } from "next-runtime-env";
import superjson from "superjson"; import superjson from "superjson";
import { ZodError } from "zod"; import { ZodError } from "zod";
@@ -45,6 +46,7 @@ interface CreateContextOptions {
user: User | null | undefined; user: User | null | undefined;
db: dbClient; db: dbClient;
auth: ReturnType<typeof createAuthWithHeaders>; auth: ReturnType<typeof createAuthWithHeaders>;
headers: Headers;
} }
export const createInnerTRPCContext = (opts: CreateContextOptions) => { export const createInnerTRPCContext = (opts: CreateContextOptions) => {
@@ -52,6 +54,7 @@ export const createInnerTRPCContext = (opts: CreateContextOptions) => {
user: opts.user, user: opts.user,
db: opts.db, db: opts.db,
auth: opts.auth, auth: opts.auth,
headers: opts.headers,
}; };
}; };
@@ -63,7 +66,7 @@ export const createTRPCContext = async ({ req }: CreateNextContextOptions) => {
const session = await auth.api.getSession(); const session = await auth.api.getSession();
return createInnerTRPCContext({ db, user: session?.user, auth }); return createInnerTRPCContext({ db, user: session?.user, auth, headers });
}; };
export const createNextApiContext = async (req: NextApiRequest) => { export const createNextApiContext = async (req: NextApiRequest) => {
@@ -74,7 +77,7 @@ export const createNextApiContext = async (req: NextApiRequest) => {
const session = await auth.api.getSession(); const session = await auth.api.getSession();
return createInnerTRPCContext({ db, user: session?.user, auth }); return createInnerTRPCContext({ db, user: session?.user, auth, headers });
}; };
export const createRESTContext = async ({ req }: CreateNextContextOptions) => { export const createRESTContext = async ({ req }: CreateNextContextOptions) => {
@@ -91,7 +94,7 @@ export const createRESTContext = async ({ req }: CreateNextContextOptions) => {
throw error; throw error;
} }
return createInnerTRPCContext({ db, user: session?.user, auth }); return createInnerTRPCContext({ db, user: session?.user, auth, headers });
}; };
const t = initTRPC const t = initTRPC
@@ -129,9 +132,28 @@ const enforceUserIsAuthed = t.middleware(async ({ ctx, next }) => {
}); });
}); });
const enforceUserIsAdmin = t.middleware(async ({ ctx, next }) => {
if (ctx.headers.get("x-admin-api-key") !== env("KAN_ADMIN_API_KEY")) {
throw new TRPCError({ code: "UNAUTHORIZED" });
}
return next({
ctx,
});
});
export const protectedProcedure = t.procedure.use(enforceUserIsAuthed).meta({ export const protectedProcedure = t.procedure.use(enforceUserIsAuthed).meta({
openapi: { openapi: {
method: "GET", method: "GET",
path: "/protected", path: "/protected",
}, },
}); });
export const adminProtectedProcedure = t.procedure
.use(enforceUserIsAdmin)
.meta({
openapi: {
method: "GET",
path: "/admin/protected",
},
});

View File

@@ -2,6 +2,7 @@ import type { RouterInputs, RouterOutputs } from "../index";
export type GetBoardByIdOutput = RouterOutputs["board"]["byId"]; export type GetBoardByIdOutput = RouterOutputs["board"]["byId"];
export type GetCardByIdOutput = RouterOutputs["card"]["byId"]; export type GetCardByIdOutput = RouterOutputs["card"]["byId"];
export type GetCardActivitiesOutput = RouterOutputs["card"]["getActivities"];
export type UpdateBoardInput = RouterInputs["board"]["update"]; export type UpdateBoardInput = RouterInputs["board"]["update"];
export type NewLabelInput = RouterInputs["label"]["create"]; export type NewLabelInput = RouterInputs["label"]["create"];
export type NewListInput = RouterInputs["list"]["create"]; export type NewListInput = RouterInputs["list"]["create"];

View File

@@ -0,0 +1,109 @@
import type { PaginatedActivitiesResult } from "@kan/db/repository/cardActivity.repo";
import type { ActivityType } from "@kan/db/schema";
type ActivityBase = PaginatedActivitiesResult["activities"][number];
interface Activity extends ActivityBase {
mergeCount?: number; // number of activities merged into this one
mergedLabels?: string[]; // list of label names when merging label activities
}
// types that can be merged with simple count
const MERGEABLE_COUNT_TYPES: readonly ActivityType[] = [
"card.updated.description",
];
// types that merge with a list of items
const MERGEABLE_LIST_TYPES: readonly ActivityType[] = [
"card.updated.label.added",
"card.updated.label.removed",
];
const MERGE_TIME_WINDOW_MS = 5 * 60 * 1000; // 5 minutes window for merging activities
export function mergeActivities(activities: Activity[]): Activity[] {
if (activities.length === 0) return [];
const merged: Activity[] = [];
let i = 0;
while (i < activities.length) {
const current = activities[i];
if (!current) {
i++;
continue;
}
const currentType = current.type;
const isCountMergeable = MERGEABLE_COUNT_TYPES.includes(currentType);
const isListMergeable = MERGEABLE_LIST_TYPES.includes(currentType);
const canMerge = (isCountMergeable || isListMergeable) && current.user?.id;
if (!canMerge) {
merged.push(current);
i++;
continue;
}
const group: Activity[] = [current];
let j = i + 1;
while (j < activities.length) {
const next = activities[j];
if (!next) break;
const timeDiff =
new Date(next.createdAt).getTime() -
new Date(current.createdAt).getTime();
if (
next.type === current.type &&
next.user?.id === current.user?.id &&
timeDiff >= 0 && // next is newer or same time
timeDiff <= MERGE_TIME_WINDOW_MS
) {
group.push(next);
j++;
} else {
break;
}
}
if (group.length > 1) {
const oldest = group[0];
const latest = group[group.length - 1];
if (oldest && latest) {
if (isListMergeable) {
const labelNames = group
.map((a) => a.label?.name)
.filter((name): name is string => !!name);
merged.push({
...oldest,
createdAt: oldest.createdAt,
mergeCount: group.length,
mergedLabels: labelNames,
});
} else {
merged.push({
...oldest,
createdAt: oldest.createdAt,
toDescription: latest.toDescription,
fromDescription: oldest.fromDescription,
mergeCount: group.length,
});
}
} else {
merged.push(current);
}
} else {
merged.push(current);
}
i = j;
}
return merged;
}

View File

@@ -1,4 +1,5 @@
import { import {
DeleteObjectCommand,
GetObjectCommand, GetObjectCommand,
PutObjectCommand, PutObjectCommand,
S3Client, S3Client,
@@ -6,14 +7,19 @@ import {
import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
export function createS3Client() { export function createS3Client() {
const credentials =
process.env.S3_ACCESS_KEY_ID && process.env.S3_SECRET_ACCESS_KEY
? {
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
}
: undefined;
return new S3Client({ return new S3Client({
region: process.env.S3_REGION ?? "", region: process.env.S3_REGION ?? "",
endpoint: process.env.S3_ENDPOINT ?? "", endpoint: process.env.S3_ENDPOINT ?? "",
forcePathStyle: process.env.S3_FORCE_PATH_STYLE === "true", forcePathStyle: process.env.S3_FORCE_PATH_STYLE === "true",
credentials: { credentials,
accessKeyId: process.env.S3_ACCESS_KEY_ID ?? "",
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY ?? "",
},
}); });
} }
@@ -51,3 +57,13 @@ export async function generateDownloadUrl(
{ expiresIn }, { expiresIn },
); );
} }
export async function deleteObject(bucket: string, key: string) {
const client = createS3Client();
await client.send(
new DeleteObjectCommand({
Bucket: bucket,
Key: key,
}),
);
}

View File

@@ -37,7 +37,7 @@
}, },
"prettier": "@kan/prettier-config", "prettier": "@kan/prettier-config",
"dependencies": { "dependencies": {
"@better-auth/stripe": "^1.3.7", "@better-auth/stripe": "^1.4.6",
"better-auth": "^1.3.7" "better-auth": "^1.4.6"
} }
} }

View File

@@ -18,6 +18,7 @@ import * as userRepo from "@kan/db/repository/user.repo";
import * as workspaceRepo from "@kan/db/repository/workspace.repo"; import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import * as schema from "@kan/db/schema"; import * as schema from "@kan/db/schema";
import { notificationClient, sendEmail } from "@kan/email"; import { notificationClient, sendEmail } from "@kan/email";
import { createEmailUnsubscribeLink } from "@kan/shared";
import { createStripeClient } from "@kan/stripe"; import { createStripeClient } from "@kan/stripe";
export const configuredProviders = socialProviderList.reduce< export const configuredProviders = socialProviderList.reduce<
@@ -31,6 +32,9 @@ export const configuredProviders = socialProviderList.reduce<
requireSelectAccount?: boolean; requireSelectAccount?: boolean;
clientKey?: string; clientKey?: string;
issuer?: string; issuer?: string;
// Google-specific optional hints
hostedDomain?: string;
hd?: string;
} }
> >
>((acc, provider) => { >((acc, provider) => {
@@ -68,6 +72,21 @@ export const configuredProviders = socialProviderList.reduce<
acc[provider].tenantId = "common"; acc[provider].tenantId = "common";
acc[provider].requireSelectAccount = true; acc[provider].requireSelectAccount = true;
} }
// Add Google domain hint if allowed domains is configured
if (
provider === "google" &&
Object.keys(acc).includes("google") &&
acc[provider]
) {
const allowed = process.env.BETTER_AUTH_ALLOWED_DOMAINS?.split(",")
.map((d) => d.trim().toLowerCase())
.filter(Boolean);
if (allowed && allowed.length > 0) {
// Use the first domain as an authorization hint
acc[provider].hostedDomain = allowed[0];
acc[provider].hd = allowed[0];
}
}
if ( if (
provider === "tiktok" && provider === "tiktok" &&
Object.keys(acc).includes("tiktok") && Object.keys(acc).includes("tiktok") &&
@@ -279,9 +298,8 @@ export const initAuth = (db: dbClient) => {
}), }),
] ]
: []), : []),
// @todo: hasing is disabled due to a bug in the api key plugin
apiKey({ apiKey({
disableKeyHashing: true, enableSessionForAPIKeys: true,
rateLimit: { rateLimit: {
enabled: true, enabled: true,
timeWindow: 1000 * 60, // 1 minute timeWindow: 1000 * 60, // 1 minute
@@ -342,7 +360,17 @@ export const initAuth = (db: dbClient) => {
return Promise.resolve(false); return Promise.resolve(false);
} }
return Promise.resolve(true); // Fall through to any additional checks below
}
// Enforce allowed domains (OIDC/social) if configured
const allowed = process.env.BETTER_AUTH_ALLOWED_DOMAINS?.split(",")
.map((d) => d.trim().toLowerCase())
.filter(Boolean);
if (allowed && allowed.length > 0) {
const domain = user.email.split("@")[1]?.toLowerCase();
if (!domain || !allowed.includes(domain)) {
return Promise.resolve(false);
}
} }
return Promise.resolve(true); return Promise.resolve(true);
}, },
@@ -353,14 +381,19 @@ export const initAuth = (db: dbClient) => {
!user.image.includes(process.env.NEXT_PUBLIC_STORAGE_DOMAIN!) !user.image.includes(process.env.NEXT_PUBLIC_STORAGE_DOMAIN!)
) { ) {
try { try {
const credentials =
env("S3_ACCESS_KEY_ID") && env("S3_SECRET_ACCESS_KEY")
? {
accessKeyId: env("S3_ACCESS_KEY_ID")!,
secretAccessKey: env("S3_SECRET_ACCESS_KEY")!,
}
: undefined;
const client = new S3Client({ const client = new S3Client({
region: env("S3_REGION") ?? "", region: env("S3_REGION") ?? "",
endpoint: env("S3_ENDPOINT") ?? "", endpoint: env("S3_ENDPOINT") ?? "",
forcePathStyle: env("S3_FORCE_PATH_STYLE") === "true", forcePathStyle: env("S3_FORCE_PATH_STYLE") === "true",
credentials: { credentials,
accessKeyId: env("S3_ACCESS_KEY_ID") ?? "",
secretAccessKey: env("S3_SECRET_ACCESS_KEY") ?? "",
},
}); });
const allowedFileExtensions = ["jpg", "jpeg", "png", "webp"]; const allowedFileExtensions = ["jpg", "jpeg", "png", "webp"];
@@ -401,6 +434,10 @@ export const initAuth = (db: dbClient) => {
? `${env("NEXT_PUBLIC_STORAGE_URL")}/${env("NEXT_PUBLIC_AVATAR_BUCKET_NAME")}/${avatarKey}` ? `${env("NEXT_PUBLIC_STORAGE_URL")}/${env("NEXT_PUBLIC_AVATAR_BUCKET_NAME")}/${avatarKey}`
: undefined; : undefined;
const unsubscribeUrl = await createEmailUnsubscribeLink(
user.id,
);
await notificationClient.trigger({ await notificationClient.trigger({
to: { to: {
subscriberId: user.id, subscriberId: user.id,
@@ -415,6 +452,9 @@ export const initAuth = (db: dbClient) => {
updatedAt: user.updatedAt, updatedAt: user.updatedAt,
}, },
}, },
payload: {
emailUnsubscribeUrl: unsubscribeUrl,
},
workflowId: "user-signup", workflowId: "user-signup",
}); });
@@ -489,6 +529,8 @@ async function triggerWorkflow(
if (!user || !notificationClient) return; if (!user || !notificationClient) return;
const unsubscribeUrl = await createEmailUnsubscribeLink(user.id);
await notificationClient.trigger({ await notificationClient.trigger({
to: { to: {
subscriberId: user.id, subscriberId: user.id,
@@ -496,6 +538,7 @@ async function triggerWorkflow(
payload: { payload: {
...subscription, ...subscription,
cancellationDetails, cancellationDetails,
emailUnsubscribeUrl: unsubscribeUrl,
}, },
workflowId, workflowId,
}); });

View File

@@ -0,0 +1,6 @@
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.dueDate.added' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.dueDate.updated' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.dueDate.removed' BEFORE 'card.archived';--> statement-breakpoint
ALTER TABLE "card_activity" ADD COLUMN "fromDueDate" timestamp;--> statement-breakpoint
ALTER TABLE "card_activity" ADD COLUMN "toDueDate" timestamp;--> statement-breakpoint
ALTER TABLE "card" ADD COLUMN "dueDate" timestamp;

File diff suppressed because it is too large Load Diff

View File

@@ -141,6 +141,13 @@
"when": 1762807463569, "when": 1762807463569,
"tag": "20251110204423_AddCardAttachments", "tag": "20251110204423_AddCardAttachments",
"breakpoints": true "breakpoints": true
},
{
"idx": 20,
"version": "7",
"when": 1764621815672,
"tag": "20251201204335_AddCardDueDates",
"breakpoints": true
} }
] ]
} }

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