Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1929d5c7d4 | ||
|
|
8ae54cd7cc | ||
|
|
bb13009e64 | ||
|
|
648dd862f5 | ||
|
|
8eccd3658e | ||
|
|
ed65b2a3ab | ||
|
|
0930121680 | ||
|
|
1068873f27 | ||
|
|
a1ece0be63 | ||
|
|
c550b4c8fc | ||
|
|
e95650637c | ||
|
|
0f3e0a1554 | ||
|
|
761dfac033 | ||
|
|
9fda4acc5b | ||
|
|
0470708aad | ||
|
|
bee392ba1a | ||
|
|
448f57442b | ||
|
|
856b090b4b | ||
|
|
b99661a411 | ||
|
|
d96a26eb3c | ||
|
|
9d08f5c7c8 | ||
|
|
4fe5f6ca6f | ||
|
|
af505935bd | ||
|
|
4a30f60622 | ||
|
|
24ed04e6c7 | ||
|
|
bed3595314 | ||
|
|
74671263bf | ||
|
|
bdc5e9c7e9 | ||
|
|
8fa1c70a97 | ||
|
|
1343c8fa8d | ||
|
|
5c0f9510a1 | ||
|
|
b2801170fa | ||
|
|
6ac19e8307 | ||
|
|
344241cfbf | ||
|
|
66ebf18fa9 | ||
|
|
e6d6f3317e | ||
|
|
55f66e6bcd | ||
|
|
22e2b0a6a9 | ||
|
|
e24f3828cb | ||
|
|
70f5bdc499 | ||
|
|
8731a39c3c | ||
|
|
e2d9e75475 | ||
|
|
55c7707b94 | ||
|
|
98944d4815 | ||
|
|
faba25acbd | ||
|
|
aab5ee344c | ||
|
|
6880f88dbe | ||
|
|
9177fe86dc | ||
|
|
bf3f8acbc0 | ||
|
|
b4fa9826f2 | ||
|
|
955de3133c | ||
|
|
faac3d0f57 | ||
|
|
3fb1ede770 | ||
|
|
53224886e3 | ||
|
|
e513180d7e | ||
|
|
3116d6df1a | ||
|
|
4284a4d16d | ||
|
|
eadca3b2c0 | ||
|
|
68125af29f | ||
|
|
d436e628fe | ||
|
|
c5483c81de | ||
|
|
9db4a04cd9 | ||
|
|
8943e8c2f6 | ||
|
|
f17fa55426 | ||
|
|
9ff83075d6 | ||
|
|
6b6043afdc | ||
|
|
fd9162e70f | ||
|
|
8331059b7c | ||
|
|
f0992b4914 | ||
|
|
e081a4cfc2 | ||
|
|
895b3ca7c9 | ||
|
|
4d30264950 | ||
|
|
3a352a94f6 | ||
|
|
8623175612 | ||
|
|
ea531777c4 | ||
|
|
2639ef7e13 | ||
|
|
0e76a19c96 | ||
|
|
3ec9eb377d | ||
|
|
44b7000509 | ||
|
|
251307f1e6 | ||
|
|
75e638ec4d | ||
|
|
443ccdd6c0 | ||
|
|
dbf11cc04b | ||
|
|
a5c9729f5f | ||
|
|
a6e2983a22 | ||
|
|
a21f0c46c7 | ||
|
|
ed4a81e852 | ||
|
|
9231218350 | ||
|
|
7d1ea4ee2b | ||
|
|
0c68e51930 | ||
|
|
8e565dc610 | ||
|
|
5b47844fa1 | ||
|
|
0d01d3246a | ||
|
|
bb31c4ba14 | ||
|
|
d9a7952467 | ||
|
|
208dcbbda3 | ||
|
|
ff4494d395 | ||
|
|
db4b32119e | ||
|
|
bfef5b1877 | ||
|
|
91962cc90b | ||
|
|
7a71a5ddd4 | ||
|
|
ca47a589ba | ||
|
|
a33dbd8922 | ||
|
|
aaab4ca741 | ||
|
|
6aadf7429d | ||
|
|
748307bc91 | ||
|
|
559389a319 | ||
|
|
a9140b6a76 | ||
|
|
8f50e873c9 | ||
|
|
9b28b7f78a | ||
|
|
4417097f97 | ||
|
|
93fc036d2c |
@@ -5,6 +5,7 @@
|
||||
# - SHARED
|
||||
# - NEXTAUTH
|
||||
# - E-MAIL SETTINGS
|
||||
# - ORGANIZATIONS
|
||||
|
||||
# - LICENSE (DEPRECATED) ************************************************************************************
|
||||
# https://github.com/calcom/cal.com/blob/main/LICENSE
|
||||
@@ -22,6 +23,8 @@ CALCOM_LICENSE_KEY=
|
||||
|
||||
# - DATABASE ************************************************************************************************
|
||||
DATABASE_URL="postgresql://postgres:@localhost:5450/calendso"
|
||||
UPSTASH_REDIS_REST_URL=
|
||||
UPSTASH_REDIS_REST_TOKEN=
|
||||
|
||||
# Uncomment to enable a dedicated connection pool for Prisma using Prisma Data Proxy
|
||||
# Cold boots will be faster and you'll be able to scale your DB independently of your app.
|
||||
@@ -32,6 +35,8 @@ PRISMA_GENERATE_DATAPROXY=
|
||||
# ***********************************************************************************************************
|
||||
|
||||
# - SHARED **************************************************************************************************
|
||||
# Set this to http://app.cal.local:3000 if you want to enable organizations, and
|
||||
# check variable ORGANIZATIONS_ENABLED at the bottom of this file
|
||||
NEXT_PUBLIC_WEBAPP_URL='http://localhost:3000'
|
||||
# Change to 'http://localhost:3001' if running the website simultaneously
|
||||
NEXT_PUBLIC_WEBSITE_URL='http://localhost:3000'
|
||||
@@ -183,3 +188,26 @@ CSP_POLICY=
|
||||
EDGE_CONFIG=
|
||||
|
||||
NEXT_PUBLIC_MINUTES_TO_BOOK=5 # Minutes
|
||||
|
||||
# - ORGANIZATIONS *******************************************************************************************
|
||||
# Enable Organizations non-prod domain setup, works in combination with organizations feature flag
|
||||
# This is mainly needed locally, because for orgs to work a full domain name needs to point
|
||||
# to the app, i.e. app.cal.local instead of using localhost, which is very disruptive
|
||||
#
|
||||
# This variable should only be set to 1 or true if you are in a non-prod environment and you want to
|
||||
# use organizations
|
||||
ORGANIZATIONS_ENABLED=
|
||||
|
||||
# Vercel Config to create subdomains for organizations
|
||||
# Get it from https://vercel.com/<TEAM_OR_USER_NAME>/<PROJECT_SLUG>/settings
|
||||
PROJECT_ID_VERCEL=
|
||||
# Get it from: https://vercel.com/teams/<TEAM_SLUG>/settings
|
||||
TEAM_ID_VERCEL=
|
||||
# Get it from: https://vercel.com/account/tokens
|
||||
AUTH_BEARER_TOKEN_VERCEL=
|
||||
|
||||
#Enables New booker for Embed only
|
||||
NEW_BOOKER_ENABLED_FOR_EMBED=0
|
||||
|
||||
#Enables New booker for All but Embed requests
|
||||
NEW_BOOKER_ENABLED_FOR_NON_EMBED=0
|
||||
@@ -40,6 +40,14 @@ runs:
|
||||
restore-keys: |
|
||||
yarn-download-cache-
|
||||
|
||||
# Invalidated on yarn.lock changes
|
||||
- name: Restore node_modules
|
||||
id: yarn-nm-cache
|
||||
uses: buildjet/cache@v3
|
||||
with:
|
||||
path: "**/node_modules/"
|
||||
key: ${{ runner.os }}-yarn-nm-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }}
|
||||
|
||||
# Invalidated on yarn.lock changes
|
||||
- name: Restore yarn install state
|
||||
id: yarn-install-state-cache
|
||||
@@ -58,5 +66,6 @@ runs:
|
||||
YARN_ENABLE_IMMUTABLE_INSTALLS: "false" # So it doesn't try to remove our private submodule deps
|
||||
YARN_ENABLE_GLOBAL_CACHE: "false" # Use local cache folder to keep downloaded archives
|
||||
YARN_INSTALL_STATE_PATH: .yarn/ci-cache/install-state.gz # Very small speedup when lock does not change
|
||||
YARN_NM_MODE: "hardlinks-local" # Reduce node_modules size
|
||||
# Other environment variables
|
||||
HUSKY: "0" # By default do not run HUSKY install
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
name: Add PRs to project Reviewing PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
add-PR-to-project:
|
||||
name: Add PRs to project Reviewing PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@v0.1.0
|
||||
with:
|
||||
project-url: https://github.com/orgs/calcom/projects/11
|
||||
github-token: ${{ secrets.GH_ACCESS_TOKEN }}
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/dangerous-git-checkout
|
||||
- uses: ./.github/actions/yarn-install
|
||||
- name: Save Code Linting Reports
|
||||
- name: Run Linting with Reports
|
||||
run: yarn lint:report
|
||||
continue-on-error: true
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
name: Detect changes
|
||||
runs-on: buildjet-4vcpu-ubuntu-2204
|
||||
permissions:
|
||||
pull-requests: read
|
||||
|
||||
@@ -201,6 +201,14 @@ echo 'NEXT_PUBLIC_DEBUG=1' >> .env
|
||||
1. Set a 32 character random string in your `.env` file for the `CALENDSO_ENCRYPTION_KEY` (You can use a command like `openssl rand -base64 24` to generate one).
|
||||
1. Set up the database using the Prisma schema (found in `packages/prisma/schema.prisma`)
|
||||
|
||||
In a development environment, run:
|
||||
|
||||
```sh
|
||||
yarn workspace @calcom/prisma db-migrate
|
||||
```
|
||||
|
||||
In a production environment, run:
|
||||
|
||||
```sh
|
||||
yarn workspace @calcom/prisma db-deploy
|
||||
```
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getUserAvailability } from "@calcom/core/getUserAvailability";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import { availabilityUserSelect } from "@calcom/prisma";
|
||||
@@ -119,8 +120,10 @@ const availabilitySchema = z
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { prisma, isAdmin, userId: reqUserId } = req;
|
||||
const { username, userId, eventTypeId, dateTo, dateFrom, teamId } = availabilitySchema.parse(req.query);
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(req.headers.host ?? "");
|
||||
if (!teamId)
|
||||
return getUserAvailability({
|
||||
orgSlug: isValidOrgDomain ? currentOrgDomain || undefined : undefined,
|
||||
username,
|
||||
dateFrom,
|
||||
dateTo,
|
||||
|
||||
@@ -50,6 +50,6 @@
|
||||
"storybook-react-i18next": "^1.1.2",
|
||||
"tailwindcss": "^3.2.1",
|
||||
"typescript": "^4.9.4",
|
||||
"vite": "^2.9.15"
|
||||
"vite": "^4.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +235,7 @@
|
||||
*/
|
||||
--cal-brand:#111827;
|
||||
--cal-brand-emphasis:#101010;
|
||||
--cal-brand-text: white;
|
||||
}
|
||||
.dark {
|
||||
/* background */
|
||||
@@ -274,7 +275,8 @@
|
||||
/* Brand shenanigans
|
||||
-> These will be computed for the users theme at runtime.
|
||||
*/
|
||||
--cal-brand: #111827;
|
||||
--cal-brand-emphasis: #101010;
|
||||
--cal-brand: white;
|
||||
--cal-brand-emphasis: #e1e1e1;
|
||||
--cal-brand-text: black;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,11 @@ import { createRef, forwardRef, useRef, useState } from "react";
|
||||
import type { ControlProps } from "react-select";
|
||||
import { components } from "react-select";
|
||||
|
||||
import type { BookerLayout } from "@calcom/features/bookings/Booker/types";
|
||||
import { useFlagMap } from "@calcom/features/flags/context/provider";
|
||||
import { APP_NAME, EMBED_LIB_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { BookerLayouts } from "@calcom/prisma/zod-utils";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
@@ -41,12 +44,13 @@ type PreviewState = {
|
||||
height: string;
|
||||
};
|
||||
theme: Theme;
|
||||
floatingPopup: Record<string, string>;
|
||||
floatingPopup: Record<string, string | boolean | undefined>;
|
||||
elementClick: Record<string, string>;
|
||||
palette: {
|
||||
brandColor: string;
|
||||
};
|
||||
hideEventTypeDetails: boolean;
|
||||
layout: BookerLayouts;
|
||||
};
|
||||
const queryParamsForDialog = ["embedType", "embedTabName", "embedUrl"];
|
||||
|
||||
@@ -129,11 +133,13 @@ const getEmbedUIInstructionString = ({
|
||||
theme,
|
||||
brandColor,
|
||||
hideEventTypeDetails,
|
||||
layout,
|
||||
}: {
|
||||
apiName: string;
|
||||
theme?: string;
|
||||
brandColor: string;
|
||||
hideEventTypeDetails: boolean;
|
||||
layout?: string;
|
||||
}) => {
|
||||
theme = theme !== "auto" ? theme : undefined;
|
||||
return getInstructionString({
|
||||
@@ -147,6 +153,7 @@ const getEmbedUIInstructionString = ({
|
||||
},
|
||||
},
|
||||
hideEventTypeDetails: hideEventTypeDetails,
|
||||
layout,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -260,6 +267,7 @@ const getEmbedTypeSpecificString = ({
|
||||
theme: PreviewState["theme"];
|
||||
brandColor: string;
|
||||
hideEventTypeDetails: boolean;
|
||||
layout?: BookerLayout;
|
||||
};
|
||||
if (embedFramework === "react") {
|
||||
uiInstructionStringArg = {
|
||||
@@ -267,6 +275,7 @@ const getEmbedTypeSpecificString = ({
|
||||
theme: previewState.theme,
|
||||
brandColor: previewState.palette.brandColor,
|
||||
hideEventTypeDetails: previewState.hideEventTypeDetails,
|
||||
layout: previewState.layout,
|
||||
};
|
||||
} else {
|
||||
uiInstructionStringArg = {
|
||||
@@ -274,6 +283,7 @@ const getEmbedTypeSpecificString = ({
|
||||
theme: previewState.theme,
|
||||
brandColor: previewState.palette.brandColor,
|
||||
hideEventTypeDetails: previewState.hideEventTypeDetails,
|
||||
layout: previewState.layout,
|
||||
};
|
||||
}
|
||||
if (!frameworkCodes[embedType]) {
|
||||
@@ -626,6 +636,7 @@ const ThemeSelectControl = ({ children, ...props }: ControlProps<{ value: Theme;
|
||||
const ChooseEmbedTypesDialogContent = () => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<DialogContent className="rounded-lg p-10" type="creation" size="lg">
|
||||
<div className="mb-2">
|
||||
@@ -671,6 +682,8 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
const router = useRouter();
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
const dialogContentRef = useRef<HTMLDivElement>(null);
|
||||
const flags = useFlagMap();
|
||||
const isBookerLayoutsEnabled = flags["booker-layouts"] === true;
|
||||
|
||||
const s = (href: string) => {
|
||||
const searchParams = new URLSearchParams(router.asPath.split("?")[1] || "");
|
||||
@@ -691,7 +704,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
|
||||
const [isEmbedCustomizationOpen, setIsEmbedCustomizationOpen] = useState(true);
|
||||
const [isBookingCustomizationOpen, setIsBookingCustomizationOpen] = useState(true);
|
||||
const [previewState, setPreviewState] = useState({
|
||||
const [previewState, setPreviewState] = useState<PreviewState>({
|
||||
inline: {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
@@ -703,6 +716,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
palette: {
|
||||
brandColor: "#000000",
|
||||
},
|
||||
layout: BookerLayouts.MONTH_VIEW,
|
||||
});
|
||||
|
||||
const close = () => {
|
||||
@@ -765,6 +779,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
arg: {
|
||||
theme: previewState.theme,
|
||||
hideEventTypeDetails: previewState.hideEventTypeDetails,
|
||||
layout: previewState.layout,
|
||||
styles: {
|
||||
branding: {
|
||||
...previewState.palette,
|
||||
@@ -798,6 +813,12 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
{ value: Theme.light, label: "Light Theme" },
|
||||
];
|
||||
|
||||
const layoutOptions = [
|
||||
{ value: BookerLayouts.MONTH_VIEW, label: t("bookerlayout_month_view") },
|
||||
{ value: BookerLayouts.WEEK_VIEW, label: t("bookerlayout_week_view") },
|
||||
{ value: BookerLayouts.COLUMN_VIEW, label: t("bookerlayout_column_view") },
|
||||
];
|
||||
|
||||
const FloatingPopupPositionOptions = [
|
||||
{
|
||||
value: "bottom-right",
|
||||
@@ -1070,6 +1091,27 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
</div>
|
||||
</Label>
|
||||
))}
|
||||
{isBookerLayoutsEnabled && (
|
||||
<Label className="mb-6">
|
||||
<div className="mb-2">{t("layout")}</div>
|
||||
<Select
|
||||
className="w-full"
|
||||
defaultValue={layoutOptions[0]}
|
||||
onChange={(option) => {
|
||||
if (!option) {
|
||||
return;
|
||||
}
|
||||
setPreviewState((previewState) => {
|
||||
return {
|
||||
...previewState,
|
||||
layout: option.value,
|
||||
};
|
||||
});
|
||||
}}
|
||||
options={layoutOptions}
|
||||
/>
|
||||
</Label>
|
||||
)}
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { DefaultSeo } from "next-seo";
|
||||
import { Inter } from "next/font/google";
|
||||
import localFont from "next/font/local";
|
||||
import Head from "next/head";
|
||||
import Script from "next/script";
|
||||
|
||||
import "@calcom/embed-core/src/embed-iframe";
|
||||
@@ -60,6 +61,12 @@ function PageWrapper(props: AppProps) {
|
||||
|
||||
return (
|
||||
<AppProviders {...providerProps}>
|
||||
<Head>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
||||
/>
|
||||
</Head>
|
||||
<DefaultSeo
|
||||
// Set canonical to https://cal.com or self-hosted URL
|
||||
canonical={
|
||||
|
||||
@@ -26,24 +26,24 @@ export default function TwoFactor({ center = true }) {
|
||||
|
||||
return (
|
||||
<div className={center ? "mx-auto !mt-0 max-w-sm" : "!mt-0 max-w-sm"}>
|
||||
<Label className="mt-4"> {t("2fa_code")}</Label>
|
||||
<Label className="mt-4">{t("2fa_code")}</Label>
|
||||
|
||||
<p className="text-subtle mb-4 text-sm">{t("2fa_enabled_instructions")}</p>
|
||||
<input hidden type="hidden" value={value} {...methods.register("totpCode")} />
|
||||
|
||||
<input type="hidden" value={value} {...methods.register("totpCode")} />
|
||||
|
||||
<div className="flex flex-row justify-between">
|
||||
<Input
|
||||
className={className}
|
||||
name="2fa1"
|
||||
inputMode="decimal"
|
||||
{...digits[0]}
|
||||
autoFocus
|
||||
autoComplete="one-time-code"
|
||||
/>
|
||||
<Input className={className} name="2fa2" inputMode="decimal" {...digits[1]} />
|
||||
<Input className={className} name="2fa3" inputMode="decimal" {...digits[2]} />
|
||||
<Input className={className} name="2fa4" inputMode="decimal" {...digits[3]} />
|
||||
<Input className={className} name="2fa5" inputMode="decimal" {...digits[4]} />
|
||||
<Input className={className} name="2fa6" inputMode="decimal" {...digits[5]} />
|
||||
{digits.map((digit, index) => (
|
||||
<Input
|
||||
key={`2fa${index}`}
|
||||
className={className}
|
||||
name={`2fa${index + 1}`}
|
||||
inputMode="decimal"
|
||||
{...digit}
|
||||
autoFocus={index === 0}
|
||||
autoComplete="one-time-code"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -24,7 +24,7 @@ export function AvailableEventLocations({ locations }: { locations: Props["event
|
||||
}
|
||||
|
||||
const translateAbleKeys = [
|
||||
"attendee_in_person",
|
||||
"in_person_attendee_address",
|
||||
"in_person",
|
||||
"attendee_phone_number",
|
||||
"link_meeting",
|
||||
|
||||
@@ -161,7 +161,8 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
|
||||
brand === "#fff" || brand === "#ffffff" ? "" : ""
|
||||
)}
|
||||
onClick={() => reserveSlot(slot)}
|
||||
data-testid="time">
|
||||
data-testid="time"
|
||||
data-disabled="false">
|
||||
{dayjs(slot.time).tz(timeZone()).format(timeFormat)}
|
||||
{!!seatsPerTimeSlot && (
|
||||
<p
|
||||
|
||||
@@ -83,7 +83,9 @@ const BookingDescription: FC<Props> = (props) => {
|
||||
size="sm"
|
||||
truncateAfter={3}
|
||||
/>
|
||||
<h2 className="text-default mt-1 mb-2 break-words text-sm font-medium ">{profile.name}</h2>
|
||||
<h2 className="text-default mt-1 mb-2 break-words text-sm font-medium ">
|
||||
{eventType.team?.parent?.name} {profile.name}
|
||||
</h2>
|
||||
<h1 className="font-cal text-emphasis mb-6 break-words text-2xl font-semibold leading-none">
|
||||
{eventType.title}
|
||||
</h1>
|
||||
|
||||
@@ -59,6 +59,7 @@ export default function CancelBooking(props: Props) {
|
||||
<div className="mt-5 sm:mt-6">
|
||||
<label className="text-default font-medium">{t("cancellation_reason")}</label>
|
||||
<TextArea
|
||||
data-testid="cancel_reason"
|
||||
ref={cancelBookingRef}
|
||||
placeholder={t("cancellation_reason_placeholder")}
|
||||
value={cancellationReason}
|
||||
@@ -75,7 +76,7 @@ export default function CancelBooking(props: Props) {
|
||||
{t("nevermind")}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="cancel"
|
||||
data-testid="confirm_cancel"
|
||||
onClick={async () => {
|
||||
setLoading(true);
|
||||
|
||||
|
||||
@@ -57,12 +57,15 @@ const LocationInput = (props: {
|
||||
<Input {...locationFormMethods.register(eventLocationType.variable)} type="text" {...remainingProps} />
|
||||
);
|
||||
} else if (eventLocationType?.organizerInputType === "phone") {
|
||||
const { defaultValue, ...rest } = remainingProps;
|
||||
|
||||
return (
|
||||
<Controller
|
||||
name={eventLocationType.variable}
|
||||
control={control}
|
||||
defaultValue={defaultValue}
|
||||
render={({ field: { onChange, value } }) => {
|
||||
return <PhoneInput onChange={onChange} value={value} {...remainingProps} />;
|
||||
return <PhoneInput onChange={onChange} value={value} {...rest} />;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -88,6 +91,9 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
|
||||
useEffect(() => {
|
||||
if (selection) {
|
||||
locationFormMethods.setValue("locationType", selection?.value);
|
||||
if (selection?.address) {
|
||||
locationFormMethods.setValue("locationAddress", selection?.address);
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selection]);
|
||||
@@ -149,12 +155,25 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
|
||||
name: "locationType",
|
||||
});
|
||||
|
||||
const selectedAddrValue = useWatch({
|
||||
control: locationFormMethods.control,
|
||||
name: "locationAddress",
|
||||
});
|
||||
|
||||
const eventLocationType = getEventLocationType(selectedLocation);
|
||||
|
||||
const defaultLocation = defaultValues?.find(
|
||||
(location: { type: EventLocationType["type"] }) => location.type === eventLocationType?.type
|
||||
(location: { type: EventLocationType["type"]; address?: string }) => {
|
||||
if (location.type === LocationType.InPerson) {
|
||||
return location.type === eventLocationType?.type && location.address === selectedAddrValue;
|
||||
} else {
|
||||
return location.type === eventLocationType?.type;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
console.log(defaultLocation);
|
||||
|
||||
const LocationOptions = (() => {
|
||||
if (eventLocationType && eventLocationType.organizerInputType && LocationInput) {
|
||||
if (!eventLocationType.variable) {
|
||||
|
||||
@@ -55,7 +55,7 @@ export const RescheduleDialog = (props: IRescheduleDialog) => {
|
||||
</p>
|
||||
<TextArea
|
||||
data-testid="reschedule_reason"
|
||||
name={t("reschedule_reason")}
|
||||
name={t("reason_for_reschedule")}
|
||||
value={rescheduleReason}
|
||||
onChange={(e) => setRescheduleReason(e.target.value)}
|
||||
className="mb-5 sm:mb-6"
|
||||
|
||||
@@ -136,9 +136,17 @@ export const EventSetupTab = (
|
||||
selectedMultipleDuration.find((opt) => opt.value === eventType.length) ?? null
|
||||
);
|
||||
|
||||
const openLocationModal = (type: EventLocationType["type"]) => {
|
||||
const openLocationModal = (type: EventLocationType["type"], address = "") => {
|
||||
const option = getLocationFromType(type, locationOptions);
|
||||
setSelectedLocation(option);
|
||||
if (option && option.value === LocationType.InPerson) {
|
||||
const inPersonOption = {
|
||||
...option,
|
||||
address,
|
||||
};
|
||||
setSelectedLocation(inPersonOption);
|
||||
} else {
|
||||
setSelectedLocation(option);
|
||||
}
|
||||
setShowLocationModal(true);
|
||||
};
|
||||
|
||||
@@ -298,10 +306,14 @@ export const EventSetupTab = (
|
||||
onClick={() => {
|
||||
locationFormMethods.setValue("locationType", location.type);
|
||||
locationFormMethods.unregister("locationLink");
|
||||
locationFormMethods.unregister("locationAddress");
|
||||
if (location.type === LocationType.InPerson) {
|
||||
locationFormMethods.setValue("locationAddress", location.address);
|
||||
} else {
|
||||
locationFormMethods.unregister("locationAddress");
|
||||
}
|
||||
locationFormMethods.unregister("locationPhoneNumber");
|
||||
setEditingLocationType(location.type);
|
||||
openLocationModal(location.type);
|
||||
openLocationModal(location.type, location.address);
|
||||
}}
|
||||
aria-label={t("edit")}
|
||||
className="hover:text-emphasis text-subtle mr-1 p-1">
|
||||
@@ -517,7 +529,18 @@ export const EventSetupTab = (
|
||||
defaultValues={formMethods.getValues("locations")}
|
||||
selection={
|
||||
selectedLocation
|
||||
? { value: selectedLocation.value, label: t(selectedLocation.label), icon: selectedLocation.icon }
|
||||
? selectedLocation.address
|
||||
? {
|
||||
value: selectedLocation.value,
|
||||
label: t(selectedLocation.label),
|
||||
icon: selectedLocation.icon,
|
||||
address: selectedLocation.address,
|
||||
}
|
||||
: {
|
||||
value: selectedLocation.value,
|
||||
label: t(selectedLocation.label),
|
||||
icon: selectedLocation.icon,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
setSelectedLocation={setSelectedLocation}
|
||||
|
||||
@@ -185,7 +185,7 @@ function EventTypeSingleLayout({
|
||||
info:
|
||||
isManagedEventType || isChildrenManagedEventType
|
||||
? eventType.schedule === null
|
||||
? "member_default_schedule"
|
||||
? "members_default_schedule"
|
||||
: isChildrenManagedEventType
|
||||
? `${
|
||||
eventType.scheduleName
|
||||
|
||||
@@ -8,21 +8,15 @@ import { md } from "@calcom/lib/markdownIt";
|
||||
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import turndown from "@calcom/lib/turndownService";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Button, Editor, ImageUploader, Label, showToast } from "@calcom/ui";
|
||||
import { Avatar } from "@calcom/ui";
|
||||
import { Avatar, Button, Editor, ImageUploader, Label, showToast } from "@calcom/ui";
|
||||
import { ArrowRight } from "@calcom/ui/components/icon";
|
||||
|
||||
import type { IOnboardingPageProps } from "../../../pages/getting-started/[[...step]]";
|
||||
|
||||
type FormData = {
|
||||
bio: string;
|
||||
};
|
||||
interface IUserProfileProps {
|
||||
user: IOnboardingPageProps["user"];
|
||||
}
|
||||
|
||||
const UserProfile = (props: IUserProfileProps) => {
|
||||
const { user } = props;
|
||||
const UserProfile = () => {
|
||||
const [user] = trpc.viewer.me.useSuspenseQuery();
|
||||
const { t } = useLocale();
|
||||
const avatarRef = useRef<HTMLInputElement>(null);
|
||||
const { setValue, handleSubmit, getValues } = useForm<FormData>({
|
||||
|
||||
@@ -13,15 +13,13 @@ import { ArrowRight } from "@calcom/ui/components/icon";
|
||||
|
||||
import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability";
|
||||
|
||||
import type { IOnboardingPageProps } from "../../../pages/getting-started/[[...step]]";
|
||||
|
||||
interface IUserSettingsProps {
|
||||
user: IOnboardingPageProps["user"];
|
||||
nextStep: () => void;
|
||||
}
|
||||
|
||||
const UserSettings = (props: IUserSettingsProps) => {
|
||||
const { user, nextStep } = props;
|
||||
const { nextStep } = props;
|
||||
const [user] = trpc.viewer.me.useSuspenseQuery();
|
||||
const { t } = useLocale();
|
||||
const [selectedTimeZone, setSelectedTimeZone] = useState(dayjs.tz.guess());
|
||||
const telemetry = useTelemetry();
|
||||
@@ -69,7 +67,7 @@ const UserSettings = (props: IUserSettingsProps) => {
|
||||
<form onSubmit={onSubmit}>
|
||||
<div className="space-y-6">
|
||||
{/* Username textfield */}
|
||||
<UsernameAvailabilityField user={user} />
|
||||
<UsernameAvailabilityField />
|
||||
|
||||
{/* Full name textfield */}
|
||||
<div className="w-full">
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useRouter } from "next/router";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
|
||||
import type { TeamWithMembers } from "@calcom/lib/server/queries/teams";
|
||||
import { Avatar } from "@calcom/ui";
|
||||
|
||||
@@ -23,7 +24,7 @@ const Member = ({ member, teamName }: { member: MemberType; teamName: string | n
|
||||
|
||||
return (
|
||||
<Link key={member.id} href={{ pathname: `/${member.username}`, query: queryParamsToForward }}>
|
||||
<div className="sm:min-w-80 sm:max-w-80 bg-default hover:bg-muted border-subtle group flex min-h-full flex-col space-y-2 rounded-md border p-4 hover:cursor-pointer">
|
||||
<div className="sm:min-w-80 sm:max-w-80 bg-default hover:bg-muted border-subtle group flex min-h-full flex-col space-y-2 rounded-md border p-4 hover:cursor-pointer">
|
||||
<Avatar
|
||||
size="md"
|
||||
alt={member.name || ""}
|
||||
@@ -36,7 +37,7 @@ const Member = ({ member, teamName }: { member: MemberType; teamName: string | n
|
||||
<>
|
||||
<div
|
||||
className=" text-subtle break-words text-sm [&_a]:text-blue-500 [&_a]:underline [&_a]:hover:text-blue-600"
|
||||
dangerouslySetInnerHTML={{ __html: md.render(member.bio || "") }}
|
||||
dangerouslySetInnerHTML={{ __html: md.render(markdownToSafeHTML(member.bio)) }}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -8,14 +8,12 @@ import { getPremiumPlanPriceValue } from "@calcom/app-store/stripepayment/lib/ut
|
||||
import { fetchUsername } from "@calcom/lib/fetchUsername";
|
||||
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { User } from "@calcom/prisma/client";
|
||||
import type { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
import { Button, Dialog, DialogClose, DialogContent, Input, Label } from "@calcom/ui";
|
||||
import { Star as StarSolid } from "@calcom/ui/components/icon";
|
||||
import { Check, Edit2, ExternalLink } from "@calcom/ui/components/icon";
|
||||
import { Check, Edit2, ExternalLink, Star as StarSolid } from "@calcom/ui/components/icon";
|
||||
|
||||
export enum UsernameChangeStatusEnum {
|
||||
UPGRADE = "UPGRADE",
|
||||
@@ -29,7 +27,6 @@ interface ICustomUsernameProps {
|
||||
setInputUsernameValue: (value: string) => void;
|
||||
onSuccessMutation?: () => void;
|
||||
onErrorMutation?: (error: TRPCClientErrorLike<AppRouter>) => void;
|
||||
user: Pick<User, "username" | "metadata">;
|
||||
readonly?: boolean;
|
||||
}
|
||||
|
||||
@@ -57,8 +54,8 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
||||
onSuccessMutation,
|
||||
onErrorMutation,
|
||||
readonly: disabled,
|
||||
user,
|
||||
} = props;
|
||||
const [user] = trpc.viewer.me.useSuspenseQuery();
|
||||
const [usernameIsAvailable, setUsernameIsAvailable] = useState(false);
|
||||
const [markAsError, setMarkAsError] = useState(false);
|
||||
const router = useRouter();
|
||||
|
||||
@@ -21,7 +21,7 @@ interface ICustomUsernameProps {
|
||||
onErrorMutation?: (error: TRPCClientErrorLike<AppRouter>) => void;
|
||||
}
|
||||
|
||||
const UsernameTextfield = (props: ICustomUsernameProps) => {
|
||||
const UsernameTextfield = (props: ICustomUsernameProps & Partial<React.ComponentProps<typeof TextField>>) => {
|
||||
const { t } = useLocale();
|
||||
const {
|
||||
currentUsername,
|
||||
@@ -31,6 +31,7 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
|
||||
usernameRef,
|
||||
onSuccessMutation,
|
||||
onErrorMutation,
|
||||
...rest
|
||||
} = props;
|
||||
const [usernameIsAvailable, setUsernameIsAvailable] = useState(false);
|
||||
const [markAsError, setMarkAsError] = useState(false);
|
||||
@@ -116,9 +117,6 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
|
||||
ref={usernameRef}
|
||||
name="username"
|
||||
value={inputUsernameValue}
|
||||
addOnLeading={
|
||||
<>{process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "")}/</>
|
||||
}
|
||||
autoComplete="none"
|
||||
autoCapitalize="none"
|
||||
autoCorrect="none"
|
||||
@@ -133,6 +131,7 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
|
||||
setInputUsernameValue(event.target.value);
|
||||
}}
|
||||
data-testid="username-input"
|
||||
{...rest}
|
||||
/>
|
||||
{currentUsername !== inputUsernameValue && (
|
||||
<div className="absolute right-[2px] top-6 flex flex-row">
|
||||
|
||||
@@ -2,9 +2,11 @@ import { useRouter } from "next/router";
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { IS_SELF_HOSTED } from "@calcom/lib/constants";
|
||||
import type { User } from "@calcom/prisma/client";
|
||||
import type { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||
|
||||
import useRouterQuery from "@lib/hooks/useRouterQuery";
|
||||
@@ -17,14 +19,24 @@ export const UsernameAvailability = IS_SELF_HOSTED ? UsernameTextfield : Premium
|
||||
interface UsernameAvailabilityFieldProps {
|
||||
onSuccessMutation?: () => void;
|
||||
onErrorMutation?: (error: TRPCClientErrorLike<AppRouter>) => void;
|
||||
user: Pick<User, "username" | "metadata">;
|
||||
}
|
||||
|
||||
function useUserNamePrefix(organization: RouterOutputs["viewer"]["me"]["organization"]): string {
|
||||
return organization
|
||||
? organization.slug
|
||||
? `${organization.slug}.${subdomainSuffix()}`
|
||||
: organization.metadata && organization.metadata.requestedSlug
|
||||
? `${organization.metadata.requestedSlug}.${subdomainSuffix()}`
|
||||
: process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "")
|
||||
: process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "");
|
||||
}
|
||||
|
||||
export const UsernameAvailabilityField = ({
|
||||
onSuccessMutation,
|
||||
onErrorMutation,
|
||||
user,
|
||||
}: UsernameAvailabilityFieldProps) => {
|
||||
const router = useRouter();
|
||||
const [user] = trpc.viewer.me.useSuspenseQuery();
|
||||
const [currentUsernameState, setCurrentUsernameState] = useState(user.username || "");
|
||||
const { username: usernameFromQuery, setQuery: setUsernameFromQuery } = useRouterQuery("username");
|
||||
const { username: currentUsername, setQuery: setCurrentUsername } =
|
||||
@@ -37,6 +49,8 @@ export const UsernameAvailabilityField = ({
|
||||
},
|
||||
});
|
||||
|
||||
const usernamePrefix = useUserNamePrefix(user.organization);
|
||||
|
||||
return (
|
||||
<Controller
|
||||
control={formMethods.control}
|
||||
@@ -51,7 +65,7 @@ export const UsernameAvailabilityField = ({
|
||||
setInputUsernameValue={onChange}
|
||||
onSuccessMutation={onSuccessMutation}
|
||||
onErrorMutation={onErrorMutation}
|
||||
user={user}
|
||||
addOnLeading={usernamePrefix}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
||||
@@ -11,6 +11,7 @@ export type LocationOption = {
|
||||
value: EventLocationType["type"];
|
||||
icon?: string;
|
||||
disabled?: boolean;
|
||||
address?: string;
|
||||
};
|
||||
|
||||
export type SingleValueLocationOption = SingleValue<LocationOption>;
|
||||
|
||||
@@ -9,6 +9,8 @@ import type { NextRouter } from "next/router";
|
||||
import { useRouter } from "next/router";
|
||||
import type { ComponentProps, PropsWithChildren, ReactNode } from "react";
|
||||
|
||||
import { OrgBrandingProvider } from "@calcom/features/ee/organizations/context/provider";
|
||||
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
|
||||
import DynamicHelpscoutProvider from "@calcom/features/ee/support/lib/helpscout/providerDynamic";
|
||||
import DynamicIntercomProvider from "@calcom/features/ee/support/lib/intercom/providerDynamic";
|
||||
import { FeatureProvider } from "@calcom/features/flags/context/provider";
|
||||
@@ -205,6 +207,11 @@ function FeatureFlagsProvider({ children }: { children: React.ReactNode }) {
|
||||
return <FeatureProvider value={flags}>{children}</FeatureProvider>;
|
||||
}
|
||||
|
||||
function OrgBrandProvider({ children }: { children: React.ReactNode }) {
|
||||
const orgBrand = useOrgBrandingValues();
|
||||
return <OrgBrandingProvider value={orgBrand}>{children}</OrgBrandingProvider>;
|
||||
}
|
||||
|
||||
const AppProviders = (props: AppPropsWithChildren) => {
|
||||
const session = trpc.viewer.public.session.useQuery().data;
|
||||
// No need to have intercom on public pages - Good for Page Performance
|
||||
@@ -222,7 +229,9 @@ const AppProviders = (props: AppPropsWithChildren) => {
|
||||
isThemeSupported={props.Component.isThemeSupported}
|
||||
isBookingPage={props.Component.isBookingPage}>
|
||||
<FeatureFlagsProvider>
|
||||
<MetaProvider>{props.children}</MetaProvider>
|
||||
<OrgBrandProvider>
|
||||
<MetaProvider>{props.children}</MetaProvider>
|
||||
</OrgBrandProvider>
|
||||
</FeatureFlagsProvider>
|
||||
</CalcomThemeProvider>
|
||||
</TooltipProvider>
|
||||
|
||||
@@ -8,6 +8,7 @@ export default function withEmbedSsr(getServerSideProps: GetServerSideProps) {
|
||||
return async (context: GetServerSidePropsContext): Promise<GetServerSidePropsResult<EmbedProps>> => {
|
||||
const ssrResponse = await getServerSideProps(context);
|
||||
const embed = context.query.embed;
|
||||
const layout = context.query.layout;
|
||||
|
||||
if ("redirect" in ssrResponse) {
|
||||
// Use a dummy URL https://base as the fallback base URL so that URL parsing works for relative URLs as well.
|
||||
@@ -18,6 +19,8 @@ export default function withEmbedSsr(getServerSideProps: GetServerSideProps) {
|
||||
destinationUrlObj.pathname +
|
||||
"/embed?" +
|
||||
destinationUrlObj.searchParams.toString() +
|
||||
"&layout=" +
|
||||
layout +
|
||||
"&embed=" +
|
||||
embed;
|
||||
|
||||
|
||||
+41
-7
@@ -3,6 +3,7 @@ import { collectEvents } from "next-collect/server";
|
||||
import type { NextMiddleware } from "next/server";
|
||||
import { NextResponse, userAgent } from "next/server";
|
||||
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { CONSOLE_URL, WEBAPP_URL, WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import { isIpInBanlist } from "@calcom/lib/getIP";
|
||||
import { extendEventData, nextCollectBasicSettings } from "@calcom/lib/telemetry";
|
||||
@@ -10,6 +11,25 @@ import { extendEventData, nextCollectBasicSettings } from "@calcom/lib/telemetry
|
||||
const middleware: NextMiddleware = async (req) => {
|
||||
const url = req.nextUrl;
|
||||
const requestHeaders = new Headers(req.headers);
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(req.headers.get("host") ?? "");
|
||||
/**
|
||||
* We are using env variable to toggle new-booker because using flags would be an unnecessary delay for booking pages
|
||||
* Also, we can't easily identify the booker page requests here(to just fetch the flags for those requests)
|
||||
*/
|
||||
|
||||
// Make sure we are in the presence of an organization
|
||||
if (isValidOrgDomain && url.pathname === "/") {
|
||||
// In the presence of an organization, cover its profile page at "/"
|
||||
// rewrites for org profile page using team profile page
|
||||
url.pathname = `/org/${currentOrgDomain}`;
|
||||
return NextResponse.rewrite(url);
|
||||
}
|
||||
|
||||
if (isIpInBanlist(req) && url.pathname !== "/api/nope") {
|
||||
// DDOS Prevention: Immediately end request with no response - Avoids a redirect as well initiated by NextAuth on invalid callback
|
||||
req.nextUrl.pathname = "/api/nope";
|
||||
return NextResponse.redirect(req.nextUrl);
|
||||
}
|
||||
|
||||
if (!url.pathname.startsWith("/api")) {
|
||||
//
|
||||
@@ -48,13 +68,6 @@ const middleware: NextMiddleware = async (req) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that embed query param is there in when /embed is added.
|
||||
// query param is the way in which client side code knows that it is in embed mode.
|
||||
if (url.pathname.endsWith("/embed") && typeof url.searchParams.get("embed") !== "string") {
|
||||
url.searchParams.set("embed", "");
|
||||
return NextResponse.redirect(url);
|
||||
}
|
||||
|
||||
// Don't 404 old routing_forms links
|
||||
if (url.pathname.startsWith("/apps/routing_forms")) {
|
||||
url.pathname = url.pathname.replace("/apps/routing_forms", "/apps/routing-forms");
|
||||
@@ -70,6 +83,26 @@ const middleware: NextMiddleware = async (req) => {
|
||||
requestHeaders.set("x-csp-enforce", "true");
|
||||
}
|
||||
|
||||
if (isValidOrgDomain) {
|
||||
// Match /:slug to determine if it corresponds to org subteam slug or org user slug
|
||||
const slugs = /^\/([^/]+)(\/[^/]+)?$/.exec(url.pathname);
|
||||
// In the presence of an organization, if not team profile, a user or team is being accessed
|
||||
if (slugs) {
|
||||
const [_, teamName, eventType] = slugs;
|
||||
// Fetch the corresponding subteams for the entered organization
|
||||
const getSubteams = await fetch(`${WEBAPP_URL}/api/organizations/${currentOrgDomain}/subteams`);
|
||||
if (getSubteams.ok) {
|
||||
const data = await getSubteams.json();
|
||||
// Treat entered slug as a team if found in the subteams fetched
|
||||
if (data.slugs.includes(teamName)) {
|
||||
// Rewriting towards /team/:slug to bring up the team profile within the org
|
||||
url.pathname = `/team/${teamName}${eventType ?? ""}`;
|
||||
return NextResponse.rewrite(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.next({
|
||||
request: {
|
||||
headers: requestHeaders,
|
||||
@@ -79,6 +112,7 @@ const middleware: NextMiddleware = async (req) => {
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
"/:path*",
|
||||
"/api/collect-events/:path*",
|
||||
"/api/auth/:path*",
|
||||
"/apps/routing_forms/:path*",
|
||||
|
||||
+104
-17
@@ -2,7 +2,7 @@ require("dotenv").config({ path: "../../.env" });
|
||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||
const os = require("os");
|
||||
const glob = require("glob");
|
||||
|
||||
const englishTranslation = require("./public/static/locales/en/common.json");
|
||||
const { withAxiom } = require("next-axiom");
|
||||
const { i18n } = require("./next-i18next.config");
|
||||
|
||||
@@ -57,6 +57,20 @@ if (process.env.GOOGLE_API_CREDENTIALS && !validJson(process.env.GOOGLE_API_CRED
|
||||
);
|
||||
}
|
||||
|
||||
const informAboutDuplicateTranslations = () => {
|
||||
const valueSet = new Set();
|
||||
|
||||
for (const key in englishTranslation) {
|
||||
if (valueSet.has(englishTranslation[key])) {
|
||||
console.warn("\x1b[33mDuplicate value found in:", "\x1b[0m", key);
|
||||
} else {
|
||||
valueSet.add(englishTranslation[key]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
informAboutDuplicateTranslations();
|
||||
|
||||
const plugins = [];
|
||||
if (process.env.ANALYZE === "true") {
|
||||
// only load dependency if env `ANALYZE` was set
|
||||
@@ -169,7 +183,16 @@ const nextConfig = {
|
||||
return config;
|
||||
},
|
||||
async rewrites() {
|
||||
return [
|
||||
// .* matches / as well(Note: *(i.e wildcard) doesn't match / but .*(i.e. RegExp) does)
|
||||
// It would match /free/30min but not /bookings/upcoming because 'bookings' is an item in pages
|
||||
// It would also not match /free/30min/embed because we are ensuring just two slashes
|
||||
const userTypeRouteRegExp = `/:user((?!${pages.join("|")})[^/]*)/:type`;
|
||||
|
||||
let rewrites = [
|
||||
{
|
||||
source: "/org/:slug",
|
||||
destination: "/team/:slug",
|
||||
},
|
||||
{
|
||||
source: "/:user/avatar.png",
|
||||
destination: "/api/user/avatar?username=:user",
|
||||
@@ -201,26 +224,85 @@ const nextConfig = {
|
||||
source: "/cancel/:path*",
|
||||
destination: "/booking/:path*",
|
||||
},
|
||||
// Keep cookie based booker enabled just in case we disable new-booker globally
|
||||
...[
|
||||
{
|
||||
source: userTypeRouteRegExp,
|
||||
destination: "/new-booker/:user/:type",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
{
|
||||
source: "/team/:slug/:type",
|
||||
destination: "/new-booker/team/:slug/:type",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
{
|
||||
source: "/d/:link/:slug",
|
||||
destination: "/new-booker/d/:link/:slug",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
],
|
||||
// Keep cookie based booker enabled to test new-booker embed in production
|
||||
...[
|
||||
{
|
||||
source: `/:user((?!${pages.join("|")}).*)/:type/embed`,
|
||||
destination: "/new-booker/:user/:type/embed",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
{
|
||||
source: "/team/:slug/:type/embed",
|
||||
destination: "/new-booker/team/:slug/:type/embed",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
],
|
||||
/* TODO: have these files being served from another deployment or CDN {
|
||||
source: "/embed/embed.js",
|
||||
destination: process.env.NEXT_PUBLIC_EMBED_LIB_URL?,
|
||||
}, */
|
||||
{
|
||||
source: `/:user((?!${pages.join("|")}).*)/:type`,
|
||||
destination: "/new-booker/:user/:type",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
{
|
||||
source: "/team/:slug/:type",
|
||||
destination: "/new-booker/team/:slug/:type",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
{
|
||||
source: "/d/:link/:slug",
|
||||
destination: "/new-booker/d/:link/:slug",
|
||||
has: [{ type: "cookie", key: "new-booker-enabled" }],
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables new booker using cookie. It works even if NEW_BOOKER_ENABLED_FOR_NON_EMBED, NEW_BOOKER_ENABLED_FOR_EMBED are disabled
|
||||
*/
|
||||
];
|
||||
|
||||
// Enable New Booker for all Embed Requests
|
||||
if (process.env.NEW_BOOKER_ENABLED_FOR_EMBED === "1") {
|
||||
console.log("Enabling New Booker for Embed");
|
||||
rewrites.push(
|
||||
...[
|
||||
{
|
||||
source: `/:user((?!${pages.join("|")}).*)/:type/embed`,
|
||||
destination: "/new-booker/:user/:type/embed",
|
||||
},
|
||||
{
|
||||
source: "/team/:slug/:type/embed",
|
||||
destination: "/new-booker/team/:slug/:type/embed",
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Enable New Booker for All but embed Requests
|
||||
if (process.env.NEW_BOOKER_ENABLED_FOR_NON_EMBED === "1") {
|
||||
console.log("Enabling New Booker for Non-Embed");
|
||||
rewrites.push(
|
||||
...[
|
||||
{
|
||||
source: userTypeRouteRegExp,
|
||||
destination: "/new-booker/:user/:type",
|
||||
},
|
||||
{
|
||||
source: "/team/:slug/:type",
|
||||
destination: "/new-booker/team/:slug/:type",
|
||||
},
|
||||
{
|
||||
source: "/d/:link/:slug",
|
||||
destination: "/new-booker/d/:link/:slug",
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
return rewrites;
|
||||
},
|
||||
async headers() {
|
||||
return [
|
||||
@@ -279,6 +361,11 @@ const nextConfig = {
|
||||
destination: "/teams",
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
source: "/settings/admin",
|
||||
destination: "/settings/admin/flags",
|
||||
permanent: true,
|
||||
},
|
||||
/* V2 testers get redirected to the new settings */
|
||||
{
|
||||
source: "/settings/profile",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@calcom/web",
|
||||
"version": "2.9.7",
|
||||
"version": "3.0.2",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"analyze": "ANALYZE=true next build",
|
||||
@@ -61,6 +61,8 @@
|
||||
"@tanstack/react-query": "^4.3.9",
|
||||
"@tremor/react": "^2.0.0",
|
||||
"@types/turndown": "^5.0.1",
|
||||
"@upstash/ratelimit": "^0.4.3",
|
||||
"@upstash/redis": "^1.21.0",
|
||||
"@vercel/edge-config": "^0.1.1",
|
||||
"@vercel/edge-functions-ui": "^0.2.1",
|
||||
"@vercel/og": "^0.5.0",
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
useEmbedStyles,
|
||||
useIsEmbed,
|
||||
} from "@calcom/embed-core/embed-iframe";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { EventTypeDescriptionLazy as EventTypeDescription } from "@calcom/features/eventtypes/components";
|
||||
import EmptyPage from "@calcom/features/eventtypes/components/EmptyPage";
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
@@ -255,6 +256,7 @@ const getEventTypesWithHiddenFromDB = async (userId: number) => {
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
const ssr = await ssrInit(context);
|
||||
const crypto = await import("crypto");
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
|
||||
|
||||
const usernameList = getUsernameList(context.query.user as string);
|
||||
const dataFetchStart = Date.now();
|
||||
@@ -263,6 +265,11 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
username: {
|
||||
in: usernameList,
|
||||
},
|
||||
organization: isValidOrgDomain
|
||||
? {
|
||||
slug: currentOrgDomain,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
@@ -272,6 +279,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
bio: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
organizationId: true,
|
||||
theme: true,
|
||||
away: true,
|
||||
verified: true,
|
||||
@@ -284,7 +292,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
avatar: `${WEBAPP_URL}/${user.username}/avatar.png`,
|
||||
}));
|
||||
|
||||
if (!users.length) {
|
||||
if (!users.length || (!isValidOrgDomain && !users.some((user) => user.organizationId === null))) {
|
||||
return {
|
||||
notFound: true,
|
||||
} as {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { GetStaticPaths, GetStaticPropsContext } from "next";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import type { LocationObject } from "@calcom/app-store/locations";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getUsernameList } from "@calcom/lib/defaultEvents";
|
||||
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
|
||||
@@ -15,7 +17,9 @@ import type { EmbedProps } from "@lib/withEmbedSsr";
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
import AvailabilityPage from "@components/booking/pages/AvailabilityPage";
|
||||
|
||||
export type AvailabilityPageProps = inferSSRProps<typeof getStaticProps> & EmbedProps;
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
export type AvailabilityPageProps = inferSSRProps<typeof getServerSideProps> & EmbedProps;
|
||||
|
||||
export default function Type(props: AvailabilityPageProps) {
|
||||
const { t } = useLocale();
|
||||
@@ -50,6 +54,21 @@ export default function Type(props: AvailabilityPageProps) {
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
) : !props.isValidOrgDomain && props.organizationContext ? (
|
||||
<div className="dark:bg-darkgray-50 h-screen">
|
||||
<main className="mx-auto max-w-3xl px-4 py-24">
|
||||
<div className="space-y-6" data-testid="event-types">
|
||||
<div className="overflow-hidden rounded-sm border dark:border-gray-900">
|
||||
<div className="text-muted dark:text-inverted p-8 text-center">
|
||||
<h2 className="font-cal dark:text-inverted text-emphasis600 mb-2 text-3xl">
|
||||
{" " + t("unavailable")}
|
||||
</h2>
|
||||
<p className="mx-auto max-w-md">{t("user_belongs_organization")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
) : (
|
||||
<AvailabilityPage {...props} />
|
||||
);
|
||||
@@ -59,21 +78,25 @@ Type.isBookingPage = true;
|
||||
Type.PageWrapper = PageWrapper;
|
||||
|
||||
const paramsSchema = z.object({ type: z.string(), user: z.string() });
|
||||
async function getUserPageProps(context: GetStaticPropsContext) {
|
||||
async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||
// load server side dependencies
|
||||
const prisma = await import("@calcom/prisma").then((mod) => mod.default);
|
||||
const { privacyFilteredLocations } = await import("@calcom/app-store/locations");
|
||||
const { parseRecurringEvent } = await import("@calcom/lib/isRecurringEvent");
|
||||
const { EventTypeMetaDataSchema, teamMetadataSchema } = await import("@calcom/prisma/zod-utils");
|
||||
const { ssgInit } = await import("@server/lib/ssg");
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
|
||||
const ssr = await ssrInit(context);
|
||||
const { type: slug, user: username } = paramsSchema.parse(context.query);
|
||||
|
||||
const { type: slug, user: username } = paramsSchema.parse(context.params);
|
||||
const ssg = await ssgInit(context);
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
const user = await prisma.user.findFirst({
|
||||
where: {
|
||||
/** TODO: We should standarize this */
|
||||
username: username.toLowerCase().replace(/( |%20)/g, "+"),
|
||||
organization: isValidOrgDomain
|
||||
? {
|
||||
slug: currentOrgDomain,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
@@ -87,6 +110,7 @@ async function getUserPageProps(context: GetStaticPropsContext) {
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
metadata: true,
|
||||
organizationId: true,
|
||||
eventTypes: {
|
||||
where: {
|
||||
// Many-to-many relationship causes inclusion of the team events - cool -
|
||||
@@ -108,6 +132,17 @@ async function getUserPageProps(context: GetStaticPropsContext) {
|
||||
schedulingType: true,
|
||||
metadata: true,
|
||||
seatsPerTimeSlot: true,
|
||||
team: {
|
||||
select: {
|
||||
logo: true,
|
||||
parent: {
|
||||
select: {
|
||||
logo: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: [
|
||||
{
|
||||
@@ -179,16 +214,17 @@ async function getUserPageProps(context: GetStaticPropsContext) {
|
||||
},
|
||||
// Dynamic group has no theme preference right now. It uses system theme.
|
||||
themeBasis: user.username,
|
||||
organizationContext: user?.organizationId !== null,
|
||||
away: user?.away,
|
||||
isDynamic: false,
|
||||
trpcState: ssg.dehydrate(),
|
||||
trpcState: ssr.dehydrate(),
|
||||
isValidOrgDomain: orgDomainConfig(context.req.headers.host ?? ""),
|
||||
isBrandingHidden: isBrandingHidden(user.hideBranding, hasActiveTeam || hasPremiumUserName),
|
||||
},
|
||||
revalidate: 10, // seconds
|
||||
};
|
||||
}
|
||||
|
||||
async function getDynamicGroupPageProps(context: GetStaticPropsContext) {
|
||||
async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
||||
// load server side dependencies
|
||||
const { getDefaultEvent, getGroupName, getUsernameList } = await import("@calcom/lib/defaultEvents");
|
||||
const { privacyFilteredLocations } = await import("@calcom/app-store/locations");
|
||||
@@ -197,10 +233,10 @@ async function getDynamicGroupPageProps(context: GetStaticPropsContext) {
|
||||
const { EventTypeMetaDataSchema, userMetadata: userMetadataSchema } = await import(
|
||||
"@calcom/prisma/zod-utils"
|
||||
);
|
||||
const { ssgInit } = await import("@server/lib/ssg");
|
||||
const ssr = await ssrInit(context);
|
||||
|
||||
const { getAppFromSlug } = await import("@calcom/app-store/utils");
|
||||
|
||||
const ssg = await ssgInit(context);
|
||||
const { type: typeParam, user: userParam } = paramsSchema.parse(context.params);
|
||||
const usernameList = getUsernameList(userParam);
|
||||
const length = parseInt(typeParam);
|
||||
@@ -230,6 +266,7 @@ async function getDynamicGroupPageProps(context: GetStaticPropsContext) {
|
||||
defaultScheduleId: true,
|
||||
allowDynamicBooking: true,
|
||||
metadata: true,
|
||||
organizationId: true,
|
||||
away: true,
|
||||
schedules: {
|
||||
select: {
|
||||
@@ -313,24 +350,21 @@ async function getDynamicGroupPageProps(context: GetStaticPropsContext) {
|
||||
themeBasis: null,
|
||||
isDynamic: true,
|
||||
away: false,
|
||||
trpcState: ssg.dehydrate(),
|
||||
organizationContext: !users.some((user) => user.organizationId === null),
|
||||
trpcState: ssr.dehydrate(),
|
||||
isValidOrgDomain: orgDomainConfig(context.req.headers.host ?? ""),
|
||||
isBrandingHidden: false, // I think we should always show branding for dynamic groups - saves us checking every single user
|
||||
},
|
||||
revalidate: 10, // seconds
|
||||
};
|
||||
}
|
||||
|
||||
export const getStaticProps = async (context: GetStaticPropsContext) => {
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const { user: userParam } = paramsSchema.parse(context.params);
|
||||
// dynamic groups are not generated at build time, but otherwise are probably cached until infinity.
|
||||
const isDynamicGroup = userParam.includes("+");
|
||||
const isDynamicGroup = getUsernameList(userParam).length > 1;
|
||||
if (isDynamicGroup) {
|
||||
return await getDynamicGroupPageProps(context);
|
||||
} else {
|
||||
return await getUserPageProps(context);
|
||||
}
|
||||
};
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
return { paths: [], fallback: "blocking" };
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import type { GetStaticPropsContext } from "next";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
|
||||
import { getStaticProps as _getStaticProps } from "../[type]";
|
||||
|
||||
export { getStaticPaths } from "../[type]";
|
||||
import { getServerSideProps as _getServerSideProps } from "../[type]";
|
||||
|
||||
export { default } from "../[type]";
|
||||
|
||||
export const getStaticProps = async (context: GetStaticPropsContext) => {
|
||||
const staticResponse = await _getStaticProps(context);
|
||||
if (staticResponse.notFound) {
|
||||
return staticResponse;
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
const ssrResponse = await _getServerSideProps(context);
|
||||
if (ssrResponse.notFound) {
|
||||
return ssrResponse;
|
||||
}
|
||||
return {
|
||||
...staticResponse,
|
||||
...ssrResponse,
|
||||
props: {
|
||||
...staticResponse.props,
|
||||
...ssrResponse.props,
|
||||
isEmbed: true,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { getStaticProps, getStaticPaths, default } from "./index";
|
||||
+1
-1
@@ -16,7 +16,7 @@ export const getStaticProps: GetStaticProps<
|
||||
{ user: string }
|
||||
> = async (context) => {
|
||||
const { user: username, month } = paramsSchema.parse(context.params);
|
||||
const userWithCredentials = await prisma.user.findUnique({
|
||||
const userWithCredentials = await prisma.user.findFirst({
|
||||
where: {
|
||||
username,
|
||||
},
|
||||
@@ -48,10 +48,6 @@ class MyDocument extends Document<Props> {
|
||||
<meta name="msapplication-TileColor" content="#ff0000" />
|
||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#f9fafb" />
|
||||
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1C1C1C" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
||||
/>
|
||||
</Head>
|
||||
|
||||
<body
|
||||
|
||||
@@ -5,15 +5,12 @@ import { z } from "zod";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { sendPasswordResetEmail } from "@calcom/emails";
|
||||
import { PASSWORD_RESET_EXPIRY_HOURS } from "@calcom/emails/templates/forgot-password-email";
|
||||
import rateLimit from "@calcom/lib/rateLimit";
|
||||
import { ErrorCode } from "@calcom/features/auth/lib/ErrorCode";
|
||||
import rateLimiter from "@calcom/lib/rateLimit";
|
||||
import { defaultHandler } from "@calcom/lib/server";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
const limiter = rateLimit({
|
||||
intervalInMs: 60 * 1000, // 1 minute
|
||||
});
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const t = await getTranslation(req.body.language ?? "en", "common");
|
||||
|
||||
@@ -37,10 +34,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
// 10 requests per minute
|
||||
|
||||
try {
|
||||
limiter.check(10, ip);
|
||||
} catch (e) {
|
||||
return res.status(429).json({ message: "Too Many Requests." });
|
||||
const limiter = await rateLimiter();
|
||||
const limit = await limiter({
|
||||
identifier: ip,
|
||||
});
|
||||
|
||||
if (!limit.success) {
|
||||
throw new Error(ErrorCode.RateLimitExceeded);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { z } from "zod";
|
||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { UserPermissionRole } from "@calcom/prisma/enums";
|
||||
import { TRPCError } from "@calcom/trpc/server";
|
||||
import { createContext } from "@calcom/trpc/server/createContext";
|
||||
import { viewerRouter } from "@calcom/trpc/server/routers/viewer/_router";
|
||||
@@ -38,9 +39,22 @@ async function handler(req: NextApiRequest, res: NextApiResponse<Response>) {
|
||||
where: { id: userId },
|
||||
});
|
||||
|
||||
/** We shape the session as required by tRPC router */
|
||||
async function sessionGetter() {
|
||||
return {
|
||||
user: {
|
||||
id: userId,
|
||||
username: "" /* Not used in this context */,
|
||||
role: UserPermissionRole.USER,
|
||||
},
|
||||
hasValidLicense: true,
|
||||
expires: "" /* Not used in this context */,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
/** @see https://trpc.io/docs/server-side-calls */
|
||||
const ctx = await createContext({ req, res });
|
||||
const ctx = await createContext({ req, res }, sessionGetter);
|
||||
const caller = viewerRouter.createCaller({
|
||||
...ctx,
|
||||
req,
|
||||
@@ -55,7 +69,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<Response>) {
|
||||
});
|
||||
} catch (e) {
|
||||
let message = "Error confirming booking";
|
||||
if (e instanceof TRPCError) message = e.message;
|
||||
if (e instanceof TRPCError) message = (e as TRPCError).message;
|
||||
res.redirect(`/booking/${bookingUid}?error=${encodeURIComponent(message)}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import {
|
||||
ANDROID_CHROME_ICON_192,
|
||||
ANDROID_CHROME_ICON_256,
|
||||
@@ -104,7 +105,7 @@ function isValidLogoType(type: string): type is LogoType {
|
||||
return type in logoDefinitions;
|
||||
}
|
||||
|
||||
async function getTeamLogos(subdomain: string) {
|
||||
async function getTeamLogos(subdomain: string, isValidOrgDomain: boolean) {
|
||||
try {
|
||||
if (
|
||||
// if not cal.com
|
||||
@@ -118,9 +119,15 @@ async function getTeamLogos(subdomain: string) {
|
||||
}
|
||||
// load from DB
|
||||
const { default: prisma } = await import("@calcom/prisma");
|
||||
const team = await prisma.team.findUnique({
|
||||
const team = await prisma.team.findFirst({
|
||||
where: {
|
||||
slug: subdomain,
|
||||
...(isValidOrgDomain && {
|
||||
metadata: {
|
||||
path: ["isOrganization"],
|
||||
equals: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
select: {
|
||||
appLogo: true,
|
||||
@@ -147,6 +154,7 @@ async function getTeamLogos(subdomain: string) {
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { query } = req;
|
||||
const parsedQuery = logoApiSchema.parse(query);
|
||||
const { isValidOrgDomain } = orgDomainConfig(req.headers.host ?? "");
|
||||
|
||||
const hostname = req?.headers["host"];
|
||||
if (!hostname) throw new Error("No hostname");
|
||||
@@ -154,7 +162,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
if (!domains) throw new Error("No domains");
|
||||
|
||||
const [subdomain] = domains;
|
||||
const teamLogos = await getTeamLogos(subdomain);
|
||||
const teamLogos = await getTeamLogos(subdomain, isValidOrgDomain);
|
||||
|
||||
// Resolve all icon types to team logos, falling back to Cal.com defaults.
|
||||
const type: LogoType = parsedQuery?.type && isValidLogoType(parsedQuery.type) ? parsedQuery.type : "logo";
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "@calcom/features/ee/organizations/api/subteams";
|
||||
@@ -0,0 +1,4 @@
|
||||
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
|
||||
import { viewerOrganizationsRouter } from "@calcom/trpc/server/routers/viewer/organizations/_router";
|
||||
|
||||
export default createNextApiHandler(viewerOrganizationsRouter);
|
||||
@@ -2,6 +2,7 @@ import crypto from "crypto";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
@@ -16,10 +17,18 @@ const querySchema = z
|
||||
|
||||
async function getIdentityData(req: NextApiRequest) {
|
||||
const { username, teamname } = querySchema.parse(req.query);
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(req.headers.host ?? "");
|
||||
|
||||
if (username) {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { username },
|
||||
const user = await prisma.user.findFirst({
|
||||
where: {
|
||||
username,
|
||||
organization: isValidOrgDomain
|
||||
? {
|
||||
slug: currentOrgDomain,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
select: { avatar: true, email: true },
|
||||
});
|
||||
return {
|
||||
@@ -29,8 +38,15 @@ async function getIdentityData(req: NextApiRequest) {
|
||||
};
|
||||
}
|
||||
if (teamname) {
|
||||
const team = await prisma.team.findUnique({
|
||||
where: { slug: teamname },
|
||||
const team = await prisma.team.findFirst({
|
||||
where: {
|
||||
slug: teamname,
|
||||
parent: isValidOrgDomain
|
||||
? {
|
||||
slug: currentOrgDomain,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
select: { logo: true },
|
||||
});
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { checkUsername } from "@calcom/lib/server/checkUsername";
|
||||
|
||||
type Response = {
|
||||
@@ -8,6 +9,7 @@ type Response = {
|
||||
};
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<Response>): Promise<void> {
|
||||
const result = await checkUsername(req.body.username);
|
||||
const { currentOrgDomain } = orgDomainConfig(req.headers.host ?? "");
|
||||
const result = await checkUsername(req.body.username, currentOrgDomain);
|
||||
return res.status(200).json(result);
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ const IntegrationsList = ({ data, handleDisconnect, variant }: IntegrationsListP
|
||||
setBulkUpdateModal(true);
|
||||
}
|
||||
}}>
|
||||
{t("change_default_conferencing_app")}
|
||||
{t("set_as_default")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useEffect } from "react";
|
||||
|
||||
import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils";
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import stripe from "@calcom/features/ee/payments/server/stripe";
|
||||
import {
|
||||
hostedCal,
|
||||
@@ -68,11 +69,12 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
|
||||
const session = await getServerSession({ req, res });
|
||||
const ssr = await ssrInit(context);
|
||||
const { currentOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
|
||||
|
||||
if (session) {
|
||||
// Validating if username is Premium, while this is true an email its required for stripe user confirmation
|
||||
if (usernameParam && session.user.email) {
|
||||
const availability = await checkUsername(usernameParam);
|
||||
const availability = await checkUsername(usernameParam, currentOrgDomain);
|
||||
if (availability.available && availability.premium) {
|
||||
const stripePremiumUrl = await getStripePremiumUsernameUrl({
|
||||
userEmail: session.user.email,
|
||||
|
||||
@@ -363,7 +363,7 @@ export default function Success(props: SuccessProps) {
|
||||
id="modal-headline">
|
||||
{needsConfirmation && !isCancelled
|
||||
? props.recurringBookings
|
||||
? t("submitted_recurring")
|
||||
? t("booking_submitted_recurring")
|
||||
: t("booking_submitted")
|
||||
: isCancelled
|
||||
? seatReferenceUid
|
||||
|
||||
@@ -22,7 +22,7 @@ import SkeletonLoader from "@components/booking/SkeletonLoader";
|
||||
|
||||
import { ssgInit } from "@server/lib/ssg";
|
||||
|
||||
type BookingListingStatus = z.infer<typeof filterQuerySchema>["status"];
|
||||
type BookingListingStatus = z.infer<NonNullable<typeof filterQuerySchema>>["status"];
|
||||
type BookingOutput = RouterOutputs["viewer"]["bookings"]["get"]["bookings"][0];
|
||||
|
||||
type RecurringInfo = {
|
||||
@@ -34,7 +34,7 @@ type RecurringInfo = {
|
||||
|
||||
const validStatuses = ["upcoming", "recurring", "past", "cancelled", "unconfirmed"] as const;
|
||||
|
||||
const descriptionByStatus: Record<BookingListingStatus, string> = {
|
||||
const descriptionByStatus: Record<NonNullable<BookingListingStatus>, string> = {
|
||||
upcoming: "upcoming_bookings",
|
||||
recurring: "recurring_bookings",
|
||||
past: "past_bookings",
|
||||
|
||||
@@ -372,8 +372,9 @@ const EventTypePage = (props: EventTypeSetupProps) => {
|
||||
throw new Error(t("seats_and_no_show_fee_error"));
|
||||
}
|
||||
|
||||
const { availability, ...rest } = input;
|
||||
updateMutation.mutate({
|
||||
...input,
|
||||
...rest,
|
||||
locations,
|
||||
recurringEvent,
|
||||
periodStartDate: periodDates.startDate,
|
||||
@@ -453,9 +454,9 @@ const EventTypePage = (props: EventTypeSetupProps) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { availability, ...rest } = input;
|
||||
updateMutation.mutate({
|
||||
...input,
|
||||
...rest,
|
||||
locations,
|
||||
recurringEvent,
|
||||
periodStartDate: periodDates.startDate,
|
||||
|
||||
@@ -7,10 +7,13 @@ import type { FC } from "react";
|
||||
import { useEffect, useState, memo } from "react";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useOrgBrandingValues } from "@calcom/features/ee/organizations/hooks";
|
||||
import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import useIntercom from "@calcom/features/ee/support/lib/intercom/useIntercom";
|
||||
import { EventTypeDescriptionLazy as EventTypeDescription } from "@calcom/features/eventtypes/components";
|
||||
import CreateEventTypeDialog from "@calcom/features/eventtypes/components/CreateEventTypeDialog";
|
||||
import { DuplicateDialog } from "@calcom/features/eventtypes/components/DuplicateDialog";
|
||||
import { OrganizationEventTypeFilter } from "@calcom/features/eventtypes/components/OrganizationEventTypeFilter";
|
||||
import Shell from "@calcom/features/shell/Shell";
|
||||
import { APP_NAME, CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
@@ -44,6 +47,8 @@ import {
|
||||
HeadSeo,
|
||||
Skeleton,
|
||||
Label,
|
||||
VerticalDivider,
|
||||
Alert,
|
||||
} from "@calcom/ui";
|
||||
import {
|
||||
ArrowDown,
|
||||
@@ -59,9 +64,11 @@ import {
|
||||
Trash,
|
||||
Upload,
|
||||
Users,
|
||||
User as UserIcon,
|
||||
} from "@calcom/ui/components/icon";
|
||||
|
||||
import { withQuery } from "@lib/QueryCell";
|
||||
import useMeQuery from "@lib/hooks/useMeQuery";
|
||||
|
||||
import { EmbedButton, EmbedDialog } from "@components/Embed";
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
@@ -74,6 +81,7 @@ interface EventTypeListHeadingProps {
|
||||
profile: EventTypeGroupProfile;
|
||||
membershipCount: number;
|
||||
teamId?: number | null;
|
||||
orgSlug?: string;
|
||||
}
|
||||
|
||||
type EventTypeGroup = EventTypeGroups[number];
|
||||
@@ -194,6 +202,7 @@ const MemoizedItem = memo(Item);
|
||||
export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeListProps): JSX.Element => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
const orgBranding = useOrgBrandingValues();
|
||||
const [parent] = useAutoAnimate<HTMLUListElement>();
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
const [deleteDialogTypeId, setDeleteDialogTypeId] = useState(0);
|
||||
@@ -362,7 +371,9 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
||||
<ul ref={parent} className="divide-subtle !static w-full divide-y" data-testid="event-types">
|
||||
{types.map((type, index) => {
|
||||
const embedLink = `${group.profile.slug}/${type.slug}`;
|
||||
const calLink = `${CAL_URL}/${embedLink}`;
|
||||
const calLink = `${
|
||||
orgBranding ? `${new URL(CAL_URL).protocol}//${orgBranding.slug}.${subdomainSuffix()}` : CAL_URL
|
||||
}/${embedLink}`;
|
||||
const isManagedEventType = type.schedulingType === SchedulingType.MANAGED;
|
||||
const isChildrenManagedEventType =
|
||||
type.metadata?.managedEventConfig !== undefined && type.schedulingType !== SchedulingType.MANAGED;
|
||||
@@ -687,6 +698,7 @@ const EventTypeListHeading = ({
|
||||
profile,
|
||||
membershipCount,
|
||||
teamId,
|
||||
orgSlug,
|
||||
}: EventTypeListHeadingProps): JSX.Element => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
@@ -727,7 +739,9 @@ const EventTypeListHeading = ({
|
||||
)}
|
||||
{profile?.slug && (
|
||||
<Link href={`${CAL_URL}/${profile.slug}`} className="text-subtle block text-xs">
|
||||
{`${CAL_URL?.replace("https://", "")}/${profile.slug}`}
|
||||
{orgSlug
|
||||
? `${orgSlug}.${subdomainSuffix()}/${profile.slug}`
|
||||
: `${CAL_URL?.replace("https://", "")}/${profile.slug}`}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
@@ -775,6 +789,7 @@ const CTA = () => {
|
||||
|
||||
return (
|
||||
<CreateButton
|
||||
data-testid="new-event-type"
|
||||
subtitle={t("create_event_on").toUpperCase()}
|
||||
options={profileOptions}
|
||||
createDialog={() => <CreateEventTypeDialog profileOptions={profileOptions} />}
|
||||
@@ -782,6 +797,43 @@ const CTA = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const Actions = () => {
|
||||
return (
|
||||
<div className="hidden items-center md:flex">
|
||||
<OrganizationEventTypeFilter />
|
||||
<VerticalDivider />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SetupProfileBanner = ({ closeAction }: { closeAction: () => void }) => {
|
||||
const { t } = useLocale();
|
||||
const orgBranding = useOrgBrandingValues();
|
||||
|
||||
return (
|
||||
<Alert
|
||||
className="my-4"
|
||||
severity="info"
|
||||
title={t("set_up_your_profile")}
|
||||
message={t("set_up_your_profile_description", { orgName: orgBranding?.name })}
|
||||
CustomIcon={UserIcon}
|
||||
actions={
|
||||
<div className="flex gap-1">
|
||||
<Button color="minimal" className="text-sky-700 hover:bg-sky-100" onClick={closeAction}>
|
||||
{t("dismiss")}
|
||||
</Button>
|
||||
<Button
|
||||
color="secondary"
|
||||
className="border-sky-700 bg-sky-50 text-sky-700 hover:border-sky-900 hover:bg-sky-200"
|
||||
href="/getting-started">
|
||||
{t("set_up")}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const WithQuery = withQuery(trpc.viewer.eventTypes.getByViewer as any);
|
||||
|
||||
@@ -790,12 +842,24 @@ const EventTypesPage = () => {
|
||||
const router = useRouter();
|
||||
const { open } = useIntercom();
|
||||
const { query } = router;
|
||||
const { data: user } = useMeQuery();
|
||||
const isMobile = useMediaQuery("(max-width: 768px)");
|
||||
const [showProfileBanner, setShowProfileBanner] = useState(false);
|
||||
const orgBranding = useOrgBrandingValues();
|
||||
|
||||
function closeBanner() {
|
||||
setShowProfileBanner(false);
|
||||
document.cookie = `calcom-profile-banner=1;max-age=${60 * 60 * 24 * 90}`; // 3 months
|
||||
showToast(t("we_wont_show_again"), "success");
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (query?.openIntercom && query?.openIntercom === "true") {
|
||||
open();
|
||||
}
|
||||
setShowProfileBanner(
|
||||
!!orgBranding && !document.cookie.includes("calcom-profile-banner=1") && !user?.completedOnboarding
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
@@ -810,6 +874,8 @@ const EventTypesPage = () => {
|
||||
heading={t("event_types_page_title")}
|
||||
hideHeadingOnMobile
|
||||
subtitle={t("event_types_page_subtitle")}
|
||||
afterHeading={showProfileBanner && <SetupProfileBanner closeAction={closeBanner} />}
|
||||
beforeCTAactions={<Actions />}
|
||||
CTA={<CTA />}>
|
||||
<WithQuery
|
||||
customLoader={<SkeletonLoader />}
|
||||
@@ -826,6 +892,7 @@ const EventTypesPage = () => {
|
||||
profile={group.profile}
|
||||
membershipCount={group.metadata.membershipCount}
|
||||
teamId={group.teamId}
|
||||
orgSlug={orgBranding?.slug}
|
||||
/>
|
||||
|
||||
<EventTypeList
|
||||
|
||||
@@ -3,15 +3,16 @@ import { serverSideTranslations } from "next-i18next/serverSideTranslations";
|
||||
import Head from "next/head";
|
||||
import { useRouter } from "next/router";
|
||||
import type { CSSProperties } from "react";
|
||||
import { Suspense } from "react";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { trpc } from "@calcom/trpc";
|
||||
import { Button, StepCard, Steps } from "@calcom/ui";
|
||||
|
||||
import type { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
import { Loader } from "@calcom/ui/components/icon";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
import { ConnectedCalendars } from "@components/getting-started/steps-views/ConnectCalendars";
|
||||
@@ -20,7 +21,7 @@ import { SetupAvailability } from "@components/getting-started/steps-views/Setup
|
||||
import UserProfile from "@components/getting-started/steps-views/UserProfile";
|
||||
import { UserSettings } from "@components/getting-started/steps-views/UserSettings";
|
||||
|
||||
export type IOnboardingPageProps = inferSSRProps<typeof getServerSideProps>;
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
const INITIAL_STEP = "user-settings";
|
||||
const steps = [
|
||||
@@ -44,9 +45,9 @@ const stepRouteSchema = z.object({
|
||||
});
|
||||
|
||||
// TODO: Refactor how steps work to be contained in one array/object. Currently we have steps,initalsteps,headers etc. These can all be in one place
|
||||
const OnboardingPage = (props: IOnboardingPageProps) => {
|
||||
const OnboardingPage = () => {
|
||||
const router = useRouter();
|
||||
const { user } = props;
|
||||
const [user] = trpc.viewer.me.useSuspenseQuery();
|
||||
const { t } = useLocale();
|
||||
|
||||
const result = stepRouteSchema.safeParse(router.query);
|
||||
@@ -139,17 +140,20 @@ const OnboardingPage = (props: IOnboardingPageProps) => {
|
||||
<Steps maxSteps={steps.length} currentStep={currentStepIndex + 1} navigateToStep={goToIndex} />
|
||||
</div>
|
||||
<StepCard>
|
||||
{currentStep === "user-settings" && <UserSettings user={user} nextStep={() => goToIndex(1)} />}
|
||||
<Suspense fallback={<Loader />}>
|
||||
{currentStep === "user-settings" && <UserSettings nextStep={() => goToIndex(1)} />}
|
||||
{currentStep === "connected-calendar" && <ConnectedCalendars nextStep={() => goToIndex(2)} />}
|
||||
|
||||
{currentStep === "connected-calendar" && <ConnectedCalendars nextStep={() => goToIndex(2)} />}
|
||||
{currentStep === "connected-video" && <ConnectedVideoStep nextStep={() => goToIndex(3)} />}
|
||||
|
||||
{currentStep === "connected-video" && <ConnectedVideoStep nextStep={() => goToIndex(3)} />}
|
||||
|
||||
{currentStep === "setup-availability" && (
|
||||
<SetupAvailability nextStep={() => goToIndex(4)} defaultScheduleId={user.defaultScheduleId} />
|
||||
)}
|
||||
|
||||
{currentStep === "user-profile" && <UserProfile user={user} />}
|
||||
{currentStep === "setup-availability" && (
|
||||
<SetupAvailability
|
||||
nextStep={() => goToIndex(4)}
|
||||
defaultScheduleId={user.defaultScheduleId}
|
||||
/>
|
||||
)}
|
||||
{currentStep === "user-profile" && <UserProfile />}
|
||||
</Suspense>
|
||||
</StepCard>
|
||||
|
||||
{headers[currentStepIndex]?.skipText && (
|
||||
@@ -176,34 +180,21 @@ const OnboardingPage = (props: IOnboardingPageProps) => {
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
const { req, res } = context;
|
||||
|
||||
const crypto = await import("crypto");
|
||||
const session = await getServerSession({ req, res });
|
||||
|
||||
if (!session?.user?.id) {
|
||||
return { redirect: { permanent: false, destination: "/auth/login" } };
|
||||
}
|
||||
|
||||
const ssr = await ssrInit(context);
|
||||
|
||||
await ssr.viewer.me.prefetch();
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: session.user.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
name: true,
|
||||
email: true,
|
||||
bio: true,
|
||||
avatar: true,
|
||||
timeZone: true,
|
||||
weekStart: true,
|
||||
hideBranding: true,
|
||||
theme: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
metadata: true,
|
||||
timeFormat: true,
|
||||
allowDynamicBooking: true,
|
||||
defaultScheduleId: true,
|
||||
completedOnboarding: true,
|
||||
teams: {
|
||||
select: {
|
||||
@@ -231,10 +222,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(context.locale ?? "", ["common"])),
|
||||
user: {
|
||||
...user,
|
||||
emailMd5: crypto.createHash("md5").update(user.email).digest("hex"),
|
||||
},
|
||||
trpcState: ssr.dehydrate(),
|
||||
hasPendingInvites: user.teams.find((team) => team.accepted === false) ?? false,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ const Heading = () => {
|
||||
return (
|
||||
<div className="min-w-52 hidden md:block">
|
||||
<h3 className="font-cal max-w-28 sm:max-w-72 md:max-w-80 text-emphasis truncate text-xl font-semibold tracking-wide xl:max-w-full">
|
||||
{t("analytics_for_organisation")}
|
||||
{t("insights")}
|
||||
</h3>
|
||||
<p className="text-default hidden text-sm md:block">{t("subtitle_analytics")}</p>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,8 @@ import { Booker } from "@calcom/atoms";
|
||||
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
||||
import { getBookingByUidOrRescheduleUid } from "@calcom/features/bookings/lib/get-booking";
|
||||
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import { classNames } from "@calcom/lib";
|
||||
import { getUsernameList } from "@calcom/lib/defaultEvents";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
@@ -15,8 +17,9 @@ import PageWrapper from "@components/PageWrapper";
|
||||
type PageProps = inferSSRProps<typeof getServerSideProps>;
|
||||
|
||||
export default function Type({ slug, user, booking, away, isBrandingHidden }: PageProps) {
|
||||
const isEmbed = typeof window !== "undefined" && window?.isEmbed?.();
|
||||
return (
|
||||
<main className="flex h-full min-h-[100dvh] items-center justify-center">
|
||||
<main className={classNames("flex h-full items-center justify-center", !isEmbed && "min-h-[100dvh]")}>
|
||||
<BookerSeo
|
||||
username={user}
|
||||
eventSlug={slug}
|
||||
@@ -84,6 +87,7 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
||||
away: false,
|
||||
trpcState: ssr.dehydrate(),
|
||||
isBrandingHidden: false,
|
||||
themeBasis: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -91,12 +95,18 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) {
|
||||
async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||
const { user: username, type: slug } = paramsSchema.parse(context.params);
|
||||
const { rescheduleUid } = context.query;
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
|
||||
|
||||
const { ssrInit } = await import("@server/lib/ssr");
|
||||
const ssr = await ssrInit(context);
|
||||
const user = await prisma.user.findUnique({
|
||||
const user = await prisma.user.findFirst({
|
||||
where: {
|
||||
username,
|
||||
organization: isValidOrgDomain
|
||||
? {
|
||||
slug: currentOrgDomain,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
select: {
|
||||
away: true,
|
||||
@@ -133,6 +143,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||
slug,
|
||||
trpcState: ssr.dehydrate(),
|
||||
isBrandingHidden: user?.hideBranding,
|
||||
themeBasis: username,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -143,7 +154,7 @@ const paramsSchema = z.object({ type: z.string(), user: z.string() });
|
||||
// whether the page should show an away state or dynamic booking not allowed.
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
const { user } = paramsSchema.parse(context.params);
|
||||
const isDynamicGroup = user.includes("+");
|
||||
const isDynamicGroup = getUsernameList(user).length > 1;
|
||||
|
||||
return isDynamicGroup ? await getDynamicGroupPageProps(context) : await getUserPageProps(context);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import withEmbedSsr from "@lib/withEmbedSsr";
|
||||
|
||||
import { getServerSideProps as _getServerSideProps } from "../[type]";
|
||||
|
||||
export { default } from "../[type]";
|
||||
|
||||
// Somehow these types don't accept the {notFound: true} return type.
|
||||
// Probably still need to fix this. I don't know why this isn't allowed yet.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
export const getServerSideProps = withEmbedSsr(_getServerSideProps);
|
||||
@@ -0,0 +1,7 @@
|
||||
import withEmbedSsr from "@lib/withEmbedSsr";
|
||||
|
||||
import { getServerSideProps as _getServerSideProps } from "../../[user]";
|
||||
|
||||
export { default } from "../../[user]";
|
||||
|
||||
export const getServerSideProps = withEmbedSsr(_getServerSideProps);
|
||||
@@ -5,6 +5,7 @@ import { Booker } from "@calcom/atoms";
|
||||
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
||||
import { getBookingByUidOrRescheduleUid } from "@calcom/features/bookings/lib/get-booking";
|
||||
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
@@ -38,6 +39,7 @@ Type.PageWrapper = PageWrapper;
|
||||
async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||
const { link, slug } = paramsSchema.parse(context.params);
|
||||
const { rescheduleUid } = context.query;
|
||||
const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
|
||||
|
||||
const { ssrInit } = await import("@server/lib/ssr");
|
||||
const ssr = await ssrInit(context);
|
||||
@@ -68,9 +70,14 @@ async function getUserPageProps(context: GetServerSidePropsContext) {
|
||||
};
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
const user = await prisma.user.findFirst({
|
||||
where: {
|
||||
username,
|
||||
organization: isValidOrgDomain
|
||||
? {
|
||||
slug: currentOrgDomain,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
select: {
|
||||
away: true,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Booker } from "@calcom/atoms";
|
||||
import { BookerSeo } from "@calcom/features/bookings/components/BookerSeo";
|
||||
import { getBookingByUidOrRescheduleUid } from "@calcom/features/bookings/lib/get-booking";
|
||||
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
|
||||
import { classNames } from "@calcom/lib";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||
@@ -14,8 +15,9 @@ import PageWrapper from "@components/PageWrapper";
|
||||
type PageProps = inferSSRProps<typeof getServerSideProps>;
|
||||
|
||||
export default function Type({ slug, user, booking, away, isBrandingHidden }: PageProps) {
|
||||
const isEmbed = typeof window !== "undefined" && window?.isEmbed?.();
|
||||
return (
|
||||
<main className="flex h-full min-h-[100dvh] items-center justify-center">
|
||||
<main className={classNames("flex h-full items-center justify-center", !isEmbed && "min-h-[100dvh]")}>
|
||||
<BookerSeo
|
||||
username={user}
|
||||
eventSlug={slug}
|
||||
@@ -85,6 +87,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
slug: meetingSlug,
|
||||
trpcState: ssr.dehydrate(),
|
||||
isBrandingHidden: team?.hideBranding,
|
||||
themeBasis: null,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import withEmbedSsr from "@lib/withEmbedSsr";
|
||||
|
||||
import { getServerSideProps as _getServerSideProps } from "../[type]";
|
||||
|
||||
export { default } from "../[type]";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
export const getServerSideProps = withEmbedSsr(_getServerSideProps);
|
||||
@@ -0,0 +1,7 @@
|
||||
import withEmbedSsr from "@lib/withEmbedSsr";
|
||||
|
||||
import { getServerSideProps as _getServerSideProps } from "../../../team/[slug]";
|
||||
|
||||
export { default } from "../../../team/[slug]";
|
||||
|
||||
export const getServerSideProps = withEmbedSsr(_getServerSideProps);
|
||||
@@ -47,15 +47,13 @@ const BillingView = () => {
|
||||
<>
|
||||
<Meta title={t("billing")} description={t("manage_billing_description")} />
|
||||
<div className="space-y-6 text-sm sm:space-y-8">
|
||||
<CtaRow
|
||||
title={t("billing_manage_details_title")}
|
||||
description={t("billing_manage_details_description")}>
|
||||
<CtaRow title={t("view_and_manage_billing_details")} description={t("view_and_edit_billing_details")}>
|
||||
<Button color="primary" href={billingHref} target="_blank" EndIcon={ExternalLink}>
|
||||
{t("billing_portal")}
|
||||
</Button>
|
||||
</CtaRow>
|
||||
|
||||
<CtaRow title={t("billing_help_title")} description={t("billing_help_description")}>
|
||||
<CtaRow title={t("need_anything_else")} description={t("further_billing_help")}>
|
||||
<Button color="secondary" onClick={onContactSupportClick}>
|
||||
{t("contact_support")}
|
||||
</Button>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { BookerLayoutSelector } from "@calcom/features/settings/BookerLayoutSelector";
|
||||
import ThemeLabel from "@calcom/features/settings/ThemeLabel";
|
||||
@@ -9,6 +10,7 @@ import { checkWCAGContrastColor } from "@calcom/lib/getBrandColours";
|
||||
import { useHasPaidPlan } from "@calcom/lib/hooks/useHasPaidPlan";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { validateBookerLayouts } from "@calcom/lib/validateBookerLayouts";
|
||||
import type { userMetadata } from "@calcom/prisma/zod-utils";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import {
|
||||
Alert,
|
||||
@@ -64,7 +66,7 @@ const AppearanceView = () => {
|
||||
brandColor: user?.brandColor || "#292929",
|
||||
darkBrandColor: user?.darkBrandColor || "#fafafa",
|
||||
hideBranding: user?.hideBranding,
|
||||
defaultBookerLayouts: user?.defaultBookerLayouts,
|
||||
metadata: user?.metadata as z.infer<typeof userMetadata>,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -99,7 +101,7 @@ const AppearanceView = () => {
|
||||
<Form
|
||||
form={formMethods}
|
||||
handleSubmit={(values) => {
|
||||
const layoutError = validateBookerLayouts(values.defaultBookerLayouts || null);
|
||||
const layoutError = validateBookerLayouts(values?.metadata?.defaultBookerLayouts || null);
|
||||
if (layoutError) throw new Error(t(layoutError));
|
||||
|
||||
mutation.mutate({
|
||||
@@ -127,14 +129,14 @@ const AppearanceView = () => {
|
||||
<ThemeLabel
|
||||
variant="light"
|
||||
value="light"
|
||||
label={t("theme_light")}
|
||||
label={t("light")}
|
||||
defaultChecked={user.theme === "light"}
|
||||
register={formMethods.register}
|
||||
/>
|
||||
<ThemeLabel
|
||||
variant="dark"
|
||||
value="dark"
|
||||
label={t("theme_dark")}
|
||||
label={t("dark")}
|
||||
defaultChecked={user.theme === "dark"}
|
||||
register={formMethods.register}
|
||||
/>
|
||||
@@ -261,7 +263,8 @@ const AppearanceView = () => {
|
||||
type="submit"
|
||||
loading={mutation.isLoading}
|
||||
color="primary"
|
||||
className="mt-8">
|
||||
className="mt-8"
|
||||
data-testid="update-theme-btn">
|
||||
{t("update")}
|
||||
</Button>
|
||||
</Form>
|
||||
|
||||
@@ -149,7 +149,7 @@ const ConferencingLayout = () => {
|
||||
});
|
||||
}
|
||||
}}>
|
||||
{t("change_default_conferencing_app")}
|
||||
{t("set_as_default")}
|
||||
</DropdownItem>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
|
||||
@@ -215,7 +215,6 @@ const ProfileView = () => {
|
||||
extraField={
|
||||
<div className="mt-8">
|
||||
<UsernameAvailabilityField
|
||||
user={user}
|
||||
onSuccessMutation={async () => {
|
||||
showToast(t("settings_updated_successfully"), "success");
|
||||
await utils.viewer.me.invalidate();
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { AboutOrganizationForm } from "@calcom/features/ee/organizations/components";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout, Meta } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const AboutOrganizationPage = () => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
if (!router.isReady) return null;
|
||||
return (
|
||||
<>
|
||||
<Meta title={t("about_your_organization")} description={t("about_your_organization_description")} />
|
||||
<AboutOrganizationForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={3} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
AboutOrganizationPage.getLayout = LayoutWrapper;
|
||||
AboutOrganizationPage.PageWrapper = PageWrapper;
|
||||
|
||||
export default AboutOrganizationPage;
|
||||
@@ -0,0 +1,37 @@
|
||||
import type { NextRouter } from "next/router";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { AddNewTeamsForm } from "@calcom/features/ee/organizations/components";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout, Meta } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const AddNewTeamsPage = () => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
if (!router.isReady) return null;
|
||||
return (
|
||||
<>
|
||||
<Meta title={t("create_your_teams")} description={t("create_your_teams_description")} />
|
||||
<AddNewTeamsForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
AddNewTeamsPage.getLayout = (page: React.ReactElement, router: NextRouter) => (
|
||||
<>
|
||||
<WizardLayout
|
||||
currentStep={5}
|
||||
maxSteps={5}
|
||||
isOptionalCallback={() => {
|
||||
router.push(`/event-types`);
|
||||
}}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
</>
|
||||
);
|
||||
|
||||
AddNewTeamsPage.PageWrapper = PageWrapper;
|
||||
|
||||
export default AddNewTeamsPage;
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { NextRouter } from "next/router";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { AddNewOrgAdminsForm } from "@calcom/features/ee/organizations/components";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout, Meta } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const OnboardTeamMembersPage = () => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
if (!router.isReady) return null;
|
||||
return (
|
||||
<>
|
||||
<Meta
|
||||
title={t("invite_organization_admins")}
|
||||
description={t("invite_organization_admins_description")}
|
||||
/>
|
||||
<AddNewOrgAdminsForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
OnboardTeamMembersPage.getLayout = (page: React.ReactElement, router: NextRouter) => (
|
||||
<WizardLayout
|
||||
currentStep={4}
|
||||
maxSteps={5}
|
||||
isOptionalCallback={() => {
|
||||
router.push(`/settings/organizations/${router.query.id}/add-teams`);
|
||||
}}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
|
||||
OnboardTeamMembersPage.PageWrapper = PageWrapper;
|
||||
|
||||
export default OnboardTeamMembersPage;
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { SetPasswordForm } from "@calcom/features/ee/organizations/components";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout, Meta } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const SetPasswordPage = () => {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
if (!router.isReady) return null;
|
||||
return (
|
||||
<>
|
||||
<Meta title={t("set_a_password")} description={t("set_a_password_description")} />
|
||||
<SetPasswordForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={2} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
SetPasswordPage.getLayout = LayoutWrapper;
|
||||
SetPasswordPage.PageWrapper = PageWrapper;
|
||||
|
||||
export default SetPasswordPage;
|
||||
@@ -0,0 +1,9 @@
|
||||
import OrgAppearanceView from "@calcom/features/ee/organizations/pages/settings/appearance";
|
||||
|
||||
import type { CalPageWrapper } from "@components/PageWrapper";
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const Page = OrgAppearanceView as CalPageWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,9 @@
|
||||
import OrgGeneralView from "@calcom/features/ee/organizations/pages/settings/general";
|
||||
|
||||
import type { CalPageWrapper } from "@components/PageWrapper";
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const Page = OrgGeneralView as CalPageWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,9 @@
|
||||
import MembersView from "@calcom/features/ee/organizations/pages/settings/members";
|
||||
|
||||
import type { CalPageWrapper } from "@components/PageWrapper";
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const Page = MembersView as CalPageWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,27 @@
|
||||
import { CreateANewOrganizationForm } from "@calcom/features/ee/organizations/components";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout, Meta } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const CreateNewOrganizationPage = () => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
<>
|
||||
<Meta title={t("set_up_your_organization")} description={t("organizations_description")} />
|
||||
<CreateANewOrganizationForm />
|
||||
</>
|
||||
);
|
||||
};
|
||||
const LayoutWrapper = (page: React.ReactElement) => {
|
||||
return (
|
||||
<WizardLayout currentStep={1} maxSteps={5}>
|
||||
{page}
|
||||
</WizardLayout>
|
||||
);
|
||||
};
|
||||
|
||||
CreateNewOrganizationPage.getLayout = LayoutWrapper;
|
||||
CreateNewOrganizationPage.PageWrapper = PageWrapper;
|
||||
|
||||
export default CreateNewOrganizationPage;
|
||||
@@ -0,0 +1,9 @@
|
||||
import OrgProfileView from "@calcom/features/ee/organizations/pages/settings/profile";
|
||||
|
||||
import type { CalPageWrapper } from "@components/PageWrapper";
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
const Page = OrgProfileView as CalPageWrapper;
|
||||
Page.PageWrapper = PageWrapper;
|
||||
|
||||
export default Page;
|
||||
@@ -36,7 +36,7 @@ const TwoFactorAuthView = () => {
|
||||
const isCalProvider = user?.identityProvider === "CAL";
|
||||
return (
|
||||
<>
|
||||
<Meta title={t("2fa")} description={t("2fa_description")} />
|
||||
<Meta title={t("2fa")} description={t("set_up_two_factor_authentication")} />
|
||||
{!isCalProvider && <Alert severity="neutral" message={t("2fa_disabled")} />}
|
||||
<div className="mt-6 flex items-start space-x-4">
|
||||
<Switch
|
||||
|
||||
@@ -2,9 +2,9 @@ import Head from "next/head";
|
||||
|
||||
import AddNewTeamMembers from "@calcom/features/ee/teams/components/AddNewTeamMembers";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
import WizardLayout from "@components/layouts/WizardLayout";
|
||||
|
||||
const OnboardTeamMembersPage = () => {
|
||||
const { t } = useLocale();
|
||||
|
||||
@@ -2,9 +2,9 @@ import Head from "next/head";
|
||||
|
||||
import { CreateANewTeamForm } from "@calcom/features/ee/teams/components";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { WizardLayout } from "@calcom/ui";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
import WizardLayout from "@components/layouts/WizardLayout";
|
||||
|
||||
const CreateNewTeamPage = () => {
|
||||
const { t } = useLocale();
|
||||
|
||||
+122
-41
@@ -5,8 +5,9 @@ import { useRouter } from "next/router";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { sdkActionManager, useIsEmbed } from "@calcom/embed-core/embed-iframe";
|
||||
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
|
||||
import EventTypeDescription from "@calcom/features/eventtypes/components/EventTypeDescription";
|
||||
import { CAL_URL } from "@calcom/lib/constants";
|
||||
import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import useTheme from "@calcom/lib/hooks/useTheme";
|
||||
@@ -15,6 +16,7 @@ import { getTeamWithMembers } from "@calcom/lib/server/queries/teams";
|
||||
import { stripMarkdown } from "@calcom/lib/stripMarkdown";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
|
||||
import { Avatar, AvatarGroup, Button, EmptyScreen, HeadSeo } from "@calcom/ui";
|
||||
import { ArrowRight } from "@calcom/ui/components/icon";
|
||||
|
||||
@@ -27,7 +29,7 @@ import Team from "@components/team/screens/Team";
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
export type TeamPageProps = inferSSRProps<typeof getServerSideProps>;
|
||||
function TeamPage({ team, isUnpublished, markdownStrippedBio }: TeamPageProps) {
|
||||
function TeamPage({ team, isUnpublished, markdownStrippedBio, isValidOrgDomain }: TeamPageProps) {
|
||||
useTheme(team.theme);
|
||||
const showMembers = useToggleQuery("members");
|
||||
const { t } = useLocale();
|
||||
@@ -36,6 +38,7 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio }: TeamPageProps) {
|
||||
const router = useRouter();
|
||||
const teamName = team.name || "Nameless Team";
|
||||
const isBioEmpty = !team.bio || !team.bio.replace("<p><br></p>", "").length;
|
||||
const metadata = teamMetadataSchema.parse(team.metadata);
|
||||
|
||||
useEffect(() => {
|
||||
telemetry.event(
|
||||
@@ -49,8 +52,12 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio }: TeamPageProps) {
|
||||
<div className="m-8 flex items-center justify-center">
|
||||
<EmptyScreen
|
||||
avatar={<Avatar alt={teamName} imageSrc={getPlaceholderAvatar(team.logo, team.name)} size="lg" />}
|
||||
headline={t("team_is_unpublished", { team: teamName })}
|
||||
description={t("team_is_unpublished_description")}
|
||||
headline={t("team_is_unpublished", {
|
||||
team: teamName,
|
||||
})}
|
||||
description={t("team_is_unpublished_description", {
|
||||
entity: metadata?.isOrganization ? t("organization").toLowerCase() : t("team").toLowerCase(),
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -71,7 +78,7 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio }: TeamPageProps) {
|
||||
<div className="px-6 py-4 ">
|
||||
<Link
|
||||
href={{
|
||||
pathname: `/team/${team.slug}/${type.slug}`,
|
||||
pathname: `${isValidOrgDomain ? "" : "/team"}/${team.slug}/${type.slug}`,
|
||||
query: queryParamsToForward,
|
||||
}}
|
||||
onClick={async () => {
|
||||
@@ -106,6 +113,53 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio }: TeamPageProps) {
|
||||
</ul>
|
||||
);
|
||||
|
||||
const SubTeams = () =>
|
||||
team.children.length ? (
|
||||
<ul className="divide-subtle border-subtle bg-default !static w-full divide-y rounded-md border">
|
||||
{team.children.map((ch, i) => (
|
||||
<li key={i} className="hover:bg-muted w-full">
|
||||
<Link href={`/${ch.slug}`} className="flex items-center justify-between">
|
||||
<div className="flex items-center px-5 py-5">
|
||||
<Avatar
|
||||
size="md"
|
||||
imageSrc={getPlaceholderAvatar(ch?.logo, ch?.name as string)}
|
||||
alt="Team Logo"
|
||||
className="inline-flex justify-center"
|
||||
/>
|
||||
<div className="ms-3 inline-block truncate">
|
||||
<span className="text-default text-sm font-bold">{ch.name}</span>
|
||||
<span className="text-subtle block text-xs">
|
||||
{t("number_member", { count: ch.members.length })}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<AvatarGroup
|
||||
className="mr-6"
|
||||
size="sm"
|
||||
truncateAfter={4}
|
||||
items={ch.members.map(({ user: member }) => ({
|
||||
alt: member.name || "",
|
||||
image: `${WEBAPP_URL}/${member.username}/avatar.png`,
|
||||
title: member.name || "",
|
||||
}))}
|
||||
/>
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<div className="space-y-6" data-testid="event-types">
|
||||
<div className="overflow-hidden rounded-sm border dark:border-gray-900">
|
||||
<div className="text-muted dark:text-inverted p-8 text-center">
|
||||
<h2 className="font-cal dark:text-inverted text-emphasis600 mb-2 text-3xl">
|
||||
{" " + t("no_teams_yet")}
|
||||
</h2>
|
||||
<p className="mx-auto max-w-md">{t("no_teams_yet_description")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeadSeo
|
||||
@@ -118,8 +172,17 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio }: TeamPageProps) {
|
||||
/>
|
||||
<main className="dark:bg-darkgray-50 bg-subtle mx-auto max-w-3xl rounded-md px-4 pt-12 pb-12">
|
||||
<div className="mx-auto mb-8 max-w-3xl text-center">
|
||||
<Avatar alt={teamName} imageSrc={getPlaceholderAvatar(team.logo, team.name)} size="lg" />
|
||||
<p className="font-cal text-emphasis mb-2 text-2xl tracking-wider">{teamName}</p>
|
||||
<div className="relative">
|
||||
<Avatar
|
||||
alt={teamName}
|
||||
imageSrc={getPlaceholderAvatar(team.parent ? team.parent.logo : team.logo, team.name)}
|
||||
size="lg"
|
||||
/>
|
||||
</div>
|
||||
<p className="font-cal text-emphasis mb-2 text-2xl tracking-wider">
|
||||
{team.parent && `${team.parent.name} `}
|
||||
{teamName}
|
||||
</p>
|
||||
{!isBioEmpty && (
|
||||
<>
|
||||
<div
|
||||
@@ -129,43 +192,49 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio }: TeamPageProps) {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{(showMembers.isOn || !team.eventTypes.length) && <Team team={team} />}
|
||||
{!showMembers.isOn && team.eventTypes.length > 0 && (
|
||||
<div className="mx-auto max-w-3xl ">
|
||||
<EventTypes />
|
||||
{metadata?.isOrganization ? (
|
||||
<SubTeams />
|
||||
) : (
|
||||
<>
|
||||
{(showMembers.isOn || !team.eventTypes.length) && <Team team={team} />}
|
||||
{!showMembers.isOn && team.eventTypes.length > 0 && (
|
||||
<div className="mx-auto max-w-3xl ">
|
||||
<EventTypes />
|
||||
|
||||
{!team.hideBookATeamMember && (
|
||||
<div>
|
||||
<div className="relative mt-12">
|
||||
<div className="absolute inset-0 flex items-center" aria-hidden="true">
|
||||
<div className="border-subtle w-full border-t" />
|
||||
</div>
|
||||
<div className="relative flex justify-center">
|
||||
<span className="dark:bg-darkgray-50 bg-subtle text-subtle dark:text-inverted px-2 text-sm">
|
||||
{t("or")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{!team.hideBookATeamMember && (
|
||||
<div>
|
||||
<div className="relative mt-12">
|
||||
<div className="absolute inset-0 flex items-center" aria-hidden="true">
|
||||
<div className="border-subtle w-full border-t" />
|
||||
</div>
|
||||
<div className="relative flex justify-center">
|
||||
<span className="dark:bg-darkgray-50 bg-subtle text-subtle dark:text-inverted px-2 text-sm">
|
||||
{t("or")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside className="dark:text-inverted mt-8 flex justify-center text-center">
|
||||
<Button
|
||||
color="minimal"
|
||||
EndIcon={ArrowRight}
|
||||
className="dark:hover:bg-darkgray-200"
|
||||
href={{
|
||||
pathname: `/team/${team.slug}`,
|
||||
query: {
|
||||
members: "1",
|
||||
...queryParamsToForward,
|
||||
},
|
||||
}}
|
||||
shallow={true}>
|
||||
{t("book_a_team_member")}
|
||||
</Button>
|
||||
</aside>
|
||||
<aside className="dark:text-inverted mt-8 flex justify-center text-center">
|
||||
<Button
|
||||
color="minimal"
|
||||
EndIcon={ArrowRight}
|
||||
className="dark:hover:bg-darkgray-200"
|
||||
href={{
|
||||
pathname: `${isValidOrgDomain ? "" : "/team"}/${team.slug}`,
|
||||
query: {
|
||||
members: "1",
|
||||
...queryParamsToForward,
|
||||
},
|
||||
}}
|
||||
shallow={true}>
|
||||
{t("book_a_team_member")}
|
||||
</Button>
|
||||
</aside>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</main>
|
||||
</>
|
||||
@@ -175,8 +244,19 @@ function TeamPage({ team, isUnpublished, markdownStrippedBio }: TeamPageProps) {
|
||||
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
|
||||
const ssr = await ssrInit(context);
|
||||
const slug = Array.isArray(context.query?.slug) ? context.query.slug.pop() : context.query.slug;
|
||||
const { isValidOrgDomain } = orgDomainConfig(context.req.headers.host ?? "");
|
||||
|
||||
const team = await getTeamWithMembers(undefined, slug);
|
||||
const metadata = teamMetadataSchema.parse(team?.metadata ?? {});
|
||||
|
||||
// Taking care of sub-teams and orgs
|
||||
if (
|
||||
(isValidOrgDomain && team?.parent && !!metadata?.isOrganization) ||
|
||||
(!isValidOrgDomain && team?.parent) ||
|
||||
(!isValidOrgDomain && !!metadata?.isOrganization)
|
||||
) {
|
||||
return { notFound: true } as const;
|
||||
}
|
||||
|
||||
if (!team) {
|
||||
const unpublishedTeam = await prisma.team.findFirst({
|
||||
@@ -193,7 +273,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
return {
|
||||
props: {
|
||||
isUnpublished: true,
|
||||
team: unpublishedTeam,
|
||||
team: { ...unpublishedTeam, createdAt: null },
|
||||
trpcState: ssr.dehydrate(),
|
||||
},
|
||||
} as const;
|
||||
@@ -222,6 +302,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
themeBasis: team.slug,
|
||||
trpcState: ssr.dehydrate(),
|
||||
markdownStrippedBio,
|
||||
isValidOrgDomain,
|
||||
},
|
||||
} as const;
|
||||
};
|
||||
|
||||
@@ -76,7 +76,6 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
title: true,
|
||||
availability: true,
|
||||
description: true,
|
||||
@@ -132,6 +131,12 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
|
||||
},
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
select: {
|
||||
logo: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -86,6 +86,12 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
theme: true,
|
||||
brandColor: true,
|
||||
darkBrandColor: true,
|
||||
parent: {
|
||||
select: {
|
||||
logo: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
users: {
|
||||
|
||||
@@ -12,6 +12,7 @@ import classNames from "@calcom/lib/classNames";
|
||||
import { APP_NAME, SEO_IMG_OGIMG_VIDEO, WEBSITE_URL } from "@calcom/lib/constants";
|
||||
import { formatToLocalizedDate, formatToLocalizedTime } from "@calcom/lib/date-fns";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
|
||||
import prisma, { bookingMinimalSelect } from "@calcom/prisma";
|
||||
import type { inferSSRProps } from "@calcom/types/inferSSRProps";
|
||||
import { ChevronRight } from "@calcom/ui/components/icon";
|
||||
@@ -244,7 +245,7 @@ export function VideoMeetingInfo(props: VideoMeetingInfo) {
|
||||
|
||||
<div
|
||||
className="prose-sm prose prose-invert"
|
||||
dangerouslySetInnerHTML={{ __html: booking.description }}
|
||||
dangerouslySetInnerHTML={{ __html: markdownToSafeHTML(booking.description) }}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -109,15 +109,14 @@ testBothBookers.describe("pro user", () => {
|
||||
await pro.apiLogin();
|
||||
|
||||
await page.goto("/bookings/upcoming");
|
||||
await page.locator('[data-testid="cancel"]').first().click();
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.waitForURL((url) => {
|
||||
return url.pathname.startsWith("/booking/");
|
||||
});
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
|
||||
const cancelledHeadline = await page.locator('[data-testid="cancelled-headline"]').innerText();
|
||||
|
||||
expect(cancelledHeadline).toBe("This event is cancelled");
|
||||
const cancelledHeadline = page.locator('[data-testid="cancelled-headline"]');
|
||||
await expect(cancelledHeadline).toBeVisible();
|
||||
|
||||
await expect(page.locator(`[data-testid="attendee-email-${testEmail}"]`)).toHaveText(testEmail);
|
||||
await expect(page.locator(`[data-testid="attendee-name-${testName}"]`)).toHaveText(testName);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { expect } from "@playwright/test";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import { uuid } from "short-uuid";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
@@ -21,7 +22,14 @@ async function createUserWithSeatedEvent(users: Fixtures["users"]) {
|
||||
const slug = "seats";
|
||||
const user = await users.create({
|
||||
eventTypes: [
|
||||
{ title: "Seated event", slug, seatsPerTimeSlot: 10, requiresConfirmation: true, length: 30 },
|
||||
{
|
||||
title: "Seated event",
|
||||
slug,
|
||||
seatsPerTimeSlot: 10,
|
||||
requiresConfirmation: true,
|
||||
length: 30,
|
||||
disableGuests: true, // should always be true for seated events
|
||||
},
|
||||
],
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
@@ -105,21 +113,13 @@ testBothBookers.describe("Booking with Seats", (bookerVariant) => {
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Make E2E test: Attendee #1 should be able to cancel his booking
|
||||
// todo("Attendee #1 should be able to cancel his booking");
|
||||
// TODO: Make E2E test: Attendee #1 should be able to reschedule his booking
|
||||
// todo("Attendee #1 should be able to reschedule his booking");
|
||||
// TODO: Make E2E test: All attendees canceling should delete the booking for the User
|
||||
// todo("All attendees canceling should delete the booking for the User");
|
||||
});
|
||||
|
||||
testBothBookers.describe("Reschedule for booking with seats", () => {
|
||||
test("Should reschedule booking with seats", async ({ page, users, bookings }) => {
|
||||
test(`Attendees can cancel a seated event time slot`, async ({ page, users, bookings }) => {
|
||||
const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [
|
||||
{ name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" },
|
||||
{ name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" },
|
||||
{ name: "John Third", email: "third+seats@cal.com", timeZone: "Europe/Berlin" },
|
||||
]);
|
||||
|
||||
const bookingAttendees = await prisma.attendee.findMany({
|
||||
where: { bookingId: booking.id },
|
||||
select: {
|
||||
@@ -137,6 +137,81 @@ testBothBookers.describe("Reschedule for booking with seats", () => {
|
||||
data: bookingSeats,
|
||||
});
|
||||
|
||||
await test.step("Attendee #1 should be able to cancel their booking", async () => {
|
||||
await page.goto(`/booking/${booking.uid}?seatReferenceUid=${bookingSeats[0].referenceUid}`);
|
||||
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.fill('[data-testid="cancel_reason"]', "Double booked!");
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page).toHaveURL(/.*booking/);
|
||||
|
||||
const cancelledHeadline = page.locator('[data-testid="cancelled-headline"]');
|
||||
await expect(cancelledHeadline).toBeVisible();
|
||||
|
||||
// Old booking should still exist, with one less attendee
|
||||
const updatedBooking = await prisma.booking.findFirst({
|
||||
where: { id: bookingSeats[0].bookingId },
|
||||
include: { attendees: true },
|
||||
});
|
||||
|
||||
const attendeeIds = updatedBooking?.attendees.map(({ id }) => id);
|
||||
expect(attendeeIds).toHaveLength(2);
|
||||
expect(attendeeIds).not.toContain(bookingAttendees[0].id);
|
||||
});
|
||||
|
||||
await test.step("All attendees cancelling should delete the booking for the user", async () => {
|
||||
// The remaining 2 attendees cancel
|
||||
for (let i = 1; i < bookingSeats.length; i++) {
|
||||
await page.goto(`/booking/${booking.uid}?seatReferenceUid=${bookingSeats[i].referenceUid}`);
|
||||
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.fill('[data-testid="cancel_reason"]', "Double booked!");
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page).toHaveURL(/.*booking/);
|
||||
|
||||
const cancelledHeadline = page.locator('[data-testid="cancelled-headline"]');
|
||||
await expect(cancelledHeadline).toBeVisible();
|
||||
}
|
||||
|
||||
// Should expect old booking to be cancelled
|
||||
const updatedBooking = await prisma.booking.findFirst({
|
||||
where: { id: bookingSeats[0].bookingId },
|
||||
});
|
||||
expect(updatedBooking).not.toBeNull();
|
||||
expect(updatedBooking?.status).toBe(BookingStatus.CANCELLED);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
testBothBookers.describe("Reschedule for booking with seats", () => {
|
||||
test("Should reschedule booking with seats", async ({ page, users, bookings }) => {
|
||||
const { booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [
|
||||
{ name: "John First", email: `first+seats-${uuid()}@cal.com`, timeZone: "Europe/Berlin" },
|
||||
{ name: "Jane Second", email: `second+seats-${uuid()}@cal.com`, timeZone: "Europe/Berlin" },
|
||||
{ name: "John Third", email: `third+seats-${uuid()}@cal.com`, timeZone: "Europe/Berlin" },
|
||||
]);
|
||||
const bookingAttendees = await prisma.attendee.findMany({
|
||||
where: { bookingId: booking.id },
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
},
|
||||
});
|
||||
|
||||
const bookingSeats = [
|
||||
{ bookingId: booking.id, attendeeId: bookingAttendees[0].id, referenceUid: uuidv4() },
|
||||
{ bookingId: booking.id, attendeeId: bookingAttendees[1].id, referenceUid: uuidv4() },
|
||||
{ bookingId: booking.id, attendeeId: bookingAttendees[2].id, referenceUid: uuidv4() },
|
||||
];
|
||||
|
||||
await prisma.bookingSeat.createMany({
|
||||
data: bookingSeats,
|
||||
});
|
||||
|
||||
const references = await prisma.bookingSeat.findMany({
|
||||
where: { bookingId: booking.id },
|
||||
});
|
||||
@@ -156,6 +231,20 @@ testBothBookers.describe("Reschedule for booking with seats", () => {
|
||||
|
||||
await expect(page).toHaveURL(/.*booking/);
|
||||
|
||||
// Should expect new booking to be created for John Third
|
||||
const newBooking = await prisma.booking.findFirst({
|
||||
where: {
|
||||
attendees: {
|
||||
some: { email: bookingAttendees[2].email },
|
||||
},
|
||||
},
|
||||
include: { seatsReferences: true, attendees: true },
|
||||
});
|
||||
expect(newBooking?.status).toBe(BookingStatus.PENDING);
|
||||
expect(newBooking?.attendees.length).toBe(1);
|
||||
expect(newBooking?.attendees[0].name).toBe("John Third");
|
||||
expect(newBooking?.seatsReferences.length).toBe(1);
|
||||
|
||||
// Should expect old booking to be accepted with two attendees
|
||||
const oldBooking = await prisma.booking.findFirst({
|
||||
where: { uid: booking.uid },
|
||||
@@ -260,7 +349,7 @@ testBothBookers.describe("Reschedule for booking with seats", () => {
|
||||
// Now we cancel the booking as the organizer
|
||||
await page.goto(`/booking/${booking.uid}?cancel=true`);
|
||||
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
@@ -309,7 +398,7 @@ testBothBookers.describe("Reschedule for booking with seats", () => {
|
||||
`/booking/${references[0].referenceUid}?cancel=true&seatReferenceUid=${references[0].referenceUid}`
|
||||
);
|
||||
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
|
||||
const oldBooking = await prisma.booking.findFirst({
|
||||
where: { uid: booking.uid },
|
||||
@@ -364,7 +453,7 @@ testBothBookers.describe("Reschedule for booking with seats", () => {
|
||||
`/booking/${booking.uid}?cancel=true&allRemainingBookings=false&seatReferenceUid=${bookingSeats[0].referenceUid}`
|
||||
);
|
||||
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
@@ -375,7 +464,7 @@ testBothBookers.describe("Reschedule for booking with seats", () => {
|
||||
);
|
||||
|
||||
// Page should not be 404
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
import { test } from "./lib/fixtures";
|
||||
|
||||
test.describe("Change Theme Test", () => {
|
||||
test("change theme to dark", async ({ page, users }) => {
|
||||
const pro = await users.create();
|
||||
await pro.apiLogin();
|
||||
|
||||
await page.goto("/settings/my-account/appearance");
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
//Click the "Dark" theme label
|
||||
await page.click('[data-testid="theme-dark"]');
|
||||
//Click the update button
|
||||
await page.click('[data-testid="update-theme-btn"]');
|
||||
//Wait for the toast to appear
|
||||
const toast = await page.waitForSelector("div[class*='data-testid-toast-success']");
|
||||
expect(toast).toBeTruthy();
|
||||
//Go to the profile page and check if the theme is dark
|
||||
await page.goto(`/${pro.username}`);
|
||||
const darkModeClass = await page.getAttribute("html", "class");
|
||||
expect(darkModeClass).toContain("dark");
|
||||
});
|
||||
|
||||
test("change theme to light", async ({ page, users }) => {
|
||||
const pro = await users.create();
|
||||
await pro.apiLogin();
|
||||
|
||||
await page.goto("/settings/my-account/appearance");
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
//Click the "Light" theme label
|
||||
await page.click('[data-testid="theme-light"]');
|
||||
//Click the update theme button
|
||||
await page.click('[data-testid="update-theme-btn"]');
|
||||
//Wait for the toast to appear
|
||||
const toast = await page.waitForSelector("div[class*='data-testid-toast-success']");
|
||||
expect(toast).toBeTruthy();
|
||||
//Go to the profile page and check if the theme is light
|
||||
await page.goto(`/${pro.username}`);
|
||||
const darkModeClass = await page.getAttribute("html", "class");
|
||||
expect(darkModeClass).toContain("light");
|
||||
});
|
||||
});
|
||||
@@ -47,14 +47,13 @@ test.skip("dynamic booking", async ({ page, users }) => {
|
||||
|
||||
await test.step("Can cancel the recently created booking", async () => {
|
||||
await page.goto("/bookings/upcoming");
|
||||
await page.locator('[data-testid="cancel"]').first().click();
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.waitForURL((url) => {
|
||||
return url.pathname.startsWith("/booking");
|
||||
});
|
||||
await page.locator('[data-testid="cancel"]').click();
|
||||
await page.locator('[data-testid="confirm_cancel"]').click();
|
||||
|
||||
const cancelledHeadline = await page.locator('[data-testid="cancelled-headline"]').innerText();
|
||||
|
||||
expect(cancelledHeadline).toBe("This event is cancelled");
|
||||
const cancelledHeadline = page.locator('[data-testid="cancelled-headline"]');
|
||||
await expect(cancelledHeadline).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -62,6 +62,7 @@ export const createBookingsFixture = (page: Page) => {
|
||||
store.bookings.push(bookingFixture);
|
||||
return bookingFixture;
|
||||
},
|
||||
update: async (args: Prisma.BookingUpdateArgs) => await prisma.booking.update(args),
|
||||
get: () => store.bookings,
|
||||
delete: async (id: number) => {
|
||||
await prisma.booking.delete({
|
||||
@@ -80,7 +81,11 @@ const createBookingFixture = (booking: Booking, page: Page) => {
|
||||
return {
|
||||
id: store.booking.id,
|
||||
uid: store.booking.uid,
|
||||
self: async () => await prisma.booking.findUnique({ where: { id: store.booking.id } }),
|
||||
self: async () =>
|
||||
await prisma.booking.findUnique({
|
||||
where: { id: store.booking.id },
|
||||
include: { attendees: true, seatsReferences: true },
|
||||
}),
|
||||
delete: async () => await prisma.booking.delete({ where: { id: store.booking.id } }),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -77,6 +77,7 @@ export const createUsersFixture = (page: Page, workerInfo: WorkerInfo) => {
|
||||
{ title: "30 min", slug: "30-min", length: 30 },
|
||||
{ title: "Paid", slug: "paid", length: 30, price: 1000 },
|
||||
{ title: "Opt in", slug: "opt-in", requiresConfirmation: true, length: 30 },
|
||||
{ title: "Seated", slug: "seated", seatsPerTimeSlot: 2, length: 30 },
|
||||
];
|
||||
|
||||
if (opts?.eventTypes) defaultEventTypes = defaultEventTypes.concat(opts.eventTypes);
|
||||
|
||||
@@ -92,7 +92,7 @@ export async function selectFirstAvailableTimeSlotNextMonth(page: Page) {
|
||||
await page.waitForTimeout(1000);
|
||||
// TODO: Find out why the first day is always booked on tests
|
||||
await page.locator('[data-testid="day"][data-disabled="false"]').nth(1).click();
|
||||
await page.locator('[data-testid="time"]').nth(0).click();
|
||||
await page.locator('[data-testid="time"][data-disabled="false"]').nth(0).click();
|
||||
}
|
||||
|
||||
export async function selectSecondAvailableTimeSlotNextMonth(page: Page) {
|
||||
@@ -110,7 +110,7 @@ export async function selectSecondAvailableTimeSlotNextMonth(page: Page) {
|
||||
await page.waitForTimeout(1000);
|
||||
// TODO: Find out why the first day is always booked on tests
|
||||
await page.locator('[data-testid="day"][data-disabled="false"]').nth(1).click();
|
||||
await page.locator('[data-testid="time"]').nth(1).click();
|
||||
await page.locator('[data-testid="time"][data-disabled="false"]').nth(1).click();
|
||||
}
|
||||
|
||||
async function bookEventOnThisPage(page: Page) {
|
||||
@@ -170,3 +170,30 @@ export const createNewSeatedEventType = async (page: Page, args: { eventTitle: s
|
||||
await page.locator('[data-testid="offer-seats-toggle"]').click();
|
||||
await page.locator('[data-testid="update-eventtype"]').click();
|
||||
};
|
||||
|
||||
export async function gotoRoutingLink({
|
||||
page,
|
||||
formId,
|
||||
queryString = "",
|
||||
}: {
|
||||
page: Page;
|
||||
formId?: string;
|
||||
queryString?: string;
|
||||
}) {
|
||||
let previewLink = null;
|
||||
if (!formId) {
|
||||
// Instead of clicking on the preview link, we are going to the preview link directly because the earlier opens a new tab which is a bit difficult to manage with Playwright
|
||||
const href = await page.locator('[data-testid="form-action-preview"]').getAttribute("href");
|
||||
if (!href) {
|
||||
throw new Error("Preview link not found");
|
||||
}
|
||||
previewLink = href;
|
||||
} else {
|
||||
previewLink = `/forms/${formId}`;
|
||||
}
|
||||
|
||||
await page.goto(`${previewLink}${queryString ? `?${queryString}` : ""}`);
|
||||
|
||||
// HACK: There seems to be some issue with the inputs to the form getting reset if we don't wait.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
}
|
||||
|
||||
@@ -12,33 +12,28 @@ test.describe("Managed Event Types tests", () => {
|
||||
const memberUser = await users.create();
|
||||
// First we work with owner user, logging in
|
||||
await adminUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
// Making sure page loads completely
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Let's create a team
|
||||
await page.goto("/teams");
|
||||
await page.goto("/settings/teams/new");
|
||||
|
||||
await test.step("Managed event option exists for team admin", async () => {
|
||||
// Proceed to create a team
|
||||
await page.locator("text=Create Team").click();
|
||||
await page.waitForURL("/settings/teams/new");
|
||||
|
||||
// Filling team creation form wizard
|
||||
await page.locator('input[name="name"]').waitFor();
|
||||
await page.locator('input[name="name"]').fill(`${adminUser.username}'s Team`);
|
||||
await page.locator("text=Continue").click();
|
||||
await page.waitForURL(/\/settings\/teams\/(\d+)\/onboard-members$/i);
|
||||
await page.locator('[data-testid="new-member-button"]').click();
|
||||
await page.getByTestId("new-member-button").click();
|
||||
await page.locator('[placeholder="email\\@example\\.com"]').fill(`${memberUser.username}@example.com`);
|
||||
await page.locator('[data-testid="invite-new-member-button"]').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.getByTestId("invite-new-member-button").click();
|
||||
// wait for the second member to be added to the pending-member-list.
|
||||
await page.getByTestId("pending-member-list").locator("li:nth-child(2)").waitFor();
|
||||
// and publish
|
||||
await page.locator("text=Publish team").click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.waitForURL("/settings/teams/**");
|
||||
// Going to create an event type
|
||||
await page.goto("/event-types");
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.click("[data-testid=new-event-type-dropdown]");
|
||||
await page.click("[data-testid=option-team-1]");
|
||||
await page.getByTestId("new-event-type").click();
|
||||
await page.getByTestId("option-team-1").click();
|
||||
// Expecting we can add a managed event type as team owner
|
||||
await expect(page.locator('button[value="MANAGED"]')).toBeVisible();
|
||||
|
||||
@@ -46,51 +41,50 @@ test.describe("Managed Event Types tests", () => {
|
||||
await page.click('button[value="MANAGED"]');
|
||||
await page.fill("[name=title]", "managed");
|
||||
await page.click("[type=submit]");
|
||||
|
||||
await page.waitForURL("event-types/**");
|
||||
});
|
||||
|
||||
await test.step("Managed event type has unlocked fields for admin", async () => {
|
||||
await page.waitForSelector('[data-testid="update-eventtype"]');
|
||||
await page.getByTestId("update-eventtype").waitFor();
|
||||
await expect(page.locator('input[name="title"]')).toBeEditable();
|
||||
await expect(page.locator('input[name="slug"]')).toBeEditable();
|
||||
await expect(page.locator('input[name="length"]')).toBeEditable();
|
||||
await adminUser.logout();
|
||||
});
|
||||
|
||||
await test.step("Managed event type exists for added member", async () => {
|
||||
// Now we need to accept the invitation as member and come back in as admin to
|
||||
// assign the member in the managed event type
|
||||
await adminUser.logout();
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
// We wait until loading is finished
|
||||
await page.waitForSelector('[data-testid="event-types"]');
|
||||
|
||||
await page.goto("/teams");
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.locator('button[data-testid^="accept-invitation"]').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.getByText("Member").waitFor();
|
||||
|
||||
await memberUser.logout();
|
||||
|
||||
// Coming back as team owner to assign member user to managed event
|
||||
await adminUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.locator('[data-testid="event-types"] a[title="managed"]').click();
|
||||
await page.locator('[data-testid="vertical-tab-assignment"]').click();
|
||||
await page.getByTestId("event-types").locator('a[title="managed"]').click();
|
||||
await page.getByTestId("vertical-tab-assignment").click();
|
||||
await page.locator('[class$="control"]').filter({ hasText: "Select..." }).click();
|
||||
await page.locator("#react-select-5-option-1").click();
|
||||
await page.getByTestId(`select-option-${memberUser.id}`).click();
|
||||
await page.locator('[type="submit"]').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await adminUser.logout();
|
||||
await page.getByTestId("toast-success").waitFor();
|
||||
|
||||
// Coming back as member user to see if there is a managed event present after assignment
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
await page.waitForLoadState("networkidle");
|
||||
await expect(page.locator('[data-testid="event-types"] a[title="managed"]')).toBeVisible();
|
||||
await adminUser.logout();
|
||||
});
|
||||
|
||||
await test.step("Managed event type has locked fields for added member", async () => {
|
||||
page.locator('[data-testid="event-types"] a[title="managed"]').click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
// Coming back as member user to see if there is a managed event present after assignment
|
||||
await memberUser.apiLogin();
|
||||
await page.goto("/event-types");
|
||||
|
||||
await page.getByTestId("event-types").locator('a[title="managed"]').click();
|
||||
await page.waitForURL("event-types/**");
|
||||
|
||||
await expect(page.locator('input[name="title"]')).not.toBeEditable();
|
||||
await expect(page.locator('input[name="slug"]')).not.toBeEditable();
|
||||
await expect(page.locator('input[name="length"]')).not.toBeEditable();
|
||||
|
||||
@@ -221,4 +221,23 @@ testBothBookers.describe("Reschedule Tests", async () => {
|
||||
expect(newBooking).not.toBeNull();
|
||||
expect(newBooking?.status).toBe(BookingStatus.ACCEPTED);
|
||||
});
|
||||
|
||||
test("Attendee should be able to reschedule a booking", async ({ page, users, bookings }) => {
|
||||
const user = await users.create();
|
||||
const eventType = user.eventTypes[0];
|
||||
const booking = await bookings.create(user.id, user.username, eventType.id);
|
||||
|
||||
// Go to attendee's reschedule link
|
||||
await page.goto(`/reschedule/${booking.uid}`);
|
||||
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
|
||||
await page.locator('[data-testid="confirm-reschedule-button"]').click();
|
||||
|
||||
await expect(page).toHaveURL(/.*booking/);
|
||||
|
||||
const newBooking = await prisma.booking.findFirst({ where: { fromReschedule: booking?.uid } });
|
||||
expect(newBooking).not.toBeNull();
|
||||
expect(newBooking?.status).toBe(BookingStatus.ACCEPTED);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
createHttpServer,
|
||||
selectFirstAvailableTimeSlotNextMonth,
|
||||
waitFor,
|
||||
gotoRoutingLink,
|
||||
} from "./lib/testUtils";
|
||||
|
||||
test.afterEach(({ users }) => users.deleteAll());
|
||||
@@ -387,3 +388,62 @@ test.describe("BOOKING_REQUESTED", async () => {
|
||||
webhookReceiver.close();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("FORM_SUBMITTED", async () => {
|
||||
test("can submit a form and get a submission event", async ({ page, users }) => {
|
||||
const webhookReceiver = createHttpServer();
|
||||
const user = await users.create();
|
||||
|
||||
await user.apiLogin();
|
||||
|
||||
await page.goto("/settings/teams/new");
|
||||
await page.waitForLoadState("networkidle");
|
||||
const teamName = `${user.username}'s Team`;
|
||||
// Create a new team
|
||||
await page.locator('input[name="name"]').fill(teamName);
|
||||
await page.locator('input[name="slug"]').fill(teamName);
|
||||
await page.locator('button[type="submit"]').click();
|
||||
|
||||
await page.locator("text=Publish team").click();
|
||||
await page.waitForURL(/\/settings\/teams\/(\d+)\/profile$/i);
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Install Routing Forms App
|
||||
await page.goto(`/apps/routing-forms`);
|
||||
// eslint-disable-next-line playwright/no-conditional-in-test
|
||||
|
||||
await page.click('[data-testid="install-app-button"]');
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.goto(`/settings/developer/webhooks/new`);
|
||||
|
||||
// Add webhook
|
||||
await page.fill('[name="subscriberUrl"]', webhookReceiver.url);
|
||||
await page.fill('[name="secret"]', "secret");
|
||||
await Promise.all([page.click("[type=submit]"), page.goForward()]);
|
||||
|
||||
// Page contains the url
|
||||
expect(page.locator(`text='${webhookReceiver.url}'`)).toBeDefined();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.goto("/apps/routing-forms/forms");
|
||||
await page.click('[data-testid="new-routing-form"]');
|
||||
// Choose to create the Form for the user(which is the first option) and not the team
|
||||
await page.click('[data-testid="option-0"]');
|
||||
await page.fill("input[name]", "TEST FORM");
|
||||
await page.click('[data-testid="add-form"]');
|
||||
await page.waitForSelector('[data-testid="add-field"]');
|
||||
|
||||
const url = page.url();
|
||||
const formId = new URL(url).pathname.split("/").at(-1);
|
||||
|
||||
await gotoRoutingLink({ page, formId: formId });
|
||||
page.click('button[type="submit"]');
|
||||
|
||||
await waitFor(() => {
|
||||
expect(webhookReceiver.requestList.length).toBe(1);
|
||||
});
|
||||
webhookReceiver.close();
|
||||
});
|
||||
});
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -11,12 +11,9 @@
|
||||
"calcom_explained_new_user": "قم بإنهاء إعداد حسابك في {{appName}}! متبقي بضع خطوات فقط لحل جميع مشاكل الجدولة لديك.",
|
||||
"have_any_questions": "هل لديك أسئلة؟ نحن هنا للمساعدة.",
|
||||
"reset_password_subject": "{{appName}}: إرشادات إعادة تعيين كلمة المرور",
|
||||
"verify_email_banner_button": "إرسال بريد إلكتروني",
|
||||
"event_declined_subject": "تم الرفض: {{title}} في {{date}}",
|
||||
"event_cancelled_subject": "تم الإلغاء: {{title}} في {{date}}",
|
||||
"event_request_declined": "تم رفض طلب الحدث الخاص بك",
|
||||
"event_request_declined_recurring": "تم رفض طلب الحدث المتكرر الخاص بك",
|
||||
"event_request_cancelled": "تم إلغاء حدثك المُجَدْوَل",
|
||||
"organizer": "المنظِّم",
|
||||
"need_to_reschedule_or_cancel": "هل تحتاج إلى إعادة جدولة أو إلغاء؟",
|
||||
"cancellation_reason": "سبب الإلغاء (اختياري)",
|
||||
@@ -78,13 +75,9 @@
|
||||
"your_meeting_has_been_booked": "لقد تم حجز الاجتماع الخاص بك",
|
||||
"event_type_has_been_rescheduled_on_time_date": "تم إعادة جدولة {{title}} إلى {{date}}.",
|
||||
"event_has_been_rescheduled": "تم التحديث - تم إعادة جدولة الحدث الخاص بك",
|
||||
"request_reschedule_title_attendee": "طلب إعادة جدولة الحجز الخاص بك",
|
||||
"request_reschedule_subtitle": "ألغى {{organizer}} الحجز وطلب منك اختيار حجز في وقت آخر.",
|
||||
"request_reschedule_title_organizer": "لقد طلبت من {{attendee}} إعادة جدولة موعد",
|
||||
"request_reschedule_subtitle_organizer": "لقد ألغيت الحجز ويجب أن يختار {{attendee}} وقتًا جديداً للحجز معك.",
|
||||
"rescheduled_event_type_subject": "تم إرسال طلب لإعادة الجدولة: {{eventType}} مع {{name}} في {{date}}",
|
||||
"requested_to_reschedule_subject_attendee": "الإجراء المطلوب إعادة الجدولة: يُرجى حجز وقت جديد لمدة {{eventType}} مع {{name}}",
|
||||
"reschedule_reason": "سبب إعادة الجدولة",
|
||||
"hi_user_name": "مرحبا {{name}}",
|
||||
"ics_event_title": "{{eventType}} مع {{name}}",
|
||||
"new_event_subject": "حدث جديد: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
@@ -122,6 +115,7 @@
|
||||
"team_upgrade_banner_description": "شكراً لك على تجربة خطة الفريق الجديدة التي نقدمها. لقد لاحظنا أن فريقك \"{{teamName}}\" بحاجة إلى الترقية.",
|
||||
"team_upgrade_banner_action": "قم بالترقية هنا",
|
||||
"team_upgraded_successfully": "تمت ترقية فريقك بنجاح!",
|
||||
"org_upgrade_banner_action": "قم بالترقية هنا",
|
||||
"use_link_to_reset_password": "استخدم الرابط أدناه لإعادة تعيين كلمة المرور",
|
||||
"hey_there": "مرحبًا،",
|
||||
"forgot_your_password_calcom": "نسيت كلمة المرور الخاصة بك؟ - {{appName}}",
|
||||
@@ -231,6 +225,7 @@
|
||||
"done": "تم",
|
||||
"all_done": "اكتمل كل شيء!",
|
||||
"all_apps": "الكل",
|
||||
"all": "الكل",
|
||||
"available_apps": "التطبيقات المتوفرة",
|
||||
"check_email_reset_password": "تحقق من البريد الإلكتروني. لقد أرسلنا رابطًا لإعادة تعيين كلمة المرور.",
|
||||
"finish": "إنهاء",
|
||||
@@ -252,7 +247,6 @@
|
||||
"welcome_to_calcom": "مرحبًا بك في {{appName}}",
|
||||
"welcome_instructions": "أخبرنا باسمك وبالمنطقة الزمنية التي توجد فيها. ستتمكن لاحقًا من تعديل هذا.",
|
||||
"connect_caldav": "الاتصال بخادم CalDav",
|
||||
"credentials_stored_and_encrypted": "سيجري تشفير بياناتك وتخزينها.",
|
||||
"connect": "الاتصال",
|
||||
"try_for_free": "جرّبه مجانًا",
|
||||
"create_booking_link_with_calcom": "أنشئ رابط الحجز الخاص بك باستخدام {{appName}}",
|
||||
@@ -273,7 +267,6 @@
|
||||
"user_needs_to_confirm_or_reject_booking_recurring": "لا يزال {{user}} بحاجة إلى تأكيد كل حجز للاجتماع المتكرر أو رفضه.",
|
||||
"meeting_is_scheduled": "تمت جدولة هذا الاجتماع",
|
||||
"meeting_is_scheduled_recurring": "تم جدولة الأحداث المتكررة",
|
||||
"submitted_recurring": "تم إرسال الاجتماع المتكرر الخاص بك",
|
||||
"booking_submitted": "تم إرسال الحجز الخاص بك",
|
||||
"booking_submitted_recurring": "تم إرسال الاجتماع المتكرر الخاص بك",
|
||||
"booking_confirmed": "تم تأكيد الحجز الخاص بك",
|
||||
@@ -306,7 +299,6 @@
|
||||
"error_end_time_next_day": "لا يمكن أن يكون وقت الانتهاء أطول من 24 ساعة",
|
||||
"back_to_bookings": "العودة إلى عمليات الحجز",
|
||||
"free_to_pick_another_event_type": "لا تتردد في اختيار حدث آخر في أي وقت.",
|
||||
"cancelled": "تم الإلغاء",
|
||||
"cancellation_successful": "تم الإلغاء بنجاح",
|
||||
"really_cancel_booking": "هل تريد حقًا إلغاء الحجز؟",
|
||||
"cannot_cancel_booking": "لا يمكنك إلغاء هذا الحجز",
|
||||
@@ -315,11 +307,9 @@
|
||||
"cancelling_event_recurring": "إن هذا الحدث أحد الأمثلة على حدث متكرر.",
|
||||
"cancelling_all_recurring": "هذه هي كل الأمثلة المتبقية في الحدث المتكرر.",
|
||||
"error_with_status_code_occured": "حدث خطأ برمز الحالة {{status}}.",
|
||||
"booking_already_cancelled": "تم إلغاء هذا الحجز بالفعل",
|
||||
"booking_already_accepted_rejected": "تم بالفعل قبول هذا الحجز أو رفضه",
|
||||
"go_back_home": "العودة إلى الشاشة الرئيسية",
|
||||
"or_go_back_home": "أو العودة إلى الشاشة الرئيسية",
|
||||
"no_availability": "غير متاح",
|
||||
"no_meeting_found": "لم يتم العثور على اجتماعات",
|
||||
"no_meeting_found_description": "هذا الاجتماع غير موجود. اتصل بصاحب الاجتماع للحصول على الرابط المُحدَّث.",
|
||||
"no_status_bookings_yet": "لا توجد عمليات حجز {{status}}",
|
||||
@@ -330,7 +320,6 @@
|
||||
"upcoming_bookings": "بمجرد أن يحجز شخص ما موعدًا معك، سيظهر هنا.",
|
||||
"recurring_bookings": "بمجرد أن يحجز شخص ما اجتماعًا متكررًا معك، سيظهر هنا.",
|
||||
"past_bookings": "ستظهر هنا عمليات حجزك السابقة.",
|
||||
"cancelled_bookings": "ستظهر هنا عمليات حجزك التي تم إلغاؤها.",
|
||||
"unconfirmed_bookings": "ستظهر هنا كل حجوزات غير المؤكدة بعد.",
|
||||
"unconfirmed_bookings_tooltip": "الحجوزات غير المؤكدة",
|
||||
"on": "في",
|
||||
@@ -370,7 +359,6 @@
|
||||
"browse_api_documentation": "استعراض مستندات واجهة برمجة التطبيقات (API) لدينا",
|
||||
"leverage_our_api": "استفد من واجهة برمجة التطبيقات (API) لدينا من أجل قدرة كاملة على التحكم والتخصيص.",
|
||||
"create_webhook": "إنشاء الويب هوك",
|
||||
"booking_cancelled": "تم إلغاء الحجز",
|
||||
"booking_rescheduled": "تمت إعادة جدولة الحجز",
|
||||
"recording_ready": "رابط تنزيل التسجيل جاهز",
|
||||
"booking_created": "تم إنشاء الحجز",
|
||||
@@ -383,8 +371,6 @@
|
||||
"team_webhooks": "فريق ويبهوكس",
|
||||
"create_new_webhook_to_account": "إنشاء ويب هوك جديد لحسابك",
|
||||
"new_webhook": "ويب هوك جديد",
|
||||
"receive_cal_meeting_data": "تلقَّ بيانات اجتماعات {{appName}} على عنوان URL محدد، وفي الوقت الفعلي، عندما تتم جدولة حدث ما أو يتم إلغاؤه.",
|
||||
"receive_cal_event_meeting_data": "تلقي بيانات اجتماعات {{appName}} على عنوان URL محدد، وفي الوقت الحقيقي، عندما تتم جدولة حدث ما أو إلغاؤه.",
|
||||
"responsive_fullscreen_iframe": "إطار iframe سريع الاستجابة بكامل الشاشة",
|
||||
"loading": "يجري التحميل...",
|
||||
"deleting": "جارٍ الحذف...",
|
||||
@@ -448,7 +434,6 @@
|
||||
"invalid_password_hint": "يجب أن تتألف كلمة المرور على الأقل من {{passwordLength}} أحرف، ورقم واحد على الأقل، ومزيج من الحروف الكبيرة والصغيرة",
|
||||
"incorrect_password": "كلمة المرور غير صحيحة.",
|
||||
"incorrect_username_password": "اسم المستخدم أو كلمة المرور غير صحيحة.",
|
||||
"24_h": "24 ساعة",
|
||||
"use_setting": "استخدام الإعداد",
|
||||
"am_pm": "صباحًا/مساءً",
|
||||
"time_options": "خيارات الوقت",
|
||||
@@ -491,15 +476,11 @@
|
||||
"booking_confirmation": "قم بتأكيد {{eventTypeTitle}} مع {{profileName}}",
|
||||
"booking_reschedule_confirmation": "أعد جدولة {{eventTypeTitle}} مع {{profileName}}",
|
||||
"in_person_meeting": "الرابط أو الاجتماع الشخصي",
|
||||
"attendee_in_person": "شخصيًا (عنوان من سيحضر)",
|
||||
"in_person": "شخصيًا (عنوان المنظم)",
|
||||
"link_meeting": "رابط الاجتماع",
|
||||
"phone_call": "رقم هاتف الحضور",
|
||||
"your_number": "رقم هاتفك",
|
||||
"phone_number": "رقم الهاتف",
|
||||
"attendee_phone_number": "رقم هاتف الحضور",
|
||||
"organizer_phone_number": "رقم هاتف المنظم",
|
||||
"host_phone_number": "رقم هاتفك",
|
||||
"enter_phone_number": "أدخل رقم الهاتف",
|
||||
"reschedule": "إعادة الجدولة",
|
||||
"reschedule_this": "إعادة الجدولة بدلاً من ذلك",
|
||||
@@ -525,6 +506,8 @@
|
||||
"team_description": "بضع جمل عن فريقك. ستظهر على صفحة رابط فريقك.",
|
||||
"members": "الأعضاء",
|
||||
"member": "العضو",
|
||||
"number_member_one": "{{count}} عضو",
|
||||
"number_member_other": "{{count}} من الأعضاء",
|
||||
"owner": "المالك",
|
||||
"admin": "المشرف",
|
||||
"administrator_user": "المستخدم المسؤول",
|
||||
@@ -625,9 +608,6 @@
|
||||
"new_event_type_btn": "نوع حدث جديد",
|
||||
"new_event_type_heading": "إنشاء نوع الحدث الأول لديك",
|
||||
"new_event_type_description": "تتيح لك أنواع الأحداث مشاركة الروابط التي تعرض الأوقات المتاحة في تقويمك وتسمح للأشخاص بالحجز معك.",
|
||||
"new_event_title": "إضافة نوع حدث جديد",
|
||||
"new_team_event": "إضافة نوع حدث جديد لفريق",
|
||||
"new_event_description": "قم بإنشاء نوع حدث جديد ليحجز الأشخاص من خلاله.",
|
||||
"event_type_created_successfully": "تم إنشاء نوع الحدث {{eventTypeTitle}} بنجاح",
|
||||
"event_type_updated_successfully": "تم تحديث نوع الحدث {{eventTypeTitle}} بنجاح",
|
||||
"event_type_deleted_successfully": "تم حذف نوع الحدث بنجاح",
|
||||
@@ -796,7 +776,6 @@
|
||||
"automation": "التشغيل التلقائي",
|
||||
"configure_how_your_event_types_interact": "اضبط كيفية تفاعل أنواع الأحداث لديك مع تقاويمك.",
|
||||
"toggle_calendars_conflict": "قم بتبديل التقويمات التي تريد التحقق من وجود تضاربات فيها لمنع حدوث حجز مزدوج.",
|
||||
"select_destination_calendar": "إنشاء أحداث في",
|
||||
"connect_additional_calendar": "ربط رزنامة إضافية",
|
||||
"calendar_updated_successfully": "تم تحديث التقويم بنجاح",
|
||||
"conferencing": "المؤتمرات عبر الفيديو",
|
||||
@@ -830,7 +809,6 @@
|
||||
"number_apps_other": "{{count}} من التطبيقات",
|
||||
"trending_apps": "التطبيقات الرائجة",
|
||||
"most_popular": "الأكثر شعبية",
|
||||
"explore_apps": "تطبيقات {{category}}",
|
||||
"installed_apps": "التطبيقات المثبتة",
|
||||
"free_to_use_apps": "متاح",
|
||||
"no_category_apps": "لا توجد تطبيقات {{category}}",
|
||||
@@ -842,7 +820,6 @@
|
||||
"no_category_apps_description_other": "أضف أي نوع آخر من التطبيقات للقيام بأي شيء",
|
||||
"no_category_apps_description_web3": "إضافة تطبيق web3 لصفحات الحجز لديك",
|
||||
"installed_app_calendar_description": "قم بتعيين التقويمات للتحقق من وجود تعارضات لمنع الحجوزات المزدوجة.",
|
||||
"installed_app_conferencing_description": "أضف تطبيقات مؤتمرات الفيديو المفضلة لديك لاجتماعاتك",
|
||||
"installed_app_payment_description": "قم بإعداد أي خدمات معالجة دفع تود استخدامها عند التحصيل من العملاء.",
|
||||
"installed_app_analytics_description": "تهيئة أي تطبيقات تستخدم لصفحات الحجز الخاصة بك",
|
||||
"installed_app_other_description": "جميع تطبيقاتك المثبتة من الفئات الأخرى.",
|
||||
@@ -868,7 +845,6 @@
|
||||
"terms_of_service": "شروط الخدمة",
|
||||
"remove": "إزالة",
|
||||
"add": "إضافة",
|
||||
"installed_one": "تم التثبيت",
|
||||
"installed_other": "{{count}} مثبت",
|
||||
"verify_wallet": "تأكيد المحفظة",
|
||||
"create_events_on": "إنشاء أحداث في",
|
||||
@@ -896,7 +872,6 @@
|
||||
"availability_updated_successfully": "تم تحديث جدول {{scheduleName}} بنجاح",
|
||||
"schedule_deleted_successfully": "تم حذف الجدول بنجاح",
|
||||
"default_schedule_name": "ساعات العمل",
|
||||
"member_default_schedule": "الجدول الزمني الافتراضي للعضو",
|
||||
"new_schedule_heading": "إنشاء جدول الأوقات المتاحة",
|
||||
"new_schedule_description": "إن إنشاء جداول الأوقات المتاحة يتيح لك إدارة الأوقات المتاحة عبر أنواع الأحداث. يمكن تطبيقها على نوع أو أكثر من أنواع الأحداث.",
|
||||
"requires_ownership_of_a_token": "يتطلب امتلاك token يخص العنوان التالي:",
|
||||
@@ -933,8 +908,6 @@
|
||||
"api_key_no_note": "مفتاح API بدون اسم",
|
||||
"api_key_never_expires": "مفتاح API هذا ليس له تاريخ انتهاء صلاحية",
|
||||
"edit_api_key": "تحرير مفتاح API",
|
||||
"never_expire_key": "لا تنتهي الصّلاحية أبدًا",
|
||||
"delete_api_key": "إلغاء مفتاح API",
|
||||
"success_api_key_created": "تم إنشاء مفتاح API بنجاح",
|
||||
"success_api_key_edited": "تم تحديث مفتاح API بنجاح",
|
||||
"create": "إنشاء",
|
||||
@@ -975,7 +948,6 @@
|
||||
"event_location_changed": "تم التحديث - تم تغيير موقع الحدث الخاص بك",
|
||||
"location_changed_event_type_subject": "تم تغيير الموقع: {{eventType}} مع {{name}} في {{date}}",
|
||||
"current_location": "الموقع الحالي",
|
||||
"user_phone": "رقم هاتفك",
|
||||
"new_location": "الموقع الجديد",
|
||||
"session": "الجلسة",
|
||||
"session_description": "التحكم في جلسة حسابك",
|
||||
@@ -1001,7 +973,6 @@
|
||||
"zapier_setup_instructions": "<0>سجل الدخول إلى حساب Zapier الخاص بك وأنشئ Zap جديد.</0><1>حدد Cal.com كتطبيق Trigger لديك. اختر أيضًا حدث Trigger.</1><2>اختر حسابك ثم أدخل مفتاح API الفريد الخاص بك.</2><3>اختبر Trigger الخاص بك.</3><4>أنت جاهز!</4>",
|
||||
"install_zapier_app": "يرجى تثبيت تطبيق Zapier من App Store أولًا.",
|
||||
"connect_apple_server": "الاتصال بخادم Apple",
|
||||
"connect_caldav_server": "الاتصال بخادم CalDav",
|
||||
"calendar_url": "رابط التقويم",
|
||||
"apple_server_generate_password": "أنشئ كلمة مرور خاصة بالتطبيق لاستخدامها مع {{appName}} على",
|
||||
"credentials_stored_encrypted": "سيتم تشفير بياناتك وتخزينها.",
|
||||
@@ -1033,19 +1004,16 @@
|
||||
"go_to": "انتقل إلى: ",
|
||||
"zapier_invite_link": "رابط دعوة Zapier",
|
||||
"meeting_url_provided_after_confirmed": "سيتم إنشاء رابط الاجتماع بمجرد تأكيد الحدث.",
|
||||
"attendees_name": "اسم الحاضر",
|
||||
"dynamically_display_attendee_or_organizer": "عرض اسم حضورك بشكل ديناميكي، أو اسمك عندما يراه حضورك",
|
||||
"event_location": "موقع الحدث",
|
||||
"reschedule_optional": "سبب إعادة الجدولة (اختياري)",
|
||||
"reschedule_placeholder": "أخبر الآخرين لماذا تحتاج إلى إعادة جدولة",
|
||||
"event_cancelled": "تم إلغاء هذا الحدث",
|
||||
"emailed_information_about_cancelled_event": "لقد أرسلنا إليك وإلى الحاضرين الآخرين بريداً إلكترونياً لإعلامهم.",
|
||||
"this_input_will_shown_booking_this_event": "سيُعرَض هذا المُدخَل عند حجز هذا الحدث",
|
||||
"meeting_url_in_conformation_email": "عنوان رابط الاجتماع موجود في رسالة التأكيد الإلكترونية",
|
||||
"url_start_with_https": "يجب أن يبدأ العنوان بـ http:// أو https://",
|
||||
"number_provided": "سيتم توفير رقم الهاتف",
|
||||
"before_event_trigger": "قبل بدء الحدث",
|
||||
"event_cancelled_trigger": "متى تم إلغاء هذا الحدث",
|
||||
"new_event_trigger": "متى تم حجز الحدث الجديد",
|
||||
"email_host_action": "إرسال رسالة إلكترونية إلى المضيف",
|
||||
"email_attendee_action": "إرسال رسالة إلكترونية إلى الحضور",
|
||||
@@ -1107,7 +1075,6 @@
|
||||
"add_exchange2016": "الاتصال بخادم Exchange 2016",
|
||||
"custom_template": "قالب مخصص",
|
||||
"email_body": "نص البريد الإلكتروني",
|
||||
"subject": "موضوع البريد الإلكتروني",
|
||||
"text_message": "رسالة نصية",
|
||||
"specific_issue": "هل لديك مشكلة معينة؟",
|
||||
"browse_our_docs": "تصفح مستنداتنا",
|
||||
@@ -1135,12 +1102,9 @@
|
||||
"new_seat_title": "شخص ما أضاف نفسه إلى حدث",
|
||||
"variable": "متغير",
|
||||
"event_name_variable": "اسم الحدث",
|
||||
"organizer_name_variable": "المنظِّم",
|
||||
"attendee_name_variable": "الحاضر",
|
||||
"event_date_variable": "تاريخ الحدث",
|
||||
"event_time_variable": "وقت الحدث",
|
||||
"location_variable": "الموقع",
|
||||
"additional_notes_variable": "ملاحظات إضافية",
|
||||
"app_upgrade_description": "لاستخدام هذه الميزة، تحتاج إلى الترقية إلى حساب Pro.",
|
||||
"invalid_number": "رقم الهاتف غير صالح",
|
||||
"navigate": "تنقّل",
|
||||
@@ -1211,7 +1175,6 @@
|
||||
"start_of_week": "بداية الأسبوع",
|
||||
"recordings_title": "التسجيلات",
|
||||
"recording": "التسجيل",
|
||||
"happy_scheduling": "جدولة سعيدة",
|
||||
"select_calendars": "حدد الرزنامات التي تريد التحقق منها بحثًا عن تضاربات لمنع الحجوزات المزدوجة.",
|
||||
"check_for_conflicts": "التحقق من وجود تضاربات",
|
||||
"view_recordings": "عرض التسجيلات",
|
||||
@@ -1234,7 +1197,6 @@
|
||||
"recurring_event_tab_description": "إعداد جدول تكرار",
|
||||
"today": "اليوم",
|
||||
"appearance": "المظهر",
|
||||
"appearance_subtitle": "إدارة إعدادات مظهر الحجز الخاص بك",
|
||||
"my_account": "حسابي",
|
||||
"general": "عام",
|
||||
"calendars": "التقويمات",
|
||||
@@ -1254,7 +1216,6 @@
|
||||
"conferencing_description": "أضف تطبيقات مؤتمرات الفيديو المفضلة لديك لاجتماعاتك",
|
||||
"add_conferencing_app": "إضافة تطبيق عقد اجتماعات",
|
||||
"password_description": "إدارة إعدادات كلمات مرور حسابك",
|
||||
"2fa_description": "إدارة إعدادات كلمات مرور حسابك",
|
||||
"we_just_need_basic_info": "نحتاج إلى بعض المعلومات الأساسية لإعداد ملفك الشخصي.",
|
||||
"skip": "تخطي",
|
||||
"do_this_later": "القيام بذلك لاحقًا",
|
||||
@@ -1278,7 +1239,6 @@
|
||||
"event_date_info": "تاريخ الحدث",
|
||||
"event_time_info": "وقت بدء الحدث",
|
||||
"location_info": "موقع الحدث",
|
||||
"organizer_name_info": "اسمك",
|
||||
"additional_notes_info": "ملاحظات إضافية للحجز",
|
||||
"attendee_name_info": "اسم الشخص صاحب الحجز",
|
||||
"to": "إلى",
|
||||
@@ -1342,8 +1302,6 @@
|
||||
"copy_link_to_form": "نسخ الرابط إلى النموذج",
|
||||
"theme": "السمة",
|
||||
"theme_applies_note": "ينطبق هذا فقط على صفحات الحجز العامة",
|
||||
"theme_light": "فاتح",
|
||||
"theme_dark": "داكن",
|
||||
"theme_system": "الافتراضي للنظام",
|
||||
"add_a_team": "إضافة فريق",
|
||||
"add_webhook_description": "تلقي بيانات الاجتماع في الوقت الحقيقي عندما يحدث شيء ما في {{appName}}",
|
||||
@@ -1352,7 +1310,6 @@
|
||||
"enable_webhook": "تمكين Webhook",
|
||||
"add_webhook": "إضافة Webhook",
|
||||
"webhook_edited_successfully": "تم حفظ Webhook",
|
||||
"webhooks_description": "تلقي بيانات الاجتماع في الوقت الحقيقي عندما يحدث شيء ما في {{appName}}",
|
||||
"api_keys_description": "إنشاء مفاتيح API لاستخدامها للوصول إلى حسابك الخاص",
|
||||
"new_api_key": "مفتاح API جديد",
|
||||
"active": "نشط",
|
||||
@@ -1394,11 +1351,7 @@
|
||||
"billing_freeplan_title": "أنت حاليًا على الخطة المجانية",
|
||||
"billing_freeplan_description": "نحن نعمل بشكل أفضل ضمن فرق. وسّع سير عملك من خلال الأحداث الدوارة والجماعية وإنشاء نماذج توجيه متقدمة",
|
||||
"billing_freeplan_cta": "جرب الآن",
|
||||
"billing_manage_details_title": "عرض تفاصيل الفواتير وإدارتها",
|
||||
"billing_manage_details_description": "اعرض تفاصيل الفواتير وعدّلها، كما يمكنك إلغاء الاشتراك.",
|
||||
"billing_portal": "بوابة الفواتير",
|
||||
"billing_help_title": "هل تحتاج إلى أي شيء آخر؟",
|
||||
"billing_help_description": "إذا كنت تحتاج إلى أي مساعدة إضافية بخصوص الفوترة، فإن فريق الدعم لدينا في انتظارك لتقديم المساعدة.",
|
||||
"billing_help_cta": "الاتصال بالدعم",
|
||||
"ignore_special_characters_booking_questions": "تجاهل الأحرف الخاصة في معرف سؤال الحجز لديك. استخدم الأحرف والأرقام فقط",
|
||||
"retry": "إعادة المحاولة",
|
||||
@@ -1406,7 +1359,6 @@
|
||||
"calendar_connection_fail": "فشل الاتصال بالتقويم",
|
||||
"booking_confirmation_success": "تم تأكيد الحجز بنجاح",
|
||||
"booking_rejection_success": "تم رفض الحجز بنجاح",
|
||||
"booking_confirmation_fail": "فشل تأكيد الحجز",
|
||||
"booking_tentative": "هذا الحجز مؤقت",
|
||||
"booking_accept_intent": "أخطأت، كنت أريد الموافقة",
|
||||
"we_wont_show_again": "لن نعرض هذا مرة أخرى",
|
||||
@@ -1429,7 +1381,6 @@
|
||||
"new_event_type_availability": "توافر {{eventTypeTitle}}",
|
||||
"error_editing_availability": "خطأ في تحرير التوافر",
|
||||
"dont_have_permission": "ليس لديك الصلاحيات الكافية للوصول إلى هذا المصدر.",
|
||||
"saml_config": "تسجيل الدخول لمرة واحدة",
|
||||
"saml_configuration_placeholder": "يُرجى لصق بيانات تعريف SAML المقدمة من مزود الهوية هنا",
|
||||
"saml_email_required": "يُرجى إدخال بريد إلكتروني حتى نتمكن من العثور على مزود هوية SAML الخاص بك",
|
||||
"saml_sp_title": "تفاصيل موفر الخدمة",
|
||||
@@ -1438,7 +1389,6 @@
|
||||
"saml_sp_entity_id": "معرف الكيان SP",
|
||||
"saml_sp_acs_url_copied": "تم نسخ رابط ACS!",
|
||||
"saml_sp_entity_id_copied": "تم نسخ معرف كيان SP!",
|
||||
"saml_btn_configure": "تهيئة",
|
||||
"add_calendar": "إضافة تقويم",
|
||||
"limit_future_bookings": "الحد من الحجوزات المستقبلية",
|
||||
"limit_future_bookings_description": "الحد من عدد مرات حجز هذا الحدث في المستقبل",
|
||||
@@ -1451,7 +1401,6 @@
|
||||
"your_team_disbanded_successfully": "تم حل فريقك بنجاح",
|
||||
"error_creating_team": "خطأ في إنشاء فريق",
|
||||
"you": "أنت",
|
||||
"send_email": "إرسال بريد إلكتروني",
|
||||
"member_already_invited": "تمت دعوة العضو بالفعل",
|
||||
"enter_email_or_username": "أدخل بريد إلكتروني أو اسم مستخدم",
|
||||
"team_name_taken": "هذا الاسم مأخوذ بالفعل",
|
||||
@@ -1618,12 +1567,8 @@
|
||||
"delete_sso_configuration_confirmation": "نعم، حذف تكوين {{connectionType}}",
|
||||
"delete_sso_configuration_confirmation_description": "هل تريد بالتأكيد حذف تكوين {{connectionType}}؟ لن يتمكن أعضاء فريقك الذين يستخدمون معلومات تسجيل الدخول إلى {{connectionType}} من الوصول إلى Cal.com بعد الآن.",
|
||||
"organizer_timezone": "منظم المناطق الزمنية",
|
||||
"email_no_user_cta": "إنشاء حسابك",
|
||||
"email_user_cta": "عرض الدعوة",
|
||||
"email_no_user_invite_heading": "لقد تمت دعوتك للانضمام إلى فريق في {{appName}}",
|
||||
"email_no_user_invite_subheading": "دعاك {{invitedBy}} للانضمام إلى فريقه على {{appName}}. إن {{appName}} هو برنامج جدولة الأحداث الذي يمكّنك أنت وفريقك من جدولة الاجتماعات دون الحاجة إلى المراسلة عبر البريد الإلكتروني.",
|
||||
"email_user_invite_subheading": "دعاك {{invitedBy}} للانضمام إلى فريقه {{teamName}} على {{appName}}. إن {{appName}} هو برنامج جدولة الأحداث الذي يمكّنك أنت وفريقك من جدولة الاجتماعات دون الحاجة إلى المراسلة عبر البريد الإلكتروني.",
|
||||
"email_no_user_invite_steps_intro": "سنرشدك خلال بضع خطوات قصيرة وستستمتع بجدولة خالية من الإجهاد مع فريقك وسريعة.",
|
||||
"email_no_user_step_one": "اختر اسم المستخدم الخاص بك",
|
||||
"email_no_user_step_two": "ربط حساب التقويم الخاص بك",
|
||||
"email_no_user_step_three": "تعيين أوقاتك المتاحة",
|
||||
@@ -1644,11 +1589,9 @@
|
||||
"no_longer_attending": "لن تحضر هذا الحدث",
|
||||
"attendee_no_longer_attending_subject": "أحد الحضور لن يحضر {{title}} في {{date}}",
|
||||
"attendee_no_longer_attending": "أحد الحضور لن يحضر الحدث الخاص بك",
|
||||
"attendee_no_longer_attending_subtitle": "تم إلغاء الحدث {{name}}، وهو ما يعني توافر معقد شاغر في هذا التوقيت",
|
||||
"create_event_on": "إنشاء حدث في",
|
||||
"default_app_link_title": "تعيين رابط تطبيق افتراضي",
|
||||
"default_app_link_description": "يسمح تعيين رابط التطبيق الافتراضي لجميع أنواع الأحداث التي تم إنشاؤها حديثًا باستخدام رابط التطبيق الذي عينته.",
|
||||
"change_default_conferencing_app": "تعيين كافتراضي",
|
||||
"organizer_default_conferencing_app": "تطبيق المنظمة الافتراضي",
|
||||
"under_maintenance": "معطل للصيانة",
|
||||
"under_maintenance_description": "يجري فريق {{appName}} صيانة مجدولة. إذا كان لديك أي أسئلة، يرجى الاتصال بالدعم.",
|
||||
@@ -1663,11 +1606,9 @@
|
||||
"booking_confirmation_failed": "فشل تأكيد الحجز",
|
||||
"not_enough_seats": "لا توجد مقاعد كافية",
|
||||
"form_builder_field_already_exists": "يوجد حقل بهذا الاسم بالفعل",
|
||||
"form_builder_field_add_subtitle": "يمكنك تخصيص الأسئلة المطروحة في صفحة الحجز",
|
||||
"show_on_booking_page": "إظهار في صفحة الحجز",
|
||||
"get_started_zapier_templates": "البدء في استخدام قوالب Zapier",
|
||||
"team_is_unpublished": "لم يُنشر {{team}}",
|
||||
"team_is_unpublished_description": "رابط هذا الفريق غير متاح حاليًا. يرجى الاتصال بمالك الفريق أو طلب نشره منه.",
|
||||
"team_member": "عضو الفريق",
|
||||
"a_routing_form": "نموذج توجيه",
|
||||
"form_description_placeholder": "وصف النموذج",
|
||||
@@ -1698,7 +1639,6 @@
|
||||
"spot_popular_event_types_description": "تعرف أي أنواع من الأحداث لديك تتلقى أكبر عدد من النقرات والحجوزات",
|
||||
"no_responses_yet": "لا توجد ردود بعد",
|
||||
"this_will_be_the_placeholder": "سيكون هذا هو العنصر النائب",
|
||||
"error_booking_event": "حدث خطأ عند حجز الحدث، الرجاء تحديث الصفحة والمحاولة ثانيةً",
|
||||
"timeslot_missing_title": "لم يتم تحديد مساحة زمنية",
|
||||
"timeslot_missing_description": "الرجاء تحديد فترة زمنية لحجز الحدث.",
|
||||
"timeslot_missing_cta": "حدد الوقت",
|
||||
@@ -1715,7 +1655,6 @@
|
||||
"verification_code": "رمز التحقق",
|
||||
"can_you_try_again": "هل يمكنك المحاولة مرة أخرى في وقت مختلف؟",
|
||||
"verify": "التحقق",
|
||||
"timezone_variable": "المنطقة الزمنية",
|
||||
"timezone_info": "المنطقة الزمنية للشخص الذي يتلقى الحجز",
|
||||
"event_end_time_variable": "وقت انتهاء الحدث",
|
||||
"event_end_time_info": "وقت نهاية الحدث",
|
||||
@@ -1760,11 +1699,9 @@
|
||||
"least_booked_members": "الأعضاء الأقل حجزًا",
|
||||
"events_created": "تم إنشاء الأحداث",
|
||||
"events_completed": "تم اكتمال الأحداث",
|
||||
"events_cancelled": "تم إلغاء الأحداث",
|
||||
"events_rescheduled": "تمت إعادة جدولة الأحداث",
|
||||
"from_last_period": "من آخر فترة",
|
||||
"from_to_date_period": "من: {{startDate}} إلى: {{endDate}}",
|
||||
"analytics_for_organisation": "Insights",
|
||||
"subtitle_analytics": "اعرف المزيد عن نشاط فريقك",
|
||||
"redirect_url_warning": "سيؤدي إضافة إعادة توجيه إلى تعطيل صفحة النجاح. تأكد من ذكر \"تأكيد الحجز\" في صفحة النجاح المخصصة.",
|
||||
"event_trends": "الرائج في الأحداث",
|
||||
@@ -1795,7 +1732,6 @@
|
||||
"complete_your_booking": "أكمل الحجز",
|
||||
"complete_your_booking_subject": "أكمل الحجز: {{title}} في {{date}}",
|
||||
"confirm_your_details": "تأكيد التفاصيل الخاصة بك",
|
||||
"never_expire": "لا تنتهي الصلاحية أبدًا",
|
||||
"currency_string": "{{amount, currency}}",
|
||||
"charge_card_dialog_body": "أنت على وشك استحصال مبلغ {{amount, currency}} من أحد الحضور. هل أنت متأكد من أنك تريد المتابعة؟",
|
||||
"charge_attendee": "استحصال مبلغ {{amount, currency}} من أحد الحضور",
|
||||
@@ -1814,7 +1750,6 @@
|
||||
"book_my_cal": "ثبّت الحجز في رزنامتي",
|
||||
"invite_as": "دعوة باسم",
|
||||
"form_updated_successfully": "تم تحديث الاستمارة بنجاح.",
|
||||
"email_not_cal_member_cta": "انضم إلى فريقك",
|
||||
"disable_attendees_confirmation_emails": "تعطيل رسائل التأكيد الافتراضية للحضور",
|
||||
"disable_attendees_confirmation_emails_description": "يوجد مسار عمل واحد على الأقل نشط في هذا النوع من الأحداث يقوم بإرسال رسائل إلكترونية إلى الحاضرين عند حجز الحدث.",
|
||||
"disable_host_confirmation_emails": "تعطيل رسائل التأكيد الافتراضية لمضيف",
|
||||
@@ -1824,5 +1759,6 @@
|
||||
"connect_google_workspace": "ربط مساحة عمل Google",
|
||||
"google_workspace_admin_tooltip": "يجب أن تكون مشرفًا على مساحة العمل لاستخدام هذه الميزة",
|
||||
"first_event_type_webhook_description": "قم بإنشاء أول شبكة ويب هوك لهذا النوع من الفعاليات",
|
||||
"create_for": "إنشاء من أجل"
|
||||
"create_for": "إنشاء من أجل",
|
||||
"organization_url_taken": "عنوان URL هذا مأخوذ بالفعل"
|
||||
}
|
||||
|
||||
@@ -11,12 +11,9 @@
|
||||
"calcom_explained_new_user": "Dokončete nastavení svého účtu {{appName}}! Jste jen několik kroků od vyřešení všech svých problémů s plánováním.",
|
||||
"have_any_questions": "Máte otázky? Jsme tu, abychom vám pomohli.",
|
||||
"reset_password_subject": "{{appName}}: Pokyny pro obnovení hesla",
|
||||
"verify_email_banner_button": "Odeslat e-mail",
|
||||
"event_declined_subject": "Odmítnuto: {{title}} v {{date}}",
|
||||
"event_cancelled_subject": "Zrušeno: {{title}} v {{date}}",
|
||||
"event_request_declined": "Žádost o událost byla zamítnuta",
|
||||
"event_request_declined_recurring": "Žádost o opakovanou událost byla zamítnuta",
|
||||
"event_request_cancelled": "Vaše naplánovaná událost byla zrušena",
|
||||
"organizer": "Organizátor",
|
||||
"need_to_reschedule_or_cancel": "Přeplánovat nebo zrušit?",
|
||||
"cancellation_reason": "Důvod zrušení",
|
||||
@@ -78,13 +75,9 @@
|
||||
"your_meeting_has_been_booked": "Vaše schůzka byla rezervována",
|
||||
"event_type_has_been_rescheduled_on_time_date": "Váš {{title}} byl přeplánován na {{date}}.",
|
||||
"event_has_been_rescheduled": "Změna - Vaše událost byla přesunuta na jindy",
|
||||
"request_reschedule_title_attendee": "Žádost o přeplánování rezervace",
|
||||
"request_reschedule_subtitle": "Organizátor {{organizer}} zrušil rezervaci a požádal vás, abyste si vybrali jiný čas.",
|
||||
"request_reschedule_title_organizer": "Požádali jste uživatele {{attendee}} o změnu časového plánu",
|
||||
"request_reschedule_subtitle_organizer": "Zrušili jste rezervaci a uživatel {{attendee}} by si s vámi měl zarezervovat nový čas.",
|
||||
"rescheduled_event_type_subject": "Žádost o přesunutí schůzky: {{eventType}} s {{name}} dne {{date}}",
|
||||
"requested_to_reschedule_subject_attendee": "Akce vyžadovaná k přeplánování: zarezervujte si nový čas pro událost {{eventType}} s osobou {{name}}",
|
||||
"reschedule_reason": "Důvod přeplánování",
|
||||
"hi_user_name": "Hezký den, {{name}}",
|
||||
"ics_event_title": "{{eventType}} s {{name}}",
|
||||
"new_event_subject": "Nová událost: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
@@ -122,6 +115,7 @@
|
||||
"team_upgrade_banner_description": "Děkujeme vám za vyzkoušení našeho nového týmového plánu. Všimli jsme si, že váš tým „{{teamName}}“ je nutné upgradovat.",
|
||||
"team_upgrade_banner_action": "Upgradovat zde",
|
||||
"team_upgraded_successfully": "Váš tým byl úspěšně přešel na vyšší verzi!",
|
||||
"org_upgrade_banner_action": "Upgradovat zde",
|
||||
"use_link_to_reset_password": "Pro obnovení hesla použijte odkaz níž",
|
||||
"hey_there": "Zdravíme,",
|
||||
"forgot_your_password_calcom": "Zapomněli jste heslo? - {{appName}}",
|
||||
@@ -231,6 +225,7 @@
|
||||
"done": "Hotovo",
|
||||
"all_done": "Hotovo!",
|
||||
"all_apps": "Všechny aplikace",
|
||||
"all": "Všechny aplikace",
|
||||
"available_apps": "Dostupné aplikace",
|
||||
"check_email_reset_password": "Podívejte se do e-mailu. Poslali jsme vám odkaz pro obnovení hesla.",
|
||||
"finish": "Dokončit",
|
||||
@@ -252,7 +247,6 @@
|
||||
"welcome_to_calcom": "Vítejte na webu {{appName}}",
|
||||
"welcome_instructions": "Řekněte nám vaše jméno a v jaké časové zóně se pohybujete. Později můžete tyto informace změnit.",
|
||||
"connect_caldav": "Připojit se k CalDav (Beta)",
|
||||
"credentials_stored_and_encrypted": "Vaše přihlašovací údaje budou uloženy a zašifrovány.",
|
||||
"connect": "Připojit",
|
||||
"try_for_free": "Vyzkoušet zdarma",
|
||||
"create_booking_link_with_calcom": "Vytvořte si vlastní rezervační odkaz s {{appName}}",
|
||||
@@ -273,7 +267,6 @@
|
||||
"user_needs_to_confirm_or_reject_booking_recurring": "Uživatel {{user}} ještě nepotvrdil ani neodmítl jednotlivé rezervace opakované schůzky.",
|
||||
"meeting_is_scheduled": "Schůzka naplánována",
|
||||
"meeting_is_scheduled_recurring": "Opakované události byly naplánovány",
|
||||
"submitted_recurring": "Opakovaná schůzka byla odeslána",
|
||||
"booking_submitted": "Vaše rezervace byla odeslána",
|
||||
"booking_submitted_recurring": "Opakovaná schůzka byla odeslána",
|
||||
"booking_confirmed": "Vaše rezervace byla schválena",
|
||||
@@ -306,7 +299,6 @@
|
||||
"error_end_time_next_day": "Čas konce nemůže být delší než 24 hodin",
|
||||
"back_to_bookings": "Zpět na rezervace",
|
||||
"free_to_pick_another_event_type": "Kdykoliv si můžete vybrat jinou událost.",
|
||||
"cancelled": "Zrušeno",
|
||||
"cancellation_successful": "Zrušení proběhlo úspěšně",
|
||||
"really_cancel_booking": "Opravdu chcete zrušit svou rezervaci?",
|
||||
"cannot_cancel_booking": "Tuto rezervaci nelze zrušit",
|
||||
@@ -315,11 +307,9 @@
|
||||
"cancelling_event_recurring": "Tato událost je jedním z případů opakující se události.",
|
||||
"cancelling_all_recurring": "Toto jsou všechny zbývající instance opakující se události.",
|
||||
"error_with_status_code_occured": "Došlo k chybě se stavovým kódem {{status}}.",
|
||||
"booking_already_cancelled": "Tato rezervace již byla zrušena",
|
||||
"booking_already_accepted_rejected": "Tato rezervace již byla přijata nebo zamítnuta",
|
||||
"go_back_home": "Přejít na úvod",
|
||||
"or_go_back_home": "Nebo přejít na úvod",
|
||||
"no_availability": "Nedostupný",
|
||||
"no_meeting_found": "Nenalezena žádná schůzka",
|
||||
"no_meeting_found_description": "Tato schůzka neexistuje. Pro aktualizovaný odkaz kontaktujte vlastníka schůzky.",
|
||||
"no_status_bookings_yet": "Zatím žádné {{status}} rezervace",
|
||||
@@ -330,7 +320,6 @@
|
||||
"upcoming_bookings": "Jakmile si někdo rezervuje váš čas, zobrazí se to zde.",
|
||||
"recurring_bookings": "Jakmile si někdo s vámi zarezervuje opakovanou schůzku, zobrazí se to zde.",
|
||||
"past_bookings": "Vaše proběhlé rezervace se zobrazí zde.",
|
||||
"cancelled_bookings": "Vaše zrušené rezervace se zobrazí zde.",
|
||||
"unconfirmed_bookings": "Vaše nepotvrzené rezervace se zobrazí zde.",
|
||||
"unconfirmed_bookings_tooltip": "Nepotvrzené rezervace",
|
||||
"on": "dne",
|
||||
@@ -370,7 +359,6 @@
|
||||
"browse_api_documentation": "Procházejte naši API dokumentaci",
|
||||
"leverage_our_api": "Pro plnou kontrolu a přizpůsobení využijte naše API.",
|
||||
"create_webhook": "Vytvořit webhook",
|
||||
"booking_cancelled": "Rezervace zrušena",
|
||||
"booking_rescheduled": "Rezervace přesunuta",
|
||||
"recording_ready": "Odkaz ke stažení záznamu je připraven",
|
||||
"booking_created": "Rezervace vytvořena",
|
||||
@@ -383,8 +371,6 @@
|
||||
"team_webhooks": "Týmové Webhooky",
|
||||
"create_new_webhook_to_account": "Vytvořit nový webhook pro váš účet",
|
||||
"new_webhook": "Nový webhook",
|
||||
"receive_cal_meeting_data": "Přijímat v reálném čase data schůzky na zadanou adresu URL, když je událost naplánována nebo zrušena.",
|
||||
"receive_cal_event_meeting_data": "Přijmout real-time data o {{appName}} události na určené URL adrese, jakmile je událost naplánována nebo zrušena.",
|
||||
"responsive_fullscreen_iframe": "Responzivní iframe na celou obrazovku",
|
||||
"loading": "Načítám...",
|
||||
"deleting": "Odstraňování...",
|
||||
@@ -448,7 +434,6 @@
|
||||
"invalid_password_hint": "Heslo musí být minimálně {{passwordLength}} znaků dlouhé, obsahovat alespoň jedno číslo a obsahovat kombinaci velkých a malých písmen",
|
||||
"incorrect_password": "Heslo není správné.",
|
||||
"incorrect_username_password": "Uživatelské jméno nebo heslo je nesprávné.",
|
||||
"24_h": "24h",
|
||||
"use_setting": "Použít nastavení",
|
||||
"am_pm": "am/pm",
|
||||
"time_options": "Nastavení času",
|
||||
@@ -491,15 +476,11 @@
|
||||
"booking_confirmation": "Potvrďte {{eventTypeTitle}} skrz účet {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Přesunout {{eventTypeTitle}} na jindy skrz účet {{profileName}}",
|
||||
"in_person_meeting": "Odkaz nebo osobní schůzka",
|
||||
"attendee_in_person": "Osobně (adresa účastníka)",
|
||||
"in_person": "Osobně (adresa organizátora)",
|
||||
"link_meeting": "Odkaz na schůzku",
|
||||
"phone_call": "Telefon",
|
||||
"your_number": "Vaše telefonní číslo",
|
||||
"phone_number": "Tel. číslo",
|
||||
"attendee_phone_number": "Telefonní číslo účastníka",
|
||||
"organizer_phone_number": "Telefonní číslo organizátora",
|
||||
"host_phone_number": "Vaše telefonní číslo",
|
||||
"enter_phone_number": "Zadejte telefonní číslo",
|
||||
"reschedule": "Přesunout na jindy",
|
||||
"reschedule_this": "Raději přesunout na jindy",
|
||||
@@ -525,6 +506,8 @@
|
||||
"team_description": "Pár vět o vašem týmu. Objeví se na URL stránce vašeho týmu.",
|
||||
"members": "Členové",
|
||||
"member": "Člen",
|
||||
"number_member_one": "Počet členů: {{count}}",
|
||||
"number_member_other": "Počet členů: {{count}}",
|
||||
"owner": "Vlastník",
|
||||
"admin": "Administrátor",
|
||||
"administrator_user": "Uživatel administrátor",
|
||||
@@ -625,9 +608,6 @@
|
||||
"new_event_type_btn": "Nový typ události",
|
||||
"new_event_type_heading": "Vytvořte svůj první typ události",
|
||||
"new_event_type_description": "Typy událostí vám umožňují sdílet odkazy, které ukazují časy v kalendáři, kdy jste dostupní, a lidí skrz ně mohou rezervovat váš čas.",
|
||||
"new_event_title": "Přidat nový typ události",
|
||||
"new_team_event": "Přidat nový typ týmové události",
|
||||
"new_event_description": "Vytvořit nový typ události, ve které si lidé mohou rezervovat časy.",
|
||||
"event_type_created_successfully": "Typ události {{eventTypeTitle}} byl úspěšně vytvořen",
|
||||
"event_type_updated_successfully": "Typ události {{eventTypeTitle}} byl úspěšně aktualizován",
|
||||
"event_type_deleted_successfully": "Typ události byl úspěšně smazán",
|
||||
@@ -796,7 +776,6 @@
|
||||
"automation": "Automatizace",
|
||||
"configure_how_your_event_types_interact": "Nastavte, jak mají typy událostí interagovat s vašimi kalendáři.",
|
||||
"toggle_calendars_conflict": "Zapněte kalendáře, u kterých chcete mít přehled o konfliktech a zabránit dvojí rezervaci.",
|
||||
"select_destination_calendar": "Vytvořit události v",
|
||||
"connect_additional_calendar": "Připojit další kalendář",
|
||||
"calendar_updated_successfully": "Kalendář byl úspěšně aktualizován",
|
||||
"conferencing": "Konference",
|
||||
@@ -830,7 +809,6 @@
|
||||
"number_apps_other": "Počet aplikací: {{count}}",
|
||||
"trending_apps": "Populární aplikace",
|
||||
"most_popular": "Nejoblíbenější",
|
||||
"explore_apps": "Aplikace v kategorii {{category}}",
|
||||
"installed_apps": "Nainstalované aplikace",
|
||||
"free_to_use_apps": "Zdarma",
|
||||
"no_category_apps": "Žádné aplikace v kategorii {{category}}",
|
||||
@@ -842,7 +820,6 @@
|
||||
"no_category_apps_description_other": "Přidejte jakýkoli jiný typ aplikace pro nejrůznější činnosti",
|
||||
"no_category_apps_description_web3": "Přidejte aplikaci web3 pro vaše rezervační stránky",
|
||||
"installed_app_calendar_description": "Nastavte si kalendáře, ať můžete kontrolovat konflikty a zabránit tak dvojím rezervacím.",
|
||||
"installed_app_conferencing_description": "Přidejte své oblíbené aplikace pro videokonference pro vaše schůzky",
|
||||
"installed_app_payment_description": "Nakonfigurujte služby zpracování plateb, které se mají používat při strhávání plateb od klientů.",
|
||||
"installed_app_analytics_description": "Nakonfigurujte aplikace, které chcete použít pro své rezervační stránky",
|
||||
"installed_app_other_description": "Všechny vaše nainstalované aplikace z ostatních kategorií.",
|
||||
@@ -868,7 +845,6 @@
|
||||
"terms_of_service": "Podmínky používání",
|
||||
"remove": "Odebrat",
|
||||
"add": "Přidat",
|
||||
"installed_one": "Nainstalováno",
|
||||
"installed_other": "Nainstalováno: {{count}}",
|
||||
"verify_wallet": "Ověřit peněženku",
|
||||
"create_events_on": "Vytvořit události v:",
|
||||
@@ -896,7 +872,6 @@
|
||||
"availability_updated_successfully": "Plán {{scheduleName}} byl úspěšně aktualizován",
|
||||
"schedule_deleted_successfully": "Plán byl úspěšně odstraněn",
|
||||
"default_schedule_name": "Pracovní doba",
|
||||
"member_default_schedule": "Výchozí rozvrh člena",
|
||||
"new_schedule_heading": "Vytvořit plán dostupnosti",
|
||||
"new_schedule_description": "Vytvoření plánů dostupnosti vám umožní spravovat dostupnost mezi typy událostí. Mohou být použity pro jeden nebo více typů událostí.",
|
||||
"requires_ownership_of_a_token": "Vyžaduje vlastnictví tokenu, který patří následující adrese:",
|
||||
@@ -933,8 +908,6 @@
|
||||
"api_key_no_note": "Bezejmenný klíč API",
|
||||
"api_key_never_expires": "Tento klíč API nemá datum uplynutí platnosti",
|
||||
"edit_api_key": "Upravit klíč API",
|
||||
"never_expire_key": "Platnost nikdy neuplyne",
|
||||
"delete_api_key": "Odvolat klíč API",
|
||||
"success_api_key_created": "Klíč API vytvořen",
|
||||
"success_api_key_edited": "Klíč API aktualizován",
|
||||
"create": "Vytvořit",
|
||||
@@ -975,7 +948,6 @@
|
||||
"event_location_changed": "Aktualizováno – u vaší události se změnilo místo",
|
||||
"location_changed_event_type_subject": "Změna místa: událost {{eventType}} jménem {{name}} v den {{date}}",
|
||||
"current_location": "Současné místo",
|
||||
"user_phone": "Vaše telefonní číslo",
|
||||
"new_location": "Nové místo",
|
||||
"session": "Relace",
|
||||
"session_description": "Mějte pod kontrolou relaci svého účtu",
|
||||
@@ -1001,7 +973,6 @@
|
||||
"zapier_setup_instructions": "<0>Přihlaste se ke svému účtu Zapier a vytvořte nový Zap.</0><1>Vyberte Cal.com jako svoji aplikaci Trigger. Také vyberte událost Trigger.</1><2>Vyberte svůj účet a pak zadejte svůj unikátní klíč API.</2><3>Otestujte svůj Trigger.</3><4>Všechno máte nastaveno!</4>",
|
||||
"install_zapier_app": "Nejdřív si z App Store nainstalujte aplikaci Zapier.",
|
||||
"connect_apple_server": "Připojit se k serveru Apple",
|
||||
"connect_caldav_server": "Připojit se k CalDav (Beta)",
|
||||
"calendar_url": "URL kalendáře",
|
||||
"apple_server_generate_password": "Vygenerujte si specifické heslo pro aplikaci {{appName}} na",
|
||||
"credentials_stored_encrypted": "Vaše přihlašovací údaje budou uloženy a zašifrovány.",
|
||||
@@ -1033,19 +1004,16 @@
|
||||
"go_to": "Přejít na: ",
|
||||
"zapier_invite_link": "Odkaz s pozvánkou do služby Zapier",
|
||||
"meeting_url_provided_after_confirmed": "Po potvrzení události bude vytvořena adresa URL schůzky.",
|
||||
"attendees_name": "Jméno účastníka",
|
||||
"dynamically_display_attendee_or_organizer": "Dynamické zobrazení jména účastníka pro vás nebo vašeho jména pro účastníka",
|
||||
"event_location": "Místo události",
|
||||
"reschedule_optional": "Důvod pro změnu plánu (volitelné)",
|
||||
"reschedule_placeholder": "Dejte ostatním vědět, proč potřebujete změnit plán",
|
||||
"event_cancelled": "Tato událost je zrušena",
|
||||
"emailed_information_about_cancelled_event": "Poslali jsme vám a ostatním účastníkům informační e-mail.",
|
||||
"this_input_will_shown_booking_this_event": "Toto pole se zobrazí při rezervaci této události",
|
||||
"meeting_url_in_conformation_email": "Adresa URL schůzky je v potvrzovacím e-mailu",
|
||||
"url_start_with_https": "Adresa URL musí začínat http:// nebo https://",
|
||||
"number_provided": "Bude uvedeno telefonní číslo",
|
||||
"before_event_trigger": "před zahájením události",
|
||||
"event_cancelled_trigger": "při zrušení události",
|
||||
"new_event_trigger": "při rezervaci nové události",
|
||||
"email_host_action": "odeslání e-mailu hostiteli",
|
||||
"email_attendee_action": "odeslat e-mail účastníkům",
|
||||
@@ -1107,7 +1075,6 @@
|
||||
"add_exchange2016": "Připojit server Exchange 2016",
|
||||
"custom_template": "Vlastní šablona",
|
||||
"email_body": "Tělo e-mailu",
|
||||
"subject": "Předmět",
|
||||
"text_message": "Textová zpráva",
|
||||
"specific_issue": "Uveďte konkrétní problém",
|
||||
"browse_our_docs": "procházet naše dokumenty",
|
||||
@@ -1135,12 +1102,9 @@
|
||||
"new_seat_title": "Někdo se přidal k události",
|
||||
"variable": "Proměnná",
|
||||
"event_name_variable": "Název události",
|
||||
"organizer_name_variable": "Jméno organizátora",
|
||||
"attendee_name_variable": "Jméno účastníka",
|
||||
"event_date_variable": "Datum události",
|
||||
"event_time_variable": "Čas události",
|
||||
"location_variable": "Místo",
|
||||
"additional_notes_variable": "Doplňující poznámky",
|
||||
"app_upgrade_description": "Pokud chcete použít tuto funkci, musíte provést aktualizaci na účet Pro.",
|
||||
"invalid_number": "Neplatné telefonní číslo",
|
||||
"navigate": "Navigace",
|
||||
@@ -1211,7 +1175,6 @@
|
||||
"start_of_week": "Začátek týdne",
|
||||
"recordings_title": "Nahrávky",
|
||||
"recording": "Nahrávka",
|
||||
"happy_scheduling": "Hodně štěstí s plánováním",
|
||||
"select_calendars": "Vyberte kalendáře, u kterých chcete kontrolovat konflikty v zájmu prevence dvojích rezervací.",
|
||||
"check_for_conflicts": "Zkontrolovat konflikty",
|
||||
"view_recordings": "Zobrazit nahrávky",
|
||||
@@ -1234,7 +1197,6 @@
|
||||
"recurring_event_tab_description": "Nastavení opakujícího se plánu",
|
||||
"today": "dnes",
|
||||
"appearance": "Vzhled",
|
||||
"appearance_subtitle": "Správa nastavení vzhledu rezervace",
|
||||
"my_account": "Můj účet",
|
||||
"general": "Obecné",
|
||||
"calendars": "Kalendáře",
|
||||
@@ -1254,7 +1216,6 @@
|
||||
"conferencing_description": "Přidejte si oblíbené videokonferenční pro vaše schůzky",
|
||||
"add_conferencing_app": "Přidat videokonferenční aplikaci",
|
||||
"password_description": "Správa nastavení hesel k vašemu účtu",
|
||||
"2fa_description": "Správa nastavení hesel k vašemu účtu",
|
||||
"we_just_need_basic_info": "K nastavení vašeho profilu potřebujeme jen několik základních informací.",
|
||||
"skip": "Přeskočit",
|
||||
"do_this_later": "Provést později",
|
||||
@@ -1278,7 +1239,6 @@
|
||||
"event_date_info": "Datum události",
|
||||
"event_time_info": "Čas začátku události",
|
||||
"location_info": "Místo události",
|
||||
"organizer_name_info": "Vaše jméno",
|
||||
"additional_notes_info": "Další poznámky k rezervaci",
|
||||
"attendee_name_info": "Jméno osoby provádějící rezervaci",
|
||||
"to": "Komu",
|
||||
@@ -1342,8 +1302,6 @@
|
||||
"copy_link_to_form": "Kopírovat odkaz na formulář",
|
||||
"theme": "Motiv",
|
||||
"theme_applies_note": "Toto se týká pouze vašich veřejných stránek s rezervacemi",
|
||||
"theme_light": "Světlý",
|
||||
"theme_dark": "Tmavý",
|
||||
"theme_system": "Výchozí nastavení systému",
|
||||
"add_a_team": "Přidat tým",
|
||||
"add_webhook_description": "Přijímejte data o schůzkách v reálném čase, pokud v {{appName}} dojde k nějaké akci",
|
||||
@@ -1352,7 +1310,6 @@
|
||||
"enable_webhook": "Povolit webhook",
|
||||
"add_webhook": "Přidat webhook",
|
||||
"webhook_edited_successfully": "Webhook byl uložen",
|
||||
"webhooks_description": "Přijímejte data o schůzkách v reálném čase, pokud v {{appName}} dojde k nějaké akci",
|
||||
"api_keys_description": "Vygenerujte si klíče API pro přístup k vlastnímu účtu",
|
||||
"new_api_key": "Nový klíč API",
|
||||
"active": "aktivní",
|
||||
@@ -1394,11 +1351,7 @@
|
||||
"billing_freeplan_title": "Momentálně používáte tarif ZDARMA",
|
||||
"billing_freeplan_description": "Lépe se pracuje v týmech. Rozšiřte své pracovní postupy o „round-robin“ a kolektivní události a vytvořte pokročilé směrovací formuláře",
|
||||
"billing_freeplan_cta": "Vyzkoušet nyní",
|
||||
"billing_manage_details_title": "Zobrazit a spravovat fakturační údaje",
|
||||
"billing_manage_details_description": "Zobrazit a spravovat fakturační údaje, možnost zrušit předplatné.",
|
||||
"billing_portal": "Fakturační portál",
|
||||
"billing_help_title": "Potřebujete ještě něco?",
|
||||
"billing_help_description": "Pokud potřebujete jakoukoliv pomoc s fakturací, náš tým zákaznické podpory je tu pro Vás.",
|
||||
"billing_help_cta": "Kontaktovat podporu",
|
||||
"ignore_special_characters_booking_questions": "Ignorujte speciální znaky v identifikátoru rezervační otázky. Používejte pouze písmena a číslice",
|
||||
"retry": "Opakovat",
|
||||
@@ -1406,7 +1359,6 @@
|
||||
"calendar_connection_fail": "Připojení kalendáře se nezdařilo",
|
||||
"booking_confirmation_success": "Potvrzení rezervace bylo úspěšné",
|
||||
"booking_rejection_success": "Zamítnutí rezervace bylo úspěšné",
|
||||
"booking_confirmation_fail": "Potvrzení rezervace se nezdařilo",
|
||||
"booking_tentative": "Tato rezervace je předběžná",
|
||||
"booking_accept_intent": "Ajaj, chci přijmout",
|
||||
"we_wont_show_again": "Znovu toto nezobrazovat",
|
||||
@@ -1429,7 +1381,6 @@
|
||||
"new_event_type_availability": "Dostupnost pro {{eventTypeTitle}}",
|
||||
"error_editing_availability": "Chyba při úpravě dostupnosti",
|
||||
"dont_have_permission": "Nemáte oprávnění k přístupu k tomuto dokumentu.",
|
||||
"saml_config": "Single Sign-On",
|
||||
"saml_configuration_placeholder": "Vložte sem SAML metadata vašeho Identity Providera",
|
||||
"saml_email_required": "Zadejte prosím e-mail, abychom mohli určit vašeho SAML Identity Providera",
|
||||
"saml_sp_title": "Podrobnosti poskytovatele služby",
|
||||
@@ -1438,7 +1389,6 @@
|
||||
"saml_sp_entity_id": "ID entity SP",
|
||||
"saml_sp_acs_url_copied": "URL adresa ACS byla zkopírována!",
|
||||
"saml_sp_entity_id_copied": "ID entity SP bylo zkopírováno!",
|
||||
"saml_btn_configure": "Konfigurovat",
|
||||
"add_calendar": "Přidat kalendář",
|
||||
"limit_future_bookings": "Omezit budoucí rezervace",
|
||||
"limit_future_bookings_description": "Omezit, jak dlouho dopředu lze tuto událost rezervovat",
|
||||
@@ -1451,7 +1401,6 @@
|
||||
"your_team_disbanded_successfully": "Váš tým byl úspěšně rozpuštěn",
|
||||
"error_creating_team": "Chyba při vytváření týmu",
|
||||
"you": "Vy",
|
||||
"send_email": "Odeslat e-mail",
|
||||
"member_already_invited": "Člen byl už pozván",
|
||||
"enter_email_or_username": "Zadejte e-mail nebo uživatelské jméno",
|
||||
"team_name_taken": "Toto jméno je už obsazeno",
|
||||
@@ -1618,12 +1567,8 @@
|
||||
"delete_sso_configuration_confirmation": "Ano, odstranit konfiguraci {{connectionType}}",
|
||||
"delete_sso_configuration_confirmation_description": "Opravdu chcete odstranit konfiguraci {{connectionType}}? Členové vašeho týmu, kteří používají přihlášení {{connectionType}}, ztratí přístup k webu Cal.com.",
|
||||
"organizer_timezone": "Časové pásmo organizátora",
|
||||
"email_no_user_cta": "Vytvořit účet",
|
||||
"email_user_cta": "Zobrazit pozvánku",
|
||||
"email_no_user_invite_heading": "Byli jste pozváni do týmu v aplikaci {{appName}}",
|
||||
"email_no_user_invite_subheading": "Uživatel {{invitedBy}} vás pozval, abyste se připojili k jeho týmu v aplikaci {{appName}}. {{appName}} je plánovač událostí, který vám a vašemu týmu umožňuje plánovat schůzky bez e-mailového ping-pongu.",
|
||||
"email_user_invite_subheading": "Uživatel {{invitedBy}} vás pozval, abyste se připojili k jeho týmu „{{teamName}}“ v aplikaci {{appName}}. {{appName}} je plánovač událostí, který vám a vašemu týmu umožňuje plánovat schůzky bez e-mailového pingpongu.",
|
||||
"email_no_user_invite_steps_intro": "Provedeme vás několika krátkými kroky a za malou chvíli si budete se svým týmem užívat plánování bez stresu.",
|
||||
"email_no_user_step_one": "Vyberte si uživatelské jméno",
|
||||
"email_no_user_step_two": "Připojte svůj účet kalendáře",
|
||||
"email_no_user_step_three": "Nastavte si dostupnost",
|
||||
@@ -1644,11 +1589,9 @@
|
||||
"no_longer_attending": "Této události se již neúčastníte",
|
||||
"attendee_no_longer_attending_subject": "Účastník se již neúčastní události {{title}} v den {{date}}",
|
||||
"attendee_no_longer_attending": "Účastník se již neúčastní vaší události",
|
||||
"attendee_no_longer_attending_subtitle": "Uživatel {{name}} zrušil svou účast. V tomto časovém intervalu se tedy uvolnilo místo",
|
||||
"create_event_on": "Vytvořit událost v:",
|
||||
"default_app_link_title": "Nastavte výchozí odkaz na aplikaci",
|
||||
"default_app_link_description": "Nastavení výchozího odkazu na aplikaci umožní, aby všechny nově vytvořené typy událostí používaly vámi nastavený odkaz na aplikaci.",
|
||||
"change_default_conferencing_app": "Nastavit jako výchozí",
|
||||
"organizer_default_conferencing_app": "Výchozí aplikace organizátora",
|
||||
"under_maintenance": "Odstávka z důvodu údržby",
|
||||
"under_maintenance_description": "Tým {{appName}} provádí plánovanou údržbu. V případě dotazů se obraťte na podporu.",
|
||||
@@ -1663,11 +1606,9 @@
|
||||
"booking_confirmation_failed": "Potvrzení rezervace se nezdařilo",
|
||||
"not_enough_seats": "Nedostatek míst",
|
||||
"form_builder_field_already_exists": "Pole s tímto názvem již existuje",
|
||||
"form_builder_field_add_subtitle": "Přizpůsobte otázky položené na stránce rezervace",
|
||||
"show_on_booking_page": "Zobrazit na stránce rezervace",
|
||||
"get_started_zapier_templates": "Začněte používat šablony Zapier",
|
||||
"team_is_unpublished": "Tým {{team}} není zveřejněn",
|
||||
"team_is_unpublished_description": "Tento týmový odkaz není v současné době k dispozici. Kontaktujte vlastníka týmu nebo ho požádejte o jeho zveřejnění.",
|
||||
"team_member": "Člen týmu",
|
||||
"a_routing_form": "Směrovací formulář",
|
||||
"form_description_placeholder": "Popis formuláře",
|
||||
@@ -1698,7 +1639,6 @@
|
||||
"spot_popular_event_types_description": "Zjistěte, které typy vašich událostí získávají nejvíce kliknutí a rezervací",
|
||||
"no_responses_yet": "Zatím žádné odpovědi",
|
||||
"this_will_be_the_placeholder": "Toto bude zástupný znak",
|
||||
"error_booking_event": "Při rezervaci události došlo k chybě, obnovte prosím stránku a zkuste to znovu",
|
||||
"timeslot_missing_title": "Nebyl vybrán žádný časový slot",
|
||||
"timeslot_missing_description": "Vyberte časový slot, aby mohla být událost zaregistrována.",
|
||||
"timeslot_missing_cta": "Vybrat časový slot",
|
||||
@@ -1715,7 +1655,6 @@
|
||||
"verification_code": "Ověřovací kód",
|
||||
"can_you_try_again": "Můžete to zkusit znovu a použít jiný čas?",
|
||||
"verify": "Ověřit",
|
||||
"timezone_variable": "Časová zóna",
|
||||
"timezone_info": "Časové pásmo přijímající osoby",
|
||||
"event_end_time_variable": "Čas ukončení události",
|
||||
"event_end_time_info": "Čas ukončení události",
|
||||
@@ -1760,11 +1699,9 @@
|
||||
"least_booked_members": "Nejméně rezervovaných členů",
|
||||
"events_created": "Události vytvořeny",
|
||||
"events_completed": "Události dokončeny",
|
||||
"events_cancelled": "Události zrušeny",
|
||||
"events_rescheduled": "Události přesunuty",
|
||||
"from_last_period": "z posledního období",
|
||||
"from_to_date_period": "Od: {{startDate}} do: {{endDate}}",
|
||||
"analytics_for_organisation": "Insights",
|
||||
"subtitle_analytics": "Zjistěte více o činnosti vašeho týmu",
|
||||
"redirect_url_warning": "Přidáním přesměrování se stránka úspěchu vypne. Nezapomeňte na vlastní stránce úspěchu uvést „Rezervace potvrzena“.",
|
||||
"event_trends": "Trendy událostí",
|
||||
@@ -1795,7 +1732,6 @@
|
||||
"complete_your_booking": "Dokončete svou rezervaci",
|
||||
"complete_your_booking_subject": "Dokončete svou rezervaci: {{title}} dne {{date}}",
|
||||
"confirm_your_details": "Potvrďte své údaje",
|
||||
"never_expire": "Platnost nikdy neuplyne",
|
||||
"currency_string": "{{amount, currency}}",
|
||||
"charge_card_dialog_body": "Chystáte se účtovat účastníkovi {{amount, currency}}. Opravdu chcete pokračovat?",
|
||||
"charge_attendee": "Naúčtovat účastníkovi {{amount, currency}}",
|
||||
@@ -1814,7 +1750,6 @@
|
||||
"book_my_cal": "Book my Cal",
|
||||
"invite_as": "Pozvat jako",
|
||||
"form_updated_successfully": "Formulář byl aktualizován.",
|
||||
"email_not_cal_member_cta": "Připojte se ke svému týmu",
|
||||
"disable_attendees_confirmation_emails": "Vypnutí výchozích potvrzovacích e-mailů pro účastníky",
|
||||
"disable_attendees_confirmation_emails_description": "U tohoto typu události je aktivní alespoň jeden pracovní postup, který po rezervaci události odešle účastníkům e-mail.",
|
||||
"disable_host_confirmation_emails": "Vypnutí výchozích potvrzovacích e-mailů pro hostitele",
|
||||
@@ -1824,5 +1759,6 @@
|
||||
"connect_google_workspace": "Propojit s Google Workspace",
|
||||
"google_workspace_admin_tooltip": "Používání této funkce vyžaduje, abyste byli administrátory Google Workspace",
|
||||
"first_event_type_webhook_description": "Vytvořte svůj první webhook pro tento typ události",
|
||||
"create_for": "Vytvořit pro"
|
||||
"create_for": "Vytvořit pro",
|
||||
"organization_url_taken": "Tato adresa URL je už obsazená"
|
||||
}
|
||||
|
||||
@@ -10,12 +10,9 @@
|
||||
"calcom_explained_new_user": "Afslut opsætningen af din {{appName}} konto! Du er kun få skridt fra at løse alle dine planlægningsproblemer.",
|
||||
"have_any_questions": "Har du spørgsmål? Vi er her for at hjælpe.",
|
||||
"reset_password_subject": "{{appName}}: Nulstil adgangskodeinstruktioner",
|
||||
"verify_email_banner_button": "Send e-mail",
|
||||
"event_declined_subject": "Afvist: {{title}} den {{date}}",
|
||||
"event_cancelled_subject": "Aflyst: {{title}} den {{date}}",
|
||||
"event_request_declined": "Din begivenhedsanmodning er blevet afvist",
|
||||
"event_request_declined_recurring": "Din tilbagevendende begivenhedsanmodning er blevet afvist",
|
||||
"event_request_cancelled": "Din planlagte begivenhed blev aflyst",
|
||||
"organizer": "Arrangør",
|
||||
"need_to_reschedule_or_cancel": "Behov for at omlægge eller annullere?",
|
||||
"cancellation_reason": "Årsag til aflysning (valgfri)",
|
||||
@@ -73,13 +70,9 @@
|
||||
"your_meeting_has_been_booked": "Dit møde er blevet booket",
|
||||
"event_type_has_been_rescheduled_on_time_date": "Din {{title}} er blevet flyttet til {{date}}.",
|
||||
"event_has_been_rescheduled": "Opdateret - Din begivenhed er blevet flyttet",
|
||||
"request_reschedule_title_attendee": "Anmodning om at omlægge din booking",
|
||||
"request_reschedule_subtitle": "{{organizer}} har annulleret bookingen og anmodet dig om at vælge et andet tidspunkt.",
|
||||
"request_reschedule_title_organizer": "Du har anmodet {{attendee}} om at omlægge",
|
||||
"request_reschedule_subtitle_organizer": "Du har annulleret bookingen og {{attendee}} bør vælge en ny bookingtid med dig.",
|
||||
"rescheduled_event_type_subject": "Anmodning om omlægning sendt: {{eventType}} med {{name}} den {{date}}",
|
||||
"requested_to_reschedule_subject_attendee": "Handling Påkrævet Omlægning: Reservér en ny tid for {{eventType}} med {{name}}",
|
||||
"reschedule_reason": "Årsag til omlægning",
|
||||
"hi_user_name": "Hej {{name}}",
|
||||
"ics_event_title": "{{eventType}} med {{name}}",
|
||||
"new_event_subject": "Ny begivenhed: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
@@ -115,6 +108,7 @@
|
||||
"team_upgrade_banner_description": "Tak fordi du har prøvet vores nye teamplan. Vi har bemærket at dit team \"{{teamName}}\" skal opgraderes.",
|
||||
"team_upgrade_banner_action": "Opgradér her",
|
||||
"team_upgraded_successfully": "Dit team blev opgraderet!",
|
||||
"org_upgrade_banner_action": "Opgradér her",
|
||||
"use_link_to_reset_password": "Brug nedenstående link for at nulstille din adgangskode",
|
||||
"hey_there": "Hej,",
|
||||
"forgot_your_password_calcom": "Glemt din adgangskode? - {{appName}}",
|
||||
@@ -223,6 +217,7 @@
|
||||
"done": "Udført",
|
||||
"all_done": "Alt er klart!",
|
||||
"all_apps": "Alle",
|
||||
"all": "Alle",
|
||||
"check_email_reset_password": "Tjek din e-mail. Vi har sendt dig et link til at nulstille din adgangskode.",
|
||||
"finish": "Afslut",
|
||||
"few_sentences_about_yourself": "Et par sætninger om dig selv. Dette vil blive vist på din personlige url side.",
|
||||
@@ -241,7 +236,6 @@
|
||||
"welcome_to_calcom": "Velkommen til {{appName}}",
|
||||
"welcome_instructions": "Fortæl os hvad du vil kaldes, og lad os vide hvilken tidszone du er i. Du vil kunne redigere dette senere.",
|
||||
"connect_caldav": "Forbind til CalDav (Beta)",
|
||||
"credentials_stored_and_encrypted": "Dine legitimationsoplysninger bliver gemt og krypteret.",
|
||||
"connect": "Tilslut",
|
||||
"try_for_free": "Prøv gratis",
|
||||
"create_booking_link_with_calcom": "Opret dit eget booking link med {{appName}}",
|
||||
@@ -262,7 +256,6 @@
|
||||
"user_needs_to_confirm_or_reject_booking_recurring": "{{user}} mangler stadig at bekræfte eller afvise hver booking af det tilbagevendende møde.",
|
||||
"meeting_is_scheduled": "Dette møde er planlagt",
|
||||
"meeting_is_scheduled_recurring": "De tilbagevendende begivenheder er planlagt",
|
||||
"submitted_recurring": "Dit tilbagevendende møde er blevet indsendt",
|
||||
"booking_submitted": "Din booking er blevet indsendt",
|
||||
"booking_submitted_recurring": "Dit tilbagevendende møde er blevet indsendt",
|
||||
"booking_confirmed": "Din booking er blevet bekræftet",
|
||||
@@ -295,7 +288,6 @@
|
||||
"error_end_time_next_day": "Sluttidspunktet kan ikke være længere end 24 timer",
|
||||
"back_to_bookings": "Tilbage til bookinger",
|
||||
"free_to_pick_another_event_type": "Du er til enhver tid velkommen til at vælge en anden begivenhed.",
|
||||
"cancelled": "Annullerede",
|
||||
"cancellation_successful": "Annullering lykkedes",
|
||||
"really_cancel_booking": "Vil du virkelig annullere din booking?",
|
||||
"cannot_cancel_booking": "Du kan ikke annullere denne booking",
|
||||
@@ -304,11 +296,9 @@
|
||||
"cancelling_event_recurring": "Begivenheden er en forekomst af en tilbagevendende begivenhed.",
|
||||
"cancelling_all_recurring": "Disse er alle resterende forekomster i den tilbagevendende begivenhed.",
|
||||
"error_with_status_code_occured": "Der opstod en fejl med statuskoden {{status}}.",
|
||||
"booking_already_cancelled": "Denne booking er allerede aflyst",
|
||||
"booking_already_accepted_rejected": "Denne booking er allerede accepteret eller afvist",
|
||||
"go_back_home": "Gå tilbage til hjem",
|
||||
"or_go_back_home": "Eller gå tilbage til hjem",
|
||||
"no_availability": "Ikke tilgængelig",
|
||||
"no_meeting_found": "Intet Møde Fundet",
|
||||
"no_meeting_found_description": "Dette møde findes ikke. Kontakt mødeejeren for et opdateret link.",
|
||||
"no_status_bookings_yet": "Ingen {{status}} bookinger",
|
||||
@@ -319,7 +309,6 @@
|
||||
"upcoming_bookings": "Så snart nogen booker en tid med dig, vil det dukke op her.",
|
||||
"recurring_bookings": "Så snart nogen booker et tilbagevendende møde med dig, vil det dukke op her.",
|
||||
"past_bookings": "Dine tidligere bookinger vil blive vist her.",
|
||||
"cancelled_bookings": "Dine annullerede bookinger vil blive vist her.",
|
||||
"unconfirmed_bookings": "Dine ubekræftede bookinger vil dukke op her.",
|
||||
"unconfirmed_bookings_tooltip": "Ubekræftede bookinger",
|
||||
"on": "den",
|
||||
@@ -359,7 +348,6 @@
|
||||
"browse_api_documentation": "Gennemse vores API-dokumentation",
|
||||
"leverage_our_api": "Udnyt vores API til fuld kontrol og tilpasning.",
|
||||
"create_webhook": "Opret Webhook",
|
||||
"booking_cancelled": "Booking Aflyst",
|
||||
"booking_rescheduled": "Booking Omlagt",
|
||||
"booking_created": "Booking Oprettet",
|
||||
"meeting_ended": "Møde Afsluttet",
|
||||
@@ -371,8 +359,6 @@
|
||||
"team_webhooks": "Team Webhooks",
|
||||
"create_new_webhook_to_account": "Opret en ny webhook til din konto",
|
||||
"new_webhook": "Ny Webhook",
|
||||
"receive_cal_meeting_data": "Modtag {{appName}} mødedata på en specificeret URL, i realtid, når en begivenhed bliver planlagt eller aflyst.",
|
||||
"receive_cal_event_meeting_data": "Modtag {{appName}} mødedata på en specificeret URL, i realtid, når denne begivenhed bliver planlagt eller aflyst.",
|
||||
"responsive_fullscreen_iframe": "Responsiv fuldskærms-iframe",
|
||||
"loading": "Indlæser...",
|
||||
"deleting": "Sletter...",
|
||||
@@ -434,7 +420,6 @@
|
||||
"invalid_password_hint": "Adgangskoden skal være mindst {{passwordLength}} tegn langt, der indeholder mindst ét tal og har en blanding af store og små bogstaver",
|
||||
"incorrect_password": "Adgangskoden er forkert.",
|
||||
"incorrect_username_password": "Brugernavn eller adgangskode er forkert.",
|
||||
"24_h": "24h",
|
||||
"use_setting": "Brug indstilling",
|
||||
"am_pm": "am/pm",
|
||||
"time_options": "Tidsmuligheder",
|
||||
@@ -476,15 +461,11 @@
|
||||
"booking_confirmation": "Bekræft din {{eventTypeTitle}} med {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Omlæg din {{eventTypeTitle}} med {{profileName}}",
|
||||
"in_person_meeting": "Personligt møde",
|
||||
"attendee_in_person": "Personlig (Deltageradresse)",
|
||||
"in_person": "Personlig (Arrangøradresse)",
|
||||
"link_meeting": "Link møde",
|
||||
"phone_call": "Deltagers Telefonnummer",
|
||||
"your_number": "Dit telefonnummer",
|
||||
"phone_number": "Telefonnummer",
|
||||
"attendee_phone_number": "Deltagers Telefonnummer",
|
||||
"organizer_phone_number": "Arrangørs Telefonnummer",
|
||||
"host_phone_number": "Dit Telefonnummer",
|
||||
"enter_phone_number": "Indtast telefonnummer",
|
||||
"reschedule": "Omlæg",
|
||||
"reschedule_this": "Omlæg i stedet",
|
||||
@@ -596,9 +577,6 @@
|
||||
"new_event_type_btn": "Ny begivenhedstype",
|
||||
"new_event_type_heading": "Opret din første begivenhedstype",
|
||||
"new_event_type_description": "Begivenhedstyper gør det muligt for dig at dele links, der viser tilgængelige tider i din kalender, og give folk mulighed for at foretage bookinger med dig.",
|
||||
"new_event_title": "Tilføj en ny begivenhedstype",
|
||||
"new_team_event": "Tilføj en ny team begivenhedstype",
|
||||
"new_event_description": "Opret en ny begivenhedstype for folk til at booke tider med.",
|
||||
"event_type_created_successfully": "{{eventTypeTitle}} begivenhedstype blev oprettet",
|
||||
"event_type_updated_successfully": "{{eventTypeTitle}} begivenhedstype blev opdateret",
|
||||
"event_type_deleted_successfully": "Begivenhedstypen blev slettet",
|
||||
@@ -758,7 +736,6 @@
|
||||
"automation": "Automatisering",
|
||||
"configure_how_your_event_types_interact": "Indstil hvordan dine begivenhedstyper skal interagere med dine kalendere.",
|
||||
"toggle_calendars_conflict": "Skift mellem de kalendere du vil tjekke for konflikter, for at forhindre dobbeltbookinger.",
|
||||
"select_destination_calendar": "Opret begivenheder på",
|
||||
"connect_additional_calendar": "Forbind yderligere kalender",
|
||||
"calendar_updated_successfully": "Kalenderen blev opdateret",
|
||||
"conferencing": "Konferencer",
|
||||
@@ -792,7 +769,6 @@
|
||||
"number_apps_other": "{{count}} Apps",
|
||||
"trending_apps": "Populære Apps",
|
||||
"most_popular": "Mest Populære",
|
||||
"explore_apps": "{{category}} apps",
|
||||
"installed_apps": "Installerede Apps",
|
||||
"free_to_use_apps": "Gratis",
|
||||
"no_category_apps": "Ingen {{category}} apps",
|
||||
@@ -804,7 +780,6 @@
|
||||
"no_category_apps_description_other": "Tilføj enhver anden type app for at gøre alle mulige ting",
|
||||
"no_category_apps_description_web3": "Tilføj en web3 app til dine bookingsider",
|
||||
"installed_app_calendar_description": "Indstil kalenderne til at tjekke for konflikter, for at forhindre dobbeltbookinger.",
|
||||
"installed_app_conferencing_description": "Tilføj dine foretrukne videokonference apps til dine møder",
|
||||
"installed_app_payment_description": "Indstil hvilke betalingsbehandlingstjenester der skal bruges, når du opkræver betaling fra dine kunder.",
|
||||
"installed_app_analytics_description": "Indstil hvilke analyseapps der skal bruges til dine bookingsider",
|
||||
"installed_app_other_description": "Alle dine installerede apps fra andre kategorier.",
|
||||
@@ -830,7 +805,6 @@
|
||||
"terms_of_service": "Vilkår og betingelser",
|
||||
"remove": "Fjern",
|
||||
"add": "Tilføj",
|
||||
"installed_one": "Installeret",
|
||||
"installed_other": "{{count}} installeret",
|
||||
"verify_wallet": "Verificér Wallet",
|
||||
"create_events_on": "Opret begivenheder på",
|
||||
@@ -892,8 +866,6 @@
|
||||
"api_key_no_note": "Navnløs API-nøgle",
|
||||
"api_key_never_expires": "Denne API-nøgle har ingen udløbsdato",
|
||||
"edit_api_key": "Redigér API-nøgle",
|
||||
"never_expire_key": "Udløber aldrig",
|
||||
"delete_api_key": "Tilbagekald API-nøgle",
|
||||
"success_api_key_created": "API-nøgle oprettet",
|
||||
"success_api_key_edited": "API-nøgle opdateret",
|
||||
"create": "Opret",
|
||||
@@ -934,7 +906,6 @@
|
||||
"event_location_changed": "Opdateret - Din begivenhed ændrede placeringen",
|
||||
"location_changed_event_type_subject": "Placering ændret: {{eventType}} med {{name}} den {{date}}",
|
||||
"current_location": "Nuværende Placering",
|
||||
"user_phone": "Dit telefonnummer",
|
||||
"new_location": "Ny Placering",
|
||||
"session": "Session",
|
||||
"session_description": "Kontrollér din kontosession",
|
||||
@@ -960,7 +931,6 @@
|
||||
"zapier_setup_instructions": "<0>Log ind på din Zapier-konto og opret en ny Zap.</0><1>Vælg Cal.com som din Trigger app. Vælg også en Trigger event. </1><2>Vælg din konto og indtast derefter din unikke API-nøgle.</2><3>Test din Trigger.</3><4>Du er klar!</4>",
|
||||
"install_zapier_app": "Du skal først installere Zapier appen i App Store.",
|
||||
"connect_apple_server": "Forbind til Apple Server",
|
||||
"connect_caldav_server": "Forbind til CalDav (Beta)",
|
||||
"calendar_url": "Kalender URL",
|
||||
"apple_server_generate_password": "Generer en app-specifik adgangskode til brug med {{appName}} på",
|
||||
"credentials_stored_encrypted": "Dine legitimationsoplysninger vil blive gemt og krypteret.",
|
||||
@@ -992,19 +962,16 @@
|
||||
"go_to": "Gå til: ",
|
||||
"zapier_invite_link": "Zapier Invitationslink",
|
||||
"meeting_url_provided_after_confirmed": "Et møde URL vil blive oprettet, når begivenheden er bekræftet.",
|
||||
"attendees_name": "Deltagerens navn",
|
||||
"dynamically_display_attendee_or_organizer": "Vis dynamisk navnet på din deltager for dig, eller dit navn hvis det ses af din deltager",
|
||||
"event_location": "Begivenhedens placering",
|
||||
"reschedule_optional": "Årsag til omlægning (valgfri)",
|
||||
"reschedule_placeholder": "Lad andre vide, hvorfor du har brug for at omlægge",
|
||||
"event_cancelled": "Denne begivenhed er aflyst",
|
||||
"emailed_information_about_cancelled_event": "Vi har sendt en e-mail til dig og de andre deltagere for at give dem besked.",
|
||||
"this_input_will_shown_booking_this_event": "Dette input vil blive vist ved booking af denne begivenhed",
|
||||
"meeting_url_in_conformation_email": "Møde-url er i bekræftelses-mailen",
|
||||
"url_start_with_https": "URL'en skal starte med http:// eller https://",
|
||||
"number_provided": "Telefonnummer vil blive angivet",
|
||||
"before_event_trigger": "før begivenheden starter",
|
||||
"event_cancelled_trigger": "når begivenheden er aflyst",
|
||||
"new_event_trigger": "når ny begivenhed er booket",
|
||||
"email_host_action": "send e-mail til vært",
|
||||
"sms_number_action": "send SMS til et specifikt nummer",
|
||||
@@ -1065,7 +1032,6 @@
|
||||
"add_exchange2016": "Forbind Exchange 2016 Server",
|
||||
"custom_template": "Brugerdefineret skabelon",
|
||||
"email_body": "Email tekst",
|
||||
"subject": "Email emne",
|
||||
"text_message": "Tekstbesked",
|
||||
"specific_issue": "Har du et konkret spørgsmål?",
|
||||
"browse_our_docs": "gennemse vores dokumenter",
|
||||
@@ -1093,12 +1059,9 @@
|
||||
"new_seat_title": "Nogen har tilføjet sig selv til en begivenhed",
|
||||
"variable": "Variabel",
|
||||
"event_name_variable": "Begivenhedsnavn",
|
||||
"organizer_name_variable": "Arrangør",
|
||||
"attendee_name_variable": "Deltager",
|
||||
"event_date_variable": "Dato for begivenhed",
|
||||
"event_time_variable": "Tidspunkt for begivenhed",
|
||||
"location_variable": "Placering",
|
||||
"additional_notes_variable": "Yderligere bemærkninger",
|
||||
"app_upgrade_description": "For at bruge denne funktion skal du opgradere til en Pro-konto.",
|
||||
"invalid_number": "Ugyldigt telefonnummer",
|
||||
"navigate": "Navigér",
|
||||
@@ -1187,7 +1150,6 @@
|
||||
"recurring_event_tab_description": "Opret en gentagende tidsplan",
|
||||
"today": "i dag",
|
||||
"appearance": "Udseende",
|
||||
"appearance_subtitle": "Administrér indstillinger for din booking visning",
|
||||
"my_account": "Min konto",
|
||||
"general": "Generelt",
|
||||
"calendars": "Kalendere",
|
||||
@@ -1205,7 +1167,6 @@
|
||||
"appearance_description": "Administrér indstillinger for din booking visning",
|
||||
"conferencing_description": "Tilføj dine foretrukne videokonference apps til dine møder",
|
||||
"password_description": "Administrér indstillinger for dine kontoadgangskoder",
|
||||
"2fa_description": "Administrér indstillinger for dine kontoadgangskoder",
|
||||
"we_just_need_basic_info": "Vi har bare brug for nogle grundlæggende oplysninger for at opsætte din profil.",
|
||||
"skip": "Spring Over",
|
||||
"do_this_later": "Gør dette senere",
|
||||
@@ -1229,7 +1190,6 @@
|
||||
"event_date_info": "Dato for begivenheden",
|
||||
"event_time_info": "Starttidspunkt for begivenheden",
|
||||
"location_info": "Begivenhedens placering",
|
||||
"organizer_name_info": "Dit navn",
|
||||
"additional_notes_info": "De yderligere noter til booking",
|
||||
"attendee_name_info": "Navn på personen der booker",
|
||||
"to": "Til",
|
||||
@@ -1282,8 +1242,6 @@
|
||||
"copy_link_to_form": "Kopiér link til formular",
|
||||
"theme": "Tema",
|
||||
"theme_applies_note": "Dette gælder kun for dine offentlige bookingsider",
|
||||
"theme_light": "Lys",
|
||||
"theme_dark": "Mørk",
|
||||
"theme_system": "System standard",
|
||||
"add_a_team": "Tilføj et team",
|
||||
"add_webhook_description": "Modtag mødedata i realtid, når der sker noget i {{appName}}",
|
||||
@@ -1292,7 +1250,6 @@
|
||||
"enable_webhook": "Aktivér Webhook",
|
||||
"add_webhook": "Tilføj Webhook",
|
||||
"webhook_edited_successfully": "Webhook gemt",
|
||||
"webhooks_description": "Modtag mødedata i realtid, når der sker noget i {{appName}}",
|
||||
"api_keys_description": "Generér API-nøgler for adgang til din egen konto",
|
||||
"new_api_key": "Ny API-nøgle",
|
||||
"active": "aktiv",
|
||||
@@ -1331,18 +1288,13 @@
|
||||
"billing_freeplan_title": "Du er i øjeblikket på den GRATIS plan",
|
||||
"billing_freeplan_description": "Vi arbejder bedre i teams. Udvid dine arbejdsgange med round-robin og kollektive arrangementer og lav avancerede ruteformer",
|
||||
"billing_freeplan_cta": "Prøv nu",
|
||||
"billing_manage_details_title": "Se og administrer dine faktureringsoplysninger",
|
||||
"billing_manage_details_description": "Se og redigér dine faktureringsoplysninger, samt annullér dit abonnement.",
|
||||
"billing_portal": "Faktureringsportal",
|
||||
"billing_help_title": "Brug for noget andet?",
|
||||
"billing_help_description": "Hvis du har brug for yderligere hjælp til fakturering, er vores supportteam her for at hjælpe.",
|
||||
"billing_help_cta": "Kontakt support",
|
||||
"retry": "Prøv igen",
|
||||
"fetching_calendars_error": "Der opstod et problem med at hente dine kalendere. Venligst <1>prøv igen</1> eller kontakt kundeservice.",
|
||||
"calendar_connection_fail": "Forbindelse til kalender mislykkedes",
|
||||
"booking_confirmation_success": "Reservationsbekræftelse lykkedes",
|
||||
"booking_rejection_success": "Bookingafvisning lykkedes",
|
||||
"booking_confirmation_fail": "Reservationsbekræftelse mislykkedes",
|
||||
"booking_tentative": "Denne booking er foreløbig",
|
||||
"booking_accept_intent": "Hovsa, jeg ønsker at acceptere",
|
||||
"we_wont_show_again": "Vi vil ikke vise dette igen",
|
||||
@@ -1365,7 +1317,6 @@
|
||||
"new_event_type_availability": "{{eventTypeTitle}} Tilgængelighed",
|
||||
"error_editing_availability": "Fejl under redigering af tilgængelighed",
|
||||
"dont_have_permission": "Du har ikke tilladelse til at tilgå denne ressource.",
|
||||
"saml_config": "Enkelt Log På",
|
||||
"saml_configuration_placeholder": "Indsæt venligst SAML-metadata fra din Identity Provider her",
|
||||
"saml_email_required": "Indtast venligst en e-mail, så vi kan finde din SAML Identity Provider",
|
||||
"saml_sp_title": "Service Provider Detaljer",
|
||||
@@ -1374,7 +1325,6 @@
|
||||
"saml_sp_entity_id": "SP Entity ID",
|
||||
"saml_sp_acs_url_copied": "ACS URL kopieret!",
|
||||
"saml_sp_entity_id_copied": "SP Entity ID kopieret!",
|
||||
"saml_btn_configure": "Indstil",
|
||||
"add_calendar": "Tilføj Kalender",
|
||||
"limit_future_bookings": "Begræns fremtidige bookinger",
|
||||
"limit_future_bookings_description": "Begræns hvor langt i fremtiden denne begivenhed kan bookes",
|
||||
@@ -1387,7 +1337,6 @@
|
||||
"your_team_disbanded_successfully": "Dit team er blevet opløst",
|
||||
"error_creating_team": "Fejl ved oprettelse af team",
|
||||
"you": "Dig",
|
||||
"send_email": "Send e-mail",
|
||||
"member_already_invited": "Medlemmet er allerede blevet inviteret",
|
||||
"enter_email_or_username": "Indtast e-mail eller brugernavn",
|
||||
"team_name_taken": "Dette navn er allerede i brug",
|
||||
@@ -1545,11 +1494,8 @@
|
||||
"delete_sso_configuration_confirmation": "Ja, slet {{connectionType}} konfiguration",
|
||||
"delete_sso_configuration_confirmation_description": "Er du sikker på, at du vil slette {{connectionType}} konfigurationen? Dine teammedlemmer, der bruger {{connectionType}} login, vil ikke længere kunne få adgang til Cal.com.",
|
||||
"organizer_timezone": "Arrangørens tidszone",
|
||||
"email_no_user_cta": "Opret din konto",
|
||||
"email_user_cta": "Vis Invitation",
|
||||
"email_no_user_invite_heading": "Du er blevet inviteret til at deltage i et team den {{appName}}",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} har inviteret dig til at deltage i deres team på {{appName}}. {{appName}} er den begivenheds-jonglerende planlægger, der gør det muligt for dig og dit team at planlægge møder uden e-mail tennis.",
|
||||
"email_no_user_invite_steps_intro": "Vi fører dig gennem et par korte trin, og du vil kunne nyde stressfri planlægning med dit team på ingen tid.",
|
||||
"email_no_user_step_one": "Vælg dit brugernavn",
|
||||
"email_no_user_step_two": "Tilslut din kalender konto",
|
||||
"email_no_user_step_three": "Angiv din tilgængelighed",
|
||||
@@ -1569,7 +1515,6 @@
|
||||
"create_event_on": "Opret begivenhed den",
|
||||
"default_app_link_title": "Angiv et standard app-link",
|
||||
"default_app_link_description": "Indstilling af et standard app-link gør det muligt for alle nyoprettede begivenhedstyper at bruge det app-link, du har angivet.",
|
||||
"change_default_conferencing_app": "Angiv som standard",
|
||||
"under_maintenance": "Nede for vedligeholdelse",
|
||||
"under_maintenance_description": "{{appName}} teamet udfører planlagt vedligeholdelse. Hvis du har spørgsmål, bedes du kontakte support.",
|
||||
"event_type_seats": "{{numberOfSeats}} pladser",
|
||||
@@ -1601,6 +1546,5 @@
|
||||
"this_will_be_the_placeholder": "Dette vil være pladsholderen",
|
||||
"verification_code": "Bekræftelseskode",
|
||||
"verify": "Bekræft",
|
||||
"timezone_variable": "Tidszone",
|
||||
"never_expire": "Udløber aldrig"
|
||||
"organization_url_taken": "Denne URL er allerede i brug"
|
||||
}
|
||||
|
||||
@@ -11,12 +11,9 @@
|
||||
"calcom_explained_new_user": "Beenden Sie die Einrichtung Ihres {{appName}} -Kontos! Sie sind nur ein paar Schritte von der Lösung aller Probleme in der Zeitplanung entfernt.",
|
||||
"have_any_questions": "Haben Sie Fragen? Wir sind hier um Ihnen zu helfen.",
|
||||
"reset_password_subject": "{{appName}}: Anleitung zum Zurücksetzen des Passworts",
|
||||
"verify_email_banner_button": "E-Mail senden",
|
||||
"event_declined_subject": "Abgelehnt: {{title}} am {{date}}",
|
||||
"event_cancelled_subject": "Storniert: {{title}} um {{date}}",
|
||||
"event_request_declined": "Ihre Event-Anfrage wurde abgelehnt",
|
||||
"event_request_declined_recurring": "Ihre wiederkehrende Terminanfrage wurde abgelehnt",
|
||||
"event_request_cancelled": "Ihr geplanter Termin wurde abgesagt",
|
||||
"organizer": "Organisator",
|
||||
"need_to_reschedule_or_cancel": "Möchten Sie einen neuen Termin finden oder absagen?",
|
||||
"cancellation_reason": "Grund für Ihre Absage (optional)",
|
||||
@@ -78,13 +75,9 @@
|
||||
"your_meeting_has_been_booked": "Dein Termin wurde gebucht",
|
||||
"event_type_has_been_rescheduled_on_time_date": "Ihr {{title}} wurde auf den {{date}} verschoben.",
|
||||
"event_has_been_rescheduled": "Ihr Termin wurde verschoben.",
|
||||
"request_reschedule_title_attendee": "Anfrage zur Neuplanung Ihrer Buchung",
|
||||
"request_reschedule_subtitle": "{{organizer}} hat die Buchung storniert und Sie gebeten, eine andere Zeit auszuwählen.",
|
||||
"request_reschedule_title_organizer": "Sie haben {{attendee}} zur Neuplanung aufgefordert",
|
||||
"request_reschedule_subtitle_organizer": "Sie haben die Buchung storniert und {{attendee}} muss eine neue Buchungszeit mit Ihnen vereinbaren.",
|
||||
"rescheduled_event_type_subject": "Anfrage für Neuplanung gesendet: {{eventType}} mit {{name}} am {{date}}",
|
||||
"requested_to_reschedule_subject_attendee": "Aktion erforderlich - Neuplanung: Bitte buchen Sie eine neue Zeit für „{{eventType}}“ mit {{name}}",
|
||||
"reschedule_reason": "Grund für die Neuplanung",
|
||||
"hi_user_name": "Hallo, {{name}}",
|
||||
"ics_event_title": "{{eventType}} mit {{name}}",
|
||||
"new_event_subject": "Neuer Termin: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
@@ -122,6 +115,7 @@
|
||||
"team_upgrade_banner_description": "Vielen Dank, dass Sie unseren neuen Teamplan getestet haben. Wir haben festgestellt, dass Ihr Team „{{teamName}}“ aktualisiert werden muss.",
|
||||
"team_upgrade_banner_action": "Hier aufrüsten",
|
||||
"team_upgraded_successfully": "Das Update für Ihr Team war erfolgreich!",
|
||||
"org_upgrade_banner_action": "Hier aufrüsten",
|
||||
"use_link_to_reset_password": "Benutzen Sie den Link, um Ihr Passwort zurückzusetzen",
|
||||
"hey_there": "Hallo,",
|
||||
"forgot_your_password_calcom": "Passwort vergessen? - {{appName}}",
|
||||
@@ -231,6 +225,7 @@
|
||||
"done": "Erledigt",
|
||||
"all_done": "Erledigt!",
|
||||
"all_apps": "Alle Apps",
|
||||
"all": "Alle Apps",
|
||||
"available_apps": "Verfügbare Apps",
|
||||
"check_email_reset_password": "Überprüfen Sie Ihre E-Mail. Wir haben Ihnen einen Link zum Zurücksetzen Ihres Passworts gesendet.",
|
||||
"finish": "Fertig",
|
||||
@@ -252,7 +247,6 @@
|
||||
"welcome_to_calcom": "Willkommen bei {{appName}}",
|
||||
"welcome_instructions": "Wie ist Ihr Name und in welcher Zeitzone sind Sie? Dies kann später bearbeitet werden.",
|
||||
"connect_caldav": "Mit CalDav-Server verbinden",
|
||||
"credentials_stored_and_encrypted": "Ihre Zugangsdaten werden verschlüsselt gespeichert.",
|
||||
"connect": "Verbinden",
|
||||
"try_for_free": "Kostenlos testen",
|
||||
"create_booking_link_with_calcom": "Erstellen Sie Ihren eigenen Buchungslink mit {{appName}}",
|
||||
@@ -273,7 +267,6 @@
|
||||
"user_needs_to_confirm_or_reject_booking_recurring": "{{user}} muss noch die Terminreihe des wiederkehrenden Termins bestätigen oder ablehnen.",
|
||||
"meeting_is_scheduled": "Dieser Termin ist geplant",
|
||||
"meeting_is_scheduled_recurring": "Ihr wiederkehrender Termin wurde geplant",
|
||||
"submitted_recurring": "Ihr wiederkehrender Termin wurde gebucht",
|
||||
"booking_submitted": "Ihre Buchung wurde versandt",
|
||||
"booking_submitted_recurring": "Ihre wiederkehrende Buchung wurde versandt",
|
||||
"booking_confirmed": "Ihr Termin wurde bestätigt",
|
||||
@@ -306,7 +299,6 @@
|
||||
"error_end_time_next_day": "Die Endzeit darf nicht größer als 24 Stunden sein",
|
||||
"back_to_bookings": "Zurück zu den Buchungen",
|
||||
"free_to_pick_another_event_type": "Sie können jederzeit einen anderen Termin wählen.",
|
||||
"cancelled": "Abgesagte",
|
||||
"cancellation_successful": "Stornierung erfolgreich",
|
||||
"really_cancel_booking": "Möchten Sie wirklich stornieren?",
|
||||
"cannot_cancel_booking": "Sie können diese Buchung nicht stornieren",
|
||||
@@ -315,11 +307,9 @@
|
||||
"cancelling_event_recurring": "Der Termin ist eine Instanz eines wiederkehrenden Termins.",
|
||||
"cancelling_all_recurring": "Dies sind alle verbleibende Instanzen im wiederkehrenden Termin.",
|
||||
"error_with_status_code_occured": "Ein Fehler mit dem Statuscode {{status}} ist aufgetreten.",
|
||||
"booking_already_cancelled": "Dieser Termin wurde bereits storniert",
|
||||
"booking_already_accepted_rejected": "Diese Buchung wurde bereits angenommen oder abgelehnt",
|
||||
"go_back_home": "Zurück zum Anfang",
|
||||
"or_go_back_home": "Oder navigieren Sie zurück",
|
||||
"no_availability": "Unverfügbar",
|
||||
"no_meeting_found": "Kein Termin gefunden",
|
||||
"no_meeting_found_description": "Dieser Termin existiert nicht. Kontaktieren Sie den Ersteller um einen aktuellen Link zu bekommen.",
|
||||
"no_status_bookings_yet": "Es gibt noch keine {{status}} Buchungen",
|
||||
@@ -330,7 +320,6 @@
|
||||
"upcoming_bookings": "Sobald jemand eine Zeit bei Ihnen bucht können Sie das hier sehen.",
|
||||
"recurring_bookings": "Sobald jemand einen wiederkehrenden Termin mit Ihnen bucht wird er hier erscheinen.",
|
||||
"past_bookings": "Ihre früheren Buchungen werden hier angezeigt.",
|
||||
"cancelled_bookings": "Ihre stornierten Buchungen werden hier angezeigt.",
|
||||
"unconfirmed_bookings": "Ihre unbestätigten Buchungen werden hier angezeigt.",
|
||||
"unconfirmed_bookings_tooltip": "Unbestätigte Buchungen",
|
||||
"on": "auf",
|
||||
@@ -370,7 +359,6 @@
|
||||
"browse_api_documentation": "Durchsuchen Sie unsere API Dokumentation",
|
||||
"leverage_our_api": "Nutzen Sie unsere API für die volle Kontrolle und Anpassbarkeit.",
|
||||
"create_webhook": "Webhook erstellen",
|
||||
"booking_cancelled": "Termin abgesagt",
|
||||
"booking_rescheduled": "Termin verlegt",
|
||||
"recording_ready": "Download-Link der Aufnahme bereit",
|
||||
"booking_created": "Termin erstellt",
|
||||
@@ -383,8 +371,6 @@
|
||||
"team_webhooks": "Team-Webhooks",
|
||||
"create_new_webhook_to_account": "Erstellen Sie einen neuen Webhook in Ihrem Account",
|
||||
"new_webhook": "Neuer Webhook",
|
||||
"receive_cal_meeting_data": "Erhalte {{appName}} Termindaten unter einer bestimmten URL in Echtzeit, wenn ein Termin geplant oder abgesagt wird.",
|
||||
"receive_cal_event_meeting_data": "Erhalte {{appName}} Termindaten unter einer bestimmten URL in Echtzeit, wenn dieser Termin geplant oder abgesagt wird.",
|
||||
"responsive_fullscreen_iframe": "Responsives Vollbild-iFrame",
|
||||
"loading": "Wird geladen...",
|
||||
"deleting": "Lösche...",
|
||||
@@ -448,7 +434,6 @@
|
||||
"invalid_password_hint": "Das Passwort muss mindestens {{passwordLength}} Zeichen lang sein und mindestens eine Nummer beinhalten, sowie eine Mischung aus Groß- und Kleinbuchstaben sein",
|
||||
"incorrect_password": "Passwort ist falsch",
|
||||
"incorrect_username_password": "Benutzername oder Passwort ist falsch.",
|
||||
"24_h": "24 Std",
|
||||
"use_setting": "Benutze Einstellung",
|
||||
"am_pm": "am/pm",
|
||||
"time_options": "Zeitoptionen",
|
||||
@@ -491,15 +476,11 @@
|
||||
"booking_confirmation": "Bestätigen Sie {{eventTypeTitle}} mit {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Planen Sie Ihr {{eventTypeTitle}} mit {{profileName}} um",
|
||||
"in_person_meeting": "Vor-Ort-Termin",
|
||||
"attendee_in_person": "Persönlich (Teilnehmeradresse)",
|
||||
"in_person": "Persönlich (Organisator-Adresse)",
|
||||
"link_meeting": "Termin verknüpfen",
|
||||
"phone_call": "Telefonat",
|
||||
"your_number": "Ihre Telefonnummer",
|
||||
"phone_number": "Telefonnummer",
|
||||
"attendee_phone_number": "Telefonnummer",
|
||||
"organizer_phone_number": "Telefonnummer des Organisators",
|
||||
"host_phone_number": "Ihre Telefonnummer",
|
||||
"enter_phone_number": "Telefonnummer eingeben",
|
||||
"reschedule": "Neuplanen",
|
||||
"reschedule_this": "Stattdessen verschieben",
|
||||
@@ -525,6 +506,8 @@
|
||||
"team_description": "Ein paar Sätze über Ihr Team auf der öffentlichen Teamseite.",
|
||||
"members": "Mitglieder",
|
||||
"member": "Mitglied",
|
||||
"number_member_one": "{{count}} Mitglied",
|
||||
"number_member_other": "{{count}} Mitglieder",
|
||||
"owner": "Inhaber",
|
||||
"admin": "Administrator",
|
||||
"administrator_user": "Administrator Benutzer",
|
||||
@@ -625,9 +608,6 @@
|
||||
"new_event_type_btn": "Neuer Ereignistyp",
|
||||
"new_event_type_heading": "Erstellen Sie Ihren ersten Ereignistyp",
|
||||
"new_event_type_description": "Mit Ereignistypen kann man verfügbare Zeiten im Kalendar freigeben, die andere Personen dann buchen können.",
|
||||
"new_event_title": "Neuen Ereignistyp hinzufügen",
|
||||
"new_team_event": "Neuen Ereignistyp hinzufügen",
|
||||
"new_event_description": "Erstellen Sie einen neuen Ereignistyp, mit dem Personen Zeiten buchen können.",
|
||||
"event_type_created_successfully": "{{eventTypeTitle}} Ereignistyp erfolgreich erstellt",
|
||||
"event_type_updated_successfully": "{{eventTypeTitle}} Ereignistyp erfolgreich aktualisiert",
|
||||
"event_type_deleted_successfully": "Termintyp erfolgreich gelöscht",
|
||||
@@ -796,7 +776,6 @@
|
||||
"automation": "Automatisierung",
|
||||
"configure_how_your_event_types_interact": "Konfigurieren Sie, wie Ihre Termin-Typen mit Ihren Kalendern interagieren sollen.",
|
||||
"toggle_calendars_conflict": "Wechseln Sie die Kalender in denen nach Konflikten gesucht werden sollen, um Doppelbuchungen zu vermeiden.",
|
||||
"select_destination_calendar": "Erstelle Termine im",
|
||||
"connect_additional_calendar": "Zusätzlichen Kalender verbinden",
|
||||
"calendar_updated_successfully": "Kalender erfolgreich aktualisiert",
|
||||
"conferencing": "Videokonferenzen",
|
||||
@@ -830,7 +809,6 @@
|
||||
"number_apps_other": "{{count}} Apps",
|
||||
"trending_apps": "Angesagte Apps",
|
||||
"most_popular": "Am beliebtesten",
|
||||
"explore_apps": "{{category}} Apps",
|
||||
"installed_apps": "Installierte Apps",
|
||||
"free_to_use_apps": "Kostenlos",
|
||||
"no_category_apps": "Keine {{category}} Apps",
|
||||
@@ -842,7 +820,6 @@
|
||||
"no_category_apps_description_other": "Füge jede beliebige andere Art von App hinzu, um alle möglichen Dinge zu tun",
|
||||
"no_category_apps_description_web3": "Fügen Sie eine web3-App für Ihre Buchungsseiten hinzu",
|
||||
"installed_app_calendar_description": "Legen Sie den/die Kalender in denen nach Konflikten gesucht werden sollen fest, um Doppelbuchungen zu vermeiden.",
|
||||
"installed_app_conferencing_description": "Fügen Sie Ihre liebsten Videokonferenz-Apps für Ihre Meetings hinzu",
|
||||
"installed_app_payment_description": "Konfigurieren Sie die Zahlungsdienstleister, welcher bei der Belastung Ihrer Kunden verwendet werden sollen.",
|
||||
"installed_app_analytics_description": "Konfigurieren Sie, welche Analyse-Apps für Ihre Buchungsseiten verwendet werden sollen",
|
||||
"installed_app_other_description": "Alle von Ihnen installierten Apps aus anderen Kategorien.",
|
||||
@@ -868,7 +845,6 @@
|
||||
"terms_of_service": "Nutzungsbedingungen",
|
||||
"remove": "Entfernen",
|
||||
"add": "Hinzufügen",
|
||||
"installed_one": "Installiert",
|
||||
"installed_other": "{{count}} installiert",
|
||||
"verify_wallet": "Wallet verifizieren",
|
||||
"create_events_on": "Erstelle Termine in:",
|
||||
@@ -896,7 +872,6 @@
|
||||
"availability_updated_successfully": "{{scheduleName}} Zeitplan erfolgreich aktualisiert",
|
||||
"schedule_deleted_successfully": "Verfügbarkeitsplan erfolgreich gelöscht",
|
||||
"default_schedule_name": "Arbeitszeiten",
|
||||
"member_default_schedule": "Standardverfügbarkeitsplan des Mitglieds",
|
||||
"new_schedule_heading": "Erstelle einen Verfügbarkeitsplan",
|
||||
"new_schedule_description": "Das Erstellen eines Verfügbarkeitsplan sorgt dafür, dass Ihre Verfügbarkeit bei mehreren Termintypen genutzt werden kann.",
|
||||
"requires_ownership_of_a_token": "Erfordert Besitz eines Tokens, das zu der folgenden Adresse gehört:",
|
||||
@@ -933,8 +908,6 @@
|
||||
"api_key_no_note": "API-Schlüssel ohne Namen",
|
||||
"api_key_never_expires": "Dieser API-Schlüssel hat kein Ablaufdatum",
|
||||
"edit_api_key": "API-Schlüssel bearbeiten",
|
||||
"never_expire_key": "Läuft niemals ab",
|
||||
"delete_api_key": "API-Schlüssel widerrufen",
|
||||
"success_api_key_created": "API-Schlüssel erfolgreich erstellt",
|
||||
"success_api_key_edited": "API-Schlüssel erfolgreich aktualisiert",
|
||||
"create": "Erstellen",
|
||||
@@ -975,7 +948,6 @@
|
||||
"event_location_changed": "Aktualisiert - Ihr Termin hat den Standort geändert",
|
||||
"location_changed_event_type_subject": "Ort geändert: {{eventType}} mit {{name}} am {{date}}",
|
||||
"current_location": "Aktueller Ort",
|
||||
"user_phone": "Ihre Telefonnummer",
|
||||
"new_location": "Neuer Ort",
|
||||
"session": "Sitzung",
|
||||
"session_description": "Verwalten Sie Ihre Kontositzung",
|
||||
@@ -1001,7 +973,6 @@
|
||||
"zapier_setup_instructions": "<0>Loggen Sie sich in Ihr Zapier-Konto ein und erstelle einen neuen Zap.</0><1>Wählen Sie Cal.com als ihre Trigger-App aus. Wählen Sie auch ein Auslöserereignis.</0><1>Wählen Sie ihr Konto aus und geben dann ihren eindeutigen API-Key ein.</2><3>Testen Sie den Trigger.</3><4>Alles fertig!</4>",
|
||||
"install_zapier_app": "Bitte installieren Sie zuerst die Zapier-App im App Store.",
|
||||
"connect_apple_server": "Mit Apple-Server verbinden",
|
||||
"connect_caldav_server": "Mit CalDav-Server verbinden",
|
||||
"calendar_url": "Kalender-URL",
|
||||
"apple_server_generate_password": "Generieren Sie ein App-spezifisches Passwort für {{appName}} unter",
|
||||
"credentials_stored_encrypted": "Ihre Zugangsdaten werden verschlüsselt gespeichert.",
|
||||
@@ -1033,19 +1004,16 @@
|
||||
"go_to": "Gehe zu: ",
|
||||
"zapier_invite_link": "Zapier Einladungs-Link",
|
||||
"meeting_url_provided_after_confirmed": "Eine Termin-URL wird angelegt, sobald der Termin bestätigt wurde.",
|
||||
"attendees_name": "Teilnehmername",
|
||||
"dynamically_display_attendee_or_organizer": "Zeigt dynamisch entweder Ihnen den Namen Ihres Teilnehmers bzw. Ihrer Teilnehmerin an oder zeigt Ihrem/Ihrer Teilnehmerin Ihren Namen an",
|
||||
"event_location": "Ort des Ereignisses",
|
||||
"reschedule_optional": "Grund für die Verschiebung (optional)",
|
||||
"reschedule_placeholder": "Lassen Sie andere wissen, warum Sie den Termin verschieben müssen",
|
||||
"event_cancelled": "Dieser Termin ist abgesagt",
|
||||
"emailed_information_about_cancelled_event": "Wir haben Ihnen und den anderen Teilnehmern eine E-Mail gesendet, damit alle Bescheid wissen.",
|
||||
"this_input_will_shown_booking_this_event": "Diese Eingabe wird bei der Buchung dieses Termins angezeigt",
|
||||
"meeting_url_in_conformation_email": "Termin-URL ist in der Bestätigungsmail",
|
||||
"url_start_with_https": "URL muss mit http:// oder https:// beginnen",
|
||||
"number_provided": "Telefonnummer wird angegeben",
|
||||
"before_event_trigger": "vor Beginn des Termins",
|
||||
"event_cancelled_trigger": "wenn das Ereignis abgesagt wird",
|
||||
"new_event_trigger": "wenn ein neer Termin gebucht wird",
|
||||
"email_host_action": "E-Mail an den Veranstalter senden",
|
||||
"email_attendee_action": "E-Mail an Teilnehmende senden",
|
||||
@@ -1107,7 +1075,6 @@
|
||||
"add_exchange2016": "Exchange 2016-Server verbinden",
|
||||
"custom_template": "Benutzerdefinierte Vorlage",
|
||||
"email_body": "Inhalt",
|
||||
"subject": "Betreff",
|
||||
"text_message": "Textnachricht",
|
||||
"specific_issue": "Haben Sie ein spezielles Problem",
|
||||
"browse_our_docs": "Durchsuchen Sie unsere Dokumentation",
|
||||
@@ -1135,12 +1102,9 @@
|
||||
"new_seat_title": "Jemand hat sich zu einem Ereignis hinzugefügt",
|
||||
"variable": "Variable",
|
||||
"event_name_variable": "Event Name",
|
||||
"organizer_name_variable": "Organisator",
|
||||
"attendee_name_variable": "Teilnehmer",
|
||||
"event_date_variable": "Event Datum",
|
||||
"event_time_variable": "Event Zeit",
|
||||
"location_variable": "Ort",
|
||||
"additional_notes_variable": "Zusätzliche Notizen",
|
||||
"app_upgrade_description": "Um diese Funktion nutzen zu können, müssen Sie ein Upgrade auf einen Pro-Account durchführen.",
|
||||
"invalid_number": "Ungültige Telefonnummer",
|
||||
"navigate": "Navigieren",
|
||||
@@ -1211,7 +1175,6 @@
|
||||
"start_of_week": "Wochenstart",
|
||||
"recordings_title": "Aufnahmen",
|
||||
"recording": "Aufnahme",
|
||||
"happy_scheduling": "Fröhliche Terminplanung",
|
||||
"select_calendars": "Wählen Sie aus, in welchen Kalendern Sie nach Konflikten suchen wollen, um Doppelbuchungen zu vermeiden.",
|
||||
"check_for_conflicts": "Auf Konflikte prüfen",
|
||||
"view_recordings": "Aufnahmen anzeigen",
|
||||
@@ -1234,7 +1197,6 @@
|
||||
"recurring_event_tab_description": "Einen wiederholenden Zeitplan einrichten",
|
||||
"today": "heute",
|
||||
"appearance": "Darstellung",
|
||||
"appearance_subtitle": "Einstellungen für Ihre Buchungsdarstellung verwalten",
|
||||
"my_account": "Mein Account",
|
||||
"general": "Allgemein",
|
||||
"calendars": "Kalender",
|
||||
@@ -1254,7 +1216,6 @@
|
||||
"conferencing_description": "Fügen Sie Ihre favorisierten Videokonferenz-Apps für Ihre Meetings hinzu",
|
||||
"add_conferencing_app": "Konferenz-App hinzufügen",
|
||||
"password_description": "Einstellungen für Ihre Konto-Passwörter verwalten",
|
||||
"2fa_description": "Einstellungen für Ihre Konto-Passwörter verwalten",
|
||||
"we_just_need_basic_info": "Wir benötigen nur ein paar grundlegende Informationen, um Ihr Profil einzurichten.",
|
||||
"skip": "Überspringen",
|
||||
"do_this_later": "Später machen",
|
||||
@@ -1278,7 +1239,6 @@
|
||||
"event_date_info": "Das Datum der Veranstaltung",
|
||||
"event_time_info": "Die Startzeit des Ereignisses",
|
||||
"location_info": "Der Ort des Events",
|
||||
"organizer_name_info": "Ihr Name",
|
||||
"additional_notes_info": "Die zusätzlichen Anmerkungen der Buchung",
|
||||
"attendee_name_info": "Name der buchenden Person",
|
||||
"to": "An",
|
||||
@@ -1342,8 +1302,6 @@
|
||||
"copy_link_to_form": "Link in Formular kopieren",
|
||||
"theme": "Theme",
|
||||
"theme_applies_note": "Dies gilt nur für Ihre öffentlichen Buchungsseiten",
|
||||
"theme_light": "Hell",
|
||||
"theme_dark": "Dunkel",
|
||||
"theme_system": "Systemstandard",
|
||||
"add_a_team": "Team hinzufügen",
|
||||
"add_webhook_description": "Erhalten Sie Meetingdaten in Echtzeit, wenn etwas in {{appName}} passiert",
|
||||
@@ -1352,7 +1310,6 @@
|
||||
"enable_webhook": "Webhook aktivieren",
|
||||
"add_webhook": "Webhook hinzufügen",
|
||||
"webhook_edited_successfully": "Webhook gespeichert",
|
||||
"webhooks_description": "Erhalten Sie Meetingdaten in Echtzeit, wenn etwas in {{appName}} passiert",
|
||||
"api_keys_description": "Generieren Sie API-Schlüssel für den Zugriff auf Ihren eigenen Account",
|
||||
"new_api_key": "Neuer API-Schlüssel",
|
||||
"active": "Aktiv",
|
||||
@@ -1394,11 +1351,7 @@
|
||||
"billing_freeplan_title": "Sie verwenden derzeit den KOSTENLOSEN Plan",
|
||||
"billing_freeplan_description": "In Teams arbeitet man am Besten. Erweitern Sie Ihre Arbeitsabläufe mit Rundlauf und kollektiven Veranstaltungen und erstellen Sie erweiterte Leitungsformulare",
|
||||
"billing_freeplan_cta": "Jetzt ausprobieren",
|
||||
"billing_manage_details_title": "Ihre Rechnungsdetails ansehen und verwalten",
|
||||
"billing_manage_details_description": "Rechnungsdaten ansehen, bearbeiten oder Abonnement kündigen.",
|
||||
"billing_portal": "Abrechnungsportal",
|
||||
"billing_help_title": "Brauchen Sie etwas anderes?",
|
||||
"billing_help_description": "Wenn Sie weitere Hilfe bei der Rechnungsstellung benötigen, hilft Ihnen unser Support-Team gerne weiter.",
|
||||
"billing_help_cta": "Support kontaktieren",
|
||||
"ignore_special_characters_booking_questions": "Ignorieren Sie Sonderzeichen in Ihrem Buchungsfragenbezeichner. Verwenden Sie nur Buchstaben und Zahlen",
|
||||
"retry": "Erneut versuchen",
|
||||
@@ -1406,7 +1359,6 @@
|
||||
"calendar_connection_fail": "Kalenderverbindung fehlgeschlagen",
|
||||
"booking_confirmation_success": "Buchungsbestätigung erfolgreich",
|
||||
"booking_rejection_success": "Buchungsablehnung erfolgreich",
|
||||
"booking_confirmation_fail": "Buchungsbestätigung fehlgeschlagen",
|
||||
"booking_tentative": "Diese Buchung ist vorläufig",
|
||||
"booking_accept_intent": "Hoppla, ich möchte akzeptieren",
|
||||
"we_wont_show_again": "Wir werden dies nicht erneut anzeigen",
|
||||
@@ -1429,7 +1381,6 @@
|
||||
"new_event_type_availability": "{{eventTypeTitle}} | Verfügbarkeit",
|
||||
"error_editing_availability": "Fehler beim Bearbeiten der Verfügbarkeit",
|
||||
"dont_have_permission": "Ihnen fehlt die Berechtigung, auf diese Ressource zuzugreifen.",
|
||||
"saml_config": "SAML-Konfiguration",
|
||||
"saml_configuration_placeholder": "Bitte fügen Sie die SAML-Metadaten von Ihrem SAML-Anbieter hier ein",
|
||||
"saml_email_required": "Bitte geben Sie eine E-Mail ein, damit wir Ihren SAML Anbieter finden können",
|
||||
"saml_sp_title": "Einzelheiten zum Dienstanbieter",
|
||||
@@ -1438,7 +1389,6 @@
|
||||
"saml_sp_entity_id": "SP-Entitäts-ID",
|
||||
"saml_sp_acs_url_copied": "ACS-URL kopiert!",
|
||||
"saml_sp_entity_id_copied": "SP-Entitäts-ID kopiert!",
|
||||
"saml_btn_configure": "Konfigurieren",
|
||||
"add_calendar": "Kalender hinzufügen",
|
||||
"limit_future_bookings": "Zukünftige Termine begrenzen",
|
||||
"limit_future_bookings_description": "Begrenzt, wie weit in die Zukunft dieser Termin gebucht werden kann",
|
||||
@@ -1451,7 +1401,6 @@
|
||||
"your_team_disbanded_successfully": "Ihr Team wurde erfolgreich aufgelöst",
|
||||
"error_creating_team": "Fehler beim Erstellen des Teams",
|
||||
"you": "Sie",
|
||||
"send_email": "E-Mail senden",
|
||||
"member_already_invited": "Mitglied wurde bereits eingeladen",
|
||||
"enter_email_or_username": "E-Mail oder Benutzername eingeben",
|
||||
"team_name_taken": "Dieser Name ist bereits vergeben",
|
||||
@@ -1618,12 +1567,8 @@
|
||||
"delete_sso_configuration_confirmation": "Ja, {{connectionType}}-Konfiguration löschen",
|
||||
"delete_sso_configuration_confirmation_description": "Sind Sie sicher, dass Sie die {{connectionType}}-Konfiguration löschen möchten? Ihre Teammitglieder, die sich über {{connectionType}} anmelden, werden keinen Zugriff mehr auf Cal.com haben.",
|
||||
"organizer_timezone": "Zeitzone des Veranstalters",
|
||||
"email_no_user_cta": "Erstellen Sie Ihr Konto",
|
||||
"email_user_cta": "Einladung anzeigen",
|
||||
"email_no_user_invite_heading": "Sie wurden eingeladen, dem Team in {{appName}} beizutreten",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} hat Sie eingeladen, dem Team in {{appName}} beizutreten. {{appName}} ist der Event-Planer, der es Ihnen und Ihrem Team ermöglicht, Meetings ohne ständiges hin und her zu planen.",
|
||||
"email_user_invite_subheading": "{{invitedBy}} hat Sie eingeladen, dem Team „{{teamName}}“ beizutreten. {{appName}} ist der Event-Planer, der es Ihnen und Ihrem Team ermöglicht, Meetings ohne Hin und Her zu planen.",
|
||||
"email_no_user_invite_steps_intro": "Wir begleiten Sie durch ein paar Schritte, danach können Sie stressfreie Planung mit Ihrem Team in kürzester Zeit genießen.",
|
||||
"email_no_user_step_one": "Wählen Sie Ihren Benutzernamen",
|
||||
"email_no_user_step_two": "Verbinden Sie Ihr Kalenderkonto",
|
||||
"email_no_user_step_three": "Legen Sie Ihre Verfügbarkeit fest",
|
||||
@@ -1644,11 +1589,9 @@
|
||||
"no_longer_attending": "Sie nehmen an diesem Termin nicht mehr teil",
|
||||
"attendee_no_longer_attending_subject": "Ein Teilnehmer nimmt nicht mehr an {{title}} am {{date}} teil",
|
||||
"attendee_no_longer_attending": "Ein Teilnehmer nimmt nicht mehr an Ihrem Termin teil",
|
||||
"attendee_no_longer_attending_subtitle": "{{name}} hat abgesagt. Das bedeutet, dass ein Platz für dieses Zeitfenster geöffnet wurde",
|
||||
"create_event_on": "Erstelle Termin am",
|
||||
"default_app_link_title": "Standard-App-Link festlegen",
|
||||
"default_app_link_description": "Mit dem Festlegen eines Standard-App-Links können alle neu erstellten Ereignistypen den App-Link verwenden, den Sie gesetzt haben.",
|
||||
"change_default_conferencing_app": "Als Standard festlegen",
|
||||
"organizer_default_conferencing_app": "Standard-App des Organisators",
|
||||
"under_maintenance": "Wartungsarbeiten",
|
||||
"under_maintenance_description": "Das {{appName}} Team führt geplante Wartungsarbeiten durch. Wenn Sie Fragen haben, wenden Sie sich bitte an den Support.",
|
||||
@@ -1663,11 +1606,9 @@
|
||||
"booking_confirmation_failed": "Buchungsbestätigung fehlgeschlagen",
|
||||
"not_enough_seats": "Nicht genügend Plätze",
|
||||
"form_builder_field_already_exists": "Ein Feld mit diesem Namen ist bereits vorhanden",
|
||||
"form_builder_field_add_subtitle": "Passen Sie die Fragen an, die auf der Buchungsseite gefragt werden",
|
||||
"show_on_booking_page": "Auf der Buchungsseite anzeigen",
|
||||
"get_started_zapier_templates": "Legen Sie mit Zapier-Vorlagen los",
|
||||
"team_is_unpublished": "{{team}} ist unveröffentlicht",
|
||||
"team_is_unpublished_description": "Dieser Team-Link ist derzeit nicht verfügbar. Bitte kontaktieren Sie den Team-Besitzer oder fragen Sie ihn, ob er ihn veröffentlicht.",
|
||||
"team_member": "Teammitglied",
|
||||
"a_routing_form": "Ein Weiterleitungsformular",
|
||||
"form_description_placeholder": "Formularbeschreibung",
|
||||
@@ -1698,7 +1639,6 @@
|
||||
"spot_popular_event_types_description": "Sehen Sie, welche Ihrer Ereignistypen die meisten Klicks und Buchungen erhalten",
|
||||
"no_responses_yet": "Noch keine Antworten",
|
||||
"this_will_be_the_placeholder": "Dies wird der Platzhalter sein",
|
||||
"error_booking_event": "Bei der Buchung dieses Termins ist ein Fehler aufgetreten, bitte aktualisieren Sie die Seite und versuchen Sie es erneut",
|
||||
"timeslot_missing_title": "Kein Zeitfenster ausgewählt",
|
||||
"timeslot_missing_description": "Bitte wählen Sie einen Zeitraum aus, um den Termin zu buchen.",
|
||||
"timeslot_missing_cta": "Zeitfenster auswählen",
|
||||
@@ -1715,7 +1655,6 @@
|
||||
"verification_code": "Bestätigungscode",
|
||||
"can_you_try_again": "Können Sie es zu einem anderen Zeitpunkt erneut versuchen?",
|
||||
"verify": "Bestätigen",
|
||||
"timezone_variable": "Zeitzone",
|
||||
"timezone_info": "Die Zeitzone der empfangenden Person",
|
||||
"event_end_time_variable": "Endzeitpunkt des Ereignisses",
|
||||
"event_end_time_info": "Der Endzeitpunkt des Termins",
|
||||
@@ -1760,11 +1699,9 @@
|
||||
"least_booked_members": "Am wenigsten gebuchte Mitglieder",
|
||||
"events_created": "Ereignisse erstellt",
|
||||
"events_completed": "Ereignisse abgeschlossen",
|
||||
"events_cancelled": "Ereignisse abgesagt",
|
||||
"events_rescheduled": "Ereignisse neu geplant",
|
||||
"from_last_period": "seit dem letzten Zeitraum",
|
||||
"from_to_date_period": "Von: {{startDate}} Bis: {{endDate}}",
|
||||
"analytics_for_organisation": "Insights",
|
||||
"subtitle_analytics": "Erfahren Sie mehr über die Aktivität Ihres Teams",
|
||||
"redirect_url_warning": "Das Hinzufügen einer Umleitung wird die Erfolgsseite deaktivieren. Erwähnen Sie \"Buchung bestätigt\" auf Ihrer benutzerdefinierten Erfolgsseite.",
|
||||
"event_trends": "Ereignistrends",
|
||||
@@ -1795,7 +1732,6 @@
|
||||
"complete_your_booking": "Schließen Sie Ihre Buchung ab",
|
||||
"complete_your_booking_subject": "Schließen Sie Ihre Buchung ab: {{title}} am {{date}}",
|
||||
"confirm_your_details": "Bestätigen Sie Ihre Daten",
|
||||
"never_expire": "Läuft niemals ab",
|
||||
"currency_string": "{{amount, currency}}",
|
||||
"charge_card_dialog_body": "Sie sind im Begriff, den Teilnehmer {{amount, currency}} in Rechnung zu stellen. Sind Sie sicher, dass Sie fortfahren möchten?",
|
||||
"charge_attendee": "Teilnehmer {{amount, currency}} berechnen",
|
||||
@@ -1814,7 +1750,6 @@
|
||||
"book_my_cal": "Mein Cal buchen",
|
||||
"invite_as": "Einladen als",
|
||||
"form_updated_successfully": "Formular erfolgreich aktualisiert.",
|
||||
"email_not_cal_member_cta": "Treten Sie Ihrem Team bei",
|
||||
"disable_attendees_confirmation_emails": "Standardmäßige Bestätigungs-E-Mails für Teilnehmer deaktivieren",
|
||||
"disable_attendees_confirmation_emails_description": "Mindestens ein Workflow ist für diesen Termintyp aktiv, welcher bei Buchung eine E-Mail an die Teilnehmer sendet.",
|
||||
"disable_host_confirmation_emails": "Standardmäßige Bestätigungs-E-Mails für Veranstalter deaktivieren",
|
||||
@@ -1824,5 +1759,6 @@
|
||||
"connect_google_workspace": "Google Workspace verbinden",
|
||||
"google_workspace_admin_tooltip": "Sie müssen ein Workspace-Admin sein, um diese Funktion nutzen zu können",
|
||||
"first_event_type_webhook_description": "Erstellen Sie Ihren ersten Webhook für diesen Termintypen",
|
||||
"create_for": "Erstellen für"
|
||||
"create_for": "Erstellen für",
|
||||
"organization_url_taken": "Diese URL ist bereits vergeben"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
"have_any_questions": "Έχετε ερωτήσεις? Είμαστε εδώ για να βοηθήσουμε.",
|
||||
"reset_password_subject": "{{appName}}: Οδηγίες επαναφοράς κωδικού πρόσβασης",
|
||||
"event_declined_subject": "Απορρίφθηκε: {{title}} στις {{date}}",
|
||||
"event_cancelled_subject": "Ακύρωση: {{title}} στις {{date}}",
|
||||
"need_to_reschedule_or_cancel": "Χρειάζεται να επαναπρογραμματίσετε ή να ακυρώσετε;",
|
||||
"cancellation_reason": "Λόγος ακύρωσης (προαιρετικό)",
|
||||
"rejection_reason": "Λόγος απόρριψης",
|
||||
@@ -57,6 +56,7 @@
|
||||
"link_expires": "Υ.Γ. Λήγει σε {{expiresIn}} ώρες.",
|
||||
"team_upgrade_banner_action": "Αναβάθμισε εδώ",
|
||||
"team_upgraded_successfully": "Η ομάδα σας αναβαθμίστηκε επιτυχώς!",
|
||||
"org_upgrade_banner_action": "Αναβάθμισε εδώ",
|
||||
"use_link_to_reset_password": "Χρησιμοποιήστε τον παρακάτω σύνδεσμο για να επαναφέρετε τον κωδικό πρόσβασης",
|
||||
"hey_there": "Γεια σας,",
|
||||
"forgot_your_password_calcom": "Ξεχάσατε τον κωδικό πρόσβασης? - {{appName}}",
|
||||
@@ -117,6 +117,7 @@
|
||||
"request_password_reset": "Αποστολή email επαναφοράς",
|
||||
"forgot_password": "Ξεχάσατε τον κωδικό πρόσβασης?",
|
||||
"all_apps": "Όλα",
|
||||
"all": "Όλα",
|
||||
"check_email_reset_password": "Ελέγξτε το email σας. Σας στείλαμε ένα σύνδεσμο για να επαναφέρετε τον κωδικό πρόσβασής σας.",
|
||||
"few_sentences_about_yourself": "Μερικά λόγια για τον εσάς. Αυτό θα εμφανιστεί στην προσωπική σελίδα σας.",
|
||||
"set_availability": "Όρισε τη διαθεσιμότητά σου",
|
||||
@@ -125,7 +126,6 @@
|
||||
"welcome_back": "Καλωσορίσατε πίσω",
|
||||
"welcome_to_calcom": "Καλωσορίσατε στο {{appName}}",
|
||||
"connect_caldav": "Σύνδεση στο CalDav (Beta)",
|
||||
"credentials_stored_and_encrypted": "Τα διαπιστευτήριά σας θα αποθηκευτούν και θα κρυπτογραφηθούν.",
|
||||
"connect": "Σύνδεση",
|
||||
"try_for_free": "Δοκιμάστε δωρεάν",
|
||||
"add_to_calendar": "Προσθήκη στο ημερολόγιο",
|
||||
@@ -151,7 +151,6 @@
|
||||
"friday_time_error": "Μη έγκυρη ώρα την Παρασκευή",
|
||||
"saturday_time_error": "Μη έγκυρη ώρα το Σάββατο",
|
||||
"error_with_status_code_occured": "Παρουσιάστηκε ένα σφάλμα με κωδικό κατάστασης {{status}}.",
|
||||
"booking_already_cancelled": "Αυτή η κράτηση είχε ήδη ακυρωθεί",
|
||||
"booking_already_accepted_rejected": "Αυτή η κράτηση έγινε ήδη αποδεκτή ή απορρίφθηκε",
|
||||
"go_back_home": "Επιστροφή στην αρχική σελίδα",
|
||||
"or_go_back_home": "Ή επιστροφή στην αρχική σελίδα",
|
||||
@@ -211,10 +210,8 @@
|
||||
"yes": "ναι",
|
||||
"no": "όχι",
|
||||
"additional_notes": "Πρόσθετες σημειώσεις",
|
||||
"your_number": "Ο αριθμός τηλεφώνου σας",
|
||||
"phone_number": "Αριθμός Τηλεφώνου",
|
||||
"attendee_phone_number": "Αριθμός Τηλεφώνου Συμμετέχοντα",
|
||||
"host_phone_number": "Ο αριθμός τηλεφώνου σας",
|
||||
"enter_phone_number": "Εισάγετε αριθμό τηλεφώνου",
|
||||
"or": "Ή",
|
||||
"go_back": "Επιστροφή",
|
||||
@@ -272,6 +269,5 @@
|
||||
"event_name_tooltip": "Το όνομα που θα εμφανίζεται στα ημερολόγια",
|
||||
"label": "Ετικέτα",
|
||||
"edit": "Επεξεργασία",
|
||||
"disable_guests": "Απενεργοποίηση επισκεπτών",
|
||||
"email_no_user_cta": "Δημιουργία λογαριασμού"
|
||||
"disable_guests": "Απενεργοποίηση επισκεπτών"
|
||||
}
|
||||
|
||||
@@ -14,18 +14,17 @@
|
||||
"verify_email_subject": "{{appName}}: Verify your account",
|
||||
"check_your_email": "Check your email",
|
||||
"verify_email_page_body": "We've sent an email to {{email}}. It is important to verify your email address to guarantee the best email and calendar deliverability from {{appName}}.",
|
||||
"verify_email_banner_body": "Please verify your email adress to guarantee the best email and calendar deliverability from {{appName}}.",
|
||||
"verify_email_banner_button": "Send email",
|
||||
"verify_email_banner_body": "Verify your email address to guarantee the best email and calendar deliverability",
|
||||
"verify_email_email_header": "Verify your email address",
|
||||
"verify_email_email_button": "Verify email",
|
||||
"verify_email_email_body": "Please verify your email address by clicking the button below.",
|
||||
"verify_email_email_link_text": "Here's the link incase you don't like clicking buttons:",
|
||||
"verify_email_email_link_text": "Here's the link in case you don't like clicking buttons:",
|
||||
"email_sent": "Email sent successfully",
|
||||
"event_declined_subject": "Declined: {{title}} at {{date}}",
|
||||
"event_cancelled_subject": "Cancelled: {{title}} at {{date}}",
|
||||
"event_cancelled_subject": "Canceled: {{title}} at {{date}}",
|
||||
"event_request_declined": "Your event request has been declined",
|
||||
"event_request_declined_recurring": "Your recurring event request has been declined",
|
||||
"event_request_cancelled": "Your scheduled event was cancelled",
|
||||
"event_request_cancelled": "Your scheduled event was canceled",
|
||||
"organizer": "Organizer",
|
||||
"need_to_reschedule_or_cancel": "Need to reschedule or cancel?",
|
||||
"cancellation_reason": "Reason for cancellation (optional)",
|
||||
@@ -87,13 +86,11 @@
|
||||
"your_meeting_has_been_booked": "Your meeting has been booked",
|
||||
"event_type_has_been_rescheduled_on_time_date": "Your {{title}} has been rescheduled to {{date}}.",
|
||||
"event_has_been_rescheduled": "Updated - Your event has been rescheduled",
|
||||
"request_reschedule_title_attendee": "Request to reschedule your booking",
|
||||
"request_reschedule_subtitle": "{{organizer}} has cancelled the booking and requested you to pick another time.",
|
||||
"request_reschedule_subtitle": "{{organizer}} has canceled the booking and requested you to pick another time.",
|
||||
"request_reschedule_title_organizer": "You have requested {{attendee}} to reschedule",
|
||||
"request_reschedule_subtitle_organizer": "You have cancelled the booking and {{attendee}} should pick a new booking time with you.",
|
||||
"request_reschedule_subtitle_organizer": "You have canceled the booking and {{attendee}} should pick a new booking time with you.",
|
||||
"rescheduled_event_type_subject": "Request for reschedule sent: {{eventType}} with {{name}} at {{date}}",
|
||||
"requested_to_reschedule_subject_attendee": "Action Required Reschedule: Please book a new time for {{eventType}} with {{name}}",
|
||||
"reschedule_reason": "Reason for reschedule",
|
||||
"hi_user_name": "Hi {{name}}",
|
||||
"ics_event_title": "{{eventType}} with {{name}}",
|
||||
"new_event_subject": "New event: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
@@ -131,6 +128,9 @@
|
||||
"team_upgrade_banner_description": "Thank you for trialing our new team plan. We noticed your team \"{{teamName}}\" needs to be upgraded.",
|
||||
"team_upgrade_banner_action": "Upgrade here",
|
||||
"team_upgraded_successfully": "Your team was upgraded successfully!",
|
||||
"org_upgrade_banner_description": "Thank you for trialing our Organization plan. We noticed your Organization \"{{teamName}}\" needs to be upgraded.",
|
||||
"org_upgrade_banner_action": "Upgrade here",
|
||||
"org_upgraded_successfully": "Your Organization was upgraded successfully!",
|
||||
"use_link_to_reset_password": "Use the link below to reset your password",
|
||||
"hey_there": "Hey there,",
|
||||
"forgot_your_password_calcom": "Forgot your password? - {{appName}}",
|
||||
@@ -241,9 +241,12 @@
|
||||
"done": "Done",
|
||||
"all_done": "All done!",
|
||||
"all_apps": "All",
|
||||
"all": "All",
|
||||
"yours": "Yours",
|
||||
"available_apps": "Available Apps",
|
||||
"check_email_reset_password": "Check your email. We sent you a link to reset your password.",
|
||||
"finish": "Finish",
|
||||
"organization_general_description":"Manage settings for your team language and timezone",
|
||||
"few_sentences_about_yourself": "A few sentences about yourself. This will appear on your personal url page.",
|
||||
"nearly_there": "Nearly there!",
|
||||
"nearly_there_instructions": "Last thing, a brief description about you and a photo really help you get bookings and let people know who they’re booking with.",
|
||||
@@ -251,8 +254,8 @@
|
||||
"set_availability": "Set your availability",
|
||||
"continue_without_calendar": "Continue without calendar",
|
||||
"connect_your_calendar": "Connect your calendar",
|
||||
"connect_your_video_app":"Connect your video apps",
|
||||
"connect_your_video_app_instructions":"Connect your video apps to use them on your event types.",
|
||||
"connect_your_video_app": "Connect your video apps",
|
||||
"connect_your_video_app_instructions": "Connect your video apps to use them on your event types.",
|
||||
"connect_your_calendar_instructions": "Connect your calendar to automatically check for busy times and new events as they’re scheduled.",
|
||||
"set_up_later": "Set up later",
|
||||
"current_time": "Current time",
|
||||
@@ -262,7 +265,6 @@
|
||||
"welcome_to_calcom": "Welcome to {{appName}}",
|
||||
"welcome_instructions": "Tell us what to call you and let us know what timezone you’re in. You’ll be able to edit this later.",
|
||||
"connect_caldav": "Connect to CalDav (Beta)",
|
||||
"credentials_stored_and_encrypted": "Your credentials will be stored and encrypted.",
|
||||
"connect": "Connect",
|
||||
"try_for_free": "Try it for free",
|
||||
"create_booking_link_with_calcom": "Create your own booking link with {{appName}}",
|
||||
@@ -283,7 +285,6 @@
|
||||
"user_needs_to_confirm_or_reject_booking_recurring": "{{user}} still needs to confirm or reject each booking of the recurring meeting.",
|
||||
"meeting_is_scheduled": "This meeting is scheduled",
|
||||
"meeting_is_scheduled_recurring": "The recurring events are scheduled",
|
||||
"submitted_recurring": "Your recurring meeting has been submitted",
|
||||
"booking_submitted": "Your booking has been submitted",
|
||||
"booking_submitted_recurring": "Your recurring meeting has been submitted",
|
||||
"booking_confirmed": "Your booking has been confirmed",
|
||||
@@ -305,6 +306,7 @@
|
||||
"failed": "Failed",
|
||||
"password_has_been_reset_login": "Your password has been reset. You can now login with your newly created password.",
|
||||
"bookerlayout_title": "Layout",
|
||||
"layout": "Layout",
|
||||
"bookerlayout_default_title": "Default view",
|
||||
"bookerlayout_description": "You can select multiple and your bookers can switch views.",
|
||||
"bookerlayout_user_settings_title": "Booking layout",
|
||||
@@ -328,7 +330,7 @@
|
||||
"error_end_time_next_day": "End time cannot be greater than 24 hours",
|
||||
"back_to_bookings": "Back to bookings",
|
||||
"free_to_pick_another_event_type": "Feel free to pick another event anytime.",
|
||||
"cancelled": "Cancelled",
|
||||
"cancelled": "Canceled",
|
||||
"cancellation_successful": "Cancellation successful",
|
||||
"really_cancel_booking": "Really cancel your booking?",
|
||||
"cannot_cancel_booking": "You cannot cancel this booking",
|
||||
@@ -337,11 +339,10 @@
|
||||
"cancelling_event_recurring": "The event is one instance of a recurring event.",
|
||||
"cancelling_all_recurring": "These are all remaining instances in the recurring event.",
|
||||
"error_with_status_code_occured": "An error with status code {{status}} occurred.",
|
||||
"booking_already_cancelled": "This booking was already cancelled",
|
||||
"booking_already_cancelled": "This booking was already canceled",
|
||||
"booking_already_accepted_rejected": "This booking was already accepted or rejected",
|
||||
"go_back_home": "Go back home",
|
||||
"or_go_back_home": "Or go back home",
|
||||
"no_availability": "Unavailable",
|
||||
"no_meeting_found": "No Meeting Found",
|
||||
"no_meeting_found_description": "This meeting does not exist. Contact the meeting owner for an updated link.",
|
||||
"no_status_bookings_yet": "No {{status}} bookings",
|
||||
@@ -352,7 +353,7 @@
|
||||
"upcoming_bookings": "As soon as someone books a time with you it will show up here.",
|
||||
"recurring_bookings": "As soon as someone books a recurring meeting with you it will show up here.",
|
||||
"past_bookings": "Your past bookings will show up here.",
|
||||
"cancelled_bookings": "Your cancelled bookings will show up here.",
|
||||
"cancelled_bookings": "Your canceled bookings will show up here.",
|
||||
"unconfirmed_bookings": "Your unconfirmed bookings will show up here.",
|
||||
"unconfirmed_bookings_tooltip": "Unconfirmed bookings",
|
||||
"on": "on",
|
||||
@@ -393,12 +394,12 @@
|
||||
"browse_api_documentation": "Browse our API documentation",
|
||||
"leverage_our_api": "Leverage our API for full control and customizability.",
|
||||
"create_webhook": "Create Webhook",
|
||||
"booking_cancelled": "Booking Cancelled",
|
||||
"booking_cancelled": "Booking Canceled",
|
||||
"booking_rescheduled": "Booking Rescheduled",
|
||||
"recording_ready":"Recording Download Link Ready",
|
||||
"recording_ready": "Recording Download Link Ready",
|
||||
"booking_created": "Booking Created",
|
||||
"booking_rejected":"Booking Rejected",
|
||||
"booking_requested":"Booking Requested",
|
||||
"booking_rejected": "Booking Rejected",
|
||||
"booking_requested": "Booking Requested",
|
||||
"meeting_ended": "Meeting Ended",
|
||||
"form_submitted": "Form Submitted",
|
||||
"event_triggers": "Event Triggers",
|
||||
@@ -408,8 +409,8 @@
|
||||
"team_webhooks": "Team Webhooks",
|
||||
"create_new_webhook_to_account": "Create a new webhook to your account",
|
||||
"new_webhook": "New Webhook",
|
||||
"receive_cal_meeting_data": "Receive {{appName}} meeting data at a specified URL, in real-time, when an event is scheduled or cancelled.",
|
||||
"receive_cal_event_meeting_data": "Receive {{appName}} meeting data at a specified URL, in real-time, when this event is scheduled or cancelled.",
|
||||
"receive_cal_meeting_data": "Receive {{appName}} meeting data at a specified URL, in real-time, when an event is scheduled or canceled.",
|
||||
"receive_cal_event_meeting_data": "Receive {{appName}} meeting data at a specified URL, in real-time, when this event is scheduled or canceled.",
|
||||
"responsive_fullscreen_iframe": "Responsive full screen iframe",
|
||||
"loading": "Loading...",
|
||||
"deleting": "Deleting...",
|
||||
@@ -473,7 +474,6 @@
|
||||
"invalid_password_hint": "The password must be a minimum of {{passwordLength}} characters long containing at least one number and have a mixture of uppercase and lowercase letters",
|
||||
"incorrect_password": "Password is incorrect.",
|
||||
"incorrect_username_password": "Username or password is incorrect.",
|
||||
"24_h": "24h",
|
||||
"use_setting": "Use setting",
|
||||
"am_pm": "am/pm",
|
||||
"time_options": "Time options",
|
||||
@@ -516,15 +516,11 @@
|
||||
"booking_confirmation": "Confirm your {{eventTypeTitle}} with {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Reschedule your {{eventTypeTitle}} with {{profileName}}",
|
||||
"in_person_meeting": "In-person meeting",
|
||||
"attendee_in_person": "In Person (Attendee Address)",
|
||||
"in_person": "In Person (Organizer Address)",
|
||||
"link_meeting": "Link meeting",
|
||||
"phone_call": "Attendee Phone Number",
|
||||
"your_number": "Your phone number",
|
||||
"phone_number": "Phone Number",
|
||||
"attendee_phone_number": "Attendee Phone Number",
|
||||
"organizer_phone_number": "Organizer Phone Number",
|
||||
"host_phone_number": "Your Phone Number",
|
||||
"enter_phone_number": "Enter phone number",
|
||||
"reschedule": "Reschedule",
|
||||
"reschedule_this": "Reschedule instead",
|
||||
@@ -548,8 +544,12 @@
|
||||
"your_team_updated_successfully": "Your team has been updated successfully.",
|
||||
"about": "About",
|
||||
"team_description": "A few sentences about your team. This will appear on your team's url page.",
|
||||
"org_description": "A few sentances about your organization. This will appear on your organization's url page.",
|
||||
"members": "Members",
|
||||
"organization_members":"Organisation members",
|
||||
"member": "Member",
|
||||
"number_member_one": "{{count}} member",
|
||||
"number_member_other": "{{count}} members",
|
||||
"owner": "Owner",
|
||||
"admin": "Admin",
|
||||
"administrator_user": "Administrator user",
|
||||
@@ -580,6 +580,8 @@
|
||||
"confirm_all": "Confirm all",
|
||||
"disband_team": "Disband Team",
|
||||
"disband_team_confirmation_message": "Are you sure you want to disband this team? Anyone who you've shared this team link with will no longer be able to book using it.",
|
||||
"disband_org": "Disband Organization",
|
||||
"disband_org_confirmation_message": "Are you sure you want to disband this Org? All teams and members will be deleted.",
|
||||
"remove_member_confirmation_message": "Are you sure you want to remove this member from the team?",
|
||||
"confirm_disband_team": "Yes, disband team",
|
||||
"confirm_remove_member": "Yes, remove member",
|
||||
@@ -650,9 +652,6 @@
|
||||
"new_event_type_btn": "New event type",
|
||||
"new_event_type_heading": "Create your first event type",
|
||||
"new_event_type_description": "Event types enable you to share links that show available times on your calendar and allow people to make bookings with you.",
|
||||
"new_event_title": "Add a new event type",
|
||||
"new_team_event": "Add a new team event type",
|
||||
"new_event_description": "Create a new event type for people to book times with.",
|
||||
"event_type_created_successfully": "{{eventTypeTitle}} event type created successfully",
|
||||
"event_type_updated_successfully": "{{eventTypeTitle}} event type updated successfully",
|
||||
"event_type_deleted_successfully": "Event type deleted successfully",
|
||||
@@ -693,6 +692,7 @@
|
||||
"create_team_to_get_started": "Create a team to get started",
|
||||
"teams": "Teams",
|
||||
"team": "Team",
|
||||
"organization": "Organization",
|
||||
"team_billing": "Team Billing",
|
||||
"team_billing_description": "Manage billing for your team",
|
||||
"upgrade_to_flexible_pro_title": "We've changed billing for teams",
|
||||
@@ -821,7 +821,6 @@
|
||||
"automation": "Automation",
|
||||
"configure_how_your_event_types_interact": "Configure how your event types should interact with your calendars.",
|
||||
"toggle_calendars_conflict": "Toggle the calendars you want to check for conflicts to prevent double bookings.",
|
||||
"select_destination_calendar": "Create events on",
|
||||
"connect_additional_calendar": "Connect additional calendar",
|
||||
"calendar_updated_successfully": "Calendar updated successfully",
|
||||
"conferencing": "Conferencing",
|
||||
@@ -855,7 +854,6 @@
|
||||
"number_apps_other": "{{count}} Apps",
|
||||
"trending_apps": "Trending Apps",
|
||||
"most_popular": "Most Popular",
|
||||
"explore_apps": "{{category}} apps",
|
||||
"installed_apps": "Installed Apps",
|
||||
"free_to_use_apps": "Free",
|
||||
"no_category_apps": "No {{category}} apps",
|
||||
@@ -867,10 +865,10 @@
|
||||
"no_category_apps_description_other": "Add any other type of app to do all sorts of things",
|
||||
"no_category_apps_description_web3": "Add a web3 app for your booking pages",
|
||||
"installed_app_calendar_description": "Set the calendars to check for conflicts to prevent double bookings.",
|
||||
"installed_app_conferencing_description": "Add your favourite video conferencing apps for your meetings",
|
||||
"installed_app_payment_description": "Configure which payment processing services to use when charging your clients.",
|
||||
"installed_app_analytics_description": "Configure which analytics apps to use for your booking pages",
|
||||
"installed_app_other_description": "All your installed apps from other categories.",
|
||||
"installed_app_conferencing_description": "Configure which conferencing apps to use",
|
||||
"installed_app_automation_description": "Configure which automation apps to use",
|
||||
"installed_app_web3_description": "Configure which web3 apps to use for your booking pages",
|
||||
"analytics": "Analytics",
|
||||
@@ -893,7 +891,6 @@
|
||||
"terms_of_service": "Terms of Service",
|
||||
"remove": "Remove",
|
||||
"add": "Add",
|
||||
"installed_one": "Installed",
|
||||
"installed_other": "{{count}} installed",
|
||||
"verify_wallet": "Verify Wallet",
|
||||
"create_events_on": "Create events on",
|
||||
@@ -921,7 +918,6 @@
|
||||
"availability_updated_successfully": "{{scheduleName}} schedule updated successfully",
|
||||
"schedule_deleted_successfully": "Schedule deleted successfully",
|
||||
"default_schedule_name": "Working Hours",
|
||||
"member_default_schedule":"Member's default schedule",
|
||||
"new_schedule_heading": "Create an availability schedule",
|
||||
"new_schedule_description": "Creating availability schedules allows you to manage availability across event types. They can be applied to one or more event types.",
|
||||
"requires_ownership_of_a_token": "Requires ownership of a token belonging to the following address:",
|
||||
@@ -938,7 +934,7 @@
|
||||
"duplicate": "Duplicate",
|
||||
"offer_seats": "Offer seats",
|
||||
"offer_seats_description": "Offer seats for booking. This automatically disables guest & opt-in bookings.",
|
||||
"seats_available_one":"Seat available",
|
||||
"seats_available_one": "Seat available",
|
||||
"seats_available_other": "Seats available",
|
||||
"number_of_seats": "Number of seats per booking",
|
||||
"enter_number_of_seats": "Enter number of seats",
|
||||
@@ -958,8 +954,6 @@
|
||||
"api_key_no_note": "Nameless API key",
|
||||
"api_key_never_expires": "This API key has no expiration date",
|
||||
"edit_api_key": "Edit API key",
|
||||
"never_expire_key": "Never expires",
|
||||
"delete_api_key": "Revoke API key",
|
||||
"success_api_key_created": "API key created successfully",
|
||||
"success_api_key_edited": "API key updated successfully",
|
||||
"create": "Create",
|
||||
@@ -1000,7 +994,6 @@
|
||||
"event_location_changed": "Updated - Your event changed the location",
|
||||
"location_changed_event_type_subject": "Location Changed: {{eventType}} with {{name}} at {{date}}",
|
||||
"current_location": "Current Location",
|
||||
"user_phone": "Your phone number",
|
||||
"new_location": "New Location",
|
||||
"session": "Session",
|
||||
"session_description": "Control your account session",
|
||||
@@ -1026,7 +1019,6 @@
|
||||
"zapier_setup_instructions": "<0>Log into your Zapier account and create a new Zap.</0><1>Select Cal.com as your Trigger app. Also choose a Trigger event.</1><2>Choose your account and then enter your Unique API Key.</2><3>Test your Trigger.</3><4>You're set!</4>",
|
||||
"install_zapier_app": "Please first install the Zapier App in the app store.",
|
||||
"connect_apple_server": "Connect to Apple Server",
|
||||
"connect_caldav_server": "Connect to CalDav (Beta)",
|
||||
"calendar_url": "Calendar URL",
|
||||
"apple_server_generate_password": "Generate an app specific password to use with {{appName}} at",
|
||||
"credentials_stored_encrypted": "Your credentials will be stored and encrypted.",
|
||||
@@ -1058,19 +1050,18 @@
|
||||
"go_to": "Go to: ",
|
||||
"zapier_invite_link": "Zapier Invite Link",
|
||||
"meeting_url_provided_after_confirmed": "A Meeting URL will be created once the event is confirmed.",
|
||||
"attendees_name": "Attendee's name",
|
||||
"dynamically_display_attendee_or_organizer": "Dynamically display the name of your attendee for you, or your name if it's viewed by your attendee",
|
||||
"event_location": "Event's location",
|
||||
"reschedule_optional": "Reason for rescheduling (optional)",
|
||||
"reschedule_placeholder": "Let others know why you need to reschedule",
|
||||
"event_cancelled": "This event is cancelled",
|
||||
"event_cancelled": "This event is canceled",
|
||||
"emailed_information_about_cancelled_event": "We emailed you and the other attendees to let them know.",
|
||||
"this_input_will_shown_booking_this_event": "This input will be shown when booking this event",
|
||||
"meeting_url_in_conformation_email": "Meeting url is in the confirmation email",
|
||||
"url_start_with_https": "URL needs to start with http:// or https://",
|
||||
"number_provided": "Phone number will be provided",
|
||||
"before_event_trigger": "before event starts",
|
||||
"event_cancelled_trigger": "when event is cancelled",
|
||||
"event_cancelled_trigger": "when event is canceled",
|
||||
"new_event_trigger": "when new event is booked",
|
||||
"email_host_action": "send email to host",
|
||||
"email_attendee_action": "send email to attendees",
|
||||
@@ -1133,7 +1124,6 @@
|
||||
"add_exchange2016": "Connect Exchange 2016 Server",
|
||||
"custom_template": "Custom template",
|
||||
"email_body": "Email body",
|
||||
"subject": "Email subject",
|
||||
"text_message": "Text message",
|
||||
"specific_issue": "Have a specific issue?",
|
||||
"browse_our_docs": "browse our docs",
|
||||
@@ -1161,12 +1151,9 @@
|
||||
"new_seat_title": "Someone has added themselves to an event",
|
||||
"variable": "Variable",
|
||||
"event_name_variable": "Event name",
|
||||
"organizer_name_variable": "Organizer",
|
||||
"attendee_name_variable": "Attendee",
|
||||
"event_date_variable": "Event date",
|
||||
"event_time_variable": "Event time",
|
||||
"location_variable": "Location",
|
||||
"additional_notes_variable": "Additional notes",
|
||||
"app_upgrade_description": "In order to use this feature, you need to upgrade to a Pro account.",
|
||||
"invalid_number": "Invalid phone number",
|
||||
"navigate": "Navigate",
|
||||
@@ -1237,7 +1224,7 @@
|
||||
"start_of_week": "Start of week",
|
||||
"recordings_title": "Recordings",
|
||||
"recording": "Recording",
|
||||
"happy_scheduling": "Happy Scheduling",
|
||||
"happy_scheduling": "Happy scheduling",
|
||||
"select_calendars": "Select which calendars you want to check for conflicts to prevent double bookings.",
|
||||
"check_for_conflicts": "Check for conflicts",
|
||||
"view_recordings": "View recordings",
|
||||
@@ -1260,7 +1247,6 @@
|
||||
"recurring_event_tab_description": "Set up a repeating schedule",
|
||||
"today": "today",
|
||||
"appearance": "Appearance",
|
||||
"appearance_subtitle": "Manage settings for your booking appearance",
|
||||
"my_account": "My account",
|
||||
"general": "General",
|
||||
"calendars": "Calendars",
|
||||
@@ -1280,7 +1266,7 @@
|
||||
"conferencing_description": "Add your favourite video conferencing apps for your meetings",
|
||||
"add_conferencing_app": "Add Conferencing App",
|
||||
"password_description": "Manage settings for your account passwords",
|
||||
"2fa_description": "Manage settings for your account passwords",
|
||||
"set_up_two_factor_authentication": "Set up your Two-factor authentication",
|
||||
"we_just_need_basic_info": "We just need some basic info to get your profile setup.",
|
||||
"skip": "Skip",
|
||||
"do_this_later": "Do this later",
|
||||
@@ -1304,7 +1290,6 @@
|
||||
"event_date_info": "The event date",
|
||||
"event_time_info": "The event start time",
|
||||
"location_info": "The location of the event",
|
||||
"organizer_name_info": "Your name",
|
||||
"additional_notes_info": "The additional notes of booking",
|
||||
"attendee_name_info": "The person booking's name",
|
||||
"to": "To",
|
||||
@@ -1313,7 +1298,7 @@
|
||||
"download_responses_description": "Download all responses to your form in CSV format.",
|
||||
"download": "Download",
|
||||
"download_recording": "Download Recording",
|
||||
"recording_from_your_recent_call":"A recording from your recent call on {{appName}} is ready for download",
|
||||
"recording_from_your_recent_call": "A recording from your recent call on {{appName}} is ready for download",
|
||||
"create_your_first_form": "Create your first form",
|
||||
"create_your_first_form_description": "With Routing Forms you can ask qualifying questions and route to the correct person or event type.",
|
||||
"create_your_first_webhook": "Create your first Webhook",
|
||||
@@ -1322,7 +1307,9 @@
|
||||
"event_one": "event",
|
||||
"event_other": "events",
|
||||
"profile_team_description": "Manage settings for your team profile",
|
||||
"profile_org_description": "Manage settings for your organization profile",
|
||||
"members_team_description": "Users that are in the group",
|
||||
"organization_description": "Manage the admins and members in your organization",
|
||||
"team_url": "Team URL",
|
||||
"team_members": "Team members",
|
||||
"more": "More",
|
||||
@@ -1363,14 +1350,13 @@
|
||||
"routing_forms_send_email_owner": "Send Email to Owner",
|
||||
"routing_forms_send_email_owner_description": "Sends an email to the owner when the form is submitted",
|
||||
"add_new_form": "Add new form",
|
||||
"add_new_team_form": "Add new form to your team",
|
||||
"create_your_first_route": "Create your first route",
|
||||
"route_to_the_right_person": "Route to the right person based on the answers to your form",
|
||||
"form_description": "Create your form to route a booker",
|
||||
"copy_link_to_form": "Copy link to form",
|
||||
"theme": "Theme",
|
||||
"theme_applies_note": "This only applies to your public booking pages",
|
||||
"theme_light": "Light",
|
||||
"theme_dark": "Dark",
|
||||
"theme_system": "System default",
|
||||
"add_a_team": "Add a team",
|
||||
"add_webhook_description": "Receive meeting data in real-time when something happens in {{appName}}",
|
||||
@@ -1379,7 +1365,6 @@
|
||||
"enable_webhook": "Enable Webhook",
|
||||
"add_webhook": "Add Webhook",
|
||||
"webhook_edited_successfully": "Webhook saved",
|
||||
"webhooks_description": "Receive meeting data in real-time when something happens in {{appName}}",
|
||||
"api_keys_description": "Generate API keys for accessing your own account",
|
||||
"new_api_key": "New API key",
|
||||
"active": "active",
|
||||
@@ -1421,11 +1406,7 @@
|
||||
"billing_freeplan_title": "You're currently on the FREE plan",
|
||||
"billing_freeplan_description": "We work better in teams. Extend your workflows with round-robin and collective events and make advanced routing forms",
|
||||
"billing_freeplan_cta": "Try now",
|
||||
"billing_manage_details_title": "View and manage your billing details",
|
||||
"billing_manage_details_description": "View and edit your billing details, as well as cancel your subscription.",
|
||||
"billing_portal": "Billing portal",
|
||||
"billing_help_title": "Need anything else?",
|
||||
"billing_help_description": "If you need any further help with billing, our support team are here to help.",
|
||||
"billing_help_cta": "Contact support",
|
||||
"ignore_special_characters_booking_questions": "Ignore special characters in your booking question identifier. Use only letters and numbers",
|
||||
"retry": "Retry",
|
||||
@@ -1433,7 +1414,6 @@
|
||||
"calendar_connection_fail": "Calendar connection failed",
|
||||
"booking_confirmation_success": "Booking confirmation succeeded",
|
||||
"booking_rejection_success": "Booking rejection succeeded",
|
||||
"booking_confirmation_fail": "Booking confirmation failed",
|
||||
"booking_tentative": "This booking is tentative",
|
||||
"booking_accept_intent": "Oops, I want to accept",
|
||||
"we_wont_show_again": "We won't show this again",
|
||||
@@ -1456,7 +1436,6 @@
|
||||
"new_event_type_availability": "{{eventTypeTitle}} Availability",
|
||||
"error_editing_availability": "Error editing availability",
|
||||
"dont_have_permission": "You don't have permission to access this resource.",
|
||||
"saml_config": "Single Sign-On",
|
||||
"saml_configuration_placeholder": "Please paste the SAML metadata from your Identity Provider here",
|
||||
"saml_email_required": "Please enter an email so we can find your SAML Identity Provider",
|
||||
"saml_sp_title": "Service Provider Details",
|
||||
@@ -1465,7 +1444,6 @@
|
||||
"saml_sp_entity_id": "SP Entity ID",
|
||||
"saml_sp_acs_url_copied": "ACS URL copied!",
|
||||
"saml_sp_entity_id_copied": "SP Entity ID copied!",
|
||||
"saml_btn_configure": "Configure",
|
||||
"add_calendar": "Add Calendar",
|
||||
"limit_future_bookings": "Limit future bookings",
|
||||
"limit_future_bookings_description": "Limit how far in the future this event can be booked",
|
||||
@@ -1476,9 +1454,10 @@
|
||||
"yearly": "Yearly",
|
||||
"checkout": "Checkout",
|
||||
"your_team_disbanded_successfully": "Your team has been disbanded successfully",
|
||||
"your_org_disbanded_successfully": "Your organization has been disbanded successfully",
|
||||
"error_creating_team": "Error creating team",
|
||||
"you": "You",
|
||||
"send_email": "Send email",
|
||||
"resend_email": "Resend email",
|
||||
"member_already_invited": "Member has already been invited",
|
||||
"enter_email_or_username": "Enter an email or username",
|
||||
"team_name_taken": "This name is already taken",
|
||||
@@ -1510,7 +1489,7 @@
|
||||
"fixed_round_robin": "Fixed round robin",
|
||||
"add_one_fixed_attendee": "Add one fixed attendee and round robin through a number of attendees.",
|
||||
"calcom_is_better_with_team": "{{appName}} is better with teams",
|
||||
"the_calcom_team":"The {{companyName}} team",
|
||||
"the_calcom_team": "The {{companyName}} team",
|
||||
"add_your_team_members": "Add your team members to your event types. Use collective scheduling to include everyone or find the most suitable person with round robin scheduling.",
|
||||
"booking_limit_reached": "Booking Limit for this event type has been reached",
|
||||
"duration_limit_reached": "Duration Limit for this event type has been reached",
|
||||
@@ -1648,12 +1627,11 @@
|
||||
"delete_sso_configuration_confirmation": "Yes, delete {{connectionType}} configuration",
|
||||
"delete_sso_configuration_confirmation_description": "Are you sure you want to delete the {{connectionType}} configuration? Your team members who use {{connectionType}} login will no longer be able to access Cal.com.",
|
||||
"organizer_timezone": "Organizer timezone",
|
||||
"email_no_user_cta": "Create your account",
|
||||
"email_user_cta": "View Invitation",
|
||||
"email_no_user_invite_heading": "You’ve been invited to join a team on {{appName}}",
|
||||
"email_no_user_invite_heading": "You’ve been invited to join a {{appName}} {{entity}}",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} has invited you to join their team on {{appName}}. {{appName}} is the event-juggling scheduler that enables you and your team to schedule meetings without the email tennis.",
|
||||
"email_user_invite_subheading": "{{invitedBy}} has invited you to join their team `{{teamName}}` on {{appName}}. {{appName}} is the event-juggling scheduler that enables you and your team to schedule meetings without the email tennis.",
|
||||
"email_no_user_invite_steps_intro": "We’ll walk you through a few short steps and you’ll be enjoying stress free scheduling with your team in no time.",
|
||||
"email_user_invite_subheading": "{{invitedBy}} has invited you to join their {{entity}} `{{teamName}}` on {{appName}}. {{appName}} is the event-juggling scheduler that enables you and your {{entity}} to schedule meetings without the email tennis.",
|
||||
"email_no_user_invite_steps_intro": "We’ll walk you through a few short steps and you’ll be enjoying stress free scheduling with your {{entity}} in no time.",
|
||||
"email_no_user_step_one": "Choose your username",
|
||||
"email_no_user_step_two": "Connect your calendar account",
|
||||
"email_no_user_step_three": "Set your Availability",
|
||||
@@ -1664,6 +1642,8 @@
|
||||
"scheduler": "{Scheduler}",
|
||||
"no_workflows": "No workflows",
|
||||
"change_filter": "Change filter to see your personal and team workflows.",
|
||||
"change_filter_common":"Change filter to see the results.",
|
||||
"no_results_for_filter": "No results for the filter",
|
||||
"recommended_next_steps": "Recommended next steps",
|
||||
"create_a_managed_event": "Create a managed event type",
|
||||
"meetings_are_better_with_the_right": "Meetings are better with the right team members there. Invite them now.",
|
||||
@@ -1674,11 +1654,11 @@
|
||||
"no_longer_attending": "You are no longer attending this event",
|
||||
"attendee_no_longer_attending_subject": "An attendee is no longer attending {{title}} at {{date}}",
|
||||
"attendee_no_longer_attending": "An attendee is no longer attending your event",
|
||||
"attendee_no_longer_attending_subtitle": "{{name}} has cancelled. This means a seat has opened up for this time slot",
|
||||
"attendee_no_longer_attending_subtitle": "{{name}} has canceled. This means a seat has opened up for this time slot",
|
||||
"create_event_on": "Create event on",
|
||||
"create_routing_form_on": "Create routing form on",
|
||||
"default_app_link_title": "Set a default app link",
|
||||
"default_app_link_description": "Setting a default app link allows all newly created event types to use the app link you set.",
|
||||
"change_default_conferencing_app": "Set as default",
|
||||
"organizer_default_conferencing_app": "Organizer's default app",
|
||||
"under_maintenance": "Down for maintenance",
|
||||
"under_maintenance_description": "The {{appName}} team are performing scheduled maintenance. If you have any questions, please contact support.",
|
||||
@@ -1694,11 +1674,10 @@
|
||||
"booking_confirmation_failed": "Booking confirmation failed",
|
||||
"not_enough_seats": "Not enough seats",
|
||||
"form_builder_field_already_exists": "A field with this name already exists",
|
||||
"form_builder_field_add_subtitle": "Customize the questions asked on the booking page",
|
||||
"show_on_booking_page": "Show on booking page",
|
||||
"get_started_zapier_templates": "Get started with Zapier templates",
|
||||
"team_is_unpublished": "{{team}} is unpublished",
|
||||
"team_is_unpublished_description": "This team link is currently not available. Please contact the team owner or ask them publish it.",
|
||||
"team_is_unpublished_description": "This {{entity}} link is currently not available. Please contact the {{entity}} owner or ask them publish it.",
|
||||
"team_member": "Team member",
|
||||
"a_routing_form": "A Routing Form",
|
||||
"form_description_placeholder": "Form Description",
|
||||
@@ -1730,13 +1709,14 @@
|
||||
"no_responses_yet": "No responses yet",
|
||||
"no_routes_defined": "No routes defined",
|
||||
"this_will_be_the_placeholder": "This will be the placeholder",
|
||||
"error_booking_event": "An error occured when booking the event, please refresh the page and try again",
|
||||
"error_booking_event": "An error occurred when booking the event, please refresh the page and try again",
|
||||
"timeslot_missing_title": "No timeslot selected",
|
||||
"timeslot_missing_description": "Please select a timeslot to book the event.",
|
||||
"timeslot_missing_cta": "Select timeslot",
|
||||
"switch_monthly": "Switch to monthly view",
|
||||
"switch_weekly": "Switch to weekly view",
|
||||
"switch_multiday": "Switch to day view",
|
||||
"switch_columnview": "Switch to column view",
|
||||
"num_locations": "{{num}} location options",
|
||||
"select_on_next_step": "Select on the next step",
|
||||
"this_meeting_has_not_started_yet": "This meeting has not started yet",
|
||||
@@ -1747,7 +1727,6 @@
|
||||
"verification_code": "Verification code",
|
||||
"can_you_try_again": "Can you try again with a different time?",
|
||||
"verify": "Verify",
|
||||
"timezone_variable": "Timezone",
|
||||
"timezone_info": "The timezone of the person receiving",
|
||||
"event_end_time_variable": "Event end time",
|
||||
"event_end_time_info": "The event end time",
|
||||
@@ -1792,11 +1771,10 @@
|
||||
"least_booked_members": "Least Booked Members",
|
||||
"events_created": "Events Created",
|
||||
"events_completed": "Events Completed",
|
||||
"events_cancelled": "Events Cancelled",
|
||||
"events_cancelled": "Events Canceled",
|
||||
"events_rescheduled": "Events Rescheduled",
|
||||
"from_last_period": "from last period",
|
||||
"from_to_date_period": "From: {{startDate}} To: {{endDate}}",
|
||||
"analytics_for_organisation": "Insights",
|
||||
"subtitle_analytics": "Learn more about your team's activity",
|
||||
"redirect_url_warning": "Adding a redirect will disable the success page. Make sure to mention \"Booking Confirmed\" on your custom success page.",
|
||||
"event_trends": "Event Trends",
|
||||
@@ -1836,7 +1814,6 @@
|
||||
"one_day": "1 day",
|
||||
"seven_days": "7 days",
|
||||
"thirty_days": "30 days",
|
||||
"never_expire": "Never expires",
|
||||
"team_invite_received": "You have been invited to join {{teamName}}",
|
||||
"currency_string": "{{amount, currency}}",
|
||||
"charge_card_dialog_body": "You are about to charge the attendee {{amount, currency}}. Are you sure you want to continue?",
|
||||
@@ -1857,17 +1834,58 @@
|
||||
"book_my_cal": "Book my Cal",
|
||||
"invite_as":"Invite as",
|
||||
"form_updated_successfully":"Form updated successfully.",
|
||||
"email_not_cal_member_cta": "Join your team",
|
||||
"disable_attendees_confirmation_emails": "Disable default confirmation emails for attendees",
|
||||
"disable_attendees_confirmation_emails_description": "At least one workflow is active on this event type that sends an email to the attendees when the event is booked.",
|
||||
"disable_host_confirmation_emails": "Disable default confirmation emails for host",
|
||||
"disable_host_confirmation_emails_description": "At least one workflow is active on this event type that sends an email to the host when the event is booked.",
|
||||
"add_an_override": "Add an override",
|
||||
"import_from_google_workspace":"Import users from Google Workspace",
|
||||
"connect_google_workspace":"Connect Google Workspace",
|
||||
"google_workspace_admin_tooltip":"You must be a Workspace Admin to use this feature",
|
||||
"import_from_google_workspace": "Import users from Google Workspace",
|
||||
"connect_google_workspace": "Connect Google Workspace",
|
||||
"google_workspace_admin_tooltip": "You must be a Workspace Admin to use this feature",
|
||||
"first_event_type_webhook_description": "Create your first webhook for this event type",
|
||||
"create_for": "Create for",
|
||||
"setup_organization": "Setup an Organization",
|
||||
"organization_banner_description": "Create an environments where your teams can create shared apps, workflows and event types with round-robin and collective scheduling.",
|
||||
"organization_banner_title": "Manage organizations with multiple teams",
|
||||
"set_up_your_organization": "Set up your organization",
|
||||
"organizations_description": "Organizations are shared environments where teams can create shared event types, apps, workflows and more.",
|
||||
"organization_url_taken": "This URL is already taken",
|
||||
"must_enter_organization_name": "Must enter an organization name",
|
||||
"must_enter_organization_admin_email": "Must enter your organization email address",
|
||||
"admin_email": "Your organization email address",
|
||||
"admin_username": "Administrator's username",
|
||||
"organization_name": "Organization name",
|
||||
"organization_url": "Organization URL",
|
||||
"organization_verify_header" :"Verify your organization email",
|
||||
"organization_verify_email_body":"Please use the code below to verify your email address to continue setting up your organization.",
|
||||
"additional_url_parameters": "Additional URL parameters",
|
||||
"about_your_organization": "About your organization",
|
||||
"about_your_organization_description": "Organizations are shared environments where you can create multiple teams with shared members, event types, apps, workflows and more.",
|
||||
"create_your_teams": "Create your teams",
|
||||
"create_your_teams_description": "Start scheduling together by adding your team members to your organisation",
|
||||
"invite_organization_admins": "Invite your organization admins",
|
||||
"invite_organization_admins_description": "These admins will have access to all teams in your organization. You can add team admins and members later.",
|
||||
"set_a_password": "Set a password",
|
||||
"set_a_password_description": "This will create a new user account with your organization email and this password.",
|
||||
"organization_logo": "Organization Logo",
|
||||
"organization_about_description": "A few sentences about your organization. This will appear on your organization public profile page.",
|
||||
"ill_do_this_later": "I'll do this later",
|
||||
"verify_your_email": "Verify your email",
|
||||
"enter_digit_code": "Enter the 6 digit code we sent to {{email}}",
|
||||
"verify_email_organization": "Verify your email to create an organization",
|
||||
"code_provided_invalid": "The code provided is not valid, try again",
|
||||
"email_already_used": "Email already being used",
|
||||
"duplicated_slugs_warning": "The following teams couldn't be created due to duplicated slugs: {{slugs}}",
|
||||
"team_names_empty": "Team names can't be empty",
|
||||
"team_names_repeated": "Team names can't be repeated",
|
||||
"user_belongs_organization": "User belongs to an organization",
|
||||
"no_teams_yet": "This organization has no teams yet",
|
||||
"no_teams_yet_description": "if you are an administrator, be sure to create teams to be shown here.",
|
||||
"set_up": "Set up",
|
||||
"set_up_your_profile": "Set up your profile",
|
||||
"set_up_your_profile_description": "Let people know who you are within {{orgName}}, and when they engage with your public link.",
|
||||
"my_profile": "My Profile",
|
||||
"my_settings": "My Settings",
|
||||
"sender_id_info": "Name or number shown as the sender of an SMS (some countries do not allow alphanumeric sender IDs)",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -11,12 +11,9 @@
|
||||
"calcom_explained_new_user": "¡Termine de configurar su cuenta de {{appName}}! Solo le faltan unos pasos para resolver todos sus problemas de programación.",
|
||||
"have_any_questions": "¿Tienes preguntas? Estamos aquí para ayudar.",
|
||||
"reset_password_subject": "{{appName}}: Instrucciones para restablecer la contraseña",
|
||||
"verify_email_banner_button": "Enviar correo electrónico",
|
||||
"event_declined_subject": "Rechazado: {{title}} en {{date}}",
|
||||
"event_cancelled_subject": "Cancelado: {{title}} en {{date}}",
|
||||
"event_request_declined": "Su solicitud de reunión ha sido rechazada",
|
||||
"event_request_declined_recurring": "Su solicitud de evento recurrente se ha rechazado",
|
||||
"event_request_cancelled": "Tu evento programado fue cancelado",
|
||||
"organizer": "Organizador",
|
||||
"need_to_reschedule_or_cancel": "¿Necesita reprogramar o cancelar?",
|
||||
"cancellation_reason": "Motivo de la cancelación (opcional)",
|
||||
@@ -78,13 +75,9 @@
|
||||
"your_meeting_has_been_booked": "Su reunión ha sido reservada",
|
||||
"event_type_has_been_rescheduled_on_time_date": "Tu {{title}} ha sido reprogramado para el {{date}}.",
|
||||
"event_has_been_rescheduled": "Tu evento ha sido reprogramado.",
|
||||
"request_reschedule_title_attendee": "Solicitud para reprogramar su reserva",
|
||||
"request_reschedule_subtitle": "{{organizer}} ha cancelado la reserva y le ha solicitado que elija otra hora.",
|
||||
"request_reschedule_title_organizer": "Le ha solicitado a {{attendee}} que reprograme",
|
||||
"request_reschedule_subtitle_organizer": "Ha cancelado la reserva y {{attendee}} deberá seleccionar una nueva hora de reserva con usted.",
|
||||
"rescheduled_event_type_subject": "Solicitud de reprogramación enviada: {{eventType}} con {{name}} el {{date}}",
|
||||
"requested_to_reschedule_subject_attendee": "Reprogramar acción requerida: reserva una nueva hora para {{eventType}} con {{name}}",
|
||||
"reschedule_reason": "Motivo de la reprogramación",
|
||||
"hi_user_name": "Hola {{name}}",
|
||||
"ics_event_title": "{{eventType}} con {{name}}",
|
||||
"new_event_subject": "Nuevo Evento: {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
@@ -122,6 +115,7 @@
|
||||
"team_upgrade_banner_description": "Gracias por probar nuestro nuevo plan de equipo. Notamos que su equipo \"{{teamName}}\" necesita actualizarse.",
|
||||
"team_upgrade_banner_action": "Actualizar aquí",
|
||||
"team_upgraded_successfully": "¡Tu equipo se actualizó con éxito!",
|
||||
"org_upgrade_banner_action": "Actualizar aquí",
|
||||
"use_link_to_reset_password": "Utilice el enlace de abajo para restablecer su contraseña",
|
||||
"hey_there": "Hola,",
|
||||
"forgot_your_password_calcom": "¿Olvidaste tu contraseña? - {{appName}}",
|
||||
@@ -231,6 +225,7 @@
|
||||
"done": "Hecho",
|
||||
"all_done": "¡Todo listo!",
|
||||
"all_apps": "Todas las aplicaciones",
|
||||
"all": "Todas las aplicaciones",
|
||||
"available_apps": "Aplicaciones disponibles",
|
||||
"check_email_reset_password": "Revisa tu email. Te hemos enviado un enlace para restablecer tu contraseña.",
|
||||
"finish": "Terminar",
|
||||
@@ -252,7 +247,6 @@
|
||||
"welcome_to_calcom": "Bienvenido a {{appName}}",
|
||||
"welcome_instructions": "Cuéntanos cómo llamarte y dinos la zona horaria en la que estás. Podrás editarla más tarde.",
|
||||
"connect_caldav": "Conectar con CalDav (Beta)",
|
||||
"credentials_stored_and_encrypted": "Sus credenciales serán almacenadas y cifradas.",
|
||||
"connect": "Conectar",
|
||||
"try_for_free": "Pruébalo Gratis",
|
||||
"create_booking_link_with_calcom": "Crea tu propio enlace de reserva con {{appName}}",
|
||||
@@ -273,7 +267,6 @@
|
||||
"user_needs_to_confirm_or_reject_booking_recurring": "El {{user}} todavía necesita confirmar o rechazar cada reserva de la reunión recurrente.",
|
||||
"meeting_is_scheduled": "Esta reunión está programada",
|
||||
"meeting_is_scheduled_recurring": "Se han programado los eventos recurrentes",
|
||||
"submitted_recurring": "Su evento recurrente se ha enviado",
|
||||
"booking_submitted": "Reserva enviada",
|
||||
"booking_submitted_recurring": "Su reunión recurrente se ha enviado",
|
||||
"booking_confirmed": "Reserva confirmada",
|
||||
@@ -306,7 +299,6 @@
|
||||
"error_end_time_next_day": "La hora final no puede ser mayor de 24 horas",
|
||||
"back_to_bookings": "Volver a Reservas",
|
||||
"free_to_pick_another_event_type": "No dude en elegir otro evento en cualquier momento.",
|
||||
"cancelled": "Cancelado",
|
||||
"cancellation_successful": "Cancelación Realizada",
|
||||
"really_cancel_booking": "¿Realmente deseas cancelar tu reserva?",
|
||||
"cannot_cancel_booking": "No puedes cancelar esta reserva",
|
||||
@@ -315,11 +307,9 @@
|
||||
"cancelling_event_recurring": "El evento es un caso de un evento recurrente.",
|
||||
"cancelling_all_recurring": "Todas estas son instancias restantes en el evento recurrente.",
|
||||
"error_with_status_code_occured": "Se produjo un error con el código de estado {{status}}.",
|
||||
"booking_already_cancelled": "Esta reserva ya fue cancelada",
|
||||
"booking_already_accepted_rejected": "Esta reserva ya se aceptó o rechazó",
|
||||
"go_back_home": "Volver a Inicio",
|
||||
"or_go_back_home": "O Volver al Inicio",
|
||||
"no_availability": "Sin disponibilidad",
|
||||
"no_meeting_found": "Reunión no Encontrada",
|
||||
"no_meeting_found_description": "Esta reunión no existe. Póngase en contacto con el responsable de la reunión para obtener un enlace actualizado.",
|
||||
"no_status_bookings_yet": "Aún no hay reservas {{status}}",
|
||||
@@ -330,7 +320,6 @@
|
||||
"upcoming_bookings": "Tan pronto como alguien reserve una hora contigo, aparecerá aquí.",
|
||||
"recurring_bookings": "Tan pronto como alguien reserve una reunión recurrente con usted, aparecerá aquí.",
|
||||
"past_bookings": "Sus reservas pasadas aparecerán aquí.",
|
||||
"cancelled_bookings": "Las reservas canceladas aparecerán aquí.",
|
||||
"unconfirmed_bookings": "Las reservas sin confirmar aparecerán aquí.",
|
||||
"unconfirmed_bookings_tooltip": "Reservas sin confirmar",
|
||||
"on": "en",
|
||||
@@ -370,7 +359,6 @@
|
||||
"browse_api_documentation": "Consulte la documentación de nuestra API",
|
||||
"leverage_our_api": "Aproveche nuestra API para un control total y personalización.",
|
||||
"create_webhook": "Crear Webhook",
|
||||
"booking_cancelled": "Reserva Cancelada",
|
||||
"booking_rescheduled": "Reserva habilitada",
|
||||
"recording_ready": "Enlace de descarga de grabación listo",
|
||||
"booking_created": "Reserva Creada",
|
||||
@@ -383,8 +371,6 @@
|
||||
"team_webhooks": "Webhooks del equipo",
|
||||
"create_new_webhook_to_account": "Crear un nuevo webhook en tu cuenta",
|
||||
"new_webhook": "Nuevo Webhook",
|
||||
"receive_cal_meeting_data": "Reciba datos de reuniones de {{appName}} en una URL específica, en tiempo real, cuando se programe o cancele un evento.",
|
||||
"receive_cal_event_meeting_data": "Reciba los datos de la reunión de {{appName}} en una URL especificada, en tiempo real, cuando este evento se programe o se cancele.",
|
||||
"responsive_fullscreen_iframe": "Iframe receptivo a pantalla completa",
|
||||
"loading": "Cargando...",
|
||||
"deleting": "Eliminando...",
|
||||
@@ -448,7 +434,6 @@
|
||||
"invalid_password_hint": "La contraseña debe tener un mínimo de {{passwordLength}} caracteres que contengan al menos un número y una mezcla de letras mayúsculas y minúsculas",
|
||||
"incorrect_password": "La Contraseña es Incorrecta.",
|
||||
"incorrect_username_password": "El nombre de usuario o la contraseña son incorrectos.",
|
||||
"24_h": "24hs",
|
||||
"use_setting": "Usar Ajuste",
|
||||
"am_pm": "am/pm",
|
||||
"time_options": "Opciones Horas",
|
||||
@@ -491,15 +476,11 @@
|
||||
"booking_confirmation": "Confirma tu {{eventTypeTitle}} con {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Reprogramar tu {{eventTypeTitle}} con {{profileName}}",
|
||||
"in_person_meeting": "Reunión en Persona",
|
||||
"attendee_in_person": "En persona (dirección del asistente)",
|
||||
"in_person": "En persona (dirección del organizador)",
|
||||
"link_meeting": "Enlace de la reunión",
|
||||
"phone_call": "Número de teléfono del asistente",
|
||||
"your_number": "Tu número de teléfono",
|
||||
"phone_number": "Nª de Telefono",
|
||||
"attendee_phone_number": "Número de teléfono del asistente",
|
||||
"organizer_phone_number": "Número de teléfono del organizador",
|
||||
"host_phone_number": "Su número de teléfono",
|
||||
"enter_phone_number": "Introducir Nº de Telefono",
|
||||
"reschedule": "Reprogramar",
|
||||
"reschedule_this": "Reprogramar en su lugar",
|
||||
@@ -525,6 +506,8 @@
|
||||
"team_description": "Comentarios sobre tu equipo. Esta información aparecerá en la página de la URL de tu equipo.",
|
||||
"members": "Miembros",
|
||||
"member": "Miembro",
|
||||
"number_member_one": "{{count}} miembro",
|
||||
"number_member_other": "{{count}} miembros",
|
||||
"owner": "Propietario",
|
||||
"admin": "Administrador",
|
||||
"administrator_user": "Usuario administrador",
|
||||
@@ -625,9 +608,6 @@
|
||||
"new_event_type_btn": "Nuevo Tipo de Evento",
|
||||
"new_event_type_heading": "Crea tu primer tipo de evento",
|
||||
"new_event_type_description": "Los tipos de eventos te permiten compartir enlaces que muestran las horas disponibles en tu calendario y permitir que la gente haga reservas contigo.",
|
||||
"new_event_title": "Crear Nuevo Tipo de Evento",
|
||||
"new_team_event": "Crear Nuevo Tipo de Evento de Equipo",
|
||||
"new_event_description": "Crea un nuevo tipo de evento con el que la gente pueda hacer reservas.",
|
||||
"event_type_created_successfully": "{{eventTypeTitle}} tipo de evento creado con éxito",
|
||||
"event_type_updated_successfully": "{{eventTypeTitle}} tipo de evento actualizado con éxito",
|
||||
"event_type_deleted_successfully": "Tipo de evento eliminado con éxito",
|
||||
@@ -796,7 +776,6 @@
|
||||
"automation": "Automatización",
|
||||
"configure_how_your_event_types_interact": "Configure cómo deben interactuar sus tipos de eventos con sus calendarios.",
|
||||
"toggle_calendars_conflict": "Activa/desactiva los calendarios en los que desees comprobar conflictos para evitar reservas dobles.",
|
||||
"select_destination_calendar": "Crear eventos en",
|
||||
"connect_additional_calendar": "Conectar calendario adicional",
|
||||
"calendar_updated_successfully": "Calendario actualizado correctamente",
|
||||
"conferencing": "Conferencias",
|
||||
@@ -830,7 +809,6 @@
|
||||
"number_apps_other": "{{count}} aplicaciones",
|
||||
"trending_apps": "Aplicaciones populares",
|
||||
"most_popular": "Más popular",
|
||||
"explore_apps": "Aplicaciones {{category}}",
|
||||
"installed_apps": "Aplicaciones instaladas",
|
||||
"free_to_use_apps": "Gratis",
|
||||
"no_category_apps": "No hay aplicaciones de {{category}}",
|
||||
@@ -842,7 +820,6 @@
|
||||
"no_category_apps_description_other": "Añade cualquier otro tipo de aplicación para hacer todo tipo de tareas",
|
||||
"no_category_apps_description_web3": "Agregue una aplicación web3 para sus páginas de reserva",
|
||||
"installed_app_calendar_description": "Configure el(los) calendario(s) para comprobar conflictos y evitar reservas duplicadas.",
|
||||
"installed_app_conferencing_description": "Añade tus aplicaciones de videoconferencia favoritas para las reuniones",
|
||||
"installed_app_payment_description": "Configura los servicios de procesamiento de pagos que vas a utilizar para cobrar a tus clientes.",
|
||||
"installed_app_analytics_description": "Configure qué aplicaciones de análisis va a utilizar para sus páginas de reserva",
|
||||
"installed_app_other_description": "Todas tus aplicaciones instaladas de otras categorías.",
|
||||
@@ -868,7 +845,6 @@
|
||||
"terms_of_service": "Términos de servicio",
|
||||
"remove": "Eliminar",
|
||||
"add": "Añadir",
|
||||
"installed_one": "Instalada",
|
||||
"installed_other": "{{count}} instaladas",
|
||||
"verify_wallet": "Verificar billetera",
|
||||
"create_events_on": "Crear eventos en",
|
||||
@@ -896,7 +872,6 @@
|
||||
"availability_updated_successfully": "El horario de {{scheduleName}} se actualizó correctamente",
|
||||
"schedule_deleted_successfully": "Programación eliminada exitosamente",
|
||||
"default_schedule_name": "Horas laborables",
|
||||
"member_default_schedule": "Horario predeterminado del miembro",
|
||||
"new_schedule_heading": "Crear un horario de disponibilidad",
|
||||
"new_schedule_description": "Crear horarios de disponibilidad le permite gestionar la disponibilidad a través de tipos de eventos. Pueden aplicarse a uno o más tipos de eventos.",
|
||||
"requires_ownership_of_a_token": "Requiere la propiedad de un token perteneciente a la siguiente dirección:",
|
||||
@@ -933,8 +908,6 @@
|
||||
"api_key_no_note": "Clave API sin nombre",
|
||||
"api_key_never_expires": "Esta clave API no tiene fecha de caducidad",
|
||||
"edit_api_key": "Editar clave API",
|
||||
"never_expire_key": "Nunca caduca",
|
||||
"delete_api_key": "Revocar clave API",
|
||||
"success_api_key_created": "Clave API creada exitosamente",
|
||||
"success_api_key_edited": "Clave API actualizada exitosamente",
|
||||
"create": "Crear",
|
||||
@@ -975,7 +948,6 @@
|
||||
"event_location_changed": "Actualizado - Su evento cambió la ubicación",
|
||||
"location_changed_event_type_subject": "Ubicación cambiada: {{eventType}} con {{name}} el {{date}}",
|
||||
"current_location": "Ubicación actual",
|
||||
"user_phone": "Su número de teléfono",
|
||||
"new_location": "Nueva ubicación",
|
||||
"session": "Sesión",
|
||||
"session_description": "Controle la sesión de su cuenta",
|
||||
@@ -1001,7 +973,6 @@
|
||||
"zapier_setup_instructions": "<0>Inicie sesión en su cuenta de Zapier y cree un nuevo Zap.</0><1>Seleccione Cal.com cómo su aplicación Trigger. También elija un evento Trigger.</1><2>Seleccione su cuenta e ingrese su Clave API única.</2><3>Pruebe su Trigger.</3><4>¡Listo!</4>",
|
||||
"install_zapier_app": "Instale primero la aplicación Zapier desde la App Store.",
|
||||
"connect_apple_server": "Conectar con Apple Server",
|
||||
"connect_caldav_server": "Conectar con CalDav (Beta)",
|
||||
"calendar_url": "URL del calendario",
|
||||
"apple_server_generate_password": "Genere una contraseña específica de la aplicación para utilizarla con {{appName}} en",
|
||||
"credentials_stored_encrypted": "Sus credenciales serán almacenadas y cifradas.",
|
||||
@@ -1033,19 +1004,16 @@
|
||||
"go_to": "Ir a: ",
|
||||
"zapier_invite_link": "Zapier Invite Link",
|
||||
"meeting_url_provided_after_confirmed": "Se creará una URL de la reunión una vez que se confirme el evento.",
|
||||
"attendees_name": "Nombre del asistente",
|
||||
"dynamically_display_attendee_or_organizer": "Mostrar dinámicamente el nombre de su asistente para usted, o su nombre si es visto por su asistente",
|
||||
"event_location": "Ubicación del evento",
|
||||
"reschedule_optional": "Razón para reagendar (opcional)",
|
||||
"reschedule_placeholder": "Informa a los demás la razón por la que necesitas reagendar",
|
||||
"event_cancelled": "Este evento se canceló",
|
||||
"emailed_information_about_cancelled_event": "Le enviamos un correo electrónico a usted y a los demás asistentes para informarles.",
|
||||
"this_input_will_shown_booking_this_event": "Esta entrada se mostrará al reservar este evento.",
|
||||
"meeting_url_in_conformation_email": "La URL de la reunión está en el correo de confirmación",
|
||||
"url_start_with_https": "La URL debe empezar por http:// o https://",
|
||||
"number_provided": "Se proporcionará el número de teléfono",
|
||||
"before_event_trigger": "antes del inicio del evento",
|
||||
"event_cancelled_trigger": "cuando se cancela el evento",
|
||||
"new_event_trigger": "cuando se reserva un nuevo evento",
|
||||
"email_host_action": "enviar correo electrónico al anfitrión",
|
||||
"email_attendee_action": "enviar correo electrónico a los asistentes",
|
||||
@@ -1107,7 +1075,6 @@
|
||||
"add_exchange2016": "Conectar con Exchange 2016 Server",
|
||||
"custom_template": "Plantilla personalizada",
|
||||
"email_body": "Cuerpo del mensaje",
|
||||
"subject": "Asunto del correo electrónico",
|
||||
"text_message": "Mensaje de texto",
|
||||
"specific_issue": "¿Tienes un problema específico?",
|
||||
"browse_our_docs": "navega por nuestros documentos",
|
||||
@@ -1135,12 +1102,9 @@
|
||||
"new_seat_title": "Alguien se ha añadido a un evento",
|
||||
"variable": "Variable",
|
||||
"event_name_variable": "Nombre del evento",
|
||||
"organizer_name_variable": "Nombre del organizador",
|
||||
"attendee_name_variable": "Nombre del asistente",
|
||||
"event_date_variable": "Fecha del evento",
|
||||
"event_time_variable": "Hora del evento",
|
||||
"location_variable": "Lugar",
|
||||
"additional_notes_variable": "Notas Adicionales",
|
||||
"app_upgrade_description": "Para poder usar esta función, necesita actualizarse a una cuenta Pro.",
|
||||
"invalid_number": "Número de teléfono no válido",
|
||||
"navigate": "Navegar",
|
||||
@@ -1211,7 +1175,6 @@
|
||||
"start_of_week": "Inicio de la semana",
|
||||
"recordings_title": "Grabaciones",
|
||||
"recording": "Grabación",
|
||||
"happy_scheduling": "Feliz programación",
|
||||
"select_calendars": "Seleccione los calendarios en los que desee comprobar conflictos para evitar reservas dobles.",
|
||||
"check_for_conflicts": "Comprobar conflictos",
|
||||
"view_recordings": "Ver grabaciones",
|
||||
@@ -1234,7 +1197,6 @@
|
||||
"recurring_event_tab_description": "Configurar un calendario repetitivo",
|
||||
"today": "hoy",
|
||||
"appearance": "Aspecto",
|
||||
"appearance_subtitle": "Administra los ajustes para el aspecto de tu reserva",
|
||||
"my_account": "Mi cuenta",
|
||||
"general": "General",
|
||||
"calendars": "Calendarios",
|
||||
@@ -1254,7 +1216,6 @@
|
||||
"conferencing_description": "Añada sus aplicaciones de videoconferencia favoritas para sus reuniones",
|
||||
"add_conferencing_app": "Añadir aplicación de conferencia",
|
||||
"password_description": "Administra los ajustes para las contraseñas de tu cuenta",
|
||||
"2fa_description": "Administra los ajustes para las contraseñas de tu cuenta",
|
||||
"we_just_need_basic_info": "Solo necesitamos información básica para configurar tu perfil.",
|
||||
"skip": "Omitir",
|
||||
"do_this_later": "Hacerlo más tarde",
|
||||
@@ -1278,7 +1239,6 @@
|
||||
"event_date_info": "Fecha del evento",
|
||||
"event_time_info": "Hora de inicio del evento",
|
||||
"location_info": "Ubicación del evento",
|
||||
"organizer_name_info": "Tu Nombre",
|
||||
"additional_notes_info": "Notas adicionales de la reserva",
|
||||
"attendee_name_info": "Nombre de la persona que reserva",
|
||||
"to": "Para",
|
||||
@@ -1342,8 +1302,6 @@
|
||||
"copy_link_to_form": "Copiar enlace al formulario",
|
||||
"theme": "Tema",
|
||||
"theme_applies_note": "Esto sólo se aplica a tus páginas públicas de reservas",
|
||||
"theme_light": "Claro",
|
||||
"theme_dark": "Oscuro",
|
||||
"theme_system": "Predeterminado del sistema",
|
||||
"add_a_team": "Añadir un equipo",
|
||||
"add_webhook_description": "Recibe los datos de la reunión en tiempo real cuando ocurra algo en {{appName}}",
|
||||
@@ -1352,7 +1310,6 @@
|
||||
"enable_webhook": "Activar Webhook",
|
||||
"add_webhook": "Añadir Webhook",
|
||||
"webhook_edited_successfully": "Webhook guardado",
|
||||
"webhooks_description": "Recibe los datos de la reunión en tiempo real cuando ocurra algo en {{appName}}",
|
||||
"api_keys_description": "Genera claves API para acceder a tu propia cuenta",
|
||||
"new_api_key": "Clave API nueva",
|
||||
"active": "activo",
|
||||
@@ -1394,11 +1351,7 @@
|
||||
"billing_freeplan_title": "Actualmente está en el plan GRATUITO",
|
||||
"billing_freeplan_description": "Trabajamos mejor en equipo. Amplíe sus flujos de trabajo con eventos colectivos y rotativos y genere formularios de enrutamiento avanzados",
|
||||
"billing_freeplan_cta": "Pruebe ahora",
|
||||
"billing_manage_details_title": "Ver y administrar tus datos de facturación",
|
||||
"billing_manage_details_description": "Ver y editar tus datos de facturación, así como cancelar tu suscripción.",
|
||||
"billing_portal": "Portal de facturación",
|
||||
"billing_help_title": "¿Necesitas algo más?",
|
||||
"billing_help_description": "Si necesitas más ayuda con la facturación, nuestro equipo de soporte está a tu disposición.",
|
||||
"billing_help_cta": "Contacte con soporte",
|
||||
"ignore_special_characters_booking_questions": "Ignore los caracteres especiales en su identificador de pregunta de reserva. Use solo letras y números",
|
||||
"retry": "Reintentar",
|
||||
@@ -1406,7 +1359,6 @@
|
||||
"calendar_connection_fail": "Error de conexión con el calendario",
|
||||
"booking_confirmation_success": "Confirmación de reserva exitosa",
|
||||
"booking_rejection_success": "Rechazo de reserva exitoso",
|
||||
"booking_confirmation_fail": "Error al confirmar la reserva",
|
||||
"booking_tentative": "Esta reserva es provisional",
|
||||
"booking_accept_intent": "Ups, quiero aceptar",
|
||||
"we_wont_show_again": "No mostraremos esto de nuevo",
|
||||
@@ -1429,7 +1381,6 @@
|
||||
"new_event_type_availability": "Disponibilidad para {{eventTypeTitle}}",
|
||||
"error_editing_availability": "Error al editar la disponibilidad",
|
||||
"dont_have_permission": "No tiene permiso para acceder a este recurso.",
|
||||
"saml_config": "Configuración de SAML",
|
||||
"saml_configuration_placeholder": "Pega los metadatos SAML de tu Proveedor de Identidad aquí",
|
||||
"saml_email_required": "Por favor, introduce un correo electrónico para que podamos encontrar tu Proveedor de Identidad SAML",
|
||||
"saml_sp_title": "Detalles del proveedor de servicios",
|
||||
@@ -1438,7 +1389,6 @@
|
||||
"saml_sp_entity_id": "ID de entidad SP",
|
||||
"saml_sp_acs_url_copied": "¡URL de ACS copiada!",
|
||||
"saml_sp_entity_id_copied": "¡ID de entidad SP copiado!",
|
||||
"saml_btn_configure": "Configurar",
|
||||
"add_calendar": "Añadir un calendario",
|
||||
"limit_future_bookings": "Limitar reservas futuras",
|
||||
"limit_future_bookings_description": "Limite hasta qué punto se puede reservar este evento en el futuro",
|
||||
@@ -1451,7 +1401,6 @@
|
||||
"your_team_disbanded_successfully": "Su equipo se ha disuelto con éxito",
|
||||
"error_creating_team": "Error al crear el equipo",
|
||||
"you": "Usted",
|
||||
"send_email": "Enviar correo electrónico",
|
||||
"member_already_invited": "El miembro ya se ha invitado",
|
||||
"enter_email_or_username": "Introduzca un correo electrónico o nombre de usuario",
|
||||
"team_name_taken": "Este nombre ya está en uso",
|
||||
@@ -1618,12 +1567,8 @@
|
||||
"delete_sso_configuration_confirmation": "Sí, eliminar la configuración de {{connectionType}}",
|
||||
"delete_sso_configuration_confirmation_description": "¿Está seguro de que desea eliminar la configuración de {{connectionType}}? Los miembros de su equipo que utilicen el inicio de sesión {{connectionType}} ya no podrán acceder a Cal.com.",
|
||||
"organizer_timezone": "Zona horaria del organizador",
|
||||
"email_no_user_cta": "Crea tu Cuenta",
|
||||
"email_user_cta": "Ver la invitación",
|
||||
"email_no_user_invite_heading": "Lo han invitado a unirse a un equipo en {{appName}}",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} lo invitó a unirse a su equipo en {{appName}}. {{appName}} es el programador de eventos que les permite a usted y a su equipo programar reuniones sin necesidad de enviar correos electrónicos.",
|
||||
"email_user_invite_subheading": "{{invitedBy}} lo ha invitado a unirse a su equipo \"{{teamName}}\" en {{appName}}. {{appName}} es el planificador de eventos que le permite a usted y a su equipo programar reuniones sin correos electrónicos de ida y vuelta.",
|
||||
"email_no_user_invite_steps_intro": "Lo guiaremos a través de unos pocos pasos y disfrutará de una programación con su equipo sin estresarse y empleando muy poco tiempo.",
|
||||
"email_no_user_step_one": "Elija su nombre de usuario",
|
||||
"email_no_user_step_two": "Conecte su cuenta de calendario",
|
||||
"email_no_user_step_three": "Establezca su disponibilidad",
|
||||
@@ -1644,11 +1589,9 @@
|
||||
"no_longer_attending": "Ya no asistirá a este evento",
|
||||
"attendee_no_longer_attending_subject": "Un asistente ya no asistirá a {{title}} a las {{date}}",
|
||||
"attendee_no_longer_attending": "Un asistente ya no asistirá a su evento",
|
||||
"attendee_no_longer_attending_subtitle": "{{name}} ha cancelado. Esto significa que está disponible una plaza para esta franja horaria",
|
||||
"create_event_on": "Crear evento en",
|
||||
"default_app_link_title": "Establecer un enlace de aplicación predeterminado",
|
||||
"default_app_link_description": "Establecer un enlace de aplicación predeterminado permite que todos los tipos de eventos recién creados utilicen el enlace de aplicación que establezca.",
|
||||
"change_default_conferencing_app": "Establecer como predeterminado",
|
||||
"organizer_default_conferencing_app": "Aplicación por defecto del organizador",
|
||||
"under_maintenance": "Fuera de servicio por mantenimiento",
|
||||
"under_maintenance_description": "El equipo de {{appName}} está realizando un mantenimiento programado. Si tiene alguna pregunta, comuníquese con soporte.",
|
||||
@@ -1663,11 +1606,9 @@
|
||||
"booking_confirmation_failed": "Error al confirmar la reserva",
|
||||
"not_enough_seats": "No hay suficientes plazas",
|
||||
"form_builder_field_already_exists": "Ya existe un campo con este nombre",
|
||||
"form_builder_field_add_subtitle": "Personalice las preguntas que se hacen en la página de reservas",
|
||||
"show_on_booking_page": "Mostrar en la página de reserva",
|
||||
"get_started_zapier_templates": "Comience con las plantillas de Zapier",
|
||||
"team_is_unpublished": "{{team}} no está publicado",
|
||||
"team_is_unpublished_description": "Este enlace del equipo no está disponible actualmente. Póngase en contacto con el propietario del equipo o pídale que lo publique.",
|
||||
"team_member": "Miembro del equipo",
|
||||
"a_routing_form": "Un formulario de enrutamiento",
|
||||
"form_description_placeholder": "Descripción del formulario",
|
||||
@@ -1698,7 +1639,6 @@
|
||||
"spot_popular_event_types_description": "Consulte cuál de sus tipos de eventos están recibiendo más clics y reservas",
|
||||
"no_responses_yet": "Aún no hay respuestas",
|
||||
"this_will_be_the_placeholder": "Este será el marcador de posición",
|
||||
"error_booking_event": "Ocurrió un error al reservar el evento, actualice la página e intente nuevamente",
|
||||
"timeslot_missing_title": "No hay intervalo de tiempo seleccionado",
|
||||
"timeslot_missing_description": "Seleccione un intervalo de tiempo para reservar el evento.",
|
||||
"timeslot_missing_cta": "Seleccionar intervalo de tiempo",
|
||||
@@ -1715,7 +1655,6 @@
|
||||
"verification_code": "Código de verificación",
|
||||
"can_you_try_again": "¿Puede intentarlo de nuevo con una hora diferente?",
|
||||
"verify": "Verificar",
|
||||
"timezone_variable": "Zona Horaria",
|
||||
"timezone_info": "Zona horaria de la persona que recibe",
|
||||
"event_end_time_variable": "Hora de finalización del evento",
|
||||
"event_end_time_info": "La hora de finalización del evento",
|
||||
@@ -1760,11 +1699,9 @@
|
||||
"least_booked_members": "Miembros con menos reservas",
|
||||
"events_created": "Eventos creados",
|
||||
"events_completed": "Eventos completados",
|
||||
"events_cancelled": "Eventos cancelados",
|
||||
"events_rescheduled": "Eventos reprogramados",
|
||||
"from_last_period": "desde el último período",
|
||||
"from_to_date_period": "Desde: {{startDate}} Hasta: {{endDate}}",
|
||||
"analytics_for_organisation": "Insights",
|
||||
"subtitle_analytics": "Obtenga más información sobre la actividad de su equipo",
|
||||
"redirect_url_warning": "Agregar una redirección deshabilitará la página de éxito. Asegúrese de mencionar \"Reserva confirmada\" en su página de éxito personalizada.",
|
||||
"event_trends": "Tendencias del evento",
|
||||
@@ -1795,7 +1732,6 @@
|
||||
"complete_your_booking": "Complete su reserva",
|
||||
"complete_your_booking_subject": "Complete su reserva: {{title}} el {{date}}",
|
||||
"confirm_your_details": "Confirme sus datos",
|
||||
"never_expire": "Nunca caduca",
|
||||
"currency_string": "{{amount, currency}}",
|
||||
"charge_card_dialog_body": "Está a punto de cobrarle {{amount, currency}} al asistente. ¿Está seguro de que desea continuar?",
|
||||
"charge_attendee": "Cobrarle al asistente {{amount, currency}}",
|
||||
@@ -1814,7 +1750,6 @@
|
||||
"book_my_cal": "Reservar mi Cal",
|
||||
"invite_as": "Invitar como",
|
||||
"form_updated_successfully": "Formulario actualizado con éxito.",
|
||||
"email_not_cal_member_cta": "Únase a su equipo",
|
||||
"disable_attendees_confirmation_emails": "Desactivar los correos electrónicos de confirmación predeterminados para los asistentes",
|
||||
"disable_attendees_confirmation_emails_description": "Al menos un flujo de trabajo está activo en este tipo de evento que envía un correo electrónico a los asistentes cuando se reserva el evento.",
|
||||
"disable_host_confirmation_emails": "Desactivar los correos electrónicos de confirmación predeterminados para el anfitrión",
|
||||
@@ -1824,5 +1759,6 @@
|
||||
"connect_google_workspace": "Conectar Google Workspace",
|
||||
"google_workspace_admin_tooltip": "Debe ser administrador del espacio de trabajo para usar esta función",
|
||||
"first_event_type_webhook_description": "Cree su primer webhook para este tipo de evento",
|
||||
"create_for": "Crear para"
|
||||
"create_for": "Crear para",
|
||||
"organization_url_taken": "Esta URL ya está en uso"
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
{
|
||||
"identity_provider": "Identidikazioaren hornitzailea",
|
||||
"trial_days_left": "$t(day, {\"count\": {{days}} }) geratzen zaizkizu zure PRO frogan",
|
||||
"day_one": "egun {{count}}",
|
||||
"day_other": "{{count}} egun",
|
||||
"second_one": "segundo {{count}}",
|
||||
"second_other": "{{count}} segundo",
|
||||
"upgrade_now": "Eguneratu orain",
|
||||
"accept_invitation": "Onartu gonbidapena",
|
||||
"have_any_questions": "Galderarik? Laguntzeko gaude.",
|
||||
"reset_password_subject": "{{appName}}: Pasahitza berrezartzeko argibideak",
|
||||
"verify_email_subject": "{{appName}}: egiaztatu zure kontua",
|
||||
"check_your_email": "Begiratu zure emaila",
|
||||
"verify_email_email_header": "Egiaztatu zure email helbidea",
|
||||
"verify_email_email_button": "Egiaztatu emaila",
|
||||
"event_declined_subject": "Baztertua: {{title}} {{date}}(e)an",
|
||||
"event_cancelled_subject": "Bertan behera: {{title}} {{date}}(e)an",
|
||||
"event_request_declined": "Zure gertaera-eskaera baztertua izan da",
|
||||
"event_request_declined_recurring": "Zure gertaera errepikari-eskaera baztertua izan da",
|
||||
"event_request_cancelled": "Zure programatutako gertaera baztertua izan da",
|
||||
"organizer": "Antolatzailea",
|
||||
"need_to_reschedule_or_cancel": "Programazioa aldatu edo bertan behera utzi behar duzu?",
|
||||
"cancellation_reason": "Bertan behera uztearen arrazoia (aukerakoa)",
|
||||
@@ -56,14 +60,11 @@
|
||||
"back_to_bookings": "Itzuli erreserbatara",
|
||||
"really_cancel_booking": "Benetan bertan behera utzi nahi duzu zure erreserba?",
|
||||
"cannot_cancel_booking": "Ezin duzu erreserba hau bertan behera utzi",
|
||||
"booking_already_cancelled": "Erreserba hau bertan behera utzi da dagoeneko",
|
||||
"booking_already_accepted_rejected": "Erreserba hau onartu edo errefusatu da dagoeneko",
|
||||
"bookings": "Erreserbak",
|
||||
"past_bookings": "Zure iraganeko erreserbak agertuko dira hemen.",
|
||||
"cancelled_bookings": "Zure bertan behera utzitako erreserbak agertuko dira hemen.",
|
||||
"unconfirmed_bookings": "Zure baieztatu gabeko erreserbak agertuko dira hemen.",
|
||||
"unconfirmed_bookings_tooltip": "Baieztatu gabeko erreserbak",
|
||||
"booking_cancelled": "Erreserba bertan behera",
|
||||
"booking_rescheduled": "Erreserbaren programazioa aldatuta",
|
||||
"booking_created": "Erreserba sortuta",
|
||||
"edit_booking": "Aldatu erreserba",
|
||||
|
||||
@@ -11,7 +11,15 @@
|
||||
"calcom_explained_new_user": "Terminez la configuration de votre compte {{appName}} ! Vous n'êtes qu'à quelques pas de résoudre tous vos problèmes de planification.",
|
||||
"have_any_questions": "Vous avez des questions ? Nous sommes là pour vous aider.",
|
||||
"reset_password_subject": "{{appName}} : Instructions de réinitialisation de mot de passe",
|
||||
"verify_email_banner_button": "Envoyer un e-mail",
|
||||
"verify_email_subject": "{{appName}} : Vérifiez votre compte",
|
||||
"check_your_email": "Vérifiez votre e-mail",
|
||||
"verify_email_page_body": "Nous avons envoyé un e-mail à {{email}}. Il est important de vérifier votre adresse e-mail pour garantir la meilleure délivrabilité des e-mails et des calendriers de {{appName}}.",
|
||||
"verify_email_banner_body": "Vérifiez votre adresse e-mail pour garantir la meilleure délivrabilité des e-mails et des calendriers",
|
||||
"verify_email_email_header": "Vérifiez votre adresse e-mail",
|
||||
"verify_email_email_button": "Vérifier l'adresse e-mail",
|
||||
"verify_email_email_body": "Veuillez vérifier votre adresse e-mail en cliquant sur le bouton ci-dessous.",
|
||||
"verify_email_email_link_text": "Si vous n'aimez pas cliquer sur les boutons, voici le lien :",
|
||||
"email_sent": "E-mail envoyé avec succès",
|
||||
"event_declined_subject": "Refusé : {{title}} le {{date}}",
|
||||
"event_cancelled_subject": "Annulé : {{title}} le {{date}}",
|
||||
"event_request_declined": "Votre demande d'événement a été refusée",
|
||||
@@ -78,13 +86,11 @@
|
||||
"your_meeting_has_been_booked": "Votre rendez-vous a été réservé",
|
||||
"event_type_has_been_rescheduled_on_time_date": "Votre {{title}} a été replanifié le {{date}}",
|
||||
"event_has_been_rescheduled": "Mise à jour - Votre événement a été replanifié",
|
||||
"request_reschedule_title_attendee": "Demander à replanifier votre réservation",
|
||||
"request_reschedule_subtitle": "{{organizer}} a annulé la réservation et vous a demandé de choisir un autre moment.",
|
||||
"request_reschedule_title_organizer": "Vous avez demandé à {{attendee}} de replanifier la réservation",
|
||||
"request_reschedule_subtitle_organizer": "Vous avez annulé la réservation et {{attendee}} doit choisir un nouveau créneau de réservation.",
|
||||
"rescheduled_event_type_subject": "Demande de replanification envoyée : {{eventType}} avec {{name}} le {{date}}",
|
||||
"requested_to_reschedule_subject_attendee": "Replanification requise : veuillez réserver un nouveau créneau pour {{eventType}} avec {{name}}",
|
||||
"reschedule_reason": "Raison de la replanification",
|
||||
"hi_user_name": "Bonjour {{name}}",
|
||||
"ics_event_title": "{{eventType}} avec {{name}}",
|
||||
"new_event_subject": "Nouvel événement : {{attendeeName}} - {{date}} - {{eventType}}",
|
||||
@@ -111,7 +117,7 @@
|
||||
"team_info": "Informations sur l'équipe",
|
||||
"request_another_invitation_email": "Si vous préférez ne pas utiliser {{toEmail}} comme votre adresse e-mail {{appName}} ou si vous avez déjà un compte {{appName}}, veuillez demander une autre invitation à cette adresse.",
|
||||
"you_have_been_invited": "Vous avez été invité(e) à rejoindre l'équipe {{teamName}}",
|
||||
"user_invited_you": "{{user}} vous a invité(e) à rejoindre l'équipe {{team}} sur {{appName}}",
|
||||
"user_invited_you": "{{user}} vous a invité à rejoindre l'équipe {{team}} sur {{appName}}",
|
||||
"hidden_team_member_title": "Vous êtes masqué(e) dans cette équipe",
|
||||
"hidden_team_member_message": "Votre place n'est pas payée, passez au plan Pro ou faites savoir au propriétaire de l'équipe qu'il peut payer votre place.",
|
||||
"hidden_team_owner_message": "Vous avez besoin d'un compte Pro pour utiliser les équipes, vous êtes masqué(e) jusqu'à ce que vous mettiez à niveau.",
|
||||
@@ -122,6 +128,9 @@
|
||||
"team_upgrade_banner_description": "Merci d'avoir essayé notre nouveau plan Équipes. Nous avons remarqué que votre équipe « {{teamName}} » doit être mise à niveau.",
|
||||
"team_upgrade_banner_action": "Mettre à niveau",
|
||||
"team_upgraded_successfully": "Votre équipe a été mise à niveau avec succès !",
|
||||
"org_upgrade_banner_description": "Merci d'avoir testé notre plan Organisation. Nous avons remarqué que votre organisation « {{teamName}} » doit être mise à niveau.",
|
||||
"org_upgrade_banner_action": "Mettre à niveau",
|
||||
"org_upgraded_successfully": "Votre organisation a été mise à niveau avec succès !",
|
||||
"use_link_to_reset_password": "Utilisez le lien ci-dessous pour réinitialiser votre mot de passe",
|
||||
"hey_there": "Salut,",
|
||||
"forgot_your_password_calcom": "Mot de passe oublié ? - {{appName}}",
|
||||
@@ -232,9 +241,12 @@
|
||||
"done": "Terminé",
|
||||
"all_done": "Terminé !",
|
||||
"all_apps": "Toutes",
|
||||
"all": "Tous",
|
||||
"yours": "Les vôtres",
|
||||
"available_apps": "Applications disponibles",
|
||||
"check_email_reset_password": "Vérifiez vos e-mails. Nous vous avons envoyé un lien pour réinitialiser votre mot de passe.",
|
||||
"finish": "Terminer",
|
||||
"organization_general_description": "Gérez les paramètres de langue et de fuseau horaire de votre équipe.",
|
||||
"few_sentences_about_yourself": "Quelques mots à propos de vous. Ces informations apparaîtront sur votre page publique.",
|
||||
"nearly_there": "C'est bientôt terminé !",
|
||||
"nearly_there_instructions": "Pour finir, une brève description de vous et une photo vous aideront vraiment à obtenir des réservations et à faire savoir aux gens avec qui ils prennent rendez-vous.",
|
||||
@@ -253,7 +265,6 @@
|
||||
"welcome_to_calcom": "Bienvenue sur {{appName}}",
|
||||
"welcome_instructions": "Dites-nous comment vous appeler et indiquez-nous dans quel fuseau horaire vous vous trouvez. Vous pourrez modifier cela plus tard. ",
|
||||
"connect_caldav": "Se connecter au serveur CalDAV (Bêta)",
|
||||
"credentials_stored_and_encrypted": "Vos identifiants seront stockés et chiffrés.",
|
||||
"connect": "Connecter",
|
||||
"try_for_free": "Essayez gratuitement",
|
||||
"create_booking_link_with_calcom": "Créez votre propre lien de réservation avec {{appName}}",
|
||||
@@ -274,7 +285,6 @@
|
||||
"user_needs_to_confirm_or_reject_booking_recurring": "{{user}} doit encore confirmer ou refuser chaque réservation du rendez-vous récurrent.",
|
||||
"meeting_is_scheduled": "Le rendez-vous est planifié",
|
||||
"meeting_is_scheduled_recurring": "Les événements récurrents sont planifiés",
|
||||
"submitted_recurring": "Votre rendez-vous récurrent a été envoyé",
|
||||
"booking_submitted": "Votre réservation a été envoyée",
|
||||
"booking_submitted_recurring": "Votre rendez-vous récurrent a été envoyé",
|
||||
"booking_confirmed": "Votre réservation a été confirmée",
|
||||
@@ -296,13 +306,14 @@
|
||||
"failed": "Échoué",
|
||||
"password_has_been_reset_login": "Votre mot de passe a été réinitialisé. Vous pouvez désormais vous connecter avec votre nouveau mot de passe.",
|
||||
"bookerlayout_title": "Mise en page",
|
||||
"layout": "Mise en page",
|
||||
"bookerlayout_default_title": "Vue par défaut",
|
||||
"bookerlayout_description": "Vous pouvez en sélectionner plusieurs, vos utilisateurs peuvent basculer entre les vues.",
|
||||
"bookerlayout_user_settings_title": "Mise en page de réservation",
|
||||
"bookerlayout_user_settings_description": "Vous pouvez en sélectionner plusieurs, les utilisateurs peuvent basculer entre les vues. Cela peut être remplacé individuellement pour événement.",
|
||||
"bookerlayout_month_view": "Mensuelle",
|
||||
"bookerlayout_week_view": "Hebdomadaire",
|
||||
"bookerlayout_column_view": "Colonne",
|
||||
"bookerlayout_column_view": "Colonnes",
|
||||
"bookerlayout_error_min_one_enabled": "Au moins une mise en page doit être activée.",
|
||||
"bookerlayout_error_default_not_enabled": "La mise en page sélectionnée comme vue par défaut ne fait pas partie des mises en page activées.",
|
||||
"bookerlayout_error_unknown_layout": "La mise en page que vous avez sélectionnée n'est pas une mise en page valide.",
|
||||
@@ -332,7 +343,6 @@
|
||||
"booking_already_accepted_rejected": "Cette réservation a déjà été acceptée ou refusée.",
|
||||
"go_back_home": "Retour à la page d'accueil",
|
||||
"or_go_back_home": "Retour à la page d'accueil",
|
||||
"no_availability": "Indisponible",
|
||||
"no_meeting_found": "Aucun rendez-vous trouvé",
|
||||
"no_meeting_found_description": "Ce rendez-vous n'existe pas. Contactez le propriétaire du rendez-vous pour obtenir un lien mis à jour.",
|
||||
"no_status_bookings_yet": "Aucune réservation {{status}} pour le moment",
|
||||
@@ -383,10 +393,10 @@
|
||||
"full_name": "Nom complet",
|
||||
"browse_api_documentation": "Parcourez la documentation de l'API",
|
||||
"leverage_our_api": "Profitez de notre API pour tout personnaliser et contrôler.",
|
||||
"create_webhook": "Créer un Webhook",
|
||||
"create_webhook": "Créer un webhook",
|
||||
"booking_cancelled": "Réservation annulée",
|
||||
"booking_rescheduled": "Réservation replanifiée",
|
||||
"recording_ready": "Lien de téléchargement d'enregistrement prêt",
|
||||
"recording_ready": "Lien de téléchargement de l'enregistrement prêt",
|
||||
"booking_created": "Réservation créée",
|
||||
"booking_rejected": "Réservation rejetée",
|
||||
"booking_requested": "Réservation demandée",
|
||||
@@ -459,12 +469,11 @@
|
||||
"password_hint_caplow": "Mélange de lettres majuscules et minuscules",
|
||||
"password_hint_min": "7 caractères minimum",
|
||||
"password_hint_admin_min": "Minimum 15 caractères",
|
||||
"password_hint_num": "Contient au moins 1 chiffre",
|
||||
"password_hint_num": "Doit contenir au moins 1 chiffre",
|
||||
"max_limit_allowed_hint": "Doit contenir {{limit}} caractères ou moins",
|
||||
"invalid_password_hint": "Le mot de passe doit contenir au moins {{passwordLength}} caractères, un chiffre et un mélange de lettres majuscules et minuscules.",
|
||||
"incorrect_password": "Le mot de passe est incorrect.",
|
||||
"incorrect_username_password": "Le nom d'utilisateur ou le mot de passe est incorrect.",
|
||||
"24_h": "24 h",
|
||||
"use_setting": "Utiliser le paramètre",
|
||||
"am_pm": "AM/PM",
|
||||
"time_options": "Options de temps",
|
||||
@@ -507,15 +516,11 @@
|
||||
"booking_confirmation": "Confirmez votre {{eventTypeTitle}} avec {{profileName}}",
|
||||
"booking_reschedule_confirmation": "Replanifiez votre {{eventTypeTitle}} avec {{profileName}}",
|
||||
"in_person_meeting": "Rendez-vous en personne",
|
||||
"attendee_in_person": "En personne (adresse du participant)",
|
||||
"in_person": "En personne (adresse de l'organisateur)",
|
||||
"link_meeting": "Rendez-vous avec lien",
|
||||
"phone_call": "Numéro de téléphone du participant",
|
||||
"your_number": "Votre numéro de téléphone",
|
||||
"phone_number": "Numéro de téléphone",
|
||||
"attendee_phone_number": "Numéro de téléphone du participant",
|
||||
"organizer_phone_number": "Numéro de téléphone de l'organisateur",
|
||||
"host_phone_number": "Votre numéro de téléphone",
|
||||
"enter_phone_number": "Saisissez votre numéro de téléphone",
|
||||
"reschedule": "Replanifier",
|
||||
"reschedule_this": "Replanifier à la place",
|
||||
@@ -539,8 +544,12 @@
|
||||
"your_team_updated_successfully": "Votre équipe a été mise à jour avec succès.",
|
||||
"about": "À propos",
|
||||
"team_description": "Quelques mots à propos de votre équipe. Ces informations apparaîtront sur la page publique de votre équipe.",
|
||||
"org_description": "Quelques phrases à propos de votre organisation. Elles apparaîtront sur la page de profil public de votre organisation.",
|
||||
"members": "Membres",
|
||||
"organization_members": "Membres de l'organisation",
|
||||
"member": "Membre",
|
||||
"number_member_one": "{{count}} membre",
|
||||
"number_member_other": "{{count}} membres",
|
||||
"owner": "Propriétaire",
|
||||
"admin": "Administrateur",
|
||||
"administrator_user": "Utilisateur administrateur",
|
||||
@@ -571,6 +580,8 @@
|
||||
"confirm_all": "Confirmer tout",
|
||||
"disband_team": "Dissoudre l'équipe",
|
||||
"disband_team_confirmation_message": "Voulez-vous vraiment dissoudre cette équipe ? Toute personne avec qui vous avez partagé ce lien d'équipe ne pourra plus faire de réservation en l'utilisant.",
|
||||
"disband_org": "Dissoudre l'organisation",
|
||||
"disband_org_confirmation_message": "Voulez-vous vraiment dissoudre cette organisation ? Toutes les équipes et tous les membres seront supprimés.",
|
||||
"remove_member_confirmation_message": "Voulez-vous vraiment supprimer ce membre de l'équipe ?",
|
||||
"confirm_disband_team": "Oui, dissoudre l'équipe",
|
||||
"confirm_remove_member": "Oui, retirer le membre",
|
||||
@@ -641,9 +652,6 @@
|
||||
"new_event_type_btn": "Nouveau type d'événement",
|
||||
"new_event_type_heading": "Créez votre premier type d'événement",
|
||||
"new_event_type_description": "Les types d'événements vous permettent de partager des liens qui affichent vos disponibilités sur votre calendrier et permettent aux personnes de réserver des créneaux.",
|
||||
"new_event_title": "Ajouter un nouveau type d'événement",
|
||||
"new_team_event": "Ajouter un nouveau type d'événement d'équipe",
|
||||
"new_event_description": "Créez un nouveau type d'événement avec lequel les personnes peuvent réserver des créneaux.",
|
||||
"event_type_created_successfully": "Type d'événement {{eventTypeTitle}} créé avec succès",
|
||||
"event_type_updated_successfully": "Type d'événement {{eventTypeTitle}} mis à jour avec succès",
|
||||
"event_type_deleted_successfully": "Type d'événement supprimé avec succès",
|
||||
@@ -684,6 +692,7 @@
|
||||
"create_team_to_get_started": "Créez une équipe pour commencer",
|
||||
"teams": "Équipes",
|
||||
"team": "Équipe",
|
||||
"organization": "Organisation",
|
||||
"team_billing": "Facturation de l'équipe",
|
||||
"team_billing_description": "Gérez la facturation pour votre équipe.",
|
||||
"upgrade_to_flexible_pro_title": "Nous avons modifié la facturation pour les équipes",
|
||||
@@ -781,7 +790,7 @@
|
||||
"slot_interval_default": "Utiliser la durée de l'événement (par défaut)",
|
||||
"delete_event_type": "Supprimer le type d'événement ?",
|
||||
"delete_managed_event_type": "Supprimer le type d'événement géré ?",
|
||||
"delete_event_type_description": "Toute personne avec qui vous avez partagé ce lien ne pourra plus réserver en l'utilisant.",
|
||||
"delete_event_type_description": "Toute personne avec qui vous avez partagé ce lien ne pourra plus réserver avec.",
|
||||
"delete_managed_event_type_description": "<ul><li>Les membres affectés à ce type d'événement verront également leurs types d'événement supprimés.</li><li>Toute personne avec qui ils ont partagé leur lien ne pourra plus réserver en l'utilisant.</li></ul>",
|
||||
"confirm_delete_event_type": "Oui, supprimer",
|
||||
"delete_account": "Supprimer le compte",
|
||||
@@ -812,7 +821,6 @@
|
||||
"automation": "Automatisation",
|
||||
"configure_how_your_event_types_interact": "Configurez la manière dont vos types d'événements doivent interagir avec vos calendriers.",
|
||||
"toggle_calendars_conflict": "Activez/désactivez les calendriers pour lesquels vous souhaitez vérifier les conflits afin d'éviter les doubles réservations.",
|
||||
"select_destination_calendar": "Créer des événements dans :",
|
||||
"connect_additional_calendar": "Connecter un calendrier supplémentaire",
|
||||
"calendar_updated_successfully": "Calendrier mis à jour avec succès",
|
||||
"conferencing": "Visioconférence",
|
||||
@@ -846,7 +854,6 @@
|
||||
"number_apps_other": "{{count}} applications",
|
||||
"trending_apps": "Applications populaires",
|
||||
"most_popular": "Les plus populaires",
|
||||
"explore_apps": "Applications {{category}}",
|
||||
"installed_apps": "Apps installées",
|
||||
"free_to_use_apps": "Gratuit",
|
||||
"no_category_apps": "Aucune application {{category}}",
|
||||
@@ -858,10 +865,10 @@
|
||||
"no_category_apps_description_other": "Ajoutez n'importe quel autre type d'application pour faire toutes sortes de choses.",
|
||||
"no_category_apps_description_web3": "Ajoutez une application Web3 pour vos pages de réservation.",
|
||||
"installed_app_calendar_description": "Définissez les calendriers pour vérifier les conflits afin d'éviter les doubles réservations.",
|
||||
"installed_app_conferencing_description": "Ajoutez vos applications de visioconférence préférées pour vos rendez-vous.",
|
||||
"installed_app_payment_description": "Configurez les services de traitement de paiement à utiliser lors de la facturation de vos clients.",
|
||||
"installed_app_analytics_description": "Configurez les applications d'analyse à utiliser pour vos pages de réservation.",
|
||||
"installed_app_other_description": "Toutes vos applications installées à partir d'autres catégories.",
|
||||
"installed_app_conferencing_description": "Configurez les applications de conférence à utiliser.",
|
||||
"installed_app_automation_description": "Configurez les applications d'automatisation à utiliser.",
|
||||
"installed_app_web3_description": "Configurez les applications Web3 à utiliser pour vos pages de réservation.",
|
||||
"analytics": "Analytiques",
|
||||
@@ -884,7 +891,6 @@
|
||||
"terms_of_service": "Conditions d'utilisation",
|
||||
"remove": "Supprimer",
|
||||
"add": "Ajouter",
|
||||
"installed_one": "Installée",
|
||||
"installed_other": "{{count}} installation(s)",
|
||||
"verify_wallet": "Vérifier le portefeuille",
|
||||
"create_events_on": "Créer des événements dans :",
|
||||
@@ -898,7 +904,7 @@
|
||||
"the_infrastructure_plan": "Le plan d'infrastructure est basé sur l'utilisation et propose des réductions adaptées aux startups.",
|
||||
"prisma_studio_tip": "Créer un compte via Prisma Studio",
|
||||
"prisma_studio_tip_description": "Découvrez comment configurer votre premier utilisateur",
|
||||
"contact_sales": "Contacter les ventes",
|
||||
"contact_sales": "Contacter le service commercial",
|
||||
"error_404": "Erreur 404",
|
||||
"default": "Par défaut",
|
||||
"set_to_default": "Définir par défaut",
|
||||
@@ -912,7 +918,6 @@
|
||||
"availability_updated_successfully": "Planning {{scheduleName}} mis à jour avec succès",
|
||||
"schedule_deleted_successfully": "Planning supprimé avec succès",
|
||||
"default_schedule_name": "Heures de travail",
|
||||
"member_default_schedule": "Planning par défaut du membre",
|
||||
"new_schedule_heading": "Créer un planning de disponibilité",
|
||||
"new_schedule_description": "La création de plannings de disponibilité vous permet de gérer la disponibilité pour tous les types d'événements. Ils peuvent être appliqués à un ou plusieurs types d'événements.",
|
||||
"requires_ownership_of_a_token": "Nécessite la propriété d'un token appartenant à l'adresse suivante :",
|
||||
@@ -930,7 +935,7 @@
|
||||
"offer_seats": "Proposer des places",
|
||||
"offer_seats_description": "Proposez des places de réservation. Cela désactive automatiquement les réservations d'invités et d'opt-in.",
|
||||
"seats_available_one": "Place disponible",
|
||||
"seats_available_other": "places disponibles",
|
||||
"seats_available_other": "Places disponibles",
|
||||
"number_of_seats": "Nombre de places par réservation",
|
||||
"enter_number_of_seats": "Saisir le nombre de sièges",
|
||||
"you_can_manage_your_schedules": "Vous pouvez gérer vos disponibilités sur la page Disponibilité.",
|
||||
@@ -949,8 +954,6 @@
|
||||
"api_key_no_note": "Clé API sans nom",
|
||||
"api_key_never_expires": "Cette clé API n'a pas de date d'expiration",
|
||||
"edit_api_key": "Modifier la clé API",
|
||||
"never_expire_key": "N'expire jamais",
|
||||
"delete_api_key": "Révoquer la clé API",
|
||||
"success_api_key_created": "Clé API créée avec succès",
|
||||
"success_api_key_edited": "Clé API mise à jour avec succès",
|
||||
"create": "Créer",
|
||||
@@ -991,7 +994,6 @@
|
||||
"event_location_changed": "Mise à jour - Votre événement a changé de lieu",
|
||||
"location_changed_event_type_subject": "Lieu modifié : {{eventType}} avec {{name}} le {{date}}",
|
||||
"current_location": "Lieu actuel",
|
||||
"user_phone": "Votre numéro de téléphone",
|
||||
"new_location": "Nouveau lieu",
|
||||
"session": "Session",
|
||||
"session_description": "Contrôlez la session de votre compte.",
|
||||
@@ -1017,7 +1019,6 @@
|
||||
"zapier_setup_instructions": "<0>Connectez-vous à votre compte Zapier et créez un nouveau Zap.</0><1>Sélectionnez Cal.com comme application Trigger. Choisissez également un événement Trigger.</1><2>Choisissez votre compte, puis saisissez votre clé API unique.</2><3>Testez votre Trigger.</3><4>Vous êtes prêt(e) !</4>",
|
||||
"install_zapier_app": "Veuillez d'abord installer l'application Zapier dans l'App Store.",
|
||||
"connect_apple_server": "Se connecter au serveur d'Apple",
|
||||
"connect_caldav_server": "Se connecter au serveur CalDAV (Bêta)",
|
||||
"calendar_url": "Lien du calendrier",
|
||||
"apple_server_generate_password": "Générez un mot de passe pour application à utiliser avec {{appName}} sur",
|
||||
"credentials_stored_encrypted": "Vos identifiants seront stockés et chiffrés.",
|
||||
@@ -1049,7 +1050,6 @@
|
||||
"go_to": "Aller à : ",
|
||||
"zapier_invite_link": "Lien d'invitation Zapier",
|
||||
"meeting_url_provided_after_confirmed": "Un lien de rendez-vous sera créé une fois l'événement confirmé.",
|
||||
"attendees_name": "Nom du participant",
|
||||
"dynamically_display_attendee_or_organizer": "Affiche dynamiquement le nom du participant pour vous ou votre nom s'il est vu par le participant",
|
||||
"event_location": "Lieu de l'événement",
|
||||
"reschedule_optional": "Raison de la replanification (facultatif)",
|
||||
@@ -1124,7 +1124,6 @@
|
||||
"add_exchange2016": "Connecter le serveur Exchange 2016",
|
||||
"custom_template": "Modèle personnalisé",
|
||||
"email_body": "Corps",
|
||||
"subject": "Objet",
|
||||
"text_message": "Message texte",
|
||||
"specific_issue": "Vous avez un problème particulier ?",
|
||||
"browse_our_docs": "parcourir notre documentation",
|
||||
@@ -1152,12 +1151,9 @@
|
||||
"new_seat_title": "Quelqu'un s'est ajouté à un événement",
|
||||
"variable": "Variable",
|
||||
"event_name_variable": "Nom de l'événement",
|
||||
"organizer_name_variable": "Nom de l'organisateur",
|
||||
"attendee_name_variable": "Nom du participant",
|
||||
"event_date_variable": "Date de l'événement",
|
||||
"event_time_variable": "Heure de l'événement",
|
||||
"location_variable": "Lieu",
|
||||
"additional_notes_variable": "Notes supplémentaires",
|
||||
"app_upgrade_description": "Pour pouvoir utiliser cette fonctionnalité, vous devez passer à un compte Pro.",
|
||||
"invalid_number": "Numéro de téléphone invalide",
|
||||
"navigate": "Naviguer",
|
||||
@@ -1197,10 +1193,10 @@
|
||||
"connect_your_calendar_and_link": "Vous pouvez connecter votre calendrier depuis <1>ici</1>.",
|
||||
"default_calendar_selected": "Calendrier par défaut",
|
||||
"hide_from_profile": "Masquer du profil",
|
||||
"event_setup_tab_title": "Configuration de l'événement",
|
||||
"event_setup_tab_title": "Configuration",
|
||||
"event_limit_tab_title": "Limites",
|
||||
"event_limit_tab_description": "Fréquence de réservation",
|
||||
"event_advanced_tab_description": "Paramètres du calendrier et plus...",
|
||||
"event_advanced_tab_description": "Paramètres du calendrier, etc.",
|
||||
"event_advanced_tab_title": "Avancé",
|
||||
"event_setup_multiple_duration_error": "Configuration de l'événement : plusieurs durées requièrent au moins une option.",
|
||||
"event_setup_multiple_duration_default_error": "Configuration de l'événement : veuillez sélectionner une durée par défaut valide.",
|
||||
@@ -1251,7 +1247,6 @@
|
||||
"recurring_event_tab_description": "Configurer une disponibilité récurrente",
|
||||
"today": "aujourd'hui",
|
||||
"appearance": "Apparence",
|
||||
"appearance_subtitle": "Gérez les paramètres d'apparence de vos réservations.",
|
||||
"my_account": "Mon compte",
|
||||
"general": "Général",
|
||||
"calendars": "Calendriers",
|
||||
@@ -1271,7 +1266,7 @@
|
||||
"conferencing_description": "Ajoutez vos applications de visioconférence préférées pour vos rendez-vous.",
|
||||
"add_conferencing_app": "Ajouter une application de conférence",
|
||||
"password_description": "Gérez les paramètres pour les mots de passe de votre compte.",
|
||||
"2fa_description": "Gérez les paramètres pour les mots de passe de votre compte.",
|
||||
"set_up_two_factor_authentication": "Configurez votre double authentification",
|
||||
"we_just_need_basic_info": "Nous avons juste besoin de quelques informations de base pour configurer votre profil.",
|
||||
"skip": "Ignorer",
|
||||
"do_this_later": "Plus tard",
|
||||
@@ -1295,7 +1290,6 @@
|
||||
"event_date_info": "Date de l'événement",
|
||||
"event_time_info": "Heure de début de l'événement",
|
||||
"location_info": "Lieu de l'événement",
|
||||
"organizer_name_info": "Votre nom",
|
||||
"additional_notes_info": "Notes supplémentaires de la réservation",
|
||||
"attendee_name_info": "Nom du participant",
|
||||
"to": "À",
|
||||
@@ -1312,8 +1306,10 @@
|
||||
"for_a_maximum_of": "Pour un maximum de",
|
||||
"event_one": "événement",
|
||||
"event_other": "événements",
|
||||
"profile_team_description": "Gérez les paramètres de votre profil d'équipe.",
|
||||
"profile_team_description": "Gérez les paramètres du profil de votre équipe.",
|
||||
"profile_org_description": "Gérez les paramètres de votre profil d'organisation.",
|
||||
"members_team_description": "Utilisateurs présents dans le groupe.",
|
||||
"organization_description": "Gérez les administrateurs et les membres de votre organisation.",
|
||||
"team_url": "Lien de l'équipe",
|
||||
"team_members": "Membres de l'équipe",
|
||||
"more": "Plus",
|
||||
@@ -1354,23 +1350,21 @@
|
||||
"routing_forms_send_email_owner": "Envoyer un e-mail au propriétaire",
|
||||
"routing_forms_send_email_owner_description": "Envoie un e-mail au propriétaire lorsque le formulaire est soumis",
|
||||
"add_new_form": "Ajouter un nouveau formulaire",
|
||||
"add_new_team_form": "Ajouter un nouveau formulaire à votre équipe",
|
||||
"create_your_first_route": "Créez votre première route",
|
||||
"route_to_the_right_person": "Acheminez vers la bonne personne en fonction des réponses à votre formulaire.",
|
||||
"form_description": "Créez votre formulaire pour rediriger un utilisateur.",
|
||||
"copy_link_to_form": "Copier le lien vers le formulaire",
|
||||
"theme": "Apparence",
|
||||
"theme_applies_note": "Ceci s'applique uniquement à vos pages publiques de réservation.",
|
||||
"theme_light": "Clair",
|
||||
"theme_dark": "Sombre",
|
||||
"theme_system": "Automatique",
|
||||
"add_a_team": "Ajouter une équipe",
|
||||
"add_webhook_description": "Recevez les données de rendez-vous en temps réel lorsque quelque chose se passe sur {{appName}}.",
|
||||
"triggers_when": "Se déclenche quand",
|
||||
"test_webhook": "Veuillez faire un test de ping avant de le créer.",
|
||||
"enable_webhook": "Activer le webhook",
|
||||
"add_webhook": "Ajouter un Webhook",
|
||||
"add_webhook": "Ajouter un webhook",
|
||||
"webhook_edited_successfully": "Webhook enregistré",
|
||||
"webhooks_description": "Recevez les données de rendez-vous en temps réel lorsque quelque chose se passe sur {{appName}}.",
|
||||
"api_keys_description": "Générez des clés API pour accéder à votre propre compte.",
|
||||
"new_api_key": "Nouvelle clé API",
|
||||
"active": "actif",
|
||||
@@ -1412,11 +1406,7 @@
|
||||
"billing_freeplan_title": "Vous êtes actuellement sur le plan Gratuit",
|
||||
"billing_freeplan_description": "Nous travaillons mieux en équipe. Élargissez vos workflows avec le Round-Robin et les événements collectifs et produisez des formulaires de routage avancés.",
|
||||
"billing_freeplan_cta": "Essayer maintenant",
|
||||
"billing_manage_details_title": "Affichez et gérez vos informations de facturation",
|
||||
"billing_manage_details_description": "Affichez et modifiez vos informations de facturation, et annulez votre abonnement.",
|
||||
"billing_portal": "Portail de facturation",
|
||||
"billing_help_title": "Besoin d'autre chose ?",
|
||||
"billing_help_description": "Si vous avez besoin d'aide pour la facturation, notre équipe d'assistance est là pour vous aider.",
|
||||
"billing_help_cta": "Contacter l'assistance",
|
||||
"ignore_special_characters_booking_questions": "Ignorez les caractères spéciaux dans l'identifiant de votre question de réservation, utilisez uniquement des lettres et des chiffres.",
|
||||
"retry": "Réessayer",
|
||||
@@ -1424,7 +1414,6 @@
|
||||
"calendar_connection_fail": "Échec de la connexion au calendrier",
|
||||
"booking_confirmation_success": "Confirmation de la réservation réussie",
|
||||
"booking_rejection_success": "Refus de la réservation réussi",
|
||||
"booking_confirmation_fail": "Échec de la confirmation de la réservation",
|
||||
"booking_tentative": "Cette réservation est provisoire",
|
||||
"booking_accept_intent": "Oups, je veux accepter",
|
||||
"we_wont_show_again": "Nous n'afficherons plus ceci",
|
||||
@@ -1447,7 +1436,6 @@
|
||||
"new_event_type_availability": "Disponibilités de {{eventTypeTitle}}",
|
||||
"error_editing_availability": "Erreur lors de la modification des disponibilités",
|
||||
"dont_have_permission": "Vous n'avez pas la permission d'accéder à cette ressource.",
|
||||
"saml_config": "Authentification unique",
|
||||
"saml_configuration_placeholder": "Veuillez coller les métadonnées SAML de votre fournisseur d'identité ici.",
|
||||
"saml_email_required": "Veuillez saisir une adresse e-mail pour que nous puissions trouver votre fournisseur d'identité SAML",
|
||||
"saml_sp_title": "Informations sur le fournisseur de services",
|
||||
@@ -1456,7 +1444,6 @@
|
||||
"saml_sp_entity_id": "Identifiant SP Entity",
|
||||
"saml_sp_acs_url_copied": "Lien ACS copié !",
|
||||
"saml_sp_entity_id_copied": "Identifiant SP Entity copié !",
|
||||
"saml_btn_configure": "Configurer",
|
||||
"add_calendar": "Ajouter un calendrier",
|
||||
"limit_future_bookings": "Limiter les réservations futures",
|
||||
"limit_future_bookings_description": "Limitez jusqu'à quand cet événement peut être réservé dans le futur.",
|
||||
@@ -1467,9 +1454,10 @@
|
||||
"yearly": "Annuellement",
|
||||
"checkout": "Paiement",
|
||||
"your_team_disbanded_successfully": "Votre équipe a bien été dissoute",
|
||||
"your_org_disbanded_successfully": "Votre organisation a bien été dissoute",
|
||||
"error_creating_team": "Erreur lors de la création de l'équipe",
|
||||
"you": "Vous",
|
||||
"send_email": "Envoyer un e-mail",
|
||||
"resend_email": "Renvoyer l’e-mail",
|
||||
"member_already_invited": "Le membre a déjà été invité",
|
||||
"enter_email_or_username": "Saisissez une adresse e-mail ou un nom d'utilisateur",
|
||||
"team_name_taken": "Ce nom est déjà pris",
|
||||
@@ -1510,7 +1498,7 @@
|
||||
"event_replaced_notice": "Un administrateur a remplacé l'un de vos types d'événements",
|
||||
"email_subject_slug_replacement": "Un administrateur d'équipe a remplacé votre événement /{{slug}}",
|
||||
"email_body_slug_replacement_notice": "Un administrateur de l'équipe <strong>{{teamName}}</strong> a remplacé votre type d'événement <strong>/{{slug}}</strong> par un type d'événement géré qu'il contrôle.",
|
||||
"email_body_slug_replacement_info": "Votre lien continuera à fonctionner, mais certains de ses paramètres peuvent avoir changé. Vous pouvez l'examiner dans les types d'événements.",
|
||||
"email_body_slug_replacement_info": "Votre lien continuera de fonctionner, mais certains de ses paramètres peuvent avoir changé. Vous pouvez l'examiner dans les types d'événements.",
|
||||
"email_body_slug_replacement_suggestion": "Si vous avez des questions sur le type d'événement, veuillez contacter votre administrateur.<br /><br />Bonne planification, <br />L'équipe Cal.com",
|
||||
"disable_payment_app": "L'administrateur a désactivé {{appName}} qui affecte votre type d'événement {{title}}. Les participants sont toujours en mesure de réserver ce type d'événement, mais ne seront pas invités à payer. Vous pouvez masquer le type d'événement pour l'empêcher jusqu'à ce que votre administrateur réactive votre moyen de paiement.",
|
||||
"payment_disabled_still_able_to_book": "Les participants sont toujours en mesure de réserver ce type d'événement, mais ne seront pas invités à payer. Vous pouvez masquer le type d'événement pour l'empêcher jusqu'à ce que votre administrateur réactive votre mode de paiement.",
|
||||
@@ -1541,7 +1529,7 @@
|
||||
"add_an_option": "Ajouter une option",
|
||||
"radio": "Radio",
|
||||
"google_meet_warning": "Pour utiliser Google Meet, vous devez définir votre calendrier de destination sur un calendrier Google",
|
||||
"individual": "Individuel",
|
||||
"individual": "Particulier",
|
||||
"all_bookings_filter_label": "Toutes les réservations",
|
||||
"all_users_filter_label": "Tous les utilisateurs",
|
||||
"your_bookings_filter_label": "Vos réservations",
|
||||
@@ -1572,7 +1560,7 @@
|
||||
"send_code": "Envoyer le code",
|
||||
"number_verified": "Numéro vérifié",
|
||||
"create_your_first_team_webhook_description": "Créez votre premier webhook pour ce type d'événement d'équipe",
|
||||
"create_webhook_team_event_type": "Créer un webhook pour ce type d'événement d'équipe",
|
||||
"create_webhook_team_event_type": "Créez un webhook pour ce type d'événement d'équipe.",
|
||||
"disable_success_page": "Désactiver la page de validation (fonctionne uniquement si vous avez un lien de redirection)",
|
||||
"invalid_admin_password": "Vous êtes administrateur, mais votre mot de passe ne fait pas au moins 15 caractères ou la double authentification n'est pas définie",
|
||||
"change_password_admin": "Changez le mot de passe pour obtenir l'accès administrateur",
|
||||
@@ -1639,12 +1627,11 @@
|
||||
"delete_sso_configuration_confirmation": "Oui, supprimer la configuration {{connectionType}}",
|
||||
"delete_sso_configuration_confirmation_description": "Voulez-vous vraiment supprimer la configuration {{connectionType}} ? Les membres de votre équipe utilisant la connexion {{connectionType}} ne pourront plus accéder à Cal.com.",
|
||||
"organizer_timezone": "Fuseau horaire de l'organisateur",
|
||||
"email_no_user_cta": "Créez votre compte",
|
||||
"email_user_cta": "Voir l'invitation",
|
||||
"email_no_user_invite_heading": "Vous avez été invité(e) à rejoindre une équipe sur {{appName}}",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} a été invité à rejoindre son équipe sur {{appName}}. {{appName}} est le planificateur d'événements qui vous permet, à vous et à votre équipe, de planifier des rendez-vous sans les allers-retours par e-mail.",
|
||||
"email_user_invite_subheading": "{{invitedBy}} vous a invité à rejoindre son équipe « {{teamName}} » sur {{appName}}. {{appName}} est le planificateur d'événements qui vous permet, à vous et à votre équipe, de planifier des réunions sans les allers-retours par e-mail.",
|
||||
"email_no_user_invite_steps_intro": "Nous vous guiderons à travers quelques étapes courtes et vous profiterez d'une planification sans stress avec votre équipe en un rien de temps.",
|
||||
"email_no_user_invite_heading": "Vous avez été invité à rejoindre une {{entity}} {{appName}}",
|
||||
"email_no_user_invite_subheading": "{{invitedBy}} vous a invité à rejoindre son équipe sur {{appName}}. {{appName}} est le planificateur d'événements qui vous permet à vous et à votre équipe d'organiser des rendez-vous sans échanges d'e-mails.",
|
||||
"email_user_invite_subheading": "{{invitedBy}} vous a invité à rejoindre son {{entity}} « {{teamName}} » sur {{appName}}. {{appName}} est le planificateur d'événements qui vous permet à vous et à votre {{entity}} d'organiser des rendez-vous sans échanges d'e-mails.",
|
||||
"email_no_user_invite_steps_intro": "Nous vous guiderons à travers quelques étapes courtes et vous profiterez d'une planification sans stress avec votre {{entity}} en un rien de temps.",
|
||||
"email_no_user_step_one": "Choisissez votre nom d'utilisateur",
|
||||
"email_no_user_step_two": "Connectez votre compte de calendrier",
|
||||
"email_no_user_step_three": "Définissez vos disponibilités",
|
||||
@@ -1655,6 +1642,8 @@
|
||||
"scheduler": "{Scheduler}",
|
||||
"no_workflows": "Aucun workflow",
|
||||
"change_filter": "Changez le filtre pour voir vos workflows personnels et d'équipe.",
|
||||
"change_filter_common": "Changez le filtre pour voir les résultats.",
|
||||
"no_results_for_filter": "Aucun résultat pour le filtre",
|
||||
"recommended_next_steps": "Étapes suivantes recommandées",
|
||||
"create_a_managed_event": "Créer un type d'événement géré",
|
||||
"meetings_are_better_with_the_right": "Les rendez-vous sont meilleurs avec les bons membres d'équipe. Invitez-les maintenant.",
|
||||
@@ -1667,9 +1656,9 @@
|
||||
"attendee_no_longer_attending": "Un participant ne participe plus à votre événement",
|
||||
"attendee_no_longer_attending_subtitle": "{{name}} a annulé. Cela signifie qu'une place s'est libérée pour ce créneau horaire",
|
||||
"create_event_on": "Créer un événement dans",
|
||||
"create_routing_form_on": "Créer un formulaire de routage sur",
|
||||
"default_app_link_title": "Définir un lien d'application par défaut",
|
||||
"default_app_link_description": "Définir un lien d'application par défaut permet à tous les nouveaux types d'événements d'utiliser le lien d'application que vous avez défini.",
|
||||
"change_default_conferencing_app": "Définir par défaut",
|
||||
"organizer_default_conferencing_app": "Application par défaut de l'organisateur",
|
||||
"under_maintenance": "En cours de maintenance",
|
||||
"under_maintenance_description": "L'équipe {{appName}} effectue une maintenance planifiée. Si vous avez des questions, veuillez contacter l'assistance.",
|
||||
@@ -1685,11 +1674,10 @@
|
||||
"booking_confirmation_failed": "Échec de la confirmation de la réservation",
|
||||
"not_enough_seats": "Pas assez de places",
|
||||
"form_builder_field_already_exists": "Un champ avec ce nom existe déjà",
|
||||
"form_builder_field_add_subtitle": "Personnalisez les questions posées sur la page de réservation.",
|
||||
"show_on_booking_page": "Afficher sur la page de réservation",
|
||||
"get_started_zapier_templates": "Démarrer avec les modèles Zapier",
|
||||
"team_is_unpublished": "{{team}} n'est pas publiée",
|
||||
"team_is_unpublished_description": "Ce lien d'équipe n'est actuellement pas disponible. Veuillez contacter le propriétaire de l'équipe ou lui demander de le publier.",
|
||||
"team_is_unpublished_description": "Ce lien d'{{entity}} n'est actuellement pas disponible. Veuillez contacter le propriétaire de l'{{entity}} ou lui demander de le publier.",
|
||||
"team_member": "Membre d'équipe",
|
||||
"a_routing_form": "Un formulaire de routage",
|
||||
"form_description_placeholder": "Description du formulaire",
|
||||
@@ -1728,6 +1716,7 @@
|
||||
"switch_monthly": "Passer en vue mensuelle",
|
||||
"switch_weekly": "Passer en vue hebdomadaire",
|
||||
"switch_multiday": "Passer en vue journalière",
|
||||
"switch_columnview": "Passer en vue colonnes",
|
||||
"num_locations": "{{num}} options de lieu",
|
||||
"select_on_next_step": "Sélectionner à l'étape suivante",
|
||||
"this_meeting_has_not_started_yet": "Ce rendez-vous n'a pas encore commencé",
|
||||
@@ -1738,7 +1727,6 @@
|
||||
"verification_code": "Code de vérification",
|
||||
"can_you_try_again": "Pouvez-vous réessayer avec un autre créneau ?",
|
||||
"verify": "Vérifier",
|
||||
"timezone_variable": "Fuseau horaire",
|
||||
"timezone_info": "Le fuseau horaire du destinataire",
|
||||
"event_end_time_variable": "Heure de fin de l'événement",
|
||||
"event_end_time_info": "L'heure de fin de l'événement",
|
||||
@@ -1787,7 +1775,6 @@
|
||||
"events_rescheduled": "Événements replanifiés",
|
||||
"from_last_period": "depuis la dernière période",
|
||||
"from_to_date_period": "De : {{startDate}} À : {{endDate}}",
|
||||
"analytics_for_organisation": "Statistiques",
|
||||
"subtitle_analytics": "En savoir plus sur l'activité de votre équipe",
|
||||
"redirect_url_warning": "L'ajout d'une redirection désactivera la page de succès. Assurez-vous de mentionner « Réservation confirmée » sur votre page de succès personnalisée.",
|
||||
"event_trends": "Tendances de l'événement",
|
||||
@@ -1815,8 +1802,8 @@
|
||||
"acknowledge_booking_no_show_fee": "Je reconnais que si je ne participe pas à cet événement, des frais d'absence de {{amount, currency}} seront appliqués à ma carte.",
|
||||
"card_details": "Détails de la carte",
|
||||
"seats_and_no_show_fee_error": "Il n'est pas possible d'activer les places et de facturer des frais d'absence pour le moment",
|
||||
"complete_your_booking": "Terminer votre réservation",
|
||||
"complete_your_booking_subject": "Terminer votre réservation : {{title}} le {{date}}",
|
||||
"complete_your_booking": "Terminez votre réservation",
|
||||
"complete_your_booking_subject": "Terminez votre réservation : {{title}} le {{date}}",
|
||||
"confirm_your_details": "Confirmez vos coordonnées",
|
||||
"copy_invite_link": "Copier le lien d'invitation",
|
||||
"edit_invite_link": "Modifier les paramètres du lien",
|
||||
@@ -1827,7 +1814,6 @@
|
||||
"one_day": "1 jour",
|
||||
"seven_days": "7 jours",
|
||||
"thirty_days": "30 jours",
|
||||
"never_expire": "N'expire jamais",
|
||||
"team_invite_received": "Vous avez été invité(e) à rejoindre {{teamName}}",
|
||||
"currency_string": "{{amount, currency}}",
|
||||
"charge_card_dialog_body": "Vous êtes sur le point de facturer {{amount, currency}} au participant. Voulez-vous vraiment continuer ?",
|
||||
@@ -1835,16 +1821,18 @@
|
||||
"payment_app_commission": "Exiger un paiement ({{paymentFeePercentage}} % + {{fee, currency}} de commission par transaction)",
|
||||
"email_invite_team": "{{email}} a été invité",
|
||||
"email_invite_team_bulk": "{{userCount}} utilisateurs ont été invités",
|
||||
"error_collecting_card": "Erreur lors de la collecte de la carte",
|
||||
"error_collecting_card": "Erreur lors de la récupération de la carte",
|
||||
"image_size_limit_exceed": "L'image téléchargée ne doit pas dépasser 5 Mo",
|
||||
"unauthorized_workflow_error_message": "{{errorCode}} : Vous n'êtes pas autorisé à activer ou désactiver ce workflow",
|
||||
"inline_embed": "Intégration en ligne",
|
||||
"load_inline_content": "Charge votre type d'événement directement en ligne avec le contenu de votre site web.",
|
||||
"floating_pop_up_button": "Bouton pop-up flottant",
|
||||
"load_inline_content": "Charge votre type d'événement directement dans le contenu de votre site web.",
|
||||
"floating_pop_up_button": "Bouton flottant",
|
||||
"floating_button_trigger_modal": "Place un bouton flottant sur votre site qui déclenche une modale avec votre type d'événement.",
|
||||
"pop_up_element_click": "Clic sur un élément",
|
||||
"open_dialog_with_element_click": "Ouvre votre boîte de dialogue Cal lorsque quelqu'un clique sur un élément.",
|
||||
"need_help_embedding": "Besoin d'aide ? Consultez nos guides pour intégrer Cal sur Wix, Squarespace ou WordPress, consultez nos questions fréquentes ou explorez les options d'intégration avancées.",
|
||||
"invite_as": "Inviter en tant que",
|
||||
"form_updated_successfully": "Formulaire mis à jour avec succès.",
|
||||
"email_not_cal_member_cta": "Rejoignez votre équipe",
|
||||
"disable_attendees_confirmation_emails": "Désactiver les e-mails de confirmation par défaut pour les participants",
|
||||
"disable_attendees_confirmation_emails_description": "Au moins un workflow est actif sur ce type d'événement qui envoie un e-mail aux participants lorsque l'événement est réservé.",
|
||||
"disable_host_confirmation_emails": "Désactiver les e-mails de confirmation par défaut pour l'hôte",
|
||||
@@ -1852,8 +1840,51 @@
|
||||
"add_an_override": "Ajouter une superposition",
|
||||
"import_from_google_workspace": "Importer des utilisateurs depuis Google Workspace",
|
||||
"connect_google_workspace": "Connecter Google Workspace",
|
||||
"google_workspace_admin_tooltip": "Vous devez être un administrateur d'espace de travail pour utiliser cette fonctionnalité",
|
||||
"first_event_type_webhook_description": "Créez votre premier webhook pour ce type d'événement",
|
||||
"create_for": "Créer pour",
|
||||
"setup_organization": "Configurer une organisation",
|
||||
"organization_banner_description": "Créez un environnement où vos équipes peuvent créer des applications partagées, des workflows et des types d'événements avec une planification Round-Robin et collective.",
|
||||
"organization_banner_title": "Gérer les organisations avec plusieurs équipes",
|
||||
"set_up_your_organization": "Configurer votre organisation",
|
||||
"organizations_description": "Les organisations sont des environnements partagés dans lesquels les équipes peuvent créer des types d'événements partagés, des applications, des workflows, etc.",
|
||||
"organization_url_taken": "Ce lien est déjà pris",
|
||||
"must_enter_organization_name": "Vous devez entrer un nom d'organisation",
|
||||
"must_enter_organization_admin_email": "Vous devez entrer l'adresse e-mail de votre organisation",
|
||||
"admin_email": "Adresse e-mail de votre organisation",
|
||||
"admin_username": "Nom d'utilisateur de l'administrateur",
|
||||
"organization_name": "Nom de l'organisation",
|
||||
"organization_url": "Lien de l'organisation",
|
||||
"organization_verify_header": "Vérifier l'adresse e-mail de votre organisation",
|
||||
"organization_verify_email_body": "Veuillez utiliser le code ci-dessous pour vérifier votre adresse e-mail et continuer à configurer votre organisation.",
|
||||
"additional_url_parameters": "Paramètres d'URL supplémentaires",
|
||||
"about_your_organization": "À propos de votre organisation",
|
||||
"about_your_organization_description": "Les organisations sont des environnements partagés dans lesquels vous pouvez créer plusieurs équipes avec des membres partagés, des types d'événements, des applications, des workflows, etc.",
|
||||
"create_your_teams": "Créer vos équipes",
|
||||
"create_your_teams_description": "Commencez à planifier ensemble en ajoutant les membres de votre équipe à votre organisation",
|
||||
"invite_organization_admins": "Inviter les administrateurs de votre organisation",
|
||||
"invite_organization_admins_description": "Ces administrateurs auront accès à toutes les équipes de votre organisation. Vous pouvez ajouter des administrateurs et des membres d'équipe plus tard.",
|
||||
"set_a_password": "Définir un mot de passe",
|
||||
"set_a_password_description": "Cela créera un nouveau compte utilisateur avec l'adresse e-mail de votre organisation et ce mot de passe.",
|
||||
"organization_logo": "Logo de l'organisation",
|
||||
"organization_about_description": "Quelques phrases à propos de votre organisation. Elles apparaîtront sur la page de profil public de votre organisation.",
|
||||
"ill_do_this_later": "Je le ferai plus tard",
|
||||
"verify_your_email": "Vérifier votre adresse e-mail",
|
||||
"enter_digit_code": "Entrez le code à 6 chiffres que nous avons envoyé à {{email}}",
|
||||
"verify_email_organization": "Vérifiez votre adresse e-mail pour créer une organisation",
|
||||
"code_provided_invalid": "Le code fourni n'est pas valide, veuillez réessayer",
|
||||
"email_already_used": "L'adresse e-mail est déjà utilisée",
|
||||
"duplicated_slugs_warning": "Les équipes suivantes n'ont pas pu être créées en raison de slugs identiques : {{slugs}}",
|
||||
"team_names_empty": "Les noms d'équipe ne peuvent pas être vides",
|
||||
"team_names_repeated": "Les noms d'équipe ne peuvent pas être répétés",
|
||||
"user_belongs_organization": "L'utilisateur appartient à une organisation",
|
||||
"no_teams_yet": "Cette organisation n'a pas encore d'équipe",
|
||||
"no_teams_yet_description": "si vous êtes administrateur, assurez-vous de créer des équipes à afficher ici.",
|
||||
"set_up": "Configurer",
|
||||
"set_up_your_profile": "Configurer votre profil",
|
||||
"set_up_your_profile_description": "Faites savoir aux gens qui vous êtes au sein de {{orgName}} et quand ils interagissent avec votre lien public.",
|
||||
"my_profile": "Mon profil",
|
||||
"my_settings": "Mes paramètres",
|
||||
"sender_id_info": "Nom ou numéro affiché comme expéditeur d'un SMS (certains pays n'autorisent pas les ID d'expéditeur alphanumériques)",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Ajoutez vos nouvelles chaînes ci-dessus ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user