Compare commits

...

10 Commits

Author SHA1 Message Date
Henry
eafe4d0cd8 fix: remove unused params from invite paths 2025-11-26 20:09:35 +00:00
Henry
50382e9186 feat(cloud): free trial notifications (#254) 2025-11-25 23:29:04 +00:00
Henry
00be5fb058 feat(cloud): add discord creds to subscribers 2025-11-25 13:22:43 +00:00
Henry
fc65f53e0c feat(cloud): add notification client (#253) 2025-11-24 22:20:34 +00:00
Henry
64aace6e3b feat: add breadcrumb navigation header to card view (#250)
* feat: add card breadcrumb navigation

* feat: wrap title onto new line
2025-11-21 21:34:12 +00:00
Henry
1651faae14 fix(cloud): reenable magic login on cloud and extend session duration (#248)
* fix(cloud): reenable magic login

* feat: extend session duration
2025-11-20 00:01:23 +00:00
Henry
b472c5ce93 feat: card attachments (#247)
* feat: add card attachment schema

* feat: setup s3 util funcs

* feat: add attachments router and repo funcs

* feat: add upload button

* feat: add thumbnails and attachment viewer

* feat: add download and delete button

* feat: add file viewer and downloads

* feat: update compose and readme

* chore: build lang

* feat: display attachments on public boards

* chore: update compiled translations
2025-11-19 21:34:43 +00:00
Arpit Soni
af6490896a feat: add list filter to board view (#241)
* feat: add list filter to board view

* feat: implement API-driven list filtering

* refactor: remove unnecessary list join from card filtering queries

* feat: enable list filter options for public boards

* refactor(perf): move to main query

---------

Co-authored-by: Henry <henry_ball@hotmail.co.uk>
2025-11-17 21:25:50 +00:00
exception-raised
c0a3c37d95 feat: add tiptap markdown support, add checklist support from trello (#245)
* feat: add tiptap markdown support, add checklist support from trello

* feat(api): implement bulk creation of checklists and items
2025-11-17 20:31:57 +00:00
Morfixx
c30da618ec fix(web): logic of disabling credential login (#244)
* fix(web): logic of disabling credential login

If credentials are disabled, then don't show the email login form at all. If credentials are disabled and no social providers are present, show message saying none are available.

* chore: update lang

---------

Co-authored-by: Henry <henry_ball@hotmail.co.uk>
2025-11-14 22:24:43 +00:00
69 changed files with 5942 additions and 861 deletions

View File

@@ -29,6 +29,7 @@ S3_SECRET_ACCESS_KEY=
S3_FORCE_PATH_STYLE= S3_FORCE_PATH_STYLE=
NEXT_PUBLIC_STORAGE_URL= NEXT_PUBLIC_STORAGE_URL=
NEXT_PUBLIC_AVATAR_BUCKET_NAME= NEXT_PUBLIC_AVATAR_BUCKET_NAME=
NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME=
NEXT_PUBLIC_STORAGE_DOMAIN= NEXT_PUBLIC_STORAGE_DOMAIN=
# Auth config (optional) # Auth config (optional)

View File

@@ -170,6 +170,7 @@ pnpm dev
| `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` | | `NEXT_PUBLIC_STORAGE_URL` | Storage service URL | For file uploads | `https://storage.kanbn.com` |
| `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` | | `NEXT_PUBLIC_STORAGE_DOMAIN` | Storage domain name | For file uploads | `kanbn.com` |
| `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` | | `NEXT_PUBLIC_AVATAR_BUCKET_NAME` | S3 bucket name for avatars | For file uploads | `avatars` |
| `NEXT_PUBLIC_ATTATCHMENTS_BUCKET_NAME` | S3 bucket name for attatchments | For file uploads | `attatchments` |
| `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` | | `NEXT_PUBLIC_ALLOW_CREDENTIALS` | Allow email & password login | For authentication | `true` |
| `NEXT_PUBLIC_DISABLE_SIGN_UP` | Disable sign up | For authentication | `false` | | `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` | | `NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY` | Hide “Powered by kan.bn” on public boards (self-host) | For white labelling | `true` |

View File

@@ -60,6 +60,7 @@ checksums:
Are%20you%20sure%20you%20want%20to%20delete%20your%20account%3F/singular: 428b74d781063224c3e63980e1094ec3 Are%20you%20sure%20you%20want%20to%20delete%20your%20account%3F/singular: 428b74d781063224c3e63980e1094ec3
assigned%20%3C0%3E%7B0%7D%3C%2F0%3E%20to%20the%20card/singular: 9df6d89fa83706123dedd8cba2243d04 assigned%20%3C0%3E%7B0%7D%3C%2F0%3E%20to%20the%20card/singular: 9df6d89fa83706123dedd8cba2243d04
Assignees/singular: 96fc0e28a783d80decfd4716a440ac08 Assignees/singular: 96fc0e28a783d80decfd4716a440ac08
Attachment%20uploaded/singular: c0233f8c2560f95ac0834f35eb07b9e7
Awaiting%20Customer/singular: 122c108794f321c10e05a08f09b11457 Awaiting%20Customer/singular: 122c108794f321c10e05a08f09b11457
Backlog/singular: 35919fd5b10ad212839a75e72829fe4e Backlog/singular: 35919fd5b10ad212839a75e72829fe4e
Basic%20Kanban/singular: e46ebc406749486f3907436970d4d6c7 Basic%20Kanban/singular: e46ebc406749486f3907436970d4d6c7
@@ -171,6 +172,7 @@ checksums:
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
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
@@ -209,6 +211,7 @@ checksums:
Failed%20to%20copy%20invite%20link/singular: 635884d5ed8d6ee20b85a003939b4ae7 Failed%20to%20copy%20invite%20link/singular: 635884d5ed8d6ee20b85a003939b4ae7
Failed%20to%20create%20board/singular: a746e2afe881c3bf0a8e82a931ca3495 Failed%20to%20create%20board/singular: a746e2afe881c3bf0a8e82a931ca3495
Failed%20to%20login%20with%20%7B0%7D.%20Please%20try%20again./singular: 669a4b4247a73f53fb9b8b16e42d166f Failed%20to%20login%20with%20%7B0%7D.%20Please%20try%20again./singular: 669a4b4247a73f53fb9b8b16e42d166f
Failed%20to%20upload%20attachment.%20Please%20try%20again./singular: f8a50d1c8491404f73d3cf701e11f297
FAQ/singular: 47e0ee2eb40b4e7e732e05e2233fc71c FAQ/singular: 47e0ee2eb40b4e7e732e05e2233fc71c
FAQs/singular: dc36d7992372ccd419b39ef51cf5b16c FAQs/singular: dc36d7992372ccd419b39ef51cf5b16c
Fast%20%26%20lightweight/singular: 4f2a80c555a5427b94eef5124aa10775 Fast%20%26%20lightweight/singular: 4f2a80c555a5427b94eef5124aa10775
@@ -295,6 +298,7 @@ checksums:
Link%20copied/singular: 4a4805700b31ec65bcb3ca962bccfd1b Link%20copied/singular: 4a4805700b31ec65bcb3ca962bccfd1b
List/singular: 94f13e7ef909a4de9db7abaa1f9f0b61 List/singular: 94f13e7ef909a4de9db7abaa1f9f0b61
List%20name/singular: e925e2e6ccaf0eb4064a888aaea8d3c2 List%20name/singular: e925e2e6ccaf0eb4064a888aaea8d3c2
Lists/singular: 9f4a73afc8de321175d71935134ef066
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
@@ -329,8 +333,10 @@ checksums:
Newsletter/singular: dcfb9666301924431ac8ae88e5b6f9d7 Newsletter/singular: dcfb9666301924431ac8ae88e5b6f9d7
Next%20Steps/singular: 12392fe73ae60b6e5a9d851256b8477e Next%20Steps/singular: 12392fe73ae60b6e5a9d851256b8477e
No%20%7B0%7D/singular: a7a95e1dfdb4396da9e2be0e27f42323 No%20%7B0%7D/singular: a7a95e1dfdb4396da9e2be0e27f42323
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%20download%20URL%20available%20for%20this%20attachment./singular: e367d39420b2242f9d2fd749c87f446a
No%20lists/singular: cedf633d99c77ff4356e089f2d98c0a6 No%20lists/singular: cedf633d99c77ff4356e089f2d98c0a6
No%20results%20found%20for%20%22%7BdebouncedQuery%7D%22./singular: 5db6294712528cd897b15ae36f4fd834 No%20results%20found%20for%20%22%7BdebouncedQuery%7D%22./singular: 5db6294712528cd897b15ae36f4fd834
Offer/singular: 82b4e0c9a3f5b4bd93590847de7c32a1 Offer/singular: 82b4e0c9a3f5b4bd93590847de7c32a1
@@ -476,6 +482,7 @@ checksums:
Unable%20to%20create%20list/singular: 7fbbf8314f8d08a4123c7daef09fed05 Unable%20to%20create%20list/singular: 7fbbf8314f8d08a4123c7daef09fed05
Unable%20to%20create%20template/singular: 7495f1434c9188849bffd015811d5337 Unable%20to%20create%20template/singular: 7495f1434c9188849bffd015811d5337
Unable%20to%20create%20workspace/singular: c1c949477e121d73ed6683eddf9cd874 Unable%20to%20create%20workspace/singular: c1c949477e121d73ed6683eddf9cd874
Unable%20to%20delete%20attachment/singular: 99d0b17b78d44e15f13d876d155f0efc
Unable%20to%20delete%20card/singular: 50ff06aa1265fe464f776aba33f1bef9 Unable%20to%20delete%20card/singular: 50ff06aa1265fe464f776aba33f1bef9
Unable%20to%20delete%20checklist/singular: d7067e2c009f4919f0cca77df3c228ee Unable%20to%20delete%20checklist/singular: d7067e2c009f4919f0cca77df3c228ee
Unable%20to%20delete%20checklist%20item/singular: a74144593b625e4d8d7ecf734462c60d Unable%20to%20delete%20checklist%20item/singular: a74144593b625e4d8d7ecf734462c60d
@@ -509,6 +516,7 @@ checksums:
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
Upgrade%20to%20Pro%20(%2429%2Fmonth)/singular: 9a91ea70f5eb55aac96640bf0fd7feff Upgrade%20to%20Pro%20(%2429%2Fmonth)/singular: 9a91ea70f5eb55aac96640bf0fd7feff
Upload%20failed/singular: 5b7b755f05330164dbfb00096c500ee3
Urgent/singular: e79afcd4398e52e10e7e8243a7eecabe Urgent/singular: e79afcd4398e52e10e7e8243a7eecabe
URL%20can%20only%20contain%20letters%2C%20numbers%2C%20and%20hyphens/singular: 875d37d2d920f98ef60a314eda8a5d9a URL%20can%20only%20contain%20letters%2C%20numbers%2C%20and%20hyphens/singular: 875d37d2d920f98ef60a314eda8a5d9a
URL%20cannot%20exceed%2024%20characters/singular: 395c25732b84ac1f5b63ee310da08e93 URL%20cannot%20exceed%2024%20characters/singular: 395c25732b84ac1f5b63ee310da08e93
@@ -563,6 +571,7 @@ checksums:
Your%20account%20has%20been%20deleted./singular: 8c8d944e07388c5877effdb2c2803dcf Your%20account%20has%20been%20deleted./singular: 8c8d944e07388c5877effdb2c2803dcf
Your%20boards%20have%20been%20imported./singular: 403972e7a25afc2415762c1c2b1ec868 Your%20boards%20have%20been%20imported./singular: 403972e7a25afc2415762c1c2b1ec868
Your%20display%20name%20has%20been%20updated./singular: 15e5fff36c554c16ec5214427fae1bf4 Your%20display%20name%20has%20been%20updated./singular: 15e5fff36c554c16ec5214427fae1bf4
Your%20file%20has%20been%20uploaded%20successfully./singular: 19d84e934877efc0fef285ff3d6e7849
Your%20password%20has%20been%20changed./singular: 8f730f68d52b7efa727aa0784282ebcb Your%20password%20has%20been%20changed./singular: 8f730f68d52b7efa727aa0784282ebcb
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

View File

@@ -30,23 +30,50 @@ const config = {
typescript: { ignoreBuildErrors: true }, typescript: { ignoreBuildErrors: true },
images: { images: {
remotePatterns: [ remotePatterns: (() => {
{ /** @type {Array<{protocol: "http" | "https", hostname: string}>} */
protocol: "https", const patterns = [
hostname: {
env("S3_FORCE_PATH_STYLE") === "true" protocol: "https",
? `${env("NEXT_PUBLIC_STORAGE_DOMAIN")}` hostname:
: `*.${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`, env("S3_FORCE_PATH_STYLE") === "true"
}, ? `${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`
{ : `*.${env("NEXT_PUBLIC_STORAGE_DOMAIN")}`,
protocol: "http", },
hostname: "localhost", {
}, protocol: "http",
{ hostname: "localhost",
protocol: "https", },
hostname: "*.googleusercontent.com", {
}, protocol: "https",
], hostname: "*.googleusercontent.com",
},
];
// Extract root domain from S3_ENDPOINT and add wildcard pattern
const s3Endpoint = env("S3_ENDPOINT");
if (s3Endpoint) {
try {
const url = new URL(s3Endpoint);
const hostname = url.hostname;
const protocol = url.protocol.replace(":", "");
// Extract root domain (last 2 parts: e.g. cloudflarestorage.com)
const parts = hostname.split(".");
if (parts.length >= 2) {
const rootDomain = parts.slice(-2).join(".");
patterns.push({
protocol: protocol === "http" ? "http" : "https",
hostname: `*.${rootDomain}`,
});
}
} catch {
// If S3_ENDPOINT is not a valid URL, ignore it
}
}
return patterns;
})(),
}, },
webpack(config) { webpack(config) {
config.module.rules.push({ config.module.rules.push({

View File

@@ -65,6 +65,7 @@
"superjson": "2.2.1", "superjson": "2.2.1",
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.5.2",
"tippy.js": "^6.3.7", "tippy.js": "^6.3.7",
"tiptap-markdown": "^0.8",
"zod": "catalog:" "zod": "catalog:"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -303,6 +303,10 @@ export function Auth({ setIsMagicLinkSent, isSignUp }: AuthProps) {
const password = watch("password"); const password = watch("password");
const isMagicLinkAvailable = useMemo(() => {
return isCloudEnv || (isEmailSendingEnabled && !isSignUp);
}, [isCloudEnv, isEmailSendingEnabled, isSignUp]);
// Determine if we should operate in magic link mode for current form state (login only) // Determine if we should operate in magic link mode for current form state (login only)
const isMagicLinkMode = useMemo(() => { const isMagicLinkMode = useMemo(() => {
// Magic link only viable when email sending enabled AND not sign up. // Magic link only viable when email sending enabled AND not sign up.
@@ -358,7 +362,16 @@ export function Auth({ setIsMagicLinkSent, isSignUp }: AuthProps) {
</div> </div>
)} )}
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
{socialProviders?.length !== 0 && ( {!isCredentialsEnabled && socialProviders?.length === 0 && (
<div className="flex w-full items-center gap-4">
<div className="h-[1px] w-1/3 bg-light-600 dark:bg-dark-600" />
<span className="text-center text-sm text-light-900 dark:text-dark-900">
{t`No authentication methods are currently available`}
</span>
<div className="h-[1px] w-1/3 bg-light-600 dark:bg-dark-600" />
</div>
)}
{!isCredentialsEnabled && socialProviders?.length !== 0 && (
<div className="mb-[1.5rem] flex w-full items-center gap-4"> <div className="mb-[1.5rem] flex w-full items-center gap-4">
<div className="h-[1px] w-full bg-light-600 dark:bg-dark-600" /> <div className="h-[1px] w-full bg-light-600 dark:bg-dark-600" />
<span className="text-sm text-light-900 dark:text-dark-900"> <span className="text-sm text-light-900 dark:text-dark-900">
@@ -381,46 +394,54 @@ export function Auth({ setIsMagicLinkSent, isSignUp }: AuthProps) {
)} )}
</div> </div>
)} )}
<div> {(isCredentialsEnabled || isMagicLinkAvailable) && (
<Input <>
{...register("email", { required: true })} <div>
placeholder={t`Enter your email address`} <Input
/> {...register("email", { required: true })}
{errors.email && ( placeholder={t`Enter your email address`}
<p className="mt-2 text-xs text-red-400"> />
{t`Please enter a valid email address`} {errors.email && (
</p> <p className="mt-2 text-xs text-red-400">
)} {t`Please enter a valid email address`}
</div> </p>
{isCredentialsEnabled && ( )}
<div> </div>
<Input
type="password" {isCredentialsEnabled && (
{...register("password", { required: true })} <div>
placeholder={t`Enter your password`} <Input
/> type="password"
{errors.password && ( {...register("password", { required: true })}
<p className="mt-2 text-xs text-red-400"> placeholder={t`Enter your password`}
{errors.password.message ?? t`Please enter a valid password`} />
</p> {errors.password && (
<p className="mt-2 text-xs text-red-400">
{errors.password.message ??
t`Please enter a valid password`}
</p>
)}
</div>
)} )}
</div> </>
)} )}
{loginError && ( {loginError && (
<p className="mt-2 text-xs text-red-400">{loginError}</p> <p className="mt-2 text-xs text-red-400">{loginError}</p>
)} )}
</div> </div>
<div className="mt-[1.5rem] flex items-center gap-4"> {(isCredentialsEnabled || isMagicLinkAvailable) && (
<Button <div className="mt-[1.5rem] flex items-center gap-4">
isLoading={isLoginWithEmailPending} <Button
fullWidth isLoading={isLoginWithEmailPending}
size="lg" fullWidth
variant="secondary" size="lg"
> variant="secondary"
{isSignUp ? t`Sign up with ` : t`Continue with `} >
{isMagicLinkMode ? t`magic link` : t`email`} {isSignUp ? t`Sign up with ` : t`Continue with `}
</Button> {isMagicLinkMode ? t`magic link` : t`email`}
</div> </Button>
</div>
)}
</form> </form>
</div> </div>
); );

View File

@@ -7,6 +7,7 @@ import type { Instance as TippyInstance } from "tippy.js";
import { Button } from "@headlessui/react"; import { Button } from "@headlessui/react";
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro";
import Link from "@tiptap/extension-link"; import Link from "@tiptap/extension-link";
import Mention from "@tiptap/extension-mention";
import Placeholder from "@tiptap/extension-placeholder"; import Placeholder from "@tiptap/extension-placeholder";
import { import {
BubbleMenu, BubbleMenu,
@@ -39,9 +40,10 @@ import {
} from "react-icons/hi2"; } from "react-icons/hi2";
import { twMerge } from "tailwind-merge"; import { twMerge } from "tailwind-merge";
import tippy from "tippy.js"; import tippy from "tippy.js";
import Mention from "@tiptap/extension-mention"; import { Markdown } from "tiptap-markdown";
import Avatar from "./Avatar";
import { getAvatarUrl } from "~/utils/helpers"; import { getAvatarUrl } from "~/utils/helpers";
import Avatar from "./Avatar";
declare module "@tiptap/core" { declare module "@tiptap/core" {
interface Commands<ReturnType> { interface Commands<ReturnType> {
@@ -77,7 +79,7 @@ export interface RenderSuggestionsProps {
command: (item: SlashCommandItem) => void; command: (item: SlashCommandItem) => void;
} }
export type WorkspaceMember = { export interface WorkspaceMember {
publicId: string; publicId: string;
user: { user: {
id: string; id: string;
@@ -85,7 +87,7 @@ export type WorkspaceMember = {
image: string | null; image: string | null;
} | null; } | null;
email: string; email: string;
}; }
const CommandsList = forwardRef< const CommandsList = forwardRef<
{ onKeyDown: (props: SuggestionKeyDownProps) => boolean }, { onKeyDown: (props: SuggestionKeyDownProps) => boolean },
@@ -200,7 +202,11 @@ const RenderSuggestions = () => {
}; };
}; };
type MentionItem = { id: string; label: string; image: string | null }; interface MentionItem {
id: string;
label: string;
image: string | null;
}
const MentionList = forwardRef< const MentionList = forwardRef<
{ onKeyDown: (props: SuggestionKeyDownProps) => boolean }, { onKeyDown: (props: SuggestionKeyDownProps) => boolean },
@@ -238,30 +244,32 @@ const MentionList = forwardRef<
return ( return (
<div className="w-56 rounded-md border-[1px] border-light-200 bg-light-50 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-500 dark:bg-dark-200"> <div className="w-56 rounded-md border-[1px] border-light-200 bg-light-50 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-dark-500 dark:bg-dark-200">
<div className="max-h-[350px] overflow-y-auto p-1 scrollbar-thin scrollbar-thumb-light-200 dark:scrollbar-thumb-dark-300"> <div className="max-h-[350px] overflow-y-auto p-1 scrollbar-thin scrollbar-thumb-light-200 dark:scrollbar-thumb-dark-300">
{items.length > 0 ? items.map((item, index) => ( {items.length > 0 ? (
<button items.map((item, index) => (
key={item.id} <button
onClick={() => command(item)} key={item.id}
className={twMerge( onClick={() => command(item)}
"group flex w-full items-center rounded-[5px] p-2 hover:bg-light-200 dark:hover:bg-dark-300", className={twMerge(
index === selectedIndex && "bg-light-200 dark:bg-dark-300", "group flex w-full items-center rounded-[5px] p-2 hover:bg-light-200 dark:hover:bg-dark-300",
)} index === selectedIndex && "bg-light-200 dark:bg-dark-300",
> )}
<Avatar >
size="xs" <Avatar
name={item.label} size="xs"
imageUrl={ name={item.label}
item.image ? getAvatarUrl(item.image) : undefined imageUrl={item.image ? getAvatarUrl(item.image) : undefined}
} email={item.label}
email={item.label} />
/> <span className="ml-3 text-[12px] font-medium text-dark-900 dark:text-dark-1000">
<span className="ml-3 text-[12px] font-medium text-dark-900 dark:text-dark-1000"> {item.label}
{item.label} </span>
</span> </button>
</button> ))
)) : ( ) : (
<div className="flex items-center justify-start p-2"> <div className="flex items-center justify-start p-2">
<span className="text-dark-900 text-[12px] dark:text-dark-1000">No results</span> <span className="text-[12px] text-dark-900 dark:text-dark-1000">
No results
</span>
</div> </div>
)} )}
</div> </div>
@@ -436,6 +444,7 @@ export default function Editor({
{ {
extensions: [ extensions: [
StarterKit, StarterKit,
Markdown,
Placeholder.configure({ Placeholder.configure({
placeholder: readOnly placeholder: readOnly
? "" ? ""
@@ -462,35 +471,37 @@ export default function Editor({
}), }),
Mention.configure({ Mention.configure({
HTMLAttributes: { HTMLAttributes: {
class: 'mention', class: "mention",
}, },
suggestion: { suggestion: {
char: "@", char: "@",
items: ({ query }: { query: string }) => { items: ({ query }: { query: string }) => {
const all: MentionItem[] = workspaceMembers.map((member: WorkspaceMember) => ({ const all: MentionItem[] = workspaceMembers.map(
id: member.publicId, (member: WorkspaceMember) => ({
label: member?.user?.name ?? member.email, id: member.publicId,
image: member?.user?.image ?? null, label: member?.user?.name ?? member.email,
})); image: member?.user?.image ?? null,
}),
);
const q = query.toLowerCase(); const q = query.toLowerCase();
return all.filter((u) => u.label.toLowerCase().includes(q)); return all.filter((u) => u.label.toLowerCase().includes(q));
}, },
command: ({ editor, range, props }: any) => { command: ({ editor, range, props }: any) => {
const mentionHTML = `<span data-type="mention" data-id="${props.id}" data-label="${props.label}">@${props.label}</span>&nbsp;`; const mentionHTML = `<span data-type="mention" data-id="${props.id}" data-label="${props.label}">@${props.label}</span>&nbsp;`;
editor editor
.chain() .chain()
.focus() .focus()
.deleteRange(range) .deleteRange(range)
.insertContent(mentionHTML) .insertContent(mentionHTML)
.focus() .focus()
.run(); .run();
},
render: renderMentionSuggestions,
},
renderText({ options, node }) {
return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;
}, },
render: renderMentionSuggestions,
},
renderText({ options, node }) {
return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;
},
}), }),
], ],
content, content,

View File

@@ -122,10 +122,10 @@ export default function SideNavigation({
)} )}
> >
<div> <div>
<div className="hidden h-14 items-center justify-between pb-[18px] pt-1.5 md:flex"> <div className="hidden h-[45px] items-center justify-between pb-3 md:flex">
{!isCollapsed && ( {!isCollapsed && (
<Link href="/" className="block"> <Link href="/" className="block">
<h1 className="pl-2 text-lg font-bold tracking-tight text-neutral-900 dark:text-dark-1000"> <h1 className="pl-2 text-[16px] font-bold tracking-tight text-neutral-900 dark:text-dark-1000">
kan.bn kan.bn
</h1> </h1>
</Link> </Link>

View File

@@ -90,6 +90,7 @@ export const env = createEnv({
NEXT_PUBLIC_BASE_URL: z.string().url(), NEXT_PUBLIC_BASE_URL: z.string().url(),
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_STORAGE_DOMAIN: z.string().optional(), NEXT_PUBLIC_STORAGE_DOMAIN: z.string().optional(),
NEXT_PUBLIC_ALLOW_CREDENTIALS: z NEXT_PUBLIC_ALLOW_CREDENTIALS: z
.string() .string()
@@ -125,6 +126,8 @@ export const env = createEnv({
NEXT_PUBLIC_BASE_URL: process.env.NEXT_PUBLIC_BASE_URL, NEXT_PUBLIC_BASE_URL: process.env.NEXT_PUBLIC_BASE_URL,
NEXT_PUBLIC_STORAGE_URL: process.env.NEXT_PUBLIC_STORAGE_URL, NEXT_PUBLIC_STORAGE_URL: process.env.NEXT_PUBLIC_STORAGE_URL,
NEXT_PUBLIC_AVATAR_BUCKET_NAME: process.env.NEXT_PUBLIC_AVATAR_BUCKET_NAME, NEXT_PUBLIC_AVATAR_BUCKET_NAME: process.env.NEXT_PUBLIC_AVATAR_BUCKET_NAME,
NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME:
process.env.NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME,
NEXT_PUBLIC_STORAGE_DOMAIN: process.env.NEXT_PUBLIC_STORAGE_DOMAIN, NEXT_PUBLIC_STORAGE_DOMAIN: process.env.NEXT_PUBLIC_STORAGE_DOMAIN,
NEXT_PUBLIC_ALLOW_CREDENTIALS: process.env.NEXT_PUBLIC_ALLOW_CREDENTIALS, NEXT_PUBLIC_ALLOW_CREDENTIALS: process.env.NEXT_PUBLIC_ALLOW_CREDENTIALS,
NEXT_PUBLIC_DISABLE_SIGN_UP: process.env.NEXT_PUBLIC_DISABLE_SIGN_UP, NEXT_PUBLIC_DISABLE_SIGN_UP: process.env.NEXT_PUBLIC_DISABLE_SIGN_UP,

View File

@@ -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:22 #: src/views/boards/index.tsx:22
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
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:442 #: src/views/board/components/NewCardForm.tsx:443
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:387 #: src/views/board/index.tsx:389
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} nicht gefunden" msgstr "{0} nicht gefunden"
@@ -79,8 +79,8 @@ msgstr "Konto"
msgid "Account deleted" msgid "Account deleted"
msgstr "Konto gelöscht" msgstr "Konto gelöscht"
#: src/views/card/index.tsx:291 #: src/views/card/index.tsx:308
#: src/views/public/board/CardModal.tsx:143 #: src/views/public/board/CardModal.tsx:157
msgid "Activity" msgid "Activity"
msgstr "Aktivität" msgstr "Aktivität"
@@ -109,7 +109,7 @@ msgstr "Element hinzufügen..."
msgid "Add checklist" msgid "Add checklist"
msgstr "Checkliste hinzufügen" msgstr "Checkliste hinzufügen"
#: src/components/Editor.tsx:442 #: src/components/Editor.tsx:451
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)"
@@ -270,6 +270,10 @@ 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
msgid "Attachment uploaded"
msgstr "Anhang hochgeladen"
#: src/views/boards/components/TemplateBoards.tsx:47 #: src/views/boards/components/TemplateBoards.tsx:47
msgid "Awaiting Customer" msgid "Awaiting Customer"
msgstr "Warten auf Kunden" msgstr "Warten auf Kunden"
@@ -304,9 +308,9 @@ msgstr "Abrechnungsportal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blogbeitrag" msgstr "Blogbeitrag"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
msgid "Board" msgid "Board"
msgstr "Board" msgstr "Board"
@@ -323,7 +327,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:151 #: src/views/public/board/index.tsx:153
msgid "Board not found" msgid "Board not found"
msgstr "Board nicht gefunden" msgstr "Board nicht gefunden"
@@ -331,19 +335,19 @@ msgstr "Board nicht gefunden"
msgid "Board sharing & invites" msgid "Board sharing & invites"
msgstr "Board-Freigabe & Einladungen" msgstr "Board-Freigabe & Einladungen"
#: src/views/board/components/UpdateBoardSlugForm.tsx:45 #: src/views/board/components/UpdateBoardSlugForm.tsx:46
msgid "Board URL can only contain letters, numbers, and hyphens" msgid "Board URL can only contain letters, numbers, and hyphens"
msgstr "Board-URL darf nur Buchstaben, Zahlen und Bindestriche enthalten" msgstr "Board-URL darf nur Buchstaben, Zahlen und Bindestriche enthalten"
#: src/views/board/components/UpdateBoardSlugForm.tsx:43 #: src/views/board/components/UpdateBoardSlugForm.tsx:44
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:67 #: src/views/public/board/index.tsx:68
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:41 #: src/views/board/components/UpdateBoardSlugForm.tsx:42
msgid "Board URL must be at least 3 characters long" msgid "Board URL must be at least 3 characters long"
msgstr "Board-URL muss mindestens 3 Zeichen lang sein" msgstr "Board-URL muss mindestens 3 Zeichen lang sein"
@@ -352,7 +356,7 @@ msgstr "Board-URL muss mindestens 3 Zeichen lang sein"
msgid "Board visibility" msgid "Board visibility"
msgstr "Board-Sichtbarkeit" msgstr "Board-Sichtbarkeit"
#: src/views/board/components/VisibilityButton.tsx:45 #: src/views/board/components/VisibilityButton.tsx:46
msgid "Board visibility updated" msgid "Board visibility updated"
msgstr "Board-Sichtbarkeit aktualisiert" msgstr "Board-Sichtbarkeit aktualisiert"
@@ -387,15 +391,15 @@ msgstr "Fehlerbericht"
msgid "Cancel" msgid "Cancel"
msgstr "Abbrechen" msgstr "Abbrechen"
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
msgid "Card" msgid "Card"
msgstr "Karte" msgstr "Karte"
#: src/views/card/index.tsx:262 #: src/views/card/index.tsx:264
msgid "Card not found" msgid "Card not found"
msgstr "Karte nicht gefunden" msgstr "Karte nicht gefunden"
#: src/views/board/components/NewCardForm.tsx:309 #: src/views/board/components/NewCardForm.tsx:310
msgid "Card title" msgid "Card title"
msgstr "Kartentitel" msgstr "Kartentitel"
@@ -428,7 +432,7 @@ msgstr "Checklistenname"
msgid "Checklists" msgid "Checklists"
msgstr "Checklisten" msgstr "Checklisten"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:180
msgid "Clear filters" msgid "Clear filters"
msgstr "Filter löschen" msgstr "Filter löschen"
@@ -519,7 +523,7 @@ msgstr "Kontaktiere uns"
msgid "Content Creation" msgid "Content Creation"
msgstr "Content-Erstellung" msgstr "Content-Erstellung"
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Continue with " msgid "Continue with "
msgstr "Fortfahren mit " msgstr "Fortfahren mit "
@@ -542,8 +546,8 @@ 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:468 #: src/views/board/components/NewCardForm.tsx:469
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Weitere erstellen" msgstr "Weitere erstellen"
@@ -551,7 +555,7 @@ 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:478 #: src/views/board/components/NewCardForm.tsx:479
msgid "Create card" msgid "Create card"
msgstr "Karte erstellen" msgstr "Karte erstellen"
@@ -567,7 +571,7 @@ msgstr "Einladungslink erstellen"
msgid "Create label" msgid "Create label"
msgstr "Label erstellen" msgstr "Label erstellen"
#: src/views/board/components/NewListForm.tsx:152 #: src/views/board/components/NewListForm.tsx:153
msgid "Create list" msgid "Create list"
msgstr "Liste erstellen" msgstr "Liste erstellen"
@@ -580,12 +584,12 @@ 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:404 #: src/views/board/components/NewCardForm.tsx:405
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:97
msgid "Create new label" msgid "Create new label"
msgstr "Neues Label erstellen" msgstr "Neues Label erstellen"
#: src/views/board/index.tsx:475 #: src/views/board/index.tsx:478
msgid "Create new list" msgid "Create new list"
msgstr "Neue Liste erstellen" msgstr "Neue Liste erstellen"
@@ -769,8 +773,12 @@ 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
msgid "Download failed"
msgstr "Download fehlgeschlagen"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:115 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Board-URL bearbeiten" msgstr "Board-URL bearbeiten"
@@ -782,7 +790,7 @@ msgstr "Kommentar bearbeiten"
msgid "Edit label" msgid "Edit label"
msgstr "Label bearbeiten" msgstr "Label bearbeiten"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161 #: src/views/board/components/UpdateBoardSlugForm.tsx:162
msgid "Edit workspace URL" msgid "Edit workspace URL"
msgstr "Workspace-URL bearbeiten" msgstr "Workspace-URL bearbeiten"
@@ -790,7 +798,7 @@ msgstr "Workspace-URL bearbeiten"
msgid "Editing" msgid "Editing"
msgstr "Bearbeitung" msgstr "Bearbeitung"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "email" msgid "email"
msgstr "E-Mail" msgstr "E-Mail"
@@ -810,11 +818,11 @@ msgstr "Geben Sie Ihr aktuelles Passwort ein"
msgid "Enter your current password and choose a new secure password." msgid "Enter your current password and choose a new secure password."
msgstr "Geben Sie Ihr aktuelles Passwort ein und wählen Sie ein neues sicheres Passwort." msgstr "Geben Sie Ihr aktuelles Passwort ein und wählen Sie ein neues sicheres Passwort."
#: src/components/AuthForm.tsx:387 #: src/components/AuthForm.tsx:398
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Gib deine E-Mail-Adresse ein" msgstr "Gib deine E-Mail-Adresse ein"
#: src/components/AuthForm.tsx:375 #: src/components/AuthForm.tsx:384
msgid "Enter your name" msgid "Enter your name"
msgstr "Gib deinen Namen ein" msgstr "Gib deinen Namen ein"
@@ -822,7 +830,7 @@ msgstr "Gib deinen Namen ein"
msgid "Enter your new password" msgid "Enter your new password"
msgstr "Geben Sie Ihr neues Passwort ein" msgstr "Geben Sie Ihr neues Passwort ein"
#: src/components/AuthForm.tsx:400 #: src/components/AuthForm.tsx:411
msgid "Enter your password" msgid "Enter your password"
msgstr "Gib dein Passwort ein" msgstr "Gib dein Passwort ein"
@@ -931,6 +939,11 @@ 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:79
msgid "Failed to upload attachment. Please try again."
msgstr "Fehler beim Hochladen des Anhangs. Bitte versuchen Sie es erneut."
#: src/views/home/components/Header.tsx:41 #: src/views/home/components/Header.tsx:41
msgid "FAQ" msgid "FAQ"
msgstr "FAQ" msgstr "FAQ"
@@ -974,7 +987,7 @@ msgstr "Feedback"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Feedback gesendet" msgstr "Feedback gesendet"
#: src/views/board/components/Filters.tsx:149 #: src/views/board/components/Filters.tsx:174
msgid "Filter" msgid "Filter"
msgstr "Filter" msgstr "Filter"
@@ -987,6 +1000,8 @@ msgid "For long-term sustainability, we recognise all good open source projects
msgstr "Für langfristige Nachhaltigkeit erkennen wir an, dass alle guten Open-Source-Projekte eine Einnahmequelle benötigen. Unsere stammt aus dem kostenpflichtigen Cloud-Angebot für Workspaces mit mehreren Benutzern und für benutzerdefinierte Workspace-Slugs. Es besteht keine Verpflichtung, es zu nutzen, und Sie können die Software kostenlos auf Ihrer eigenen Infrastruktur selbst hosten." msgstr "Für langfristige Nachhaltigkeit erkennen wir an, dass alle guten Open-Source-Projekte eine Einnahmequelle benötigen. Unsere stammt aus dem kostenpflichtigen Cloud-Angebot für Workspaces mit mehreren Benutzern und für benutzerdefinierte Workspace-Slugs. Es besteht keine Verpflichtung, es zu nutzen, und Sie können die Software kostenlos auf Ihrer eigenen Infrastruktur selbst hosten."
#: src/views/pricing/components/Pricing.tsx:32 #: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/PricingTiers.tsx:30
#: src/views/pricing/components/PricingTiers.tsx:30 #: src/views/pricing/components/PricingTiers.tsx:30
msgid "Free" msgid "Free"
msgstr "Kostenlos" msgstr "Kostenlos"
@@ -1028,7 +1043,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:467 #: src/views/board/index.tsx:470
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"
@@ -1242,9 +1257,9 @@ msgstr "Kanban neu gedacht"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Beachten Sie, dass diese Aktion nicht rückgängig gemacht werden kann." msgstr "Beachten Sie, dass diese Aktion nicht rückgängig gemacht werden kann."
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:115
#: src/views/board/components/NewCardForm.tsx:408 #: src/views/board/components/NewCardForm.tsx:409
#: src/views/card/index.tsx:117 #: src/views/card/index.tsx:119
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -1294,18 +1309,22 @@ msgstr "Lizenz"
msgid "Light" msgid "Light"
msgstr "Hell" msgstr "Hell"
#: src/views/public/board/index.tsx:65 #: src/views/public/board/index.tsx:66
msgid "Link copied" msgid "Link copied"
msgstr "Link kopiert" msgstr "Link kopiert"
#: src/views/card/index.tsx:109 #: src/views/card/index.tsx:111
msgid "List" msgid "List"
msgstr "Liste" msgstr "Liste"
#: src/views/board/components/NewListForm.tsx:128 #: src/views/board/components/NewListForm.tsx:129
msgid "List name" msgid "List name"
msgstr "Listenname" msgstr "Listenname"
#: src/views/board/components/Filters.tsx:123
msgid "Lists"
msgstr "Listen"
#: 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"
@@ -1326,7 +1345,7 @@ msgstr "Von Teams weltweit geliebt"
msgid "Low Priority" msgid "Low Priority"
msgstr "Niedrige Priorität" msgstr "Niedrige Priorität"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "magic link" msgid "magic link"
msgstr "Magic Link" msgstr "Magic Link"
@@ -1348,9 +1367,9 @@ msgid "Medium Priority"
msgstr "Mittlere Priorität" msgstr "Mittlere Priorität"
#: src/components/SideNavigation.tsx:101 #: src/components/SideNavigation.tsx:101
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:107
#: src/views/board/components/NewCardForm.tsx:366 #: src/views/board/components/NewCardForm.tsx:367
#: src/views/card/index.tsx:126 #: src/views/card/index.tsx:128
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Mitglieder" msgstr "Mitglieder"
@@ -1403,7 +1422,7 @@ 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:292 #: src/views/board/components/NewCardForm.tsx:293
msgid "New card" msgid "New card"
msgstr "Neue Karte" msgstr "Neue Karte"
@@ -1419,8 +1438,8 @@ msgstr "Neuer Import"
msgid "New label" msgid "New label"
msgstr "Neues Label" msgstr "Neues Label"
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:439 #: src/views/board/index.tsx:442
msgid "New list" msgid "New list"
msgstr "Neue Liste" msgstr "Neue Liste"
@@ -1457,6 +1476,10 @@ msgstr "Nächste Schritte"
msgid "No {0}" msgid "No {0}"
msgstr "Keine {0}" msgstr "Keine {0}"
#: src/components/AuthForm.tsx:365
msgid "No authentication methods are currently available"
msgstr "Derzeit sind keine Authentifizierungsmethoden verfügbar"
#: src/views/boards/components/ImportBoardsForm.tsx:242 #: src/views/boards/components/ImportBoardsForm.tsx:242
msgid "No boards found" msgid "No boards found"
msgstr "Keine Boards gefunden" msgstr "Keine Boards gefunden"
@@ -1465,7 +1488,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/board/index.tsx:464 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "No download URL available for this attachment."
msgstr "Für diesen Anhang ist keine Download-URL verfügbar."
#: src/views/board/index.tsx:467
msgid "No lists" msgid "No lists"
msgstr "Keine Listen" msgstr "Keine Listen"
@@ -1497,7 +1524,7 @@ msgstr "Open Source"
msgid "Open Source Friends" msgid "Open Source Friends"
msgstr "Open-Source-Freunde" msgstr "Open-Source-Freunde"
#: src/components/AuthForm.tsx:365 #: src/components/AuthForm.tsx:374
msgid "or" msgid "or"
msgstr "oder" msgstr "oder"
@@ -1579,15 +1606,15 @@ msgstr "Plattform"
msgid "Please confirm your new password" msgid "Please confirm your new password"
msgstr "Bitte bestätigen Sie Ihr neues Passwort" msgstr "Bitte bestätigen Sie Ihr neues Passwort"
#: src/components/AuthForm.tsx:391 #: src/components/AuthForm.tsx:402
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Bitte gib eine gültige E-Mail-Adresse ein" msgstr "Bitte gib eine gültige E-Mail-Adresse ein"
#: src/components/AuthForm.tsx:379 #: src/components/AuthForm.tsx:388
msgid "Please enter a valid name" msgid "Please enter a valid name"
msgstr "Bitte gib einen gültigen Namen ein" msgstr "Bitte gib einen gültigen Namen ein"
#: src/components/AuthForm.tsx:404 #: src/components/AuthForm.tsx:416
msgid "Please enter a valid password" msgid "Please enter a valid password"
msgstr "Bitte gib ein gültiges Passwort ein" msgstr "Bitte gib ein gültiges Passwort ein"
@@ -1598,15 +1625,16 @@ 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:176 #: src/views/board/components/NewCardForm.tsx:177
#: src/views/board/components/NewListForm.tsx:78 #: 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:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:149 #: src/views/board/index.tsx:151
#: src/views/board/index.tsx:205 #: src/views/board/index.tsx:207
#: 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/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:46
@@ -1620,7 +1648,7 @@ msgstr "Bitte wähle eine Datei zum Hochladen aus."
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/index.tsx:175 #: src/views/card/index.tsx:177
#: 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
@@ -1664,7 +1692,7 @@ msgstr "Prioritäts-E-Mail-Support"
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Datenschutzrichtlinie" msgstr "Datenschutzrichtlinie"
#: src/views/board/components/VisibilityButton.tsx:73 #: src/views/board/components/VisibilityButton.tsx:74
msgid "Private" msgid "Private"
msgstr "Privat" msgstr "Privat"
@@ -1684,7 +1712,7 @@ msgstr "Profilbild aktualisiert"
msgid "Profile picture" msgid "Profile picture"
msgstr "Profilbild" msgstr "Profilbild"
#: src/views/board/components/VisibilityButton.tsx:68 #: src/views/board/components/VisibilityButton.tsx:69
msgid "Public" msgid "Public"
msgstr "Öffentlich" msgstr "Öffentlich"
@@ -1886,7 +1914,7 @@ msgstr "Registrierung deaktiviert"
msgid "Sign up is currently disabled. Please try again later." msgid "Sign up is currently disabled. Please try again later."
msgstr "Die Registrierung ist derzeit deaktiviert. Bitte versuche es später erneut." msgstr "Die Registrierung ist derzeit deaktiviert. Bitte versuche es später erneut."
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Sign up with " msgid "Sign up with "
msgstr "Registrieren mit " msgstr "Registrieren mit "
@@ -1953,8 +1981,8 @@ msgstr "Team-Plan"
msgid "Teams" msgid "Teams"
msgstr "Teams" msgstr "Teams"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/board/index.tsx:396 #: src/views/board/index.tsx:398
msgid "Template" msgid "Template"
msgstr "Vorlage" msgstr "Vorlage"
@@ -2004,7 +2032,7 @@ msgid "The open source <0/> alternative to Trello"
msgstr "Die open source <0/> alternative zu Trello" msgstr "Die open source <0/> alternative zu Trello"
#. placeholder {0}: isPublic ? "public" : "private" #. placeholder {0}: isPublic ? "public" : "private"
#: src/views/board/components/VisibilityButton.tsx:46 #: src/views/board/components/VisibilityButton.tsx:47
msgid "The visibility of your board has been set to {0}." msgid "The visibility of your board has been set to {0}."
msgstr "Die Sichtbarkeit deines Boards wurde auf {0} gesetzt." msgstr "Die Sichtbarkeit deines Boards wurde auf {0} gesetzt."
@@ -2028,11 +2056,11 @@ 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:154 #: src/views/public/board/index.tsx:156
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135 #: src/views/board/components/UpdateBoardSlugForm.tsx:136
msgid "This board URL has already been taken" msgid "This board URL has already been taken"
msgstr "Diese Board-URL ist bereits vergeben" msgstr "Diese Board-URL ist bereits vergeben"
@@ -2102,7 +2130,7 @@ msgstr "Checklistenelement kann nicht hinzugefügt werden"
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:173 #: src/views/board/components/NewCardForm.tsx:174
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Karte konnte nicht erstellt werden" msgstr "Karte konnte nicht erstellt werden"
@@ -2110,7 +2138,7 @@ msgstr "Karte konnte nicht erstellt werden"
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Checkliste kann nicht erstellt werden" msgstr "Checkliste kann nicht erstellt werden"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:78
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Liste konnte nicht erstellt werden" msgstr "Liste konnte nicht erstellt werden"
@@ -2123,6 +2151,10 @@ 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
msgid "Unable to delete attachment"
msgstr "Anhang kann nicht gelöscht werden"
#: src/views/card/components/DeleteCardConfirmation.tsx:51 #: src/views/card/components/DeleteCardConfirmation.tsx:51
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Karte konnte nicht gelöscht werden" msgstr "Karte konnte nicht gelöscht werden"
@@ -2147,16 +2179,16 @@ msgstr "Mitglied konnte nicht entfernt werden"
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Feedback konnte nicht gesendet werden" msgstr "Feedback konnte nicht gesendet werden"
#: src/views/board/components/UpdateBoardSlugForm.tsx:71 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
msgid "Unable to update board URL" msgid "Unable to update board URL"
msgstr "Board-URL kann nicht aktualisiert werden" msgstr "Board-URL kann nicht aktualisiert werden"
#: src/views/board/components/VisibilityButton.tsx:52 #: src/views/board/components/VisibilityButton.tsx:53
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:204 #: src/views/board/index.tsx:206
#: src/views/card/index.tsx:174 #: src/views/card/index.tsx:176
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Karte konnte nicht aktualisiert werden" msgstr "Karte konnte nicht aktualisiert werden"
@@ -2176,7 +2208,7 @@ msgstr "Kommentar konnte nicht aktualisiert werden"
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:148 #: src/views/board/index.tsx:150
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:51
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Liste konnte nicht aktualisiert werden" msgstr "Liste konnte nicht aktualisiert werden"
@@ -2232,7 +2264,7 @@ msgstr "Unbegrenzte Mitglieder"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Unbegrenzte Workspaces" msgstr "Unbegrenzte Workspaces"
#: src/views/board/components/UpdateBoardSlugForm.tsx:174 #: 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
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83 #: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83
@@ -2271,6 +2303,11 @@ 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:78
msgid "Upload failed"
msgstr "Hochladen fehlgeschlagen"
#: src/views/boards/components/TemplateBoards.tsx:38 #: src/views/boards/components/TemplateBoards.tsx:38
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Urgent" msgid "Urgent"
@@ -2320,7 +2357,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:128 #: src/views/public/board/index.tsx:129
msgid "View only" msgid "View only"
msgstr "Nur ansehen" msgstr "Nur ansehen"
@@ -2328,11 +2365,11 @@ 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:157 #: src/views/public/board/index.tsx:159
msgid "View workspace" msgid "View workspace"
msgstr "Workspace anzeigen" msgstr "Workspace anzeigen"
#: src/views/board/components/VisibilityButton.tsx:91 #: src/views/board/components/VisibilityButton.tsx:92
msgid "Visibility" msgid "Visibility"
msgstr "Sichtbarkeit" msgstr "Sichtbarkeit"
@@ -2369,10 +2406,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:361 #: src/views/board/index.tsx:363
#: src/views/boards/index.tsx:22 #: src/views/boards/index.tsx:22
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Arbeitsbereich" msgstr "Arbeitsbereich"
@@ -2502,6 +2539,10 @@ 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
msgid "Your file has been uploaded successfully."
msgstr "Ihre Datei wurde erfolgreich hochgeladen."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70 #: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "Ihr Passwort wurde geändert." msgstr "Ihr Passwort wurde geändert."

File diff suppressed because one or more lines are too long

View File

@@ -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:22 #: src/views/boards/index.tsx:22
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
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:442 #: src/views/board/components/NewCardForm.tsx:443
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:387 #: src/views/board/index.tsx:389
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} not found" msgstr "{0} not found"
@@ -91,8 +91,8 @@ msgstr "Account"
msgid "Account deleted" msgid "Account deleted"
msgstr "Account deleted" msgstr "Account deleted"
#: src/views/card/index.tsx:291 #: src/views/card/index.tsx:308
#: src/views/public/board/CardModal.tsx:143 #: src/views/public/board/CardModal.tsx:157
msgid "Activity" msgid "Activity"
msgstr "Activity" msgstr "Activity"
@@ -121,7 +121,7 @@ msgstr "Add an item..."
msgid "Add checklist" msgid "Add checklist"
msgstr "Add checklist" msgstr "Add checklist"
#: src/components/Editor.tsx:442 #: src/components/Editor.tsx:451
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Add description... (type '/' to open commands or '@' to mention)" msgstr "Add description... (type '/' to open commands or '@' to mention)"
@@ -306,6 +306,10 @@ msgstr "assigned <0>{0}</0> to the card"
msgid "Assignees" msgid "Assignees"
msgstr "Assignees" msgstr "Assignees"
#: src/views/card/components/AttachmentUpload.tsx:25
msgid "Attachment uploaded"
msgstr "Attachment uploaded"
#: src/views/boards/components/TemplateBoards.tsx:47 #: src/views/boards/components/TemplateBoards.tsx:47
msgid "Awaiting Customer" msgid "Awaiting Customer"
msgstr "Awaiting Customer" msgstr "Awaiting Customer"
@@ -344,9 +348,9 @@ msgstr "Billing portal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blog Post" msgstr "Blog Post"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
msgid "Board" msgid "Board"
msgstr "Board" msgstr "Board"
@@ -372,7 +376,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:151 #: src/views/public/board/index.tsx:153
msgid "Board not found" msgid "Board not found"
msgstr "Board not found" msgstr "Board not found"
@@ -380,19 +384,19 @@ msgstr "Board not found"
msgid "Board sharing & invites" msgid "Board sharing & invites"
msgstr "Board sharing & invites" msgstr "Board sharing & invites"
#: src/views/board/components/UpdateBoardSlugForm.tsx:45 #: src/views/board/components/UpdateBoardSlugForm.tsx:46
msgid "Board URL can only contain letters, numbers, and hyphens" msgid "Board URL can only contain letters, numbers, and hyphens"
msgstr "Board URL can only contain letters, numbers, and hyphens" msgstr "Board URL can only contain letters, numbers, and hyphens"
#: src/views/board/components/UpdateBoardSlugForm.tsx:43 #: src/views/board/components/UpdateBoardSlugForm.tsx:44
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:67 #: src/views/public/board/index.tsx:68
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "Board URL copied to clipboard" msgstr "Board URL copied to clipboard"
#: src/views/board/components/UpdateBoardSlugForm.tsx:41 #: src/views/board/components/UpdateBoardSlugForm.tsx:42
msgid "Board URL must be at least 3 characters long" msgid "Board URL must be at least 3 characters long"
msgstr "Board URL must be at least 3 characters long" msgstr "Board URL must be at least 3 characters long"
@@ -401,7 +405,7 @@ msgstr "Board URL must be at least 3 characters long"
msgid "Board visibility" msgid "Board visibility"
msgstr "Board visibility" msgstr "Board visibility"
#: src/views/board/components/VisibilityButton.tsx:45 #: src/views/board/components/VisibilityButton.tsx:46
msgid "Board visibility updated" msgid "Board visibility updated"
msgstr "Board visibility updated" msgstr "Board visibility updated"
@@ -444,15 +448,15 @@ msgstr "Bug Report"
msgid "Cancel" msgid "Cancel"
msgstr "Cancel" msgstr "Cancel"
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
msgid "Card" msgid "Card"
msgstr "Card" msgstr "Card"
#: src/views/card/index.tsx:262 #: src/views/card/index.tsx:264
msgid "Card not found" msgid "Card not found"
msgstr "Card not found" msgstr "Card not found"
#: src/views/board/components/NewCardForm.tsx:309 #: src/views/board/components/NewCardForm.tsx:310
msgid "Card title" msgid "Card title"
msgstr "Card title" msgstr "Card title"
@@ -489,7 +493,7 @@ msgstr "Checklist name"
msgid "Checklists" msgid "Checklists"
msgstr "Checklists" msgstr "Checklists"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:180
msgid "Clear filters" msgid "Clear filters"
msgstr "Clear filters" msgstr "Clear filters"
@@ -584,7 +588,7 @@ msgstr "Contact us"
msgid "Content Creation" msgid "Content Creation"
msgstr "Content Creation" msgstr "Content Creation"
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Continue with " msgid "Continue with "
msgstr "Continue with " msgstr "Continue with "
@@ -607,8 +611,8 @@ 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:468 #: src/views/board/components/NewCardForm.tsx:469
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Create another" msgstr "Create another"
@@ -624,7 +628,7 @@ msgstr "Create API key"
#~ msgid "Create board" #~ msgid "Create board"
#~ msgstr "Create board" #~ msgstr "Create board"
#: src/views/board/components/NewCardForm.tsx:478 #: src/views/board/components/NewCardForm.tsx:479
msgid "Create card" msgid "Create card"
msgstr "Create card" msgstr "Create card"
@@ -640,7 +644,7 @@ msgstr "Create invite link"
msgid "Create label" msgid "Create label"
msgstr "Create label" msgstr "Create label"
#: src/views/board/components/NewListForm.tsx:152 #: src/views/board/components/NewListForm.tsx:153
msgid "Create list" msgid "Create list"
msgstr "Create list" msgstr "Create list"
@@ -657,12 +661,12 @@ 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:404 #: src/views/board/components/NewCardForm.tsx:405
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:97
msgid "Create new label" msgid "Create new label"
msgstr "Create new label" msgstr "Create new label"
#: src/views/board/index.tsx:475 #: src/views/board/index.tsx:478
msgid "Create new list" msgid "Create new list"
msgstr "Create new list" msgstr "Create new list"
@@ -858,8 +862,12 @@ 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
msgid "Download failed"
msgstr "Download failed"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:115 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Edit board URL" msgstr "Edit board URL"
@@ -871,7 +879,7 @@ msgstr "Edit comment"
msgid "Edit label" msgid "Edit label"
msgstr "Edit label" msgstr "Edit label"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161 #: src/views/board/components/UpdateBoardSlugForm.tsx:162
msgid "Edit workspace URL" msgid "Edit workspace URL"
msgstr "Edit workspace URL" msgstr "Edit workspace URL"
@@ -879,7 +887,7 @@ msgstr "Edit workspace URL"
msgid "Editing" msgid "Editing"
msgstr "Editing" msgstr "Editing"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "email" msgid "email"
msgstr "email" msgstr "email"
@@ -899,11 +907,11 @@ msgstr "Enter your current password"
msgid "Enter your current password and choose a new secure password." msgid "Enter your current password and choose a new secure password."
msgstr "Enter your current password and choose a new secure password." msgstr "Enter your current password and choose a new secure password."
#: src/components/AuthForm.tsx:387 #: src/components/AuthForm.tsx:398
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Enter your email address" msgstr "Enter your email address"
#: src/components/AuthForm.tsx:375 #: src/components/AuthForm.tsx:384
msgid "Enter your name" msgid "Enter your name"
msgstr "Enter your name" msgstr "Enter your name"
@@ -911,7 +919,7 @@ msgstr "Enter your name"
msgid "Enter your new password" msgid "Enter your new password"
msgstr "Enter your new password" msgstr "Enter your new password"
#: src/components/AuthForm.tsx:400 #: src/components/AuthForm.tsx:411
msgid "Enter your password" msgid "Enter your password"
msgstr "Enter your password" msgstr "Enter your password"
@@ -1020,6 +1028,11 @@ 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:79
msgid "Failed to upload attachment. Please try again."
msgstr "Failed to upload attachment. Please try again."
#: src/views/home/components/Header.tsx:41 #: src/views/home/components/Header.tsx:41
msgid "FAQ" msgid "FAQ"
msgstr "FAQ" msgstr "FAQ"
@@ -1063,7 +1076,7 @@ msgstr "Feedback"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Feedback sent" msgstr "Feedback sent"
#: src/views/board/components/Filters.tsx:149 #: src/views/board/components/Filters.tsx:174
msgid "Filter" msgid "Filter"
msgstr "Filter" msgstr "Filter"
@@ -1131,7 +1144,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:467 #: src/views/board/index.tsx:470
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"
@@ -1353,9 +1366,9 @@ msgstr "Kanban reimagined"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Keep in mind that this action is irreversible." msgstr "Keep in mind that this action is irreversible."
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:115
#: src/views/board/components/NewCardForm.tsx:408 #: src/views/board/components/NewCardForm.tsx:409
#: src/views/card/index.tsx:117 #: src/views/card/index.tsx:119
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -1405,18 +1418,22 @@ msgstr "License"
msgid "Light" msgid "Light"
msgstr "Light" msgstr "Light"
#: src/views/public/board/index.tsx:65 #: src/views/public/board/index.tsx:66
msgid "Link copied" msgid "Link copied"
msgstr "Link copied" msgstr "Link copied"
#: src/views/card/index.tsx:109 #: src/views/card/index.tsx:111
msgid "List" msgid "List"
msgstr "List" msgstr "List"
#: src/views/board/components/NewListForm.tsx:128 #: src/views/board/components/NewListForm.tsx:129
msgid "List name" msgid "List name"
msgstr "List name" msgstr "List name"
#: src/views/board/components/Filters.tsx:123
msgid "Lists"
msgstr "Lists"
#: 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"
@@ -1437,7 +1454,7 @@ msgstr "Loved by teams worldwide"
msgid "Low Priority" msgid "Low Priority"
msgstr "Low Priority" msgstr "Low Priority"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "magic link" msgid "magic link"
msgstr "magic link" msgstr "magic link"
@@ -1459,9 +1476,9 @@ msgid "Medium Priority"
msgstr "Medium Priority" msgstr "Medium Priority"
#: src/components/SideNavigation.tsx:101 #: src/components/SideNavigation.tsx:101
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:107
#: src/views/board/components/NewCardForm.tsx:366 #: src/views/board/components/NewCardForm.tsx:367
#: src/views/card/index.tsx:126 #: src/views/card/index.tsx:128
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Members" msgstr "Members"
@@ -1526,7 +1543,7 @@ msgstr "New API key"
#~ msgid "New board" #~ msgid "New board"
#~ msgstr "New board" #~ msgstr "New board"
#: src/views/board/components/NewCardForm.tsx:292 #: src/views/board/components/NewCardForm.tsx:293
msgid "New card" msgid "New card"
msgstr "New card" msgstr "New card"
@@ -1542,8 +1559,8 @@ msgstr "New import"
msgid "New label" msgid "New label"
msgstr "New label" msgstr "New label"
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:439 #: src/views/board/index.tsx:442
msgid "New list" msgid "New list"
msgstr "New list" msgstr "New list"
@@ -1584,6 +1601,10 @@ msgstr "Next Steps"
msgid "No {0}" msgid "No {0}"
msgstr "No {0}" msgstr "No {0}"
#: src/components/AuthForm.tsx:365
msgid "No authentication methods are currently available"
msgstr "No authentication methods are currently available"
#: src/views/boards/components/BoardsList.tsx:35 #: src/views/boards/components/BoardsList.tsx:35
#~ msgid "No boards" #~ msgid "No boards"
#~ msgstr "No boards" #~ msgstr "No boards"
@@ -1596,7 +1617,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/board/index.tsx:464 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "No download URL available for this attachment."
msgstr "No download URL available for this attachment."
#: src/views/board/index.tsx:467
msgid "No lists" msgid "No lists"
msgstr "No lists" msgstr "No lists"
@@ -1628,7 +1653,7 @@ msgstr "Open source"
msgid "Open Source Friends" msgid "Open Source Friends"
msgstr "Open Source Friends" msgstr "Open Source Friends"
#: src/components/AuthForm.tsx:365 #: src/components/AuthForm.tsx:374
msgid "or" msgid "or"
msgstr "or" msgstr "or"
@@ -1710,15 +1735,15 @@ msgstr "Platform"
msgid "Please confirm your new password" msgid "Please confirm your new password"
msgstr "Please confirm your new password" msgstr "Please confirm your new password"
#: src/components/AuthForm.tsx:391 #: src/components/AuthForm.tsx:402
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Please enter a valid email address" msgstr "Please enter a valid email address"
#: src/components/AuthForm.tsx:379 #: src/components/AuthForm.tsx:388
msgid "Please enter a valid name" msgid "Please enter a valid name"
msgstr "Please enter a valid name" msgstr "Please enter a valid name"
#: src/components/AuthForm.tsx:404 #: src/components/AuthForm.tsx:416
msgid "Please enter a valid password" msgid "Please enter a valid password"
msgstr "Please enter a valid password" msgstr "Please enter a valid password"
@@ -1729,15 +1754,16 @@ 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:176 #: src/views/board/components/NewCardForm.tsx:177
#: src/views/board/components/NewListForm.tsx:78 #: 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:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:149 #: src/views/board/index.tsx:151
#: src/views/board/index.tsx:205 #: src/views/board/index.tsx:207
#: 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/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:46
@@ -1751,7 +1777,7 @@ msgstr "Please select a file to upload."
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/index.tsx:175 #: src/views/card/index.tsx:177
#: 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
@@ -1795,7 +1821,7 @@ msgstr "Priority email support"
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Privacy policy" msgstr "Privacy policy"
#: src/views/board/components/VisibilityButton.tsx:73 #: src/views/board/components/VisibilityButton.tsx:74
msgid "Private" msgid "Private"
msgstr "Private" msgstr "Private"
@@ -1815,7 +1841,7 @@ msgstr "Profile image updated"
msgid "Profile picture" msgid "Profile picture"
msgstr "Profile picture" msgstr "Profile picture"
#: src/views/board/components/VisibilityButton.tsx:68 #: src/views/board/components/VisibilityButton.tsx:69
msgid "Public" msgid "Public"
msgstr "Public" msgstr "Public"
@@ -2037,7 +2063,7 @@ msgstr "Sign up disabled"
msgid "Sign up is currently disabled. Please try again later." msgid "Sign up is currently disabled. Please try again later."
msgstr "Sign up is currently disabled. Please try again later." msgstr "Sign up is currently disabled. Please try again later."
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Sign up with " msgid "Sign up with "
msgstr "Sign up with " msgstr "Sign up with "
@@ -2104,8 +2130,8 @@ msgstr "Team Plan"
msgid "Teams" msgid "Teams"
msgstr "Teams" msgstr "Teams"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/board/index.tsx:396 #: src/views/board/index.tsx:398
msgid "Template" msgid "Template"
msgstr "Template" msgstr "Template"
@@ -2155,7 +2181,7 @@ msgid "The open source <0/> alternative to Trello"
msgstr "The open source <0/> alternative to Trello" msgstr "The open source <0/> alternative to Trello"
#. placeholder {0}: isPublic ? "public" : "private" #. placeholder {0}: isPublic ? "public" : "private"
#: src/views/board/components/VisibilityButton.tsx:46 #: src/views/board/components/VisibilityButton.tsx:47
msgid "The visibility of your board has been set to {0}." msgid "The visibility of your board has been set to {0}."
msgstr "The visibility of your board has been set to {0}." msgstr "The visibility of your board has been set to {0}."
@@ -2179,11 +2205,11 @@ 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:154 #: src/views/public/board/index.tsx:156
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135 #: src/views/board/components/UpdateBoardSlugForm.tsx:136
msgid "This board URL has already been taken" msgid "This board URL has already been taken"
msgstr "This board URL has already been taken" msgstr "This board URL has already been taken"
@@ -2261,7 +2287,7 @@ msgstr "Unable to add checklist item"
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:173 #: src/views/board/components/NewCardForm.tsx:174
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Unable to create card" msgstr "Unable to create card"
@@ -2269,7 +2295,7 @@ msgstr "Unable to create card"
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Unable to create checklist" msgstr "Unable to create checklist"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:78
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Unable to create list" msgstr "Unable to create list"
@@ -2282,6 +2308,10 @@ 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
msgid "Unable to delete attachment"
msgstr "Unable to delete attachment"
#: src/views/card/components/DeleteCardConfirmation.tsx:51 #: src/views/card/components/DeleteCardConfirmation.tsx:51
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Unable to delete card" msgstr "Unable to delete card"
@@ -2306,16 +2336,16 @@ msgstr "Unable to remove member"
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Unable to send feedback" msgstr "Unable to send feedback"
#: src/views/board/components/UpdateBoardSlugForm.tsx:71 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
msgid "Unable to update board URL" msgid "Unable to update board URL"
msgstr "Unable to update board URL" msgstr "Unable to update board URL"
#: src/views/board/components/VisibilityButton.tsx:52 #: src/views/board/components/VisibilityButton.tsx:53
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:204 #: src/views/board/index.tsx:206
#: src/views/card/index.tsx:174 #: src/views/card/index.tsx:176
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Unable to update card" msgstr "Unable to update card"
@@ -2335,7 +2365,7 @@ msgstr "Unable to update comment"
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:148 #: src/views/board/index.tsx:150
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:51
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Unable to update list" msgstr "Unable to update list"
@@ -2395,7 +2425,7 @@ msgstr "Unlimited members"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Unlimited workspaces" msgstr "Unlimited workspaces"
#: src/views/board/components/UpdateBoardSlugForm.tsx:174 #: 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
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83 #: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83
@@ -2446,6 +2476,11 @@ 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:78
msgid "Upload failed"
msgstr "Upload failed"
#: src/views/boards/components/TemplateBoards.tsx:38 #: src/views/boards/components/TemplateBoards.tsx:38
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Urgent" msgid "Urgent"
@@ -2495,7 +2530,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:128 #: src/views/public/board/index.tsx:129
msgid "View only" msgid "View only"
msgstr "View only" msgstr "View only"
@@ -2503,11 +2538,11 @@ 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:157 #: src/views/public/board/index.tsx:159
msgid "View workspace" msgid "View workspace"
msgstr "View workspace" msgstr "View workspace"
#: src/views/board/components/VisibilityButton.tsx:91 #: src/views/board/components/VisibilityButton.tsx:92
msgid "Visibility" msgid "Visibility"
msgstr "Visibility" msgstr "Visibility"
@@ -2552,10 +2587,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:361 #: src/views/board/index.tsx:363
#: src/views/boards/index.tsx:22 #: src/views/boards/index.tsx:22
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Workspace" msgstr "Workspace"
@@ -2689,6 +2724,10 @@ 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
msgid "Your file has been uploaded successfully."
msgstr "Your file has been uploaded successfully."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70 #: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "Your password has been changed." msgstr "Your password has been changed."

File diff suppressed because one or more lines are too long

View File

@@ -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:22 #: src/views/boards/index.tsx:22
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
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:442 #: src/views/board/components/NewCardForm.tsx:443
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:387 #: src/views/board/index.tsx:389
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} no encontrado" msgstr "{0} no encontrado"
@@ -79,8 +79,8 @@ msgstr "Cuenta"
msgid "Account deleted" msgid "Account deleted"
msgstr "Cuenta eliminada" msgstr "Cuenta eliminada"
#: src/views/card/index.tsx:291 #: src/views/card/index.tsx:308
#: src/views/public/board/CardModal.tsx:143 #: src/views/public/board/CardModal.tsx:157
msgid "Activity" msgid "Activity"
msgstr "Actividad" msgstr "Actividad"
@@ -109,7 +109,7 @@ msgstr "Añadir un elemento..."
msgid "Add checklist" msgid "Add checklist"
msgstr "Añadir lista de verificación" msgstr "Añadir lista de verificación"
#: src/components/Editor.tsx:442 #: src/components/Editor.tsx:451
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)"
@@ -270,6 +270,10 @@ msgstr "asignó <0>{0}</0> a la tarjeta"
msgid "Assignees" msgid "Assignees"
msgstr "Asignados" msgstr "Asignados"
#: src/views/card/components/AttachmentUpload.tsx:25
msgid "Attachment uploaded"
msgstr "Archivo adjunto subido"
#: src/views/boards/components/TemplateBoards.tsx:47 #: src/views/boards/components/TemplateBoards.tsx:47
msgid "Awaiting Customer" msgid "Awaiting Customer"
msgstr "Esperando al cliente" msgstr "Esperando al cliente"
@@ -304,9 +308,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:361 #: src/views/board/index.tsx:363
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
msgid "Board" msgid "Board"
msgstr "Tablero" msgstr "Tablero"
@@ -323,7 +327,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:151 #: src/views/public/board/index.tsx:153
msgid "Board not found" msgid "Board not found"
msgstr "Tablero no encontrado" msgstr "Tablero no encontrado"
@@ -331,19 +335,19 @@ msgstr "Tablero no encontrado"
msgid "Board sharing & invites" msgid "Board sharing & invites"
msgstr "Compartir tablero e invitaciones" msgstr "Compartir tablero e invitaciones"
#: src/views/board/components/UpdateBoardSlugForm.tsx:45 #: src/views/board/components/UpdateBoardSlugForm.tsx:46
msgid "Board URL can only contain letters, numbers, and hyphens" msgid "Board URL can only contain letters, numbers, and hyphens"
msgstr "La URL del tablero solo puede contener letras, números y guiones" msgstr "La URL del tablero solo puede contener letras, números y guiones"
#: src/views/board/components/UpdateBoardSlugForm.tsx:43 #: src/views/board/components/UpdateBoardSlugForm.tsx:44
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:67 #: src/views/public/board/index.tsx:68
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:41 #: src/views/board/components/UpdateBoardSlugForm.tsx:42
msgid "Board URL must be at least 3 characters long" msgid "Board URL must be at least 3 characters long"
msgstr "La URL del tablero debe tener al menos 3 caracteres" msgstr "La URL del tablero debe tener al menos 3 caracteres"
@@ -352,7 +356,7 @@ msgstr "La URL del tablero debe tener al menos 3 caracteres"
msgid "Board visibility" msgid "Board visibility"
msgstr "Visibilidad del tablero" msgstr "Visibilidad del tablero"
#: src/views/board/components/VisibilityButton.tsx:45 #: src/views/board/components/VisibilityButton.tsx:46
msgid "Board visibility updated" msgid "Board visibility updated"
msgstr "Visibilidad del tablero actualizada" msgstr "Visibilidad del tablero actualizada"
@@ -387,15 +391,15 @@ msgstr "Informe de error"
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
msgid "Card" msgid "Card"
msgstr "Tarjeta" msgstr "Tarjeta"
#: src/views/card/index.tsx:262 #: src/views/card/index.tsx:264
msgid "Card not found" msgid "Card not found"
msgstr "Tarjeta no encontrada" msgstr "Tarjeta no encontrada"
#: src/views/board/components/NewCardForm.tsx:309 #: src/views/board/components/NewCardForm.tsx:310
msgid "Card title" msgid "Card title"
msgstr "Título de la tarjeta" msgstr "Título de la tarjeta"
@@ -428,7 +432,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:155 #: src/views/board/components/Filters.tsx:180
msgid "Clear filters" msgid "Clear filters"
msgstr "Borrar filtros" msgstr "Borrar filtros"
@@ -519,7 +523,7 @@ msgstr "Contáctanos"
msgid "Content Creation" msgid "Content Creation"
msgstr "Creación de contenido" msgstr "Creación de contenido"
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Continue with " msgid "Continue with "
msgstr "Continuar con " msgstr "Continuar con "
@@ -542,8 +546,8 @@ 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:468 #: src/views/board/components/NewCardForm.tsx:469
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Crear otro" msgstr "Crear otro"
@@ -551,7 +555,7 @@ 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:478 #: src/views/board/components/NewCardForm.tsx:479
msgid "Create card" msgid "Create card"
msgstr "Crear tarjeta" msgstr "Crear tarjeta"
@@ -567,7 +571,7 @@ msgstr "Crear enlace de invitación"
msgid "Create label" msgid "Create label"
msgstr "Crear etiqueta" msgstr "Crear etiqueta"
#: src/views/board/components/NewListForm.tsx:152 #: src/views/board/components/NewListForm.tsx:153
msgid "Create list" msgid "Create list"
msgstr "Crear lista" msgstr "Crear lista"
@@ -580,12 +584,12 @@ 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:404 #: src/views/board/components/NewCardForm.tsx:405
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:97
msgid "Create new label" msgid "Create new label"
msgstr "Crear nueva etiqueta" msgstr "Crear nueva etiqueta"
#: src/views/board/index.tsx:475 #: src/views/board/index.tsx:478
msgid "Create new list" msgid "Create new list"
msgstr "Crear nueva lista" msgstr "Crear nueva lista"
@@ -769,8 +773,12 @@ 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
msgid "Download failed"
msgstr "Error en la descarga"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:115 #: 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"
@@ -782,7 +790,7 @@ msgstr "Editar comentario"
msgid "Edit label" msgid "Edit label"
msgstr "Editar etiqueta" msgstr "Editar etiqueta"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161 #: src/views/board/components/UpdateBoardSlugForm.tsx:162
msgid "Edit workspace URL" msgid "Edit workspace URL"
msgstr "Editar URL del espacio de trabajo" msgstr "Editar URL del espacio de trabajo"
@@ -790,7 +798,7 @@ msgstr "Editar URL del espacio de trabajo"
msgid "Editing" msgid "Editing"
msgstr "Editando" msgstr "Editando"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "email" msgid "email"
msgstr "correo electrónico" msgstr "correo electrónico"
@@ -810,11 +818,11 @@ msgstr "Introduce tu contraseña actual"
msgid "Enter your current password and choose a new secure password." msgid "Enter your current password and choose a new secure password."
msgstr "Introduce tu contraseña actual y elige una nueva contraseña segura." msgstr "Introduce tu contraseña actual y elige una nueva contraseña segura."
#: src/components/AuthForm.tsx:387 #: src/components/AuthForm.tsx:398
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Introduce tu dirección de correo electrónico" msgstr "Introduce tu dirección de correo electrónico"
#: src/components/AuthForm.tsx:375 #: src/components/AuthForm.tsx:384
msgid "Enter your name" msgid "Enter your name"
msgstr "Introduce tu nombre" msgstr "Introduce tu nombre"
@@ -822,7 +830,7 @@ msgstr "Introduce tu nombre"
msgid "Enter your new password" msgid "Enter your new password"
msgstr "Introduce tu nueva contraseña" msgstr "Introduce tu nueva contraseña"
#: src/components/AuthForm.tsx:400 #: src/components/AuthForm.tsx:411
msgid "Enter your password" msgid "Enter your password"
msgstr "Introduce tu contraseña" msgstr "Introduce tu contraseña"
@@ -931,6 +939,11 @@ 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:79
msgid "Failed to upload attachment. Please try again."
msgstr "Error al subir el archivo adjunto. Por favor, inténtalo de nuevo."
#: src/views/home/components/Header.tsx:41 #: src/views/home/components/Header.tsx:41
msgid "FAQ" msgid "FAQ"
msgstr "FAQ" msgstr "FAQ"
@@ -974,7 +987,7 @@ msgstr "Comentarios"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Comentarios enviados" msgstr "Comentarios enviados"
#: src/views/board/components/Filters.tsx:149 #: src/views/board/components/Filters.tsx:174
msgid "Filter" msgid "Filter"
msgstr "Filtrar" msgstr "Filtrar"
@@ -987,6 +1000,8 @@ msgid "For long-term sustainability, we recognise all good open source projects
msgstr "Para la sostenibilidad a largo plazo, reconocemos que todos los buenos proyectos de código abierto necesitan una fuente de ingresos. La nuestra proviene de la oferta de nube de pago para espacios de trabajo con múltiples usuarios y para slugs de espacio de trabajo personalizados. No hay obligación de usarla, y puedes alojar el software en tu propia infraestructura sin costo alguno." msgstr "Para la sostenibilidad a largo plazo, reconocemos que todos los buenos proyectos de código abierto necesitan una fuente de ingresos. La nuestra proviene de la oferta de nube de pago para espacios de trabajo con múltiples usuarios y para slugs de espacio de trabajo personalizados. No hay obligación de usarla, y puedes alojar el software en tu propia infraestructura sin costo alguno."
#: src/views/pricing/components/Pricing.tsx:32 #: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/PricingTiers.tsx:30
#: src/views/pricing/components/PricingTiers.tsx:30 #: src/views/pricing/components/PricingTiers.tsx:30
msgid "Free" msgid "Free"
msgstr "Gratis" msgstr "Gratis"
@@ -1028,7 +1043,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:467 #: src/views/board/index.tsx:470
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"
@@ -1242,9 +1257,9 @@ msgstr "Kanban reinventado"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Ten en cuenta que esta acción es irreversible." msgstr "Ten en cuenta que esta acción es irreversible."
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:115
#: src/views/board/components/NewCardForm.tsx:408 #: src/views/board/components/NewCardForm.tsx:409
#: src/views/card/index.tsx:117 #: src/views/card/index.tsx:119
msgid "Labels" msgid "Labels"
msgstr "Etiquetas" msgstr "Etiquetas"
@@ -1294,18 +1309,22 @@ msgstr "Licencia"
msgid "Light" msgid "Light"
msgstr "Claro" msgstr "Claro"
#: src/views/public/board/index.tsx:65 #: src/views/public/board/index.tsx:66
msgid "Link copied" msgid "Link copied"
msgstr "Enlace copiado" msgstr "Enlace copiado"
#: src/views/card/index.tsx:109 #: src/views/card/index.tsx:111
msgid "List" msgid "List"
msgstr "Lista" msgstr "Lista"
#: src/views/board/components/NewListForm.tsx:128 #: src/views/board/components/NewListForm.tsx:129
msgid "List name" msgid "List name"
msgstr "Nombre de la lista" msgstr "Nombre de la lista"
#: src/views/board/components/Filters.tsx:123
msgid "Lists"
msgstr "Listas"
#: 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"
@@ -1326,7 +1345,7 @@ msgstr "Amado por equipos en todo el mundo"
msgid "Low Priority" msgid "Low Priority"
msgstr "Prioridad baja" msgstr "Prioridad baja"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "magic link" msgid "magic link"
msgstr "enlace mágico" msgstr "enlace mágico"
@@ -1348,9 +1367,9 @@ msgid "Medium Priority"
msgstr "Prioridad media" msgstr "Prioridad media"
#: src/components/SideNavigation.tsx:101 #: src/components/SideNavigation.tsx:101
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:107
#: src/views/board/components/NewCardForm.tsx:366 #: src/views/board/components/NewCardForm.tsx:367
#: src/views/card/index.tsx:126 #: src/views/card/index.tsx:128
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Miembros" msgstr "Miembros"
@@ -1403,7 +1422,7 @@ 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:292 #: src/views/board/components/NewCardForm.tsx:293
msgid "New card" msgid "New card"
msgstr "Nueva tarjeta" msgstr "Nueva tarjeta"
@@ -1419,8 +1438,8 @@ msgstr "Nueva importación"
msgid "New label" msgid "New label"
msgstr "Nueva etiqueta" msgstr "Nueva etiqueta"
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:439 #: src/views/board/index.tsx:442
msgid "New list" msgid "New list"
msgstr "Nueva lista" msgstr "Nueva lista"
@@ -1457,6 +1476,10 @@ msgstr "Próximos pasos"
msgid "No {0}" msgid "No {0}"
msgstr "Sin {0}" msgstr "Sin {0}"
#: src/components/AuthForm.tsx:365
msgid "No authentication methods are currently available"
msgstr "No hay métodos de autenticación disponibles actualmente"
#: src/views/boards/components/ImportBoardsForm.tsx:242 #: src/views/boards/components/ImportBoardsForm.tsx:242
msgid "No boards found" msgid "No boards found"
msgstr "No se encontraron tableros" msgstr "No se encontraron tableros"
@@ -1465,7 +1488,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/board/index.tsx:464 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "No download URL available for this attachment."
msgstr "No hay URL de descarga disponible para este archivo adjunto."
#: src/views/board/index.tsx:467
msgid "No lists" msgid "No lists"
msgstr "Sin listas" msgstr "Sin listas"
@@ -1497,7 +1524,7 @@ msgstr "Código abierto"
msgid "Open Source Friends" msgid "Open Source Friends"
msgstr "Amigos de código abierto" msgstr "Amigos de código abierto"
#: src/components/AuthForm.tsx:365 #: src/components/AuthForm.tsx:374
msgid "or" msgid "or"
msgstr "o" msgstr "o"
@@ -1579,15 +1606,15 @@ msgstr "Plataforma"
msgid "Please confirm your new password" msgid "Please confirm your new password"
msgstr "Por favor, confirma tu nueva contraseña" msgstr "Por favor, confirma tu nueva contraseña"
#: src/components/AuthForm.tsx:391 #: src/components/AuthForm.tsx:402
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Por favor, introduce una dirección de correo electrónico válida" msgstr "Por favor, introduce una dirección de correo electrónico válida"
#: src/components/AuthForm.tsx:379 #: src/components/AuthForm.tsx:388
msgid "Please enter a valid name" msgid "Please enter a valid name"
msgstr "Por favor, introduce un nombre válido" msgstr "Por favor, introduce un nombre válido"
#: src/components/AuthForm.tsx:404 #: src/components/AuthForm.tsx:416
msgid "Please enter a valid password" msgid "Please enter a valid password"
msgstr "Por favor, introduce una contraseña válida" msgstr "Por favor, introduce una contraseña válida"
@@ -1598,15 +1625,16 @@ 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:176 #: src/views/board/components/NewCardForm.tsx:177
#: src/views/board/components/NewListForm.tsx:78 #: 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:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:149 #: src/views/board/index.tsx:151
#: src/views/board/index.tsx:205 #: src/views/board/index.tsx:207
#: 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/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:46
@@ -1620,7 +1648,7 @@ msgstr "Por favor selecciona un archivo para subir."
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/index.tsx:175 #: src/views/card/index.tsx:177
#: 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
@@ -1664,7 +1692,7 @@ msgstr "Soporte prioritario por email"
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Política de privacidad" msgstr "Política de privacidad"
#: src/views/board/components/VisibilityButton.tsx:73 #: src/views/board/components/VisibilityButton.tsx:74
msgid "Private" msgid "Private"
msgstr "Privado" msgstr "Privado"
@@ -1684,7 +1712,7 @@ msgstr "Imagen de perfil actualizada"
msgid "Profile picture" msgid "Profile picture"
msgstr "Foto de perfil" msgstr "Foto de perfil"
#: src/views/board/components/VisibilityButton.tsx:68 #: src/views/board/components/VisibilityButton.tsx:69
msgid "Public" msgid "Public"
msgstr "Público" msgstr "Público"
@@ -1886,7 +1914,7 @@ msgstr "Registro deshabilitado"
msgid "Sign up is currently disabled. Please try again later." msgid "Sign up is currently disabled. Please try again later."
msgstr "El registro está actualmente deshabilitado. Por favor, inténtalo de nuevo más tarde." msgstr "El registro está actualmente deshabilitado. Por favor, inténtalo de nuevo más tarde."
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Sign up with " msgid "Sign up with "
msgstr "Registrarse con " msgstr "Registrarse con "
@@ -1953,8 +1981,8 @@ msgstr "Plan de Equipo"
msgid "Teams" msgid "Teams"
msgstr "Equipos" msgstr "Equipos"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/board/index.tsx:396 #: src/views/board/index.tsx:398
msgid "Template" msgid "Template"
msgstr "Plantilla" msgstr "Plantilla"
@@ -2004,7 +2032,7 @@ msgid "The open source <0/> alternative to Trello"
msgstr "La alternativa de código abierto <0/> a Trello" msgstr "La alternativa de código abierto <0/> a Trello"
#. placeholder {0}: isPublic ? "public" : "private" #. placeholder {0}: isPublic ? "public" : "private"
#: src/views/board/components/VisibilityButton.tsx:46 #: src/views/board/components/VisibilityButton.tsx:47
msgid "The visibility of your board has been set to {0}." msgid "The visibility of your board has been set to {0}."
msgstr "La visibilidad de tu tablero ha sido establecida a {0}." msgstr "La visibilidad de tu tablero ha sido establecida a {0}."
@@ -2028,11 +2056,11 @@ 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:154 #: src/views/public/board/index.tsx:156
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135 #: src/views/board/components/UpdateBoardSlugForm.tsx:136
msgid "This board URL has already been taken" msgid "This board URL has already been taken"
msgstr "Esta URL de tablero ya ha sido utilizada" msgstr "Esta URL de tablero ya ha sido utilizada"
@@ -2102,7 +2130,7 @@ msgstr "No se puede añadir el elemento a la lista de verificación"
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:173 #: src/views/board/components/NewCardForm.tsx:174
msgid "Unable to create card" msgid "Unable to create card"
msgstr "No se puede crear la tarjeta" msgstr "No se puede crear la tarjeta"
@@ -2110,7 +2138,7 @@ msgstr "No se puede crear la tarjeta"
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"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:78
msgid "Unable to create list" msgid "Unable to create list"
msgstr "No se puede crear la lista" msgstr "No se puede crear la lista"
@@ -2123,6 +2151,10 @@ 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
msgid "Unable to delete attachment"
msgstr "No se puede eliminar el archivo adjunto"
#: src/views/card/components/DeleteCardConfirmation.tsx:51 #: src/views/card/components/DeleteCardConfirmation.tsx:51
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "No se puede eliminar la tarjeta" msgstr "No se puede eliminar la tarjeta"
@@ -2147,16 +2179,16 @@ msgstr "No se puede eliminar al miembro"
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "No se pudieron enviar los comentarios" msgstr "No se pudieron enviar los comentarios"
#: src/views/board/components/UpdateBoardSlugForm.tsx:71 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
msgid "Unable to update board URL" msgid "Unable to update board URL"
msgstr "No se puede actualizar la URL del tablero" msgstr "No se puede actualizar la URL del tablero"
#: src/views/board/components/VisibilityButton.tsx:52 #: src/views/board/components/VisibilityButton.tsx:53
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:204 #: src/views/board/index.tsx:206
#: src/views/card/index.tsx:174 #: src/views/card/index.tsx:176
msgid "Unable to update card" msgid "Unable to update card"
msgstr "No se puede actualizar la tarjeta" msgstr "No se puede actualizar la tarjeta"
@@ -2176,7 +2208,7 @@ msgstr "No se puede actualizar el comentario"
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:148 #: src/views/board/index.tsx:150
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:51
msgid "Unable to update list" msgid "Unable to update list"
msgstr "No se puede actualizar la lista" msgstr "No se puede actualizar la lista"
@@ -2232,7 +2264,7 @@ msgstr "Miembros ilimitados"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Espacios de trabajo ilimitados" msgstr "Espacios de trabajo ilimitados"
#: src/views/board/components/UpdateBoardSlugForm.tsx:174 #: 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
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83 #: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83
@@ -2271,6 +2303,11 @@ 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:78
msgid "Upload failed"
msgstr "Error al subir"
#: src/views/boards/components/TemplateBoards.tsx:38 #: src/views/boards/components/TemplateBoards.tsx:38
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Urgent" msgid "Urgent"
@@ -2320,7 +2357,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:128 #: src/views/public/board/index.tsx:129
msgid "View only" msgid "View only"
msgstr "Solo visualización" msgstr "Solo visualización"
@@ -2328,11 +2365,11 @@ 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:157 #: src/views/public/board/index.tsx:159
msgid "View workspace" msgid "View workspace"
msgstr "Ver espacio de trabajo" msgstr "Ver espacio de trabajo"
#: src/views/board/components/VisibilityButton.tsx:91 #: src/views/board/components/VisibilityButton.tsx:92
msgid "Visibility" msgid "Visibility"
msgstr "Visibilidad" msgstr "Visibilidad"
@@ -2369,10 +2406,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:361 #: src/views/board/index.tsx:363
#: src/views/boards/index.tsx:22 #: src/views/boards/index.tsx:22
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
#: 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"
@@ -2502,6 +2539,10 @@ 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
msgid "Your file has been uploaded successfully."
msgstr "Tu archivo se ha subido correctamente."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70 #: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "Tu contraseña ha sido cambiada." msgstr "Tu contraseña ha sido cambiada."

File diff suppressed because one or more lines are too long

View File

@@ -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:22 #: src/views/boards/index.tsx:22
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
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:442 #: src/views/board/components/NewCardForm.tsx:443
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:387 #: src/views/board/index.tsx:389
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} introuvable" msgstr "{0} introuvable"
@@ -79,8 +79,8 @@ msgstr "Compte"
msgid "Account deleted" msgid "Account deleted"
msgstr "Compte supprimé" msgstr "Compte supprimé"
#: src/views/card/index.tsx:291 #: src/views/card/index.tsx:308
#: src/views/public/board/CardModal.tsx:143 #: src/views/public/board/CardModal.tsx:157
msgid "Activity" msgid "Activity"
msgstr "Activité" msgstr "Activité"
@@ -109,7 +109,7 @@ msgstr "Ajouter un élément..."
msgid "Add checklist" msgid "Add checklist"
msgstr "Ajouter une checklist" msgstr "Ajouter une checklist"
#: src/components/Editor.tsx:442 #: src/components/Editor.tsx:451
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)"
@@ -270,6 +270,10 @@ 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
msgid "Attachment uploaded"
msgstr "Pièce jointe téléversée"
#: src/views/boards/components/TemplateBoards.tsx:47 #: src/views/boards/components/TemplateBoards.tsx:47
msgid "Awaiting Customer" msgid "Awaiting Customer"
msgstr "En attente du client" msgstr "En attente du client"
@@ -304,9 +308,9 @@ msgstr "Portail de facturation"
msgid "Blog Post" msgid "Blog Post"
msgstr "Article de blog" msgstr "Article de blog"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
msgid "Board" msgid "Board"
msgstr "Tableau" msgstr "Tableau"
@@ -323,7 +327,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:151 #: src/views/public/board/index.tsx:153
msgid "Board not found" msgid "Board not found"
msgstr "Tableau introuvable" msgstr "Tableau introuvable"
@@ -331,19 +335,19 @@ msgstr "Tableau introuvable"
msgid "Board sharing & invites" msgid "Board sharing & invites"
msgstr "Partage de tableau & invitations" msgstr "Partage de tableau & invitations"
#: src/views/board/components/UpdateBoardSlugForm.tsx:45 #: src/views/board/components/UpdateBoardSlugForm.tsx:46
msgid "Board URL can only contain letters, numbers, and hyphens" msgid "Board URL can only contain letters, numbers, and hyphens"
msgstr "L'URL du tableau ne peut contenir que des lettres, des chiffres et des traits d'union" msgstr "L'URL du tableau ne peut contenir que des lettres, des chiffres et des traits d'union"
#: src/views/board/components/UpdateBoardSlugForm.tsx:43 #: src/views/board/components/UpdateBoardSlugForm.tsx:44
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:67 #: src/views/public/board/index.tsx:68
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:41 #: src/views/board/components/UpdateBoardSlugForm.tsx:42
msgid "Board URL must be at least 3 characters long" msgid "Board URL must be at least 3 characters long"
msgstr "L'URL du tableau doit comporter au moins 3 caractères" msgstr "L'URL du tableau doit comporter au moins 3 caractères"
@@ -352,7 +356,7 @@ msgstr "L'URL du tableau doit comporter au moins 3 caractères"
msgid "Board visibility" msgid "Board visibility"
msgstr "Visibilité du tableau" msgstr "Visibilité du tableau"
#: src/views/board/components/VisibilityButton.tsx:45 #: src/views/board/components/VisibilityButton.tsx:46
msgid "Board visibility updated" msgid "Board visibility updated"
msgstr "Visibilité du tableau mise à jour" msgstr "Visibilité du tableau mise à jour"
@@ -387,15 +391,15 @@ msgstr "Rapport de bug"
msgid "Cancel" msgid "Cancel"
msgstr "Annuler" msgstr "Annuler"
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
msgid "Card" msgid "Card"
msgstr "Carte" msgstr "Carte"
#: src/views/card/index.tsx:262 #: src/views/card/index.tsx:264
msgid "Card not found" msgid "Card not found"
msgstr "Carte introuvable" msgstr "Carte introuvable"
#: src/views/board/components/NewCardForm.tsx:309 #: src/views/board/components/NewCardForm.tsx:310
msgid "Card title" msgid "Card title"
msgstr "Titre de la carte" msgstr "Titre de la carte"
@@ -428,7 +432,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:155 #: src/views/board/components/Filters.tsx:180
msgid "Clear filters" msgid "Clear filters"
msgstr "Effacer les filtres" msgstr "Effacer les filtres"
@@ -519,7 +523,7 @@ msgstr "Contactez-nous"
msgid "Content Creation" msgid "Content Creation"
msgstr "Création de contenu" msgstr "Création de contenu"
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Continue with " msgid "Continue with "
msgstr "Continuer avec " msgstr "Continuer avec "
@@ -542,8 +546,8 @@ 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:468 #: src/views/board/components/NewCardForm.tsx:469
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Créer un autre" msgstr "Créer un autre"
@@ -551,7 +555,7 @@ 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:478 #: src/views/board/components/NewCardForm.tsx:479
msgid "Create card" msgid "Create card"
msgstr "Créer une carte" msgstr "Créer une carte"
@@ -567,7 +571,7 @@ msgstr "Créer un lien d'invitation"
msgid "Create label" msgid "Create label"
msgstr "Créer une étiquette" msgstr "Créer une étiquette"
#: src/views/board/components/NewListForm.tsx:152 #: src/views/board/components/NewListForm.tsx:153
msgid "Create list" msgid "Create list"
msgstr "Créer une liste" msgstr "Créer une liste"
@@ -580,12 +584,12 @@ 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:404 #: src/views/board/components/NewCardForm.tsx:405
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:97
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:475 #: src/views/board/index.tsx:478
msgid "Create new list" msgid "Create new list"
msgstr "Créer une nouvelle liste" msgstr "Créer une nouvelle liste"
@@ -769,8 +773,12 @@ 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
msgid "Download failed"
msgstr "Échec du téléchargement"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:115 #: 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"
@@ -782,7 +790,7 @@ msgstr "Modifier le commentaire"
msgid "Edit label" msgid "Edit label"
msgstr "Modifier l'étiquette" msgstr "Modifier l'étiquette"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161 #: src/views/board/components/UpdateBoardSlugForm.tsx:162
msgid "Edit workspace URL" msgid "Edit workspace URL"
msgstr "Modifier l'URL de l'espace de travail" msgstr "Modifier l'URL de l'espace de travail"
@@ -790,7 +798,7 @@ msgstr "Modifier l'URL de l'espace de travail"
msgid "Editing" msgid "Editing"
msgstr "Édition" msgstr "Édition"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "email" msgid "email"
msgstr "e-mail" msgstr "e-mail"
@@ -810,11 +818,11 @@ msgstr "Saisissez votre mot de passe actuel"
msgid "Enter your current password and choose a new secure password." msgid "Enter your current password and choose a new secure password."
msgstr "Saisissez votre mot de passe actuel et choisissez un nouveau mot de passe sécurisé." msgstr "Saisissez votre mot de passe actuel et choisissez un nouveau mot de passe sécurisé."
#: src/components/AuthForm.tsx:387 #: src/components/AuthForm.tsx:398
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Saisissez votre adresse e-mail" msgstr "Saisissez votre adresse e-mail"
#: src/components/AuthForm.tsx:375 #: src/components/AuthForm.tsx:384
msgid "Enter your name" msgid "Enter your name"
msgstr "Saisissez votre nom" msgstr "Saisissez votre nom"
@@ -822,7 +830,7 @@ msgstr "Saisissez votre nom"
msgid "Enter your new password" msgid "Enter your new password"
msgstr "Saisissez votre nouveau mot de passe" msgstr "Saisissez votre nouveau mot de passe"
#: src/components/AuthForm.tsx:400 #: src/components/AuthForm.tsx:411
msgid "Enter your password" msgid "Enter your password"
msgstr "Saisissez votre mot de passe" msgstr "Saisissez votre mot de passe"
@@ -931,6 +939,11 @@ 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:79
msgid "Failed to upload attachment. Please try again."
msgstr "Échec du téléversement de la pièce jointe. Veuillez réessayer."
#: src/views/home/components/Header.tsx:41 #: src/views/home/components/Header.tsx:41
msgid "FAQ" msgid "FAQ"
msgstr "FAQ" msgstr "FAQ"
@@ -974,7 +987,7 @@ msgstr "Commentaires"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Commentaires envoyés" msgstr "Commentaires envoyés"
#: src/views/board/components/Filters.tsx:149 #: src/views/board/components/Filters.tsx:174
msgid "Filter" msgid "Filter"
msgstr "Filtrer" msgstr "Filtrer"
@@ -987,6 +1000,8 @@ msgid "For long-term sustainability, we recognise all good open source projects
msgstr "Pour une durabilité à long terme, nous reconnaissons que tous les bons projets open source ont besoin d'une source de revenus. La nôtre provient de l'offre cloud payante pour les espaces de travail avec plusieurs utilisateurs et pour les slugs d'espace de travail personnalisés. Il n'y a aucune obligation de l'utiliser, et vous pouvez auto-héberger le logiciel sur votre propre infrastructure gratuitement." msgstr "Pour une durabilité à long terme, nous reconnaissons que tous les bons projets open source ont besoin d'une source de revenus. La nôtre provient de l'offre cloud payante pour les espaces de travail avec plusieurs utilisateurs et pour les slugs d'espace de travail personnalisés. Il n'y a aucune obligation de l'utiliser, et vous pouvez auto-héberger le logiciel sur votre propre infrastructure gratuitement."
#: src/views/pricing/components/Pricing.tsx:32 #: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/PricingTiers.tsx:30
#: src/views/pricing/components/PricingTiers.tsx:30 #: src/views/pricing/components/PricingTiers.tsx:30
msgid "Free" msgid "Free"
msgstr "Gratuit" msgstr "Gratuit"
@@ -1028,7 +1043,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:467 #: src/views/board/index.tsx:470
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"
@@ -1242,9 +1257,9 @@ msgstr "Kanban réinventé"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Gardez à l'esprit que cette action est irréversible." msgstr "Gardez à l'esprit que cette action est irréversible."
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:115
#: src/views/board/components/NewCardForm.tsx:408 #: src/views/board/components/NewCardForm.tsx:409
#: src/views/card/index.tsx:117 #: src/views/card/index.tsx:119
msgid "Labels" msgid "Labels"
msgstr "Étiquettes" msgstr "Étiquettes"
@@ -1294,18 +1309,22 @@ msgstr "Licence"
msgid "Light" msgid "Light"
msgstr "Clair" msgstr "Clair"
#: src/views/public/board/index.tsx:65 #: src/views/public/board/index.tsx:66
msgid "Link copied" msgid "Link copied"
msgstr "Lien copié" msgstr "Lien copié"
#: src/views/card/index.tsx:109 #: src/views/card/index.tsx:111
msgid "List" msgid "List"
msgstr "Liste" msgstr "Liste"
#: src/views/board/components/NewListForm.tsx:128 #: src/views/board/components/NewListForm.tsx:129
msgid "List name" msgid "List name"
msgstr "Nom de la liste" msgstr "Nom de la liste"
#: src/views/board/components/Filters.tsx:123
msgid "Lists"
msgstr "Listes"
#: 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"
@@ -1326,7 +1345,7 @@ msgstr "Adoré par les équipes du monde entier"
msgid "Low Priority" msgid "Low Priority"
msgstr "Priorité basse" msgstr "Priorité basse"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "magic link" msgid "magic link"
msgstr "lien magique" msgstr "lien magique"
@@ -1348,9 +1367,9 @@ msgid "Medium Priority"
msgstr "Priorité moyenne" msgstr "Priorité moyenne"
#: src/components/SideNavigation.tsx:101 #: src/components/SideNavigation.tsx:101
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:107
#: src/views/board/components/NewCardForm.tsx:366 #: src/views/board/components/NewCardForm.tsx:367
#: src/views/card/index.tsx:126 #: src/views/card/index.tsx:128
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Membres" msgstr "Membres"
@@ -1403,7 +1422,7 @@ 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:292 #: src/views/board/components/NewCardForm.tsx:293
msgid "New card" msgid "New card"
msgstr "Nouvelle carte" msgstr "Nouvelle carte"
@@ -1419,8 +1438,8 @@ msgstr "Nouvel import"
msgid "New label" msgid "New label"
msgstr "Nouvelle étiquette" msgstr "Nouvelle étiquette"
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:439 #: src/views/board/index.tsx:442
msgid "New list" msgid "New list"
msgstr "Nouvelle liste" msgstr "Nouvelle liste"
@@ -1457,6 +1476,10 @@ msgstr "Prochaines étapes"
msgid "No {0}" msgid "No {0}"
msgstr "Aucun {0}" msgstr "Aucun {0}"
#: src/components/AuthForm.tsx:365
msgid "No authentication methods are currently available"
msgstr "Aucune méthode d'authentification n'est actuellement disponible"
#: src/views/boards/components/ImportBoardsForm.tsx:242 #: src/views/boards/components/ImportBoardsForm.tsx:242
msgid "No boards found" msgid "No boards found"
msgstr "Aucun tableau trouvé" msgstr "Aucun tableau trouvé"
@@ -1465,7 +1488,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/board/index.tsx:464 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "No download URL available for this attachment."
msgstr "Aucune URL de téléchargement disponible pour cette pièce jointe."
#: src/views/board/index.tsx:467
msgid "No lists" msgid "No lists"
msgstr "Aucune liste" msgstr "Aucune liste"
@@ -1497,7 +1524,7 @@ msgstr "Open source"
msgid "Open Source Friends" msgid "Open Source Friends"
msgstr "Amis Open Source" msgstr "Amis Open Source"
#: src/components/AuthForm.tsx:365 #: src/components/AuthForm.tsx:374
msgid "or" msgid "or"
msgstr "ou" msgstr "ou"
@@ -1579,15 +1606,15 @@ msgstr "Plateforme"
msgid "Please confirm your new password" msgid "Please confirm your new password"
msgstr "Veuillez confirmer votre nouveau mot de passe" msgstr "Veuillez confirmer votre nouveau mot de passe"
#: src/components/AuthForm.tsx:391 #: src/components/AuthForm.tsx:402
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Veuillez saisir une adresse e-mail valide" msgstr "Veuillez saisir une adresse e-mail valide"
#: src/components/AuthForm.tsx:379 #: src/components/AuthForm.tsx:388
msgid "Please enter a valid name" msgid "Please enter a valid name"
msgstr "Veuillez saisir un nom valide" msgstr "Veuillez saisir un nom valide"
#: src/components/AuthForm.tsx:404 #: src/components/AuthForm.tsx:416
msgid "Please enter a valid password" msgid "Please enter a valid password"
msgstr "Veuillez saisir un mot de passe valide" msgstr "Veuillez saisir un mot de passe valide"
@@ -1598,15 +1625,16 @@ 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:176 #: src/views/board/components/NewCardForm.tsx:177
#: src/views/board/components/NewListForm.tsx:78 #: 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:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:149 #: src/views/board/index.tsx:151
#: src/views/board/index.tsx:205 #: src/views/board/index.tsx:207
#: 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/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:46
@@ -1620,7 +1648,7 @@ msgstr "Veuillez sélectionner un fichier à télécharger."
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/index.tsx:175 #: src/views/card/index.tsx:177
#: 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
@@ -1664,7 +1692,7 @@ msgstr "Support par e-mail prioritaire"
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Politique de confidentialité" msgstr "Politique de confidentialité"
#: src/views/board/components/VisibilityButton.tsx:73 #: src/views/board/components/VisibilityButton.tsx:74
msgid "Private" msgid "Private"
msgstr "Privé" msgstr "Privé"
@@ -1684,7 +1712,7 @@ msgstr "Image de profil mise à jour"
msgid "Profile picture" msgid "Profile picture"
msgstr "Photo de profil" msgstr "Photo de profil"
#: src/views/board/components/VisibilityButton.tsx:68 #: src/views/board/components/VisibilityButton.tsx:69
msgid "Public" msgid "Public"
msgstr "Public" msgstr "Public"
@@ -1886,7 +1914,7 @@ msgstr "Inscription désactivée"
msgid "Sign up is currently disabled. Please try again later." msgid "Sign up is currently disabled. Please try again later."
msgstr "L'inscription est actuellement désactivée. Veuillez réessayer plus tard." msgstr "L'inscription est actuellement désactivée. Veuillez réessayer plus tard."
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Sign up with " msgid "Sign up with "
msgstr "S'inscrire avec " msgstr "S'inscrire avec "
@@ -1953,8 +1981,8 @@ msgstr "Forfait d'équipe"
msgid "Teams" msgid "Teams"
msgstr "Équipes" msgstr "Équipes"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/board/index.tsx:396 #: src/views/board/index.tsx:398
msgid "Template" msgid "Template"
msgstr "Modèle" msgstr "Modèle"
@@ -2004,7 +2032,7 @@ msgid "The open source <0/> alternative to Trello"
msgstr "L'alternative open source <0/> à Trello" msgstr "L'alternative open source <0/> à Trello"
#. placeholder {0}: isPublic ? "public" : "private" #. placeholder {0}: isPublic ? "public" : "private"
#: src/views/board/components/VisibilityButton.tsx:46 #: src/views/board/components/VisibilityButton.tsx:47
msgid "The visibility of your board has been set to {0}." msgid "The visibility of your board has been set to {0}."
msgstr "La visibilité de votre tableau a été définie sur {0}." msgstr "La visibilité de votre tableau a été définie sur {0}."
@@ -2028,11 +2056,11 @@ 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:154 #: src/views/public/board/index.tsx:156
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135 #: src/views/board/components/UpdateBoardSlugForm.tsx:136
msgid "This board URL has already been taken" msgid "This board URL has already been taken"
msgstr "Cette URL de tableau est déjà utilisée" msgstr "Cette URL de tableau est déjà utilisée"
@@ -2102,7 +2130,7 @@ msgstr "Impossible d'ajouter l'élément à la liste de contrôle"
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:173 #: src/views/board/components/NewCardForm.tsx:174
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Impossible de créer la carte" msgstr "Impossible de créer la carte"
@@ -2110,7 +2138,7 @@ msgstr "Impossible de créer la carte"
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"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:78
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Impossible de créer une liste" msgstr "Impossible de créer une liste"
@@ -2123,6 +2151,10 @@ 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
msgid "Unable to delete attachment"
msgstr "Impossible de supprimer la pièce jointe"
#: src/views/card/components/DeleteCardConfirmation.tsx:51 #: src/views/card/components/DeleteCardConfirmation.tsx:51
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Impossible de supprimer la carte" msgstr "Impossible de supprimer la carte"
@@ -2147,16 +2179,16 @@ msgstr "Impossible de supprimer le membre"
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Impossible d'envoyer les commentaires" msgstr "Impossible d'envoyer les commentaires"
#: src/views/board/components/UpdateBoardSlugForm.tsx:71 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
msgid "Unable to update board URL" msgid "Unable to update board URL"
msgstr "Impossible de mettre à jour l'URL du tableau" msgstr "Impossible de mettre à jour l'URL du tableau"
#: src/views/board/components/VisibilityButton.tsx:52 #: src/views/board/components/VisibilityButton.tsx:53
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:204 #: src/views/board/index.tsx:206
#: src/views/card/index.tsx:174 #: src/views/card/index.tsx:176
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Impossible de mettre à jour la carte" msgstr "Impossible de mettre à jour la carte"
@@ -2176,7 +2208,7 @@ msgstr "Impossible de mettre à jour le commentaire"
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:148 #: src/views/board/index.tsx:150
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:51
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Impossible de mettre à jour la liste" msgstr "Impossible de mettre à jour la liste"
@@ -2232,7 +2264,7 @@ msgstr "Membres illimités"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Espaces de travail illimités" msgstr "Espaces de travail illimités"
#: src/views/board/components/UpdateBoardSlugForm.tsx:174 #: 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
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83 #: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83
@@ -2271,6 +2303,11 @@ 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:78
msgid "Upload failed"
msgstr "Échec du téléversement"
#: src/views/boards/components/TemplateBoards.tsx:38 #: src/views/boards/components/TemplateBoards.tsx:38
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Urgent" msgid "Urgent"
@@ -2320,7 +2357,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:128 #: src/views/public/board/index.tsx:129
msgid "View only" msgid "View only"
msgstr "Affichage uniquement" msgstr "Affichage uniquement"
@@ -2328,11 +2365,11 @@ 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:157 #: src/views/public/board/index.tsx:159
msgid "View workspace" msgid "View workspace"
msgstr "Voir l'espace de travail" msgstr "Voir l'espace de travail"
#: src/views/board/components/VisibilityButton.tsx:91 #: src/views/board/components/VisibilityButton.tsx:92
msgid "Visibility" msgid "Visibility"
msgstr "Visibilité" msgstr "Visibilité"
@@ -2369,10 +2406,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:361 #: src/views/board/index.tsx:363
#: src/views/boards/index.tsx:22 #: src/views/boards/index.tsx:22
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
#: 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"
@@ -2502,6 +2539,10 @@ 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
msgid "Your file has been uploaded successfully."
msgstr "Votre fichier a été téléversé avec succès."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70 #: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "Votre mot de passe a été modifié." msgstr "Votre mot de passe a été modifié."

File diff suppressed because one or more lines are too long

View File

@@ -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:22 #: src/views/boards/index.tsx:22
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
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:442 #: src/views/board/components/NewCardForm.tsx:443
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:387 #: src/views/board/index.tsx:389
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} non trovato" msgstr "{0} non trovato"
@@ -79,8 +79,8 @@ msgstr "Account"
msgid "Account deleted" msgid "Account deleted"
msgstr "Account eliminato" msgstr "Account eliminato"
#: src/views/card/index.tsx:291 #: src/views/card/index.tsx:308
#: src/views/public/board/CardModal.tsx:143 #: src/views/public/board/CardModal.tsx:157
msgid "Activity" msgid "Activity"
msgstr "Attività" msgstr "Attività"
@@ -109,7 +109,7 @@ msgstr "Aggiungi un elemento..."
msgid "Add checklist" msgid "Add checklist"
msgstr "Aggiungi checklist" msgstr "Aggiungi checklist"
#: src/components/Editor.tsx:442 #: src/components/Editor.tsx:451
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)"
@@ -270,6 +270,10 @@ msgstr "ha assegnato <0>{0}</0> alla scheda"
msgid "Assignees" msgid "Assignees"
msgstr "Assegnatari" msgstr "Assegnatari"
#: src/views/card/components/AttachmentUpload.tsx:25
msgid "Attachment uploaded"
msgstr "Allegato caricato"
#: src/views/boards/components/TemplateBoards.tsx:47 #: src/views/boards/components/TemplateBoards.tsx:47
msgid "Awaiting Customer" msgid "Awaiting Customer"
msgstr "In attesa del cliente" msgstr "In attesa del cliente"
@@ -304,9 +308,9 @@ msgstr "Portale di fatturazione"
msgid "Blog Post" msgid "Blog Post"
msgstr "Post del blog" msgstr "Post del blog"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
msgid "Board" msgid "Board"
msgstr "Bacheca" msgstr "Bacheca"
@@ -323,7 +327,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:151 #: src/views/public/board/index.tsx:153
msgid "Board not found" msgid "Board not found"
msgstr "Bacheca non trovata" msgstr "Bacheca non trovata"
@@ -331,19 +335,19 @@ msgstr "Bacheca non trovata"
msgid "Board sharing & invites" msgid "Board sharing & invites"
msgstr "Condivisione bacheca & inviti" msgstr "Condivisione bacheca & inviti"
#: src/views/board/components/UpdateBoardSlugForm.tsx:45 #: src/views/board/components/UpdateBoardSlugForm.tsx:46
msgid "Board URL can only contain letters, numbers, and hyphens" msgid "Board URL can only contain letters, numbers, and hyphens"
msgstr "L'URL della bacheca può contenere solo lettere, numeri e trattini" msgstr "L'URL della bacheca può contenere solo lettere, numeri e trattini"
#: src/views/board/components/UpdateBoardSlugForm.tsx:43 #: src/views/board/components/UpdateBoardSlugForm.tsx:44
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:67 #: src/views/public/board/index.tsx:68
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:41 #: src/views/board/components/UpdateBoardSlugForm.tsx:42
msgid "Board URL must be at least 3 characters long" msgid "Board URL must be at least 3 characters long"
msgstr "L'URL della bacheca deve contenere almeno 3 caratteri" msgstr "L'URL della bacheca deve contenere almeno 3 caratteri"
@@ -352,7 +356,7 @@ msgstr "L'URL della bacheca deve contenere almeno 3 caratteri"
msgid "Board visibility" msgid "Board visibility"
msgstr "Visibilità bacheca" msgstr "Visibilità bacheca"
#: src/views/board/components/VisibilityButton.tsx:45 #: src/views/board/components/VisibilityButton.tsx:46
msgid "Board visibility updated" msgid "Board visibility updated"
msgstr "Visibilità della bacheca aggiornata" msgstr "Visibilità della bacheca aggiornata"
@@ -387,15 +391,15 @@ msgstr "Segnalazione bug"
msgid "Cancel" msgid "Cancel"
msgstr "Annulla" msgstr "Annulla"
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
msgid "Card" msgid "Card"
msgstr "Carta" msgstr "Carta"
#: src/views/card/index.tsx:262 #: src/views/card/index.tsx:264
msgid "Card not found" msgid "Card not found"
msgstr "Carta non trovata" msgstr "Carta non trovata"
#: src/views/board/components/NewCardForm.tsx:309 #: src/views/board/components/NewCardForm.tsx:310
msgid "Card title" msgid "Card title"
msgstr "Titolo della carta" msgstr "Titolo della carta"
@@ -428,7 +432,7 @@ msgstr "Nome della checklist"
msgid "Checklists" msgid "Checklists"
msgstr "Checklist" msgstr "Checklist"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:180
msgid "Clear filters" msgid "Clear filters"
msgstr "Cancella filtri" msgstr "Cancella filtri"
@@ -519,7 +523,7 @@ msgstr "Contattaci"
msgid "Content Creation" msgid "Content Creation"
msgstr "Creazione contenuti" msgstr "Creazione contenuti"
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Continue with " msgid "Continue with "
msgstr "Continua con " msgstr "Continua con "
@@ -542,8 +546,8 @@ 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:468 #: src/views/board/components/NewCardForm.tsx:469
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Crea un altro" msgstr "Crea un altro"
@@ -551,7 +555,7 @@ 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:478 #: src/views/board/components/NewCardForm.tsx:479
msgid "Create card" msgid "Create card"
msgstr "Crea carta" msgstr "Crea carta"
@@ -567,7 +571,7 @@ msgstr "Crea link di invito"
msgid "Create label" msgid "Create label"
msgstr "Crea etichetta" msgstr "Crea etichetta"
#: src/views/board/components/NewListForm.tsx:152 #: src/views/board/components/NewListForm.tsx:153
msgid "Create list" msgid "Create list"
msgstr "Crea lista" msgstr "Crea lista"
@@ -580,12 +584,12 @@ 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:404 #: src/views/board/components/NewCardForm.tsx:405
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:97
msgid "Create new label" msgid "Create new label"
msgstr "Crea nuova etichetta" msgstr "Crea nuova etichetta"
#: src/views/board/index.tsx:475 #: src/views/board/index.tsx:478
msgid "Create new list" msgid "Create new list"
msgstr "Crea nuova lista" msgstr "Crea nuova lista"
@@ -769,8 +773,12 @@ 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
msgid "Download failed"
msgstr "Download fallito"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:115 #: 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"
@@ -782,7 +790,7 @@ msgstr "Modifica commento"
msgid "Edit label" msgid "Edit label"
msgstr "Modifica etichetta" msgstr "Modifica etichetta"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161 #: src/views/board/components/UpdateBoardSlugForm.tsx:162
msgid "Edit workspace URL" msgid "Edit workspace URL"
msgstr "Modifica URL dell'area di lavoro" msgstr "Modifica URL dell'area di lavoro"
@@ -790,7 +798,7 @@ msgstr "Modifica URL dell'area di lavoro"
msgid "Editing" msgid "Editing"
msgstr "Modifica" msgstr "Modifica"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "email" msgid "email"
msgstr "email" msgstr "email"
@@ -810,11 +818,11 @@ msgstr "Inserisci la tua password attuale"
msgid "Enter your current password and choose a new secure password." msgid "Enter your current password and choose a new secure password."
msgstr "Inserisci la tua password attuale e scegli una nuova password sicura." msgstr "Inserisci la tua password attuale e scegli una nuova password sicura."
#: src/components/AuthForm.tsx:387 #: src/components/AuthForm.tsx:398
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Inserisci il tuo indirizzo email" msgstr "Inserisci il tuo indirizzo email"
#: src/components/AuthForm.tsx:375 #: src/components/AuthForm.tsx:384
msgid "Enter your name" msgid "Enter your name"
msgstr "Inserisci il tuo nome" msgstr "Inserisci il tuo nome"
@@ -822,7 +830,7 @@ msgstr "Inserisci il tuo nome"
msgid "Enter your new password" msgid "Enter your new password"
msgstr "Inserisci la tua nuova password" msgstr "Inserisci la tua nuova password"
#: src/components/AuthForm.tsx:400 #: src/components/AuthForm.tsx:411
msgid "Enter your password" msgid "Enter your password"
msgstr "Inserisci la tua password" msgstr "Inserisci la tua password"
@@ -931,6 +939,11 @@ 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:79
msgid "Failed to upload attachment. Please try again."
msgstr "Impossibile caricare l'allegato. Riprova."
#: src/views/home/components/Header.tsx:41 #: src/views/home/components/Header.tsx:41
msgid "FAQ" msgid "FAQ"
msgstr "FAQ" msgstr "FAQ"
@@ -974,7 +987,7 @@ msgstr "Feedback"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Feedback inviato" msgstr "Feedback inviato"
#: src/views/board/components/Filters.tsx:149 #: src/views/board/components/Filters.tsx:174
msgid "Filter" msgid "Filter"
msgstr "Filtra" msgstr "Filtra"
@@ -987,6 +1000,8 @@ msgid "For long-term sustainability, we recognise all good open source projects
msgstr "Per la sostenibilità a lungo termine, riconosciamo che tutti i buoni progetti open source necessitano di una fonte di entrate. La nostra proviene dall'offerta cloud a pagamento per gli spazi di lavoro con più utenti e per gli slug personalizzati degli spazi di lavoro. Non c'è alcun obbligo di utilizzarla, e puoi ospitare autonomamente il software sulla tua infrastruttura gratuitamente." msgstr "Per la sostenibilità a lungo termine, riconosciamo che tutti i buoni progetti open source necessitano di una fonte di entrate. La nostra proviene dall'offerta cloud a pagamento per gli spazi di lavoro con più utenti e per gli slug personalizzati degli spazi di lavoro. Non c'è alcun obbligo di utilizzarla, e puoi ospitare autonomamente il software sulla tua infrastruttura gratuitamente."
#: src/views/pricing/components/Pricing.tsx:32 #: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/PricingTiers.tsx:30
#: src/views/pricing/components/PricingTiers.tsx:30 #: src/views/pricing/components/PricingTiers.tsx:30
msgid "Free" msgid "Free"
msgstr "Gratuito" msgstr "Gratuito"
@@ -1028,7 +1043,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:467 #: src/views/board/index.tsx:470
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"
@@ -1242,9 +1257,9 @@ msgstr "Kanban reinventato"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Tieni presente che questa azione è irreversibile." msgstr "Tieni presente che questa azione è irreversibile."
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:115
#: src/views/board/components/NewCardForm.tsx:408 #: src/views/board/components/NewCardForm.tsx:409
#: src/views/card/index.tsx:117 #: src/views/card/index.tsx:119
msgid "Labels" msgid "Labels"
msgstr "Etichette" msgstr "Etichette"
@@ -1294,18 +1309,22 @@ msgstr "Licenza"
msgid "Light" msgid "Light"
msgstr "Chiaro" msgstr "Chiaro"
#: src/views/public/board/index.tsx:65 #: src/views/public/board/index.tsx:66
msgid "Link copied" msgid "Link copied"
msgstr "Link copiato" msgstr "Link copiato"
#: src/views/card/index.tsx:109 #: src/views/card/index.tsx:111
msgid "List" msgid "List"
msgstr "Lista" msgstr "Lista"
#: src/views/board/components/NewListForm.tsx:128 #: src/views/board/components/NewListForm.tsx:129
msgid "List name" msgid "List name"
msgstr "Nome lista" msgstr "Nome lista"
#: src/views/board/components/Filters.tsx:123
msgid "Lists"
msgstr "Liste"
#: 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"
@@ -1326,7 +1345,7 @@ msgstr "Amato dai team di tutto il mondo"
msgid "Low Priority" msgid "Low Priority"
msgstr "Bassa priorità" msgstr "Bassa priorità"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "magic link" msgid "magic link"
msgstr "link magico" msgstr "link magico"
@@ -1348,9 +1367,9 @@ msgid "Medium Priority"
msgstr "Media priorità" msgstr "Media priorità"
#: src/components/SideNavigation.tsx:101 #: src/components/SideNavigation.tsx:101
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:107
#: src/views/board/components/NewCardForm.tsx:366 #: src/views/board/components/NewCardForm.tsx:367
#: src/views/card/index.tsx:126 #: src/views/card/index.tsx:128
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Membri" msgstr "Membri"
@@ -1403,7 +1422,7 @@ 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:292 #: src/views/board/components/NewCardForm.tsx:293
msgid "New card" msgid "New card"
msgstr "Nuova carta" msgstr "Nuova carta"
@@ -1419,8 +1438,8 @@ msgstr "Nuova importazione"
msgid "New label" msgid "New label"
msgstr "Nuova etichetta" msgstr "Nuova etichetta"
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:439 #: src/views/board/index.tsx:442
msgid "New list" msgid "New list"
msgstr "Nuova lista" msgstr "Nuova lista"
@@ -1457,6 +1476,10 @@ msgstr "Prossimi passi"
msgid "No {0}" msgid "No {0}"
msgstr "Nessun {0}" msgstr "Nessun {0}"
#: src/components/AuthForm.tsx:365
msgid "No authentication methods are currently available"
msgstr "Nessun metodo di autenticazione è attualmente disponibile"
#: src/views/boards/components/ImportBoardsForm.tsx:242 #: src/views/boards/components/ImportBoardsForm.tsx:242
msgid "No boards found" msgid "No boards found"
msgstr "Nessuna bacheca trovata" msgstr "Nessuna bacheca trovata"
@@ -1465,7 +1488,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/board/index.tsx:464 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "No download URL available for this attachment."
msgstr "Nessun URL di download disponibile per questo allegato."
#: src/views/board/index.tsx:467
msgid "No lists" msgid "No lists"
msgstr "Nessuna lista" msgstr "Nessuna lista"
@@ -1497,7 +1524,7 @@ msgstr "Open source"
msgid "Open Source Friends" msgid "Open Source Friends"
msgstr "Amici Open Source" msgstr "Amici Open Source"
#: src/components/AuthForm.tsx:365 #: src/components/AuthForm.tsx:374
msgid "or" msgid "or"
msgstr "o" msgstr "o"
@@ -1579,15 +1606,15 @@ msgstr "Piattaforma"
msgid "Please confirm your new password" msgid "Please confirm your new password"
msgstr "Conferma la tua nuova password" msgstr "Conferma la tua nuova password"
#: src/components/AuthForm.tsx:391 #: src/components/AuthForm.tsx:402
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Inserisci un indirizzo email valido" msgstr "Inserisci un indirizzo email valido"
#: src/components/AuthForm.tsx:379 #: src/components/AuthForm.tsx:388
msgid "Please enter a valid name" msgid "Please enter a valid name"
msgstr "Inserisci un nome valido" msgstr "Inserisci un nome valido"
#: src/components/AuthForm.tsx:404 #: src/components/AuthForm.tsx:416
msgid "Please enter a valid password" msgid "Please enter a valid password"
msgstr "Inserisci una password valida" msgstr "Inserisci una password valida"
@@ -1598,15 +1625,16 @@ 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:176 #: src/views/board/components/NewCardForm.tsx:177
#: src/views/board/components/NewListForm.tsx:78 #: 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:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:149 #: src/views/board/index.tsx:151
#: src/views/board/index.tsx:205 #: src/views/board/index.tsx:207
#: 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/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:46
@@ -1620,7 +1648,7 @@ msgstr "Seleziona un file da caricare."
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/index.tsx:175 #: src/views/card/index.tsx:177
#: 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
@@ -1664,7 +1692,7 @@ msgstr "Supporto email prioritario"
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Informativa sulla privacy" msgstr "Informativa sulla privacy"
#: src/views/board/components/VisibilityButton.tsx:73 #: src/views/board/components/VisibilityButton.tsx:74
msgid "Private" msgid "Private"
msgstr "Privato" msgstr "Privato"
@@ -1684,7 +1712,7 @@ msgstr "Immagine del profilo aggiornata"
msgid "Profile picture" msgid "Profile picture"
msgstr "Immagine del profilo" msgstr "Immagine del profilo"
#: src/views/board/components/VisibilityButton.tsx:68 #: src/views/board/components/VisibilityButton.tsx:69
msgid "Public" msgid "Public"
msgstr "Pubblico" msgstr "Pubblico"
@@ -1886,7 +1914,7 @@ msgstr "Registrazione disabilitata"
msgid "Sign up is currently disabled. Please try again later." msgid "Sign up is currently disabled. Please try again later."
msgstr "La registrazione è attualmente disabilitata. Riprova più tardi." msgstr "La registrazione è attualmente disabilitata. Riprova più tardi."
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Sign up with " msgid "Sign up with "
msgstr "Registrati con " msgstr "Registrati con "
@@ -1953,8 +1981,8 @@ msgstr "Piano Team"
msgid "Teams" msgid "Teams"
msgstr "Team" msgstr "Team"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/board/index.tsx:396 #: src/views/board/index.tsx:398
msgid "Template" msgid "Template"
msgstr "Template" msgstr "Template"
@@ -2004,7 +2032,7 @@ msgid "The open source <0/> alternative to Trello"
msgstr "L'alternativa open source <0/> a Trello" msgstr "L'alternativa open source <0/> a Trello"
#. placeholder {0}: isPublic ? "public" : "private" #. placeholder {0}: isPublic ? "public" : "private"
#: src/views/board/components/VisibilityButton.tsx:46 #: src/views/board/components/VisibilityButton.tsx:47
msgid "The visibility of your board has been set to {0}." msgid "The visibility of your board has been set to {0}."
msgstr "La visibilità della tua bacheca è stata impostata su {0}." msgstr "La visibilità della tua bacheca è stata impostata su {0}."
@@ -2028,11 +2056,11 @@ 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:154 #: src/views/public/board/index.tsx:156
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135 #: src/views/board/components/UpdateBoardSlugForm.tsx:136
msgid "This board URL has already been taken" msgid "This board URL has already been taken"
msgstr "Questo URL della bacheca è già stato utilizzato" msgstr "Questo URL della bacheca è già stato utilizzato"
@@ -2102,7 +2130,7 @@ msgstr "Impossibile aggiungere l'elemento della checklist"
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:173 #: src/views/board/components/NewCardForm.tsx:174
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Impossibile creare la scheda" msgstr "Impossibile creare la scheda"
@@ -2110,7 +2138,7 @@ msgstr "Impossibile creare la scheda"
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Impossibile creare la checklist" msgstr "Impossibile creare la checklist"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:78
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Impossibile creare la lista" msgstr "Impossibile creare la lista"
@@ -2123,6 +2151,10 @@ 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
msgid "Unable to delete attachment"
msgstr "Impossibile eliminare l'allegato"
#: src/views/card/components/DeleteCardConfirmation.tsx:51 #: src/views/card/components/DeleteCardConfirmation.tsx:51
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Impossibile eliminare la scheda" msgstr "Impossibile eliminare la scheda"
@@ -2147,16 +2179,16 @@ msgstr "Impossibile rimuovere il membro"
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Impossibile inviare feedback" msgstr "Impossibile inviare feedback"
#: src/views/board/components/UpdateBoardSlugForm.tsx:71 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
msgid "Unable to update board URL" msgid "Unable to update board URL"
msgstr "Impossibile aggiornare l'URL della bacheca" msgstr "Impossibile aggiornare l'URL della bacheca"
#: src/views/board/components/VisibilityButton.tsx:52 #: src/views/board/components/VisibilityButton.tsx:53
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:204 #: src/views/board/index.tsx:206
#: src/views/card/index.tsx:174 #: src/views/card/index.tsx:176
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Impossibile aggiornare la scheda" msgstr "Impossibile aggiornare la scheda"
@@ -2176,7 +2208,7 @@ msgstr "Impossibile aggiornare il commento"
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:148 #: src/views/board/index.tsx:150
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:51
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Impossibile aggiornare la lista" msgstr "Impossibile aggiornare la lista"
@@ -2232,7 +2264,7 @@ msgstr "Membri illimitati"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Aree di lavoro illimitate" msgstr "Aree di lavoro illimitate"
#: src/views/board/components/UpdateBoardSlugForm.tsx:174 #: 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
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83 #: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83
@@ -2271,6 +2303,11 @@ 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:78
msgid "Upload failed"
msgstr "Caricamento fallito"
#: src/views/boards/components/TemplateBoards.tsx:38 #: src/views/boards/components/TemplateBoards.tsx:38
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Urgent" msgid "Urgent"
@@ -2320,7 +2357,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:128 #: src/views/public/board/index.tsx:129
msgid "View only" msgid "View only"
msgstr "Solo visualizzazione" msgstr "Solo visualizzazione"
@@ -2328,11 +2365,11 @@ 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:157 #: src/views/public/board/index.tsx:159
msgid "View workspace" msgid "View workspace"
msgstr "Visualizza spazio di lavoro" msgstr "Visualizza spazio di lavoro"
#: src/views/board/components/VisibilityButton.tsx:91 #: src/views/board/components/VisibilityButton.tsx:92
msgid "Visibility" msgid "Visibility"
msgstr "Visibilità" msgstr "Visibilità"
@@ -2369,10 +2406,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:361 #: src/views/board/index.tsx:363
#: src/views/boards/index.tsx:22 #: src/views/boards/index.tsx:22
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
#: 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"
@@ -2502,6 +2539,10 @@ 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
msgid "Your file has been uploaded successfully."
msgstr "Il tuo file è stato caricato con successo."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70 #: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "La tua password è stata modificata." msgstr "La tua password è stata modificata."

File diff suppressed because one or more lines are too long

View File

@@ -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:22 #: src/views/boards/index.tsx:22
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
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:442 #: src/views/board/components/NewCardForm.tsx:443
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:387 #: src/views/board/index.tsx:389
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} niet gevonden" msgstr "{0} niet gevonden"
@@ -79,8 +79,8 @@ msgstr "Account"
msgid "Account deleted" msgid "Account deleted"
msgstr "Account verwijderd" msgstr "Account verwijderd"
#: src/views/card/index.tsx:291 #: src/views/card/index.tsx:308
#: src/views/public/board/CardModal.tsx:143 #: src/views/public/board/CardModal.tsx:157
msgid "Activity" msgid "Activity"
msgstr "Activiteit" msgstr "Activiteit"
@@ -109,7 +109,7 @@ msgstr "Voeg een item toe..."
msgid "Add checklist" msgid "Add checklist"
msgstr "Checklist toevoegen" msgstr "Checklist toevoegen"
#: src/components/Editor.tsx:442 #: src/components/Editor.tsx:451
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)"
@@ -270,6 +270,10 @@ 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
msgid "Attachment uploaded"
msgstr "Bijlage geüpload"
#: src/views/boards/components/TemplateBoards.tsx:47 #: src/views/boards/components/TemplateBoards.tsx:47
msgid "Awaiting Customer" msgid "Awaiting Customer"
msgstr "Wachten op klant" msgstr "Wachten op klant"
@@ -304,9 +308,9 @@ msgstr "Factureringsportaal"
msgid "Blog Post" msgid "Blog Post"
msgstr "Blogbericht" msgstr "Blogbericht"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
msgid "Board" msgid "Board"
msgstr "Bord" msgstr "Bord"
@@ -323,7 +327,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:151 #: src/views/public/board/index.tsx:153
msgid "Board not found" msgid "Board not found"
msgstr "Bord niet gevonden" msgstr "Bord niet gevonden"
@@ -331,19 +335,19 @@ msgstr "Bord niet gevonden"
msgid "Board sharing & invites" msgid "Board sharing & invites"
msgstr "Bord delen & uitnodigingen" msgstr "Bord delen & uitnodigingen"
#: src/views/board/components/UpdateBoardSlugForm.tsx:45 #: src/views/board/components/UpdateBoardSlugForm.tsx:46
msgid "Board URL can only contain letters, numbers, and hyphens" msgid "Board URL can only contain letters, numbers, and hyphens"
msgstr "Board URL kan alleen letters, cijfers en koppeltekens bevatten" msgstr "Board URL kan alleen letters, cijfers en koppeltekens bevatten"
#: src/views/board/components/UpdateBoardSlugForm.tsx:43 #: src/views/board/components/UpdateBoardSlugForm.tsx:44
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:67 #: src/views/public/board/index.tsx:68
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "Board URL gekopieerd naar klembord" msgstr "Board URL gekopieerd naar klembord"
#: src/views/board/components/UpdateBoardSlugForm.tsx:41 #: src/views/board/components/UpdateBoardSlugForm.tsx:42
msgid "Board URL must be at least 3 characters long" msgid "Board URL must be at least 3 characters long"
msgstr "Board URL moet minimaal 3 tekens lang zijn" msgstr "Board URL moet minimaal 3 tekens lang zijn"
@@ -352,7 +356,7 @@ msgstr "Board URL moet minimaal 3 tekens lang zijn"
msgid "Board visibility" msgid "Board visibility"
msgstr "Bordzichtbaarheid" msgstr "Bordzichtbaarheid"
#: src/views/board/components/VisibilityButton.tsx:45 #: src/views/board/components/VisibilityButton.tsx:46
msgid "Board visibility updated" msgid "Board visibility updated"
msgstr "Zichtbaarheid van bord bijgewerkt" msgstr "Zichtbaarheid van bord bijgewerkt"
@@ -387,15 +391,15 @@ msgstr "Bugrapport"
msgid "Cancel" msgid "Cancel"
msgstr "Annuleren" msgstr "Annuleren"
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
msgid "Card" msgid "Card"
msgstr "Kaart" msgstr "Kaart"
#: src/views/card/index.tsx:262 #: src/views/card/index.tsx:264
msgid "Card not found" msgid "Card not found"
msgstr "Kaart niet gevonden" msgstr "Kaart niet gevonden"
#: src/views/board/components/NewCardForm.tsx:309 #: src/views/board/components/NewCardForm.tsx:310
msgid "Card title" msgid "Card title"
msgstr "Kaarttitel" msgstr "Kaarttitel"
@@ -428,7 +432,7 @@ msgstr "Naam checklist"
msgid "Checklists" msgid "Checklists"
msgstr "Checklists" msgstr "Checklists"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:180
msgid "Clear filters" msgid "Clear filters"
msgstr "Filters wissen" msgstr "Filters wissen"
@@ -519,7 +523,7 @@ msgstr "Neem contact op"
msgid "Content Creation" msgid "Content Creation"
msgstr "Content creatie" msgstr "Content creatie"
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Continue with " msgid "Continue with "
msgstr "Doorgaan met " msgstr "Doorgaan met "
@@ -542,8 +546,8 @@ 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:468 #: src/views/board/components/NewCardForm.tsx:469
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Maak nog een" msgstr "Maak nog een"
@@ -551,7 +555,7 @@ 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:478 #: src/views/board/components/NewCardForm.tsx:479
msgid "Create card" msgid "Create card"
msgstr "Maak kaart" msgstr "Maak kaart"
@@ -567,7 +571,7 @@ msgstr "Uitnodigingslink maken"
msgid "Create label" msgid "Create label"
msgstr "Maak label" msgstr "Maak label"
#: src/views/board/components/NewListForm.tsx:152 #: src/views/board/components/NewListForm.tsx:153
msgid "Create list" msgid "Create list"
msgstr "Lijst maken" msgstr "Lijst maken"
@@ -580,12 +584,12 @@ 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:404 #: src/views/board/components/NewCardForm.tsx:405
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:97
msgid "Create new label" msgid "Create new label"
msgstr "Maak nieuw label" msgstr "Maak nieuw label"
#: src/views/board/index.tsx:475 #: src/views/board/index.tsx:478
msgid "Create new list" msgid "Create new list"
msgstr "Maak nieuwe lijst" msgstr "Maak nieuwe lijst"
@@ -769,8 +773,12 @@ 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
msgid "Download failed"
msgstr "Download mislukt"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:115 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Board URL bewerken" msgstr "Board URL bewerken"
@@ -782,7 +790,7 @@ msgstr "Reactie bewerken"
msgid "Edit label" msgid "Edit label"
msgstr "Label bewerken" msgstr "Label bewerken"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161 #: src/views/board/components/UpdateBoardSlugForm.tsx:162
msgid "Edit workspace URL" msgid "Edit workspace URL"
msgstr "Werkruimte-URL bewerken" msgstr "Werkruimte-URL bewerken"
@@ -790,7 +798,7 @@ msgstr "Werkruimte-URL bewerken"
msgid "Editing" msgid "Editing"
msgstr "Bewerken" msgstr "Bewerken"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "email" msgid "email"
msgstr "e-mail" msgstr "e-mail"
@@ -810,11 +818,11 @@ msgstr "Voer je huidige wachtwoord in"
msgid "Enter your current password and choose a new secure password." msgid "Enter your current password and choose a new secure password."
msgstr "Voer je huidige wachtwoord in en kies een nieuw veilig wachtwoord." msgstr "Voer je huidige wachtwoord in en kies een nieuw veilig wachtwoord."
#: src/components/AuthForm.tsx:387 #: src/components/AuthForm.tsx:398
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Voer je e-mailadres in" msgstr "Voer je e-mailadres in"
#: src/components/AuthForm.tsx:375 #: src/components/AuthForm.tsx:384
msgid "Enter your name" msgid "Enter your name"
msgstr "Voer je naam in" msgstr "Voer je naam in"
@@ -822,7 +830,7 @@ msgstr "Voer je naam in"
msgid "Enter your new password" msgid "Enter your new password"
msgstr "Voer je nieuwe wachtwoord in" msgstr "Voer je nieuwe wachtwoord in"
#: src/components/AuthForm.tsx:400 #: src/components/AuthForm.tsx:411
msgid "Enter your password" msgid "Enter your password"
msgstr "Voer je wachtwoord in" msgstr "Voer je wachtwoord in"
@@ -931,6 +939,11 @@ 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:79
msgid "Failed to upload attachment. Please try again."
msgstr "Bijlage uploaden mislukt. Probeer het opnieuw."
#: src/views/home/components/Header.tsx:41 #: src/views/home/components/Header.tsx:41
msgid "FAQ" msgid "FAQ"
msgstr "FAQ" msgstr "FAQ"
@@ -974,7 +987,7 @@ msgstr "Feedback"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Feedback verzonden" msgstr "Feedback verzonden"
#: src/views/board/components/Filters.tsx:149 #: src/views/board/components/Filters.tsx:174
msgid "Filter" msgid "Filter"
msgstr "Filter" msgstr "Filter"
@@ -987,6 +1000,8 @@ msgid "For long-term sustainability, we recognise all good open source projects
msgstr "Voor duurzaamheid op lange termijn erkennen we dat alle goede open source projecten een inkomstenbron nodig hebben. De onze komt van de betaalde cloudoplossing voor werkruimtes met meerdere gebruikers en voor aangepaste werkruimte-slugs. Er is geen verplichting om het te gebruiken, en je kunt de software gratis op je eigen infrastructuur hosten." msgstr "Voor duurzaamheid op lange termijn erkennen we dat alle goede open source projecten een inkomstenbron nodig hebben. De onze komt van de betaalde cloudoplossing voor werkruimtes met meerdere gebruikers en voor aangepaste werkruimte-slugs. Er is geen verplichting om het te gebruiken, en je kunt de software gratis op je eigen infrastructuur hosten."
#: src/views/pricing/components/Pricing.tsx:32 #: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/PricingTiers.tsx:30
#: src/views/pricing/components/PricingTiers.tsx:30 #: src/views/pricing/components/PricingTiers.tsx:30
msgid "Free" msgid "Free"
msgstr "Gratis" msgstr "Gratis"
@@ -1028,7 +1043,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:467 #: src/views/board/index.tsx:470
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"
@@ -1242,9 +1257,9 @@ msgstr "Kanban opnieuw uitgevonden"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Houd er rekening mee dat deze actie onomkeerbaar is." msgstr "Houd er rekening mee dat deze actie onomkeerbaar is."
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:115
#: src/views/board/components/NewCardForm.tsx:408 #: src/views/board/components/NewCardForm.tsx:409
#: src/views/card/index.tsx:117 #: src/views/card/index.tsx:119
msgid "Labels" msgid "Labels"
msgstr "Labels" msgstr "Labels"
@@ -1294,18 +1309,22 @@ msgstr "Licentie"
msgid "Light" msgid "Light"
msgstr "Licht" msgstr "Licht"
#: src/views/public/board/index.tsx:65 #: src/views/public/board/index.tsx:66
msgid "Link copied" msgid "Link copied"
msgstr "Link gekopieerd" msgstr "Link gekopieerd"
#: src/views/card/index.tsx:109 #: src/views/card/index.tsx:111
msgid "List" msgid "List"
msgstr "Lijst" msgstr "Lijst"
#: src/views/board/components/NewListForm.tsx:128 #: src/views/board/components/NewListForm.tsx:129
msgid "List name" msgid "List name"
msgstr "Lijstnaam" msgstr "Lijstnaam"
#: src/views/board/components/Filters.tsx:123
msgid "Lists"
msgstr "Lijsten"
#: 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"
@@ -1326,7 +1345,7 @@ msgstr "Geliefd door teams wereldwijd"
msgid "Low Priority" msgid "Low Priority"
msgstr "Lage prioriteit" msgstr "Lage prioriteit"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "magic link" msgid "magic link"
msgstr "magische link" msgstr "magische link"
@@ -1348,9 +1367,9 @@ msgid "Medium Priority"
msgstr "Gemiddelde prioriteit" msgstr "Gemiddelde prioriteit"
#: src/components/SideNavigation.tsx:101 #: src/components/SideNavigation.tsx:101
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:107
#: src/views/board/components/NewCardForm.tsx:366 #: src/views/board/components/NewCardForm.tsx:367
#: src/views/card/index.tsx:126 #: src/views/card/index.tsx:128
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Leden" msgstr "Leden"
@@ -1403,7 +1422,7 @@ 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:292 #: src/views/board/components/NewCardForm.tsx:293
msgid "New card" msgid "New card"
msgstr "Nieuwe kaart" msgstr "Nieuwe kaart"
@@ -1419,8 +1438,8 @@ msgstr "Nieuwe import"
msgid "New label" msgid "New label"
msgstr "Nieuw label" msgstr "Nieuw label"
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:439 #: src/views/board/index.tsx:442
msgid "New list" msgid "New list"
msgstr "Nieuwe lijst" msgstr "Nieuwe lijst"
@@ -1457,6 +1476,10 @@ msgstr "Volgende stappen"
msgid "No {0}" msgid "No {0}"
msgstr "Geen {0}" msgstr "Geen {0}"
#: src/components/AuthForm.tsx:365
msgid "No authentication methods are currently available"
msgstr "Er zijn momenteel geen authenticatiemethoden beschikbaar"
#: src/views/boards/components/ImportBoardsForm.tsx:242 #: src/views/boards/components/ImportBoardsForm.tsx:242
msgid "No boards found" msgid "No boards found"
msgstr "Geen borden gevonden" msgstr "Geen borden gevonden"
@@ -1465,7 +1488,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/board/index.tsx:464 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "No download URL available for this attachment."
msgstr "Geen download-URL beschikbaar voor deze bijlage."
#: src/views/board/index.tsx:467
msgid "No lists" msgid "No lists"
msgstr "Geen lijsten" msgstr "Geen lijsten"
@@ -1497,7 +1524,7 @@ msgstr "Open source"
msgid "Open Source Friends" msgid "Open Source Friends"
msgstr "Open Source Vrienden" msgstr "Open Source Vrienden"
#: src/components/AuthForm.tsx:365 #: src/components/AuthForm.tsx:374
msgid "or" msgid "or"
msgstr "of" msgstr "of"
@@ -1579,15 +1606,15 @@ msgstr "Platform"
msgid "Please confirm your new password" msgid "Please confirm your new password"
msgstr "Bevestig je nieuwe wachtwoord" msgstr "Bevestig je nieuwe wachtwoord"
#: src/components/AuthForm.tsx:391 #: src/components/AuthForm.tsx:402
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Voer een geldig e-mailadres in" msgstr "Voer een geldig e-mailadres in"
#: src/components/AuthForm.tsx:379 #: src/components/AuthForm.tsx:388
msgid "Please enter a valid name" msgid "Please enter a valid name"
msgstr "Voer een geldige naam in" msgstr "Voer een geldige naam in"
#: src/components/AuthForm.tsx:404 #: src/components/AuthForm.tsx:416
msgid "Please enter a valid password" msgid "Please enter a valid password"
msgstr "Voer een geldig wachtwoord in" msgstr "Voer een geldig wachtwoord in"
@@ -1598,15 +1625,16 @@ 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:176 #: src/views/board/components/NewCardForm.tsx:177
#: src/views/board/components/NewListForm.tsx:78 #: 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:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:149 #: src/views/board/index.tsx:151
#: src/views/board/index.tsx:205 #: src/views/board/index.tsx:207
#: 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/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:46
@@ -1620,7 +1648,7 @@ msgstr "Selecteer een bestand om te uploaden."
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/index.tsx:175 #: src/views/card/index.tsx:177
#: 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
@@ -1664,7 +1692,7 @@ msgstr "Prioriteit e-mailondersteuning"
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Privacybeleid" msgstr "Privacybeleid"
#: src/views/board/components/VisibilityButton.tsx:73 #: src/views/board/components/VisibilityButton.tsx:74
msgid "Private" msgid "Private"
msgstr "Privé" msgstr "Privé"
@@ -1684,7 +1712,7 @@ msgstr "Profielafbeelding bijgewerkt"
msgid "Profile picture" msgid "Profile picture"
msgstr "Profielfoto" msgstr "Profielfoto"
#: src/views/board/components/VisibilityButton.tsx:68 #: src/views/board/components/VisibilityButton.tsx:69
msgid "Public" msgid "Public"
msgstr "Openbaar" msgstr "Openbaar"
@@ -1886,7 +1914,7 @@ msgstr "Registreren uitgeschakeld"
msgid "Sign up is currently disabled. Please try again later." msgid "Sign up is currently disabled. Please try again later."
msgstr "Registreren is momenteel uitgeschakeld. Probeer het later opnieuw." msgstr "Registreren is momenteel uitgeschakeld. Probeer het later opnieuw."
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Sign up with " msgid "Sign up with "
msgstr "Registreren met " msgstr "Registreren met "
@@ -1953,8 +1981,8 @@ msgstr "Teamplan"
msgid "Teams" msgid "Teams"
msgstr "Teams" msgstr "Teams"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/board/index.tsx:396 #: src/views/board/index.tsx:398
msgid "Template" msgid "Template"
msgstr "Sjabloon" msgstr "Sjabloon"
@@ -2004,7 +2032,7 @@ msgid "The open source <0/> alternative to Trello"
msgstr "Het open source <0/> alternatief voor Trello" msgstr "Het open source <0/> alternatief voor Trello"
#. placeholder {0}: isPublic ? "public" : "private" #. placeholder {0}: isPublic ? "public" : "private"
#: src/views/board/components/VisibilityButton.tsx:46 #: src/views/board/components/VisibilityButton.tsx:47
msgid "The visibility of your board has been set to {0}." msgid "The visibility of your board has been set to {0}."
msgstr "De zichtbaarheid van je bord is ingesteld op {0}." msgstr "De zichtbaarheid van je bord is ingesteld op {0}."
@@ -2028,11 +2056,11 @@ 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:154 #: src/views/public/board/index.tsx:156
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135 #: src/views/board/components/UpdateBoardSlugForm.tsx:136
msgid "This board URL has already been taken" msgid "This board URL has already been taken"
msgstr "Deze board URL is al in gebruik" msgstr "Deze board URL is al in gebruik"
@@ -2102,7 +2130,7 @@ msgstr "Kan checklistitem niet toevoegen"
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:173 #: src/views/board/components/NewCardForm.tsx:174
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Kan kaart niet aanmaken" msgstr "Kan kaart niet aanmaken"
@@ -2110,7 +2138,7 @@ msgstr "Kan kaart niet aanmaken"
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Kan checklist niet maken" msgstr "Kan checklist niet maken"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:78
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Kan geen lijst maken" msgstr "Kan geen lijst maken"
@@ -2123,6 +2151,10 @@ 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
msgid "Unable to delete attachment"
msgstr "Kan bijlage niet verwijderen"
#: src/views/card/components/DeleteCardConfirmation.tsx:51 #: src/views/card/components/DeleteCardConfirmation.tsx:51
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Kan kaart niet verwijderen" msgstr "Kan kaart niet verwijderen"
@@ -2147,16 +2179,16 @@ msgstr "Kan lid niet verwijderen"
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Feedback kon niet worden verzonden" msgstr "Feedback kon niet worden verzonden"
#: src/views/board/components/UpdateBoardSlugForm.tsx:71 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
msgid "Unable to update board URL" msgid "Unable to update board URL"
msgstr "Kan board URL niet bijwerken" msgstr "Kan board URL niet bijwerken"
#: src/views/board/components/VisibilityButton.tsx:52 #: src/views/board/components/VisibilityButton.tsx:53
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:204 #: src/views/board/index.tsx:206
#: src/views/card/index.tsx:174 #: src/views/card/index.tsx:176
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Kan kaart niet bijwerken" msgstr "Kan kaart niet bijwerken"
@@ -2176,7 +2208,7 @@ msgstr "Kan reactie niet bijwerken"
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:148 #: src/views/board/index.tsx:150
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:51
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Kan lijst niet bijwerken" msgstr "Kan lijst niet bijwerken"
@@ -2232,7 +2264,7 @@ msgstr "Onbeperkt aantal leden"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Onbeperkte werkruimtes" msgstr "Onbeperkte werkruimtes"
#: src/views/board/components/UpdateBoardSlugForm.tsx:174 #: 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
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83 #: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83
@@ -2271,6 +2303,11 @@ 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:78
msgid "Upload failed"
msgstr "Uploaden mislukt"
#: src/views/boards/components/TemplateBoards.tsx:38 #: src/views/boards/components/TemplateBoards.tsx:38
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Urgent" msgid "Urgent"
@@ -2320,7 +2357,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:128 #: src/views/public/board/index.tsx:129
msgid "View only" msgid "View only"
msgstr "Alleen bekijken" msgstr "Alleen bekijken"
@@ -2328,11 +2365,11 @@ 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:157 #: src/views/public/board/index.tsx:159
msgid "View workspace" msgid "View workspace"
msgstr "Werkruimte bekijken" msgstr "Werkruimte bekijken"
#: src/views/board/components/VisibilityButton.tsx:91 #: src/views/board/components/VisibilityButton.tsx:92
msgid "Visibility" msgid "Visibility"
msgstr "Zichtbaarheid" msgstr "Zichtbaarheid"
@@ -2369,10 +2406,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:361 #: src/views/board/index.tsx:363
#: src/views/boards/index.tsx:22 #: src/views/boards/index.tsx:22
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Werkruimte" msgstr "Werkruimte"
@@ -2502,6 +2539,10 @@ 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
msgid "Your file has been uploaded successfully."
msgstr "Je bestand is succesvol geüpload."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70 #: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "Je wachtwoord is gewijzigd." msgstr "Je wachtwoord is gewijzigd."

File diff suppressed because one or more lines are too long

View File

@@ -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:22 #: src/views/boards/index.tsx:22
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
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:442 #: src/views/board/components/NewCardForm.tsx:443
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:387 #: src/views/board/index.tsx:389
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} nie znaleziono" msgstr "{0} nie znaleziono"
@@ -84,8 +84,8 @@ msgstr "Konto"
msgid "Account deleted" msgid "Account deleted"
msgstr "Konto zostało usunięte" msgstr "Konto zostało usunięte"
#: src/views/card/index.tsx:291 #: src/views/card/index.tsx:308
#: src/views/public/board/CardModal.tsx:143 #: src/views/public/board/CardModal.tsx:157
msgid "Activity" msgid "Activity"
msgstr "Aktywność" msgstr "Aktywność"
@@ -114,7 +114,7 @@ msgstr "Dodaj element..."
msgid "Add checklist" msgid "Add checklist"
msgstr "Dodaj listę kontrolną" msgstr "Dodaj listę kontrolną"
#: src/components/Editor.tsx:442 #: src/components/Editor.tsx:451
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ć)"
@@ -275,6 +275,10 @@ msgstr "przypisano <0>{0}</0> do karty"
msgid "Assignees" msgid "Assignees"
msgstr "Osoby przypisane" msgstr "Osoby przypisane"
#: src/views/card/components/AttachmentUpload.tsx:25
msgid "Attachment uploaded"
msgstr "Załącznik został przesłany"
#: src/views/boards/components/TemplateBoards.tsx:47 #: src/views/boards/components/TemplateBoards.tsx:47
msgid "Awaiting Customer" msgid "Awaiting Customer"
msgstr "Oczekuje na klienta" msgstr "Oczekuje na klienta"
@@ -309,9 +313,9 @@ msgstr "Portal rozliczeniowy"
msgid "Blog Post" msgid "Blog Post"
msgstr "Post na blogu" msgstr "Post na blogu"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
msgid "Board" msgid "Board"
msgstr "Tablica" msgstr "Tablica"
@@ -328,7 +332,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:151 #: src/views/public/board/index.tsx:153
msgid "Board not found" msgid "Board not found"
msgstr "Tablica nie została znaleziona" msgstr "Tablica nie została znaleziona"
@@ -336,19 +340,19 @@ msgstr "Tablica nie została znaleziona"
msgid "Board sharing & invites" msgid "Board sharing & invites"
msgstr "Udostępnianie tablicy i zaproszenia" msgstr "Udostępnianie tablicy i zaproszenia"
#: src/views/board/components/UpdateBoardSlugForm.tsx:45 #: src/views/board/components/UpdateBoardSlugForm.tsx:46
msgid "Board URL can only contain letters, numbers, and hyphens" msgid "Board URL can only contain letters, numbers, and hyphens"
msgstr "Adres URL tablicy może zawierać tylko litery, cyfry i myślniki" msgstr "Adres URL tablicy może zawierać tylko litery, cyfry i myślniki"
#: src/views/board/components/UpdateBoardSlugForm.tsx:43 #: src/views/board/components/UpdateBoardSlugForm.tsx:44
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:67 #: src/views/public/board/index.tsx:68
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:41 #: src/views/board/components/UpdateBoardSlugForm.tsx:42
msgid "Board URL must be at least 3 characters long" msgid "Board URL must be at least 3 characters long"
msgstr "Adres URL tablicy musi mieć co najmniej 3 znaki" msgstr "Adres URL tablicy musi mieć co najmniej 3 znaki"
@@ -357,7 +361,7 @@ msgstr "Adres URL tablicy musi mieć co najmniej 3 znaki"
msgid "Board visibility" msgid "Board visibility"
msgstr "Widoczność tablicy" msgstr "Widoczność tablicy"
#: src/views/board/components/VisibilityButton.tsx:45 #: src/views/board/components/VisibilityButton.tsx:46
msgid "Board visibility updated" msgid "Board visibility updated"
msgstr "Widoczność tablicy została zaktualizowana" msgstr "Widoczność tablicy została zaktualizowana"
@@ -392,15 +396,15 @@ msgstr "Zgłoszenie błędu"
msgid "Cancel" msgid "Cancel"
msgstr "Anuluj" msgstr "Anuluj"
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
msgid "Card" msgid "Card"
msgstr "Karta" msgstr "Karta"
#: src/views/card/index.tsx:262 #: src/views/card/index.tsx:264
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:309 #: src/views/board/components/NewCardForm.tsx:310
msgid "Card title" msgid "Card title"
msgstr "Tytuł karty" msgstr "Tytuł karty"
@@ -433,7 +437,7 @@ msgstr "Nazwa listy kontrolnej"
msgid "Checklists" msgid "Checklists"
msgstr "Listy kontrolne" msgstr "Listy kontrolne"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:180
msgid "Clear filters" msgid "Clear filters"
msgstr "Wyczyść filtry" msgstr "Wyczyść filtry"
@@ -524,7 +528,7 @@ msgstr "Skontaktuj się z nami"
msgid "Content Creation" msgid "Content Creation"
msgstr "Tworzenie treści" msgstr "Tworzenie treści"
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Continue with " msgid "Continue with "
msgstr "Kontynuuj z " msgstr "Kontynuuj z "
@@ -547,8 +551,8 @@ 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:468 #: src/views/board/components/NewCardForm.tsx:469
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Utwórz kolejny" msgstr "Utwórz kolejny"
@@ -556,7 +560,7 @@ 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:478 #: src/views/board/components/NewCardForm.tsx:479
msgid "Create card" msgid "Create card"
msgstr "Utwórz kartę" msgstr "Utwórz kartę"
@@ -572,7 +576,7 @@ msgstr "Utwórz link zaproszenia"
msgid "Create label" msgid "Create label"
msgstr "Utwórz etykietę" msgstr "Utwórz etykietę"
#: src/views/board/components/NewListForm.tsx:152 #: src/views/board/components/NewListForm.tsx:153
msgid "Create list" msgid "Create list"
msgstr "Utwórz listę" msgstr "Utwórz listę"
@@ -585,12 +589,12 @@ 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:404 #: src/views/board/components/NewCardForm.tsx:405
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:97
msgid "Create new label" msgid "Create new label"
msgstr "Utwórz nową etykietę" msgstr "Utwórz nową etykietę"
#: src/views/board/index.tsx:475 #: src/views/board/index.tsx:478
msgid "Create new list" msgid "Create new list"
msgstr "Utwórz nową listę" msgstr "Utwórz nową listę"
@@ -774,8 +778,12 @@ 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
msgid "Download failed"
msgstr "Pobieranie nie powiodło się"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:115 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Edytuj URL tablicy" msgstr "Edytuj URL tablicy"
@@ -787,7 +795,7 @@ msgstr "Edytuj komentarz"
msgid "Edit label" msgid "Edit label"
msgstr "Edytuj etykietę" msgstr "Edytuj etykietę"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161 #: src/views/board/components/UpdateBoardSlugForm.tsx:162
msgid "Edit workspace URL" msgid "Edit workspace URL"
msgstr "Edytuj URL przestrzeni roboczej" msgstr "Edytuj URL przestrzeni roboczej"
@@ -795,7 +803,7 @@ msgstr "Edytuj URL przestrzeni roboczej"
msgid "Editing" msgid "Editing"
msgstr "Edycja" msgstr "Edycja"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "email" msgid "email"
msgstr "email" msgstr "email"
@@ -815,11 +823,11 @@ msgstr "Wprowadź swoje obecne hasło"
msgid "Enter your current password and choose a new secure password." msgid "Enter your current password and choose a new secure password."
msgstr "Wprowadź swoje obecne hasło i wybierz nowe, bezpieczne hasło." msgstr "Wprowadź swoje obecne hasło i wybierz nowe, bezpieczne hasło."
#: src/components/AuthForm.tsx:387 #: src/components/AuthForm.tsx:398
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Wprowadź swój adres e-mail" msgstr "Wprowadź swój adres e-mail"
#: src/components/AuthForm.tsx:375 #: src/components/AuthForm.tsx:384
msgid "Enter your name" msgid "Enter your name"
msgstr "Wprowadź swoje imię" msgstr "Wprowadź swoje imię"
@@ -827,7 +835,7 @@ msgstr "Wprowadź swoje imię"
msgid "Enter your new password" msgid "Enter your new password"
msgstr "Wprowadź swoje nowe hasło" msgstr "Wprowadź swoje nowe hasło"
#: src/components/AuthForm.tsx:400 #: src/components/AuthForm.tsx:411
msgid "Enter your password" msgid "Enter your password"
msgstr "Wprowadź swoje hasło" msgstr "Wprowadź swoje hasło"
@@ -936,6 +944,11 @@ 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:79
msgid "Failed to upload attachment. Please try again."
msgstr "Nie udało się przesłać załącznika. Proszę spróbować ponownie."
#: src/views/home/components/Header.tsx:41 #: src/views/home/components/Header.tsx:41
msgid "FAQ" msgid "FAQ"
msgstr "FAQ" msgstr "FAQ"
@@ -979,7 +992,7 @@ msgstr "Opinie"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Opinia wysłana" msgstr "Opinia wysłana"
#: src/views/board/components/Filters.tsx:149 #: src/views/board/components/Filters.tsx:174
msgid "Filter" msgid "Filter"
msgstr "Filtr" msgstr "Filtr"
@@ -992,6 +1005,8 @@ msgid "For long-term sustainability, we recognise all good open source projects
msgstr "Dla długoterminowej trwałości uznajemy, że wszystkie dobre projekty open source potrzebują źródła dochodu. Nasze pochodzi z płatnej oferty w chmurze dla przestrzeni roboczych z wieloma użytkownikami oraz dla niestandardowych nazw przestrzeni roboczych. Nie ma obowiązku korzystania z niej, a oprogramowanie można hostować samodzielnie na własnej infrastrukturze bezpłatnie." msgstr "Dla długoterminowej trwałości uznajemy, że wszystkie dobre projekty open source potrzebują źródła dochodu. Nasze pochodzi z płatnej oferty w chmurze dla przestrzeni roboczych z wieloma użytkownikami oraz dla niestandardowych nazw przestrzeni roboczych. Nie ma obowiązku korzystania z niej, a oprogramowanie można hostować samodzielnie na własnej infrastrukturze bezpłatnie."
#: src/views/pricing/components/Pricing.tsx:32 #: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/PricingTiers.tsx:30
#: src/views/pricing/components/PricingTiers.tsx:30 #: src/views/pricing/components/PricingTiers.tsx:30
msgid "Free" msgid "Free"
msgstr "Darmowy" msgstr "Darmowy"
@@ -1033,7 +1048,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:467 #: src/views/board/index.tsx:470
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ę"
@@ -1247,9 +1262,9 @@ msgstr "Kanban wymyślony na nowo"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Pamiętaj, że ta akcja jest nieodwracalna." msgstr "Pamiętaj, że ta akcja jest nieodwracalna."
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:115
#: src/views/board/components/NewCardForm.tsx:408 #: src/views/board/components/NewCardForm.tsx:409
#: src/views/card/index.tsx:117 #: src/views/card/index.tsx:119
msgid "Labels" msgid "Labels"
msgstr "Etykiety" msgstr "Etykiety"
@@ -1299,18 +1314,22 @@ msgstr "Licencja"
msgid "Light" msgid "Light"
msgstr "Jasny" msgstr "Jasny"
#: src/views/public/board/index.tsx:65 #: src/views/public/board/index.tsx:66
msgid "Link copied" msgid "Link copied"
msgstr "Link skopiowany" msgstr "Link skopiowany"
#: src/views/card/index.tsx:109 #: src/views/card/index.tsx:111
msgid "List" msgid "List"
msgstr "Lista" msgstr "Lista"
#: src/views/board/components/NewListForm.tsx:128 #: src/views/board/components/NewListForm.tsx:129
msgid "List name" msgid "List name"
msgstr "Nazwa listy" msgstr "Nazwa listy"
#: src/views/board/components/Filters.tsx:123
msgid "Lists"
msgstr "Listy"
#: 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"
@@ -1331,7 +1350,7 @@ msgstr "Uwielbiane przez zespoły na całym świecie"
msgid "Low Priority" msgid "Low Priority"
msgstr "Niski priorytet" msgstr "Niski priorytet"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "magic link" msgid "magic link"
msgstr "magiczny link" msgstr "magiczny link"
@@ -1353,9 +1372,9 @@ msgid "Medium Priority"
msgstr "Średni priorytet" msgstr "Średni priorytet"
#: src/components/SideNavigation.tsx:101 #: src/components/SideNavigation.tsx:101
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:107
#: src/views/board/components/NewCardForm.tsx:366 #: src/views/board/components/NewCardForm.tsx:367
#: src/views/card/index.tsx:126 #: src/views/card/index.tsx:128
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Członkowie" msgstr "Członkowie"
@@ -1408,7 +1427,7 @@ 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:292 #: src/views/board/components/NewCardForm.tsx:293
msgid "New card" msgid "New card"
msgstr "Nowa karta" msgstr "Nowa karta"
@@ -1424,8 +1443,8 @@ msgstr "Nowy import"
msgid "New label" msgid "New label"
msgstr "Nowa etykieta" msgstr "Nowa etykieta"
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:439 #: src/views/board/index.tsx:442
msgid "New list" msgid "New list"
msgstr "Nowa lista" msgstr "Nowa lista"
@@ -1462,6 +1481,10 @@ msgstr "Następne kroki"
msgid "No {0}" msgid "No {0}"
msgstr "Brak {0}" msgstr "Brak {0}"
#: src/components/AuthForm.tsx:365
msgid "No authentication methods are currently available"
msgstr "Obecnie brak dostępnych metod uwierzytelniania"
#: src/views/boards/components/ImportBoardsForm.tsx:242 #: src/views/boards/components/ImportBoardsForm.tsx:242
msgid "No boards found" msgid "No boards found"
msgstr "Nie znaleziono tablic" msgstr "Nie znaleziono tablic"
@@ -1470,7 +1493,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/board/index.tsx:464 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "No download URL available for this attachment."
msgstr "Brak dostępnego URL do pobrania tego załącznika."
#: src/views/board/index.tsx:467
msgid "No lists" msgid "No lists"
msgstr "Brak list" msgstr "Brak list"
@@ -1502,7 +1529,7 @@ msgstr "Otwartoźródłowe"
msgid "Open Source Friends" msgid "Open Source Friends"
msgstr "Przyjaciele Open Source" msgstr "Przyjaciele Open Source"
#: src/components/AuthForm.tsx:365 #: src/components/AuthForm.tsx:374
msgid "or" msgid "or"
msgstr "lub" msgstr "lub"
@@ -1584,15 +1611,15 @@ msgstr "Platforma"
msgid "Please confirm your new password" msgid "Please confirm your new password"
msgstr "Proszę potwierdzić nowe hasło" msgstr "Proszę potwierdzić nowe hasło"
#: src/components/AuthForm.tsx:391 #: src/components/AuthForm.tsx:402
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Proszę wprowadzić prawidłowy adres e-mail" msgstr "Proszę wprowadzić prawidłowy adres e-mail"
#: src/components/AuthForm.tsx:379 #: src/components/AuthForm.tsx:388
msgid "Please enter a valid name" msgid "Please enter a valid name"
msgstr "Proszę wprowadzić poprawne imię" msgstr "Proszę wprowadzić poprawne imię"
#: src/components/AuthForm.tsx:404 #: src/components/AuthForm.tsx:416
msgid "Please enter a valid password" msgid "Please enter a valid password"
msgstr "Proszę wprowadzić poprawne hasło" msgstr "Proszę wprowadzić poprawne hasło"
@@ -1603,15 +1630,16 @@ 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:176 #: src/views/board/components/NewCardForm.tsx:177
#: src/views/board/components/NewListForm.tsx:78 #: 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:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:149 #: src/views/board/index.tsx:151
#: src/views/board/index.tsx:205 #: src/views/board/index.tsx:207
#: 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/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:46
@@ -1625,7 +1653,7 @@ msgstr "Proszę wybrać plik do przesłania."
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/index.tsx:175 #: src/views/card/index.tsx:177
#: 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
@@ -1669,7 +1697,7 @@ msgstr "Priorytetowe wsparcie e-mail"
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Polityka prywatności" msgstr "Polityka prywatności"
#: src/views/board/components/VisibilityButton.tsx:73 #: src/views/board/components/VisibilityButton.tsx:74
msgid "Private" msgid "Private"
msgstr "Prywatne" msgstr "Prywatne"
@@ -1689,7 +1717,7 @@ msgstr "Zaktualizowano zdjęcie profilowe"
msgid "Profile picture" msgid "Profile picture"
msgstr "Zdjęcie profilowe" msgstr "Zdjęcie profilowe"
#: src/views/board/components/VisibilityButton.tsx:68 #: src/views/board/components/VisibilityButton.tsx:69
msgid "Public" msgid "Public"
msgstr "Publiczne" msgstr "Publiczne"
@@ -1891,7 +1919,7 @@ msgstr "Rejestracja wyłączona"
msgid "Sign up is currently disabled. Please try again later." msgid "Sign up is currently disabled. Please try again later."
msgstr "Rejestracja jest obecnie wyłączona. Spróbuj ponownie później." msgstr "Rejestracja jest obecnie wyłączona. Spróbuj ponownie później."
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Sign up with " msgid "Sign up with "
msgstr "Zarejestruj się za pomocą " msgstr "Zarejestruj się za pomocą "
@@ -1958,8 +1986,8 @@ msgstr "Plan zespołowy"
msgid "Teams" msgid "Teams"
msgstr "Zespoły" msgstr "Zespoły"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/board/index.tsx:396 #: src/views/board/index.tsx:398
msgid "Template" msgid "Template"
msgstr "Szablon" msgstr "Szablon"
@@ -2009,7 +2037,7 @@ msgid "The open source <0/> alternative to Trello"
msgstr "Otwarta alternatywa <0/> dla Trello" msgstr "Otwarta alternatywa <0/> dla Trello"
#. placeholder {0}: isPublic ? "public" : "private" #. placeholder {0}: isPublic ? "public" : "private"
#: src/views/board/components/VisibilityButton.tsx:46 #: src/views/board/components/VisibilityButton.tsx:47
msgid "The visibility of your board has been set to {0}." msgid "The visibility of your board has been set to {0}."
msgstr "Widoczność Twojej tablicy została ustawiona na {0}." msgstr "Widoczność Twojej tablicy została ustawiona na {0}."
@@ -2033,11 +2061,11 @@ 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:154 #: src/views/public/board/index.tsx:156
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"
#: src/views/board/components/UpdateBoardSlugForm.tsx:135 #: src/views/board/components/UpdateBoardSlugForm.tsx:136
msgid "This board URL has already been taken" msgid "This board URL has already been taken"
msgstr "Ten adres URL tablicy jest już zajęty" msgstr "Ten adres URL tablicy jest już zajęty"
@@ -2107,7 +2135,7 @@ msgstr "Nie można dodać elementu listy kontrolnej"
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:173 #: src/views/board/components/NewCardForm.tsx:174
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Nie można utworzyć karty" msgstr "Nie można utworzyć karty"
@@ -2115,7 +2143,7 @@ msgstr "Nie można utworzyć karty"
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Nie można utworzyć listy kontrolnej" msgstr "Nie można utworzyć listy kontrolnej"
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:78
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Nie można utworzyć listy" msgstr "Nie można utworzyć listy"
@@ -2128,6 +2156,10 @@ 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
msgid "Unable to delete attachment"
msgstr "Nie można usunąć załącznika"
#: src/views/card/components/DeleteCardConfirmation.tsx:51 #: src/views/card/components/DeleteCardConfirmation.tsx:51
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Nie można usunąć karty" msgstr "Nie można usunąć karty"
@@ -2152,16 +2184,16 @@ msgstr "Nie można usunąć członka"
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Nie można wysłać opinii" msgstr "Nie można wysłać opinii"
#: src/views/board/components/UpdateBoardSlugForm.tsx:71 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
msgid "Unable to update board URL" msgid "Unable to update board URL"
msgstr "Nie można zaktualizować adresu URL tablicy" msgstr "Nie można zaktualizować adresu URL tablicy"
#: src/views/board/components/VisibilityButton.tsx:52 #: src/views/board/components/VisibilityButton.tsx:53
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:204 #: src/views/board/index.tsx:206
#: src/views/card/index.tsx:174 #: src/views/card/index.tsx:176
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Nie można zaktualizować karty" msgstr "Nie można zaktualizować karty"
@@ -2181,7 +2213,7 @@ msgstr "Nie można zaktualizować komentarza"
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:148 #: src/views/board/index.tsx:150
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:51
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Nie można zaktualizować listy" msgstr "Nie można zaktualizować listy"
@@ -2237,7 +2269,7 @@ msgstr "Nieograniczona liczba członków"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Nieograniczona liczba przestrzeni roboczych" msgstr "Nieograniczona liczba przestrzeni roboczych"
#: src/views/board/components/UpdateBoardSlugForm.tsx:174 #: 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
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83 #: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83
@@ -2276,6 +2308,11 @@ 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:78
msgid "Upload failed"
msgstr "Przesyłanie nie powiodło się"
#: src/views/boards/components/TemplateBoards.tsx:38 #: src/views/boards/components/TemplateBoards.tsx:38
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Urgent" msgid "Urgent"
@@ -2325,7 +2362,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:128 #: src/views/public/board/index.tsx:129
msgid "View only" msgid "View only"
msgstr "Tylko podgląd" msgstr "Tylko podgląd"
@@ -2333,11 +2370,11 @@ 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:157 #: src/views/public/board/index.tsx:159
msgid "View workspace" msgid "View workspace"
msgstr "Zobacz obszar roboczy" msgstr "Zobacz obszar roboczy"
#: src/views/board/components/VisibilityButton.tsx:91 #: src/views/board/components/VisibilityButton.tsx:92
msgid "Visibility" msgid "Visibility"
msgstr "Widoczność" msgstr "Widoczność"
@@ -2374,10 +2411,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:361 #: src/views/board/index.tsx:363
#: src/views/boards/index.tsx:22 #: src/views/boards/index.tsx:22
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Obszar roboczy" msgstr "Obszar roboczy"
@@ -2507,6 +2544,10 @@ 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
msgid "Your file has been uploaded successfully."
msgstr "Twój plik został pomyślnie przesłany."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70 #: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "Twoje hasło zostało zmienione." msgstr "Twoje hasło zostało zmienione."

File diff suppressed because one or more lines are too long

View File

@@ -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:22 #: src/views/boards/index.tsx:22
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
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:442 #: src/views/board/components/NewCardForm.tsx:443
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:387 #: src/views/board/index.tsx:389
msgid "{0} not found" msgid "{0} not found"
msgstr "{0} не найден" msgstr "{0} не найден"
@@ -79,8 +79,8 @@ msgstr "Аккаунт"
msgid "Account deleted" msgid "Account deleted"
msgstr "Аккаунт удалён" msgstr "Аккаунт удалён"
#: src/views/card/index.tsx:291 #: src/views/card/index.tsx:308
#: src/views/public/board/CardModal.tsx:143 #: src/views/public/board/CardModal.tsx:157
msgid "Activity" msgid "Activity"
msgstr "Активность" msgstr "Активность"
@@ -109,7 +109,7 @@ msgstr "Добавить элемент..."
msgid "Add checklist" msgid "Add checklist"
msgstr "Добавить чек-лист" msgstr "Добавить чек-лист"
#: src/components/Editor.tsx:442 #: src/components/Editor.tsx:451
msgid "Add description... (type '/' to open commands or '@' to mention)" msgid "Add description... (type '/' to open commands or '@' to mention)"
msgstr "Добавить описание... (введите '/' для открытия команд или '@' для упоминания)" msgstr "Добавить описание... (введите '/' для открытия команд или '@' для упоминания)"
@@ -270,6 +270,10 @@ msgstr "назначено <0>{0}</0> к карточке"
msgid "Assignees" msgid "Assignees"
msgstr "Исполнители" msgstr "Исполнители"
#: src/views/card/components/AttachmentUpload.tsx:25
msgid "Attachment uploaded"
msgstr "Вложение загружено"
#: src/views/boards/components/TemplateBoards.tsx:47 #: src/views/boards/components/TemplateBoards.tsx:47
msgid "Awaiting Customer" msgid "Awaiting Customer"
msgstr "Ожидание клиента" msgstr "Ожидание клиента"
@@ -304,9 +308,9 @@ msgstr "Портал выставления счетов"
msgid "Blog Post" msgid "Blog Post"
msgstr "Пост в блоге" msgstr "Пост в блоге"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
msgid "Board" msgid "Board"
msgstr "Доска" msgstr "Доска"
@@ -323,7 +327,7 @@ msgstr "Название доски не может превышать 100 си
msgid "Board name is required" msgid "Board name is required"
msgstr "Название доски обязательно" msgstr "Название доски обязательно"
#: src/views/public/board/index.tsx:151 #: src/views/public/board/index.tsx:153
msgid "Board not found" msgid "Board not found"
msgstr "Доска не найдена" msgstr "Доска не найдена"
@@ -331,19 +335,19 @@ msgstr "Доска не найдена"
msgid "Board sharing & invites" msgid "Board sharing & invites"
msgstr "Общий доступ к доске и приглашения" msgstr "Общий доступ к доске и приглашения"
#: src/views/board/components/UpdateBoardSlugForm.tsx:45 #: src/views/board/components/UpdateBoardSlugForm.tsx:46
msgid "Board URL can only contain letters, numbers, and hyphens" msgid "Board URL can only contain letters, numbers, and hyphens"
msgstr "URL доски может содержать только буквы, цифры и дефисы" msgstr "URL доски может содержать только буквы, цифры и дефисы"
#: src/views/board/components/UpdateBoardSlugForm.tsx:43 #: src/views/board/components/UpdateBoardSlugForm.tsx:44
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:67 #: src/views/public/board/index.tsx:68
msgid "Board URL copied to clipboard" msgid "Board URL copied to clipboard"
msgstr "URL доски скопирован в буфер обмена" msgstr "URL доски скопирован в буфер обмена"
#: src/views/board/components/UpdateBoardSlugForm.tsx:41 #: src/views/board/components/UpdateBoardSlugForm.tsx:42
msgid "Board URL must be at least 3 characters long" msgid "Board URL must be at least 3 characters long"
msgstr "URL доски должен содержать не менее 3 символов" msgstr "URL доски должен содержать не менее 3 символов"
@@ -352,7 +356,7 @@ msgstr "URL доски должен содержать не менее 3 сим
msgid "Board visibility" msgid "Board visibility"
msgstr "Видимость доски" msgstr "Видимость доски"
#: src/views/board/components/VisibilityButton.tsx:45 #: src/views/board/components/VisibilityButton.tsx:46
msgid "Board visibility updated" msgid "Board visibility updated"
msgstr "Видимость доски обновлена" msgstr "Видимость доски обновлена"
@@ -387,15 +391,15 @@ msgstr "Отчет об ошибке"
msgid "Cancel" msgid "Cancel"
msgstr "Отмена" msgstr "Отмена"
#: src/views/card/index.tsx:216 #: src/views/card/index.tsx:218
msgid "Card" msgid "Card"
msgstr "Карточка" msgstr "Карточка"
#: src/views/card/index.tsx:262 #: src/views/card/index.tsx:264
msgid "Card not found" msgid "Card not found"
msgstr "Карточка не найдена" msgstr "Карточка не найдена"
#: src/views/board/components/NewCardForm.tsx:309 #: src/views/board/components/NewCardForm.tsx:310
msgid "Card title" msgid "Card title"
msgstr "Название карточки" msgstr "Название карточки"
@@ -428,7 +432,7 @@ msgstr "Название контрольного списка"
msgid "Checklists" msgid "Checklists"
msgstr "Контрольные списки" msgstr "Контрольные списки"
#: src/views/board/components/Filters.tsx:155 #: src/views/board/components/Filters.tsx:180
msgid "Clear filters" msgid "Clear filters"
msgstr "Очистить фильтры" msgstr "Очистить фильтры"
@@ -519,7 +523,7 @@ msgstr "Свяжитесь с нами"
msgid "Content Creation" msgid "Content Creation"
msgstr "Создание контента" msgstr "Создание контента"
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Continue with " msgid "Continue with "
msgstr "Продолжить с " msgstr "Продолжить с "
@@ -542,8 +546,8 @@ msgid "Create {0}"
msgstr "Создать {0}" msgstr "Создать {0}"
#: src/components/LabelForm.tsx:213 #: src/components/LabelForm.tsx:213
#: src/views/board/components/NewCardForm.tsx:468 #: src/views/board/components/NewCardForm.tsx:469
#: src/views/board/components/NewListForm.tsx:140 #: src/views/board/components/NewListForm.tsx:141
msgid "Create another" msgid "Create another"
msgstr "Создать ещё одну" msgstr "Создать ещё одну"
@@ -551,7 +555,7 @@ msgstr "Создать ещё одну"
msgid "Create API key" msgid "Create API key"
msgstr "Создать API-ключ" msgstr "Создать API-ключ"
#: src/views/board/components/NewCardForm.tsx:478 #: src/views/board/components/NewCardForm.tsx:479
msgid "Create card" msgid "Create card"
msgstr "Создать карточку" msgstr "Создать карточку"
@@ -567,7 +571,7 @@ msgstr "Создать ссылку-приглашение"
msgid "Create label" msgid "Create label"
msgstr "Создать метку" msgstr "Создать метку"
#: src/views/board/components/NewListForm.tsx:152 #: src/views/board/components/NewListForm.tsx:153
msgid "Create list" msgid "Create list"
msgstr "Создать список" msgstr "Создать список"
@@ -580,12 +584,12 @@ msgstr "Создать новый {0}"
msgid "Create new key" msgid "Create new key"
msgstr "Создать новый ключ" msgstr "Создать новый ключ"
#: src/views/board/components/NewCardForm.tsx:404 #: src/views/board/components/NewCardForm.tsx:405
#: src/views/card/components/LabelSelector.tsx:97 #: src/views/card/components/LabelSelector.tsx:97
msgid "Create new label" msgid "Create new label"
msgstr "Создать новую метку" msgstr "Создать новую метку"
#: src/views/board/index.tsx:475 #: src/views/board/index.tsx:478
msgid "Create new list" msgid "Create new list"
msgstr "Создать новый список" msgstr "Создать новый список"
@@ -769,8 +773,12 @@ msgstr "Нет аккаунта? <0><1>Зарегистрируйтесь</1></0
msgid "Done" msgid "Done"
msgstr "Готово" msgstr "Готово"
#: src/views/card/components/AttachmentThumbnails.tsx:141
msgid "Download failed"
msgstr "Не удалось загрузить"
#: src/views/board/components/BoardDropdown.tsx:41 #: src/views/board/components/BoardDropdown.tsx:41
#: src/views/board/components/UpdateBoardSlugForm.tsx:115 #: src/views/board/components/UpdateBoardSlugForm.tsx:116
msgid "Edit board URL" msgid "Edit board URL"
msgstr "Изменить URL доски" msgstr "Изменить URL доски"
@@ -782,7 +790,7 @@ msgstr "Редактировать комментарий"
msgid "Edit label" msgid "Edit label"
msgstr "Редактировать метку" msgstr "Редактировать метку"
#: src/views/board/components/UpdateBoardSlugForm.tsx:161 #: src/views/board/components/UpdateBoardSlugForm.tsx:162
msgid "Edit workspace URL" msgid "Edit workspace URL"
msgstr "Редактировать URL рабочей области" msgstr "Редактировать URL рабочей области"
@@ -790,7 +798,7 @@ msgstr "Редактировать URL рабочей области"
msgid "Editing" msgid "Editing"
msgstr "Редактирование" msgstr "Редактирование"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "email" msgid "email"
msgstr "email" msgstr "email"
@@ -810,11 +818,11 @@ msgstr "Введите ваш текущий пароль"
msgid "Enter your current password and choose a new secure password." msgid "Enter your current password and choose a new secure password."
msgstr "Введите ваш текущий пароль и выберите новый безопасный пароль." msgstr "Введите ваш текущий пароль и выберите новый безопасный пароль."
#: src/components/AuthForm.tsx:387 #: src/components/AuthForm.tsx:398
msgid "Enter your email address" msgid "Enter your email address"
msgstr "Введите ваш адрес электронной почты" msgstr "Введите ваш адрес электронной почты"
#: src/components/AuthForm.tsx:375 #: src/components/AuthForm.tsx:384
msgid "Enter your name" msgid "Enter your name"
msgstr "Введите ваше имя" msgstr "Введите ваше имя"
@@ -822,7 +830,7 @@ msgstr "Введите ваше имя"
msgid "Enter your new password" msgid "Enter your new password"
msgstr "Введите ваш новый пароль" msgstr "Введите ваш новый пароль"
#: src/components/AuthForm.tsx:400 #: src/components/AuthForm.tsx:411
msgid "Enter your password" msgid "Enter your password"
msgstr "Введите ваш пароль" msgstr "Введите ваш пароль"
@@ -931,6 +939,11 @@ 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:79
msgid "Failed to upload attachment. Please try again."
msgstr "Не удалось загрузить вложение. Пожалуйста, попробуйте еще раз."
#: src/views/home/components/Header.tsx:41 #: src/views/home/components/Header.tsx:41
msgid "FAQ" msgid "FAQ"
msgstr "FAQ" msgstr "FAQ"
@@ -974,7 +987,7 @@ msgstr "Обратная связь"
msgid "Feedback sent" msgid "Feedback sent"
msgstr "Обратная связь отправлена" msgstr "Обратная связь отправлена"
#: src/views/board/components/Filters.tsx:149 #: src/views/board/components/Filters.tsx:174
msgid "Filter" msgid "Filter"
msgstr "Фильтр" msgstr "Фильтр"
@@ -987,6 +1000,8 @@ msgid "For long-term sustainability, we recognise all good open source projects
msgstr "Для долгосрочной устойчивости мы признаем, что всем хорошим проектам с открытым исходным кодом необходим источник дохода. Наш доход поступает от платного облачного предложения для рабочих пространств с несколькими пользователями и для пользовательских идентификаторов рабочих пространств. Нет обязательства использовать его, и вы можете самостоятельно разместить программное обеспечение на своей инфраструктуре бесплатно." msgstr "Для долгосрочной устойчивости мы признаем, что всем хорошим проектам с открытым исходным кодом необходим источник дохода. Наш доход поступает от платного облачного предложения для рабочих пространств с несколькими пользователями и для пользовательских идентификаторов рабочих пространств. Нет обязательства использовать его, и вы можете самостоятельно разместить программное обеспечение на своей инфраструктуре бесплатно."
#: src/views/pricing/components/Pricing.tsx:32 #: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/Pricing.tsx:32
#: src/views/pricing/components/PricingTiers.tsx:30
#: src/views/pricing/components/PricingTiers.tsx:30 #: src/views/pricing/components/PricingTiers.tsx:30
msgid "Free" msgid "Free"
msgstr "Бесплатно" msgstr "Бесплатно"
@@ -1028,7 +1043,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:467 #: src/views/board/index.tsx:470
msgid "Get started by creating a new list" msgid "Get started by creating a new list"
msgstr "Начните с создания нового списка" msgstr "Начните с создания нового списка"
@@ -1242,9 +1257,9 @@ msgstr "Канбан переосмыслен"
msgid "Keep in mind that this action is irreversible." msgid "Keep in mind that this action is irreversible."
msgstr "Имейте в виду, что это действие необратимо." msgstr "Имейте в виду, что это действие необратимо."
#: src/views/board/components/Filters.tsx:101 #: src/views/board/components/Filters.tsx:115
#: src/views/board/components/NewCardForm.tsx:408 #: src/views/board/components/NewCardForm.tsx:409
#: src/views/card/index.tsx:117 #: src/views/card/index.tsx:119
msgid "Labels" msgid "Labels"
msgstr "Метки" msgstr "Метки"
@@ -1294,18 +1309,22 @@ msgstr "Лицензия"
msgid "Light" msgid "Light"
msgstr "Светлый" msgstr "Светлый"
#: src/views/public/board/index.tsx:65 #: src/views/public/board/index.tsx:66
msgid "Link copied" msgid "Link copied"
msgstr "Ссылка скопирована" msgstr "Ссылка скопирована"
#: src/views/card/index.tsx:109 #: src/views/card/index.tsx:111
msgid "List" msgid "List"
msgstr "Список" msgstr "Список"
#: src/views/board/components/NewListForm.tsx:128 #: src/views/board/components/NewListForm.tsx:129
msgid "List name" msgid "List name"
msgstr "Название списка" msgstr "Название списка"
#: src/views/board/components/Filters.tsx:123
msgid "Lists"
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"
@@ -1326,7 +1345,7 @@ msgstr "Любим командами по всему миру"
msgid "Low Priority" msgid "Low Priority"
msgstr "Низкий приоритет" msgstr "Низкий приоритет"
#: src/components/AuthForm.tsx:421 #: src/components/AuthForm.tsx:435
msgid "magic link" msgid "magic link"
msgstr "магическая ссылка" msgstr "магическая ссылка"
@@ -1348,9 +1367,9 @@ msgid "Medium Priority"
msgstr "Средний приоритет" msgstr "Средний приоритет"
#: src/components/SideNavigation.tsx:101 #: src/components/SideNavigation.tsx:101
#: src/views/board/components/Filters.tsx:93 #: src/views/board/components/Filters.tsx:107
#: src/views/board/components/NewCardForm.tsx:366 #: src/views/board/components/NewCardForm.tsx:367
#: src/views/card/index.tsx:126 #: src/views/card/index.tsx:128
#: src/views/members/index.tsx:178 #: src/views/members/index.tsx:178
msgid "Members" msgid "Members"
msgstr "Участники" msgstr "Участники"
@@ -1403,7 +1422,7 @@ msgstr "Новый {0}"
msgid "New API key" msgid "New API key"
msgstr "Новый API-ключ" msgstr "Новый API-ключ"
#: src/views/board/components/NewCardForm.tsx:292 #: src/views/board/components/NewCardForm.tsx:293
msgid "New card" msgid "New card"
msgstr "Новая карточка" msgstr "Новая карточка"
@@ -1419,8 +1438,8 @@ msgstr "Новый импорт"
msgid "New label" msgid "New label"
msgstr "Новая метка" msgstr "Новая метка"
#: src/views/board/components/NewListForm.tsx:112 #: src/views/board/components/NewListForm.tsx:113
#: src/views/board/index.tsx:439 #: src/views/board/index.tsx:442
msgid "New list" msgid "New list"
msgstr "Новый список" msgstr "Новый список"
@@ -1457,6 +1476,10 @@ msgstr "Следующие шаги"
msgid "No {0}" msgid "No {0}"
msgstr "Нет {0}" msgstr "Нет {0}"
#: src/components/AuthForm.tsx:365
msgid "No authentication methods are currently available"
msgstr "В настоящее время нет доступных методов аутентификации"
#: src/views/boards/components/ImportBoardsForm.tsx:242 #: src/views/boards/components/ImportBoardsForm.tsx:242
msgid "No boards found" msgid "No boards found"
msgstr "Доски не найдены" msgstr "Доски не найдены"
@@ -1465,7 +1488,11 @@ msgstr "Доски не найдены"
msgid "No credit card required" msgid "No credit card required"
msgstr "Кредитная карта не требуется" msgstr "Кредитная карта не требуется"
#: src/views/board/index.tsx:464 #: src/views/card/components/AttachmentThumbnails.tsx:142
msgid "No download URL available for this attachment."
msgstr "URL для загрузки этого вложения недоступен."
#: src/views/board/index.tsx:467
msgid "No lists" msgid "No lists"
msgstr "Нет списков" msgstr "Нет списков"
@@ -1497,7 +1524,7 @@ msgstr "С открытым исходным кодом"
msgid "Open Source Friends" msgid "Open Source Friends"
msgstr "Друзья с открытым исходным кодом" msgstr "Друзья с открытым исходным кодом"
#: src/components/AuthForm.tsx:365 #: src/components/AuthForm.tsx:374
msgid "or" msgid "or"
msgstr "или" msgstr "или"
@@ -1579,15 +1606,15 @@ msgstr "Платформа"
msgid "Please confirm your new password" msgid "Please confirm your new password"
msgstr "Пожалуйста, подтвердите новый пароль" msgstr "Пожалуйста, подтвердите новый пароль"
#: src/components/AuthForm.tsx:391 #: src/components/AuthForm.tsx:402
msgid "Please enter a valid email address" msgid "Please enter a valid email address"
msgstr "Пожалуйста, введите действительный адрес электронной почты" msgstr "Пожалуйста, введите действительный адрес электронной почты"
#: src/components/AuthForm.tsx:379 #: src/components/AuthForm.tsx:388
msgid "Please enter a valid name" msgid "Please enter a valid name"
msgstr "Пожалуйста, введите действительное имя" msgstr "Пожалуйста, введите действительное имя"
#: src/components/AuthForm.tsx:404 #: src/components/AuthForm.tsx:416
msgid "Please enter a valid password" msgid "Please enter a valid password"
msgstr "Пожалуйста, введите действительный пароль" msgstr "Пожалуйста, введите действительный пароль"
@@ -1598,15 +1625,16 @@ 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:176 #: src/views/board/components/NewCardForm.tsx:177
#: src/views/board/components/NewListForm.tsx:78 #: 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:72 #: src/views/board/components/UpdateBoardSlugForm.tsx:73
#: src/views/board/components/VisibilityButton.tsx:53 #: src/views/board/components/VisibilityButton.tsx:54
#: src/views/board/index.tsx:149 #: src/views/board/index.tsx:151
#: src/views/board/index.tsx:205 #: src/views/board/index.tsx:207
#: 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/ChecklistItemRow.tsx:60 #: src/views/card/components/ChecklistItemRow.tsx:60
#: src/views/card/components/ChecklistItemRow.tsx:88 #: src/views/card/components/ChecklistItemRow.tsx:88
#: src/views/card/components/ChecklistNameInput.tsx:46 #: src/views/card/components/ChecklistNameInput.tsx:46
@@ -1620,7 +1648,7 @@ msgstr "Пожалуйста, выберите файл для загрузки.
#: src/views/card/components/NewChecklistForm.tsx:70 #: src/views/card/components/NewChecklistForm.tsx:70
#: src/views/card/components/NewChecklistItemForm.tsx:89 #: src/views/card/components/NewChecklistItemForm.tsx:89
#: src/views/card/components/NewCommentForm.tsx:31 #: src/views/card/components/NewCommentForm.tsx:31
#: src/views/card/index.tsx:175 #: src/views/card/index.tsx:177
#: 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
@@ -1664,7 +1692,7 @@ msgstr "Приоритетная поддержка по электронной
msgid "Privacy policy" msgid "Privacy policy"
msgstr "Политика конфиденциальности" msgstr "Политика конфиденциальности"
#: src/views/board/components/VisibilityButton.tsx:73 #: src/views/board/components/VisibilityButton.tsx:74
msgid "Private" msgid "Private"
msgstr "Личное" msgstr "Личное"
@@ -1684,7 +1712,7 @@ msgstr "Изображение профиля обновлено"
msgid "Profile picture" msgid "Profile picture"
msgstr "Фотография профиля" msgstr "Фотография профиля"
#: src/views/board/components/VisibilityButton.tsx:68 #: src/views/board/components/VisibilityButton.tsx:69
msgid "Public" msgid "Public"
msgstr "Публичное" msgstr "Публичное"
@@ -1886,7 +1914,7 @@ msgstr "Регистрация отключена"
msgid "Sign up is currently disabled. Please try again later." msgid "Sign up is currently disabled. Please try again later."
msgstr "Регистрация в настоящее время отключена. Пожалуйста, попробуйте позже." msgstr "Регистрация в настоящее время отключена. Пожалуйста, попробуйте позже."
#: src/components/AuthForm.tsx:420 #: src/components/AuthForm.tsx:434
msgid "Sign up with " msgid "Sign up with "
msgstr "Зарегистрироваться с " msgstr "Зарегистрироваться с "
@@ -1953,8 +1981,8 @@ msgstr "Командный план"
msgid "Teams" msgid "Teams"
msgstr "Команды" msgstr "Команды"
#: src/views/board/index.tsx:361 #: src/views/board/index.tsx:363
#: src/views/board/index.tsx:396 #: src/views/board/index.tsx:398
msgid "Template" msgid "Template"
msgstr "Шаблон" msgstr "Шаблон"
@@ -2004,7 +2032,7 @@ msgid "The open source <0/> alternative to Trello"
msgstr "Альтернатива Trello с открытым исходным кодом <0/>" msgstr "Альтернатива Trello с открытым исходным кодом <0/>"
#. placeholder {0}: isPublic ? "public" : "private" #. placeholder {0}: isPublic ? "public" : "private"
#: src/views/board/components/VisibilityButton.tsx:46 #: src/views/board/components/VisibilityButton.tsx:47
msgid "The visibility of your board has been set to {0}." msgid "The visibility of your board has been set to {0}."
msgstr "Видимость вашей доски установлена на {0}." msgstr "Видимость вашей доски установлена на {0}."
@@ -2028,11 +2056,11 @@ 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:154 #: src/views/public/board/index.tsx:156
msgid "This board is private or does not exist" msgid "This board is private or does not exist"
msgstr "Эта доска является приватной или не существует." msgstr "Эта доска является приватной или не существует."
#: src/views/board/components/UpdateBoardSlugForm.tsx:135 #: src/views/board/components/UpdateBoardSlugForm.tsx:136
msgid "This board URL has already been taken" msgid "This board URL has already been taken"
msgstr "Этот URL доски уже занят." msgstr "Этот URL доски уже занят."
@@ -2102,7 +2130,7 @@ msgstr "Не удалось добавить элемент контрольно
msgid "Unable to add comment" msgid "Unable to add comment"
msgstr "Не удалось добавить комментарий." msgstr "Не удалось добавить комментарий."
#: src/views/board/components/NewCardForm.tsx:173 #: src/views/board/components/NewCardForm.tsx:174
msgid "Unable to create card" msgid "Unable to create card"
msgstr "Не удалось создать карточку." msgstr "Не удалось создать карточку."
@@ -2110,7 +2138,7 @@ msgstr "Не удалось создать карточку."
msgid "Unable to create checklist" msgid "Unable to create checklist"
msgstr "Не удалось создать контрольный список." msgstr "Не удалось создать контрольный список."
#: src/views/board/components/NewListForm.tsx:77 #: src/views/board/components/NewListForm.tsx:78
msgid "Unable to create list" msgid "Unable to create list"
msgstr "Не удалось создать список." msgstr "Не удалось создать список."
@@ -2123,6 +2151,10 @@ msgstr "Не удалось создать шаблон"
msgid "Unable to create workspace" msgid "Unable to create workspace"
msgstr "Не удалось создать рабочее пространство." msgstr "Не удалось создать рабочее пространство."
#: src/views/card/components/AttachmentThumbnails.tsx:72
msgid "Unable to delete attachment"
msgstr "Не удалось удалить вложение"
#: src/views/card/components/DeleteCardConfirmation.tsx:51 #: src/views/card/components/DeleteCardConfirmation.tsx:51
msgid "Unable to delete card" msgid "Unable to delete card"
msgstr "Не удалось удалить карточку." msgstr "Не удалось удалить карточку."
@@ -2147,16 +2179,16 @@ msgstr "Не удалось удалить участника"
msgid "Unable to send feedback" msgid "Unable to send feedback"
msgstr "Не удалось отправить отзыв" msgstr "Не удалось отправить отзыв"
#: src/views/board/components/UpdateBoardSlugForm.tsx:71 #: src/views/board/components/UpdateBoardSlugForm.tsx:72
msgid "Unable to update board URL" msgid "Unable to update board URL"
msgstr "Не удалось обновить URL доски" msgstr "Не удалось обновить URL доски"
#: src/views/board/components/VisibilityButton.tsx:52 #: src/views/board/components/VisibilityButton.tsx:53
msgid "Unable to update board visibility" msgid "Unable to update board visibility"
msgstr "Не удалось обновить видимость доски" msgstr "Не удалось обновить видимость доски"
#: src/views/board/index.tsx:204 #: src/views/board/index.tsx:206
#: src/views/card/index.tsx:174 #: src/views/card/index.tsx:176
msgid "Unable to update card" msgid "Unable to update card"
msgstr "Не удалось обновить карточку" msgstr "Не удалось обновить карточку"
@@ -2176,7 +2208,7 @@ msgstr "Не удалось обновить комментарий"
msgid "Unable to update labels" msgid "Unable to update labels"
msgstr "Не удалось обновить метки" msgstr "Не удалось обновить метки"
#: src/views/board/index.tsx:148 #: src/views/board/index.tsx:150
#: src/views/card/components/ListSelector.tsx:51 #: src/views/card/components/ListSelector.tsx:51
msgid "Unable to update list" msgid "Unable to update list"
msgstr "Не удалось обновить список" msgstr "Не удалось обновить список"
@@ -2232,7 +2264,7 @@ msgstr "Неограниченное количество участников"
msgid "Unlimited workspaces" msgid "Unlimited workspaces"
msgstr "Неограниченное количество рабочих пространств" msgstr "Неограниченное количество рабочих пространств"
#: src/views/board/components/UpdateBoardSlugForm.tsx:174 #: 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
#: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83 #: src/views/settings/components/UpdateWorkspaceNameForm.tsx:83
@@ -2271,6 +2303,11 @@ 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:78
msgid "Upload failed"
msgstr "Не удалось загрузить"
#: src/views/boards/components/TemplateBoards.tsx:38 #: src/views/boards/components/TemplateBoards.tsx:38
#: src/views/boards/components/TemplateBoards.tsx:55 #: src/views/boards/components/TemplateBoards.tsx:55
msgid "Urgent" msgid "Urgent"
@@ -2320,7 +2357,7 @@ msgstr "Просмотр и управление вашими счетами и
msgid "View docs" msgid "View docs"
msgstr "Просмотреть документацию" msgstr "Просмотреть документацию"
#: src/views/public/board/index.tsx:128 #: src/views/public/board/index.tsx:129
msgid "View only" msgid "View only"
msgstr "Только просмотр" msgstr "Только просмотр"
@@ -2328,11 +2365,11 @@ msgstr "Только просмотр"
msgid "View our roadmap." msgid "View our roadmap."
msgstr "Просмотреть нашу дорожную карту." msgstr "Просмотреть нашу дорожную карту."
#: src/views/public/board/index.tsx:157 #: src/views/public/board/index.tsx:159
msgid "View workspace" msgid "View workspace"
msgstr "Просмотреть рабочее пространство" msgstr "Просмотреть рабочее пространство"
#: src/views/board/components/VisibilityButton.tsx:91 #: src/views/board/components/VisibilityButton.tsx:92
msgid "Visibility" msgid "Visibility"
msgstr "Видимость" msgstr "Видимость"
@@ -2369,10 +2406,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:361 #: src/views/board/index.tsx:363
#: src/views/boards/index.tsx:22 #: src/views/boards/index.tsx:22
#: src/views/members/index.tsx:173 #: src/views/members/index.tsx:173
#: src/views/public/board/index.tsx:100 #: src/views/public/board/index.tsx:101
#: src/views/public/boards/index.tsx:66 #: src/views/public/boards/index.tsx:66
msgid "Workspace" msgid "Workspace"
msgstr "Рабочее пространство" msgstr "Рабочее пространство"
@@ -2502,6 +2539,10 @@ msgstr "Ваши доски были импортированы."
msgid "Your display name has been updated." msgid "Your display name has been updated."
msgstr "Ваше отображаемое имя было обновлено." msgstr "Ваше отображаемое имя было обновлено."
#: src/views/card/components/AttachmentUpload.tsx:26
msgid "Your file has been uploaded successfully."
msgstr "Ваш файл успешно загружен."
#: src/views/settings/components/ChangePasswordConfirmation.tsx:70 #: src/views/settings/components/ChangePasswordConfirmation.tsx:70
msgid "Your password has been changed." msgid "Your password has been changed."
msgstr "Ваш пароль был изменён." msgstr "Ваш пароль был изменён."

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,48 @@
import type { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (req.method !== "GET") {
return res.status(405).json({ message: "Method not allowed" });
}
const { url, filename } = req.query;
if (!url || typeof url !== "string") {
return res.status(400).json({
message: "url parameter is required",
});
}
try {
const downloadUrl = decodeURIComponent(url);
const downloadFilename =
(typeof filename === "string" ? decodeURIComponent(filename) : null) ??
"attachment";
const upstream = await fetch(downloadUrl);
if (!upstream.ok) {
return res.status(upstream.status).json({
message: "Failed to fetch attachment",
});
}
const contentType =
upstream.headers.get("Content-Type") ?? "application/octet-stream";
res.setHeader("Content-Type", contentType);
res.setHeader(
"Content-Disposition",
`attachment; filename="${downloadFilename}"`,
);
const buffer = await upstream.arrayBuffer();
return res.send(Buffer.from(buffer));
} catch (error) {
console.error("Error downloading attachment:", error);
return res.status(500).json({ message: "Failed to download attachment" });
}
}

View File

@@ -1,3 +1,4 @@
import { HiOutlinePaperClip } from "react-icons/hi";
import { HiBars3BottomLeft, HiChatBubbleLeft } from "react-icons/hi2"; import { HiBars3BottomLeft, HiChatBubbleLeft } from "react-icons/hi2";
import Avatar from "~/components/Avatar"; import Avatar from "~/components/Avatar";
@@ -13,6 +14,7 @@ const Card = ({
checklists, checklists,
description, description,
comments, comments,
attachments,
}: { }: {
title: string; title: string;
labels: { name: string; colourCode: string | null }[]; labels: { name: string; colourCode: string | null }[];
@@ -33,6 +35,7 @@ const Card = ({
}[]; }[];
description: string | null; description: string | null;
comments: { publicId: string }[]; comments: { publicId: string }[];
attachments?: { publicId: string }[];
}) => { }) => {
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;
@@ -47,6 +50,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;
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">
@@ -55,7 +59,8 @@ const Card = ({
members.length || members.length ||
checklists.length > 0 || checklists.length > 0 ||
hasDescription || hasDescription ||
comments.length > 0 ? ( comments.length > 0 ||
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">
{labels.map((label) => ( {labels.map((label) => (
@@ -77,6 +82,11 @@ const Card = ({
<HiChatBubbleLeft className="h-4 w-4" /> <HiChatBubbleLeft className="h-4 w-4" />
</div> </div>
)} )}
{hasAttachments && (
<div className="flex items-center gap-1 text-light-700 dark:text-dark-800">
<HiOutlinePaperClip className="h-4 w-4" />
</div>
)}
</div> </div>
<div className="flex items-center justify-end gap-1"> <div className="flex items-center justify-end gap-1">
{checklists.length > 0 && ( {checklists.length > 0 && (

View File

@@ -12,6 +12,7 @@ interface QueryParams {
boardPublicId: string; boardPublicId: string;
members: string[]; members: string[];
labels: string[]; labels: string[];
lists: string[];
} }
export function DeleteListConfirmation({ export function DeleteListConfirmation({

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,
HiOutlineSquare3Stack3D,
HiOutlineTag, HiOutlineTag,
HiOutlineUserCircle, HiOutlineUserCircle,
} from "react-icons/hi2"; } from "react-icons/hi2";
@@ -32,15 +33,22 @@ interface Label {
colourCode: string | null; colourCode: string | null;
} }
interface List {
publicId: string;
name: string;
}
const Filters = ({ const Filters = ({
position = "right", position = "right",
labels, labels,
members, members,
lists,
isLoading, isLoading,
}: { }: {
position?: "left" | "right"; position?: "left" | "right";
labels: Label[]; labels: Label[];
members: Member[]; members: Member[];
lists: List[];
isLoading: boolean; isLoading: boolean;
}) => { }) => {
const router = useRouter(); const router = useRouter();
@@ -52,7 +60,7 @@ const Filters = ({
try { try {
await router.push({ await router.push({
pathname: router.pathname, pathname: router.pathname,
query: { ...router.query, members: [], labels: [] }, query: { ...router.query, members: [], labels: [], lists: [] },
}); });
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@@ -85,6 +93,12 @@ const Filters = ({
leftIcon: <LabelIcon colourCode={label.colourCode} />, leftIcon: <LabelIcon colourCode={label.colourCode} />,
})); }));
const formattedLists = lists.map((list) => ({
key: list.publicId,
value: list.name,
selected: !!router.query.lists?.includes(list.publicId),
}));
const groups = [ const groups = [
...(formattedMembers.length ...(formattedMembers.length
? [ ? [
@@ -102,6 +116,16 @@ const Filters = ({
icon: <HiOutlineTag size={16} />, icon: <HiOutlineTag size={16} />,
items: formattedLabels, items: formattedLabels,
}, },
...(formattedLists.length
? [
{
key: "lists",
label: t`Lists`,
icon: <HiOutlineSquare3Stack3D size={16} />,
items: formattedLists,
},
]
: []),
]; ];
const handleSelect = async ( const handleSelect = async (
@@ -131,6 +155,7 @@ const Filters = ({
const numOfFilters = [ const numOfFilters = [
...formatToArray(router.query.members), ...formatToArray(router.query.members),
...formatToArray(router.query.labels), ...formatToArray(router.query.labels),
...formatToArray(router.query.lists),
].length; ].length;
return ( return (

View File

@@ -33,6 +33,7 @@ interface QueryParams {
boardPublicId: string; boardPublicId: string;
members: string[]; members: string[];
labels: string[]; labels: string[];
lists: string[];
} }
interface NewCardFormProps { interface NewCardFormProps {

View File

@@ -21,6 +21,7 @@ interface QueryParams {
boardPublicId: string; boardPublicId: string;
members: string[]; members: string[];
labels: string[]; labels: string[];
lists: string[];
} }
export function NewListForm({ export function NewListForm({

View File

@@ -17,6 +17,7 @@ interface QueryParams {
boardPublicId: string; boardPublicId: string;
members: string[]; members: string[];
labels: string[]; labels: string[];
lists: string[];
} }
export function UpdateBoardSlugForm({ export function UpdateBoardSlugForm({

View File

@@ -11,6 +11,7 @@ interface QueryParams {
boardPublicId: string; boardPublicId: string;
members: string[]; members: string[];
labels: string[]; labels: string[];
lists: string[];
} }
const VisibilityButton = ({ const VisibilityButton = ({

View File

@@ -80,11 +80,13 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
boardPublicId: string; boardPublicId: string;
members: string[]; members: string[];
labels: string[]; labels: string[];
lists: string[];
type: "regular" | "template"; type: "regular" | "template";
} = { } = {
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),
type: isTemplate ? "template" : "regular", type: isTemplate ? "template" : "regular",
}; };
@@ -418,6 +420,7 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
members={boardData.workspace.members.filter( members={boardData.workspace.members.filter(
(member) => member.user !== null, (member) => member.user !== null,
)} )}
lists={boardData.allLists}
position="left" position="left"
isLoading={!boardData} isLoading={!boardData}
/> />
@@ -550,6 +553,7 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
card.description ?? null card.description ?? null
} }
comments={card.comments ?? []} comments={card.comments ?? []}
attachments={card.attachments}
/> />
</Link> </Link>
)} )}

View File

@@ -0,0 +1,462 @@
import Image from "next/image";
import { Dialog, Transition } from "@headlessui/react";
import { t } from "@lingui/core/macro";
import { Fragment, useEffect, useState } from "react";
import {
HiArrowDownTray,
HiChevronLeft,
HiChevronRight,
HiDocumentText,
HiOutlineTrash,
HiXMark,
} from "react-icons/hi2";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
interface Attachment {
publicId: string;
contentType: string;
url: string | null;
originalFilename: string | null;
s3Key: string;
size?: number | null;
}
export function AttachmentThumbnails({
attachments,
cardPublicId,
isReadOnly = false,
}: {
attachments?: Attachment[];
cardPublicId: string;
isReadOnly?: boolean;
}) {
const { showPopup } = usePopup();
const utils = api.useUtils();
const imageAttachments =
attachments?.filter(
(attachment) =>
attachment.contentType.startsWith("image/") && attachment.url,
) ?? [];
const nonImageAttachments =
attachments?.filter(
(attachment) =>
!attachment.contentType.startsWith("image/") && attachment.url,
) ?? [];
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
const deleteAttachment = api.attachment.delete.useMutation({
onMutate: async (args) => {
if (isReadOnly) return;
await utils.card.byId.cancel({ cardPublicId });
const currentState = utils.card.byId.getData({ cardPublicId });
utils.card.byId.setData({ cardPublicId }, (oldCard) => {
if (!oldCard) return oldCard;
const updatedAttachments = oldCard.attachments.filter(
(attachment) => attachment.publicId !== args.attachmentPublicId,
);
return { ...oldCard, attachments: updatedAttachments };
});
return { previousState: currentState };
},
onError: (_error, _args, context) => {
if (isReadOnly) return;
utils.card.byId.setData({ cardPublicId }, context?.previousState);
showPopup({
header: t`Unable to delete attachment`,
message: t`Please try again later, or contact customer support.`,
icon: "error",
});
},
onSuccess: () => {
if (isReadOnly) return;
// Close viewer if the deleted image was being viewed
setSelectedIndex(null);
},
onSettled: async () => {
if (isReadOnly) return;
await utils.card.byId.invalidate({ cardPublicId });
},
});
// Keyboard navigation
useEffect(() => {
if (selectedIndex === null) return;
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === "Escape") {
setSelectedIndex(null);
} else if (e.key === "ArrowLeft") {
setSelectedIndex((prev) => {
if (prev === null) return null;
return prev === 0 ? imageAttachments.length - 1 : prev - 1;
});
} else if (e.key === "ArrowRight") {
setSelectedIndex((prev) => {
if (prev === null) return null;
return prev === imageAttachments.length - 1 ? 0 : prev + 1;
});
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [selectedIndex, imageAttachments.length]);
if (imageAttachments.length === 0 && nonImageAttachments.length === 0) {
return null;
}
const openViewer = (index: number) => {
setSelectedIndex(index);
};
const closeViewer = () => {
setSelectedIndex(null);
};
const goToPrevious = () => {
if (selectedIndex === null) return;
const newIndex =
selectedIndex === 0 ? imageAttachments.length - 1 : selectedIndex - 1;
setSelectedIndex(newIndex);
};
const goToNext = () => {
if (selectedIndex === null) return;
const newIndex =
selectedIndex === imageAttachments.length - 1 ? 0 : selectedIndex + 1;
setSelectedIndex(newIndex);
};
const handleDownload = (attachment: Attachment) => {
if (!attachment.url) {
showPopup({
header: t`Download failed`,
message: t`No download URL available for this attachment.`,
icon: "error",
});
return;
}
const downloadUrl = `/api/download/attatchment?url=${encodeURIComponent(attachment.url)}&filename=${encodeURIComponent(attachment.originalFilename ?? "attachment")}`;
const link = document.createElement("a");
link.href = downloadUrl;
link.style.display = "none";
document.body.appendChild(link);
link.click();
};
const selectedAttachment =
selectedIndex !== null ? imageAttachments[selectedIndex] : null;
return (
<>
<div className="mb-3 flex flex-wrap gap-2 pt-1">
{imageAttachments.map((attachment, index) => {
if (!attachment.url) return null;
return (
<AttachmentThumbnail
key={attachment.publicId}
attachment={{
publicId: attachment.publicId,
url: attachment.url,
originalFilename: attachment.originalFilename ?? "",
contentType: attachment.contentType,
}}
onClick={() => openViewer(index)}
isImage={true}
/>
);
})}
</div>
{nonImageAttachments.length > 0 && (
<div className="mb-3 flex flex-col gap-2">
{nonImageAttachments.map((attachment) => {
if (!attachment.url) return null;
return (
<FileListItem
key={attachment.publicId}
attachment={attachment}
onDownload={() => handleDownload(attachment)}
onDelete={
isReadOnly
? undefined
: () => {
deleteAttachment.mutate({
attachmentPublicId: attachment.publicId,
});
}
}
/>
);
})}
</div>
)}
<Transition.Root show={selectedIndex !== null} as={Fragment}>
<Dialog
as="div"
className="relative z-50"
onClose={() => {
// Dialog closing is handled by the background overlay click
}}
static
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div
className="fixed inset-0 bg-light-50 transition-opacity dark:bg-dark-50"
onClick={(e) => {
// Only close if clicking directly on the background, not on buttons
if (e.target === e.currentTarget) {
closeViewer();
}
}}
/>
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
{selectedIndex !== null && selectedAttachment && (
<div
className="fixed left-2 top-2 z-20 flex gap-1"
onMouseDown={(e) => e.stopPropagation()}
onClick={(e) => e.stopPropagation()}
>
{!isReadOnly && (
<button
onMouseDown={(e) => {
e.preventDefault();
e.stopPropagation();
}}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
deleteAttachment.mutate({
attachmentPublicId: selectedAttachment.publicId,
});
}}
className="rounded-full bg-light-50 p-1.5 text-light-1000 transition-colors hover:bg-light-100 focus:outline-none dark:bg-dark-50 dark:text-dark-1000 dark:hover:bg-dark-100"
aria-label="Delete image"
disabled={deleteAttachment.isPending}
>
<HiOutlineTrash className="h-4 w-4" />
</button>
)}
<button
onMouseDown={(e) => {
e.preventDefault();
e.stopPropagation();
}}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
handleDownload(selectedAttachment);
}}
className="rounded-full bg-light-50 p-1.5 text-light-1000 transition-colors hover:bg-light-100 focus:outline-none dark:bg-dark-50 dark:text-dark-1000 dark:hover:bg-dark-100"
aria-label="Download image"
>
<HiArrowDownTray className="h-4 w-4" />
</button>
</div>
)}
<div className="fixed right-2 top-2 z-20 flex gap-1">
{imageAttachments.length > 1 && selectedIndex !== null && (
<button
onClick={(e) => {
e.stopPropagation();
goToPrevious();
}}
className="rounded-full bg-light-50 p-1.5 text-light-1000 transition-colors hover:bg-light-100 focus:outline-none dark:bg-dark-50 dark:text-dark-1000 dark:hover:bg-dark-100"
aria-label="Previous image"
>
<HiChevronLeft className="h-4 w-4" />
</button>
)}
{imageAttachments.length > 1 && selectedIndex !== null && (
<button
onClick={(e) => {
e.stopPropagation();
goToNext();
}}
className="rounded-full bg-light-50 p-1.5 text-light-1000 transition-colors hover:bg-light-100 focus:outline-none dark:bg-dark-50 dark:text-dark-1000 dark:hover:bg-dark-100"
aria-label="Next image"
>
<HiChevronRight className="h-4 w-4" />
</button>
)}
{selectedIndex !== null && (
<button
onClick={(e) => {
e.stopPropagation();
closeViewer();
}}
className="rounded-full bg-light-50 p-1.5 text-light-1000 transition-colors hover:bg-light-100 focus:outline-none dark:bg-dark-50 dark:text-dark-1000 dark:hover:bg-dark-100"
aria-label="Close"
>
<HiXMark className="h-4 w-4" />
</button>
)}
</div>
<div className="flex min-h-full items-center justify-center p-4">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel
className="relative w-full max-w-7xl"
onClick={(e) => e.stopPropagation()}
>
{selectedAttachment?.url && (
<div className="relative">
<div className="relative mx-auto max-h-[90vh] w-full">
<Image
src={selectedAttachment.url}
alt={
selectedAttachment.originalFilename ?? "Attachment"
}
width={1920}
height={1080}
className="mx-auto max-h-[90vh] w-auto object-contain"
unoptimized
/>
</div>
{imageAttachments.length > 1 && (
<div className="absolute bottom-4 left-1/2 -translate-x-1/2 rounded-full bg-black/50 px-3 py-1.5 text-[10px] text-white">
{selectedIndex !== null && selectedIndex + 1} /{" "}
{imageAttachments.length}
</div>
)}
</div>
)}
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
</>
);
}
function AttachmentThumbnail({
attachment,
onClick,
isImage,
}: {
attachment: {
publicId: string;
url: string;
originalFilename: string;
contentType: string;
};
onClick: () => void;
isImage: boolean;
}) {
return (
<button
onClick={onClick}
className="relative h-16 w-16 overflow-hidden rounded-xl border border-light-300 transition-transform hover:scale-105 dark:border-dark-300"
aria-label={`View ${attachment.originalFilename}`}
>
{isImage ? (
<Image
src={attachment.url}
alt={attachment.originalFilename}
fill
className="object-cover"
sizes="64px"
/>
) : (
<div className="flex h-full w-full items-center justify-center bg-light-100 dark:bg-dark-100">
<HiDocumentText className="h-6 w-6 text-light-700 dark:text-dark-700" />
</div>
)}
</button>
);
}
function formatFileSize(bytes: number | null | undefined): string {
if (!bytes || bytes === 0 || isNaN(bytes)) return "0 B";
const k = 1024;
const sizes = ["B", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i] ?? "B"}`;
}
function FileListItem({
attachment,
onDownload,
onDelete,
}: {
attachment: Attachment;
onDownload: () => void;
onDelete?: () => void;
}) {
return (
<div className="group flex w-full items-center gap-3 rounded-lg border border-light-300 bg-light-50 px-3 py-2 dark:border-dark-200 dark:bg-dark-100">
<div className="flex-shrink-0">
<HiDocumentText className="h-5 w-5 text-light-700 dark:text-dark-700" />
</div>
<div className="min-w-0 flex-1 truncate text-sm text-light-1000 dark:text-dark-1000">
{attachment.originalFilename ?? "File"}
</div>
<div className="flex items-center gap-2 opacity-0 transition-opacity group-hover:opacity-100">
<div className="text-xs text-light-500 dark:text-dark-900">
{attachment.size != null &&
!isNaN(attachment.size) &&
`${formatFileSize(attachment.size)}`}
</div>
<div className="flex items-center gap-1">
<button
onClick={(e) => {
e.stopPropagation();
onDownload();
}}
className="flex-shrink-0 rounded-full bg-light-100 p-1.5 text-light-1000 transition-colors hover:bg-light-200 focus:outline-none dark:bg-dark-100 dark:text-dark-950 dark:hover:bg-dark-300"
aria-label={`Download ${attachment.originalFilename}`}
>
<HiArrowDownTray className="h-4 w-4" />
</button>
{onDelete && (
<button
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
className="flex-shrink-0 rounded-full bg-light-100 p-1.5 text-light-1000 transition-colors hover:bg-light-200 focus:outline-none dark:bg-dark-100 dark:text-dark-950 dark:hover:bg-dark-300"
aria-label={`Delete ${attachment.originalFilename}`}
>
<HiXMark className="h-4 w-4" />
</button>
)}
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,174 @@
import { t } from "@lingui/core/macro";
import { useRef, useState } from "react";
import { HiOutlinePaperClip } from "react-icons/hi";
import { HiCheckBadge } from "react-icons/hi2";
import { twMerge } from "tailwind-merge";
import Button from "~/components/Button";
import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
export function AttachmentUpload({ cardPublicId }: { cardPublicId: string }) {
const { openModal } = useModal();
const { showPopup } = usePopup();
const utils = api.useUtils();
const [uploading, setUploading] = useState(false);
const [isDragging, setIsDragging] = useState(false);
const inputRef = useRef<HTMLInputElement | null>(null);
const generateUploadUrl = api.attachment.generateUploadUrl.useMutation();
const confirmAttachment = api.attachment.confirm.useMutation({
onSuccess: async () => {
await utils.card.byId.invalidate({ cardPublicId });
showPopup({
header: t`Attachment uploaded`,
message: t`Your file has been uploaded successfully.`,
icon: "success",
});
},
onError: () => {
showPopup({
header: t`Upload failed`,
message: t`Failed to upload attachment. Please try again.`,
icon: "error",
});
},
onSettled: () => {
setUploading(false);
},
});
const uploadFile = async (file: File) => {
setUploading(true);
try {
// Generate presigned URL
const { url, key } = await generateUploadUrl.mutateAsync({
cardPublicId,
filename: file.name,
contentType: file.type,
size: file.size,
});
// Upload file to S3
const uploadResponse = await fetch(url, {
method: "PUT",
body: file,
headers: {
"Content-Type": file.type,
},
});
if (!uploadResponse.ok) {
throw new Error("Upload failed");
}
// Confirm attachment in database
await confirmAttachment.mutateAsync({
cardPublicId,
s3Key: key,
filename: file.name,
originalFilename: file.name,
contentType: file.type,
size: file.size,
});
} catch {
showPopup({
header: t`Upload failed`,
message: t`Failed to upload attachment. Please try again.`,
icon: "error",
});
setUploading(false);
}
};
const handleFileSelect = async (
event: React.ChangeEvent<HTMLInputElement>,
) => {
const file = event.target.files?.[0];
if (!file) return;
// Reset input
event.target.value = "";
await uploadFile(file);
};
const handleDragOver = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
if (!uploading) {
setIsDragging(true);
}
};
const handleDragLeave = (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
};
const handleDrop = async (e: React.DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
if (uploading) return;
const files = Array.from(e.dataTransfer.files);
if (files.length === 0) return;
// Upload the first file (or could upload all files)
await uploadFile(files[0] ?? new File([], ""));
};
return (
<div className="mb-6">
<input
ref={inputRef}
type="file"
id="attachment-upload"
className="hidden"
onChange={handleFileSelect}
disabled={uploading}
/>
<div
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
className={twMerge(
"rounded-lg border-2 border-dashed transition-colors",
isDragging
? "border-light-300 bg-light-100 dark:border-dark-300 dark:bg-dark-100"
: "border-transparent",
)}
>
<div className="flex items-center justify-between p-2">
<Button
type="button"
variant="ghost"
iconLeft={
<HiCheckBadge className="h-4 w-4 text-light-950 dark:text-dark-950" />
}
iconOnly
size="sm"
onClick={() => openModal("ADD_CHECKLIST")}
/>
<Button
type="button"
variant="ghost"
iconLeft={
<HiOutlinePaperClip className="h-4 w-4 text-light-950 dark:text-dark-950" />
}
isLoading={uploading}
disabled={uploading}
iconOnly
size="sm"
onClick={() => inputRef.current?.click()}
/>
</div>
</div>
</div>
);
}

View File

@@ -28,7 +28,7 @@ export default function BoardDropdown() {
}, },
]} ]}
> >
<HiEllipsisHorizontal className="h-6 w-6 text-dark-900" /> <HiEllipsisHorizontal className="h-5 w-5 text-dark-900" />
</Dropdown> </Dropdown>
); );
} }

View File

@@ -20,6 +20,8 @@ import { api } from "~/utils/api";
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";
import { AttachmentThumbnails } from "./components/AttachmentThumbnails";
import { AttachmentUpload } from "./components/AttachmentUpload";
import Checklists from "./components/Checklists"; import Checklists from "./components/Checklists";
import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation"; import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation";
import { DeleteChecklistConfirmation } from "./components/DeleteChecklistConfirmation"; import { DeleteChecklistConfirmation } from "./components/DeleteChecklistConfirmation";
@@ -105,7 +107,7 @@ export function CardRightPanel({ isTemplate }: { isTemplate?: boolean }) {
return ( return (
<div className="h-full w-[360px] border-l-[1px] border-light-300 bg-light-50 p-8 text-light-900 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900"> <div className="h-full w-[360px] border-l-[1px] border-light-300 bg-light-50 p-8 text-light-900 dark:border-dark-300 dark:bg-dark-50 dark:text-dark-900">
<div className="mb-4 flex w-full flex-row"> <div className="mb-4 flex w-full flex-row pt-[18px]">
<p className="my-2 mb-2 w-[100px] text-sm font-medium">{t`List`}</p> <p className="my-2 mb-2 w-[100px] text-sm font-medium">{t`List`}</p>
<ListSelector <ListSelector
cardPublicId={cardId ?? ""} cardPublicId={cardId ?? ""}
@@ -208,6 +210,17 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
} }
}, [card, getModalState, clearModalState]); }, [card, getModalState, clearModalState]);
// Auto-resize title textarea
useEffect(() => {
const titleTextarea = document.getElementById(
"title",
) as HTMLTextAreaElement;
if (titleTextarea) {
titleTextarea.style.height = "auto";
titleTextarea.style.height = `${titleTextarea.scrollHeight}px`;
}
}, [card]);
if (!cardId) return <></>; if (!cardId) return <></>;
return ( return (
@@ -215,47 +228,71 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
<PageHead <PageHead
title={t`${card?.title ?? t`Card`} | ${board?.name ?? t`Board`}`} title={t`${card?.title ?? t`Card`} | ${board?.name ?? t`Board`}`}
/> />
<div className="flex h-full flex-1 flex-row overflow-hidden"> <div className="flex h-full flex-1 flex-col overflow-hidden">
{/* Full-width top strip with board link and dropdown */}
<div className="flex w-full items-center justify-between border-b-[1px] border-light-300 bg-light-50 px-8 py-2 dark:border-dark-300 dark:bg-dark-50">
{!card && isLoading && (
<div className="flex space-x-2">
<div className="h-[1.5rem] w-[150px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" />
</div>
)}
{card && (
<>
<div className="flex items-center gap-1">
<Link
className="whitespace-nowrapleading-[1.5rem] text-sm font-bold text-light-900 dark:text-dark-950"
href={`${isTemplate ? "/templates" : "/boards"}`}
>
{workspace.name}
</Link>
<IoChevronForwardSharp className="h-[10px] w-[10px] text-light-900 dark:text-dark-900" />
<Link
className="whitespace-nowrap text-sm font-bold leading-[1.5rem] text-light-900 dark:text-dark-950"
href={`${isTemplate ? "/templates" : "/boards"}/${board?.publicId}`}
>
{board?.name}
</Link>
</div>
<div className="flex items-center gap-2">
<Dropdown />
</div>
</>
)}
{!card && !isLoading && (
<p className="block p-0 py-0 font-bold leading-[1.5rem] tracking-tight text-light-900 dark:text-dark-900 sm:text-[1rem]">
{t`Card not found`}
</p>
)}
</div>
<div className="scrollbar-thumb-rounded-[4px] scrollbar-track-rounded-[4px] w-full flex-1 overflow-y-auto scrollbar scrollbar-track-light-200 scrollbar-thumb-light-400 hover:scrollbar-thumb-light-400 dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-300 dark:hover:scrollbar-thumb-dark-300"> <div className="scrollbar-thumb-rounded-[4px] scrollbar-track-rounded-[4px] w-full flex-1 overflow-y-auto scrollbar scrollbar-track-light-200 scrollbar-thumb-light-400 hover:scrollbar-thumb-light-400 dark:scrollbar-track-dark-100 dark:scrollbar-thumb-dark-300 dark:hover:scrollbar-thumb-dark-300">
<div className="p-auto mx-auto flex h-full w-full max-w-[800px] flex-col"> <div className="p-auto mx-auto flex h-full w-full max-w-[800px] flex-col">
<div className="p-6 md:p-8"> <div className="p-6 md:p-8">
<div className="mb-8 flex w-full items-center justify-between md:mt-6"> <div className="mb-8 md:mt-4">
{!card && isLoading && ( {!card && isLoading && (
<div className="flex space-x-2"> <div className="flex space-x-2">
<div className="h-[2.3rem] w-[150px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" />
<div className="h-[2.3rem] w-[300px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" /> <div className="h-[2.3rem] w-[300px] animate-pulse rounded-[5px] bg-light-300 dark:bg-dark-300" />
</div> </div>
)} )}
{card && ( {card && (
<> <form
<Link onSubmit={handleSubmit(onSubmit)}
className="whitespace-nowrap font-bold leading-[2.3rem] tracking-tight text-light-900 dark:text-dark-900 sm:text-[1.2rem]" className="w-full space-y-6"
href={`${isTemplate ? "/templates" : "/boards"}/${board?.publicId}`} >
> <div>
{board?.name} <textarea
</Link> id="title"
<IoChevronForwardSharp {...register("title")}
size={18} onBlur={handleSubmit(onSubmit)}
className="mx-2 text-light-900 dark:text-dark-900" rows={1}
/> className="block w-full resize-none overflow-hidden border-0 bg-transparent p-0 py-0 font-bold leading-relaxed text-neutral-900 focus:ring-0 dark:text-dark-1000 sm:text-[1.2rem]"
<form onInput={(e) => {
onSubmit={handleSubmit(onSubmit)} const target = e.target as HTMLTextAreaElement;
className="w-full space-y-6" target.style.height = "auto";
> target.style.height = `${target.scrollHeight}px`;
<div> }}
<input />
type="text"
id="title"
{...register("title")}
onBlur={handleSubmit(onSubmit)}
className="block w-full border-0 bg-transparent p-0 py-0 font-bold tracking-tight text-neutral-900 focus:ring-0 dark:text-dark-1000 sm:text-[1.2rem]"
/>
</div>
</form>
<div className="flex">
<Dropdown />
</div> </div>
</> </form>
)} )}
{!card && !isLoading && ( {!card && !isLoading && (
<p className="block p-0 py-0 font-bold leading-[2.3rem] tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]"> <p className="block p-0 py-0 font-bold leading-[2.3rem] tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
@@ -286,6 +323,21 @@ export default function CardPage({ isTemplate }: { isTemplate?: boolean }) {
activeChecklistForm={activeChecklistForm} activeChecklistForm={activeChecklistForm}
setActiveChecklistForm={setActiveChecklistForm} setActiveChecklistForm={setActiveChecklistForm}
/> />
{!isTemplate && (
<>
{card?.attachments.length > 0 && (
<div className="mt-6">
<AttachmentThumbnails
attachments={card.attachments}
cardPublicId={cardId ?? ""}
/>
</div>
)}
<div className="mt-6">
<AttachmentUpload cardPublicId={cardId} />
</div>
</>
)}
<div className="border-t-[1px] border-light-300 pt-12 dark:border-dark-300"> <div className="border-t-[1px] border-light-300 pt-12 dark:border-dark-300">
<h2 className="text-md pb-4 font-medium text-light-1000 dark:text-dark-1000"> <h2 className="text-md pb-4 font-medium text-light-1000 dark:text-dark-1000">
{t`Activity`} {t`Activity`}

View File

@@ -9,6 +9,7 @@ import LabelIcon from "~/components/LabelIcon";
import { useModal } from "~/providers/modal"; import { useModal } from "~/providers/modal";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import ActivityList from "~/views/card/components/ActivityList"; import ActivityList from "~/views/card/components/ActivityList";
import { AttachmentThumbnails } from "~/views/card/components/AttachmentThumbnails";
import Checklists from "~/views/card/components/Checklists"; import Checklists from "~/views/card/components/Checklists";
export function CardModal({ export function CardModal({
@@ -126,11 +127,24 @@ export function CardModal({
<Editor <Editor
content={data.description} content={data.description}
readOnly readOnly
workspaceMembers={data?.list.board.workspace.members ?? []} workspaceMembers={
data?.list.board.workspace.members ?? []
}
/> />
</div> </div>
</div> </div>
)} )}
{data?.attachments &&
data.attachments.length > 0 &&
cardPublicId && (
<div className="mb-10 max-w-2xl">
<AttachmentThumbnails
attachments={data.attachments}
cardPublicId={cardPublicId}
isReadOnly
/>
</div>
)}
{data?.checklists && data.checklists.length > 0 && ( {data?.checklists && data.checklists.length > 0 && (
<Checklists <Checklists
checklists={data.checklists} checklists={data.checklists}

View File

@@ -44,6 +44,7 @@ export default function PublicBoardView() {
workspaceSlug: workspaceSlug ?? "", workspaceSlug: workspaceSlug ?? "",
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),
}, },
{ {
enabled: router.isReady && !!boardSlug, enabled: router.isReady && !!boardSlug,
@@ -130,6 +131,7 @@ export default function PublicBoardView() {
<Filters <Filters
labels={data.labels ?? []} labels={data.labels ?? []}
members={[]} members={[]}
lists={data.allLists ?? []}
isLoading={isLoading} isLoading={isLoading}
/> />
</div> </div>
@@ -187,6 +189,7 @@ export default function PublicBoardView() {
members={[]} members={[]}
description={card.description} description={card.description}
comments={card.comments ?? []} comments={card.comments ?? []}
attachments={card.attachments}
/> />
</Link> </Link>
))} ))}

View File

@@ -35,8 +35,10 @@ 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}
- PLUNK_API_KEY=${PLUNK_API_KEY}
- PLUNK_API_URL=${PLUNK_API_URL} # Notifications
- NOVU_API_KEY=${NOVU_API_KEY}
- DISCORD_WEBHOOK_URL=${DISCORD_WEBHOOK_URL}
# S3 storage # S3 storage
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID} - S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
@@ -46,6 +48,7 @@ services:
- S3_FORCE_PATH_STYLE=${S3_FORCE_PATH_STYLE} - S3_FORCE_PATH_STYLE=${S3_FORCE_PATH_STYLE}
- NEXT_PUBLIC_STORAGE_URL=${NEXT_PUBLIC_STORAGE_URL} - NEXT_PUBLIC_STORAGE_URL=${NEXT_PUBLIC_STORAGE_URL}
- NEXT_PUBLIC_AVATAR_BUCKET_NAME=${NEXT_PUBLIC_AVATAR_BUCKET_NAME} - NEXT_PUBLIC_AVATAR_BUCKET_NAME=${NEXT_PUBLIC_AVATAR_BUCKET_NAME}
- NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME=${NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME}
- NEXT_PUBLIC_STORAGE_DOMAIN=${NEXT_PUBLIC_STORAGE_DOMAIN} - NEXT_PUBLIC_STORAGE_DOMAIN=${NEXT_PUBLIC_STORAGE_DOMAIN}
# Auth config # Auth config

View File

@@ -36,6 +36,7 @@ services:
- S3_FORCE_PATH_STYLE=${S3_FORCE_PATH_STYLE} - S3_FORCE_PATH_STYLE=${S3_FORCE_PATH_STYLE}
- NEXT_PUBLIC_STORAGE_URL=${NEXT_PUBLIC_STORAGE_URL} - NEXT_PUBLIC_STORAGE_URL=${NEXT_PUBLIC_STORAGE_URL}
- NEXT_PUBLIC_AVATAR_BUCKET_NAME=${NEXT_PUBLIC_AVATAR_BUCKET_NAME} - NEXT_PUBLIC_AVATAR_BUCKET_NAME=${NEXT_PUBLIC_AVATAR_BUCKET_NAME}
- NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME=${NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME}
- NEXT_PUBLIC_STORAGE_DOMAIN=${NEXT_PUBLIC_STORAGE_DOMAIN} - NEXT_PUBLIC_STORAGE_DOMAIN=${NEXT_PUBLIC_STORAGE_DOMAIN}
# White label # White label

View File

@@ -35,6 +35,8 @@
"typecheck": "tsc --noEmit --emitDeclarationOnly false" "typecheck": "tsc --noEmit --emitDeclarationOnly false"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.802.0",
"@aws-sdk/s3-request-presigner": "^3.812.0",
"@kan/auth": "workspace:*", "@kan/auth": "workspace:*",
"@kan/db": "workspace:*", "@kan/db": "workspace:*",
"@kan/email": "workspace:^", "@kan/email": "workspace:^",

View File

@@ -1,3 +1,4 @@
import { attachmentRouter } from "./routers/attachment";
import { boardRouter } from "./routers/board"; 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";
@@ -12,6 +13,7 @@ import { workspaceRouter } from "./routers/workspace";
import { createTRPCRouter } from "./trpc"; import { createTRPCRouter } from "./trpc";
export const appRouter = createTRPCRouter({ export const appRouter = createTRPCRouter({
attachment: attachmentRouter,
board: boardRouter, board: boardRouter,
card: cardRouter, card: cardRouter,
checklist: checklistRouter, checklist: checklistRouter,

View File

@@ -0,0 +1,205 @@
import { TRPCError } from "@trpc/server";
import { z } from "zod";
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 workspaceRepo from "@kan/db/repository/workspace.repo";
import { generateUID } from "@kan/shared/utils";
import { createTRPCRouter, protectedProcedure } from "../trpc";
import { assertUserInWorkspace } from "../utils/auth";
import { generateUploadUrl } from "../utils/s3";
export const attachmentRouter = createTRPCRouter({
generateUploadUrl: protectedProcedure
.meta({
openapi: {
summary: "Generate presigned URL for attachment upload",
method: "POST",
path: "/cards/{cardPublicId}/attachments/upload-url",
description:
"Generates a presigned URL for uploading an attachment to S3",
tags: ["Attachments"],
protect: true,
},
})
.input(
z.object({
cardPublicId: z.string().min(12),
filename: z.string().min(1).max(255),
contentType: z.string(),
size: z
.number()
.positive()
.max(50 * 1024 * 1024), // 50MB max
}),
)
.output(z.object({ url: z.string(), key: z.string() }))
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
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",
});
await assertUserInWorkspace(ctx.db, userId, card.workspaceId);
// Get workspace publicId
const workspace = await workspaceRepo.getById(ctx.db, card.workspaceId);
if (!workspace)
throw new TRPCError({
message: `Workspace not found`,
code: "NOT_FOUND",
});
const bucket = process.env.NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME;
if (!bucket)
throw new TRPCError({
message: `Attachments bucket not configured`,
code: "INTERNAL_SERVER_ERROR",
});
// Sanitize filename
const sanitizedFilename = input.filename
.replace(/[^a-zA-Z0-9._-]/g, "_")
.substring(0, 200);
const s3Key = `${workspace.publicId}/${input.cardPublicId}/${generateUID()}-${sanitizedFilename}`;
const url = await generateUploadUrl(
bucket,
s3Key,
input.contentType,
3600, // 1 hour
);
return { url, key: s3Key };
}),
confirm: protectedProcedure
.meta({
openapi: {
summary: "Confirm attachment upload and save to database",
method: "POST",
path: "/cards/{cardPublicId}/attachments/confirm",
description:
"Confirms an attachment upload and saves the record to the database",
tags: ["Attachments"],
protect: true,
},
})
.input(
z.object({
cardPublicId: z.string().min(12),
s3Key: z.string(),
filename: z.string(),
originalFilename: z.string(),
contentType: z.string(),
size: z.number().positive(),
}),
)
.output(z.custom<Awaited<ReturnType<typeof cardAttachmentRepo.create>>>())
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
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",
});
await assertUserInWorkspace(ctx.db, userId, card.workspaceId);
const attachment = await cardAttachmentRepo.create(ctx.db, {
cardId: card.id,
filename: input.filename,
originalFilename: input.originalFilename,
contentType: input.contentType,
size: input.size,
s3Key: input.s3Key,
createdBy: userId,
});
await cardActivityRepo.create(ctx.db, {
type: "card.updated.attachment.added",
cardId: card.id,
createdBy: userId,
});
return attachment;
}),
delete: protectedProcedure
.meta({
openapi: {
summary: "Delete an attachment",
method: "DELETE",
path: "/attachments/{attachmentPublicId}",
description: "Soft deletes an attachment",
tags: ["Attachments"],
protect: true,
},
})
.input(z.object({ attachmentPublicId: z.string().min(12) }))
.output(z.object({ success: z.boolean() }))
.mutation(async ({ ctx, input }) => {
const userId = ctx.user?.id;
if (!userId)
throw new TRPCError({
message: `User not authenticated`,
code: "UNAUTHORIZED",
});
const attachment = await cardAttachmentRepo.getByPublicId(
ctx.db,
input.attachmentPublicId,
);
if (!attachment || attachment.deletedAt)
throw new TRPCError({
message: `Attachment with public ID ${input.attachmentPublicId} not found`,
code: "NOT_FOUND",
});
const workspaceId = attachment.card.list.board.workspaceId;
await assertUserInWorkspace(ctx.db, userId, workspaceId);
await cardAttachmentRepo.softDelete(ctx.db, {
attachmentId: attachment.id,
deletedAt: new Date(),
});
await cardActivityRepo.create(ctx.db, {
type: "card.updated.attachment.removed",
cardId: attachment.cardId,
createdBy: userId,
});
return { success: true };
}),
});

View File

@@ -78,6 +78,7 @@ export const boardRouter = createTRPCRouter({
boardPublicId: z.string().min(12), boardPublicId: z.string().min(12),
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(),
type: z.enum(["regular", "template"]).optional(), type: z.enum(["regular", "template"]).optional(),
}), }),
) )
@@ -110,6 +111,7 @@ export const boardRouter = createTRPCRouter({
{ {
members: input.members ?? [], members: input.members ?? [],
labels: input.labels ?? [], labels: input.labels ?? [],
lists: input.lists ?? [],
type: input.type, type: input.type,
}, },
); );
@@ -142,6 +144,7 @@ export const boardRouter = createTRPCRouter({
.regex(/^(?![-]+$)[a-zA-Z0-9-]+$/), .regex(/^(?![-]+$)[a-zA-Z0-9-]+$/),
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(),
}), }),
) )
.output(z.custom<Awaited<ReturnType<typeof boardRepo.getBySlug>>>()) .output(z.custom<Awaited<ReturnType<typeof boardRepo.getBySlug>>>())
@@ -164,6 +167,7 @@ export const boardRouter = createTRPCRouter({
{ {
members: input.members ?? [], members: input.members ?? [],
labels: input.labels ?? [], labels: input.labels ?? [],
lists: input.lists ?? [],
}, },
); );
@@ -234,6 +238,7 @@ export const boardRouter = createTRPCRouter({
{ {
members: [], members: [],
labels: [], labels: [],
lists: [],
type: sourceBoardInfo.type, type: sourceBoardInfo.type,
}, },
); );

View File

@@ -10,6 +10,7 @@ import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc"; import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
import { assertUserInWorkspace } from "../utils/auth"; import { assertUserInWorkspace } from "../utils/auth";
import { generateDownloadUrl } from "../utils/s3";
export const cardRouter = createTRPCRouter({ export const cardRouter = createTRPCRouter({
create: protectedProcedure create: protectedProcedure
@@ -574,7 +575,21 @@ export const cardRouter = createTRPCRouter({
.input(z.object({ cardPublicId: z.string().min(12) })) .input(z.object({ cardPublicId: z.string().min(12) }))
.output( .output(
z.custom< z.custom<
Awaited<ReturnType<typeof cardRepo.getWithListAndMembersByPublicId>> Omit<
NonNullable<
Awaited<ReturnType<typeof cardRepo.getWithListAndMembersByPublicId>>
>,
"attachments"
> & {
attachments: {
publicId: string;
contentType: string;
s3Key: string;
originalFilename: string | null;
size?: number | null;
url: string | null;
}[];
}
>(), >(),
) )
.query(async ({ ctx, input }) => { .query(async ({ ctx, input }) => {
@@ -612,7 +627,46 @@ export const cardRouter = createTRPCRouter({
code: "NOT_FOUND", code: "NOT_FOUND",
}); });
return result; // Generate URLs for all attachments
const bucket = process.env.NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME;
if (result.attachments && Array.isArray(result.attachments)) {
const attachments = result.attachments as {
publicId: string;
contentType: string;
s3Key: string;
originalFilename: string | null;
size?: number | null;
}[];
const attachmentsWithUrls = await Promise.all(
attachments.map(async (attachment) => {
const base = {
publicId: attachment.publicId,
contentType: attachment.contentType,
s3Key: attachment.s3Key,
originalFilename: attachment.originalFilename,
size: attachment.size,
};
if (!bucket || !attachment.s3Key) {
return { ...base, url: null };
}
try {
const url = await generateDownloadUrl(
bucket,
attachment.s3Key,
86400, // 24 hours expiration
);
return { ...base, url };
} catch {
// If URL generation fails, return attachment with url: null
return { ...base, url: null };
}
}),
);
return { ...result, attachments: attachmentsWithUrls };
}
return { ...result, attachments: [] };
}), }),
update: protectedProcedure update: protectedProcedure
.meta({ .meta({

View File

@@ -4,6 +4,7 @@ import { z } from "zod";
import * as boardRepo from "@kan/db/repository/board.repo"; import * as boardRepo from "@kan/db/repository/board.repo";
import * as cardRepo from "@kan/db/repository/card.repo"; import * as cardRepo from "@kan/db/repository/card.repo";
import * as cardActivityRepo from "@kan/db/repository/cardActivity.repo"; import * as cardActivityRepo from "@kan/db/repository/cardActivity.repo";
import * as checklistRepo from "@kan/db/repository/checklist.repo";
import * as importRepo from "@kan/db/repository/import.repo"; import * as importRepo from "@kan/db/repository/import.repo";
import * as integrationsRepo from "@kan/db/repository/integration.repo"; import * as integrationsRepo from "@kan/db/repository/integration.repo";
import * as labelRepo from "@kan/db/repository/label.repo"; import * as labelRepo from "@kan/db/repository/label.repo";
@@ -22,6 +23,7 @@ export interface TrelloBoard {
labels: TrelloLabel[]; labels: TrelloLabel[];
lists: TrelloList[]; lists: TrelloList[];
cards: TrelloCard[]; cards: TrelloCard[];
checklists: TrelloChecklist[];
} }
interface TrelloLabel { interface TrelloLabel {
@@ -34,12 +36,34 @@ interface TrelloList {
name: string; name: string;
} }
interface TrelloChecklist {
id: string;
idCard: string;
name: string;
checkItems: TrelloCheckItem[];
}
interface TrelloCheckItem {
id: string;
name: string;
state: "complete" | "incomplete";
pos: number;
}
interface TrelloCard { interface TrelloCard {
id: string; id: string;
name: string; name: string;
desc: string; desc: string;
idList: string; idList: string;
labels: TrelloLabel[]; labels: TrelloLabel[];
idChecklists: string[];
checkItemStates: TrelloCheckItemState[];
}
interface TrelloCheckItemState {
idChecklist: string;
idCheckItem: string;
state: "complete" | "incomplete";
} }
export const importRouter = createTRPCRouter({ export const importRouter = createTRPCRouter({
@@ -170,7 +194,7 @@ export const importRouter = createTRPCRouter({
for (const boardId of input.boardIds) { for (const boardId of input.boardIds) {
const response = await fetch( const response = await fetch(
`${urls.trello}/boards/${boardId}?key=${apiKey}&token=${integration.accessToken}&lists=open&cards=open&labels=all`, `${urls.trello}/boards/${boardId}?key=${apiKey}&token=${integration.accessToken}&lists=open&cards=open&labels=all&checklists=all&checkItemStates=all`,
); );
const data = (await response.json()) as TrelloBoard; const data = (await response.json()) as TrelloBoard;
@@ -194,6 +218,18 @@ export const importRouter = createTRPCRouter({
sourceId: label.id, sourceId: label.id,
name: label.name, name: label.name,
})), })),
checklists: data.checklists
.filter((checklist) => checklist.idCard === _card.id)
.map((_checklist) => ({
sourceId: _checklist.id,
name: _checklist.name,
items: _checklist.checkItems.map((_item) => ({
sourceId: _item.id,
title: _item.name,
completed: _item.state === "complete",
index: _item.pos,
})),
})),
})), })),
})), })),
}; };
@@ -289,6 +325,97 @@ export const importRouter = createTRPCRouter({
await cardActivityRepo.bulkCreate(ctx.db, activities); await cardActivityRepo.bulkCreate(ctx.db, activities);
} }
const checklistsToCreate: {
cardId: number;
name: string;
createdBy: string;
index: number;
sourceId: string;
items: {
sourceId: string;
title: string;
completed: boolean;
index: number;
}[];
}[] = [];
for (const card of list.cards) {
const _card = createdCards.find(
(c) => c.sourceId === card.sourceId,
);
if (!_card || !card.checklists.length) continue;
for (
let checklistIndex = 0;
checklistIndex < card.checklists.length;
checklistIndex++
) {
const checklist = card.checklists[checklistIndex];
if (!checklist) continue;
checklistsToCreate.push({
cardId: _card.id,
name: checklist.name,
createdBy: userId,
index: checklistIndex,
sourceId: checklist.sourceId,
items: checklist.items.map((item) => ({
sourceId: item.sourceId,
title: item.title,
completed: item.completed,
index: item.index,
})),
});
}
}
if (checklistsToCreate.length > 0) {
const newChecklists = await checklistRepo.bulkCreate(
ctx.db,
checklistsToCreate.map((checklist) => ({
cardId: checklist.cardId,
name: checklist.name,
createdBy: checklist.createdBy,
index: checklist.index,
})),
);
const itemsToCreate: {
checklistId: number;
title: string;
createdBy: string;
index: number;
completed: boolean;
}[] = [];
for (let i = 0; i < checklistsToCreate.length; i++) {
const checklistData = checklistsToCreate[i];
const newChecklist = newChecklists[i];
if (!newChecklist || !checklistData?.items.length) continue;
// NOTE: Sorting here to prevent checklist items being out of order
const sortedItems = [...checklistData.items].sort(
(a, b) => a.index - b.index,
);
for (const item of sortedItems) {
itemsToCreate.push({
checklistId: newChecklist.id,
title: item.title,
createdBy: userId,
index: item.index,
completed: item.completed,
});
}
}
if (itemsToCreate.length > 0) {
await checklistRepo.bulkCreateItems(ctx.db, itemsToCreate);
}
}
if (createdLabels.length && createdCards.length) { if (createdLabels.length && createdCards.length) {
const cardLabelRelations: { const cardLabelRelations: {
cardId: number; cardId: number;

View File

@@ -476,7 +476,7 @@ export const memberRouter = createTRPCRouter({
openapi: { openapi: {
summary: "Get invite information by code", summary: "Get invite information by code",
method: "GET", method: "GET",
path: "/workspaces/{workspacePublicId}/invites/{inviteCode}", path: "/invites/{inviteCode}",
description: "Get invite information by invite code", description: "Get invite information by invite code",
tags: ["Invites"], tags: ["Invites"],
protect: false, protect: false,
@@ -521,7 +521,7 @@ export const memberRouter = createTRPCRouter({
openapi: { openapi: {
summary: "Accept an invite link", summary: "Accept an invite link",
method: "POST", method: "POST",
path: "/workspaces/{workspacePublicId}/invites/accept", path: "/invites/accept",
description: "Accepts an invitation via invite link", description: "Accepts an invitation via invite link",
tags: ["Invites"], tags: ["Invites"],
protect: false, protect: false,

View File

@@ -0,0 +1,53 @@
import {
GetObjectCommand,
PutObjectCommand,
S3Client,
} from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
export function createS3Client() {
return new S3Client({
region: process.env.S3_REGION ?? "",
endpoint: process.env.S3_ENDPOINT ?? "",
forcePathStyle: process.env.S3_FORCE_PATH_STYLE === "true",
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY_ID ?? "",
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY ?? "",
},
});
}
export async function generateUploadUrl(
bucket: string,
key: string,
contentType: string,
expiresIn = 3600,
) {
const client = createS3Client();
return getSignedUrl(
client,
new PutObjectCommand({
Bucket: bucket,
Key: key,
ContentType: contentType,
// Don't set ACL for private files
}),
{ expiresIn },
);
}
export async function generateDownloadUrl(
bucket: string,
key: string,
expiresIn = 3600,
) {
const client = createS3Client();
return getSignedUrl(
client,
new GetObjectCommand({
Bucket: bucket,
Key: key,
}),
{ expiresIn },
);
}

View File

@@ -1,5 +1,8 @@
import type { Subscription } from "@better-auth/stripe";
import type Stripe from "stripe";
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3"; import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { stripe } from "@better-auth/stripe"; import { stripe } from "@better-auth/stripe";
import { ChatOrPushProviderEnum } from "@novu/api/models/components";
import { betterAuth } from "better-auth"; import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle"; import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { createAuthEndpoint, createAuthMiddleware } from "better-auth/api"; import { createAuthEndpoint, createAuthMiddleware } from "better-auth/api";
@@ -14,7 +17,7 @@ import * as subscriptionRepo from "@kan/db/repository/subscription.repo";
import * as userRepo from "@kan/db/repository/user.repo"; 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 { cloudMailerClient, sendEmail } from "@kan/email"; import { notificationClient, sendEmail } from "@kan/email";
import { createStripeClient } from "@kan/stripe"; import { createStripeClient } from "@kan/stripe";
export const configuredProviders = socialProviderList.reduce< export const configuredProviders = socialProviderList.reduce<
@@ -129,6 +132,11 @@ export const initAuth = (db: dbClient) => {
user: schema.users, user: schema.users,
}, },
}), }),
session: {
expiresIn: 60 * 60 * 24 * 30, // 30 days
updateAge: 60 * 60 * 24 * 2, // Update session expiry every 48 hours if user is active
freshAge: 0,
},
emailAndPassword: { emailAndPassword: {
enabled: env("NEXT_PUBLIC_ALLOW_CREDENTIALS")?.toLowerCase() === "true", enabled: env("NEXT_PUBLIC_ALLOW_CREDENTIALS")?.toLowerCase() === "true",
disableSignUp: disableSignUp:
@@ -173,19 +181,17 @@ export const initAuth = (db: dbClient) => {
freeTrial: { freeTrial: {
days: 14, days: 14,
onTrialStart: async (subscription) => { onTrialStart: async (subscription) => {
// Called when a trial starts await triggerWorkflow(db, "trial-start", subscription);
// @todo: send trial start email
// await sendTrialStartEmail(subscription.referenceId);
}, },
onTrialEnd: async ({ subscription }, request) => { onTrialEnd: async ({ subscription }) => {
// Called when a trial ends await triggerWorkflow(db, "trial-end", subscription);
// @todo: send trial end email
// await sendTrialEndEmail(user.email);
}, },
onTrialExpired: async (subscription) => { onTrialExpired: async (subscription) => {
// Called when a trial expires without conversion await triggerWorkflow(
// @todo: send trial expired email db,
// await sendTrialExpiredEmail(subscription.referenceId); "trial-expired",
subscription,
);
}, },
}, },
}, },
@@ -197,19 +203,17 @@ export const initAuth = (db: dbClient) => {
freeTrial: { freeTrial: {
days: 14, days: 14,
onTrialStart: async (subscription) => { onTrialStart: async (subscription) => {
// Called when a trial starts await triggerWorkflow(db, "trial-start", subscription);
// @todo: send trial start email
// await sendTrialStartEmail(subscription.referenceId);
}, },
onTrialEnd: async ({ subscription }, request) => { onTrialEnd: async ({ subscription }) => {
// Called when a trial ends await triggerWorkflow(db, "trial-end", subscription);
// @todo: send trial end email
// await sendTrialEndEmail(user.email);
}, },
onTrialExpired: async (subscription) => { onTrialExpired: async (subscription) => {
// Called when a trial expires without conversion await triggerWorkflow(
// @todo: send trial expired email db,
// await sendTrialExpiredEmail(subscription.referenceId); "trial-expired",
subscription,
);
}, },
}, },
}, },
@@ -343,17 +347,7 @@ export const initAuth = (db: dbClient) => {
return Promise.resolve(true); return Promise.resolve(true);
}, },
async after(user) { async after(user) {
if (cloudMailerClient) { let avatarKey = user.image;
await cloudMailerClient.events.track({
event: "user-signup",
email: user.email,
data: {
name: user.name,
userId: user.id,
},
});
}
if ( if (
user.image && user.image &&
!user.image.includes(process.env.NEXT_PUBLIC_STORAGE_DOMAIN!) !user.image.includes(process.env.NEXT_PUBLIC_STORAGE_DOMAIN!)
@@ -386,6 +380,9 @@ export const initAuth = (db: dbClient) => {
ACL: "public-read", ACL: "public-read",
}), }),
); );
avatarKey = key;
await userRepo.update(db, user.id, { await userRepo.update(db, user.id, {
image: key, image: key,
}); });
@@ -393,6 +390,51 @@ export const initAuth = (db: dbClient) => {
console.error(error); console.error(error);
} }
} }
if (notificationClient) {
try {
const [firstName, ...rest] = user.name
.split(" ")
.filter(Boolean);
const lastName = rest.length ? rest.join(" ") : undefined;
const avatarUrl = avatarKey
? `${env("NEXT_PUBLIC_STORAGE_URL")}/${env("NEXT_PUBLIC_AVATAR_BUCKET_NAME")}/${avatarKey}`
: undefined;
await notificationClient.trigger({
to: {
subscriberId: user.id,
firstName: firstName,
lastName: lastName,
email: user.email,
avatar: avatarUrl,
data: {
emailVerified: user.emailVerified,
stripeCustomerId: user.stripeCustomerId,
createdAt: user.createdAt,
updatedAt: user.updatedAt,
},
},
workflowId: "user-signup",
});
await notificationClient.subscribers.credentials.update(
{
providerId: ChatOrPushProviderEnum.Discord,
credentials: {
webhookUrl: process.env.DISCORD_WEBHOOK_URL!,
},
integrationIdentifier: "discord",
},
user.id,
);
} catch (error) {
console.error(
"Error adding user to notification client",
error,
);
}
}
}, },
}, },
}, },
@@ -430,3 +472,34 @@ export const initAuth = (db: dbClient) => {
}, },
}); });
}; };
async function triggerWorkflow(
db: dbClient,
workflowId: string,
subscription: Subscription,
cancellationDetails?: Stripe.Subscription.CancellationDetails | null,
) {
try {
if (!subscription.stripeCustomerId || !notificationClient) return;
const user = await userRepo.getByStripeCustomerId(
db,
subscription.stripeCustomerId,
);
if (!user || !notificationClient) return;
await notificationClient.trigger({
to: {
subscriberId: user.id,
},
payload: {
...subscription,
cancellationDetails,
},
workflowId,
});
} catch (error) {
console.error("Error triggering workflow", error);
}
}

View File

@@ -0,0 +1,29 @@
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.attachment.added' BEFORE 'card.archived';--> statement-breakpoint
ALTER TYPE "public"."card_activity_type" ADD VALUE 'card.updated.attachment.removed' BEFORE 'card.archived';--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "card_attachment" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
"cardId" bigint NOT NULL,
"filename" varchar(255) NOT NULL,
"originalFilename" varchar(255) NOT NULL,
"contentType" varchar(100) NOT NULL,
"size" bigint NOT NULL,
"s3Key" varchar(500) NOT NULL,
"createdBy" uuid,
"createdAt" timestamp DEFAULT now() NOT NULL,
"deletedAt" timestamp,
CONSTRAINT "card_attachment_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
ALTER TABLE "card_attachment" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_attachment" ADD CONSTRAINT "card_attachment_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "public"."card"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_attachment" ADD CONSTRAINT "card_attachment_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

File diff suppressed because it is too large Load Diff

View File

@@ -134,6 +134,13 @@
"when": 1760044396109, "when": 1760044396109,
"tag": "20251009211316_AddBoardSourceIdToCardActivity", "tag": "20251009211316_AddBoardSourceIdToCardActivity",
"breakpoints": true "breakpoints": true
},
{
"idx": 19,
"version": "7",
"when": 1762807463569,
"tag": "20251110204423_AddCardAttachments",
"breakpoints": true
} }
] ]
} }

View File

@@ -5,6 +5,7 @@ import type { BoardVisibilityStatus } from "@kan/db/schema";
import { import {
boards, boards,
cardActivities, cardActivities,
cardAttachments,
cards, cards,
cardsToLabels, cardsToLabels,
cardToWorkspaceMembers, cardToWorkspaceMembers,
@@ -70,6 +71,7 @@ export const getByPublicId = async (
filters: { filters: {
members: string[]; members: string[];
labels: string[]; labels: string[];
lists: string[];
type: "regular" | "template" | undefined; type: "regular" | "template" | undefined;
}, },
) => { ) => {
@@ -195,6 +197,13 @@ export const getByPublicId = async (
}, },
}, },
}, },
attachments: {
columns: {
publicId: true,
},
where: isNull(cardAttachments.deletedAt),
orderBy: asc(cardAttachments.createdAt),
},
checklists: { checklists: {
columns: { columns: {
publicId: true, publicId: true,
@@ -231,6 +240,19 @@ export const getByPublicId = async (
orderBy: [asc(cards.index)], orderBy: [asc(cards.index)],
}, },
}, },
where: and(
isNull(lists.deletedAt),
filters.lists.length > 0
? inArray(lists.publicId, filters.lists)
: undefined,
),
orderBy: [asc(lists.index)],
},
allLists: {
columns: {
publicId: true,
name: true,
},
where: isNull(lists.deletedAt), where: isNull(lists.deletedAt),
orderBy: [asc(lists.index)], orderBy: [asc(lists.index)],
}, },
@@ -268,6 +290,7 @@ export const getBySlug = async (
filters: { filters: {
members: string[]; members: string[];
labels: string[]; labels: string[];
lists: string[];
}, },
) => { ) => {
let cardIds: string[] = []; let cardIds: string[] = [];
@@ -343,6 +366,13 @@ export const getBySlug = async (
}, },
}, },
}, },
attachments: {
columns: {
publicId: true,
},
where: isNull(cardAttachments.deletedAt),
orderBy: asc(cardAttachments.createdAt),
},
comments: { comments: {
columns: { columns: {
publicId: true, publicId: true,
@@ -379,6 +409,19 @@ export const getBySlug = async (
orderBy: [asc(cards.index)], orderBy: [asc(cards.index)],
}, },
}, },
where: and(
isNull(lists.deletedAt),
filters.lists.length > 0
? inArray(lists.publicId, filters.lists)
: undefined,
),
orderBy: [asc(lists.index)],
},
allLists: {
columns: {
publicId: true,
name: true,
},
where: isNull(lists.deletedAt), where: isNull(lists.deletedAt),
orderBy: [asc(lists.index)], orderBy: [asc(lists.index)],
}, },

View File

@@ -3,6 +3,7 @@ import { and, asc, desc, eq, gt, inArray, isNull, sql } from "drizzle-orm";
import type { dbClient } from "@kan/db/client"; import type { dbClient } from "@kan/db/client";
import { import {
cardActivities, cardActivities,
cardAttachments,
cards, cards,
cardsToLabels, cardsToLabels,
cardToWorkspaceMembers, cardToWorkspaceMembers,
@@ -409,6 +410,17 @@ export const getWithListAndMembersByPublicId = async (
}, },
}, },
}, },
attachments: {
columns: {
publicId: true,
contentType: true,
s3Key: true,
originalFilename: true,
size: true,
},
where: isNull(cardAttachments.deletedAt),
orderBy: asc(cardAttachments.createdAt),
},
checklists: { checklists: {
columns: { columns: {
publicId: true, publicId: true,

View File

@@ -0,0 +1,99 @@
import { and, eq, isNull } from "drizzle-orm";
import type { dbClient } from "@kan/db/client";
import { cardAttachments } from "@kan/db/schema";
import { generateUID } from "@kan/shared/utils";
export const create = async (
db: dbClient,
attachmentInput: {
cardId: number;
filename: string;
originalFilename: string;
contentType: string;
size: number;
s3Key: string;
createdBy: string;
},
) => {
const [result] = await db
.insert(cardAttachments)
.values({
publicId: generateUID(),
cardId: attachmentInput.cardId,
filename: attachmentInput.filename,
originalFilename: attachmentInput.originalFilename,
contentType: attachmentInput.contentType,
size: attachmentInput.size,
s3Key: attachmentInput.s3Key,
createdBy: attachmentInput.createdBy,
})
.returning({
id: cardAttachments.id,
publicId: cardAttachments.publicId,
filename: cardAttachments.filename,
originalFilename: cardAttachments.originalFilename,
contentType: cardAttachments.contentType,
size: cardAttachments.size,
s3Key: cardAttachments.s3Key,
createdBy: cardAttachments.createdBy,
createdAt: cardAttachments.createdAt,
});
return result;
};
export const getByPublicId = (db: dbClient, publicId: string) => {
return db.query.cardAttachments.findFirst({
where: eq(cardAttachments.publicId, publicId),
with: {
card: {
columns: {
id: true,
publicId: true,
},
with: {
list: {
columns: {
id: true,
},
with: {
board: {
columns: {
id: true,
workspaceId: true,
},
},
},
},
},
},
},
});
};
export const getAllByCardId = (db: dbClient, cardId: number) => {
return db.query.cardAttachments.findMany({
where: and(
eq(cardAttachments.cardId, cardId),
isNull(cardAttachments.deletedAt),
),
orderBy: (attachments, { desc }) => [desc(attachments.createdAt)],
});
};
export const softDelete = async (
db: dbClient,
args: {
attachmentId: number;
deletedAt: Date;
},
) => {
const [result] = await db
.update(cardAttachments)
.set({ deletedAt: args.deletedAt })
.where(eq(cardAttachments.id, args.attachmentId))
.returning({ id: cardAttachments.id });
return result;
};

View File

@@ -46,6 +46,7 @@ export const createItem = async (
checklistId: number; checklistId: number;
title: string; title: string;
createdBy: string; createdBy: string;
completed?: boolean;
}, },
) => { ) => {
return db.transaction(async (tx) => { return db.transaction(async (tx) => {
@@ -65,7 +66,7 @@ export const createItem = async (
createdBy: checklistItemInput.createdBy, createdBy: checklistItemInput.createdBy,
checklistId: checklistItemInput.checklistId, checklistId: checklistItemInput.checklistId,
index: lastItem ? lastItem.index + 1 : 0, index: lastItem ? lastItem.index + 1 : 0,
completed: false, completed: checklistItemInput.completed ?? false,
}) })
.returning({ .returning({
id: checklistItems.id, id: checklistItems.id,
@@ -214,3 +215,129 @@ export const updateChecklistById = async (
.returning({ publicId: checklists.publicId, name: checklists.name }); .returning({ publicId: checklists.publicId, name: checklists.name });
return result; return result;
}; };
export const bulkCreate = async (
db: dbClient,
checklistInput: {
cardId: number;
name: string;
createdBy: string;
index: number;
}[],
) => {
if (checklistInput.length === 0) return [];
return db.transaction(async (tx) => {
const byCard = groupByKey(checklistInput, "cardId");
const allValuesToInsert: {
publicId: string;
cardId: number;
name: string;
createdBy: string;
index: number;
}[] = [];
for (const [cardId, items] of byCard.entries()) {
const last = await tx.query.checklists.findFirst({
columns: { index: true },
where: and(eq(checklists.cardId, cardId), isNull(checklists.deletedAt)),
orderBy: [desc(checklists.index)],
});
let nextIndex = last ? last.index + 1 : 0;
const sorted = [...items].sort((a, b) => a.index - b.index);
for (const item of sorted) {
allValuesToInsert.push({
publicId: generateUID(),
...item,
index: nextIndex++,
});
}
}
const inserted = await tx
.insert(checklists)
.values(allValuesToInsert)
.returning({ id: checklists.id, publicId: checklists.publicId });
return inserted;
});
};
export const bulkCreateItems = async (
db: dbClient,
checklistItemInput: {
checklistId: number;
title: string;
createdBy: string;
index: number;
completed: boolean;
}[],
) => {
if (checklistItemInput.length === 0) return [];
return db.transaction(async (tx) => {
const byChecklist = groupByKey(checklistItemInput, "checklistId");
const allValuesToInsert: {
publicId: string;
checklistId: number;
title: string;
createdBy: string;
index: number;
completed: boolean;
}[] = [];
for (const [checklistId, items] of byChecklist.entries()) {
const last = await tx.query.checklistItems.findFirst({
columns: { index: true },
where: and(
eq(checklistItems.checklistId, checklistId),
isNull(checklistItems.deletedAt),
),
orderBy: [desc(checklistItems.index)],
});
let nextIndex = last ? last.index + 1 : 0;
const sorted = [...items].sort((a, b) => a.index - b.index);
for (const item of sorted) {
allValuesToInsert.push({
publicId: generateUID(),
...item,
index: nextIndex++,
});
}
}
const inserted = await tx
.insert(checklistItems)
.values(allValuesToInsert)
.returning({
id: checklistItems.id,
publicId: checklistItems.publicId,
title: checklistItems.title,
completed: checklistItems.completed,
});
return inserted;
});
};
const groupByKey = <T extends Record<string, unknown>>(
items: T[],
keyField: keyof T,
): Map<number, T[]> => {
const grouped = new Map<number, T[]>();
for (const item of items) {
const key = item[keyField] as number;
const arr = grouped.get(key) ?? [];
arr.push(item);
grouped.set(key, arr);
}
return grouped;
};

View File

@@ -28,6 +28,15 @@ export const getById = async (db: dbClient, userId: string) => {
}); });
}; };
export const getByStripeCustomerId = async (
db: dbClient,
stripeCustomerId: string,
) => {
return await db.query.users.findFirst({
where: eq(users.stripeCustomerId, stripeCustomerId),
});
};
export const getByEmail = (db: dbClient, email: string) => { export const getByEmail = (db: dbClient, email: string) => {
return db.query.users.findFirst({ return db.query.users.findFirst({
columns: { columns: {

View File

@@ -73,6 +73,7 @@ export const boardsRelations = relations(boards, ({ one, many }) => ({
relationName: "boardCreatedByUser", relationName: "boardCreatedByUser",
}), }),
lists: many(lists), lists: many(lists),
allLists: many(lists),
labels: many(labels), labels: many(labels),
deletedBy: one(users, { deletedBy: one(users, {
fields: [boards.deletedBy], fields: [boards.deletedBy],

View File

@@ -42,6 +42,8 @@ export const activityTypes = [
"card.updated.checklist.item.completed", "card.updated.checklist.item.completed",
"card.updated.checklist.item.uncompleted", "card.updated.checklist.item.uncompleted",
"card.updated.checklist.item.deleted", "card.updated.checklist.item.deleted",
"card.updated.attachment.added",
"card.updated.attachment.removed",
"card.archived", "card.archived",
] as const; ] as const;
@@ -96,6 +98,7 @@ export const cardsRelations = relations(cards, ({ one, many }) => ({
comments: many(comments), comments: many(comments),
activities: many(cardActivities), activities: many(cardActivities),
checklists: many(checklists), checklists: many(checklists),
attachments: many(cardAttachments),
})); }));
export const cardActivities = pgTable("card_activity", { export const cardActivities = pgTable("card_activity", {
@@ -273,3 +276,37 @@ export const commentsRelations = relations(comments, ({ one }) => ({
relationName: "commentsDeletedByUser", relationName: "commentsDeletedByUser",
}), }),
})); }));
export const cardAttachments = pgTable("card_attachment", {
id: bigserial("id", { mode: "number" }).primaryKey(),
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
cardId: bigint("cardId", { mode: "number" })
.notNull()
.references(() => cards.id, { onDelete: "cascade" }),
filename: varchar("filename", { length: 255 }).notNull(),
originalFilename: varchar("originalFilename", { length: 255 }).notNull(),
contentType: varchar("contentType", { length: 100 }).notNull(),
size: bigint("size", { mode: "number" }).notNull(),
s3Key: varchar("s3Key", { length: 500 }).notNull(),
createdBy: uuid("createdBy").references(() => users.id, {
onDelete: "set null",
}),
createdAt: timestamp("createdAt").defaultNow().notNull(),
deletedAt: timestamp("deletedAt"),
}).enableRLS();
export const cardAttachmentsRelations = relations(
cardAttachments,
({ one }) => ({
card: one(cards, {
fields: [cardAttachments.cardId],
references: [cards.id],
relationName: "cardAttachmentsCard",
}),
createdBy: one(users, {
fields: [cardAttachments.createdBy],
references: [users.id],
relationName: "cardAttachmentsCreatedByUser",
}),
}),
);

View File

@@ -23,7 +23,7 @@
"typecheck": "tsc --noEmit --emitDeclarationOnly false" "typecheck": "tsc --noEmit --emitDeclarationOnly false"
}, },
"dependencies": { "dependencies": {
"@plunk/node": "^3.0.3", "@novu/api": "^3.11.0",
"@react-email/components": "^0.0.25", "@react-email/components": "^0.0.25",
"nodemailer": "^7.0.3", "nodemailer": "^7.0.3",
"react-email": "^3.0.1" "react-email": "^3.0.1"

View File

@@ -1,10 +0,0 @@
import Plunk from "@plunk/node";
export const cloudMailerClient =
process.env.NEXT_PUBLIC_KAN_ENV === "cloud" &&
process.env.PLUNK_API_KEY &&
process.env.PLUNK_API_URL
? new Plunk(process.env.PLUNK_API_KEY ?? "", {
baseUrl: process.env.PLUNK_API_URL,
})
: null;

View File

@@ -1,4 +1,4 @@
export const name = "email"; export const name = "email";
export { sendEmail } from "./sendEmail"; export { sendEmail } from "./sendEmail";
export { cloudMailerClient } from "./cloudMailerClient"; export { notificationClient } from "./notificationClient";

View File

@@ -0,0 +1,6 @@
import { Novu } from "@novu/api";
export const notificationClient =
process.env.NEXT_PUBLIC_KAN_ENV === "cloud" && process.env.NOVU_API_KEY
? new Novu({ secretKey: process.env.NOVU_API_KEY })
: null;

View File

@@ -1,7 +1,6 @@
import { render } from "@react-email/render"; import { render } from "@react-email/render";
import nodemailer from "nodemailer"; import nodemailer from "nodemailer";
import { cloudMailerClient } from "./cloudMailerClient";
import JoinWorkspaceTemplate from "./templates/join-workspace"; import JoinWorkspaceTemplate from "./templates/join-workspace";
import MagicLinkTemplate from "./templates/magic-link"; import MagicLinkTemplate from "./templates/magic-link";
import ResetPasswordTemplate from "./templates/reset-password"; import ResetPasswordTemplate from "./templates/reset-password";
@@ -45,15 +44,6 @@ export const sendEmail = async (
html, html,
}; };
// if (cloudMailerClient) {
// const response = await cloudMailerClient.emails.send({
// ...options,
// body: html,
// });
// return response;
// }
const response = await transporter.sendMail(options); const response = await transporter.sendMail(options);
if (!response.accepted.length) { if (!response.accepted.length) {

View File

@@ -71,4 +71,13 @@ export const updateSubscriptionSeats = async (
return updatedSubscription; return updatedSubscription;
}; };
export const getCancellationDetails = async (
stripeSubscriptionId: string,
): Promise<Stripe.Subscription.CancellationDetails | null> => {
const stripe = createStripeClient();
const stripeSubscription =
await stripe.subscriptions.retrieve(stripeSubscriptionId);
return stripeSubscription.cancellation_details ?? null;
};
export { createStripeClient }; export { createStripeClient };

67
pnpm-lock.yaml generated
View File

@@ -223,6 +223,9 @@ importers:
tippy.js: tippy.js:
specifier: ^6.3.7 specifier: ^6.3.7
version: 6.3.7 version: 6.3.7
tiptap-markdown:
specifier: ^0.8
version: 0.8.10(@tiptap/core@2.26.1(@tiptap/pm@2.26.1))
zod: zod:
specifier: 'catalog:' specifier: 'catalog:'
version: 3.25.76 version: 3.25.76
@@ -290,6 +293,12 @@ importers:
packages/api: packages/api:
dependencies: dependencies:
'@aws-sdk/client-s3':
specifier: ^3.802.0
version: 3.879.0
'@aws-sdk/s3-request-presigner':
specifier: ^3.812.0
version: 3.879.0
'@kan/auth': '@kan/auth':
specifier: workspace:* specifier: workspace:*
version: link:../auth version: link:../auth
@@ -431,9 +440,9 @@ importers:
packages/email: packages/email:
dependencies: dependencies:
'@plunk/node': '@novu/api':
specifier: ^3.0.3 specifier: ^3.11.0
version: 3.0.3 version: 3.11.0
'@react-email/components': '@react-email/components':
specifier: ^0.0.25 specifier: ^0.0.25
version: 0.0.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1) version: 0.0.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -2674,6 +2683,9 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
'@novu/api@3.11.0':
resolution: {integrity: sha512-8u0mB5VThL7MhdxoN0UoA4CS9eu2k3Xa6iulauMhCHENuJNxUNuirJWq5t8jDoH4bFTQTfMN0VRkC0qodKR2qA==}
'@octokit/auth-token@3.0.4': '@octokit/auth-token@3.0.4':
resolution: {integrity: sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==} resolution: {integrity: sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
@@ -2753,9 +2765,6 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'} engines: {node: '>=14'}
'@plunk/node@3.0.3':
resolution: {integrity: sha512-f3NT418/EdLjebQ4arAwR64cnz7d5H7i1CeKh8+B0cVBrwzHvF+Q+QkhutF+FAp49yuI/BYc71qQH+RFc2fxxQ==}
'@popperjs/core@2.11.8': '@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
@@ -3575,9 +3584,15 @@ packages:
'@types/katex@0.16.7': '@types/katex@0.16.7':
resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
'@types/linkify-it@3.0.5':
resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==}
'@types/linkify-it@5.0.0': '@types/linkify-it@5.0.0':
resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
'@types/markdown-it@13.0.9':
resolution: {integrity: sha512-1XPwR0+MgXLWfTn9gCsZ55AHOKW1WN+P9vr0PaQh5aerR9LLQXUbjfEAFhjmEmyoYFWAyuN2Mqkn40MZ4ukjBw==}
'@types/markdown-it@14.1.2': '@types/markdown-it@14.1.2':
resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
@@ -3587,6 +3602,9 @@ packages:
'@types/mdast@4.0.4': '@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
'@types/mdurl@1.0.5':
resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==}
'@types/mdurl@2.0.0': '@types/mdurl@2.0.0':
resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
@@ -5730,6 +5748,9 @@ packages:
make-error@1.3.6: make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
markdown-it-task-lists@2.1.1:
resolution: {integrity: sha512-TxFAc76Jnhb2OUu+n3yz9RMu4CwGfaT788br6HhEDlvWfdeJcLUsxk1Hgw2yJio0OXsxv7pyIPmvECY7bMbluA==}
markdown-it@14.1.0: markdown-it@14.1.0:
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true hasBin: true
@@ -7411,6 +7432,11 @@ packages:
tippy.js@6.3.7: tippy.js@6.3.7:
resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==}
tiptap-markdown@0.8.10:
resolution: {integrity: sha512-iDVkR2BjAqkTDtFX0h94yVvE2AihCXlF0Q7RIXSJPRSR5I0PA1TMuAg6FHFpmqTn4tPxJ0by0CK7PUMlnFLGEQ==}
peerDependencies:
'@tiptap/core': ^2.0.3
title-case@2.1.1: title-case@2.1.1:
resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==}
@@ -10200,6 +10226,10 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5 '@nodelib/fs.scandir': 2.1.5
fastq: 1.19.1 fastq: 1.19.1
'@novu/api@3.11.0':
dependencies:
zod: 3.25.76
'@octokit/auth-token@3.0.4': {} '@octokit/auth-token@3.0.4': {}
'@octokit/core@4.2.4': '@octokit/core@4.2.4':
@@ -10319,10 +10349,6 @@ snapshots:
'@pkgjs/parseargs@0.11.0': '@pkgjs/parseargs@0.11.0':
optional: true optional: true
'@plunk/node@3.0.3':
dependencies:
tslib: 2.8.1
'@popperjs/core@2.11.8': {} '@popperjs/core@2.11.8': {}
'@posthog/core@1.0.2': {} '@posthog/core@1.0.2': {}
@@ -11321,8 +11347,15 @@ snapshots:
'@types/katex@0.16.7': {} '@types/katex@0.16.7': {}
'@types/linkify-it@3.0.5': {}
'@types/linkify-it@5.0.0': {} '@types/linkify-it@5.0.0': {}
'@types/markdown-it@13.0.9':
dependencies:
'@types/linkify-it': 3.0.5
'@types/mdurl': 1.0.5
'@types/markdown-it@14.1.2': '@types/markdown-it@14.1.2':
dependencies: dependencies:
'@types/linkify-it': 5.0.0 '@types/linkify-it': 5.0.0
@@ -11336,6 +11369,8 @@ snapshots:
dependencies: dependencies:
'@types/unist': 3.0.3 '@types/unist': 3.0.3
'@types/mdurl@1.0.5': {}
'@types/mdurl@2.0.0': {} '@types/mdurl@2.0.0': {}
'@types/ms@2.1.0': {} '@types/ms@2.1.0': {}
@@ -13777,6 +13812,8 @@ snapshots:
make-error@1.3.6: {} make-error@1.3.6: {}
markdown-it-task-lists@2.1.1: {}
markdown-it@14.1.0: markdown-it@14.1.0:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
@@ -16085,6 +16122,14 @@ snapshots:
dependencies: dependencies:
'@popperjs/core': 2.11.8 '@popperjs/core': 2.11.8
tiptap-markdown@0.8.10(@tiptap/core@2.26.1(@tiptap/pm@2.26.1)):
dependencies:
'@tiptap/core': 2.26.1(@tiptap/pm@2.26.1)
'@types/markdown-it': 13.0.9
markdown-it: 14.1.0
markdown-it-task-lists: 2.1.1
prosemirror-markdown: 1.13.2
title-case@2.1.1: title-case@2.1.1:
dependencies: dependencies:
no-case: 2.3.2 no-case: 2.3.2
@@ -16466,7 +16511,7 @@ snapshots:
'@webassemblyjs/wasm-parser': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1
acorn: 8.15.0 acorn: 8.15.0
acorn-import-phases: 1.0.4(acorn@8.15.0) acorn-import-phases: 1.0.4(acorn@8.15.0)
browserslist: 4.25.4 browserslist: 4.27.0
chrome-trace-event: 1.0.4 chrome-trace-event: 1.0.4
enhanced-resolve: 5.18.3 enhanced-resolve: 5.18.3
es-module-lexer: 1.7.0 es-module-lexer: 1.7.0

View File

@@ -99,6 +99,7 @@
"NEXT_PUBLIC_KAN_ENV", "NEXT_PUBLIC_KAN_ENV",
"NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY", "NEXT_PUBLIC_WHITE_LABEL_HIDE_POWERED_BY",
"STRIPE_SECRET_KEY", "STRIPE_SECRET_KEY",
"DISCORD_WEBHOOK_URL",
"STRIPE_WEBHOOK_SECRET", "STRIPE_WEBHOOK_SECRET",
"STRIPE_WEBHOOK_SECRET_LEGACY", "STRIPE_WEBHOOK_SECRET_LEGACY",
"STRIPE_PRO_PLAN_MONTHLY_PRICE_ID", "STRIPE_PRO_PLAN_MONTHLY_PRICE_ID",
@@ -108,6 +109,7 @@
"NEXT_PUBLIC_STORAGE_DOMAIN", "NEXT_PUBLIC_STORAGE_DOMAIN",
"NEXT_PUBLIC_STORAGE_URL", "NEXT_PUBLIC_STORAGE_URL",
"NEXT_PUBLIC_AVATAR_BUCKET_NAME", "NEXT_PUBLIC_AVATAR_BUCKET_NAME",
"NEXT_PUBLIC_ATTACHMENTS_BUCKET_NAME",
"NEXT_PUBLIC_ALLOW_CREDENTIALS", "NEXT_PUBLIC_ALLOW_CREDENTIALS",
"NEXT_PUBLIC_DISABLE_SIGN_UP", "NEXT_PUBLIC_DISABLE_SIGN_UP",
"NEXT_PUBLIC_USE_STANDALONE_OUTPUT", "NEXT_PUBLIC_USE_STANDALONE_OUTPUT",
@@ -119,8 +121,7 @@
"PORT", "PORT",
"BETTER_AUTH_SECRET", "BETTER_AUTH_SECRET",
"BETTER_AUTH_TRUSTED_ORIGINS", "BETTER_AUTH_TRUSTED_ORIGINS",
"PLUNK_API_KEY", "NOVU_API_KEY"
"PLUNK_API_URL"
], ],
"globalPassThroughEnv": [ "globalPassThroughEnv": [
"NODE_ENV", "NODE_ENV",