Compare commits

...
112 Commits
Author SHA1 Message Date
Alex van Andel 1929d5c7d4 v3.0.2
release.yml / release (push) Canceled after 0s
2023-06-19 13:33:13 +02:00
Papageorgiou Nikos 8ae54cd7cc fix: Storybook build and fix cal brand colors (#9588)
Storybook failed with satisfies operator
Fix cal brand colors in storybook
2023-06-19 13:28:49 +02:00
Hariom Balhara bb13009e64 + is %2B as well (#9624) 2023-06-19 11:22:13 +00:00
Jeroen Reumkens 648dd862f5 Tweaks to booker grid sizing to prevent buttons from overflow booker wrapper in Safari (#9620) 2023-06-19 11:34:49 +01:00
sean-brydonandzomars 8eccd3658e feat: Upstash implementation for rate limiting/redis (#9514)
* Introduce rate limiting that works on the edge

* typo

* Log once on init

* Update rateLimit.ts

---------

Co-authored-by: zomars <zomars@me.com>
2023-06-19 10:01:06 +00:00
Ujwal KumarandJeroen Reumkens ed65b2a3ab fix: Hide layout switcher when only 1 layout is enabled (#9610)
* Hide layout switcher when only 1 layouts is enabled

* Ran prettier

---------

Co-authored-by: Jeroen Reumkens <hello@jeroenreumkens.nl>
2023-06-19 08:55:25 +00:00
Manav Guptaandsean-brydon 0930121680 fix: event type filter in Mobile view (#9619)
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
2023-06-18 21:11:41 +00:00
Crowdin Bot 1068873f27 New Crowdin translations by Github Action 2023-06-18 20:55:42 +00:00
Udit TakkarandPeer Richelsen a1ece0be63 fix: sidebar ui (#9581)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-06-18 20:54:57 +00:00
Crowdin Bot c550b4c8fc New Crowdin translations by Github Action 2023-06-18 19:22:51 +00:00
VIvek ChavanandKeith Williams e95650637c fix: changes "cancelled" to canceled (#9505)
* fixed #9502 changes cancelled to cenceled

* fixed cancelled to cancelled from all places in common.json

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2023-06-18 19:21:52 +00:00
0f3e0a1554 fix: Alert component fixed (#9605)
* fix: Alert Component Fixed

* Update packages/ui/components/alert/Alert.tsx

---------

Co-authored-by: Peer Richelsen <peer@cal.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-06-17 20:57:15 +00:00
Peer Richelsen 761dfac033 3.0.1
release.yml / release (push) Canceled after 0s
2023-06-17 22:48:38 +02:00
Crowdin Bot 9fda4acc5b New Crowdin translations by Github Action 2023-06-17 20:45:08 +00:00
Jaideep Guntupalli 0470708aad refactor: translated request_password_reset in dutch (#9601) 2023-06-17 22:44:36 +02:00
Crowdin Bot bee392ba1a New Crowdin translations by Github Action 2023-06-17 20:43:01 +00:00
Hariom BalharaandPeer Richelsen 448f57442b Use the old booker redirect approach (#9589)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-06-17 20:42:15 +00:00
Crowdin Bot 856b090b4b New Crowdin translations by Github Action 2023-06-17 20:28:18 +00:00
Ujwal Kumar b99661a411 Fix typo in email verification banner (#9595) 2023-06-17 22:27:24 +02:00
Crowdin Bot d96a26eb3c New Crowdin translations by Github Action 2023-06-17 15:48:23 +00:00
Eric Dantas 9d08f5c7c8 chore: Create add-PRs-to-project-reviewing-PRs.yml (#9597)
* Create add-PRs-to-project-eric.yml

* Update and rename add-PRs-to-project-eric.yml to add-PRs-to-project-reviewing-PRs.yml

* Update add-PRs-to-project-reviewing-PRs.yml
2023-06-17 17:47:29 +02:00
Crowdin Bot 4fe5f6ca6f New Crowdin translations by Github Action 2023-06-17 01:06:55 +00:00
Esaú MoraisandAlex van Andel af505935bd fix: update top banner (#9580)
* fix: update wrong banner message in english

* fix: update `resend_email` translation in pt-BR

* chore: add `Icon` prop to `TopBanner` component

* fix: remove unnecessary variant scope

* Remove translations so they can be retranslated, complete design

* Changed key of already translated entry

---------

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2023-06-17 01:06:04 +00:00
Leo Giovanetti 4a30f60622 Configuring totp code when verifying too (#9584) 2023-06-16 20:08:12 +00:00
Alex van Andel 24ed04e6c7 v3.0.0.2
release.yml / release (push) Canceled after 0s
2023-06-16 19:21:26 +02:00
Hariom Balhara bed3595314 fix: Dynamic Group Links on vercel (#9576)
* Potential fix

* Debug

* Debug

* Use the same logic in new-booker
2023-06-16 19:00:23 +02:00
Alex van Andel 74671263bf fix: New booker selected date issues (#9570)
* Pick correct selected date

* Commented out unused booking page revalidation

* Fixed selected default bookerLayout not being applied

* Use the right weekdayOfFirst - date(1) of browsingDate
2023-06-16 18:08:58 +02:00
Crowdin Bot bdc5e9c7e9 New Crowdin translations by Github Action 2023-06-16 14:39:35 +00:00
Leo Giovanetti 8fa1c70a97 Adding more time to org admin email verif step (#9574) 2023-06-16 14:38:40 +00:00
Hariom Balhara 1343c8fa8d fix: Booking Page crash with prefilling guests (#9566)
* Fix Booking Page crash with prefilling guests

* Update packages/features/bookings/Booker/components/BookEventForm/BookEventForm.tsx
2023-06-16 15:02:59 +02:00
Crowdin Bot 5c0f9510a1 New Crowdin translations by Github Action 2023-06-16 12:46:06 +00:00
b2801170fa fix: Default tab selected issue (#9546)
* default tab selected issue

* refactor: improve cde

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: use onSuccess

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: move onsuccess and onerror

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Vinoth Kumar V <vinoth_kumar_v@Vinoths-MacBook-Pro.local>
Co-authored-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2023-06-16 12:45:20 +00:00
Alex van Andel 6ac19e8307 v3.0.0.1
release.yml / release (push) Canceled after 0s
2023-06-16 12:48:20 +02:00
Hariom Balhara 344241cfbf fix: New Booker Rewrites (#9557)
* Solve the problem using Next.config.js only

* Debug

* Avoid infinite rewritees

* Apply suggestions from code review

* Apply suggestions from code review

* Remove stale comments

* Update packages/embeds/embed-core/src/embed-iframe.ts
2023-06-16 12:31:57 +02:00
Carina WollendorferandCarinaWolli 66ebf18fa9 add team slug to team event link (#9558)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2023-06-16 11:05:47 +02:00
Crowdin Bot e6d6f3317e New Crowdin translations by Github Action 2023-06-16 08:38:03 +00:00
Carina WollendorferandCarinaWolli 55f66e6bcd remove slash (#9556)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2023-06-16 08:37:06 +00:00
Crowdin Bot 22e2b0a6a9 New Crowdin translations by Github Action 2023-06-16 06:27:50 +00:00
sydwardrae e24f3828cb Spelling chore common.json (#9550)
Fixed occured to occurred
2023-06-16 08:26:59 +02:00
Crowdin Bot 70f5bdc499 New Crowdin translations by Github Action 2023-06-15 22:38:02 +00:00
zomars 8731a39c3c fix: api build 2023-06-15 15:36:59 -07:00
Omar López e2d9e75475 v3.0.0
release.yml / release (push) Canceled after 0s
2023-06-15 15:15:39 -07:00
Crowdin Bot 55c7707b94 New Crowdin translations by Github Action 2023-06-15 22:15:20 +00:00
Crowdin Bot 98944d4815 New Crowdin translations by Github Action 2023-06-15 17:29:48 +00:00
Crowdin Bot faba25acbd New Crowdin translations by Github Action 2023-06-15 17:28:46 +00:00
aab5ee344c feat: Org settings - profile,appearance, child teams, create new child (#9231)
* Initial commit

* Adding feature flag

* Desktop first banner, mobile pending

* Removing dead code and img

* AppInstallButtonBase

* WIP

* Adds Email verification template+translations for organizations (#9202)

* feat: Orgs Schema Changing `scopedMembers` to `orgUsers` (#9209)

* Change scopedMembers to orgMembers

* Change to orgUsers

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Session logic to show org label

* Step 2 done, avatar not working

* List orgs and list teams specific if orgs exist

* Conditionally show org - fix settings layout - add labels for all pages

* Profile Page + update

* Org specific team creation

* appearance page

* Ensure members cant of org cant update settings in UI

* Fix update handler imports

* hide billing on sub teams

* Update profile slug page

* Letting duplicate slugs for teams to support orgs

* Add slug coliisions for org

* Covering null on unique clauses

* Covering null on unique clauses

* Extract to utils

* Update settings to use subdomain path in team url , team + org

* Supporting having the orgId in the session cookie

* Onboarding admins step

* Last step to create teams

* Update handler comments

* Upgrade ORG banner - disabled team banner for child teams

* Handle publishing ORGS

* Fix licenese issue

* Update packages/trpc/server/routers/viewer/teams/create.handler.ts

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* A11ly

* Feedback

* Making an org avatar (temp)

* Add slug colission detection for user and team name

* Fix Import

* Remove update password func

* Fix module import over relative

* feat: organization event type filter (#9253)

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* Missing changes to support orgs schema changes

* Remove app install button sa its in 9337

* Remove i18n key not being used

* feat: Onboarding process to create an organization (#9184)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* feedback

* Making sure we check requestedSlug now

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* feat: [CAL-1816] Organization subdomain support (#9345)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* Covering users and subteams, excluding non-org users

* Unpublished teams shows correctly

* Create subdomain in Vercel

* feedback

* Renaming Vercel env vars

* Vercel domain check before creation

* Supporting cal-staging.com

* Change to have vercel detect it

* vercel domain check data message error

* Remove check domain

* Making sure we check requestedSlug now

* Feedback and unneeded code

* Reverting unneeded changes

* Unneeded changes

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Vercel subdomain creation in PROD only

* feat: organization settings general and members page (#9266)

* feat: organization settings general page

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* feat: add members page

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* chore: remove

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: use invalidate

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: delete mutation

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: remove organization id

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* chore

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: use zod schema

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* Type fixes

* Reverting changes

* Update UsernameTextfield.tsx

* More reverts

* Update next-auth-options.ts

* Update common.json

* Type fixes

* Include invite token for orgs

* Update org schema

* Make token settings optional as it isnt used in orgs yet

* Fix missing prop

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2023-06-15 10:27:39 -07:00
Leo Giovanettiandzomars 6880f88dbe Org teams (#9544)
Co-authored-by: zomars <zomars@me.com>
2023-06-15 16:55:45 +00:00
Crowdin Bot 9177fe86dc New Crowdin translations by Github Action 2023-06-15 16:37:15 +00:00
bf3f8acbc0 feat: Enable new booker globally for 3.0 (#9541)
* Update migration to be on by default - remove cookie check

* Use env variable to control enabling NEW_BOOKER for all

* Update packages/prisma/migrations/20230524105015_added_newbooker_feature_flag/migration.sql

* Update turbo.json

---------

Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
2023-06-15 16:36:25 +00:00
b4fa9826f2 feat: organizations sidebar (#9395)
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Efraín Rochín <roae.85@gmail.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2023-06-15 16:12:47 +05:30
Jeroen ReumkensandPeer Richelsen 955de3133c feat: weekly view calendar improvements (#9491)
* Add correct start/end time for weekly calendar by looking at calendar's availability

* Always show 24h in weekly calendar, added scroll functionality, current time and events in correct timezone

* Improved current time style

* Show slots for every minute, so also odd timeslots due to offsets work

* Show correct timeformat for weekly view on left side time stamps

* Fix data attr for debug

* Position events differently so we can accomodate for offset start times.

* Removed schedule from public event api, because we don't use it anymore

* Fixed alignment of timeslots in weekview calendar.

* Added loading spinner to weekly calendar

* Force weekly view calendar hour labels to show 00 minutes, also for gmt x.5 timezones that are offset 30 mins.

* Change event duration blocks in weekly calendar when user changes duration in multi duration event

* Improved week view slot time label alignments for shorter durations

---------

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-06-15 09:59:58 +00:00
Jeroen Reumkens faac3d0f57 fix: Fixed merge mistake in next.config breaking new booker redirects. (#9532) 2023-06-15 14:30:44 +05:30
Crowdin Bot 3fb1ede770 New Crowdin translations by Github Action 2023-06-15 08:59:05 +00:00
Hariom Balhara 53224886e3 feat: Routing Forms/Teams Support (#9417) 2023-06-15 08:58:07 +00:00
Udit Takkar e513180d7e fix: check user session in banner (#9530)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2023-06-15 09:36:09 +01:00
Udit Takkar 3116d6df1a fix: Email verification banner (#9519) 2023-06-15 11:41:32 +05:30
4284a4d16d feat: Organizations users calendar cache (#9498)
* Initial commit

* Adding feature flag

* feat: Orgs Schema Changing `scopedMembers` to `orgUsers` (#9209)

* Change scopedMembers to orgMembers

* Change to orgUsers

* Letting duplicate slugs for teams to support orgs

* Covering null on unique clauses

* Supporting having the orgId in the session cookie

* feat: organization event type filter (#9253)

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* Missing changes to support orgs schema changes

* feat: Onboarding process to create an organization (#9184)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* feedback

* Making sure we check requestedSlug now

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* feat: [CAL-1816] Organization subdomain support (#9345)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* Covering users and subteams, excluding non-org users

* Unpublished teams shows correctly

* Create subdomain in Vercel

* feedback

* Renaming Vercel env vars

* Vercel domain check before creation

* Supporting cal-staging.com

* Change to have vercel detect it

* vercel domain check data message error

* Remove check domain

* Making sure we check requestedSlug now

* Feedback and unneeded code

* Reverting unneeded changes

* Unneeded changes

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Vercel subdomain creation in PROD only

* Making sure we let localhost still work

* Feedback

* Type check fixes

* feat: Organization branding in side menu (#9279)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Org branding provider used in shell sidebar

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Using org avatar (temp)

* Not showing org logo if not set

* User onboarding with org branding (slug)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* feedback

* Feedback

* Org public profile

* Public profiles for team event types

* Added setup profile alert

* Using org avatar on subteams avatar

* Making sure we show the set up profile on org only

* Profile username availability rely on org hook

* Update apps/web/pages/team/[slug].tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Update apps/web/pages/team/[slug].tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* feat: Organization support for event types page (#9449)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Org branding provider used in shell sidebar

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Using org avatar (temp)

* Not showing org logo if not set

* User onboarding with org branding (slug)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* feedback

* Feedback

* Org public profile

* Public profiles for team event types

* Added setup profile alert

* Using org avatar on subteams avatar

* Processing orgs and children as profile options

* Reverting change not belonging to this PR

* Making sure we show the set up profile on org only

* Removing console.log

* Comparing memberships to choose the highest one

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Type errors

* Refactor and type fixes

* Update orgDomains.ts

* Feedback

* Reverting

* NIT

* fix issue getting org slug from domain

* Improving orgDomains util

* Host comes with port

* Update useRouterQuery.ts

* add org users cache-calendar

* fix typo

* re-use the simple user calendar-cache page

* Apply suggestions from code review

* Update packages/core/CalendarManager.ts

* type fixes

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Leo Giovanetti <hello@leog.me>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
2023-06-15 00:40:47 +00:00
zomars eadca3b2c0 Update .env.example 2023-06-14 14:45:53 -07:00
Crowdin Bot 68125af29f New Crowdin translations by Github Action 2023-06-14 21:44:55 +00:00
Crowdin Bot d436e628fe New Crowdin translations by Github Action 2023-06-14 21:41:30 +00:00
c5483c81de feat: Organizations (#8993)
* Initial commit

* Adding feature flag

* feat: Orgs Schema Changing `scopedMembers` to `orgUsers` (#9209)

* Change scopedMembers to orgMembers

* Change to orgUsers

* Letting duplicate slugs for teams to support orgs

* Covering null on unique clauses

* Supporting having the orgId in the session cookie

* feat: organization event type filter (#9253)

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* Missing changes to support orgs schema changes

* feat: Onboarding process to create an organization (#9184)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* feedback

* Making sure we check requestedSlug now

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* feat: [CAL-1816] Organization subdomain support (#9345)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* Covering users and subteams, excluding non-org users

* Unpublished teams shows correctly

* Create subdomain in Vercel

* feedback

* Renaming Vercel env vars

* Vercel domain check before creation

* Supporting cal-staging.com

* Change to have vercel detect it

* vercel domain check data message error

* Remove check domain

* Making sure we check requestedSlug now

* Feedback and unneeded code

* Reverting unneeded changes

* Unneeded changes

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Vercel subdomain creation in PROD only

* Making sure we let localhost still work

* Feedback

* Type check fixes

* feat: Organization branding in side menu (#9279)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Org branding provider used in shell sidebar

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Using org avatar (temp)

* Not showing org logo if not set

* User onboarding with org branding (slug)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* feedback

* Feedback

* Org public profile

* Public profiles for team event types

* Added setup profile alert

* Using org avatar on subteams avatar

* Making sure we show the set up profile on org only

* Profile username availability rely on org hook

* Update apps/web/pages/team/[slug].tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Update apps/web/pages/team/[slug].tsx

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* feat: Organization support for event types page (#9449)

* Desktop first banner, mobile pending

* Removing dead code and img

* WIP

* Adds Email verification template+translations for organizations (#9202)

* First step done

* Merge branch 'feat/organizations-onboarding' of github.com:calcom/cal.com into feat/organizations-onboarding

* Step 2 done, avatar not working

* Covering null on unique clauses

* Onboarding admins step

* Last step to create teams

* Moving change password handler, improving verifying code flow

* Clearing error before submitting

* Reverting email testing api changes

* Reverting having the banner for now

* Consistent exported components

* Remove unneeded files from banner

* Removing uneeded code

* Fixing avatar selector

* Org branding provider used in shell sidebar

* Using meta component for head/descr

* Missing i18n strings

* Feedback

* Making an org avatar (temp)

* Using org avatar (temp)

* Not showing org logo if not set

* User onboarding with org branding (slug)

* Check for subteams slug clashes with usernames

* Fixing create teams onsuccess

* feedback

* Feedback

* Org public profile

* Public profiles for team event types

* Added setup profile alert

* Using org avatar on subteams avatar

* Processing orgs and children as profile options

* Reverting change not belonging to this PR

* Making sure we show the set up profile on org only

* Removing console.log

* Comparing memberships to choose the highest one

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>

* Type errors

* Refactor and type fixes

* Update orgDomains.ts

* Feedback

* Reverting

* NIT

* fix issue getting org slug from domain

* Improving orgDomains util

* Host comes with port

* Update useRouterQuery.ts

* Feedback

* Feedback

* Feedback

* Feedback: SSR for user event-types to have org context

* chore: Cache node_modules (#9492)

* Adding check for cache hit

* Adding a separate install step first

* Put the restore cache steps back

* Revert the uses type for restoring cache

* Added step to restore nm cache

* Removed the cache-hit check

* Comments and naming

* Removed extra install command

* Updated the name of the linting step to be more clear

* Removes the need for useEffect here

* Feedback

* Feedback

* Cookie domain needs a dot

* Type fix

* Update apps/web/public/static/locales/en/common.json

Co-authored-by: Omar López <zomars@me.com>

* Update packages/emails/src/templates/OrganizationAccountVerifyEmail.tsx

* Feedback

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: zomars <zomars@me.com>
Co-authored-by: Efraín Rochín <roae.85@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2023-06-14 21:40:20 +00:00
Keith Williams 9db4a04cd9 chore: Cache node_modules (#9492)
* Adding check for cache hit

* Adding a separate install step first

* Put the restore cache steps back

* Revert the uses type for restoring cache

* Added step to restore nm cache

* Removed the cache-hit check

* Comments and naming

* Removed extra install command

* Updated the name of the linting step to be more clear
2023-06-14 15:27:47 -03:00
Alex van Andel 8943e8c2f6 Fix: Sets null to undefined during workflow select (#9513) 2023-06-14 14:43:42 +00:00
Crowdin Bot f17fa55426 New Crowdin translations by Github Action 2023-06-14 14:39:25 +00:00
Hariom BalharaandLeo Giovanetti 9ff83075d6 Improve IP Ban (#9512)
Co-authored-by: Leo Giovanetti <hello@leog.me>
2023-06-14 16:38:34 +02:00
Jeroen Reumkens 6b6043afdc Added custom error with more details to debug the ciaran event issue (#9482) 2023-06-14 10:47:58 +00:00
Crowdin Bot fd9162e70f New Crowdin translations by Github Action 2023-06-14 09:54:17 +00:00
Jeroen ReumkensandHariom Balhara 8331059b7c feat: new booker embed (#9023)
* Added embed files for new booker routes.

* Updated nextjs config to redirect to correct embed url.

* Notify embed of booker size after animation completes.

* Don't use animations and 100vh in embed.

* Added booker layout toggles to embed settings (wip)

* Booker header positioning tweaks

* Show correct layout in embed

* Don't show pricing event meta if stripe app is not installed

* Support custom border booker for embed

* wip on passing layout prop to iframe for previews

* Only show booker layout settings in embed-create-popup if booker layout feature is enabled.

* Made layout prop in preview state for embed optional

* Made layout prop in preview state for embed optional

* Get layout toggle working

* Fixed types

* Added themebasis prop

* Fix potential circular import that should then fix type errors

* Fixed type error by fixing casing.

* Type fixes

* Added translations

* More translations

* Remove comment

* Removed uneccessary addition to package.json

* Removed todo since it's solved in another way

---------

Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2023-06-14 09:22:44 +00:00
Syed Ali Shahbaz f0992b4914 fix with object undefined check (#9493) 2023-06-13 20:27:42 +00:00
TachyonicBytesandTachyonicBytes e081a4cfc2 fix: Add e2e test for routing forms webhook subscription (#9401)
* add e2e test for routing forms webhook subscription

* remove debugging checks

* fixed missing method for e2e

* remove forced timeout for e2e test

* fix e2e webhook test

* use routing forms page for install

---------

Co-authored-by: TachyonicBytes <support@tachyonicbytes.com>
2023-06-13 15:22:19 +00:00
895b3ca7c9 feat: add paid webhook (#8721)
* feat: add BOOKING_PAID on enums

* feat: trigger the BOOKING_PAID webhook

* refactor: create payment variable

* feat: add REJECTED and REQUESTED on enums

* feat: create migration to booking werbhooks

* Update packages/features/webhooks/lib/constants.ts

Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>

* Update packages/prisma/schema.prisma

Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>

* Update packages/prisma/migrations/20230513235419_add_booking_webhooks/migration.sql

Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>

---------

Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: alannnc <alannnc@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
2023-06-13 14:57:59 +00:00
Jaideep GuntupalliandBailey Pumfleet 4d30264950 fix: Multiple In Person Locations not working as expected in Event Setup Tab (#9465)
Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>
2023-06-13 14:54:53 +00:00
3a352a94f6 fix: phone input update state persistence (#9471)
* fix: phone input update state persistence

* refactor: use spreading

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: alannnc <alannnc@gmail.com>
Co-authored-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2023-06-13 14:54:13 +00:00
Nikeshkumar TK 8623175612 fix: Routing form two "New" button issue. (#9479)
* event types public api fix

* Routing form new button issue

* Routing form new button issue

* Routing form new button issue

* Routing form new button issue

* Routing form new button issue
2023-06-13 14:53:50 +00:00
Udit TakkarandPeer Richelsen ea531777c4 fix: size of cell (#9486)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-06-13 11:08:00 +00:00
Soham Datta 2639ef7e13 fix: #9217 | redirected unready /admin to one of its tabs (#9222) 2023-06-13 10:46:41 +00:00
Jeroen Reumkens 0e76a19c96 Pass event duration to schedule api call (#9484) 2023-06-13 10:14:45 +00:00
3ec9eb377d docs: Added command in manual section (#9433)
Co-authored-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2023-06-12 21:46:29 +01:00
Udit TakkarandBailey Pumfleet 44b7000509 fix: dark mode in Alert component (#9467)
* fix: dark mode in Alert component

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* chore

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>
2023-06-12 17:49:44 +00:00
depfu[bot]andHariom Balhara 251307f1e6 chore: Update vite 2.9.15 → 2.9.16 (patch) (#9346)
* Update vite to version 2.9.16

* Upgrade vite to 4.1.2 everywhere

---------

Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2023-06-12 16:51:02 +00:00
Balveer Singh RaoandUdit Takkar 75e638ec4d fix: copy icon for dark mode (#9459)
* fixed copy icon for dark mode

* fix: height

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2023-06-12 16:48:37 +00:00
Crowdin Bot 443ccdd6c0 New Crowdin translations by Github Action 2023-06-12 16:28:32 +00:00
Abhishek Sunil dbf11cc04b test: Add E2E test to verify theme change (#9455)
* Add E2E test to verify theme change

* PR fixes
2023-06-12 16:14:40 +00:00
Crowdin Bot a5c9729f5f New Crowdin translations by Github Action 2023-06-12 10:57:30 +00:00
sean-brydon a6e2983a22 Fix translations (#9466) 2023-06-12 10:43:50 +00:00
Meet Patel a21f0c46c7 enabled csv upload for team bulk invites (#9446) 2023-06-11 09:36:59 +00:00
Udit Takkar ed4a81e852 fix: theme in new booker (#9453)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2023-06-11 09:11:46 +00:00
9231218350 fix: carify what sender ID means (#9431)
* add tooltip on info icon

* fix text

* fix UI in addActionDialog

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
2023-06-11 03:20:13 +00:00
7d1ea4ee2b chore: moved viewport meta from document to PageWrapper (#9406)
* moved viewport meta from document to _app

* moved viewport meta from _app.tsx to PageWrapper.tsx

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Efraín Rochín <roae.85@gmail.com>
2023-06-10 15:19:17 +00:00
Efraín Rochín 0c68e51930 fix: [CAL-1765] opt-in: clicking "confirm" or "reject" broken (#9443)
* Add support to a custom sessionGetter in trpc createContext

* type fixes
2023-06-10 11:02:50 +00:00
Alex van Andel 8e565dc610 v2.9.8
release.yml / release (push) Canceled after 0s
2023-06-10 12:46:24 +02:00
Rob JacksonandUdit Takkar 5b47844fa1 fix: Able to toggle off timeFormat on new booker UI (#9442)
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2023-06-10 07:51:49 +00:00
Rob JacksonandEfraín Rochín 0d01d3246a test: Add E2E tests for seated attendee rescheduling or cancelling bookings (#9422)
* Add test for attendees rescheduling bookings

* Add tests for rescheduling seated bookings (first attendee)

* Fix tests not skipping disabled times on new booker UI

* Add tests for rescheduling seated bookings (all attendees)

* Remove duplicate tests (my mistake)

* Add explicit test ids for cancel inputs

* Add E2E tests for seated attendees cancelling their bookings

* Update E2E tests for a seated attendee rescheduling their booking

* Update tests to remove dependence on localised text

* Updated seated E2E tests to remove testing of unused URL

---------

Co-authored-by: Efraín Rochín <roae.85@gmail.com>
2023-06-10 03:47:50 +00:00
Alex van AndelandEfraín Rochín bb31c4ba14 fix: Prevent invalid host assignment (#9441)
* Avoids invalid hosts

* Fixed test selector, instead using react-select-2-listbox

* Different way of selecting the managed user

* Convert select-option- to value instead of label

* Replaced all instances of networkidle

* done rewriting test

* Fix prisma is not defined error

* Depend on inner text rather than testid

* Fill of team create is unstable

* Removed console.log

---------

Co-authored-by: Efraín Rochín <roae.85@gmail.com>
2023-06-10 02:39:49 +00:00
Crowdin Bot d9a7952467 New Crowdin translations by Github Action 2023-06-09 22:33:12 +00:00
Balveer Singh Rao 208dcbbda3 fixed Rotate spinner (#9429) 2023-06-09 22:21:54 +00:00
Crowdin Bot ff4494d395 New Crowdin translations by Github Action 2023-06-09 20:45:51 +00:00
Udit Takkar db4b32119e fix: UI bugs (#9435)
* fix: toggle group background

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: background

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* chore

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: confirm modal

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: dark mode footer

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: change tootltip

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2023-06-09 20:32:35 +00:00
Carina WollendorferandCarinaWolli bfef5b1877 fix: team bio (#9438)
* fix bio rendering

* fix type error

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2023-06-09 12:50:35 +00:00
Carina WollendorferandCarinaWolli 91962cc90b check that input teamId equals webhook team (#9434)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2023-06-09 11:18:59 +00:00
Carina WollendorferandCarinaWolli 7a71a5ddd4 fix error when updating event type availability (#9428)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2023-06-09 10:19:49 +00:00
Jeroen Reumkens ca47a589ba feat: weekly view for new booker. (#9389)
* WIP on weekly view for new booker.

* Set responsive grid height for booker weekly view.

* Fixed types

* Ensure you can't click on disabled dates in weekly calendar

* CAL-1916: Improvements for blocked out parts background blocks, made the lines connect by using a shared background.

* Margin, padding and color tweaks for new booker CAL-1911

* Made week view have more days visible by default

* Fix to prevent layout switch from breaking when clicking same layout twice.
2023-06-09 09:38:18 +00:00
Crowdin Bot a33dbd8922 New Crowdin translations by Github Action 2023-06-09 08:31:50 +00:00
aaab4ca741 refactor: TwoFactor.tsx (#9392)
* Update TwoFactor.tsx

* fix: useeffect

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-06-09 08:19:33 +00:00
Crowdin Bot 6aadf7429d New Crowdin translations by Github Action 2023-06-08 16:57:52 +00:00
GitStart-Cal.comandgitstart-calcom 748307bc91 fix: Wrong padding on modals - second version (CALCOM-8414) (#9419)
Co-authored-by: gitstart-calcom <gitstart@users.noreply.github.com>
2023-06-08 16:45:06 +00:00
Crowdin Bot 559389a319 New Crowdin translations by Github Action 2023-06-08 14:37:40 +00:00
Ninad Trivedi a9140b6a76 Scrollbar bug fixed (#9357) 2023-06-08 14:25:23 +00:00
Crowdin Bot 8f50e873c9 New Crowdin translations by Github Action 2023-06-08 13:53:38 +00:00
9b28b7f78a fix: remove duplicate value i18n (#8547)
* fix: remove duplicate value i18n

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* feat: add duplicate check in next config

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: remove more duplicates

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* fix: description on two factor page

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

* Update apps/web/next.config.js

* Update apps/web/next.config.js

---------

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2023-06-08 13:37:54 +00:00
Crowdin Bot 4417097f97 New Crowdin translations by Github Action 2023-06-08 12:45:11 +00:00
Jeroen Reumkens 93fc036d2c feat: Made booker layout settings more user friendly (#9397)
* Made booker layout settings more user friendly

* Fixed tyeps and default values in appearance form for booker layout

* Enable all layouts by default
2023-06-08 12:32:17 +00:00
343 changed files with 8135 additions and 3975 deletions
+28
View File
@@ -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
+9
View File
@@ -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 }}
+1 -1
View File
@@ -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
+1
View File
@@ -16,6 +16,7 @@ concurrency:
jobs:
changes:
name: Detect changes
runs-on: buildjet-4vcpu-ubuntu-2204
permissions:
pull-requests: read
+8
View File
@@ -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
```
+3
View File
@@ -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,
+1 -1
View File
@@ -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"
}
}
+4 -2
View File
@@ -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;
}
}
+44 -2
View File
@@ -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>
+7
View File
@@ -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={
+15 -15
View File
@@ -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">
+3 -2
View File
@@ -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>;
+10 -1
View File
@@ -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>
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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",
+3 -1
View File
@@ -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",
+9 -1
View File
@@ -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 {
+56 -22
View File
@@ -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" };
};
}
+8 -10
View File
@@ -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";
@@ -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,
},
-4
View File
@@ -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
+9 -9
View File
@@ -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 {
+16 -2
View File
@@ -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;
}
+11 -3
View File
@@ -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);
+20 -4
View File
@@ -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 {
+3 -1
View File
@@ -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);
}
+1 -1
View File
@@ -182,7 +182,7 @@ const IntegrationsList = ({ data, handleDisconnect, variant }: IntegrationsListP
setBulkUpdateModal(true);
}
}}>
{t("change_default_conferencing_app")}
{t("set_as_default")}
</DropdownItem>
</DropdownMenuItem>
)}
+3 -1
View File
@@ -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,
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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",
+4 -3
View File
@@ -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,
+69 -2
View File
@@ -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
+23 -35
View File
@@ -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,
},
};
+1 -1
View File
@@ -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>
+14 -3
View File
@@ -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);
+2 -4
View File
@@ -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();
+1 -1
View File
@@ -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
View File
@@ -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;
};
+6 -1
View File
@@ -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,
},
},
},
},
},
+6
View File
@@ -86,6 +86,12 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
theme: true,
brandColor: true,
darkBrandColor: true,
parent: {
select: {
logo: true,
name: true,
},
},
},
},
users: {
+2 -1
View File
@@ -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) }}
/>
</>
)}
+4 -5
View File
@@ -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);
+104 -15
View File
@@ -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");
+45
View File
@@ -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();
});
});
+6 -1
View File
@@ -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 } }),
};
};
+1
View File
@@ -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);
+29 -2
View File
@@ -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));
}
+30 -36
View File
@@ -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();
+19
View File
@@ -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);
});
});
+60
View File
@@ -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

+6 -70
View File
@@ -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 هذا مأخوذ بالفعل"
}
+6 -70
View File
@@ -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á"
}
+3 -59
View File
@@ -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"
}
+6 -70
View File
@@ -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": "Απενεργοποίηση επισκεπτών"
}
+100 -82
View File
@@ -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 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+6 -70
View File
@@ -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",
+105 -74
View File
@@ -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