Compare commits

..
64 Commits
Author SHA1 Message Date
zomars 5d775bd4a3 v2.3.6
release.yml / release (push) Canceled after 0s
2022-12-07 14:02:24 -07:00
Nafees Nazik 4e02b22472 fix: add optimistic update for disabling forms (#5547) 2022-12-07 13:55:41 -07:00
4686d3ff48 Improve multilingualism and fix search routes (#5334)
* fixed search routes

* made static text multilingual and fixed german translations

# Conflicts:
#	apps/web/components/availability/Schedule.tsx

* delete empty file created by fixing merge conflicts

* fixing TextField placeholder by passing attendeeName and fixed json variable

* Using useLocal to modify static text to make it multilingual, and passing the correct variables for brand and mail

* seperated whitelabel and improved translations

* added missing translation

* added missing translation for webhooks

* Updated AdminAppsView with dynamic translations.
Added translations for german and english files only.

* changed back to one liner

* updated german and english translations for impersonation.tsx

* updated german and english translations for impersonation.tsx and users.tsx. added missing german translation for timeformat_profile_hint

* updated german and english translations for team-billing-view.tsx

* updated german and english translations for LicenseRequired.tsx

* updated routes for profile and avatar

* yarn.lock updated from newer changes

* Revert " yarn.lock updated from newer changes"

This reverts commit efd9a90bf774371a331861e4fb441ab4f4d0b7fd.

* sanitize dangerouslySetInnerHTML to prevent xss attacks

* tried to fix window title flicker

* changed ssdInit to ssrInit for getServerSideProps. Serverside translation works but current route still set as a window title

* flicker with route in window title is caused here. It is not necessary to check if isPublic and session is false because it already gets checked in useRedirectToLoginIfUnauthenticated hook.

* fixed window title translation flicker for availability page

* fixed window title translation flicker for teams page

* fixed window title translation flicker for workflow page

* fixed error that div may not be rendered within p element

* fixed window title translation flicker for booking page

* fixed window title translation flicker by adding getServerSideProps

* Only set HeadSeo if an page title exists. If window title is set by the Meta component, shell is causing a flicker because it overwrites the title which is set by Meta. It is a problem especially for settings pages.

* fixed window title translation flicker by adding the Meta component to the skeleton

* fixed condition

* removed condition and added withoutSeo for settings pages

* using translations for create team page further fixed flicker for window title

* fixed flicker for window title for event-type creation page

* fixed flicker for window title for availability creation page

* fixed flicker for window title for sso page

* updated conferencing en translation

* added meta.CTA back it was mistakenly removed

* fixed flicker for workflows page

* fixed missing variable

* Update packages/ui/v2/core/Shell.tsx

* Delete index.tsx

* Update sso.tsx

* Updates subdmoules

Co-authored-by: maxi <maximilian.oehrlein@clicksports.de>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Omar López <zomars@me.com>
2022-12-07 13:53:44 -07:00
zomars 02e9d8d45f Sync submodules 2022-12-07 13:40:37 -07:00
Udit Takkar 7ce5096f13 fix: resetting input on cancel and refactoring input fiedl (#5522)
* fix: resetting input on cancel and refactoring input fiedl

* feat: add username field in /usersettings

* chore: remove unused

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

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2022-12-07 13:15:15 -07:00
Udit Takkar 83e51e9b9d fix: use trim in zod (#5915)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2022-12-07 13:12:53 -07:00
Udit TakkarandPeer Richelsen dca3278c40 fix: zoom video (#5910)
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: Peer Richelsen <peeroke@gmail.com>
2022-12-07 13:12:26 -07:00
Udit Takkar 7501635fbf fix: delete use when 2fa is disabled (#5899)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2022-12-07 13:12:14 -07:00
Peer Richelsen 80c96ea5ac remove "Add bugs to Bug Hunting" workflow (#5901)
not needed anymore
2022-12-07 13:09:01 -07:00
Hariom BalharaandPeer Richelsen 8c001e0d34 Fix reschedule embed (#5861)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-07 13:08:34 -07:00
Joe Au-Yeungandalannnc bf275497a2 MS Teams use joinWebUrl from response body (#5886)
* Add joinWebUrl to event

* Remove console.log

Co-authored-by: alannnc <alannnc@gmail.com>
2022-12-07 12:56:15 -07:00
6e351a4b20 fix/premium-username-flow (#5815)
* Removes user plan logic for stripe sub

* Update hardcoded price

* Removed checkoutSessionId metadata and fix for trpc query

* Remove or comment team billing unused code

* Add todo note

* Fix type checks

* Change function that was renamed

* Remove duplicated test

* remove plan when creating user on test

Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-07 12:55:47 -07:00
github-actions[bot]andCrowdin Bot 5360cea3bf New Crowdin translations by Github Action (#5919)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-12-07 20:49:45 +01:00
+2 2f36985462 /availability - Add ability to set as default in the dropdown (#5717)
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: Matheus Benini Ferreira <88898100+MatheusBeniniF@users.noreply.github.com>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
Co-authored-by: gitstart-app[bot] <57568882+gitstart-app[bot]@users.noreply.github.com>
Co-authored-by: gitstart <gitstart@gitstart.com>
Co-authored-by: gGh00sTt <coolmagnas@gmail.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>

Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: Matheus Benini Ferreira <88898100+MatheusBeniniF@users.noreply.github.com>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
Co-authored-by: gitstart-app[bot] <57568882+gitstart-app[bot]@users.noreply.github.com>
Co-authored-by: gitstart <gitstart@gitstart.com>
Co-authored-by: gGh00sTt <coolmagnas@gmail.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>
Co-authored-by: Omar López <zomars@me.com>
2022-12-07 12:35:55 -07:00
6b26e9a7de Harsh/fix timeformat hint (#5918)
* fix: 404 page for undefined events

* remove prev code merge

* fix: timeformat profile hint

Co-authored-by: Guest <guest@pop-os.localdomain>
Co-authored-by: root <root@pop-os.localdomain>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-07 18:22:43 +00:00
github-actions[bot]andCrowdin Bot d7655f0521 New Crowdin translations by Github Action (#5914)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-12-07 19:10:15 +01:00
sean-brydonandLeo Giovanetti f4ed345a87 Fixes disable branding for teams and users (#5913)
* Adding new nextauth object

* Use correct brand hidden values

* Move check to getprops instead of a function

* Update apps/web/components/booking/pages/AvailabilityPage.tsx

* Update apps/web/components/booking/pages/AvailabilityPage.tsx

* Update apps/web/pages/[user]/[type].tsx

Co-authored-by: Leo Giovanetti <hello@leog.me>

* Update apps/web/pages/api/auth/[...nextauth].tsx

Co-authored-by: Leo Giovanetti <hello@leog.me>

* Update apps/web/pages/api/auth/[...nextauth].tsx

Co-authored-by: Leo Giovanetti <hello@leog.me>

Co-authored-by: Leo Giovanetti <hello@leog.me>
2022-12-07 15:04:04 +00:00
SumedhandPeer Richelsen c3122c82e4 fix/cant-create-team-name-taken (#5911)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-07 14:50:54 +00:00
Udit Takkar cc9b49131e fix: add toast and fix delete action (#5912)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2022-12-07 15:37:20 +01:00
github-actions[bot]andCrowdin Bot 190db1a0f6 New Crowdin translations by Github Action (#5903)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-12-06 23:25:53 +01:00
Cory Dransfeldt bd48a72e99 [Feature] Adds support for Plausible analytics to app store (#5906) 2022-12-06 21:19:16 +00:00
Nafees Nazik a6836a1488 fix: use the new docker compose command if it exists (#5852) 2022-12-06 11:41:50 -07:00
2b67ea9635 Harsh/fix 404 page for undefined events (#5700)
* fix: 404 page for undefined events

* Update apps/web/pages/[user]/[type].tsx

Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>

Co-authored-by: Guest <guest@pop-os.localdomain>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
2022-12-06 15:04:34 +00:00
Udit Takkar a9117c2d36 fix: use tooltip portal (#5889)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2022-12-06 13:57:02 +00:00
+1 10d3b5f1b9 Remove the back arrow (#5402)
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
Co-authored-by: Matheus Benini <matheus_benini@hotmail.com>
Co-authored-by: Matheus Benini Ferreira <88898100+MatheusBeniniF@users.noreply.github.com>
Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>
Co-authored-by: gitstart-app[bot] <57568882+gitstart-app[bot]@users.noreply.github.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>
Co-authored-by: gitstart <gitstart@gitstart.com>

Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
Co-authored-by: Matheus Benini <matheus_benini@hotmail.com>
Co-authored-by: Matheus Benini Ferreira <88898100+MatheusBeniniF@users.noreply.github.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>
Co-authored-by: gitstart-app[bot] <57568882+gitstart-app[bot]@users.noreply.github.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>
Co-authored-by: gitstart <gitstart@gitstart.com>
2022-12-06 13:02:58 +00:00
Peer Richelsen b757cb6ba1 added new teams empty screen (#5847)
* added new teams empty screen

* replaced svg background with smaller jpg

* nit

* nit

* nit

* nit

* show old emptyscreen for self-hosters

* nit
2022-12-05 15:20:33 -07:00
5968e0aa19 added EventReservationSchema to success page (#5777)
* added EventReservationSchema to success page

* removed duplicated of yarn.lock

Co-authored-by: René Müller <rene.mueller@clicksports.de>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-05 21:35:44 +00:00
zomars a06fffc4ec Adds missing translation 2022-12-05 14:24:09 -07:00
zomars 3312c84e7c Update turbo.json 2022-12-05 14:17:35 -07:00
Nafees NazikandPeer Richelsen d86710d5e9 fix: remove unnecessary title (#5853)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-05 21:11:10 +00:00
Udit Takkar 2d8e65c160 fix: ui of calendar item (#5879)
Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>

Signed-off-by: Udit Takkar <udit.07814802719@cse.mait.ac.in>
2022-12-05 20:39:52 +00:00
Udit TakkarandPeer Richelsen f74eaf7cb3 fix: increase edit location height (#5882)
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: Peer Richelsen <peeroke@gmail.com>
2022-12-05 20:18:45 +00:00
bcfd57c953 Bugfix/payment options (#5805)
* removed locale to use automatic detection in teams/lib/payments.ts

* removed payment_method_types to manage payment methods in the Dashboard

* added customer_update and automatic_tax to apply tax rates to payments

* added allow_promotion_codes to allow promotion codes

* removed multiple usages of `allow_promotion_codes` in payments.ts

Co-authored-by: René Müller <rene.mueller@clicksports.de>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: alannnc <alannnc@gmail.com>
2022-12-05 13:02:59 -07:00
c38588b93d New Crowdin translations by Github Action (#5842)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-05 20:59:12 +01:00
alannnc 32ed43574d Fix input parse to number (#5884) 2022-12-05 20:57:33 +01:00
38a5a22b9e Harsh/fix bookings name (#5848)
Co-authored-by: Guest <guest@pop-os.localdomain>
Co-authored-by: root <root@pop-os.localdomain>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-05 17:41:40 +00:00
Sascha FoersterandPeer Richelsen 2120e301c3 Update german translations (#5854)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-05 17:29:19 +00:00
Bailey Pumfleet dd0aec4e97 Fix Kbar translation (#5867) 2022-12-05 14:43:31 +00:00
Peer Richelsen 3815b86258 added norwegian to i18n (#5866) 2022-12-05 13:58:00 +00:00
Hariom BalharaandPeer Richelsen 7a6545bd03 Wordpress App Files cleanup (#5858)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-05 13:42:38 +00:00
Udit TakkarandPeer Richelsen 11f467af5d fix: toggle (#5865)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-05 13:28:21 +00:00
0930cf50b6 BugFix: Link based Apps installation - Opens 2 tabs instead of 1 (#5859)
Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-12-05 14:13:01 +01:00
c37cddd0b7 feat: add each app from the app store to KBar (#5724)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: alannnc <alannnc@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2022-12-05 12:13:31 +00:00
09253f83bf [CAL-463] Clicking Members from event types screen should take you to the members page (#5857)
Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>
Co-authored-by: gitstart-app[bot] <57568882+gitstart-app[bot]@users.noreply.github.com>
Co-authored-by: Matheus Benini Ferreira <88898100+MatheusBeniniF@users.noreply.github.com>
Co-authored-by: Matheus Benini <matheus_benini@hotmail.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>
Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>
2022-12-05 12:12:37 +00:00
Leo GiovanettiandBailey Pumfleet 1cdcebac01 Requires Confirmation Threshold (#5825)
* WIP + react errors fixed

* Booking and Availability page treatment

* Update BookingPage.tsx

Co-authored-by: Bailey Pumfleet <bailey@pumfleet.co.uk>
2022-12-05 12:12:14 +00:00
sean-brydon 58270fa653 Team impersonation (#5863)
* Re Implement frontend logic to impersonate team members

* Refactor dialog + correct disable toggle.

* fix translation

* Update packages/features/ee/impersonation/lib/ImpersonationProvider.ts
2022-12-05 12:03:36 +00:00
Peer Richelsen 1a26a254ab added team subdomain to whereby validation (#5850) 2022-12-03 19:32:40 +00:00
Udit Takkarandalannnc a36d15894d fix: user infer props and remove avatarSSr from onboarding (#5549)
Co-authored-by: alannnc <alannnc@gmail.com>
2022-12-03 19:20:18 +00:00
Sumedh cf077fd33c fix/sidebar-profiledropdown-wired-hoverstate (#5832) 2022-12-03 15:12:12 +00:00
sean-brydonandPeer Richelsen 0c979d3604 Fix imports + buttons (#5831)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-03 14:53:07 +00:00
zomars 33bc786bb3 API scripts 2022-12-02 15:25:13 -07:00
zomars a7f16462db v2.3.5
release.yml / release (push) Canceled after 0s
2022-12-02 13:33:41 -07:00
zomars 2c7fcbcf51 hotfix: 404 for mixed case usernames 2022-12-02 13:32:56 -07:00
Syed Ali ShahbazandAlex van Andel d3e4d26fa5 fixes UTC consideration in CalDAV (#5827)
* fixes UTC consideration

* typecheck fix

* code quality

* comment location

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-12-02 19:46:38 +00:00
Carina WollendorferandCarinaWolli 3be6c05722 Fixes some translation issues (#5841)
* fix french translation for rescheduled email

* fix translations for team invite

* fix rescheduling email in german

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2022-12-02 17:56:48 +00:00
Carina WollendorferandCarinaWolli e293e590bd remove if and at to query (#5838)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2022-12-02 13:43:07 +00:00
+1 d8c1c103a1 [CAL-103] All Bookings show up under Today and Today should be uppercase (#5155)
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>
Co-authored-by: Matheus Benini Ferreira <88898100+MatheusBeniniF@users.noreply.github.com>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>
Co-authored-by: Rafael <rafael.toledo@engenharia.ufjf.br>
Co-authored-by: gitstart <gitstart@gitstart.com>
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>

Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com>
Co-authored-by: Rafael Toledo <87545086+Toledodev@users.noreply.github.com>
Co-authored-by: Matheus Benini Ferreira <88898100+MatheusBeniniF@users.noreply.github.com>
Co-authored-by: Matheus Muniz <87545749+matheusmuniz03@users.noreply.github.com>
Co-authored-by: Rafael <rafael.toledo@engenharia.ufjf.br>
Co-authored-by: gitstart <gitstart@gitstart.com>
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-02 10:08:12 +00:00
Joe Au-YeungandAlan 19d00e691c Fix attendees on a booking with seats and payments, navigate to the payment page. (#5788)
* Payment booking logic to seats

* Pass email to success page from payment page

* Fix type error

Co-authored-by: Alan <alannnc@gmail.com>
2022-12-02 00:12:06 +00:00
78aa4aecef Settings: Tab item line height fix && Stop x-axis overflow of settings tab (#5699)
Co-authored-by: Guest <guest@pop-os.localdomain>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2022-12-01 23:09:14 +00:00
3ab002e547 5444 cal 339 radio option in additional questions on public booking page (#5804)
* Use field array intro

* WIP - form submitting wrong form

* WIP with fake useFormHook

* WORKING! OMG

Co-authored-by: Alex <alex@cal.com>
Co-authored-by: Jeroen Reumkens <hello@jeroenreumkens.nl>

* Booking Page styling

* Fix duplicate fields

* Radio string

* Type error

* Linting errors

* Remove unused duplicate file

* Fixed user related type error

* remove log

* Remove console logs

* remove console log

* fix dark mode text and comment style

Co-authored-by: Alex <alex@cal.com>
Co-authored-by: Jeroen Reumkens <hello@jeroenreumkens.nl>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: alannnc <alannnc@gmail.com>
2022-12-01 21:53:52 +00:00
Nafees Nazikandalannnc 7f461bc275 fix: padding (#5808)
Co-authored-by: alannnc <alannnc@gmail.com>
2022-12-01 13:30:57 -07:00
Carina WollendorferandCarinaWolli 571176102e add smsReminderNumber to webhook payload (#5823)
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2022-12-01 12:51:59 -07:00
github-actions[bot]andCrowdin Bot 8f1d3fbc50 New Crowdin translations by Github Action (#5816)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2022-12-01 15:42:24 +00:00
Joe Au-YeungandAlex van Andel 5e88ad50ea If no location is set, default to Cal Video (#5812)
* Default to Cal Video

* Show web conferencing details to follow on success page

* Show web conferencing details to follow on success page

* Show web conferencing details to follow on success page

* Type fixes

* Pass tests

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2022-12-01 10:20:01 -05:00
195 changed files with 2648 additions and 2259 deletions
-22
View File
@@ -1,22 +0,0 @@
name: Add bugs to Bug Hunting
on:
issues:
types:
- opened
- labeled
pull_request:
types:
- opened
- labeled
jobs:
add-to-project:
name: Add issue to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v0.1.0
with:
project-url: https://github.com/orgs/calcom/projects/9
github-token: ${{ secrets.GH_ACCESS_TOKEN }}
labeled: 🙋🏻‍♂️help wanted
+2 -2
View File
@@ -42,7 +42,7 @@ const Component = ({
const mutation = useAddAppMutation(null, {
onSuccess: (data) => {
if (data.setupPending) return;
if (data?.setupPending) return;
showToast(t("app_successfully_installed"), "success");
},
onError: (error) => {
@@ -195,7 +195,7 @@ const Component = ({
<h4 className="mt-8 font-semibold text-gray-900 ">{t("pricing")}</h4>
<span>
{price === 0 ? (
"Free"
t("free_to_use_apps")
) : (
<>
{Intl.NumberFormat("en-US", {
@@ -1,6 +1,7 @@
import { SchedulingType } from "@prisma/client";
import { FC, ReactNode, useEffect } from "react";
import dayjs from "@calcom/dayjs";
import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Icon, Badge } from "@calcom/ui";
@@ -41,6 +42,7 @@ interface Props {
const BookingDescription: FC<Props> = (props) => {
const { profile, eventType, isBookingPage = false, children } = props;
const { date: bookingDate } = useRouterQuery("date");
const { t } = useLocale();
const { duration, setQuery: setDuration } = useRouterQuery("duration");
useEffect(() => {
@@ -54,6 +56,21 @@ const BookingDescription: FC<Props> = (props) => {
}
}
}, []);
let requiresConfirmation = eventType?.requiresConfirmation;
let requiresConfirmationText = t("requires_confirmation");
const rcThreshold = eventType?.metadata?.requiresConfirmationThreshold;
if (rcThreshold) {
if (isBookingPage) {
if (dayjs(bookingDate).diff(dayjs(), rcThreshold.unit) > rcThreshold.time) {
requiresConfirmation = false;
}
} else {
requiresConfirmationText = t("requires_confirmation_threshold", {
...rcThreshold,
unit: rcThreshold.unit.slice(0, -1),
});
}
}
return (
<>
<UserAvatars
@@ -89,16 +106,16 @@ const BookingDescription: FC<Props> = (props) => {
</div>
</div>
)}
{eventType?.requiresConfirmation && (
{requiresConfirmation && (
<div
className={classNames(
"flex items-center",
"items-top flex",
isBookingPage && "dark:text-darkgray-600 text-sm font-medium text-gray-600"
)}>
<div>
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] inline-block h-4 w-4 " />
</div>
{t("requires_confirmation")}
{requiresConfirmationText}
</div>
)}
<AvailableEventLocations
@@ -1,7 +1,6 @@
import { useAutoAnimate } from "@formkit/auto-animate/react";
import { EventType } from "@prisma/client";
import * as Popover from "@radix-ui/react-popover";
import { TFunction } from "next-i18next";
import { useRouter } from "next/router";
import { useReducer, useEffect, useMemo, useState } from "react";
import { Toaster } from "react-hot-toast";
@@ -19,7 +18,6 @@ import {
} from "@calcom/embed-core/embed-iframe";
import CustomBranding from "@calcom/lib/CustomBranding";
import classNames from "@calcom/lib/classNames";
import { WEBSITE_URL } from "@calcom/lib/constants";
import getStripeAppData from "@calcom/lib/getStripeAppData";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import useTheme from "@calcom/lib/hooks/useTheme";
@@ -27,7 +25,6 @@ import notEmpty from "@calcom/lib/notEmpty";
import { getRecurringFreq } from "@calcom/lib/recurringStrings";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { detectBrowserTimeFormat, setIs24hClockInLocalStorage, TimeFormat } from "@calcom/lib/timeFormat";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { trpc } from "@calcom/trpc/react";
import { Icon, DatePicker } from "@calcom/ui";
@@ -48,23 +45,6 @@ import type { AvailabilityPageProps } from "../../../pages/[user]/[type]";
import type { DynamicAvailabilityPageProps } from "../../../pages/d/[link]/[slug]";
import type { AvailabilityTeamPageProps } from "../../../pages/team/[slug]/[type]";
// Get router variables
const GoBackToPreviousPage = ({ t }: { t: TFunction }) => {
const router = useRouter();
const path = router.asPath.split("/");
path.pop(); // Remove the last item (where we currently are)
path.shift(); // Removes first item e.g. if we were visitng "/teams/test/30mins" the array will new look like ["teams","test"]
const slug = path.join("/");
return (
<div className="flex h-full flex-col justify-end">
<button title={t("profile")} onClick={() => router.replace(`${WEBSITE_URL}/${slug}`)}>
<Icon.FiArrowLeft className="dark:text-darkgray-600 h-4 w-4 text-black transition-opacity hover:cursor-pointer" />
<p className="sr-only">Go Back</p>
</button>
</div>
);
};
const useSlots = ({
eventTypeId,
eventTypeSlug,
@@ -237,7 +217,7 @@ function TimezoneDropdown({
return (
<Popover.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen}>
<Popover.Trigger className="min-w-32 dark:text-darkgray-600 radix-state-open:bg-gray-200 dark:radix-state-open:bg-darkgray-200 group relative mb-2 -ml-2 inline-block rounded-md px-2 py-2 text-left text-gray-600">
<Popover.Trigger className="min-w-32 dark:text-darkgray-600 radix-state-open:bg-gray-200 dark:radix-state-open:bg-darkgray-200 group relative mb-2 -ml-2 !mt-2 inline-block self-start rounded-md px-2 py-2 text-left text-gray-600">
<p className="flex items-center text-sm font-medium">
<Icon.FiGlobe className="min-h-4 min-w-4 mr-[10px] ml-[2px] -mt-[2px] inline-block" />
{timeZone}
@@ -423,12 +403,6 @@ const AvailabilityPage = ({ profile, eventType, ...restProps }: Props) => {
{timezoneDropdown}
</BookingDescription>
{!isEmbed && (
<div className="mt-auto hidden md:block">
<GoBackToPreviousPage t={t} />
</div>
)}
{/* Temporarily disabled - booking?.startTime && rescheduleUid && (
<div>
<p
@@ -468,7 +442,7 @@ const AvailabilityPage = ({ profile, eventType, ...restProps }: Props) => {
/>
</div>
</div>
{(!eventType.users[0] || !isBrandingHidden(eventType.users[0])) && !isEmbed && <PoweredByCal />}
{(!restProps.isBrandingHidden || isEmbed) && <PoweredByCal />}
</div>
</main>
</div>
@@ -39,11 +39,11 @@ import { HttpError } from "@calcom/lib/http-error";
import { getEveryFreqFor } from "@calcom/lib/recurringStrings";
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
import { AddressInput, Button, EmailInput, Form, Icon, PhoneInput, Tooltip } from "@calcom/ui";
import { Group, RadioField } from "@calcom/ui";
import { asStringOrNull } from "@lib/asStringOrNull";
import { timeZone } from "@lib/clock";
import { ensureArray } from "@lib/ensureArray";
import useMeQuery from "@lib/hooks/useMeQuery";
import useRouterQuery from "@lib/hooks/useRouterQuery";
import createBooking from "@lib/mutations/bookings/create-booking";
import createRecurringBooking from "@lib/mutations/bookings/create-recurring-booking";
@@ -103,7 +103,6 @@ const BookingPage = ({
{}
);
const stripeAppData = getStripeAppData(eventType);
// Define duration now that we support multiple duration eventTypes
let duration = eventType.length;
if (queryDuration && !isNaN(Number(queryDuration))) {
@@ -241,7 +240,7 @@ const BookingPage = ({
const bookingFormSchema = z
.object({
name: z.string().min(1),
email: z.string().email(),
email: z.string().trim().email(),
phone: z
.string()
.refine((val) => isValidPhoneNumber(val))
@@ -745,6 +744,27 @@ const BookingPage = ({
</div>
</div>
)}
{input.options && input.type === EventTypeCustomInputType.RADIO && (
<div className="">
<div className="flex">
<Group
onValueChange={(e) => {
bookingForm.setValue(`customInputs.${input.id}`, e);
}}>
<>
{input.options.map((option, i) => (
<RadioField
label={option.label}
key={`option.${i}.radio`}
value={option.label}
id={`option.${i}.radio`}
/>
))}
</>
</Group>
</div>
</div>
)}
</div>
))}
{!eventType.disableGuests && guestToggle && (
@@ -297,7 +297,7 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
control={locationFormMethods.control}
render={() => (
<Select<{ label: string; value: string; icon?: string }>
maxMenuHeight={150}
maxMenuHeight={300}
name="location"
defaultValue={selection}
options={locationOptions}
@@ -20,12 +20,13 @@ type AvailabilityOption = {
const Option = ({ ...props }: OptionProps<AvailabilityOption>) => {
const { label, isDefault } = props.data;
const { t } = useLocale();
return (
<components.Option {...props}>
<span>{label}</span>
{isDefault && (
<Badge variant="blue" className="ml-2">
Default
{t("default")}
</Badge>
)}
</components.Option>
@@ -34,12 +35,13 @@ const Option = ({ ...props }: OptionProps<AvailabilityOption>) => {
const SingleValue = ({ ...props }: SingleValueProps<AvailabilityOption>) => {
const { label, isDefault } = props.data;
const { t } = useLocale();
return (
<components.SingleValue {...props}>
<span>{label}</span>
{isDefault && (
<Badge variant="blue" className="ml-2">
Default
{t("default")}
</Badge>
)}
</components.SingleValue>
@@ -1,23 +1,33 @@
import { EventTypeCustomInput, EventTypeCustomInputType } from "@prisma/client";
import { useAutoAnimate } from "@formkit/auto-animate/react";
import { EventTypeCustomInputType } from "@prisma/client";
import type { CustomInputParsed } from "pages/event-types/[type]";
import { FC } from "react";
import { Controller, SubmitHandler, useForm, useWatch } from "react-hook-form";
import { Control, Controller, useFieldArray, useForm, UseFormRegister, useWatch } from "react-hook-form";
import { Button, Select, TextField } from "@calcom/ui";
import { useLocale } from "@lib/hooks/useLocale";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon, Label, Select, TextField } from "@calcom/ui";
interface OptionTypeBase {
label: string;
value: EventTypeCustomInputType;
options?: { label: string; type: string }[];
}
interface Props {
onSubmit: SubmitHandler<IFormInput>;
onSubmit: (output: CustomInputParsed) => void;
onCancel: () => void;
selectedCustomInput?: EventTypeCustomInput;
selectedCustomInput?: CustomInputParsed;
}
type IFormInput = EventTypeCustomInput;
type IFormInput = CustomInputParsed;
/**
* Getting a random ID gives us the option to know WHICH field is changed
* when the user edits a custom field.
* This UUID is only used to check for changes in the UI and not the ID we use in the DB
* There is very very very slim chance that this will cause a collision
* */
const randomId = () => Math.floor(Math.random() * 1000000 + new Date().getTime());
const CustomInputTypeForm: FC<Props> = (props) => {
const { t } = useLocale();
@@ -26,10 +36,22 @@ const CustomInputTypeForm: FC<Props> = (props) => {
{ value: EventTypeCustomInputType.TEXTLONG, label: t("multiline_text") },
{ value: EventTypeCustomInputType.NUMBER, label: t("number") },
{ value: EventTypeCustomInputType.BOOL, label: t("checkbox") },
{
value: EventTypeCustomInputType.RADIO,
label: t("radio"),
},
];
const { selectedCustomInput } = props;
const defaultValues = selectedCustomInput || { type: inputOptions[0].value };
const { register, control, handleSubmit } = useForm<IFormInput>({
const defaultValues = selectedCustomInput
? { ...selectedCustomInput, id: selectedCustomInput?.id || randomId() }
: {
id: randomId(),
type: EventTypeCustomInputType.TEXT,
};
const { register, control, getValues } = useForm<IFormInput>({
defaultValues,
});
const selectedInputType = useWatch({ name: "type", control });
@@ -40,7 +62,7 @@ const CustomInputTypeForm: FC<Props> = (props) => {
};
return (
<form className="flex flex-col space-y-4">
<div className="flex flex-col space-y-4">
<div>
<label htmlFor="type" className="block text-sm font-medium text-gray-700">
{t("input_type")}
@@ -83,6 +105,10 @@ const CustomInputTypeForm: FC<Props> = (props) => {
{...register("placeholder")}
/>
)}
{selectedInputType === EventTypeCustomInputType.RADIO && (
<RadioInputHandler control={control} register={register} />
)}
<div className="flex h-5 items-center">
<input
id="required"
@@ -111,12 +137,75 @@ const CustomInputTypeForm: FC<Props> = (props) => {
<Button onClick={onCancel} type="button" color="secondary" className="ltr:mr-2">
{t("cancel")}
</Button>
<Button onClick={handleSubmit(props.onSubmit)} form="custom-input">
<Button
type="button"
onClick={() => {
props.onSubmit(getValues());
}}>
{t("save")}
</Button>
</div>
</form>
</div>
);
};
function RadioInputHandler({
register,
control,
}: {
register: UseFormRegister<IFormInput>;
control: Control<IFormInput>;
}) {
const { t } = useLocale();
const { fields, append, remove } = useFieldArray<IFormInput>({
control,
name: "options",
shouldUnregister: true,
});
const [animateRef] = useAutoAnimate<HTMLUListElement>();
return (
<div className="flex flex-col ">
<Label htmlFor="radio_options">{t("options")}</Label>
<ul
className="flex max-h-80 w-full flex-col space-y-1 overflow-y-scroll rounded-md bg-gray-50 p-4"
ref={animateRef}>
<>
{fields.map((option, index) => (
<li key={`${option.id}`}>
<TextField
id={option.id}
placeholder={t("enter_option", { index: index + 1 })}
addOnFilled={false}
label={t("option", { index: index + 1 })}
labelSrOnly
{...register(`options.${index}.label` as const, { required: true })}
addOnSuffix={
<Button
size="icon"
color="minimal"
StartIcon={Icon.FiX}
onClick={() => {
remove(index);
}}
/>
}
/>
</li>
))}
<Button
color="minimal"
StartIcon={Icon.FiPlus}
className="!text-sm !font-medium"
onClick={() => {
append({ label: "", type: "text" });
}}>
{t("add_an_option")}
</Button>
</>
</ul>
</div>
);
}
export default CustomInputTypeForm;
@@ -1,371 +0,0 @@
import { ErrorMessage } from "@hookform/error-message";
import { zodResolver } from "@hookform/resolvers/zod";
import { isValidPhoneNumber } from "libphonenumber-js";
import { Trans } from "next-i18next";
import { useEffect } from "react";
import { Controller, useForm, useWatch } from "react-hook-form";
import { components } from "react-select";
import { z } from "zod";
import {
EventLocationType,
getEventLocationType,
getHumanReadableLocationValue,
getMessageForOrganizer,
LocationObject,
LocationType,
} from "@calcom/app-store/locations";
import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { RouterOutputs, trpc } from "@calcom/trpc/react";
import { Button, Dialog, DialogContent, Form, Icon, Label, PhoneInput, Select } from "@calcom/ui";
import { QueryCell } from "@lib/QueryCell";
import { LinkText } from "@components/ui/LinkText";
import CheckboxField from "@components/ui/form/CheckboxField";
type BookingItem = RouterOutputs["viewer"]["bookings"]["get"]["bookings"][number];
type OptionTypeBase = {
label: string;
value: EventLocationType["type"];
disabled?: boolean;
};
interface ISetLocationDialog {
saveLocation: (newLocationType: EventLocationType["type"], details: { [key: string]: string }) => void;
selection?: OptionTypeBase;
booking?: BookingItem;
defaultValues?: LocationObject[];
setShowLocationModal: React.Dispatch<React.SetStateAction<boolean>>;
isOpenDialog: boolean;
setSelectedLocation?: (param: OptionTypeBase | undefined) => void;
}
const LocationInput = (props: {
eventLocationType: EventLocationType;
locationFormMethods: ReturnType<typeof useForm>;
id: string;
required: boolean;
placeholder: string;
className?: string;
defaultValue?: string;
}): JSX.Element | null => {
const { eventLocationType, locationFormMethods, ...remainingProps } = props;
if (eventLocationType?.organizerInputType === "text") {
return (
<input {...locationFormMethods.register(eventLocationType.variable)} type="text" {...remainingProps} />
);
} else if (eventLocationType?.organizerInputType === "phone") {
return (
<PhoneInput
name={eventLocationType.variable}
control={locationFormMethods.control}
{...remainingProps}
/>
);
}
return null;
};
export const EditLocationDialog = (props: ISetLocationDialog) => {
const {
saveLocation,
selection,
booking,
setShowLocationModal,
isOpenDialog,
defaultValues,
setSelectedLocation,
} = props;
const { t } = useLocale();
const locationsQuery = trpc.viewer.locationOptions.useQuery();
useEffect(() => {
if (selection) {
locationFormMethods.setValue("locationType", selection?.value);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selection]);
const locationFormSchema = z.object({
locationType: z.string(),
phone: z.string().optional(),
locationAddress: z.string().optional(),
locationLink: z
.string()
.optional()
.superRefine((val, ctx) => {
if (
eventLocationType &&
!eventLocationType.default &&
eventLocationType.linkType === "static" &&
eventLocationType.urlRegExp
) {
const valid = z
.string()
.regex(new RegExp(eventLocationType.urlRegExp || ""))
.safeParse(val).success;
if (!valid) {
const sampleUrl = eventLocationType.organizerInputPlaceholder;
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `Invalid URL for ${eventLocationType.label}. ${
sampleUrl ? "Sample URL: " + sampleUrl : ""
}`,
});
}
return;
}
const valid = z.string().url().optional().safeParse(val).success;
if (!valid) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `Invalid URL`,
});
}
return;
}),
displayLocationPublicly: z.boolean().optional(),
locationPhoneNumber: z
.string()
.refine((val) => isValidPhoneNumber(val))
.optional(),
});
const locationFormMethods = useForm({
mode: "onSubmit",
resolver: zodResolver(locationFormSchema),
});
const selectedLocation = useWatch({
control: locationFormMethods.control,
name: "locationType",
});
const eventLocationType = getEventLocationType(selectedLocation);
const defaultLocation = defaultValues?.find(
(location: { type: EventLocationType["type"] }) => location.type === eventLocationType?.type
);
const LocationOptions = (() => {
if (eventLocationType && eventLocationType.organizerInputType && LocationInput) {
if (!eventLocationType.variable) {
console.error("eventLocationType.variable can't be undefined");
return null;
}
return (
<div>
<div>
<Label htmlFor="locationInput">{t(eventLocationType.messageForOrganizer || "")}</Label>
<LocationInput
locationFormMethods={locationFormMethods}
eventLocationType={eventLocationType}
id="locationInput"
placeholder={t(eventLocationType.organizerInputPlaceholder || "")}
required
className="block w-full rounded-md border-gray-300 text-sm"
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
defaultValue={
(defaultLocation && defaultLocation[eventLocationType.defaultValueVariable]) || ""
}
/>
<ErrorMessage
errors={locationFormMethods.formState.errors}
name={eventLocationType.variable}
className="mt-1 text-sm text-red-500"
as="p"
/>
</div>
{!booking && (
<div className="mt-3">
<Controller
name="displayLocationPublicly"
control={locationFormMethods.control}
render={() => (
<CheckboxField
defaultChecked={defaultLocation?.displayLocationPublicly}
description={t("display_location_label")}
onChange={(e) =>
locationFormMethods.setValue("displayLocationPublicly", e.target.checked)
}
informationIconText={t("display_location_info_badge")}
/>
)}
/>
</div>
)}
</div>
);
} else {
return <p className="text-sm">{getMessageForOrganizer(selectedLocation, t)}</p>;
}
})();
return (
<Dialog open={isOpenDialog}>
<DialogContent
type="creation"
Icon={Icon.FiMapPin}
title={t("edit_location")}
description={!booking ? t("this_input_will_shown_booking_this_event") : undefined}>
{booking && (
<>
<p className="mt-6 mb-2 ml-1 text-sm font-bold text-black">{t("current_location")}:</p>
<p className="mb-2 ml-1 text-sm text-black">
{getHumanReadableLocationValue(booking.location, t)}
</p>
</>
)}
<Form
form={locationFormMethods}
className="space-y-4"
handleSubmit={async (values) => {
const { locationType: newLocation, displayLocationPublicly } = values;
let details = {};
if (newLocation === LocationType.AttendeeInPerson) {
details = {
address: values.locationAddress,
};
}
if (newLocation === LocationType.InPerson) {
details = {
address: values.locationAddress,
};
}
const eventLocationType = getEventLocationType(newLocation);
// TODO: There can be a property that tells if it is to be saved in `link`
if (
newLocation === LocationType.Link ||
(!eventLocationType?.default && eventLocationType?.linkType === "static")
) {
details = { link: values.locationLink };
}
if (newLocation === LocationType.UserPhone) {
details = { hostPhoneNumber: values.locationPhoneNumber };
}
if (eventLocationType?.organizerInputType) {
details = {
...details,
displayLocationPublicly,
};
}
saveLocation(newLocation, details);
setShowLocationModal(false);
setSelectedLocation?.(undefined);
locationFormMethods.unregister([
"locationType",
"locationLink",
"locationAddress",
"locationPhoneNumber",
]);
}}>
<QueryCell
query={locationsQuery}
success={({ data: locationOptions }) => {
if (!locationOptions.length) return null;
if (booking) {
locationOptions.forEach((location) => {
if (location.label === "phone") {
location.options.filter((l) => l.value !== "phone");
}
});
}
return (
<Controller
name="locationType"
control={locationFormMethods.control}
render={() => (
<Select<{ label: string; value: string; icon?: string }>
maxMenuHeight={150}
name="location"
defaultValue={selection}
options={locationOptions}
components={{
Option: (props) => (
<components.Option {...props}>
<div className="flex items-center gap-3">
{props.data.icon && (
<img src={props.data.icon} alt="cover" className="h-3.5 w-3.5" />
)}
<span
className={classNames(
"text-sm font-medium",
props.isSelected ? "text-white" : "text-gray-900"
)}>
{props.data.label}
</span>
</div>
</components.Option>
),
}}
formatOptionLabel={(e) => (
<div className="flex items-center gap-2.5">
{e.icon && <img src={e.icon} alt="app-icon" className="h-5 w-5" />}
<span>{e.label}</span>
</div>
)}
formatGroupLabel={(e) => <p className="text-xs font-medium text-gray-600">{e.label}</p>}
isSearchable={false}
onChange={(val) => {
if (val) {
locationFormMethods.setValue("locationType", val.value);
locationFormMethods.unregister([
"locationLink",
"locationAddress",
"locationPhoneNumber",
]);
locationFormMethods.clearErrors([
"locationLink",
"locationPhoneNumber",
"locationAddress",
]);
setSelectedLocation?.(val);
}
}}
/>
)}
/>
);
}}
/>
{selectedLocation && LocationOptions}
<div className="mt-5">
<p className="text-sm text-gray-400">
<Trans i18nKey="cant_find_the_right_video_app_visit_our_app_store">
Can&apos;t find the right video app? Visit our
<LinkText href="/apps/categories/video" classNameChildren="text-blue-400" target="_blank">
App Store
</LinkText>
.
</Trans>
</p>
</div>
<div className="mt-4 flex justify-end space-x-2">
<Button
onClick={() => {
setShowLocationModal(false);
setSelectedLocation?.(undefined);
locationFormMethods.unregister("locationType");
}}
type="button"
color="secondary">
{t("cancel")}
</Button>
<Button type="submit">{t("update")}</Button>
</div>
</Form>
</DialogContent>
</Dialog>
);
};
@@ -1,6 +1,5 @@
import { EventTypeCustomInput } from "@prisma/client/";
import Link from "next/link";
import { EventTypeSetupInfered, FormValues } from "pages/event-types/[type]";
import type { CustomInputParsed, EventTypeSetupInfered, FormValues } from "pages/event-types/[type]";
import { useEffect, useState } from "react";
import { Controller, useFormContext } from "react-hook-form";
import short from "short-uuid";
@@ -28,6 +27,8 @@ import {
import CustomInputTypeForm from "@components/eventtype/CustomInputTypeForm";
import RequiresConfirmationController from "./RequiresConfirmationController";
const generateHashedLink = (id: number) => {
const translator = short();
const seed = `${id}:${new Date().getTime()}`;
@@ -43,11 +44,12 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
const [hashedLinkVisible, setHashedLinkVisible] = useState(!!eventType.hashedLink);
const [redirectUrlVisible, setRedirectUrlVisible] = useState(!!eventType.successRedirectUrl);
const [hashedUrl, setHashedUrl] = useState(eventType.hashedLink?.link);
const [customInputs, setCustomInputs] = useState<EventTypeCustomInput[]>(
const [customInputs, setCustomInputs] = useState<CustomInputParsed[]>(
eventType.customInputs.sort((a, b) => a.id - b.id) || []
);
const [selectedCustomInput, setSelectedCustomInput] = useState<EventTypeCustomInput | undefined>(undefined);
const [selectedCustomInput, setSelectedCustomInput] = useState<CustomInputParsed | undefined>(undefined);
const [selectedCustomInputModalOpen, setSelectedCustomInputModalOpen] = useState(false);
const [requiresConfirmation, setRequiresConfirmation] = useState(eventType.requiresConfirmation);
const placeholderHashedLink = `${CAL_URL}/d/${hashedUrl}/${eventType.slug}`;
const seatsEnabled = formMethods.getValues("seatsPerTimeSlotEnabled");
@@ -101,7 +103,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
<TextField
label={t("event_name")}
type="text"
placeholder={t("meeting_with_user")}
placeholder={t("meeting_with_user", { attendeeName: eventType.users[0]?.name })}
defaultValue={eventType.eventName || ""}
{...formMethods.register("eventName")}
addOnSuffix={
@@ -125,15 +127,13 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
onCheckedChange={(e) => {
if (e && customInputs.length === 0) {
// Push a placeholders
setSelectedCustomInput(undefined);
setSelectedCustomInputModalOpen(true);
} else if (!e) {
setCustomInputs([]);
formMethods.setValue("customInputs", []);
}
}}>
<ul className="my-4 rounded-md border">
{customInputs.map((customInput: EventTypeCustomInput, idx: number) => (
{customInputs.map((customInput, idx) => (
<CustomInputItem
key={idx}
question={customInput.label}
@@ -162,18 +162,11 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
</SettingsToggle>
</div>
<hr />
<Controller
name="requiresConfirmation"
defaultValue={eventType.requiresConfirmation}
render={({ field: { value, onChange } }) => (
<SettingsToggle
title={t("requires_confirmation")}
description={t("requires_confirmation_description")}
checked={value}
onCheckedChange={(e) => onChange(e)}
disabled={seatsEnabled}
/>
)}
<RequiresConfirmationController
seatsEnabled={seatsEnabled}
metadata={eventType.metadata}
requiresConfirmation={requiresConfirmation}
onRequiresConfirmation={setRequiresConfirmation}
/>
<hr />
<Controller
@@ -309,6 +302,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
if (e) {
formMethods.setValue("disableGuests", true);
formMethods.setValue("requiresConfirmation", false);
setRequiresConfirmation(false);
formMethods.setValue("seatsPerTimeSlot", 2);
} else {
formMethods.setValue("seatsPerTimeSlot", null);
@@ -358,7 +352,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
<TextField
label={t("event_name")}
type="text"
placeholder={t("meeting_with_user")}
placeholder={t("meeting_with_user", { attendeeName: eventType.users[0]?.name })}
defaultValue={eventType.eventName || ""}
{...formMethods.register("eventName")}
/>
@@ -391,24 +385,36 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
<CustomInputTypeForm
selectedCustomInput={selectedCustomInput}
onSubmit={(values) => {
const customInput: EventTypeCustomInput = {
const customInput: CustomInputParsed = {
id: -1,
eventTypeId: -1,
label: values.label,
placeholder: values.placeholder,
required: values.required,
type: values.type,
options: values.options,
};
if (selectedCustomInput) {
selectedCustomInput.label = customInput.label;
selectedCustomInput.placeholder = customInput.placeholder;
selectedCustomInput.required = customInput.required;
selectedCustomInput.type = customInput.type;
selectedCustomInput.options = customInput.options || undefined;
// Update by id
const inputIndex = customInputs.findIndex((input) => input.id === values.id);
customInputs[inputIndex] = selectedCustomInput;
setCustomInputs(customInputs);
formMethods.setValue("customInputs", customInputs);
} else {
setCustomInputs(customInputs.concat(customInput));
formMethods.setValue("customInputs", customInputs.concat(customInput));
const concatted = customInputs.concat({
...customInput,
options: customInput.options,
});
console.log(concatted);
setCustomInputs(concatted);
formMethods.setValue("customInputs", concatted);
}
setSelectedCustomInputModalOpen(false);
}}
onCancel={() => {
@@ -33,22 +33,10 @@ export const EventSetupTab = (
const [selectedLocation, setSelectedLocation] = useState<OptionTypeBase | undefined>(undefined);
const [multipleDuration, setMultipleDuration] = useState(eventType.metadata.multipleDuration);
const multipleDurationOptions = [
{ value: 5, label: t("multiple_duration_mins", { count: 5 }) },
{ value: 10, label: t("multiple_duration_mins", { count: 10 }) },
{ value: 15, label: t("multiple_duration_mins", { count: 15 }) },
{ value: 20, label: t("multiple_duration_mins", { count: 20 }) },
{ value: 25, label: t("multiple_duration_mins", { count: 25 }) },
{ value: 30, label: t("multiple_duration_mins", { count: 30 }) },
{ value: 45, label: t("multiple_duration_mins", { count: 45 }) },
{ value: 50, label: t("multiple_duration_mins", { count: 50 }) },
{ value: 60, label: t("multiple_duration_mins", { count: 60 }) },
{ value: 75, label: t("multiple_duration_mins", { count: 75 }) },
{ value: 80, label: t("multiple_duration_mins", { count: 80 }) },
{ value: 90, label: t("multiple_duration_mins", { count: 90 }) },
{ value: 120, label: t("multiple_duration_mins", { count: 120 }) },
{ value: 180, label: t("multiple_duration_mins", { count: 180 }) },
];
const multipleDurationOptions = [5, 10, 15, 20, 25, 30, 45, 50, 60, 75, 80, 90, 120, 180].map((mins) => ({
value: mins,
label: t("multiple_duration_mins", { count: mins }),
}));
const [selectedMultipleDuration, setSelectedMultipleDuration] = useState<
MultiValue<{
@@ -142,6 +130,7 @@ export const EventSetupTab = (
{validLocations.length === 0 && (
<div className="flex">
<Select
placeholder={t("select")}
options={locationOptions}
isSearchable={false}
className="block w-full min-w-0 flex-1 rounded-sm text-sm"
@@ -224,7 +213,7 @@ export const EventSetupTab = (
<div className="space-y-8">
<TextField
required
label={t("Title")}
label={t("title")}
defaultValue={eventType.title}
{...formMethods.register("title")}
/>
@@ -67,7 +67,7 @@ function getNavigation(props: {
name: "availability",
href: `/event-types/${eventType.id}?tabName=availability`,
icon: Icon.FiCalendar,
info: `Working Hours`, // TODO: Get this from props
info: `default_schedule_name`, // TODO: Get this from props
},
{
name: "event_limit_tab_title",
@@ -0,0 +1,156 @@
import * as RadioGroup from "@radix-ui/react-radio-group";
import { UnitTypeLongPlural } from "dayjs";
import { Trans } from "next-i18next";
import type { FormValues } from "pages/event-types/[type]";
import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { Controller, useFormContext } from "react-hook-form";
import z from "zod";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { Alert, Input, Label, SettingsToggle } from "@calcom/ui";
type RequiresConfirmationControllerProps = {
metadata: z.infer<typeof EventTypeMetaDataSchema>;
requiresConfirmation: boolean;
onRequiresConfirmation: Dispatch<SetStateAction<boolean>>;
seatsEnabled: boolean;
};
export default function RequiresConfirmationController({
metadata,
requiresConfirmation,
onRequiresConfirmation,
seatsEnabled,
}: RequiresConfirmationControllerProps) {
const { t } = useLocale();
const [requiresConfirmationSetup, setRequiresConfirmationSetup] = useState(
metadata?.requiresConfirmationThreshold
);
const defaultRequiresConfirmationSetup = { time: 30, unit: "minutes" as UnitTypeLongPlural };
const formMethods = useFormContext<FormValues>();
useEffect(() => {
if (!requiresConfirmation) {
formMethods.setValue("metadata.requiresConfirmationThreshold", undefined);
}
}, [requiresConfirmation]);
return (
<div className="block items-start sm:flex">
<div className={!seatsEnabled ? "w-full" : ""}>
{seatsEnabled ? (
<Alert severity="warning" title="Seats option doesn't support confirmation requirement" />
) : (
<Controller
name="requiresConfirmation"
control={formMethods.control}
render={() => (
<SettingsToggle
title={t("requires_confirmation")}
description={t("requires_confirmation_description")}
checked={requiresConfirmation}
onCheckedChange={(val) => {
formMethods.setValue("requiresConfirmation", val);
onRequiresConfirmation(val);
}}>
<RadioGroup.Root
defaultValue={
requiresConfirmation
? requiresConfirmationSetup === undefined
? "always"
: "notice"
: undefined
}
onValueChange={(val) => {
if (val === "always") {
formMethods.setValue("requiresConfirmation", true);
onRequiresConfirmation(true);
formMethods.setValue("metadata.requiresConfirmationThreshold", undefined);
setRequiresConfirmationSetup(undefined);
} else if (val === "notice") {
formMethods.setValue("requiresConfirmation", true);
onRequiresConfirmation(true);
formMethods.setValue(
"metadata.requiresConfirmationThreshold",
requiresConfirmationSetup || defaultRequiresConfirmationSetup
);
}
}}>
<div className="-ml-2 flex flex-col flex-wrap justify-start gap-y-2 space-y-2">
<div className="flex items-center">
<RadioGroup.Item
id="always"
value="always"
className="min-w-4 flex h-4 w-4 cursor-pointer items-center rounded-full border border-black bg-white focus:border-2 focus:outline-none ltr:mr-2 rtl:ml-2">
<RadioGroup.Indicator className="relative flex h-4 w-4 items-center justify-center after:block after:h-2 after:w-2 after:rounded-full after:bg-black" />
</RadioGroup.Item>
<Label htmlFor="always" className="!m-0 flex items-center">
{t("always_requires_confirmation")}
</Label>
</div>
<div className="flex items-center">
<RadioGroup.Item
id="notice"
value="notice"
className="min-w-4 flex h-4 w-4 cursor-pointer items-center rounded-full border border-black bg-white focus:border-2 focus:outline-none ltr:mr-2 rtl:ml-2">
<RadioGroup.Indicator className="relative flex h-4 w-4 items-center justify-center after:block after:h-2 after:w-2 after:rounded-full after:bg-black" />
</RadioGroup.Item>
<Label htmlFor="notice" className="!m-0 flex items-center">
<Trans
i18nKey="when_booked_with_less_than_notice"
defaults="When booked with less than <time></time> notice"
components={{
time: (
<div className="mx-2 flex">
<Input
type="number"
min={1}
onChange={(evt) => {
const val = Number(evt.target?.value);
setRequiresConfirmationSetup({
unit:
requiresConfirmationSetup?.unit ??
defaultRequiresConfirmationSetup.unit,
time: val,
});
formMethods.setValue("metadata.requiresConfirmationThreshold.time", val);
}}
className="!m-0 block w-16 rounded-md border-gray-300 text-sm [appearance:textfield]"
defaultValue={metadata?.requiresConfirmationThreshold?.time || 30}
/>
<select
onChange={(evt) => {
const val = evt.target.value as UnitTypeLongPlural;
setRequiresConfirmationSetup({
time:
requiresConfirmationSetup?.time ??
defaultRequiresConfirmationSetup.time,
unit: val,
});
formMethods.setValue("metadata.requiresConfirmationThreshold.unit", val);
}}
className="ml-2 block h-9 rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:outline-none"
defaultValue={
metadata?.requiresConfirmationThreshold?.unit ||
defaultRequiresConfirmationSetup.unit
}>
<option value="minutes">{t("minute_timeUnit")}</option>
<option value="hours">{t("hour_timeUnit")}</option>
</select>
</div>
),
}}
/>
</Label>
</div>
</div>
</RadioGroup.Root>
</SettingsToggle>
)}
/>
)}
</div>
</div>
);
}
@@ -4,21 +4,20 @@ import { FormEvent, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { User } from "@calcom/prisma/client";
import { trpc } from "@calcom/trpc/react";
import { Button, ImageUploader, showToast, TextArea } from "@calcom/ui";
import { Avatar } from "@calcom/ui";
import { AvatarSSR } from "@components/ui/AvatarSSR";
interface IUserProfile {
user?: User;
}
import type { IOnboardingPageProps } from "../../../pages/getting-started/[[...step]]";
type FormData = {
bio: string;
};
interface IUserProfileProps {
user: IOnboardingPageProps["user"];
}
const UserProfile = (props: IUserProfile) => {
const UserProfile = (props: IUserProfileProps) => {
const { user } = props;
const { t } = useLocale();
const avatarRef = useRef<HTMLInputElement>(null!);
@@ -100,7 +99,14 @@ const UserProfile = (props: IUserProfile) => {
return (
<form onSubmit={onSubmit}>
<div className="flex flex-row items-center justify-start rtl:justify-end">
{user && <AvatarSSR user={user} alt="Profile picture" className="h-16 w-16" />}
{user && (
<Avatar
alt={user.username || "user avatar"}
gravatarFallbackMd5={user.emailMd5}
size="lg"
imageSrc={imageSrc}
/>
)}
<input
ref={avatarRef}
type="hidden"
@@ -1,17 +1,18 @@
import { ArrowRightIcon } from "@heroicons/react/outline";
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { useForm } from "react-hook-form";
import dayjs from "@calcom/dayjs";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { User } from "@calcom/prisma/client";
import { trpc } from "@calcom/trpc/react";
import { Button, TimezoneSelect } from "@calcom/ui";
import { UsernameAvailability } from "@components/ui/UsernameAvailability";
import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability";
import type { IOnboardingPageProps } from "../../../pages/getting-started/[[...step]]";
interface IUserSettingsProps {
user: User;
user: IOnboardingPageProps["user"];
nextStep: () => void;
}
@@ -23,11 +24,9 @@ const UserSettings = (props: IUserSettingsProps) => {
register,
handleSubmit,
formState: { errors },
control,
} = useForm({
defaultValues: {
name: user?.name || "",
username: user?.username || "",
},
reValidateMode: "onChange",
});
@@ -41,39 +40,19 @@ const UserSettings = (props: IUserSettingsProps) => {
const mutation = trpc.viewer.updateProfile.useMutation({
onSuccess: onSuccess,
});
const { data: stripeCustomer } = trpc.viewer.stripeCustomer.useQuery();
const paymentRequired = stripeCustomer?.isPremium ? !stripeCustomer?.paidForPremium : false;
const onSubmit = handleSubmit((data) => {
if (paymentRequired) {
return;
}
mutation.mutate({
name: data.name,
timeZone: selectedTimeZone,
});
});
const [currentUsername, setCurrentUsername] = useState(user.username || "");
return (
<form onSubmit={onSubmit}>
<div className="space-y-6">
{/* Username textfield */}
<Controller
control={control}
name="username"
render={({ field: { value, ref, onChange } }) => (
<UsernameAvailability
readonly={true}
currentUsername={currentUsername}
setCurrentUsername={setCurrentUsername}
inputUsernameValue={value}
usernameRef={ref}
setInputUsernameValue={onChange}
user={user}
/>
)}
/>
<UsernameAvailabilityField user={user} />
{/* Full name textfield */}
<div className="w-full">
@@ -1,134 +0,0 @@
import { EventTypeCustomInput, EventTypeCustomInputType } from "@prisma/client";
import React, { FC } from "react";
import { Controller, SubmitHandler, useForm, useWatch } from "react-hook-form";
import { Button } from "@calcom/ui";
import { useLocale } from "@lib/hooks/useLocale";
import Select from "@components/ui/form/Select";
interface OptionTypeBase {
label: string;
value: EventTypeCustomInputType;
}
interface Props {
onSubmit: SubmitHandler<IFormInput>;
onCancel: () => void;
selectedCustomInput?: EventTypeCustomInput;
}
type IFormInput = EventTypeCustomInput;
const CustomInputTypeForm: FC<Props> = (props) => {
const { t } = useLocale();
const inputOptions: OptionTypeBase[] = [
{ value: EventTypeCustomInputType.TEXT, label: t("text") },
{ value: EventTypeCustomInputType.TEXTLONG, label: t("multiline_text") },
{ value: EventTypeCustomInputType.NUMBER, label: t("number") },
{ value: EventTypeCustomInputType.BOOL, label: t("checkbox") },
];
const { selectedCustomInput } = props;
const defaultValues = selectedCustomInput || { type: inputOptions[0].value };
const { register, control, handleSubmit } = useForm<IFormInput>({
defaultValues,
});
const selectedInputType = useWatch({ name: "type", control });
const selectedInputOption = inputOptions.find((e) => selectedInputType === e.value);
const onCancel = () => {
props.onCancel();
};
return (
<form onSubmit={handleSubmit(props.onSubmit)}>
<div className="mb-2">
<label htmlFor="type" className="block text-sm font-medium text-gray-700">
{t("input_type")}
</label>
<Controller
name="type"
control={control}
render={({ field }) => (
<Select
id="type"
defaultValue={selectedInputOption}
options={inputOptions}
isSearchable={false}
className="mt-1 mb-2 block w-full min-w-0 flex-1 text-sm"
onChange={(option) => option && field.onChange(option.value)}
value={selectedInputOption}
onBlur={field.onBlur}
name={field.name}
/>
)}
/>
</div>
<div className="mb-2">
<label htmlFor="label" className="block text-sm font-medium text-gray-700">
{t("label")}
</label>
<div className="mt-1">
<input
type="text"
id="label"
required
className="block w-full rounded-sm border-gray-300 text-sm"
defaultValue={selectedCustomInput?.label}
{...register("label", { required: true })}
/>
</div>
</div>
{(selectedInputType === EventTypeCustomInputType.TEXT ||
selectedInputType === EventTypeCustomInputType.TEXTLONG) && (
<div className="mb-2">
<label htmlFor="placeholder" className="block text-sm font-medium text-gray-700">
{t("placeholder")}
</label>
<div className="mt-1">
<input
type="text"
id="placeholder"
className="block w-full rounded-sm border-gray-300 text-sm"
defaultValue={selectedCustomInput?.placeholder}
{...register("placeholder")}
/>
</div>
</div>
)}
<div className="flex h-5 items-center">
<input
id="required"
type="checkbox"
className="text-primary-600 focus:ring-primary-500 h-4 w-4 rounded border-gray-300 ltr:mr-2 rtl:ml-2"
defaultChecked={selectedCustomInput?.required ?? true}
{...register("required")}
/>
<label htmlFor="required" className="block text-sm font-medium text-gray-700">
{t("is_required")}
</label>
</div>
<input
type="hidden"
id="eventTypeId"
value={selectedCustomInput?.eventTypeId || -1}
{...register("eventTypeId", { valueAsNumber: true })}
/>
<input
type="hidden"
id="id"
value={selectedCustomInput?.id || -1}
{...register("id", { valueAsNumber: true })}
/>
<div className="mt-5 flex space-x-2 sm:mt-4">
<Button onClick={onCancel} type="button" color="secondary" className="ltr:mr-2">
{t("cancel")}
</Button>
<Button type="submit">{t("save")}</Button>
</div>
</form>
);
};
export default CustomInputTypeForm;
@@ -0,0 +1,73 @@
import type { Attendee, Booking, User } from "@prisma/client";
import type { FC } from "react";
import { useMemo } from "react";
import { JsonLd } from "react-schemaorg";
import type { EventReservation, Person, ReservationStatusType } from "schema-dts";
type EventSchemaUser = Pick<User, "name" | "email">;
type EventSchemaAttendee = Pick<Attendee, "name" | "email">;
interface EventReservationSchemaInterface {
reservationId: Booking["uid"];
eventName: Booking["title"];
startTime: Booking["startTime"];
endTime: Booking["endTime"];
organizer: EventSchemaUser | null;
attendees: EventSchemaAttendee[];
location: Booking["location"];
description: Booking["description"];
status: Booking["status"];
}
const EventReservationSchema: FC<EventReservationSchemaInterface> = ({
reservationId,
eventName,
startTime,
endTime,
organizer,
attendees,
location,
description,
status,
}) => {
const reservationStatus = useMemo<ReservationStatusType>(() => {
switch (status) {
case "ACCEPTED":
return "ReservationConfirmed";
case "REJECTED":
case "CANCELLED":
return "ReservationCancelled";
case "PENDING":
return "ReservationPending";
default:
return "ReservationHold";
}
}, [status]);
return (
<JsonLd<EventReservation>
item={{
"@context": "https://schema.org",
"@type": "EventReservation",
reservationId,
reservationStatus,
reservationFor: {
"@type": "Event",
name: eventName,
startDate: startTime.toString(),
endDate: endTime.toString(),
organizer: organizer
? ({ "@type": "Person", name: organizer.name, email: organizer.email } as Person)
: undefined,
attendee: attendees?.map(
(person) => ({ "@type": "Person", name: person.name, email: person.email } as Person)
),
location: location || undefined,
description: description || undefined,
},
}}
/>
);
};
export default EventReservationSchema;
@@ -3,7 +3,7 @@ import { debounce, noop } from "lodash";
import { useRouter } from "next/router";
import { RefCallback, useEffect, useMemo, useState } from "react";
import { getPremiumPlanMode, getPremiumPlanPriceValue } from "@calcom/app-store/stripepayment/lib/utils";
import { getPremiumPlanPriceValue } from "@calcom/app-store/stripepayment/lib/utils";
import { fetchUsername } from "@calcom/lib/fetchUsername";
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -24,9 +24,7 @@ import {
} from "@calcom/ui";
export enum UsernameChangeStatusEnum {
NORMAL = "NORMAL",
UPGRADE = "UPGRADE",
DOWNGRADE = "DOWNGRADE",
}
interface ICustomUsernameProps {
@@ -60,20 +58,14 @@ interface ICustomUsernameProps {
const obtainNewUsernameChangeCondition = ({
userIsPremium,
isNewUsernamePremium,
stripeCustomer,
}: {
userIsPremium: boolean;
isNewUsernamePremium: boolean;
stripeCustomer: RouterOutputs["viewer"]["stripeCustomer"] | undefined;
}) => {
if (!userIsPremium && isNewUsernamePremium && !stripeCustomer?.paidForPremium) {
if (!userIsPremium && isNewUsernamePremium) {
return UsernameChangeStatusEnum.UPGRADE;
}
if (userIsPremium && !isNewUsernamePremium && getPremiumPlanMode() === "subscription") {
return UsernameChangeStatusEnum.DOWNGRADE;
}
return UsernameChangeStatusEnum.NORMAL;
};
const PremiumTextfield = (props: ICustomUsernameProps) => {
@@ -106,7 +98,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
setIsInputUsernamePremium(data.premium);
setUsernameIsAvailable(data.available);
}, 150),
[]
[currentUsername]
);
useEffect(() => {
@@ -137,7 +129,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
});
// when current username isn't set - Go to stripe to check what username he wanted to buy and was it a premium and was it paid for
const paymentRequired = !currentUsername && stripeCustomer?.isPremium && !stripeCustomer?.paidForPremium;
const paymentRequired = !currentUsername && stripeCustomer?.isPremium;
const usernameChangeCondition = obtainNewUsernameChangeCondition({
userIsPremium: isCurrentUsernamePremium,
@@ -194,7 +186,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
};
const saveUsername = () => {
if (usernameChangeCondition === UsernameChangeStatusEnum.NORMAL) {
if (usernameChangeCondition !== UsernameChangeStatusEnum.UPGRADE) {
updateUsername.mutate({
username: inputUsernameValue,
});
@@ -279,14 +271,6 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
{paymentMsg}
{markAsError && <p className="mt-1 text-xs text-red-500">Username is already taken</p>}
{usernameIsAvailable && (
<p className={classNames("mt-1 text-xs text-gray-900")}>
{usernameChangeCondition === UsernameChangeStatusEnum.DOWNGRADE && (
<>{t("premium_to_standard_username_description")}</>
)}
</p>
)}
<Dialog open={openDialogSaveUsername}>
<DialogContent>
<div className="flex flex-row">
@@ -295,13 +279,8 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
</div>
<div className="mb-4 w-full px-4 pt-1">
<DialogHeader title={t("confirm_username_change_dialog_title")} />
{usernameChangeCondition && usernameChangeCondition !== UsernameChangeStatusEnum.NORMAL && (
<p className="-mt-4 mb-4 text-sm text-gray-800">
{usernameChangeCondition === UsernameChangeStatusEnum.UPGRADE &&
t("change_username_standard_to_premium")}
{usernameChangeCondition === UsernameChangeStatusEnum.DOWNGRADE &&
t("change_username_premium_to_standard")}
</p>
{usernameChangeCondition && usernameChangeCondition === UsernameChangeStatusEnum.UPGRADE && (
<p className="mb-4 text-sm text-gray-800">{t("change_username_standard_to_premium")}</p>
)}
<div className="flex w-full flex-wrap rounded-sm bg-gray-100 py-3 text-sm">
@@ -323,8 +302,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
<div className="mt-4 flex flex-row-reverse gap-x-2">
{/* redirect to checkout */}
{(usernameChangeCondition === UsernameChangeStatusEnum.UPGRADE ||
usernameChangeCondition === UsernameChangeStatusEnum.DOWNGRADE) && (
{usernameChangeCondition === UsernameChangeStatusEnum.UPGRADE && (
<Button
type="button"
loading={updateUsername.isLoading}
@@ -336,7 +314,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
</Button>
)}
{/* Normal save */}
{usernameChangeCondition === UsernameChangeStatusEnum.NORMAL && (
{usernameChangeCondition !== UsernameChangeStatusEnum.UPGRADE && (
<Button
type="button"
loading={updateUsername.isLoading}
@@ -124,6 +124,7 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
<Input
ref={usernameRef}
name="username"
value={inputUsernameValue}
autoComplete="none"
autoCapitalize="none"
autoCorrect="none"
@@ -133,7 +134,6 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
? "focus:shadow-0 focus:ring-shadow-0 border-red-500 focus:border-red-500 focus:outline-none focus:ring-0"
: ""
)}
defaultValue={currentUsername}
onChange={(event) => {
event.preventDefault();
setInputUsernameValue(event.target.value);
@@ -1,6 +1,67 @@
import { useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { IS_SELF_HOSTED } from "@calcom/lib/constants";
import { User } from "@calcom/prisma/client";
import { TRPCClientErrorLike } from "@calcom/trpc/client";
import { AppRouter } from "@calcom/trpc/server/routers/_app";
import { PremiumTextfield } from "./PremiumTextfield";
import { UsernameTextfield } from "./UsernameTextfield";
export const UsernameAvailability = IS_SELF_HOSTED ? UsernameTextfield : PremiumTextfield;
interface UsernameAvailabilityFieldProps {
onSuccessMutation?: () => void;
onErrorMutation?: (error: TRPCClientErrorLike<AppRouter>) => void;
user: Pick<
User,
| "username"
| "name"
| "email"
| "bio"
| "avatar"
| "timeZone"
| "weekStart"
| "hideBranding"
| "theme"
| "plan"
| "brandColor"
| "darkBrandColor"
| "timeFormat"
| "metadata"
>;
}
export const UsernameAvailabilityField = ({
onSuccessMutation,
onErrorMutation,
user,
}: UsernameAvailabilityFieldProps) => {
const [currentUsername, setCurrentUsername] = useState(user.username ?? "");
const formMethods = useForm({
defaultValues: {
username: currentUsername,
},
});
return (
<Controller
control={formMethods.control}
name="username"
render={({ field: { ref, onChange, value } }) => {
return (
<UsernameAvailability
currentUsername={currentUsername}
setCurrentUsername={setCurrentUsername}
inputUsernameValue={value}
usernameRef={ref}
setInputUsernameValue={onChange}
onSuccessMutation={onSuccessMutation}
onErrorMutation={onErrorMutation}
user={user}
/>
);
}}
/>
);
};
+2 -4
View File
@@ -1,5 +1,3 @@
import { User } from "@prisma/client";
export function isBrandingHidden<TUser extends Pick<User, "hideBranding" | "plan">>(user: TUser) {
return user.hideBranding && user.plan !== "FREE";
export function isBrandingHidden(hideBrandingSetting: boolean, belongsToActiveTeam: boolean) {
return belongsToActiveTeam && hideBrandingSetting;
}
+23
View File
@@ -7,6 +7,29 @@ export type EmbedProps = {
export default function withEmbedSsr(getServerSideProps: GetServerSideProps) {
return async (context: GetServerSidePropsContext): Promise<GetServerSidePropsResult<EmbedProps>> => {
const ssrResponse = await getServerSideProps(context);
const embed = context.query.embed;
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.
const destinationUrlObj = new URL(ssrResponse.redirect.destination, "https://base");
// Make sure that redirect happens to /embed page and pass on embed query param as is for preserving Cal JS API namespace
const newDestinationUrl =
destinationUrlObj.pathname +
"/embed?" +
destinationUrlObj.searchParams.toString() +
"&embed=" +
embed;
return {
...ssrResponse,
redirect: {
...ssrResponse.redirect,
destination: newDestinationUrl,
},
};
}
if (!("props" in ssrResponse)) {
return ssrResponse;
}
+3 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@calcom/web",
"version": "2.3.4",
"version": "2.3.6",
"private": true,
"scripts": {
"analyze": "ANALYZE=true next build",
@@ -107,12 +107,14 @@
"react-live-chat-loader": "^2.7.3",
"react-multi-email": "^0.5.3",
"react-phone-number-input": "^3.2.7",
"react-schemaorg": "^2.0.0",
"react-select": "^5.4.0",
"react-timezone-select": "^1.3.2",
"react-use-intercom": "1.5.1",
"react-virtualized-auto-sizer": "^1.0.6",
"react-window": "^1.8.7",
"rrule": "^2.7.1",
"schema-dts": "^1.1.0",
"short-uuid": "^4.2.0",
"stripe": "^9.16.0",
"superjson": "1.9.1",
+4 -1
View File
@@ -1,9 +1,12 @@
import Head from "next/head";
import { APP_NAME, WEBSITE_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button } from "@calcom/ui";
export default function Error500() {
const { t } = useLocale();
return (
<div className="flex h-screen">
<Head>
@@ -24,7 +27,7 @@ export default function Error500() {
Something went wrong on our end. Get in touch with our support team, and we’ll get it fixed right
away for you.
</p>
<Button href={`${WEBSITE_URL}/support`}>Contact support</Button>
<Button href={`${WEBSITE_URL}/support`}>{t("contact_support")}</Button>
<Button color="secondary" href="javascript:history.back()" className="ml-2">
Go back
</Button>
+17 -2
View File
@@ -10,8 +10,9 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
import prisma from "@calcom/prisma";
import { User } from "@calcom/prisma/client";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { EventTypeMetaDataSchema, teamMetadataSchema } from "@calcom/prisma/zod-utils";
import { isBrandingHidden } from "@lib/isBrandingHidden";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import { EmbedProps } from "@lib/withEmbedSsr";
@@ -110,6 +111,11 @@ async function getUserPageProps(context: GetStaticPropsContext) {
},
],
},
teams: {
include: {
team: true,
},
},
},
});
@@ -121,7 +127,7 @@ async function getUserPageProps(context: GetStaticPropsContext) {
"strikethrough",
]);
if (!user || !user.eventTypes) return { notFound: true };
if (!user || !user.eventTypes.length) return { notFound: true };
const [eventType]: (typeof user.eventTypes[number] & {
users: Pick<User, "name" | "username" | "hideBranding" | "plan" | "timeZone">[];
@@ -150,6 +156,13 @@ async function getUserPageProps(context: GetStaticPropsContext) {
locations: privacyFilteredLocations(locations),
descriptionAsSafeHTML: eventType.description ? md.render(eventType.description) : null,
});
// Check if the user you are logging into has any active teams
const hasActiveTeam =
user.teams.filter((m) => {
const metadata = teamMetadataSchema.safeParse(m.team.metadata);
if (metadata.success && metadata.data?.subscriptionId) return false;
return true;
}).length > 0;
return {
props: {
@@ -167,6 +180,7 @@ async function getUserPageProps(context: GetStaticPropsContext) {
away: user?.away,
isDynamic: false,
trpcState: ssg.dehydrate(),
isBrandingHidden: isBrandingHidden(user.hideBranding, hasActiveTeam),
},
revalidate: 10, // seconds
};
@@ -262,6 +276,7 @@ async function getDynamicGroupPageProps(context: GetStaticPropsContext) {
isDynamic: true,
away: false,
trpcState: ssg.dehydrate(),
isBrandingHidden: false, // I think we should always show branding for dynamic groups - saves us checking every single user
},
revalidate: 10, // seconds
};
+2 -1
View File
@@ -12,7 +12,7 @@ import {
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { bookEventTypeSelect } from "@calcom/prisma";
import prisma from "@calcom/prisma";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { asStringOrNull, asStringOrThrow } from "@lib/asStringOrNull";
import getBooking, { GetBookingType } from "@lib/getBooking";
@@ -127,6 +127,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
periodStartDate: e.periodStartDate?.toString() ?? null,
periodEndDate: e.periodEndDate?.toString() ?? null,
schedulingType: null,
customInputs: customInputSchema.array().parse(e.customInputs || []),
users: users.map((u) => ({
id: u.id,
name: u.name,
+3 -4
View File
@@ -3,10 +3,9 @@ import Document, { DocumentContext, Head, Html, Main, NextScript, DocumentProps
type Props = Record<string, unknown> & DocumentProps;
function toRunBeforeReactOnClient() {
const calEmbedMode =
location.search.includes("embed=") ||
/* Iframe Name */
window.name.includes("cal-embed");
const calEmbedMode = typeof new URL(document.URL).searchParams.get("embed") === "string";
/* Iframe Name */
window.name.includes("cal-embed");
window.isEmbed = () => {
// Once an embed mode always an embed mode
+18
View File
@@ -20,6 +20,7 @@ import { defaultCookies } from "@calcom/lib/default-cookies";
import rateLimit from "@calcom/lib/rateLimit";
import { serverConfig } from "@calcom/lib/serverConfig";
import prisma from "@calcom/prisma";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
import CalComAdapter from "@lib/auth/next-auth-custom-adapter";
import { randomString } from "@lib/random";
@@ -63,6 +64,11 @@ const providers: Provider[] = [
password: true,
twoFactorEnabled: true,
twoFactorSecret: true,
teams: {
include: {
team: true,
},
},
},
});
@@ -116,6 +122,13 @@ const providers: Provider[] = [
intervalInMs: 60 * 1000, // 1 minute
});
await limiter.check(10, user.email); // 10 requests per minute
// Check if the user you are logging into has any active teams
const hasActiveTeams =
user.teams.filter((m) => {
const metadata = teamMetadataSchema.safeParse(m.team.metadata);
if (metadata.success && metadata.data?.subscriptionId) return false;
return true;
}).length > 0;
// authentication success- but does it meet the minimum password requirements?
if (user.role === "ADMIN" && !isPasswordValid(credentials.password, false, true)) {
@@ -125,6 +138,7 @@ const providers: Provider[] = [
email: user.email,
name: user.name,
role: "USER",
belongsToActiveTeam: hasActiveTeams,
};
}
@@ -134,6 +148,7 @@ const providers: Provider[] = [
email: user.email,
name: user.name,
role: user.role,
belongsToActiveTeam: hasActiveTeams,
};
},
}),
@@ -272,6 +287,7 @@ export default NextAuth({
email: user.email,
role: user.role,
impersonatedByUID: user?.impersonatedByUID,
belongsToActiveTeam: user?.belongsToActiveTeam,
};
}
@@ -307,6 +323,7 @@ export default NextAuth({
email: existingUser.email,
role: existingUser.role,
impersonatedByUID: token.impersonatedByUID as number,
belongsToActiveTeam: token?.belongsToActiveTeam as boolean,
};
}
@@ -324,6 +341,7 @@ export default NextAuth({
username: token.username as string,
role: token.role as UserPermissionRole,
impersonatedByUID: token.impersonatedByUID as number,
belongsToActiveTeam: token?.belongsToActiveTeam as boolean,
},
};
return calendsoSession;
-68
View File
@@ -1,68 +0,0 @@
import { MembershipRole } from "@prisma/client";
import type { NextApiRequest, NextApiResponse } from "next";
import { closeComUpsertTeamUser } from "@calcom/lib/sync/SyncServiceManager";
import prisma from "@calcom/prisma";
import { getSession } from "@lib/auth";
import slugify from "@lib/slugify";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const session = await getSession({ req: req });
if (!session?.user?.id) {
res.status(401).json({ message: "Not authenticated" });
return;
}
const ownerUser = await prisma.user.findFirst({
where: {
id: session.user.id,
},
select: {
id: true,
username: true,
createdDate: true,
name: true,
plan: true,
email: true,
},
});
if (req.method === "POST") {
const slug = slugify(req.body.name);
const nameCollisions = await prisma.team.count({
where: {
OR: [{ name: req.body.name }, { slug: slug }],
},
});
if (nameCollisions > 0) {
return res.status(409).json({ errorCode: "TeamNameCollision", message: "Team name already taken." });
}
const createTeam = await prisma.team.create({
data: {
name: req.body.name,
slug: slug,
},
});
await prisma.membership.create({
data: {
teamId: createTeam.id,
userId: session.user.id,
role: MembershipRole.OWNER,
accepted: true,
},
});
// Sync Services: Close.com
closeComUpsertTeamUser(createTeam, ownerUser, MembershipRole.OWNER);
return res.status(201).json({ message: "Team created" });
}
res.status(404).json({ message: "Team not found" });
}
+2 -2
View File
@@ -3,7 +3,7 @@ import { signIn } from "next-auth/react";
import { useRouter } from "next/router";
import { useEffect } from "react";
import { getPremiumPlanPrice } from "@calcom/app-store/stripepayment/lib/utils";
import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils";
import stripe from "@calcom/features/ee/payments/server/stripe";
import {
hostedCal,
@@ -161,7 +161,7 @@ const getStripePremiumUsernameUrl = async ({
customer: customer.id,
line_items: [
{
price: getPremiumPlanPrice(),
price: getPremiumMonthlyPlanPriceId(),
quantity: 1,
},
],
+6 -2
View File
@@ -29,6 +29,8 @@ import { HttpError } from "@lib/core/http/error";
import { SelectSkeletonLoader } from "@components/availability/SkeletonLoader";
import EditableHeading from "@components/ui/EditableHeading";
import { ssgInit } from "@server/lib/ssg";
const querySchema = z.object({
schedule: stringOrNumber,
});
@@ -91,7 +93,7 @@ export default function Availability({ schedule }: { schedule: number }) {
return (
<Shell
backPath="/availability"
title={data?.schedule.name && data.schedule.name + " | " + t("availability")}
title={data?.schedule.name ? data.schedule.name + " | " + t("availability") : t("availability")}
heading={
<Controller
control={form.control}
@@ -209,14 +211,16 @@ export default function Availability({ schedule }: { schedule: number }) {
);
}
export const getStaticProps: GetStaticProps = (ctx) => {
export const getStaticProps: GetStaticProps = async (ctx) => {
const params = querySchema.safeParse(ctx.params);
const ssg = await ssgInit(ctx);
if (!params.success) return { notFound: true };
return {
props: {
schedule: params.data.schedule,
trpcState: ssg.dehydrate(),
},
revalidate: 10, // seconds
};
+32
View File
@@ -1,4 +1,5 @@
import { useAutoAnimate } from "@formkit/auto-animate/react";
import { GetServerSidePropsContext } from "next";
import { NewScheduleButton, ScheduleListItem } from "@calcom/features/schedules";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -10,6 +11,8 @@ import { HttpError } from "@lib/core/http/error";
import SkeletonLoader from "@components/availability/SkeletonLoader";
import { ssrInit } from "@server/lib/ssr";
export function AvailabilityList({ schedules }: RouterOutputs["viewer"]["availability"]["list"]) {
const { t } = useLocale();
const utils = trpc.useContext();
@@ -45,6 +48,24 @@ export function AvailabilityList({ schedules }: RouterOutputs["viewer"]["availab
},
});
const updateMutation = trpc.viewer.availability.schedule.update.useMutation({
onSuccess: async ({ schedule }) => {
await utils.viewer.availability.list.invalidate();
showToast(
t("availability_updated_successfully", {
scheduleName: schedule.name,
}),
"success"
);
},
onError: (err) => {
if (err instanceof HttpError) {
const message = `${err.statusCode}: ${err.message}`;
showToast(message, "error");
}
},
});
// Adds smooth delete button - item fades and old item slides into place
const [animationParentRef] = useAutoAnimate<HTMLUListElement>();
@@ -71,6 +92,7 @@ export function AvailabilityList({ schedules }: RouterOutputs["viewer"]["availab
}}
key={schedule.id}
schedule={schedule}
updateDefault={updateMutation.mutate}
deleteFunction={deleteMutation.mutate}
/>
))}
@@ -93,3 +115,13 @@ export default function AvailabilityPage() {
</div>
);
}
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
+68 -14
View File
@@ -34,13 +34,14 @@ import { getIs24hClockFromLocalStorage, isBrowserLocale24h } from "@calcom/lib/t
import { localStorage } from "@calcom/lib/webstorage";
import prisma, { baseUserSelect } from "@calcom/prisma";
import { Prisma } from "@calcom/prisma/client";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { Button, EmailInput, Icon } from "@calcom/ui";
import { timeZone } from "@lib/clock";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import CancelBooking from "@components/booking/CancelBooking";
import EventReservationSchema from "@components/schemas/EventReservationSchema";
import { HeadSeo } from "@components/seo/head-seo";
import { ssrInit } from "@server/lib/ssr";
@@ -167,21 +168,27 @@ export default function Success(props: SuccessProps) {
if ((isCancellationMode || changes) && typeof window !== "undefined") {
window.scrollTo(0, document.body.scrollHeight);
}
const location: ReturnType<typeof getEventLocationValue> = Array.isArray(props.bookingInfo.location)
? props.bookingInfo.location[0] || ""
: props.bookingInfo.location || "";
? props.bookingInfo.location[0]
: // If there is no location set then we default to Cal Video
"integrations:daily";
if (!location) {
// Can't use logger.error because it throws error on client. stdout isn't available to it.
console.error(`No location found `);
}
const name = props.bookingInfo?.user?.name;
const email = props.bookingInfo?.user?.email;
const status = props.bookingInfo?.status;
const reschedule = props.bookingInfo.status === BookingStatus.ACCEPTED;
const cancellationReason = props.bookingInfo.cancellationReason;
const attendeeName =
typeof props?.bookingInfo?.attendees?.[0]?.name === "string"
? props?.bookingInfo?.attendees?.[0]?.name
: "Nameless";
const [is24h, setIs24h] = useState(isBrowserLocale24h());
const { data: session } = useSession();
@@ -203,8 +210,6 @@ export default function Success(props: SuccessProps) {
});
}
const attendeeName = typeof name === "string" ? name : "Nameless";
const eventNameObject = {
attendeeName,
eventType: props.eventType.title,
@@ -317,6 +322,19 @@ export default function Success(props: SuccessProps) {
return (
<div className={isEmbed ? "" : "h-screen"} data-testid="success-page">
{!isEmbed && (
<EventReservationSchema
reservationId={bookingInfo.uid}
eventName={eventName}
startTime={bookingInfo.startTime}
endTime={bookingInfo.endTime}
organizer={bookingInfo.user}
attendees={bookingInfo.attendees}
location={locationToDisplay}
description={bookingInfo.description}
status={status}
/>
)}
{userIsOwner && !isEmbed && (
<div className="mt-2 ml-4 -mb-4">
<Link href={allRemainingBookings ? "/bookings/recurring" : "/bookings/upcoming"}>
@@ -454,10 +472,37 @@ export default function Success(props: SuccessProps) {
)}
{customInputs &&
Object.keys(customInputs).map((key) => {
// This breaks if you have two label that are the same.
// TODO: Fix this in another PR
const customInput = customInputs[key as keyof typeof customInputs];
const eventTypeCustomFound = eventType.customInputs?.find((ci) => ci.label === key);
return (
<>
{customInput !== "" && (
{eventTypeCustomFound?.type === "RADIO" && (
<>
<div className="col-span-3 mt-8 border-t pt-8 pr-3 font-medium">
{eventTypeCustomFound.label}
</div>
<div className="col-span-3 mt-1 mb-2">
{eventTypeCustomFound.options &&
eventTypeCustomFound.options.map((option) => {
const selected = option.label == customInput;
return (
<div
key={option.label}
className={classNames(
"flex space-x-1",
!selected && "text-gray-500"
)}>
<p>{option.label}</p>
<span>{option.label === customInput && "✅"}</span>
</div>
);
})}
</div>
</>
)}
{eventTypeCustomFound?.type !== "RADIO" && customInput !== "" && (
<>
<div className="col-span-3 mt-8 border-t pt-8 pr-3 font-medium">{key}</div>
<div className="col-span-3 mt-2 mb-2">
@@ -785,6 +830,7 @@ const getEventTypesFromDB = async (id: number) => {
requiresConfirmation: true,
userId: true,
successRedirectUrl: true,
customInputs: true,
locations: true,
price: true,
currency: true,
@@ -851,22 +897,25 @@ const handleSeatsEventTypeOnBooking = (
seatsShowAttendees: boolean | null;
[x: string | number | symbol]: unknown;
},
booking: Partial<
bookingInfo: Partial<
Prisma.BookingGetPayload<{ include: { attendees: { select: { name: true; email: true } } } }>
>,
email: string
) => {
if (eventType?.seatsPerTimeSlot !== null) {
// @TODO: right now bookings with seats doesn't save every description that its entered by every user
delete booking.description;
delete bookingInfo.description;
} else {
return;
}
if (!eventType.seatsShowAttendees) {
const attendee = booking?.attendees?.find((a) => a.email === email);
booking["attendees"] = attendee ? [attendee] : [];
const attendee = bookingInfo?.attendees?.find((a) => {
return a.email === email;
});
bookingInfo["attendees"] = attendee ? [attendee] : [];
}
return;
return bookingInfo;
};
export async function getServerSideProps(context: GetServerSidePropsContext) {
@@ -945,7 +994,11 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
select: baseUserSelect,
});
if (user) {
eventTypeRaw.users.push(user);
eventTypeRaw.users.push({
...user,
avatar: "",
allowDynamicBooking: true,
});
}
}
@@ -961,6 +1014,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
periodEndDate: eventTypeRaw.periodEndDate?.toString() ?? null,
metadata: EventTypeMetaDataSchema.parse(eventTypeRaw.metadata),
recurringEvent: parseRecurringEvent(eventTypeRaw.recurringEvent),
customInputs: customInputSchema.array().parse(eventTypeRaw.customInputs),
};
const profile = {
@@ -972,7 +1026,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
slug: eventType.team?.slug || eventType.users[0]?.username || null,
};
if (bookingInfo !== null && email) {
if (bookingInfo !== null && email && eventType.seatsPerTimeSlot) {
handleSeatsEventTypeOnBooking(eventType, bookingInfo, email);
}
+77 -34
View File
@@ -14,9 +14,18 @@ import { useInViewObserver } from "@lib/hooks/useInViewObserver";
import BookingListItem from "@components/booking/BookingListItem";
import SkeletonLoader from "@components/booking/SkeletonLoader";
import { ssgInit } from "@server/lib/ssg";
type BookingListingStatus = RouterInputs["viewer"]["bookings"]["get"]["status"];
type BookingOutput = RouterOutputs["viewer"]["bookings"]["get"]["bookings"][0];
type RecurringInfo = {
recurringEventId: string | null;
count: number;
firstDate: Date | null;
bookings: { [key: string]: Date[] };
};
const validStatuses = ["upcoming", "recurring", "past", "cancelled", "unconfirmed"] as const;
const descriptionByStatus: Record<BookingListingStatus, string> = {
@@ -73,6 +82,18 @@ export default function Bookings() {
return true;
};
let recurringInfoToday: RecurringInfo | undefined;
const bookingsToday =
query.data?.pages.map((page) =>
page.bookings.filter((booking: BookingOutput) => {
recurringInfoToday = page.recurringInfo.find(
(info) => info.recurringEventId === booking.recurringEventId
);
return new Date(booking.startTime).toDateString() === new Date().toDateString();
})
)[0] || [];
const [animationParentRef] = useAutoAnimate<HTMLDivElement>();
return (
@@ -83,45 +104,65 @@ export default function Bookings() {
)}
{(query.status === "loading" || query.isPaused) && <SkeletonLoader />}
{query.status === "success" && !isEmpty && (
<div className="pt-2 xl:pt-0">
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
{/* TODO: add today only for the current day
<p className="pb-3 text-xs font-medium leading-4 text-gray-500 uppercase">{t("today")}</p>
*/}
<div className="overflow-hidden rounded-md border border-gray-200">
<table className="w-full max-w-full table-fixed">
<tbody className="divide-y divide-gray-200 bg-white" data-testid="bookings">
{query.data.pages.map((page, index) => (
<Fragment key={index}>
{page.bookings.filter(filterBookings).map((booking: BookingOutput) => {
const recurringInfo = page.recurringInfo.find(
(info) => info.recurringEventId === booking.recurringEventId
);
return (
<>
{!!bookingsToday.length && status === "upcoming" && (
<div className="mb-6 pt-2 xl:pt-0">
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
<p className="mb-2 text-xs font-medium uppercase leading-4 text-gray-500">{t("today")}</p>
<div className="overflow-hidden rounded-md border border-gray-200">
<table className="w-full max-w-full table-fixed">
<tbody className="divide-y divide-gray-200 bg-white">
<Fragment>
{bookingsToday.map((booking: BookingOutput) => (
<BookingListItem
key={booking.id}
listingStatus={status}
recurringInfo={recurringInfo}
recurringInfo={recurringInfoToday}
{...booking}
/>
);
})}
</Fragment>
))}
</tbody>
</table>
))}
</Fragment>
</tbody>
</table>
</div>
</div>
)}
<div className="pt-2 xl:pt-0">
<p className="mb-2 text-xs font-medium uppercase leading-4 text-gray-500">{t("all")}</p>
<div className="overflow-hidden rounded-md border border-gray-200">
<table className="w-full max-w-full table-fixed">
<tbody className="divide-y divide-gray-200 bg-white" data-testid="bookings">
{query.data.pages.map((page, index) => (
<Fragment key={index}>
{page.bookings.filter(filterBookings).map((booking: BookingOutput) => {
const recurringInfo = page.recurringInfo.find(
(info) => info.recurringEventId === booking.recurringEventId
);
return (
<BookingListItem
key={booking.id}
listingStatus={status}
recurringInfo={recurringInfo}
{...booking}
/>
);
})}
</Fragment>
))}
</tbody>
</table>
</div>
<div className="p-4 text-center" ref={buttonInView.ref}>
<Button
color="minimal"
loading={query.isFetchingNextPage}
disabled={!query.hasNextPage}
onClick={() => query.fetchNextPage()}>
{query.hasNextPage ? t("load_more_results") : t("no_more_results")}
</Button>
</div>
</div>
<div className="p-4 text-center" ref={buttonInView.ref}>
<Button
color="minimal"
loading={query.isFetchingNextPage}
disabled={!query.hasNextPage}
onClick={() => query.fetchNextPage()}>
{query.hasNextPage ? t("load_more_results") : t("no_more_results")}
</Button>
</div>
</div>
</>
)}
{query.status === "success" && isEmpty && (
<div className="flex items-center justify-center pt-2 xl:mx-6 xl:pt-0">
@@ -140,14 +181,16 @@ export default function Bookings() {
);
}
export const getStaticProps: GetStaticProps = (ctx) => {
export const getStaticProps: GetStaticProps = async (ctx) => {
const params = querySchema.safeParse(ctx.params);
const ssg = await ssgInit(ctx);
if (!params.success) return { notFound: true };
return {
props: {
status: params.data.status,
trpcState: ssg.dehydrate(),
},
};
};
+1
View File
@@ -166,6 +166,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
previousPage: context.req.headers.referer ?? null,
booking,
users: [user.username],
isBrandingHidden: user.hideBranding,
},
};
};
+2 -1
View File
@@ -4,7 +4,7 @@ import { JSONObject } from "superjson/dist/types";
import { parseRecurringEvent } from "@calcom/lib";
import prisma from "@calcom/prisma";
import { bookEventTypeSelect } from "@calcom/prisma/selects";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { asStringOrNull, asStringOrThrow } from "@lib/asStringOrNull";
import { inferSSRProps } from "@lib/types/inferSSRProps";
@@ -79,6 +79,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
...e,
periodStartDate: e.periodStartDate?.toString() ?? null,
periodEndDate: e.periodEndDate?.toString() ?? null,
customInputs: customInputSchema.array().parse(e.customInputs || []),
schedulingType: null,
users: users.map((u) => ({
id: u.id,
+14 -4
View File
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import { useAutoAnimate } from "@formkit/auto-animate/react";
import { EventTypeCustomInput, PeriodType, Prisma, SchedulingType } from "@prisma/client";
import { PeriodType, Prisma, SchedulingType } from "@prisma/client";
import { GetServerSidePropsContext } from "next";
import { useRouter } from "next/router";
import { useState } from "react";
@@ -16,15 +16,15 @@ import convertToNewDurationType from "@calcom/lib/convertToNewDurationType";
import findDurationType from "@calcom/lib/findDurationType";
import getStripeAppData from "@calcom/lib/getStripeAppData";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { HttpError } from "@calcom/lib/http-error";
import prisma from "@calcom/prisma";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { trpc } from "@calcom/trpc/react";
import type { BookingLimit, RecurringEvent } from "@calcom/types/Calendar";
import { Form, showToast } from "@calcom/ui";
import { asStringOrThrow } from "@lib/asStringOrNull";
import { getSession } from "@lib/auth";
import { HttpError } from "@lib/core/http/error";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import { AvailabilityTab } from "@components/eventtype/AvailabilityTab";
@@ -39,6 +39,7 @@ import { EventTypeSingleLayout } from "@components/eventtype/EventTypeSingleLayo
import EventWorkflowsTab from "@components/eventtype/EventWorkfowsTab";
import { getTranslation } from "@server/lib/i18n";
import { ssrInit } from "@server/lib/ssr";
export type FormValues = {
title: string;
@@ -63,7 +64,7 @@ export type FormValues = {
displayLocationPublicly?: boolean;
phone?: string;
}[];
customInputs: EventTypeCustomInput[];
customInputs: CustomInputParsed[];
users: string[];
schedule: number;
periodType: PeriodType;
@@ -87,6 +88,8 @@ export type FormValues = {
bookingLimits?: BookingLimit;
};
export type CustomInputParsed = typeof customInputSchema._output;
const querySchema = z.object({
tabName: z
.enum(["setup", "availability", "apps", "limits", "recurring", "team", "advanced", "workflows"])
@@ -261,6 +264,7 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
recurringEvent,
locations,
metadata,
customInputs,
// We don't need to send send these values to the backend
// eslint-disable-next-line @typescript-eslint/no-unused-vars
seatsPerTimeSlotEnabled,
@@ -298,6 +302,7 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
seatsPerTimeSlot,
seatsShowAttendees,
metadata,
customInputs,
});
}}>
<div ref={animationParentRef} className="space-y-6">
@@ -312,6 +317,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
const { req, query } = context;
const session = await getSession({ req });
const typeParam = parseInt(asStringOrThrow(query.type));
const ssr = await ssrInit(context);
if (Number.isNaN(typeParam)) {
return {
@@ -495,6 +501,8 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
// const parsedMetaData = _EventTypeModel.parse(newMetadata);
const parsedMetaData = newMetadata;
const parsedCustomInputs = (rawEventType.customInputs || []).map((input) => customInputSchema.parse(input));
const eventType = {
...restEventType,
schedule: rawEventType.schedule?.id || rawEventType.users[0]?.defaultScheduleId || null,
@@ -502,6 +510,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
bookingLimits: parseBookingLimit(restEventType.bookingLimits),
locations: locations as unknown as LocationObject[],
metadata: parsedMetaData,
customInputs: parsedCustomInputs,
};
// backwards compat
@@ -546,6 +555,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
team: eventTypeObject.team || null,
teamMembers,
currentUserMembership,
trpcState: ssr.dehydrate(),
},
};
};
+16 -7
View File
@@ -1,5 +1,5 @@
import { useAutoAnimate } from "@formkit/auto-animate/react";
import Head from "next/head";
import { GetServerSidePropsContext } from "next";
import Link from "next/link";
import { useRouter } from "next/router";
import React, { Fragment, useEffect, useState } from "react";
@@ -38,6 +38,8 @@ import SkeletonLoader from "@components/eventtype/SkeletonLoader";
import Avatar from "@components/ui/Avatar";
import AvatarGroup from "@components/ui/AvatarGroup";
import { ssrInit } from "@server/lib/ssr";
type EventTypeGroups = RouterOutputs["viewer"]["eventTypes"]["getByViewer"]["eventTypeGroups"];
type EventTypeGroupProfile = EventTypeGroups[number]["profile"];
@@ -531,9 +533,9 @@ const EventTypeListHeading = ({
<Link href={teamId ? `/settings/teams/${teamId}/profile` : "/settings/my-account/profile"}>
<a className="font-bold">{profile?.name || ""}</a>
</Link>
{membershipCount && (
{membershipCount && teamId && (
<span className="relative -top-px text-xs text-neutral-500 ltr:ml-2 rtl:mr-2">
<Link href="/settings/teams">
<Link href={`/settings/teams/${teamId}/members`}>
<a>
<Badge variant="gray">
<Icon.FiUsers className="mr-1 -mt-px inline h-3 w-3" />
@@ -579,12 +581,9 @@ const WithQuery = withQuery(trpc.viewer.eventTypes.getByViewer);
const EventTypesPage = () => {
const { t } = useLocale();
return (
<div>
<Head>
<title>Home | {APP_NAME}</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<Shell
heading={t("event_types_page_title") as string}
subtitle={t("event_types_page_subtitle") as string}
@@ -622,4 +621,14 @@ const EventTypesPage = () => {
);
};
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default EventTypesPage;
@@ -11,15 +11,14 @@ import { User } from "@calcom/prisma/client";
import { Button, StepCard, Steps } from "@calcom/ui";
import prisma from "@lib/prisma";
import { inferSSRProps } from "@lib/types/inferSSRProps";
import { ConnectedCalendars } from "@components/getting-started/steps-views/ConnectCalendars";
import { SetupAvailability } from "@components/getting-started/steps-views/SetupAvailability";
import UserProfile from "@components/getting-started/steps-views/UserProfile";
import { UserSettings } from "@components/getting-started/steps-views/UserSettings";
interface IOnboardingPageProps {
user: User;
}
export type IOnboardingPageProps = inferSSRProps<typeof getServerSideProps>;
const INITIAL_STEP = "user-settings";
const steps = ["user-settings", "connected-calendar", "setup-availability", "user-profile"] as const;
+4 -1
View File
@@ -42,6 +42,8 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
if (!booking) {
return {
notFound: true,
} as {
notFound: true;
};
}
@@ -49,6 +51,8 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
// TODO: Show something in UI to let user know that this booking is not rescheduleable.
return {
notFound: true,
} as {
notFound: true;
};
}
@@ -62,7 +66,6 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
: booking.user?.username || "rick") /* This shouldn't happen */ +
"/" +
eventType?.slug;
return {
redirect: {
destination: "/" + eventPage + "?rescheduleUid=" + context.query.uid,
@@ -0,0 +1,7 @@
import withEmbedSsr from "@lib/withEmbedSsr";
import { getServerSideProps as _getServerSideProps } from "../[uid]";
export { default } from "../[uid]";
export const getServerSideProps = withEmbedSsr(_getServerSideProps);
+18 -2
View File
@@ -1,14 +1,30 @@
import { GetServerSidePropsContext } from "next";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { getAdminLayout as getLayout, Meta } from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
function AdminAppsView() {
const { t } = useLocale();
return (
<>
<Meta title="Apps" description="apps_description" />
<h1>App listing</h1>
<Meta title={t("apps")} description={t("apps_description")} />
<h1>{t("apps_listing")}</h1>
</>
);
}
AdminAppsView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default AdminAppsView;
@@ -1,16 +1,19 @@
import { GetServerSidePropsContext } from "next";
import { signIn } from "next-auth/react";
import { useRef } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, getAdminLayout as getLayout, Meta, TextField } from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
function AdminView() {
const { t } = useLocale();
const usernameRef = useRef<HTMLInputElement>(null);
return (
<>
<Meta title="Admin" description="Impersonation" />
<Meta title={t("admin")} description={t("impersonation")} />
<form
className="mb-6 w-full sm:w-1/2"
onSubmit={(e) => {
@@ -21,7 +24,7 @@ function AdminView() {
<div className="flex items-center space-x-2">
<TextField
containerClassName="w-full"
name="Impersonate User"
name={t("user_impersonation_heading")}
addOnLeading={<>{process.env.NEXT_PUBLIC_WEBSITE_URL}/</>}
ref={usernameRef}
hint={t("impersonate_user_tip")}
@@ -36,4 +39,14 @@ function AdminView() {
AdminView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default AdminView;
+14
View File
@@ -1,5 +1,9 @@
import { GetServerSidePropsContext } from "next";
import { getAdminLayout as getLayout, Meta } from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
function AdminAppsView() {
return (
<>
@@ -11,4 +15,14 @@ function AdminAppsView() {
AdminAppsView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default AdminAppsView;
+18 -2
View File
@@ -1,14 +1,30 @@
import { GetServerSidePropsContext } from "next";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { getAdminLayout as getLayout, Meta } from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
function AdminUsersView() {
const { t } = useLocale();
return (
<>
<Meta title="Users" description="users_description" />
<h1>Users listing</h1>
<Meta title={t("users")} description={t("users_description")} />
<h1>{t("users_listing")}</h1>
</>
);
}
AdminUsersView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default AdminUsersView;
+14 -1
View File
@@ -1,3 +1,4 @@
import { GetServerSidePropsContext } from "next";
import { useRouter } from "next/router";
import { useState } from "react";
import { HelpScout, useChat } from "react-live-chat-loader";
@@ -8,6 +9,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { Button, getSettingsLayout as getLayout, Icon, Meta } from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
interface CtaRowProps {
title: string;
description: string;
@@ -64,7 +67,7 @@ const BillingView = () => {
<CtaRow title={t("billing_help_title")} description={t("billing_help_description")}>
<Button color="secondary" onClick={onContactSupportClick}>
{t("billing_help_cta")}
{t("contact_support")}
</Button>
</CtaRow>
{showChat && <HelpScout color="#292929" icon="message" horizontalPosition="right" zIndex="1" />}
@@ -75,4 +78,14 @@ const BillingView = () => {
BillingView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default BillingView;
@@ -1,3 +1,4 @@
import { GetServerSidePropsContext } from "next";
import { useState } from "react";
import { TApiKeys } from "@calcom/ee/api-keys/components/ApiKeyListItem";
@@ -18,6 +19,8 @@ import {
SkeletonLoader,
} from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
const ApiKeysView = () => {
const { t } = useLocale();
@@ -93,4 +96,14 @@ const ApiKeysView = () => {
ApiKeysView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default ApiKeysView;
@@ -1,3 +1,5 @@
import { GetServerSidePropsContext } from "next";
import { useSession } from "next-auth/react";
import { Controller, useForm } from "react-hook-form";
import { APP_NAME } from "@calcom/lib/constants";
@@ -17,9 +19,12 @@ import {
Switch,
} from "@calcom/ui";
const SkeletonLoader = () => {
import { ssrInit } from "@server/lib/ssr";
const SkeletonLoader = ({ title, description }: { title: string; description: string }) => {
return (
<SkeletonContainer>
<Meta title={title} description={description} />
<div className="mt-6 mb-8 space-y-6 divide-y">
<div className="flex items-center">
<SkeletonButton className="mr-6 h-32 w-48 rounded-md p-5" />
@@ -41,7 +46,7 @@ const SkeletonLoader = () => {
const AppearanceView = () => {
const { t } = useLocale();
const session = useSession();
const utils = trpc.useContext();
const { data: user, isLoading } = trpc.viewer.me.useQuery();
@@ -68,7 +73,7 @@ const AppearanceView = () => {
},
});
if (isLoading) return <SkeletonLoader />;
if (isLoading) return <SkeletonLoader title={t("appearance")} description={t("appearance_description")} />;
if (!user) return null;
@@ -85,7 +90,7 @@ const AppearanceView = () => {
theme: values.theme || null,
});
}}>
<Meta title="Appearance" description="Manage settings for your booking appearance" />
<Meta title={t("appearance")} description={t("appearance_description")} />
<div className="mb-6 flex items-center text-sm">
<div>
<p className="font-semibold">{t("theme")}</p>
@@ -180,6 +185,7 @@ const AppearanceView = () => {
<div className="flex-none">
<Switch
id="hideBranding"
disabled={!session.data?.user.belongsToActiveTeam}
onCheckedChange={(checked) =>
formMethods.setValue("hideBranding", checked, { shouldDirty: true })
}
@@ -204,6 +210,16 @@ const AppearanceView = () => {
AppearanceView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default AppearanceView;
interface ThemeLabelProps {
variant: "light" | "dark" | "system";
@@ -1,3 +1,4 @@
import { GetServerSidePropsContext } from "next";
import { Trans } from "next-i18next";
import Link from "next/link";
import { useRouter } from "next/router";
@@ -22,12 +23,15 @@ import {
SkeletonButton,
SkeletonContainer,
SkeletonText,
showToast,
} from "@calcom/ui";
import { QueryCell } from "@lib/QueryCell";
import { CalendarSwitch } from "@components/settings/CalendarSwitch";
import { ssrInit } from "@server/lib/ssr";
const SkeletonLoader = () => {
return (
<SkeletonContainer>
@@ -66,15 +70,17 @@ const CalendarsView = () => {
async onSettled() {
await utils.viewer.connectedCalendars.invalidate();
},
onSuccess: async () => {
showToast(t("calendar_updated_successfully"), "success");
},
onError: () => {
showToast(t("unexpected_error_try_again"), "error");
},
});
return (
<>
<Meta
title="Calendars"
description="Configure how your event types interact with your calendars"
CTA={<AddCalendarButton />}
/>
<Meta title={t("calendars")} description={t("calendars_description")} CTA={<AddCalendarButton />} />
<QueryCell
query={query}
customLoader={<SkeletonLoader />}
@@ -110,7 +116,7 @@ const CalendarsView = () => {
{t("check_for_conflicts")}
</h4>
<p className="pb-2 text-sm leading-5 text-gray-600">{t("select_calendars")}</p>
<List>
<List className="flex flex-col gap-6" noBorderTreatment>
{data.connectedCalendars.map((item) => (
<Fragment key={item.credentialId}>
{item.error && item.error.message && (
@@ -137,7 +143,7 @@ const CalendarsView = () => {
/>
)}
{item?.error === undefined && item.calendars && (
<ListItem className="flex-col">
<ListItem className="flex-col rounded-md">
<div className="flex w-full flex-1 items-center space-x-3 p-4 rtl:space-x-reverse">
{
// eslint-disable-next-line @next/next/no-img-element
@@ -164,7 +170,7 @@ const CalendarsView = () => {
<DisconnectIntegration
trashIcon
credentialId={item.credentialId}
buttonProps={{ size: "icon", color: "secondary" }}
buttonProps={{ className: "border border-gray-300" }}
/>
</div>
</div>
@@ -172,7 +178,7 @@ const CalendarsView = () => {
<p className="px-2 pt-4 text-sm text-neutral-500">
{t("toggle_calendars_conflict")}
</p>
<ul className="space-y-2 px-2 pt-4">
<ul className="space-y-2 p-4">
{item.calendars.map((cal) => (
<CalendarSwitch
key={cal.externalId}
@@ -224,4 +230,14 @@ const CalendarsView = () => {
CalendarsView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default CalendarsView;
@@ -1,3 +1,4 @@
import { GetServerSidePropsContext } from "next";
import { useState } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -24,9 +25,12 @@ import {
SkeletonText,
} from "@calcom/ui";
const SkeletonLoader = () => {
import { ssrInit } from "@server/lib/ssr";
const SkeletonLoader = ({ title, description }: { title: string; description: string }) => {
return (
<SkeletonContainer>
<Meta title={title} description={description} />
<div className="mt-6 mb-8 space-y-6 divide-y">
<SkeletonText className="h-8 w-full" />
<SkeletonText className="h-8 w-full" />
@@ -60,18 +64,19 @@ const ConferencingLayout = () => {
const [deleteAppModal, setDeleteAppModal] = useState(false);
const [deleteCredentialId, setDeleteCredentialId] = useState<number>(0);
if (isLoading) return <SkeletonLoader />;
if (isLoading)
return <SkeletonLoader title={t("conferencing")} description={t("conferencing_description")} />;
return (
<div className="w-full bg-white sm:mx-0 xl:mt-0">
<Meta title="Conferencing" description="Add your favourite video conferencing apps for your meetings" />
<Meta title={t("conferencing")} description={t("conferencing_description")} />
<List>
{apps?.items &&
apps.items
.map((app) => ({ ...app, title: app.title || app.name }))
.map((app) => (
<ListItem className="flex-col border-0" key={app.title}>
<div className="flex w-full flex-1 items-center space-x-3 pl-1 pt-1 rtl:space-x-reverse">
<div className="flex w-full flex-1 items-center space-x-2 p-4 rtl:space-x-reverse">
{
// eslint-disable-next-line @next/next/no-img-element
app.logo && <img className="h-10 w-10" src={app.logo} alt={app.title} />
@@ -128,4 +133,14 @@ const ConferencingLayout = () => {
ConferencingLayout.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default ConferencingLayout;
+18 -4
View File
@@ -1,3 +1,4 @@
import { GetServerSidePropsContext } from "next";
import { useRouter } from "next/router";
import { useMemo } from "react";
import { Controller, useForm } from "react-hook-form";
@@ -21,9 +22,12 @@ import {
import { withQuery } from "@lib/QueryCell";
import { nameOfDay } from "@lib/core/i18n/weekday";
const SkeletonLoader = () => {
import { ssrInit } from "@server/lib/ssr";
const SkeletonLoader = ({ title, description }: { title: string; description: string }) => {
return (
<SkeletonContainer>
<Meta title={title} description={description} />
<div className="mt-6 mb-8 space-y-6 divide-y">
<SkeletonText className="h-8 w-full" />
<SkeletonText className="h-8 w-full" />
@@ -47,14 +51,14 @@ const GeneralQueryView = () => {
const { t } = useLocale();
const { data: user, isLoading } = trpc.viewer.me.useQuery();
if (isLoading) return <SkeletonLoader />;
if (isLoading) return <SkeletonLoader title={t("general")} description={t("general_description")} />;
if (!user) {
throw new Error(t("something_went_wrong"));
}
return (
<WithQuery
success={({ data }) => <GeneralView user={user} localeProp={data.locale} />}
customLoader={<SkeletonLoader />}
customLoader={<SkeletonLoader title={t("general")} description={t("general_description")} />}
/>
);
};
@@ -127,7 +131,7 @@ const GeneralView = ({ localeProp, user }: GeneralViewProps) => {
weekStart: values.weekStart.value,
});
}}>
<Meta title="General" description="Manage settings for your language and timezone" />
<Meta title={t("general")} description={t("general_description")} />
<Controller
name="locale"
render={({ field: { value, onChange } }) => (
@@ -210,4 +214,14 @@ const GeneralView = ({ localeProp, user }: GeneralViewProps) => {
GeneralQueryView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default GeneralQueryView;
+24 -20
View File
@@ -1,5 +1,6 @@
import { IdentityProvider } from "@prisma/client";
import crypto from "crypto";
import { GetServerSidePropsContext } from "next";
import { signOut } from "next-auth/react";
import { BaseSyntheticEvent, useEffect, useRef, useState } from "react";
import { Controller, useForm } from "react-hook-form";
@@ -35,11 +36,14 @@ import {
} from "@calcom/ui";
import TwoFactor from "@components/auth/TwoFactor";
import { UsernameAvailability } from "@components/ui/UsernameAvailability";
import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability";
const SkeletonLoader = () => {
import { ssrInit } from "@server/lib/ssr";
const SkeletonLoader = ({ title, description }: { title: string; description: string }) => {
return (
<SkeletonContainer>
<Meta title={title} description={description} />
<div className="mt-6 mb-8 space-y-6 divide-y">
<div className="flex items-center">
<SkeletonAvatar className=" h-12 w-12 px-4" />
@@ -208,11 +212,14 @@ const ProfileView = () => {
showToast(t("error_updating_settings"), "error");
};
if (isLoading || !user) return <SkeletonLoader />;
if (isLoading || !user)
return <SkeletonLoader title={t("profile")} description={t("profile_description")} />;
const isDisabled = isSubmitting || !isDirty;
return (
<>
<Meta title={t("profile")} description={t("profile_description", { appName: APP_NAME })} />
<Form
form={formMethods}
handleSubmit={(values) => {
@@ -222,7 +229,6 @@ const ProfileView = () => {
mutation.mutate(values);
}
}}>
<Meta title="Profile" description={t("profile_description", { appName: APP_NAME })} />
<div className="flex items-center">
<Controller
control={formMethods.control}
@@ -246,22 +252,10 @@ const ProfileView = () => {
/>
</div>
<div className="mt-8">
<Controller
control={formMethods.control}
name="username"
render={({ field: { ref, onChange, value } }) => {
return (
<UsernameAvailability
currentUsername={user?.username || ""}
inputUsernameValue={value}
usernameRef={ref}
setInputUsernameValue={onChange}
onSuccessMutation={onSuccessfulUsernameUpdate}
onErrorMutation={onErrorInUsernameUpdate}
user={user}
/>
);
}}
<UsernameAvailabilityField
user={user}
onSuccessMutation={onSuccessfulUsernameUpdate}
onErrorMutation={onErrorInUsernameUpdate}
/>
</div>
<div className="mt-8">
@@ -371,4 +365,14 @@ const ProfileView = () => {
ProfileView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default ProfileView;
@@ -1,3 +1,4 @@
import { GetServerSidePropsContext } from "next";
import { useForm } from "react-hook-form";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -13,6 +14,8 @@ import {
Switch,
} from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
const ProfileImpersonationView = () => {
const { t } = useLocale();
const utils = trpc.useContext();
@@ -39,7 +42,7 @@ const ProfileImpersonationView = () => {
return (
<>
<Meta title="Impersonation Settings" description="" />
<Meta title={t("impersonation")} description={t("impersonation_description")} />
<Form
form={formMethods}
handleSubmit={({ disableImpersonation }) => {
@@ -74,4 +77,14 @@ const ProfileImpersonationView = () => {
ProfileImpersonationView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default ProfileImpersonationView;
@@ -1,4 +1,5 @@
import { IdentityProvider } from "@prisma/client";
import { GetServerSidePropsContext } from "next";
import { Trans } from "next-i18next";
import { useForm } from "react-hook-form";
@@ -7,6 +8,8 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { Button, Form, getSettingsLayout as getLayout, Meta, PasswordField, showToast } from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
type ChangePasswordFormValues = {
oldPassword: string;
newPassword: string;
@@ -92,4 +95,14 @@ const PasswordView = () => {
PasswordView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default PasswordView;
+14
View File
@@ -1 +1,15 @@
import { GetServerSidePropsContext } from "next";
import { ssrInit } from "@server/lib/ssr";
export { default } from "@calcom/features/ee/sso/page/user-sso-view";
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
@@ -1,12 +1,37 @@
import { GetServerSidePropsContext } from "next";
import { useState } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { Badge, getSettingsLayout as getLayout, Loader, Meta, Switch } from "@calcom/ui";
import {
Badge,
getSettingsLayout as getLayout,
Meta,
Switch,
SkeletonButton,
SkeletonContainer,
SkeletonText,
} from "@calcom/ui";
import DisableTwoFactorModal from "@components/settings/DisableTwoFactorModal";
import EnableTwoFactorModal from "@components/settings/EnableTwoFactorModal";
import { ssrInit } from "@server/lib/ssr";
const SkeletonLoader = ({ title, description }: { title: string; description: string }) => {
return (
<SkeletonContainer>
<Meta title={title} description={description} />
<div className="mt-6 mb-8 space-y-6 divide-y">
<div className="flex items-center">
<SkeletonButton className="mr-6 h-8 w-20 rounded-md p-5" />
<SkeletonText className="h-8 w-full" />
</div>
</div>
</SkeletonContainer>
);
};
const TwoFactorAuthView = () => {
const utils = trpc.useContext();
@@ -16,11 +41,11 @@ const TwoFactorAuthView = () => {
const [enableModalOpen, setEnableModalOpen] = useState(false);
const [disableModalOpen, setDisableModalOpen] = useState(false);
if (isLoading) return <Loader />;
if (isLoading) return <SkeletonLoader title={t("2fa")} description={t("2fa_description")} />;
return (
<>
<Meta title="Two-Factor Authentication" description="Manage settings for your account passwords" />
<Meta title={t("2fa")} description={t("2fa_description")} />
<div className="mt-6 flex items-start space-x-4">
<Switch
checked={user?.twoFactorEnabled}
@@ -35,7 +60,7 @@ const TwoFactorAuthView = () => {
{user?.twoFactorEnabled ? t("enabled") : t("disabled")}
</Badge>
</div>
<p className="text-sm text-gray-600">Add an extra layer of security to your account.</p>
<p className="text-sm text-gray-600">{t("add_an_extra_layer_of_security")}</p>
</div>
</div>
@@ -68,4 +93,14 @@ const TwoFactorAuthView = () => {
TwoFactorAuthView.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default TwoFactorAuthView;
@@ -1 +1,15 @@
import { GetServerSidePropsContext } from "next";
import { ssrInit } from "@server/lib/ssr";
export { default } from "@calcom/features/ee/teams/pages/team-appearance-view";
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
@@ -1 +1,15 @@
import { GetServerSidePropsContext } from "next";
import { ssrInit } from "@server/lib/ssr";
export { default } from "@calcom/features/ee/teams/pages/team-billing-view";
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
@@ -1 +1,15 @@
import { GetServerSidePropsContext } from "next";
import { ssrInit } from "@server/lib/ssr";
export { default } from "@calcom/features/ee/teams/pages/team-members-view";
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
@@ -1 +1,15 @@
import { GetServerSidePropsContext } from "next";
import { ssrInit } from "@server/lib/ssr";
export { default } from "@calcom/features/ee/teams/pages/team-profile-view";
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
@@ -1 +1,15 @@
import { GetServerSidePropsContext } from "next";
import { ssrInit } from "@server/lib/ssr";
export { default } from "@calcom/features/ee/sso/page/teams-sso-view";
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
+17 -2
View File
@@ -1,14 +1,19 @@
import { GetServerSidePropsContext } from "next";
import Head from "next/head";
import { CreateANewTeamForm } from "@calcom/features/ee/teams/components";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { getWizardLayout as getLayout } from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
const CreateNewTeamPage = () => {
const { t } = useLocale();
return (
<>
<Head>
<title>Create a new Team</title>
<meta name="description" content="Create a new team to ease your organisational booking" />
<title>{t("create_new_team")}</title>
<meta name="description" content={t("create_new_team_description")} />
</Head>
<CreateANewTeamForm />
</>
@@ -17,4 +22,14 @@ const CreateNewTeamPage = () => {
CreateNewTeamPage.getLayout = getLayout;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default CreateNewTeamPage;
+2
View File
@@ -43,6 +43,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
name: true,
slug: true,
logo: true,
hideBranding: true,
eventTypes: {
where: {
slug: typeParam,
@@ -160,6 +161,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
previousPage: context.req.headers.referer ?? null,
booking,
trpcState: ssg.dehydrate(),
isBrandingHidden: team.hideBranding,
},
};
};
+2 -1
View File
@@ -4,7 +4,7 @@ import { JSONObject } from "superjson/dist/types";
import { LocationObject, privacyFilteredLocations } from "@calcom/app-store/locations";
import { parseRecurringEvent } from "@calcom/lib";
import prisma from "@calcom/prisma";
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { customInputSchema, EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
import { asStringOrNull, asStringOrThrow } from "@lib/asStringOrNull";
import getBooking, { GetBookingType } from "@lib/getBooking";
@@ -96,6 +96,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
metadata: EventTypeMetaDataSchema.parse(eventType.metadata || {}),
periodStartDate: e.periodStartDate?.toString() ?? null,
periodEndDate: e.periodEndDate?.toString() ?? null,
customInputs: customInputSchema.array().parse(e.customInputs || []),
users: eventType.users.map((u) => ({
id: u.id,
name: u.name,
+14
View File
@@ -1,8 +1,12 @@
import { GetServerSidePropsContext } from "next";
import { TeamsListing } from "@calcom/features/ee/teams/components";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button, Icon, Shell } from "@calcom/ui";
import { ssrInit } from "@server/lib/ssr";
function Teams() {
const { t } = useLocale();
return (
@@ -22,4 +26,14 @@ function Teams() {
Teams.requiresLicense = false;
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
export default Teams;
+14
View File
@@ -1 +1,15 @@
import { GetServerSidePropsContext } from "next";
import { ssrInit } from "@server/lib/ssr";
export { default } from "@calcom/features/ee/workflows/pages/index";
export const getServerSideProps = async (context: GetServerSidePropsContext) => {
const ssr = await ssrInit(context);
return {
props: {
trpcState: ssr.dehydrate(),
},
};
};
+5 -67
View File
@@ -1,8 +1,7 @@
import { expect } from "@playwright/test";
import { UserPlan } from "@prisma/client";
import { getFreePlanPrice, getProPlanPrice } from "@calcom/app-store/stripepayment/lib/utils";
import dayjs from "@calcom/dayjs";
import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils";
import stripe from "@calcom/features/ee/payments/server/stripe";
import { WEBAPP_URL } from "@calcom/lib/constants";
@@ -27,7 +26,7 @@ test.describe("Change username on settings", () => {
/** TODO: Find out why it's timing out */
test.fixme("User can change username", async ({ page, users, prisma }) => {
const user = await users.create({ plan: UserPlan.TRIAL });
const user = await users.create();
await user.login();
// Try to go homepage
@@ -50,28 +49,13 @@ test.describe("Change username on settings", () => {
expect(newUpdatedUser.username).toBe("demousernamex");
});
test("User trial can update to PREMIUM username", async ({ page, users }, testInfo) => {
test("User can update to PREMIUM username", async ({ page, users }, testInfo) => {
// eslint-disable-next-line playwright/no-skipped-test
test.skip(!IS_STRIPE_ENABLED, "It should only run if Stripe is installed");
test.skip(IS_SELF_HOSTED, "It shouldn't run on self hosted");
const user = await users.create({ plan: UserPlan.TRIAL });
const customer = await stripe.customers.create({ email: `${user?.username}@example.com` });
await stripe.subscriptionSchedules.create({
customer: customer.id,
start_date: "now",
end_behavior: "release",
phases: [
{
items: [{ price: getProPlanPrice() }],
trial_end: dayjs().add(14, "day").unix(),
end_date: dayjs().add(14, "day").unix(),
},
{
items: [{ price: getFreePlanPrice() }],
},
],
});
const user = await users.create();
await stripe.customers.create({ email: `${user?.username}@example.com` });
await user.login();
await page.goto("/settings/my-account/profile");
@@ -97,50 +81,4 @@ test.describe("Change username on settings", () => {
await expect(page).toHaveURL(/.*checkout.stripe.com/);
});
test("User PRO can update to PREMIUM username", async ({ page, users }, testInfo) => {
// eslint-disable-next-line playwright/no-skipped-test
test.skip(!IS_STRIPE_ENABLED, "It should only run if Stripe is installed");
test.skip(IS_SELF_HOSTED, "It shouldn't run on self hosted");
const user = await users.create({ plan: UserPlan.PRO });
const customer = await stripe.customers.create({ email: `${user?.username}@example.com` });
const paymentMethod = await stripe.paymentMethods.create({
type: "card",
card: {
number: "4242424242424242",
cvc: "123",
exp_month: 12,
exp_year: 2040,
},
});
await stripe.paymentMethods.attach(paymentMethod.id, { customer: customer.id });
await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: getProPlanPrice() }],
});
await user.login();
await page.goto("/settings/profile");
// Change username from normal to premium
const usernameInput = page.locator("[data-testid=username-input]");
await usernameInput.fill(`xx${testInfo.workerIndex}`);
// Click on save button
await page.click('button[type="submit"]');
// Validate modal text fields
const currentUsernameText = page.locator("[data-testid=current-username]").innerText();
const newUsernameText = page.locator("[data-testid=new-username]").innerText();
expect(currentUsernameText).not.toBe(newUsernameText);
// Click on Go to billing
await page.click("[data-testid=go-to-billing]", { timeout: 300 });
await page.waitForLoadState();
await expect(page).toHaveURL(/.*billing.stripe.com/);
});
});
+2
View File
@@ -65,6 +65,8 @@ test("add webhook & test that creating an event triggers a webhook call", async
body.payload.additionalInformation = dynamic;
body.payload.requiresConfirmation = dynamic;
body.payload.eventTypeId = dynamic;
body.payload.videoCallData = dynamic;
body.payload.appsStatus = dynamic;
// if we change the shape of our webhooks, we can simply update this by clicking `u`
// console.log("BODY", body);
@@ -1 +1 @@
{"triggerEvent":"BOOKING_CREATED","createdAt":"[redacted/dynamic]","payload":{"type":"30 min","title":"30 min between PRO and Test Testson","description":"","additionalNotes":"","customInputs":{},"startTime":"[redacted/dynamic]","endTime":"[redacted/dynamic]","organizer":{"name":"PRO","email":"[redacted/dynamic]","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"},"attendees":[{"email":"test@example.com","name":"Test Testson","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"}],"location":"[redacted/dynamic]","destinationCalendar":null,"hideCalendarNotes":false,"requiresConfirmation":"[redacted/dynamic]","eventTypeId":"[redacted/dynamic]","seatsShowAttendees":false,"uid":"[redacted/dynamic]","eventTitle":"30 min","eventDescription":null,"price":0,"currency":"usd","length":30,"bookingId":"[redacted/dynamic]","metadata":{},"status":"ACCEPTED","additionalInformation":"[redacted/dynamic]"}}
{"triggerEvent":"BOOKING_CREATED","createdAt":"[redacted/dynamic]","payload":{"type":"30 min","title":"30 min between PRO and Test Testson","description":"","additionalNotes":"","customInputs":{},"startTime":"[redacted/dynamic]","endTime":"[redacted/dynamic]","organizer":{"name":"PRO","email":"[redacted/dynamic]","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"},"attendees":[{"email":"test@example.com","name":"Test Testson","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"}],"location":"[redacted/dynamic]","destinationCalendar":null,"hideCalendarNotes":false,"requiresConfirmation":"[redacted/dynamic]","eventTypeId":"[redacted/dynamic]","seatsShowAttendees":false,"uid":"[redacted/dynamic]","videoCallData":"[redacted/dynamic]","appsStatus":"[redacted/dynamic]","eventTitle":"30 min","eventDescription":null,"price":0,"currency":"usd","length":30,"bookingId":"[redacted/dynamic]","metadata":{},"status":"ACCEPTED","additionalInformation":"[redacted/dynamic]"}}
+19 -19
View File
@@ -16,8 +16,8 @@
"event_request_cancelled": "تم إلغاء حدثك المُجَدْوَل",
"organizer": "المنظِّم",
"need_to_reschedule_or_cancel": "هل تحتاج إلى إعادة جدولة أو إلغاء؟",
"cancellation_reason": "سبب الإلغاء",
"cancellation_reason_placeholder": "ما سبب الإلغاء؟ (اختياري)",
"cancellation_reason": "سبب الإلغاء (اختياري)",
"cancellation_reason_placeholder": "لماذا تلغي؟",
"rejection_reason": "سبب الرفض",
"rejection_reason_title": "رفض طلب الحجز؟",
"rejection_reason_description": "هل أنت متأكد من رغبتك في رفض الحجز؟ سنقوم بإبلاغ الشخص الذي حاول الحجز. يمكنك تقديم سبب أدناه.",
@@ -109,7 +109,7 @@
"upgrade_to_per_seat": "الترقية إلى \"كل مقعد بشكل منفرد\"",
"team_upgrade_seats_details": "من بين {{memberCount}} من الأعضاء في فريقك، لم يتم الدفع مقابل {{unpaidCount}} من المقاعد. بما أن سعر المقعد ${{seatPrice}} شهريًا، تبلغ التكلفة الإجمالية المقدرة لعضويتك ${{totalCost}} شهريًا.",
"team_upgrade_banner_description": "شكراً لك على تجربة خطة الفريق الجديدة التي نقدمها. لقد لاحظنا أن فريقك \"{{teamName}}\" بحاجة إلى الترقية.",
"team_upgrade_banner_action": "الترقية هنا",
"team_upgrade_banner_action": "قم بالترقية هنا",
"team_upgraded_successfully": "تمت ترقية فريقك بنجاح!",
"use_link_to_reset_password": "استخدم الرابط أدناه لإعادة تعيين كلمة المرور",
"hey_there": "مرحبًا،",
@@ -419,7 +419,7 @@
"forgotten_secret_description": "إذا فقدت هذا السر أو نسيته، يمكنك تغييره، ولكن ضع في اعتبارك أن جميع التكاملات التي تستخدم هذا السر ستحتاج إلى تحديث",
"current_incorrect_password": "كلمة المرور الحالية غير صحيحة",
"password_hint_caplow": "مزيج من الحروف الكبيرة والحروف الصغيرة",
"password_hint_min": "7 أحرف كحد أدنى",
"password_hint_min": "8 أحرف كحد أدنى",
"password_hint_num": "يحتوي على رقم واحد على الأقل",
"invalid_password_hint": "يجب أن تتألف كلمة المرور على الأقل من 7 أحرف، ورقم واحد على الأقل، ومزيج من الحروف الكبيرة والصغيرة",
"incorrect_password": "كلمة المرور غير صحيحة.",
@@ -653,7 +653,7 @@
"show_advanced_settings": "عرض الإعدادات المتقدمة",
"event_name": "اسم الحدث",
"event_name_tooltip": "الاسم الذي سيظهر في التقاويم",
"meeting_with_user": "الاجتماع مع {ATTENDEE}",
"meeting_with_user": "الاجتماع مع {{attendeeName}}",
"additional_inputs": "مدخلات إضافية",
"additional_input_description": "يتطلب من المجدول إدخال مدخلات إضافية قبل تأكيد الحجز",
"label": "العلامة",
@@ -784,7 +784,7 @@
"analytics": "التحليلات",
"empty_installed_apps_headline": "لم يتم تثبيت أي تطبيق",
"empty_installed_apps_description": "تعطيك التطبيقات القدرة على تعزيز سير عملك وتحسين الجدولة في حياتك بشدة.",
"empty_installed_apps_button": "استكشف App Store أو قم بالتثبيت من التطبيقات أدناه",
"empty_installed_apps_button": "تصفح متجر التطبيقات",
"manage_your_connected_apps": "إدارة تطبيقاتك المثبتة أو تغيير الإعدادات",
"browse_apps": "استعراض التطبيقات",
"features": "الميزات",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "رمز المصادقة الثنائية غير صحيح",
"which_event_type_apply": "ما نوع الحدث الذي سينطبق عليه هذا؟",
"no_workflows_description": "تعمل سير العمل على تمكين أتمتة إرسال الإشعارات والتذكيرات التي تمكنك من بناء عمليات حول الأحداث الخاصة بك.",
"timeformat_profile_hint": "هذا إعداد داخلي، ولن يؤثر على كيفية عرض الأوقات على صفحات الحجز العامة لديك أو لدى أي شخص يقوم بحجزك.",
"create_workflow": "إنشاء سير عمل",
"do_this": "افعل هذا",
"turn_off": "إيقاف التشغيل",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "خطأ في تحديث الإعدادات",
"personal_cal_url": "عنوان {{appName}} URL الخاص بي",
"bio_hint": "اكتب بضع جمل عن نفسك، والتي ستظهر على صفحة عنوان Url الشخصية لديك.",
"timeformat_profile_hint": "هذا إعداد داخلي، ولن يؤثر على كيفية عرض الأوقات على صفحات الحجز العامة لديك أو لدى أي شخص يقوم بحجزك.",
"delete_account_modal_title": "حذف الحساب",
"confirm_delete_account_modal": "هل أنت متأكد من أنك تريد حذف حساب {{appName}} الخاص بك؟",
"delete_my_account": "حذف حسابي",
@@ -1130,7 +1130,7 @@
"removes_cal_branding": "إزالة أي علامات تجارية ذات صلة بـ{{appName}} ، أي 'تم تشغيلها من قبل {{appName}}.'",
"profile_picture": "صورة الملف الشخصي",
"upload": "تحميل",
"add_profile_photo": "إضافة صورة ملف تعريفي",
"add_profile_photo": "إضافة صورة الملف الشخصي",
"web3": "Web3",
"rainbow_token_gated": "يتم فتح هذا النوع من الأحداث برمز مميز.",
"rainbow_connect_wallet_gate": "قم بربط محفظتك إذا كنت تملك <1>{{name}}</1> (<3>{{symbol}}</3>).",
@@ -1229,7 +1229,7 @@
"exchange_compression": "ضغط Gzip",
"routing_forms_description": "يمكنك رؤية جميع النماذج والتوجيهات التي أنشأتها هنا.",
"routing_forms_send_email_owner": "إرسال رسالة إلكترونية إلى المالك",
"routing_forms_send_email_owner_description": "يرسل رسالة إلكترونية إلى المالك عند يتم تقديم الاستمارة",
"routing_forms_send_email_owner_description": "يرسل رسالة بريد إلكتروني إلى المالك عند إرسال النموذج",
"add_new_form": "إضافة استمارة جديدة",
"form_description": "قم بإنشاء النموذج الخاص بك لتوجيه صاحب حجز",
"copy_link_to_form": "نسخ الرابط إلى النموذج",
@@ -1324,7 +1324,7 @@
"saml_config_updated_successfully": "تم تحديث تهيئة SAML بنجاح",
"saml_configuration": "تكوين SAML",
"delete_saml_configuration": "حذف تكوين SAML",
"delete_saml_configuration_confirmation_message": "هل تريد بالتأكيد حذف تكوين SAML؟ لن يتمكن بعد الآن أعضاء فريقك الذين يستخدمون تسجيل الدخول عبر SAML من الوصول إلى {{appName}}.",
"delete_saml_configuration_confirmation_message": "هل تريد بالتأكيد حذف تكوين SAML؟ لن يتمكن بعد الآن أعضاء فريقك الذين يستخدمون تسجيل الدخول عبر SAML من الوصول إلى Cal.com.",
"confirm_delete_saml_configuration": "نعم، احذف تكوين SAML",
"saml_not_configured_yet": "لم يتم تكوين SAML حتى الآن",
"saml_configuration_description": "يُرجى لصق بيانات تعريف SAML المقدمة من مزود الهوية في مربع النص أدناه لتحديث تكوين SAML.",
@@ -1342,15 +1342,15 @@
"limit_future_bookings_description": "الحد من عدد مرات حجز هذا الحدث في المستقبل",
"no_event_types": "لا يوجد إعداد لأنواع الأحداث",
"no_event_types_description": "لم يتم إعداد أي نوع من الأحداث لك من قِبل {{name}}.",
"billing_frequency": "تواتر الفواتير",
"monthly": "شهرياً",
"yearly": "سنوياً",
"billing_frequency": "تواتر إصدار الفواتير",
"monthly": "شهريًا",
"yearly": "سنويًا",
"checkout": "الدفع",
"your_team_disbanded_successfully": "تم حل فريقك بنجاح",
"error_creating_team": "خطأ في إنشاء فريق",
"you": "أنت",
"send_email": "إرسال رسالة إلكترونية",
"member_already_invited": "تم بالفعل دعوة العضو",
"send_email": "إرسال بريد إلكتروني",
"member_already_invited": "تمت دعوة العضو بالفعل",
"enter_email_or_username": "أدخل بريد إلكتروني أو اسم مستخدم",
"team_name_taken": "هذا الاسم مأخوذ بالفعل",
"must_enter_team_name": "يجب إدخال اسم فريق",
@@ -1360,15 +1360,15 @@
"number_sms_notifications": "رقم الهاتف (إشعارات الرسائل النصية)",
"attendee_email_workflow": "اسم الحاضر",
"attendee_email_info": "البريد الإلكتروني للشخص الحجز",
"invalid_credential": "أوه لا! يبدو أن الصلاحية انتهت أو تم إلغاؤها. الرجاء إعادة التثبيت مرة أخرى.",
"invalid_credential": "لا! يبدو أن الصلاحية انتهت أو تم إلغاؤها. يرجى إعادة التثبيت مرة أخرى.",
"choose_common_schedule_team_event": "اختر جدولاً زمنياً مشتركاً",
"choose_common_schedule_team_event_description": "قم بتمكين هذا إذا كنت ترغب في استخدام جدول زمني مشترك بين المضيفين. عند تعطيل هذا الخيار، سيتم حجز كل مضيف على أساس جدوله الافتراضي.",
"choose_common_schedule_team_event_description": "قم بتمكين هذا الخيار إذا كنت ترغب في استخدام جدول زمني مشترك بين المضيفين. عند تعطيل هذا الخيار، سيتم حجز كل مضيف على أساس جدوله الافتراضي.",
"reason": "السبب",
"sender_id": "معرّف المرسل",
"sender_id_error_message": "فقط الحروف والأرقام والمسافات مسموح بها (بحد أقصى 11 مِحرَفاً)",
"sender_id_error_message": "يسمح بالحروف والأرقام والمسافات فقط (بحد أقصى 11 حرفًا)",
"test_routing_form": "اختبار استمارة إعادة التوجيه",
"test_preview": "اختبار المعاينة",
"route_to": "التوجيه إلى",
"test_preview_description": "اختبار نموذج التوجيه الخاص بك من دون تقديم أي بيانات",
"test_preview_description": "اختبار نموذج التوجيه الخاص بك دون تقديم أي بيانات",
"test_routing": "اختبار التوجيه"
}
@@ -17,7 +17,7 @@
"organizer": "Organizátor",
"need_to_reschedule_or_cancel": "Přeplánovat nebo zrušit?",
"cancellation_reason": "Důvod zrušení",
"cancellation_reason_placeholder": "Proč rušíte? (nepovinné)",
"cancellation_reason_placeholder": "Proč rušíte?\n",
"rejection_reason": "Důvod odmítnutí",
"rejection_reason_title": "Odmítnout žádost o rezervaci?",
"rejection_reason_description": "Opravdu chcete rezervaci odmítnout? Osobě, která se váš čas pokusila rezervovat, dáme vědět. Níž můžete uvést důvod.",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Zobrazit pokročilá nastavení",
"event_name": "Název události",
"event_name_tooltip": "Název, který se zobrazí v kalendářích",
"meeting_with_user": "Schůzka s {ATTENDEE}",
"meeting_with_user": "Schůzka s {{attendeeName}}",
"additional_inputs": "Další pole",
"additional_input_description": "Před potvrzením rezervace vyžadovat od plánující osoby zadání dalších vstupů",
"label": "Popisek",
@@ -736,6 +736,7 @@
"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",
"calendar": "Kalendář",
"payments": "Platby",
@@ -1108,6 +1109,7 @@
"incorrect_2fa": "Nesprávný kód dvoufázového ověření",
"which_event_type_apply": "Na jaký typ události se to bude vztahovat?",
"no_workflows_description": "Pracovní postupy umožňují jednoduchou automatizaci zasílání oznámení a připomínek, což vám umožní vytvářet procesy v souvislosti s vašimi událostmi.",
"timeformat_profile_hint": "Jedná se o interní nastavení, které nemá vliv na to, jak se vám nebo komukoli, kdo vás rezervuje, na veřejných rezervačních stránkách zobrazují časy.",
"create_workflow": "Vytvoření pracovního postupu",
"do_this": "Provést",
"turn_off": "Vypnout",
@@ -1115,7 +1117,6 @@
"error_updating_settings": "Chyba při aktualizaci nastavení",
"personal_cal_url": "Moje osobní adresa URL {{appName}}",
"bio_hint": "Několik vět o vás. Obsah se zobrazí se na vaší osobní stránce URL.",
"timeformat_profile_hint": "Jedná se o interní nastavení, které nemá vliv na to, jak se vám nebo komukoli, kdo vás rezervuje, na veřejných rezervačních stránkách zobrazují časy.",
"delete_account_modal_title": "Odstranit účet",
"confirm_delete_account_modal": "Opravdu chcete odstranit svůj účet {{appName}}?",
"delete_my_account": "Odstranit můj účet",
@@ -1350,17 +1351,17 @@
"error_creating_team": "Chyba při vytváření týmu",
"you": "Vy",
"send_email": "Odeslat e-mail",
"member_already_invited": "Člen byl již pozván",
"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 již obsazeno",
"team_name_taken": "Toto jméno je už obsazeno",
"must_enter_team_name": "Musíte zadat název týmu",
"team_url_required": "Musíte zadat adresu URL týmu",
"team_url_taken": "Tato adresa URL je již obsazená",
"team_url_taken": "Tato adresa URL je už obsazená",
"team_publish": "Zveřejnit tým",
"number_sms_notifications": "Číslo telefonu (SMS oznámení)",
"attendee_email_workflow": "E-mail účastníka",
"attendee_email_info": "E-mail osoby provádějící rezervaci",
"invalid_credential": "Ale ne! Zdá se, že platnost oprávnění vypršela nebo byla zrušena. Proveďte prosím novou instalaci.",
"invalid_credential": "Ale ne! Zdá se, že platnost oprávnění vypršela nebo byla zrušena. Proveďte novou instalaci.",
"choose_common_schedule_team_event": "Vyberte společný plán",
"choose_common_schedule_team_event_description": "Tuto možnost povolte, pokud chcete používat společný plán mezi hostiteli. Při zakázání této možnosti bude každý hostitel rezervován na základě svého výchozího plánu.",
"reason": "Důvod",
@@ -1368,7 +1369,7 @@
"sender_id_error_message": "Povolena jsou pouze písmena, číslice a mezery (max. 11 znaků)",
"test_routing_form": "Test směrovacího formuláře",
"test_preview": "Testovací náhled",
"route_to": "Směrovat kam:",
"route_to": "Směrovat na",
"test_preview_description": "Otestujte svůj směrovací formulář bez odeslání jakýchkoli dat",
"test_routing": "Test směrování"
}
+77 -111
View File
@@ -6,9 +6,7 @@
"second_other": "{{count}} Sekunden",
"upgrade_now": "Jetzt upgraden",
"accept_invitation": "Einladung annehmen",
"calcom_explained": "{{appName}} ist die Open Source Calendly Alternative, die Ihnen die Kontrolle über Ihre eigenen Daten, Workflow und Erscheinungsbild gibt.",
"have_any_questions": "Haben Sie Fragen? Wir sind hier um Ihnen zu helfen.",
"reset_password_subject": "{{appName}}: Anleitung zum Zurücksetzen des Passworts",
"event_declined_subject": "Abgelehnt: {{eventType}} mit {{name}} am {{date}}",
"event_cancelled_subject": "Abgesagt: {{eventType}} mit {{name}} am {{date}}",
"event_request_declined": "Ihre Event-Anfrage wurde abgelehnt",
@@ -55,20 +53,20 @@
"load_more_results": "Weitere Ergebnisse laden",
"integration_meeting_id": "{{integrationName}} Termin-ID: {{meetingId}}",
"confirmed_event_type_subject": "Bestätigt: {{eventType}} mit {{name}} am {{date}}",
"new_event_request": "Neue Event-Anfrage: {{attendeeName}} - {{date}} - {{eventType}}",
"new_event_request": "Neue Termin-Anfrage: {{attendeeName}} - {{date}} - {{eventType}}",
"confirm_or_reject_request": "Anfrage bestätigen oder ablehnen",
"check_bookings_page_to_confirm_or_reject": "Überprüfen Sie Ihre Buchungsseite, um die Buchung zu bestätigen oder abzulehnen.",
"event_awaiting_approval": "Ein neues Event wartet auf Ihre Bestätigung",
"event_awaiting_approval_recurring": "Ein wiederkehrender Termin wartet auf Ihre Genehmigung",
"event_awaiting_approval": "Ein neuer Termin wartet auf Ihre Bestätigung",
"event_awaiting_approval_recurring": "Ein wiederkehrender Termin wartet auf Ihre Bestätigung",
"someone_requested_an_event": "Jemand hat eine Buchungsanfrage gestellt.",
"someone_requested_password_reset": "Jemand hat einen Link angefordert, um Ihr Passwort zu ändern.",
"password_reset_instructions": "Wenn Sie dies nicht angefordert haben, können Sie diese E-Mail sicher ignorieren und Ihr Passwort wird nicht geändert.",
"event_awaiting_approval_subject": "Warte auf Bestätigung: {{eventType}} mit {{name}} um {{date}}",
"event_still_awaiting_approval": "Ein Event wartet noch auf Ihre Bestätigung",
"event_still_awaiting_approval": "Ein Termin wartet noch auf Ihre Bestätigung",
"booking_submitted_subject": "Buchung eingereicht: {{eventType}} mit {{name}} am {{date}}",
"your_meeting_has_been_booked": "Dein Termin wurde gebucht",
"event_type_has_been_rescheduled_on_time_date": "Ihr {{eventType}} mit {{name}} wurde auf {{time}} ({{timeZone}}) am {{date}} verschoben.",
"event_has_been_rescheduled": "Ihr Event wurde 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",
@@ -76,7 +74,7 @@
"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": "Hi {{userName}}",
"hi_user_name": "Hallo {{userName}}",
"ics_event_title": "{{eventType}} mit {{name}}",
"new_event_subject": "Neuer Termin: {{attendeeName}} - {{date}} - {{eventType}}",
"join_by_entrypoint": "{{entryPoint}} beitreten",
@@ -99,9 +97,7 @@
"join_team": "Team beitreten",
"manage_this_team": "Dieses Team verwalten",
"team_info": "Informationen zum Team",
"request_another_invitation_email": "Falls Sie {{toEmail}} lieber nicht als Ihre {{appName}}-E-Mail verwenden möchten oder bereits über ein {{appName}}-Konto verfügen, fordern Sie bitte eine weitere Einladung zu dieser E-Mail an.",
"you_have_been_invited": "Sie wurden eingeladen, dem Team {{teamName}} beizutreten",
"user_invited_you": "{{user}} hat Sie eingeladen, dem Team {{teamName}} beizutreten",
"hidden_team_member_title": "Sie sind in diesem Team ausgeblendet",
"hidden_team_member_message": "Ihre Teammitgliedschaft ist nicht bezahlt, entweder upgraden Sie Ihren Account auf Pro oder lassen den Team-Organisator wissen, dass er für Ihren Platz im Team bezahlen kann.",
"hidden_team_owner_message": "Sie benötigen einen Pro-Account um die Teamfunktionen zu verweden. Sie werden dem Team nicht angezeigt, bis der Account upgegradet wurde.",
@@ -113,8 +109,6 @@
"team_upgraded_successfully": "Das Update für Ihr Team war erfolgreich!",
"use_link_to_reset_password": "Benutzen Sie den Link, um Ihr Passwort zurückzusetzen",
"hey_there": "Hallo,",
"forgot_your_password_calcom": "Passwort vergessen? - {{appName}}",
"delete_webhook_confirmation_message": "Sind Sie sicher, dass Sie diesen Webhook löschen möchten? Sie werden keine {{appName}} Termindaten mehr erhalten.",
"confirm_delete_webhook": "Ja, Webhook löschen",
"edit_webhook": "Webhook bearbeiten",
"delete_webhook": "Webhook löschen",
@@ -124,7 +118,7 @@
"webhook_response": "Webhook-Antwort",
"webhook_test": "Webhook-Test",
"manage_your_webhook": "Webhook verwalten",
"webhook_created_successfully": "Webhook erfolgreich aktualisiert!",
"webhook_created_successfully": "Webhook erfolgreich erstellt!",
"webhook_updated_successfully": "Webhook erfolgreich aktualisiert!",
"webhook_removed_successfully": "Webhook erfolgreich entfernt!",
"payload_template": "Payload Vorlage",
@@ -148,7 +142,7 @@
"install_another": "Weitere installieren",
"until": "bis",
"powered_by": "betrieben von",
"unavailable": "Unverfügbar",
"unavailable": "Nicht verfügbar",
"set_work_schedule": "Arbeitszeiten festlegen",
"change_bookings_availability": "Verfügbarkeit für Buchungen ändern",
"select": "Auswählen...",
@@ -184,15 +178,14 @@
"register": "Registrieren",
"page_doesnt_exist": "Diese Seite existiert nicht.",
"check_spelling_mistakes_or_go_back": "Prüfen Sie auf Rechtschreibfehler oder gehen Sie zur vorherigen Seite zurück.",
"404_page_not_found": "404: Diese Seite konnte nicht gefunden werden.",
"404_page_not_found": "Fehler 404: Diese Seite konnte nicht gefunden werden.",
"getting_started": "Los geht's",
"15min_meeting": "15 Minuten Termin",
"30min_meeting": "30 Minuten Termin",
"secret": "Passwort",
"leave_blank_to_remove_secret": "Leer lassen, um Passwort zu entfernen",
"webhook_secret_key_description": "Stellen Sie sicher, dass Ihr Server aus Sicherheitsgründen nur die erwarteten {{appName}}-Anfragen empfängt",
"secret_meeting": "Geheimer Termin",
"login_instead": "Stattdessen anmelden",
"login_instead": "Stattdessen einloggen",
"already_have_an_account": "Haben Sie bereits ein Konto?",
"create_account": "Konto erstellen",
"confirm_password": "Passwort bestätigen",
@@ -234,13 +227,11 @@
"details": "Details",
"welcome": "Willkommen",
"welcome_back": "Willkommen zurück",
"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}}",
"who": "Wer",
"what": "Was",
"when": "Wann",
@@ -249,7 +240,7 @@
"add_another_calendar": "Einen weiteren Kalender hinzufügen",
"other": "Sonstige",
"emailed_you_and_attendees": "Wir haben Ihnen und den anderen Teilnehmern eine Einladung zum Kalender mit allen Details zugeschickt.",
"emailed_you_and_attendees_recurring": "Wir haben Ihnn und den anderen Teilnemern eine Kalendereinladung für den ersten Termin dieses wiederkehrendem Ereignisses gesendet.",
"emailed_you_and_attendees_recurring": "Wir haben Ihnn und den anderen Teilnemern eine Kalendereinladung für den ersten Termin dieser wiederkehrenden Termins gesendet.",
"emailed_you_and_any_other_attendees": "Wir haben Ihnen und allen anderen Teilnehmer diesen Informationen per E-Mail geschickt.",
"needs_to_be_confirmed_or_rejected": "Ihre Buchung muss noch bestätigt oder abgelehnt werden.",
"needs_to_be_confirmed_or_rejected_recurring": "Ihr wiederkehrender Termin muss noch bestätigt oder abgelehnt werden.",
@@ -327,8 +318,8 @@
"start_time": "Beginn",
"end_time": "Ende",
"buffer_time": "Pufferzeit",
"before_event": "Vor dem Ereignis",
"after_event": "Nach dem Event",
"before_event": "Vor dem Termin",
"after_event": "Nach dem Termin",
"event_buffer_default": "Keine Pufferzeit",
"buffer": "Puffer",
"your_day_starts_at": "Ihr Tag beginnt um",
@@ -346,37 +337,33 @@
"dark": "Dunkel",
"automatically_adjust_theme": "Theme automatisch basierend auf den Einstellungen des Teilnehmers anpassen",
"user_dynamic_booking_disabled": "Einige der Benutzer in der Gruppe haben derzeit dynamische Gruppenbuchungen deaktiviert",
"allow_dynamic_booking_tooltip": "Gruppenbuchungslinks, die dynamisch durch Hinzufügen mehrerer Benutzernamen mit einem '+' erstellt werden können. Beispiel: '{{appName}}/bailey+peer'",
"allow_dynamic_booking": "Ermöglichen Sie es den Teilnehmenden, Sie über dynamische Gruppenbuchungen zu buchen",
"email": "Email",
"email_placeholder": "jdoe@example.com",
"email": "E-Mail",
"email_placeholder": "max@example.com",
"full_name": "Vollständiger Name",
"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",
"booking_created": "Buchung erstellt",
"booking_created": "Termin erstellt",
"meeting_ended": "Meeting beendet",
"form_submitted": "Formular gesendet",
"event_triggers": "Ereignis-Auslöser",
"event_triggers": "Event-Auslöser",
"subscriber_url": "Subscriber-URL",
"create_new_webhook": "Einen neuen Webhook erstellen",
"webhooks": "Webhooks",
"team_webhooks": "Team Webhooks",
"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 ein Ereignis geplant oder abgesagt wird.",
"responsive_fullscreen_iframe": "Responsives Vollbild-iframe",
"responsive_fullscreen_iframe": "Responsives Vollbild-iFrame",
"loading": "Wird geladen...",
"deleting": "Lösche...",
"standard_iframe": "Standard iframe",
"standard_iframe": "Standard iFrame",
"developer": "Entwickler",
"manage_developer_settings": "Verwalten Sie Ihre Entwicklereinstellungen.",
"iframe_embed": "iframe Embed",
"embed_calcom": "Der einfachste Weg, {{appName}} auf Ihrer Website einzubinden.",
"integrate_using_embed_or_webhooks": "Integrieren Sie {{appName}} in Ihre Website mit unseren Einbettungs-Optionen oder erhalten Sie Buchungsdaten mit Webhooks.",
"iframe_embed": "iFrame-Einbettung",
"integrate_using_embed_or_webhooks": "Integrieren Sie Cal.com in Ihre Website mit unseren Einbettungs-Optionen oder erhalten Sie Buchungsdaten mit Webhooks.",
"schedule_a_meeting": "Termin planen",
"view_and_manage_billing_details": "Ihre Rechnungsdetails ansehen und verwalten",
"view_and_edit_billing_details": "Rechnungsdaten ansehen, bearbeiten oder Abonnement kündigen.",
@@ -495,7 +482,7 @@
"members": "Mitglieder",
"member": "Mitglied",
"owner": "Inhaber",
"admin": "Admin",
"admin": "Administrator",
"administrator_user": "Administrator Benutzer",
"lets_create_first_administrator_user": "Lass uns als erstes den Administrator Benutzer anlegen.",
"new_member": "Neues Mitglied",
@@ -507,8 +494,6 @@
"invite_new_member_description": "Hinweis: Dies wird <1>einen zusätzlichen Platz(15 $/m)</1> in Ihrem Abonnement kosten.",
"invite_new_team_member": "Laden Sie jemanden in Ihr Team ein.",
"change_member_role": "Rolle des Teammitglieds ändern",
"disable_cal_branding": "{{appName}} Werbung deaktivieren",
"disable_cal_branding_description": "Verstecken Sie {{appName}} Werbung auf Ihren öffentlichen Seiten.",
"danger_zone": "Achtung",
"back": "Zurück",
"cancel": "Abbrechen",
@@ -582,7 +567,7 @@
"web3_metamask_added": "Metamask erfolgreich hinzugefügt",
"web3_metamask_disconnected": "Metamask erfolgreich getrennt",
"hours": "Stunden",
"your_email": "Ihre Emailadresse",
"your_email": "Ihre E-Mail-Adresse",
"change_avatar": "Profilbild ändern",
"language": "Sprache",
"timezone": "Zeitzone",
@@ -605,8 +590,8 @@
"max": "Maximal",
"single_theme": "Einzelnes Theme",
"brand_color": "Markenfarbe",
"light_brand_color": "Brand Farbe (Helles Theme)",
"dark_brand_color": "Brand Farbe (Dunkles Theme)",
"light_brand_color": "Markenfarbe (Helles Theme)",
"dark_brand_color": "Markenfarbe (Dunkles Theme)",
"file_not_named": "Datei heißt nicht [idOrSlug]/[user]",
"create_team": "Team anlegen",
"name": "Name",
@@ -619,18 +604,18 @@
"teams": "Teams",
"team": "Team",
"team_billing": "Abrechnung der Teams",
"team_billing_description": "Verwalte die Abrechungen deines Teams",
"upgrade_to_flexible_pro_title": "Wir haben die Abrechnung für Teams geändert",
"upgrade_to_flexible_pro_message": "Es gibt Mitglieder in Ihrem Team ohne Lizenz. Upgraden Sie Ihren Pro-Plan um fehlende Lizenzen abzudecken.",
"changed_team_billing_info": "Ab Januar 2022 berechnen wir pro Sitzplatz für Teammitglieder. Mitglieder deines Teams, die Pro kostenlos hatten, sind jetzt in einer 14 Tage Testphase. Sobald die Testversion abläuft, werden diese Mitglieder vor Ihrem Team verborgen, es sei denn, Sie upgraden jetzt.",
"create_manage_teams_collaborative": "Erstellen und verwalten Sie Teams, um kollaborative Funktionen zu nutzen.",
"only_available_on_pro_plan": "Diese Funktion ist nur im Pro Plan verfügbar",
"remove_cal_branding_description": "Um die {{appName}} Werbung von Ihren Buchungsseiten zu entfernen, müssen Sie auf ein Pro-Konto upgraden.",
"edit_profile_info_description": "Bearbeiten Sie Ihre Profilinformationen, welche bei Ihrem Cal-Link angezeigt werden.",
"change_email_tip": "Möglicherweise müssen Sie sich aus- und einloggen, um die Änderung wirksam zu machen.",
"little_something_about": "Ein wenig über sich selbst.",
"profile_updated_successfully": "Profil erfolgreich aktualisiert",
"your_user_profile_updated_successfully": "Ihr Benutzerprofil wurde erfolgreich aktualisiert.",
"user_cannot_found_db": "Benutzer scheint eingeloggt zu sein, kann aber nicht in db gefunden werden",
"user_cannot_found_db": "Benutzer scheint eingeloggt zu sein, kann aber nicht in der Datenbank gefunden werden",
"embed_and_webhooks": "Einbetten & Webhooks",
"enabled": "Aktiviert",
"disabled": "Deaktiviert",
@@ -646,18 +631,18 @@
"error": "Fehler",
"at_least_characters_one": "Bitte geben Sie wenigstens ein Zeichen ein",
"at_least_characters_other": "Bitte geben Sie mindestens {{count}} Zeichen ein",
"team_logo": "Team Logo",
"team_logo": "Team-Logo",
"add_location": "Standort hinzufügen",
"attendees": "TeilnehmerInnen",
"add_attendees": "TeilnehmerInnen hinzufügen",
"attendees": "Teilnehmende",
"add_attendees": "Teilnehmende hinzufügen",
"show_advanced_settings": "Erweiterte Einstellungen anzeigen",
"event_name": "Termin Name",
"event_name": "Termin-Name",
"event_name_tooltip": "Der Name, der in Kalendern angezeigt wird",
"meeting_with_user": "Meeting mit {ATTENDEE}",
"meeting_with_user": "Meeting mit {{attendeeName}}",
"additional_inputs": "Zusätzliche Notizen",
"additional_input_description": "Erfordert die Eingabe zusätzlicher Eingaben durch den Planer vor der Buchungsbestätigung",
"label": "Bezeichnung",
"placeholder": "Placeholder",
"placeholder": "Platzhalter",
"type": "Typ",
"edit": "Bearbeiten",
"add_input": "Eingabe hinzufügen",
@@ -673,21 +658,13 @@
"private_link_label": "Privater Link",
"private_link_hint": "Ihr privater Link wird nach jeder Nutzung neu generiert",
"copy_private_link": "Privaten Link kopieren",
"private_link_description": "Erzeuge einen privaten Link um einen Link zu teilen, der deinen {{appName}} Benutzername nicht preisgibt",
"invitees_can_schedule": "Teilnehmer können folgendes buchen",
"invitees_can_schedule": "Teilnehmende können folgendes buchen",
"date_range": "Datumszeitraum",
"calendar_days": "Kalendertage",
"business_days": "Werktage",
"set_address_place": "Adresse oder Ort festlegen",
"set_link_meeting": "Einen Link zum Termin setzen",
"cal_invitee_phone_number_scheduling": "{{appName}} wird Ihren Teilnehmer bitten, vor der Planung eine Telefonnummer einzugeben.",
"cal_provide_google_meet_location": "{{appName}} wird einen Google Meet Termin zur Verfügung stellen.",
"cal_provide_zoom_meeting_url": "{{appName}} stellt eine Zoom Termin-URL zur Verfügung.",
"cal_provide_tandem_meeting_url": "{{appName}} stellt eine Tandem Termin-URL zur Verfügung.",
"cal_provide_video_meeting_url": "{{appName}} stellt eine tägliche Video-Termin-URL zur Verfügung.",
"cal_provide_jitsi_meeting_url": "{{appName}} stellt eine Jitsi Meet URL zur Verfügung.",
"cal_provide_huddle01_meeting_url": "{{appName}} stellt eine tägliche Huddle01-Web3-Termin-URL zur Verfügung.",
"cal_provide_teams_meeting_url": "{{appName}} stellt eine MS Teams Termin-URL zur Verfügung. HINWEIS: Sie brauchen ein berufliches- oder Schulkonto.",
"cal_provide_jitsi_meeting_url": "Cal stellt eine Jitsi Meet URL zur Verfügung.",
"require_payment": "Zahlung erforderlich",
"commission_per_transaction": "Provision pro Transaktion",
"event_type_updated_successfully_description": "Ihr Termintyp wurde erfolgreich aktualisiert.",
@@ -697,7 +674,7 @@
"within_date_range": "Innerhalb eines Zeitraums",
"indefinitely_into_future": "Auf unbestimmte Zeit in die Zukunft",
"add_new_custom_input_field": "Neues individuelles Eingabefeld hinzufügen",
"quick_chat": "Quick Chat",
"quick_chat": "Schneller Chat",
"add_new_team_event_type": "Neuen Termintyp hinzufügen",
"add_new_event_type": "Neuen Termintyp hinzufügen",
"new_event_type_to_book_description": "Erstellen Sie einen neuen Termintyp, mit dem Personen Zeiten buchen können.",
@@ -710,9 +687,10 @@
"confirm_delete_event_type": "Ja, Termintyp löschen",
"delete_account": "Account löschen",
"confirm_delete_account": "Ja, Account löschen",
"delete_account_confirmation_message": "Sind Sie sicher, dass Sie ihren {{appName}} Account löschen wollen? Sie können dann nicht mehr über Ihre geteilten Links gebucht werden und und alle Einstellungen gehen verloren.",
"integrations": "Integrationen",
"apps": "Apps",
"apps_description": "Hier findest du eine Auflistung deiner Apps",
"apps_listing": "App-Liste",
"category_apps": "{{category}} Apps",
"app_store": "App Store",
"app_store_description": "Verbindet Menschen, Technologie und den Arbeitsplatz.",
@@ -732,7 +710,7 @@
"embed_your_calendar": "Fügen Sie Ihren Kalender in Ihre Webseite ein",
"connect_your_favourite_apps": "Verbinden Sie Ihre Lieblings-Apps.",
"automation": "Automatisierung",
"configure_how_your_event_types_interact": "Konfigurieren Sie, wie Ihre Event-Typen mit Ihren Kalendern interagieren sollen.",
"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",
@@ -748,7 +726,7 @@
"set_as_away": "Stelle deinen Status auf Abwesend",
"set_as_free": "Abwesenheitsstatus deaktivieren",
"user_away": "Dieser Benutzer ist derzeit abwesend.",
"user_away_description": "Die Person, mi der Sie einen Termin buchen wollen, ist zur Zeit abwesend und akzeptiert daher keine neuen Buchungen.",
"user_away_description": "Die Person, mit der Sie einen Termin buchen wollen, ist zur Zeit abwesend und akzeptiert daher keine neuen Buchungen.",
"meet_people_with_the_same_tokens": "Triff Leute mit den selben Token",
"only_book_people_and_allow": "Nur Buchungen von Personen erlauben, die die gleichen Token, DAOs oder NFTs teilen.",
"account_created_with_identity_provider": "Ihr Konto wurde mit einem Identitäts-Anbieter erstellt.",
@@ -768,11 +746,12 @@
"trending_apps": "Angesagte Apps",
"explore_apps": "{{category}} Apps",
"installed_apps": "Installierte Apps",
"free_to_use_apps": "Kostenlos",
"no_category_apps": "Keine {{category}} Apps",
"no_category_apps_description_calendar": "Fügen Sie eine Kalender-App hinzu, in der nach Konflikten gesucht werden soll, um Doppelbuchungen zu vermeiden",
"no_category_apps_description_conferencing": "Versuchen Sie, eine Konferenz-App hinzuzufügen, um Videoanrufe mit Ihren Kunden zu integrieren",
"no_category_apps_description_payment": "Fügen Sie eine Zahlungs-App hinzu, um die Transaktion zwischen Ihnen und Ihren Kunden zu erleichtern",
"no_category_apps_description_analytics": "Fügen Sie eine Analyse-App für Ihre Buchungsseiten hinzu",
"no_category_apps_description_automation": "Fügen Sie eine Automatisierungs-App hinzu, die verwendet werden soll",
"no_category_apps_description_other": "Füge jede beliebige andere Art von App hinzu, um alle möglichen Dinge zu tun",
"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",
@@ -805,11 +784,8 @@
"verify_wallet": "Wallet verifizieren",
"connect_metamask": "Metamask verbinden",
"create_events_on": "Erstelle Termine in:",
"enterprise_license": "Das ist eine Enterprise-Funktion",
"enterprise_license_description": "Um diese Funktion zu aktivieren, holen Sie sich einen Deployment-Schlüssel von der {{consoleUrl}}-Konsole und fügen Sie ihn als CALCOM_LICENSE_KEY zu Ihrer .env hinzu. Wenn Ihr Team bereits eine Lizenz hat, wenden Sie sich bitte an {{supportMail}} für Hilfe.",
"missing_license": "Lizenz fehlt",
"signup_requires": "Kommerzielle Lizenz erforderlich",
"signup_requires_description": "{{companyName}} bietet zur Zeit keine kostenlose Open-Source-Version der Anmeldeseite an. Um vollen Zugriff auf die Registrierungskomponenten zu erhalten, müssen Sie eine kommerzielle Lizenz erwerben. Für den persönlichen Gebrauch empfehlen wir die Prisma Data Platform oder jede andere Postgres-Schnittstelle zur Erstellung von Accounts.",
"next_steps": "Nächste Schritte",
"acquire_commercial_license": "Eine kommerzielle Lizenz erwerben",
"the_infrastructure_plan": "Der Infrastrukturplan ist nutzungsbasiert und bietet Startup-freundliche Discounts an.",
@@ -825,11 +801,11 @@
"set_calendar": "Legen Sie fest, wo neue Events hinzugefügt werden sollen, wenn Sie ausgebucht sind.",
"delete_schedule": "Verfügbarkeitsplan löschen",
"schedule_created_successfully": "{{scheduleName}} -Verfügbarkeitsplan erfolgreich erstellt",
"availability_updated_successfully": "Verfügbarkeit erfolgreich aktualisiert",
"availability_updated_successfully": "Verfügbarkeitsplan erfolgreich aktualisiert",
"schedule_deleted_successfully": "Verfügbarkeitsplan erfolgreich gelöscht",
"default_schedule_name": "Arbeitszeiten",
"new_schedule_heading": "Erstelle einen Verfügbarkeitsplan",
"new_schedule_description": "Das Erstellen von Verfügbarkeitsplan sorgt dafür, dass Ihre Verfügbarkeit bei mehreren Termintypen genutzt werden kann.",
"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:",
"example_name": "Max Mustermann",
"time_format": "Zeitformat",
@@ -899,9 +875,9 @@
"user_impersonation_description": "Erlaubt es unserem Support-Team, sich vorübergehend mit Ihrem Konto anzumelden, um jegliche Probleme, die Sie gemeldet haben, schneller zu lösen.",
"team_impersonation_description": "Ermöglicht den Team-Administratoren, sich vorübergehend als Sie einzuloggen.",
"impersonate_user_tip": "Alle Verwendungen dieser Funktion werden geprüft.",
"impersonating_user_warning": "Imitiere den User {{user}}.",
"impersonating_user_warning": "Imitiere den Account {{user}}.",
"impersonating_stop_instructions": "<0>Klicke hier um zu stoppen </0>.",
"event_location_changed": "Aktualisiert - Ihr Ereignis hat den Standort geändert",
"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",
@@ -911,23 +887,17 @@
"update_location": "Ort aktualisieren",
"location_updated": "Ort aktualisiert",
"email_validation_error": "Das sieht nicht wie eine E-Mail-Adresse aus",
"place_where_cal_widget_appear": "Kopieren Sie diesen Code in ihr HTML wo ihr {{appName}}-Widget erscheinen soll.",
"create_update_react_component": "Erstellen oder Aktualisieren einer existierenden Reaktionskomponente wie unten gezeigt.",
"copy_code": "Code kopieren",
"code_copied": "Code kopiert!",
"how_you_want_add_cal_site": "Wie möchten Sie {{appName}} zu Ihrer Website hinzufügen?",
"choose_ways_put_cal_site": "Wählen Sie eine der folgenden Möglichkeiten, {{appName}} auf Ihrer Website zu integrieren.",
"setting_up_zapier": "Einrichtung Ihrer Zapier-Integration",
"generate_api_key": "Api Key generieren",
"generate_api_key_description": "Generieren Sie einen API-Schlüssel für {{appName}} auf",
"your_unique_api_key": "Ihr eindeutiger API-Key",
"copy_safe_api_key": "Kopieren Sie diesen API-Key und speichern Sie ihn an einem sicheren Ort. Wenn Sie diesen Key verlieren, müssen Sie einen neuen generieren.",
"zapier_setup_instructions": "<0>Gehen Sie zu: <1>Zapier-Einladungs-Link</1></0><1>Logge Sie sich in Ihr Zapier-Konto ein und erstelle einen neuen Zap.</1><2>Wählen Sie {{appName}} als ihre Trigger-App aus. Wählen Sie auch ein Auslöserereignis.</2><3>Wähle Sie ihr Konto aus und geben dann ihren eindeutigen API-Key ein.</3><4>Teste Sie den Trigger.</4><5>Alles fertig!</5>",
"copy_safe_api_key": "Kopieren Sie diesen API-Schlüssel und speichern Sie ihn an einem sicheren Ort. Wenn Sie diesen Schlüssel verlieren, müssen Sie einen neuen generieren.",
"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.",
"it_stored_encrypted": "Er wird gespeichert und verschlüsselt.",
"go_to_app_store": "Zum App Store",
@@ -944,7 +914,7 @@
"share_feedback": "Feedback teilen",
"resources": "Ressourcen",
"support_documentation": "Support Dokumentation",
"developer_documentation": "Entwickler Dokumentation",
"developer_documentation": "Entwickler-Dokumentation",
"get_in_touch": "Kontakt aufnehmen",
"contact_support": "Support kontaktieren",
"feedback": "Feedback",
@@ -956,7 +926,7 @@
"nevermind": "Egal",
"go_to": "Gehe zu: ",
"zapier_invite_link": "Zapier Einladungs-Link",
"meeting_url_provided_after_confirmed": "Eine Temrin-URL wird angelegt, sobald die Buchung bestätigt wurde.",
"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",
@@ -970,7 +940,7 @@
"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 neues Ereignis gebucht 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 Teilnehmer senden",
"sms_attendee_action": "SMS an Teilnehmer senden",
@@ -1045,7 +1015,7 @@
"invalid_input": "Ungültige Eingabe",
"broken_video_action": "Wir konnten den <1>{{location}}</1> Meeting-Link nicht zu Ihrem geplanten Ereignis hinzufügen. Kontaktieren Sie Ihre Eingeladenen oder aktualisieren Sie Ihr Kalenderereignis, um die Einzelheiten hinzuzufügen. Sie können entweder <3> Ihren Standort im Ereignistyp ändern</3> oder <5>die App entfernen und erneut hinzufügen.</5>",
"broken_calendar_action": "Wir konnten Ihren <1>{{calendar}}</1> nicht aktualisieren. <2> Bitte überprüfen Sie die Kalendereinstellungen oder entfernen Sie Ihren Kalender und fügen Sie Ihren Kalender erneut hinzu </2>",
"attendee_name": "Teilnehmername",
"attendee_name": "Name des Teilnehmenden",
"broken_integration": "Defekte Integration",
"problem_adding_video_link": "Beim Hinzufügen eines Video-Links ist ein Problem aufgetreten",
"problem_updating_calendar": "Es gab ein Problem beim Aktualisieren Ihres Kalenders",
@@ -1097,38 +1067,35 @@
"connect_your_calendar_and_link": "Sie können Ihren Kalender von <1>hier</1> verbinden.",
"default_calendar_selected": "Standardkalender",
"hide_from_profile": "Im Profil ausblenden",
"event_setup_tab_title": "Event-Einrichtung",
"event_setup_tab_title": "Termin-Einrichtung",
"event_limit_tab_title": "Limits",
"event_limit_tab_description": "Wie oft können Sie gebucht werden",
"event_advanced_tab_description": "Kalendereinstellungen & mehr...",
"event_advanced_tab_title": "Erweitert",
"select_which_cal": "Wählen Sie den Kalender aus, zu dem Buchungen hinzugefügt werden sollen",
"custom_event_name": "Eigener Ereignisname",
"custom_event_name_description": "Erstellen Sie benutzerdefinierte Ereignisnamen, die im Kalenderereignis angezeigt werden sollen",
"select_which_cal": "Wählen Sie den Kalender aus, zu dem Termine hinzugefügt werden sollen",
"custom_event_name": "Eigener Terminname",
"custom_event_name_description": "Erstellen Sie benutzerdefinierte Terminnamen, die im Kalendereintrag angezeigt werden sollen",
"2fa_required": "Zwei-Faktor-Authentifizierung erforderlich",
"incorrect_2fa": "Falscher Zwei-Faktor-Authentifizierungscode",
"which_event_type_apply": "Auf welchen Ereignistyp wird dies angewandt?",
"which_event_type_apply": "Auf welchen Termintyp wird dies angewandt?",
"no_workflows_description": "Workflows ermöglichen die einfache Automatisierung des Versands von Benachrichtigungen und Erinnerungen, so dass Sie Prozesse rund um Ihre Ereignisse erstellen können.",
"timeformat_profile_hint": "Dies ist eine interne Einstellung und hat keinen Einfluss darauf, wie die Zeiten auf den öffentlichen Buchungsseiten für Sie oder jemanden, der Sie buchen möchte, angezeigt werden.",
"create_workflow": "Einen Workflow erstellen",
"do_this": "Mache dies",
"turn_off": "Abschalten",
"settings_updated_successfully": "Einstellungen erfolgreich aktualisiert",
"error_updating_settings": "Fehler beim Aktualisieren der Einstellungen",
"personal_cal_url": "Meine persönliche {{appName}} URL",
"bio_hint": "Schreiben Sie eine kurze Beschreibung, welche auf Ihrer persönlichen Url-Seite erscheinen wird.",
"timeformat_profile_hint": "Dies ist eine interne Einstellung und hat keinen Einfluss darauf, wie die Zeiten auf den öffentlichen Buchungsseiten für Sie oder jemanden, der Sie buchen möchte, angezeigt werden.",
"bio_hint": "Schreiben Sie eine kurze Beschreibung, welche auf Ihrer persönlichen Profil-Seite erscheinen wird.",
"delete_account_modal_title": "Account löschen",
"confirm_delete_account_modal": "Sind Sie sicher, dass Sie Ihr {{appName}}-Konto löschen möchten?",
"delete_my_account": "Meinen Account löschen",
"start_of_week": "Wochenstart",
"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",
"adding_events_to": "Ereignisse hinzufügen zu",
"adding_events_to": "Termine hinzufügen zu",
"follow_system_preferences": "Systemeinstellungen folgen",
"custom_brand_colors": "Eigene Marken-Farben",
"customize_your_brand_colors": "Passen Sie Ihre eigene Markenfarbe auf Ihrer Buchungsseite an.",
"pro": "Pro",
"removes_cal_branding": "Entfernt alle {{appName}}-bezogenen Markenzeichen, z.B. \"Powered by {{appName}}.\"",
"profile_picture": "Profilbild",
"upload": "Upload",
"add_profile_photo": "Profilbild hinzufügen",
@@ -1155,8 +1122,11 @@
"invoices": "Rechnungen",
"embeds": "Embeds",
"impersonation": "Benutzeridentitätswechsel",
"impersonation_description": "Einstellungen um Benutzeridentitätswechsel zu verwalten",
"users": "Benutzer",
"profile_description": "Einstellungen für Ihr {{appName}} Profil verwalten",
"users_description": "Hier findest du eine Auflistung aller Benutzer",
"users_listing": "Benutzerliste",
"general_description": "Einstellungen für Ihre Sprache und Zeitzone verwalten",
"calendars_description": "Konfigurieren Sie, wie Ihre Event-Typen mit Ihren Kalendern interagieren sollen",
"appearance_description": "Einstellungen für Ihre Buchungsdarstellung verwalten",
@@ -1194,7 +1164,6 @@
"create_your_first_form": "Erstellen Sie Ihr erstes Formular",
"create_your_first_form_description": "Mithilfe von Leitungsformularen können Sie qualifizierende Fragen stellen und zur richtigen Person oder zum richtigen Veranstaltungstyp weiterleiten.",
"create_your_first_webhook": "Erstellen Sie Ihren ersten Webhook",
"create_your_first_webhook_description": "Mit Webhooks können Sie Meetingdaten in Echtzeit erhalten, sobald etwas auf {{appName}} passiert.",
"for_a_maximum_of": "Für maximal",
"event_one": "Ereignis",
"event_other": "Ereignisse",
@@ -1210,7 +1179,6 @@
"workflow_example_4": "Eine Erinnerung per SMS an die Teilnehmer verschicken, 24 Stunden bevor das Event startet",
"workflow_example_5": "Benutzerdefinierte E-Mail senden, wenn der Termin zum Moderieren neu geplant wird",
"workflow_example_6": "Benutzerdefinierte SMS senden, wenn der Termin zum Moderieren gebucht wird",
"welcome_to_cal_header": "Willkommen bei {{appName}}!",
"edit_form_later_subtitle": "Sie können dies später bearbeiten.",
"connect_calendar_later": "Ich verbinde meinen Kalender später",
"set_my_availability_later": "Ich werde meine Verfügbarkeit später festlegen",
@@ -1220,7 +1188,6 @@
"booking_appearance": "Darstellung der Buchungsseite",
"appearance_team_description": "Einstellungen für die Buchungsdarstellung Ihres Teams verwalten",
"only_owner_change": "Nur der Besitzer dieses Teams kann Änderungen an den Buchungen des Teams vornehmen ",
"team_disable_cal_branding_description": "Entfernt alle {{appName}}-bezogenen Markenzeichen, z.B. 'Powered by {{appName}}.'",
"invited_by_team": "{{teamName}} hat Sie eingeladen, dem Team als {{role}} beizutreten",
"token_invalid_expired": "Token ist entweder ungültig oder abgelaufen.",
"exchange_add": "Mit Microsoft Exchange verbinden",
@@ -1229,7 +1196,7 @@
"exchange_authentication_ntlm": "NTLM-Authentifizierung",
"exchange_compression": "GZip-Kompression",
"routing_forms_description": "Hier sehen Sie alle Formulare und Weiterleitungen, die Sie erstellt haben.",
"routing_forms_send_email_owner": "E-Mail an Besitzer senden",
"routing_forms_send_email_owner": "E-Mail an Eigentümer senden",
"routing_forms_send_email_owner_description": "Sendet eine E-Mail an den Eigentümer, wenn das Formular abgeschickt wird",
"add_new_form": "Neues Formular hinzufügen",
"form_description": "Erstellen Sie Ihr Formular, um einen Bucher zu anzuleiten",
@@ -1240,13 +1207,11 @@
"theme_dark": "Dunkel",
"theme_system": "Systemstandard",
"add_a_team": "Team hinzufügen",
"add_webhook_description": "Erhalten Sie Meetingdaten in Echtzeit, wenn etwas auf {{appName}} passiert",
"triggers_when": "Löst aus, wenn",
"test_webhook": "Bitte führen Sie einen Pingtest vor der Erstellung durch.",
"enable_webhook": "Webhook aktivieren",
"add_webhook": "Webhook hinzufügen",
"webhook_edited_successfully": "Webhook gespeichert",
"webhooks_description": "Erhalten Sie Meetingdaten in Echtzeit, wenn etwas auf {{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",
@@ -1255,21 +1220,19 @@
"embeds_title": "HTML iframe-Einbettung",
"embeds_description": "Alle Event-Typen auf Ihrer Website einbetten",
"create_first_api_key": "Erstellen Sie Ihren ersten API-Schlüssel",
"create_first_api_key_description": "API-Schlüssel erlauben es anderen Apps, mit {{appName}} zu kommunizieren",
"back_to_signin": "Zurück zur Anmeldung",
"reset_link_sent": "Zurücksetzungslink gesendet",
"password_reset_email": "Eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts ist auf dem Weg zu {{email}}.",
"password_reset_leading": "Falls Sie nicht bald eine E-Mail erhalten, überprüfen Sie, ob die eingegebene E-Mail-Adresse korrekt ist. Überprüfen Sie außerdem Ihren Spam-Ordner oder wenden Sie sich an den Support, wenn das Problem weiterhin besteht.",
"password_updated": "Passwort aktualisiert!",
"pending_payment": "Zahlung ausstehend",
"confirmation_page_rainbow": "Sperren Sie Ihr Ereignis hinter Tokens oder NFTs auf Ethereum, Polygon und mehr.",
"not_on_cal": "Nicht auf {{appName}}",
"no_calendar_installed": "Kein Kalender installiert",
"no_calendar_installed_description": "Sie haben noch keinen Ihrer Kalender verbunden",
"add_a_calendar": "Kalender hinzufügen",
"change_email_hint": "Möglicherweise müssen Sie sich aus- und einloggen, um jegliche Änderung wirksam zu machen",
"confirm_password_change_email": "Bitte bestätigen Sie Ihr Passwort, bevor Sie Ihre E-Mail-Adresse ändern",
"seats": "Plätze",
"every_app_published": "Jede App, die im {{appName}} App Store veröffentlicht wird, ist Open Source und gründlich durch Peer Reviews getestet. {{companyName}} unterstützt oder zertifiziert diese Apps jedoch nicht, es sei denn, sie werden von {{appName}} veröffentlicht. Wenn Sie auf unangemessene Inhalte oder Verhaltensweisen stoßen, melden Sie diese bitte.",
"report_app": "App melden",
"limit_booking_frequency": "Buchungsfrequenz begrenzen",
"limit_booking_frequency_description": "Begrenzen, wie oft dieses Ereignis gebucht werden kann",
@@ -1324,7 +1287,7 @@
"saml_config_updated_successfully": "SAML-Konfiguration erfolgreich aktualisiert",
"saml_configuration": "SAML-Einstellungen",
"delete_saml_configuration": "SAML-Konfiguration löschen",
"delete_saml_configuration_confirmation_message": "Sind Sie sicher, dass Sie die SAML-Konfiguration löschen möchten? Ihre Teammitglieder, die SAML-Login verwenden, können nicht mehr auf {{appName}} zugreifen.",
"delete_saml_configuration_confirmation_message": "Sind Sie sicher, dass Sie die SAML-Konfiguration löschen möchten? Ihre Teammitglieder, die SAML-Login verwenden, können nicht mehr auf Cal.com zugreifen.",
"confirm_delete_saml_configuration": "Ja, SAML-Einstellungen löschen",
"saml_not_configured_yet": "SAML wurde noch nicht konfiguriert",
"saml_configuration_description": "Bitte fügen Sie die SAML-Metadaten Ihres SAML-Anbieters in die Textbox ein, um Ihre SAML-Konfiguration zu aktualisieren.",
@@ -1337,12 +1300,15 @@
"saml_sp_acs_url_copied": "ACS-URL kopiert!",
"saml_sp_entity_id_copied": "SP-Entitäts-ID kopiert!",
"saml_btn_configure": "Konfigurieren",
"kbar_search_placeholder": "Geben Sie einen Befehl ein oder suchen Sie..."
"kbar_search_placeholder": "Geben Sie einen Befehl ein oder suchen Sie...",
"free_to_use_apps": "Kostenlos",
"enterprise_license": "Das ist eine Enterprise-Funktion",
"enterprise_license_description": "Um diese Funktion zu aktivieren, holen Sie sich einen Deployment-Schlüssel von der {{consoleUrl}}-Konsole und fügen Sie ihn als CALCOM_LICENSE_KEY zu Ihrer .env hinzu. Wenn Ihr Team bereits eine Lizenz hat, wenden Sie sich bitte an {{supportMail}} für Hilfe.",
"add_calendar": "Kalender hinzufügen",
"limit_future_bookings": "Zukünftige Buchungen begrenzen",
"limit_future_bookings_description": "Begrenzt, wie weit in die Zukunft dieses Ereignis gebucht werden kann",
"no_event_types": "Keine Ereignistypen eingerichtet",
"no_event_types_description": "{{name}} hat keine für Sie buchbaren Ereignistypen eingerichtet.",
"limit_future_bookings": "Zukünftige Termine begrenzen",
"limit_future_bookings_description": "Begrenzt, wie weit in die Zukunft dieser Termin gebucht werden kann",
"no_event_types": "Keine Termintypen eingerichtet",
"no_event_types_description": "{{name}} hat keine für Sie buchbaren Termintypen eingerichtet.",
"billing_frequency": "Rechnungshäufigkeit",
"monthly": "Monatlich",
"yearly": "Jährlich",
@@ -1354,7 +1320,7 @@
"member_already_invited": "Mitglied wurde bereits eingeladen",
"enter_email_or_username": "E-Mail oder Benutzername eingeben",
"team_name_taken": "Dieser Name ist bereits vergeben",
"must_enter_team_name": "Teamname muss eingegeben werden",
"must_enter_team_name": "Team-Name muss eingegeben werden",
"team_url_required": "Team-URL muss eingegeben werden",
"team_url_taken": "Diese URL ist bereits vergeben",
"team_publish": "Team veröffentlichen",
@@ -1367,8 +1333,8 @@
"reason": "Grund",
"sender_id": "Absender-ID",
"sender_id_error_message": "Nur Buchstaben, Zahlen und Leerzeichen erlaubt (max. 11 Zeichen)",
"test_routing_form": "Testleitungsformular",
"test_preview": "Testvorschau",
"test_routing_form": "Testweiterleitungsformular",
"test_preview": "Vorschau testen",
"route_to": "Route zu",
"test_preview_description": "Testen Sie Ihr Leitungsformular, ohne Daten zu senden",
"test_routing": "Testweiterleitung"
+39 -8
View File
@@ -466,14 +466,14 @@
"booking_confirmation": "Confirm your {{eventTypeTitle}} with {{profileName}}",
"booking_reschedule_confirmation": "Reschedule your {{eventTypeTitle}} with {{profileName}}",
"in_person_meeting": "In-person meeting",
"attendeeInPerson":"In Person (Attendee Address)",
"inPerson":"In Person (Organizer Address)",
"attendeeInPerson": "In Person (Attendee Address)",
"inPerson": "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",
"organizer_phone_number": "Organizer Phone Number",
"host_phone_number": "Your Phone Number",
"enter_phone_number": "Enter phone number",
"reschedule": "Reschedule",
@@ -629,6 +629,7 @@
"teams": "Teams",
"team": "Team",
"team_billing": "Team Billing",
"team_billing_description": "Manage billing for your team",
"upgrade_to_flexible_pro_title": "We've changed billing for teams",
"upgrade_to_flexible_pro_message": "There are members in your team without a seat. Upgrade your pro plan to cover missing seats.",
"changed_team_billing_info": "As of January 2022 we charge on a per-seat basis for team members. Members of your team who had PRO for free are now on a 14 day trial. Once their trial expires these members will be hidden from your team unless you upgrade now.",
@@ -663,7 +664,7 @@
"show_advanced_settings": "Show advanced settings",
"event_name": "Event Name",
"event_name_tooltip": "The name that will appear in calendars",
"meeting_with_user": "Meeting with {ATTENDEE}",
"meeting_with_user": "Meeting with {{attendeeName}}",
"additional_inputs": "Additional Inputs",
"additional_input_description": "Require scheduler to input additional inputs prior the booking is confirmed",
"label": "Label",
@@ -704,6 +705,7 @@
"hide_event_type": "Hide event type",
"edit_location": "Edit location",
"into_the_future": "into the future",
"when_booked_with_less_than_notice": "When booked with less than <time></time> notice",
"within_date_range": "Within a date range",
"indefinitely_into_future": "Indefinitely into the future",
"add_new_custom_input_field": "Add new custom input field",
@@ -723,6 +725,8 @@
"delete_account_confirmation_message": "Are you sure you want to delete your {{appName}} account? Anyone who you've shared your account link with will no longer be able to book using it and any preferences you have saved will be lost.",
"integrations": "Integrations",
"apps": "Apps",
"apps_description": "Here you can find a list of your apps",
"apps_listing": "App listing",
"category_apps": "{{category}} apps",
"app_store": "App Store",
"app_store_description": "Connecting people, technology and the workplace.",
@@ -746,6 +750,7 @@
"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",
"calendar": "Calendar",
"payments": "Payments",
@@ -909,7 +914,7 @@
"impersonate": "Impersonate",
"user_impersonation_heading": "User Impersonation",
"user_impersonation_description": "Allows our support team to temporarily sign in as you to help us quickly resolve any issues you report to us.",
"team_impersonation_description": "Allows your team members to temporarily sign in as you.",
"team_impersonation_description": "Allows your team Owners/Admins to temporarily sign in as you.",
"allow_booker_to_select_duration": "Allow booker to select duration",
"impersonate_user_tip": "All uses of this feature is audited.",
"impersonating_user_warning": "Impersonating username \"{{user}}\".",
@@ -1028,6 +1033,9 @@
"error_removing_app": "Error removing app",
"web_conference": "Web conference",
"requires_confirmation": "Requires confirmation",
"always_requires_confirmation": "Always",
"requires_confirmation_threshold": "Requires confirmation if booked with < {{time}} $t({{unit}}_timeUnit) notice",
"may_require_confirmation": "May require confirmation",
"nr_event_type_one": "{{count}} event type",
"nr_event_type_other": "{{count}} event types",
"add_action": "Add action",
@@ -1125,6 +1133,7 @@
"incorrect_2fa": "Incorrect two factor authentication code",
"which_event_type_apply": "Which event type will this apply to?",
"no_workflows_description": "Workflows enable simple automation to send notifications & reminders enabling you to build processes around your events.",
"timeformat_profile_hint": "This is an internal setting and will not affect how times are displayed on public booking pages for you or anyone booking you.",
"create_workflow": "Create a workflow",
"do_this": "Do this",
"turn_off": "Turn off",
@@ -1170,12 +1179,15 @@
"invoices": "Invoices",
"embeds": "Embeds",
"impersonation": "Impersonation",
"impersonation_description": "Settings to manage user impersonation",
"users": "Users",
"profile_description": "Manage settings for your {{appName}} profile",
"users_description": "Here you can find a list of all users",
"users_listing": "User listing",
"general_description": "Manage settings for your language and timezone",
"calendars_description": "Configure how your event types interact with your calendars",
"appearance_description": "Manage settings for your booking appearance",
"conferencing_description": "Manage your video conferencing apps for your meetings",
"conferencing_description": "Add your favourite video conferencing apps for your meetings",
"password_description": "Manage settings for your account passwords",
"2fa_description": "Manage settings for your account passwords",
"we_just_need_basic_info": "We just need some basic info to get your profile setup.",
@@ -1376,17 +1388,36 @@
"number_sms_notifications": "Phone number (SMS\u00a0notifications)",
"attendee_email_workflow": "Attendee email",
"attendee_email_info": "The person booking's email",
"kbar_search_placeholder": "Type a command or search...",
"free_to_use_apps": "Free",
"enterprise_license": "This is an enterprise feature",
"enterprise_license_description": "To enable this feature, get a deployment key at {{consoleUrl}} console and add it to your .env as CALCOM_LICENSE_KEY. If your team already has a license, please contact {{supportMail}} for help.",
"invalid_credential": "Oh no! Looks like permission expired or was revoked. Please reinstall again.",
"choose_common_schedule_team_event": "Choose a common schedule",
"choose_common_schedule_team_event_description": "Enable this if you want to use a common schedule between hosts. When disabled, each host will be booked based on their default schedule.",
"reason": "Reason",
"sender_id": "Sender ID",
"sender_id_error_message":"Only letters, numbers and spaces allowed (max. 11 characters)",
"sender_id_error_message": "Only letters, numbers and spaces allowed (max. 11 characters)",
"test_routing_form": "Test Routing Form",
"test_preview": "Test Preview",
"route_to": "Route to",
"test_preview_description": "Test your routing form without submitting any data",
"test_routing": "Test Routing",
"booking_limit_reached": "Booking Limit for this event type has been reached",
"fill_this_field": "Please fill in this field",
"collective_scheduling": "Collective Scheduling",
"make_it_easy_to_book": "Make it easy to book your team when everyone is available.",
"find_the_best_person": "Find the best person available and cycle through your team.",
"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": "Cal.com is better with teams",
"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",
"fill_this_field": "Please fill in this field"
"fill_this_field": "Please fill in this field",
"options": "Options",
"enter_option": "Enter Option {{index}}",
"add_an_option": "Add an option",
"radio": "Radio",
"kbar_search_placeholder" : "Start typing to search",
"set_as_default": "Set as default"
}
+12 -8
View File
@@ -101,7 +101,7 @@
"team_info": "Información del equipo",
"request_another_invitation_email": "Si prefiere no utilizar {{toEmail}} como su correo electrónico de {{appName}} o ya tiene una cuenta de {{appName}}, por favor solicite otra invitación a ese email.",
"you_have_been_invited": "Has sido invitado a unirte al equipo {{teamName}}",
"user_invited_you": "{{user}} te invitó a unirte al equipo {{teamName}}",
"user_invited_you": "{{user}} te invitó a unirte al equipo {{team}}",
"hidden_team_member_title": "Estás oculto en este equipo",
"hidden_team_member_message": "No está paga tu plaza, actualiza a PRO o infórmale al propietario del equipo para que pague tu plaza.",
"hidden_team_owner_message": "Necesitas una cuenta Pro para gestionar equipos, permanecerás oculto hasta que se realice la mejora.",
@@ -316,6 +316,7 @@
"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",
"and": "y",
"calendar_shows_busy_between": "Tu calendario te muestra como ocupado entre",
@@ -503,7 +504,7 @@
"add_team_members_description": "Invitar a otros a unirse a tu equipo",
"add_team_member": "Añadir miembro del equipo",
"invite_new_member": "Invitar a un nuevo miembro",
"invite_new_member_description": "Nota: Esto costará <1>un asiento adicional ($15/m)</1> en su suscripción.",
"invite_new_member_description": "Nota: Esto costará <1>un cupo adicional ($15/m)</1> en su suscripción.",
"invite_new_team_member": "Invita a alguien a tu equipo.",
"change_member_role": "Cambiar rol del miembro del equipo",
"disable_cal_branding": "Desactivar marca de {{appName}}",
@@ -534,7 +535,7 @@
"open_options": "Abrir Opciones",
"copy_link": "Copiar Enlace",
"share": "Compartir",
"share_event": "¿Quieres reservar mi {{appName}} o enviarme tu enlace?",
"share_event": "¿Quieres reservar mi Cal o enviarme tu enlace?",
"copy_link_team": "Copiar enlace al equipo",
"leave_team": "Abandonar equipo",
"confirm_leave_team": "Sí, abandonar equipo",
@@ -652,7 +653,7 @@
"show_advanced_settings": "Mostrar Opciones Avanzadas",
"event_name": "Nombre del Evento",
"event_name_tooltip": "Nombre que aparecerá en los calendarios",
"meeting_with_user": "Reunión con {ATTENDEE}",
"meeting_with_user": "Reunión con {{attendeeName}}",
"additional_inputs": "Campos Adicionales",
"additional_input_description": "Requerir que el planificador introduzca entradas adicionales antes de confirmar la reserva",
"label": "Etiqueta",
@@ -684,7 +685,7 @@
"cal_provide_zoom_meeting_url": "{{appName}} proporcionará una URL de reunión de Zoom.",
"cal_provide_tandem_meeting_url": "{{appName}} proporcionará una URL de reunión de Tandem.",
"cal_provide_video_meeting_url": "{{appName}} proporcionará una URL de reunión de Daily Video.",
"cal_provide_jitsi_meeting_url": "{{appName}} proporcionará una URL de reunión de Jitsi Meet.",
"cal_provide_jitsi_meeting_url": "Cal proporcionará una URL de reunión de Jitsi Meet.",
"cal_provide_huddle01_meeting_url": "{{appName}} proporcionará una URL de reunión de Huddle01 Web3 Video.",
"cal_provide_teams_meeting_url": "{{appName}} proporcionará una URL de reunión de MS Teams. NOTA: DEBE TENER UNA CUENTA DE TRABAJO O DE EDUCACIÓN",
"require_payment": "Requiere Pago",
@@ -838,6 +839,7 @@
"redirect_success_booking": "Redirigir al reservar ",
"you_are_being_redirected": "Serás redirigido a {{ url }} en $t(second, {\"count\": {{seconds}} }).",
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
"redirect_url_description": "Redirija a una URL personalizada después de una reserva exitosa",
"duplicate": "Duplicar",
"offer_seats": "Ofrecer plazas",
"offer_seats_description": "Ofrecer plazas para las reservas (desactiva las reservas de invitados y las optativas)",
@@ -1106,6 +1108,7 @@
"incorrect_2fa": "Código de autenticación de dos factores incorrecto",
"which_event_type_apply": "¿A qué tipo de evento se aplicará esto?",
"no_workflows_description": "Los flujos de trabajo permiten una automatización simple para enviar notificaciones y recordatorios que le permiten crear procesos para sus eventos.",
"timeformat_profile_hint": "Esta es una configuración interna y no afectará la manera en que se muestran los horarios en las páginas de reservas públicas para usted o para cualquier persona que lo solicite.",
"create_workflow": "Crear un flujo de trabajo",
"do_this": "Hacer esto",
"turn_off": "Apagar",
@@ -1113,7 +1116,6 @@
"error_updating_settings": "Error al actualizar la configuración",
"personal_cal_url": "Mi URL personal de {{appName}}",
"bio_hint": "Algunas frases sobre usted, esta información aparecerá en la página de su URL personal.",
"timeformat_profile_hint": "Esta es una configuración interna y no afectará la manera en que se muestran los horarios en las páginas de reservas públicas para usted o para cualquier persona que lo solicite.",
"delete_account_modal_title": "Eliminar cuenta",
"confirm_delete_account_modal": "¿Está seguro que desea eliminar su cuenta de {{appName}}?",
"delete_my_account": "Eliminar mi cuenta",
@@ -1169,6 +1171,8 @@
"connect_conference_apps": "Conectar aplicaciones de conferencia",
"connect_calendar_apps": "Conectar aplicaciones de calendario",
"connect_payment_apps": "Conectar aplicaciones de pago",
"connect_automation_apps": "Conecte aplicaciones de automatización",
"connect_analytics_apps": "Conecte aplicaciones de análisis",
"connect_other_apps": "Conectar otras aplicaciones",
"current_step_of_total": "Paso {{currentStep}} de {{maxSteps}}",
"add_variable": "Añadir variable",
@@ -1320,7 +1324,7 @@
"saml_config_updated_successfully": "Configuración de SAML actualizada correctamente",
"saml_configuration": "Configuración SAML",
"delete_saml_configuration": "Eliminar configuración SAML",
"delete_saml_configuration_confirmation_message": "¿Estás seguro de que deseas eliminar la configuración SAML? Los miembros de tu equipo que utilicen el inicio de sesión SAML ya no podrán acceder a {{appName}}.",
"delete_saml_configuration_confirmation_message": "¿Estás seguro de que deseas eliminar la configuración SAML? Los miembros de tu equipo que utilicen el inicio de sesión SAML ya no podrán acceder a Cal.com.",
"confirm_delete_saml_configuration": "Sí, eliminar la configuración SAML",
"saml_not_configured_yet": "SAML no está configurado aún",
"saml_configuration_description": "Pega los metadatos SAML de tu Proveedor de Identidad en el cuadro de texto de abajo para actualizar tu configuración SAML.",
@@ -1363,7 +1367,7 @@
"sender_id": "ID del remitente",
"sender_id_error_message": "Sólo se permiten letras, números y espacios (máx. 11 caracteres)",
"test_routing_form": "Prueba de formulario de ruta",
"test_preview": "Vista previa de la prueba",
"test_preview": "Vista previa de prueba",
"route_to": "Ruta hacia",
"test_preview_description": "Pruebe su formulario de ruta sin enviar ningún dato",
"test_routing": "Prueba de ruta"
@@ -101,7 +101,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é à rejoindre l'équipe {{teamName}}",
"user_invited_you": "{{user}} vous a invité à rejoindre l'équipe {{teamName}}",
"user_invited_you": "{{user}} vous a invité à rejoindre l'équipe {{team}}",
"hidden_team_member_title": "Vous êtes caché dans cette équipe",
"hidden_team_member_message": "Votre place n'est pas payée, passez en version 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 caché jusqu'à ce que vous mettiez à niveau.",
@@ -535,7 +535,7 @@
"open_options": "Ouvrir les options",
"copy_link": "Copier le lien vers l'événement",
"share": "Partager",
"share_event": "Voulez-vous réserver mon {{appName}} ou m'envoyer votre lien ?",
"share_event": "Voulez-vous réserver mon cal ou m'envoyer votre lien ?",
"copy_link_team": "Copier le lien vers l'équipe",
"leave_team": "Quitter l'équipe",
"confirm_leave_team": "Oui, quitter l'équipe",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Afficher les paramètres avancés",
"event_name": "Nom de l'événement",
"event_name_tooltip": "Le nom qui apparaîtra dans les calendriers",
"meeting_with_user": "Rendez-vous avec {ATTENDEE}",
"meeting_with_user": "Rendez-vous avec {{attendeeName}}",
"additional_inputs": "Entrées additionnelles",
"additional_input_description": "Exiger que le planificateur saisisse des entrées supplémentaires avant que la réservation soit confirmée",
"label": "Libellé",
@@ -685,7 +685,7 @@
"cal_provide_zoom_meeting_url": "{{appName}} fournira une URL de réunion Zoom.",
"cal_provide_tandem_meeting_url": "{{appName}} fournira une URL de réunion Tandem.",
"cal_provide_video_meeting_url": "{{appName}} fournira une URL de réunion Daily video.",
"cal_provide_jitsi_meeting_url": "{{appName}} fournira une URL de réunion Jitsi Meet.",
"cal_provide_jitsi_meeting_url": "Cal fournira une URL de réunion Jitsi Meet.",
"cal_provide_huddle01_meeting_url": "{{appName}} fournira une URL de réunion Huddle01 web3 video.",
"cal_provide_teams_meeting_url": "{{appName}} fournira une URL de réunion MS Teams. NOTE : IL FAUT AVOIR UN COMPTE PROFESSIONNEL OU SCOLAIRE",
"require_payment": "Exiger un paiement",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Code d'authentification à deux facteurs incorrect",
"which_event_type_apply": "À quel type d'événement s'appliquera-t-il ?",
"no_workflows_description": "Les workflows permettent une automatisation simple pour envoyer des notifications et des rappels vous permettant de construire des processus autour de vos événements.",
"timeformat_profile_hint": "Ceci est un paramètre interne et n'affectera pas la façon dont les heures sont affichées sur les pages publiques de réservation pour vous ou toute personne qui réserve votre temps.",
"create_workflow": "Créer un workflow",
"do_this": "Effectuer ceci",
"turn_off": "Désactiver",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Erreur lors de la mise à jour des paramètres",
"personal_cal_url": "Mon URL {{appName}} personnelle",
"bio_hint": "Quelques phrases à propos de vous. Ces informations apparaîtront sur votre page d'url personnelle.",
"timeformat_profile_hint": "Ceci est un paramètre interne et n'affectera pas la façon dont les heures sont affichées sur les pages publiques de réservation pour vous ou toute personne qui réserve votre temps.",
"delete_account_modal_title": "Supprimer le compte",
"confirm_delete_account_modal": "Êtes-vous sûr de vouloir supprimer votre compte {{appName}} ?",
"delete_my_account": "Supprimer mon compte",
@@ -1258,6 +1258,7 @@
"back_to_signin": "Retour à la connexion",
"reset_link_sent": "Lien de réinitialisation envoyé",
"password_reset_email": "Un e-mail est transmis vers {{email}} avec les instructions pour réinitialiser votre mot de passe.",
"password_reset_leading": "Si vous ne recevez pas de courriel bientôt, vérifiez que l'adresse e-mail que vous avez saisie est correcte, vérifiez votre dossier spam ou contactez le support si le problème persiste.",
"password_updated": "Mot de passe mis à jour !",
"pending_payment": "Paiement en attente",
"confirmation_page_rainbow": "Le jeton limite l'accès à votre événement en fonction des jetons ou des NFT sur Ethereum, Polygone et plus encore.",
@@ -1323,7 +1324,7 @@
"saml_config_updated_successfully": "Configuration SAML mise à jour",
"saml_configuration": "Configuration SAML",
"delete_saml_configuration": "Supprimer la configuration SAML",
"delete_saml_configuration_confirmation_message": "Êtes-vous sûr de vouloir supprimer la configuration SAML ? Les membres de votre équipe qui utilisent la connexion SAML ne pourront plus accéder à {{appName}}.",
"delete_saml_configuration_confirmation_message": "Êtes-vous sûr de vouloir supprimer la configuration SAML ? Les membres de votre équipe qui utilisent la connexion SAML ne pourront plus accéder à Cal.com.",
"confirm_delete_saml_configuration": "Oui, supprimer la configuration SAML",
"saml_not_configured_yet": "SAML non configuré pour l'instant",
"saml_configuration_description": "Veuillez coller les métadonnées SAML de votre fournisseur d'identité dans la zone de texte ci-dessous pour mettre à jour votre configuration SAML.",
+15 -15
View File
@@ -16,8 +16,8 @@
"event_request_cancelled": "האירוע המתוכנן בוטל",
"organizer": "מארגן",
"need_to_reschedule_or_cancel": "רוצה לקבוע מועד חדש או לבטל?",
"cancellation_reason": "הסיבה לביטול",
"cancellation_reason_placeholder": "מדוע בחרת לבטל? (אופציונלי)",
"cancellation_reason": "הסיבה לביטול (לא חובה)",
"cancellation_reason_placeholder": "מדוע בחרת לבטל? (לא חובה)",
"rejection_reason": "הסיבה לדחייה",
"rejection_reason_title": "לדחות את בקשת ההזמנה?",
"rejection_reason_description": "בטוח שברצונך לדחות את ההזמנה? אנחנו ניידע את האדם שניסה להזמין. יש לך אפשרות להוסיף את הסיבה לדחייה למטה.",
@@ -108,7 +108,7 @@
"link_expires": "נ.ב. תוקף הקישור יפוג תוך {{expiresIn}} שעות.",
"upgrade_to_per_seat": "שדרג למינוי לפי מקום",
"team_upgrade_seats_details": "לא התבצע תשלום עבור {{unpaidCount}} מקומות מתוך {{memberCount}} חברי הצוות שלך. תמורת ${{seatPrice}} לחודש למקום, עלות המינוי הכוללת המשוערת שלך היא ${{totalCost}} לחודש.",
"team_upgrade_banner_description": "אנחנו מודים לך על שניסית את החבילה החדשה שלנו לצוותים. שמנו לב שהצוות שלך, \"{{teamName}}\", זקוק לשדרוג.",
"team_upgrade_banner_description": "אנחנו מודים לך על כך שניסית את החבילה החדשה שלנו לצוותים. שמנו לב שהצוות שלך, \"{{teamName}}\", זקוק לשדרוג.",
"team_upgrade_banner_action": "כאן משדרגים",
"team_upgraded_successfully": "הצוות שלך שודרג בהצלחה!",
"use_link_to_reset_password": "נא להשתמש בקישור הבא כדי לאפס את הסיסמה",
@@ -419,7 +419,7 @@
"forgotten_secret_description": "אם שכחת או איבדת את הסוד, יש לך אפשרות לשנות אותו, אבל חשוב לזכור שיהיה צורך לעדכן את כל השילובים שבהם נעשה שימוש בסוד זה",
"current_incorrect_password": "הסיסמה הנוכחית שגויה",
"password_hint_caplow": "שילוב של אותיות רישיות וקטנות",
"password_hint_min": "באורך של 7 תווים לפחות",
"password_hint_min": "באורך 8 תווים לפחות",
"password_hint_num": "לכלול לפחות ספרה אחת",
"invalid_password_hint": "הסיסמה חייבת להיות באורך של 7 תווים לפחות ולכלול לפחות ספרה אחת ושילוב של אותיות רישיות וקטנות",
"incorrect_password": "הסיסמה שגויה.",
@@ -653,7 +653,7 @@
"show_advanced_settings": "הצגת הגדרות מתקדמות",
"event_name": "שם האירוע",
"event_name_tooltip": "השם שיופיע בלוחות השנה",
"meeting_with_user": "פגישה עם {ATTENDEE}",
"meeting_with_user": "פגישה עם {{attendeeName}}",
"additional_inputs": "אפשרויות קלט נוספות",
"additional_input_description": "לדרוש מכלי התזמון להוסיף פרטים לפני אישור ההזמנה",
"label": "תווית",
@@ -784,7 +784,7 @@
"analytics": "ניתוח נתונים",
"empty_installed_apps_headline": "אין אפליקציות מותקנות",
"empty_installed_apps_description": "אפליקציות מאפשרות לך לשפר משמעותית את תהליכי העבודה שלך ואת תהליך קביעת המועדים.",
"empty_installed_apps_button": "נא לעיין ב-App Store או להתקין מהאפליקציות שלהלן",
"empty_installed_apps_button": "נא לעיין ב-App Store",
"manage_your_connected_apps": "ניהול האפליקציות המותקנות שלך או שינוי הגדרות",
"browse_apps": "עיון באפליקציות",
"features": "תכונות",
@@ -924,7 +924,7 @@
"zapier_setup_instructions": "<0>התחבר/י לחשבון Zapier שלך וצור/י Zap חדש.</0><1>בחר/י את {{appName}} כאפליקציית ה-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",
"connect_caldav_server": "חיבור לשרת CalDav (בטא)",
"calendar_url": "כתובת ה-URL של לוח השנה",
"apple_server_generate_password": "צור סיסמה ספציפית לאפליקציה כדי להשתמש ב-{{appName}} ב:",
"credentials_stored_encrypted": "פרטי הכניסה שלך יישמרו ויוצפנו.",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "קוד שגוי של אימות בשני גורמים",
"which_event_type_apply": "על איזה סוג אירוע זה יחול?",
"no_workflows_description": "תהליכי עבודה מאפשרים שימוש באוטומציה פשוטה לשליחת עדכונים ותזכורות, כך שאת/ה יכול/ה לתכנן תהליכים שקשורים לאירועים שלך.",
"timeformat_profile_hint": "זוהי הגדרה פנימית שלא תשפיע על אופן התצוגה של תאריכים ושעות בדפים של הזמנות ציבוריות עבורך או עבור מי שמבצע הזמנות בשמך.",
"create_workflow": "יצירת תהליך עבודה",
"do_this": "יש לבצע את הפעולה הזו",
"turn_off": "השבתה",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "שגיאה במהלך עדכון ההגדרות",
"personal_cal_url": "כתובת ה-URL של ה-{{appName}} האישי שלי",
"bio_hint": "מספר משפטים אודותיך. המידע הזה יופיע בדף ה-URL האישי שלך.",
"timeformat_profile_hint": "זוהי הגדרה פנימית שלא תשפיע על אופן התצוגה של תאריכים ושעות בדפים של הזמנות ציבוריות עבורך או עבור מי שמבצע הזמנות בשמך.",
"delete_account_modal_title": "מחיקת חשבון",
"confirm_delete_account_modal": "בטוח שברצונך למחוק את חשבון {{appName}} שלך?",
"delete_my_account": "מחיקת החשבון שלי",
@@ -1229,7 +1229,7 @@
"exchange_compression": "דחיסת GZip",
"routing_forms_description": "כאן ניתן לצפות בכל הטפסים והנתיבים שיצרת.",
"routing_forms_send_email_owner": "שליחת דוא\"ל לבעלים",
"routing_forms_send_email_owner_description": "שליחת דוא\"ל לבעלים כשהטופס נשלח",
"routing_forms_send_email_owner_description": "דוא\"ל נשלח לבעלים לאחר שליחת הטופס",
"add_new_form": "הוספת טופס חדש",
"form_description": "צור/י טופס משלך כדי לנתב אל מזמין/ה",
"copy_link_to_form": "להעתיק את הקישור לטופס",
@@ -1324,7 +1324,7 @@
"saml_config_updated_successfully": "תצורת SAML עודכנה בהצלחה",
"saml_configuration": "תצורת SAML",
"delete_saml_configuration": "מחיקת תצורת SAML",
"delete_saml_configuration_confirmation_message": "בטוח שברצונך למחוק את תצורת SAML? חברי הצוות שלך שנכנסים אמצעות SAML לא יוכלו יותר לגשת ל-{{appName}}.",
"delete_saml_configuration_confirmation_message": "בטוח שברצונך למחוק את תצורת SAML? חברי הצוות שלך שנכנסים אמצעות SAML לא יוכלו יותר לגשת ל-Cal.com.",
"confirm_delete_saml_configuration": "כן, אני רוצה למחוק את תצורת SAML",
"saml_not_configured_yet": "SAML עדיין לא הוגדר",
"saml_configuration_description": "יש להדביק את המטא-נתונים של SAML מספק הזהויות בתיבת הטקסט הבאה כדי לעדכן את תצורת SAML.",
@@ -1341,11 +1341,11 @@
"limit_future_bookings": "הגבלת הזמנות עתידיות",
"limit_future_bookings_description": "הגבלת התאריך הרחוק ביותר בעתיד שעד אליו ניתן להזמין את האירוע הזה",
"no_event_types": "לא הוגדר אף סוג אירוע",
"no_event_types_description": "{{name}} לא הגדיר/ה אף סוג אירוע שבאפשרותך להזמין.",
"no_event_types_description": "לא הוגדר על ידי {{name}} אף סוג אירוע שבאפשרותך להזמין.",
"billing_frequency": "תדירות חיוב",
"monthly": "אחת לחודש",
"yearly": "אחת לשנה",
"checkout": "קופה",
"checkout": "תשלום",
"your_team_disbanded_successfully": "פיזור הצוות שלך בוצע בהצלחה",
"error_creating_team": "אירעה שגיאה במהלך יצירת הצוות",
"you": "את/ה",
@@ -1364,11 +1364,11 @@
"choose_common_schedule_team_event": "בחירת לוח זמנים משותף",
"choose_common_schedule_team_event_description": "יש להפעיל אפשרות זו אם רוצים להשתמש בלוח זמנים משותף בין המארחים. אם האפשרות הזו מבוטלת, כל מארח יוזמן לפי לוח הזמנים המשמש כברירת המחדל שלו.",
"reason": "סיבה",
"sender_id": "מזהה שולח/ת",
"sender_id": "מזהה השולח/ת",
"sender_id_error_message": "מותר להשתמש רק באותיות, במספרים וברווחים (לכל היותר 11 תווים)",
"test_routing_form": "בדיקת טופס ניתוב",
"test_preview": "תצוגה מקדימה של הבדיקה",
"test_preview": "בדיקת התצוגה המקדימה",
"route_to": "ניתוב אל",
"test_preview_description": "בדיקת טופס הניתוב שלך בלי לשלוח נתונים",
"test_preview_description": "לבדוק את טופס הניתוב שלך בלי לשלוח נתונים",
"test_routing": "בדיקת ניתוב"
}
@@ -653,7 +653,7 @@
"show_advanced_settings": "Mostra impostazioni avanzate",
"event_name": "Nome Dell'Evento",
"event_name_tooltip": "Il nome che apparirà nei calendari",
"meeting_with_user": "Riunione con {ATTENDEE}",
"meeting_with_user": "Riunione con {{attendeeName}}",
"additional_inputs": "Input Aggiuntivi",
"additional_input_description": "Chiedi al creatore del programma di inserire dei campi di input aggiuntivi prima che la prenotazione sia confermata",
"label": "Etichetta",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Codice di autenticazione a due fattori errato",
"which_event_type_apply": "A quale tipo di evento si applicherà?",
"no_workflows_description": "I flussi di lavoro attivano una semplice automazione per inviare notifiche e promemoria che ti consentono di creare processi per i tuoi eventi.",
"timeformat_profile_hint": "Questa è un'impostazione interna e non influenzerà il modo in cui gli orari sono visualizzati nelle pagine di prenotazione pubbliche a te e a chiunque faccia una prenotazione.",
"create_workflow": "Crea un flusso di lavoro",
"do_this": "Esegui questa operazione",
"turn_off": "Disattiva",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Errore durante l'aggiornamento delle impostazioni",
"personal_cal_url": "Il mio URL personale di {{appName}}",
"bio_hint": "Scrivi qualcosa di te. Queste informazioni appariranno nella tua pagina personale.",
"timeformat_profile_hint": "Questa è un'impostazione interna e non influenzerà il modo in cui gli orari sono visualizzati nelle pagine di prenotazione pubbliche a te e a chiunque faccia una prenotazione.",
"delete_account_modal_title": "Elimina account",
"confirm_delete_account_modal": "Eliminare il tuo account {{appName}}?",
"delete_my_account": "Elimina il mio account",
@@ -1258,6 +1258,7 @@
"back_to_signin": "Torna alla pagina di accesso",
"reset_link_sent": "Link per la reimpostazione inviato",
"password_reset_email": "Un'e-mail con le istruzioni per reimpostare la password è stata inviata all'indirizzo {{email}}.",
"password_reset_leading": "Se un'e-mail non ti dovesse arrivare a breve, assicurati che l'indirizzo specificato sia corretto e controlla la cartella della posta indesiderata. Se il problema persiste, contatta l'assistenza clienti.",
"password_updated": "Password aggiornata!",
"pending_payment": "Pagamento in sospeso",
"confirmation_page_rainbow": "Proteggi i tuoi eventi con token o NFT su Ethereum, Polygon e altri.",
@@ -1323,7 +1324,7 @@
"saml_config_updated_successfully": "Configurazione SAML aggiornata correttamente",
"saml_configuration": "Configurazione SAML",
"delete_saml_configuration": "Elimina configurazione SAML",
"delete_saml_configuration_confirmation_message": "Sei sicuro di voler eliminare la configurazione SAML? I membri del tuo team che utilizzano l'accesso SAML non saranno più in grado di accedere a {{appName}}.",
"delete_saml_configuration_confirmation_message": "Sei sicuro di voler eliminare la configurazione SAML? I membri del tuo team che utilizzano l'accesso SAML non saranno più in grado di accedere a Cal.com.",
"confirm_delete_saml_configuration": "Sì, elimina configurazione SAML",
"saml_not_configured_yet": "SAML non ancora configurato",
"saml_configuration_description": "Per aggiornare la configurazione SAML, incolla nella casella sottostante i metadati SAML forniti dal tuo provider di identità.",
@@ -235,7 +235,7 @@
"welcome": "ようこそ",
"welcome_back": "おかえりなさい",
"welcome_to_calcom": "{{appName}} へようこそ",
"welcome_instructions": "{{appName}} でご使用になるお名前とタイムゾーンを教えてください。これらは後から編集できます。",
"welcome_instructions": "Cal.com でご使用になるお名前とタイムゾーンを教えてください。これらは後から編集できます。",
"connect_caldav": "CalDav (ベータ版) に接続",
"credentials_stored_and_encrypted": "認証情報は保存され暗号化されます。",
"connect": "接続",
@@ -653,7 +653,7 @@
"show_advanced_settings": "詳細設定を表示",
"event_name": "イベント名",
"event_name_tooltip": "カレンダーに表示される名前",
"meeting_with_user": "{ATTENDEE} とのミーティング",
"meeting_with_user": "{{attendeeName}} とのミーティング",
"additional_inputs": "追加入力",
"additional_input_description": "予約確認前にスケジュール設定者の追加入力が必要です",
"label": "ラベル",
@@ -685,7 +685,7 @@
"cal_provide_zoom_meeting_url": "{{appName}} は Zoom ミーティングの URLを提供する。",
"cal_provide_tandem_meeting_url": "{{appName}} は Tandem ミーティングの URL を提供する。",
"cal_provide_video_meeting_url": "{{appName}} はビデオミーティングの URL を提供する。",
"cal_provide_jitsi_meeting_url": "{{appName}} は Jitsi Meet の URL を提供する。",
"cal_provide_jitsi_meeting_url": "Cal は Jitsi Meet の URL を提供する。",
"cal_provide_huddle01_meeting_url": "{{appName}} は Huddle01 web3 ビデオミーティングの URL を提供する。",
"cal_provide_teams_meeting_url": "{{appName}} は、MS Teams のミーティングの URL を提供する。注: 職場や学校のアカウントが必要です。",
"require_payment": "有料",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "不正な二要素認証コード",
"which_event_type_apply": "これはどのイベントタイプに適用されますか?",
"no_workflows_description": "ワークフローを使用すると通知やリマインダーの送信を簡単に自動化することができ、イベントに関するプロセスを構築することができます。",
"timeformat_profile_hint": "これは内部設定であり、あなたやあなたを予約した人の公開予約ページの時間表示には影響しません。",
"create_workflow": "ワークフローを作成",
"do_this": "これを実行する",
"turn_off": "オフにする",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "設定の更新中にエラーが発生しました",
"personal_cal_url": "私の個人 {{appName}} URL",
"bio_hint": "あなたに関する簡潔な説明。これはあなたの個人 URL ページに表示されます。",
"timeformat_profile_hint": "これは内部設定であり、あなたやあなたを予約した人の公開予約ページの時間表示には影響しません。",
"delete_account_modal_title": "アカウントを削除する",
"confirm_delete_account_modal": "{{appName}} アカウントを削除してもよろしいですか?",
"delete_my_account": "アカウントを削除する",
@@ -1324,7 +1324,7 @@
"saml_config_updated_successfully": "SAML の構成が正常に更新されました",
"saml_configuration": "SAML の構成",
"delete_saml_configuration": "SAML の構成を削除する",
"delete_saml_configuration_confirmation_message": "SAML の構成を本当に削除してよろしいですか?SAML を使用してログインしているチームメンバーは、{{appName}} にアクセスすることができなくなります。",
"delete_saml_configuration_confirmation_message": "SAML の構成を本当に削除してよろしいですか?SAML を使用してログインしているチームメンバーは、Cal.com にアクセスすることができなくなります。",
"confirm_delete_saml_configuration": "はい。SAML の構成を削除します",
"saml_not_configured_yet": "SAML がまだ構成されていません",
"saml_configuration_description": "SAML の構成を更新するには、以下のテキストボックスに ID プロバイダーから提供されている SAML のメタデータを貼り付けてください。",
@@ -535,7 +535,7 @@
"open_options": "옵션 열기",
"copy_link": "이벤트 링크 복사",
"share": "공유",
"share_event": "내 {{appName}}을 예약하거나 링크를 보내 주시겠습니까?",
"share_event": "내 Cal을 예약하거나 링크를 보내 주시겠습니까?",
"copy_link_team": "팀에 링크 복사",
"leave_team": "팀 떠나기",
"confirm_leave_team": "예, 팀을 떠납니다",
@@ -653,7 +653,7 @@
"show_advanced_settings": "고급 설정 표시",
"event_name": "이벤트 이름",
"event_name_tooltip": "캘린더에 표시될 이름",
"meeting_with_user": "{ATTENDEE} 님과의 회의",
"meeting_with_user": "{{attendeeName}} 님과의 회의",
"additional_inputs": "추가 입력",
"additional_input_description": "예약이 확정되기 전 스케줄러가 추가 입력을 해야 합니다",
"label": "레이블",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "잘못된 2단계 인증 코드",
"which_event_type_apply": "이것은 어떤 이벤트 유형에 적용될까요?",
"no_workflows_description": "워크플로를 사용하면 이벤트와 관련된 프로세스를 구축할 수 있도록 알림 및 미리 알림을 보내는 간단한 자동화가 가능합니다.",
"timeformat_profile_hint": "이것은 내부 설정이며 귀하 또는 귀하를 예약하는 모든 사람의 공개 예약 페이지에 시간이 표시되는 방식에는 영향을 미치지 않습니다.",
"create_workflow": "워크플로를 만듭니다",
"do_this": "이렇게 하세요",
"turn_off": "끄기",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "설정 업데이트 중 오류 발생",
"personal_cal_url": "내 개인 {{appName}} URL",
"bio_hint": "자신에 대해 몇 마디를 써보세요. 개인 URL 페이지에 보이는 내용입니다.",
"timeformat_profile_hint": "이것은 내부 설정이며 귀하 또는 귀하를 예약하는 모든 사람의 공개 예약 페이지에 시간이 표시되는 방식에는 영향을 미치지 않습니다.",
"delete_account_modal_title": "계정 삭제",
"confirm_delete_account_modal": "{{appName}} 계정을 삭제하시겠습니까?",
"delete_my_account": "내 계정 삭제",
@@ -1188,7 +1188,6 @@
"additional_notes_info": "예약 추가 메모",
"attendee_name_info": "예약자 이름",
"to": "대상",
"attendee_required_enter_number": "예약 시 참석자가 전화번호를 입력해야 합니다",
"workflow_turned_on_successfully": "{{workflowName}} 워크플로 {{offOn}} 설정 완료",
"download_responses": "다운로드 응답",
"create_your_first_form": "첫 양식 작성",
@@ -1198,7 +1197,7 @@
"for_a_maximum_of": "최대",
"event_one": "이벤트",
"event_other": "이벤트",
"profile_team_description": "사용자 팀 프로필 설정 관리",
"profile_team_description": "팀 프로필 설정 관리",
"members_team_description": "그룹 내 사용자",
"team_url": "팀 URL",
"team_members": "팀원",
@@ -535,7 +535,7 @@
"open_options": "Opties openen",
"copy_link": "Link naar afspraak kopiëren",
"share": "Delen",
"share_event": "Zou u mijn {{appName}} willen boeken of mij uw link willen sturen?",
"share_event": "Zou u mijn Cal willen boeken of mij uw link willen sturen?",
"copy_link_team": "Link naar team kopiëren",
"leave_team": "Team verlaten",
"confirm_leave_team": "Ja, team verlaten",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Toon geavanceerde instellingen",
"event_name": "Naam van evenement",
"event_name_tooltip": "De naam die in kalenders wordt weergegeven",
"meeting_with_user": "Afspraak met {ATTENDEE}",
"meeting_with_user": "Afspraak met {{attendeeName}}",
"additional_inputs": "Extra invoer",
"additional_input_description": "Planner vereist om extra gegevens in te voeren voordat de boeking wordt bevestigd",
"label": "Omschrijving",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Onjuiste tweestapsverificatiecode",
"which_event_type_apply": "Op welk type gebeurtenis is dit van toepassing?",
"no_workflows_description": "Werkstromen maken eenvoudige automatisering van het versturen van meldingen en herinneringen mogelijk, zodat u processen rond uw gebeurtenissen kunt opbouwen.",
"timeformat_profile_hint": "Dit is een interne instelling en heeft geen invloed op hoe de tijden worden weergegeven op de openbare boekingspagina's voor u of voor iemand die u boekt.",
"create_workflow": "Maak een werkstroom",
"do_this": "Doe dit",
"turn_off": "Uitschakelen",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Fout bij het bijwerken van de instellingen",
"personal_cal_url": "Mijn persoonlijke {{appName}}-URL",
"bio_hint": "Een korte introductie over uzelf. Dit wordt weergegeven op uw persoonlijke pagina.",
"timeformat_profile_hint": "Dit is een interne instelling en heeft geen invloed op hoe de tijden worden weergegeven op de openbare boekingspagina's voor u of voor iemand die u boekt.",
"delete_account_modal_title": "Account verwijderen",
"confirm_delete_account_modal": "Weet u zeker dat u uw {{appName}}-account wilt verwijderen?",
"delete_my_account": "Verwijder mijn account",
@@ -1258,6 +1258,7 @@
"back_to_signin": "Terug naar aanmelden",
"reset_link_sent": "Link om opnieuw in te stellen is verzonden",
"password_reset_email": "Een e-mail is onderweg naar {{email}} met instructies om uw wachtwoord opnieuw in te stellen.",
"password_reset_leading": "Als u niet spoedig een e-mail ontvangt, controleer dan of het ingevoerde e-mailadres correct is, controleer uw spamfolder of neem contact op met de ondersteuning als het probleem zich blijft voordoen.",
"password_updated": "Wachtwoord bijgewerkt!",
"pending_payment": "In afwachting van betaling",
"confirmation_page_rainbow": "Scherm uw gebeurtenis af met tokens of NFT's op Ethereum, Polygon en meer.",
@@ -1323,7 +1324,7 @@
"saml_config_updated_successfully": "SAML-configuratie bijgewerkt",
"saml_configuration": "SAML-configuratie",
"delete_saml_configuration": "SAML-configuratie verwijderen",
"delete_saml_configuration_confirmation_message": "Weet u zeker dat u de SAML-configuratie wilt verwijderen? Uw teamleden die SAML-aanmelding gebruiken hebben niet langer toegang tot {{appName}}.",
"delete_saml_configuration_confirmation_message": "Weet u zeker dat u de SAML-configuratie wilt verwijderen? Uw teamleden die SAML-aanmelding gebruiken hebben niet langer toegang tot Cal.com.",
"confirm_delete_saml_configuration": "Ja, SAML-configuratie verwijderen",
"saml_not_configured_yet": "SAML nog niet geconfigureerd",
"saml_configuration_description": "Plak de SAML-metagegevens van uw identiteitsprovider in het tekstvak hieronder om uw SAML-configuratie bij te werken.",
+55 -46
View File
@@ -6,9 +6,9 @@
"second_other": "{{count}} sekunder",
"upgrade_now": "Oppgrader nå",
"accept_invitation": "Aksepter invitasjon",
"calcom_explained": "Cal.com er en åpen kildekodeversjon av Calendly som gir deg kontroll over dine egne data, arbeidsflyt og utseende.",
"calcom_explained": "{{appName}} er en åpen kildekodeversjon av Calendly som gir deg kontroll over dine egne data, arbeidsflyt og utseende.",
"have_any_questions": "Har du spørsmål? Vi er her for å hjelpe.",
"reset_password_subject": "Cal.com: Instruksjoner for tilbakestilling av passord",
"reset_password_subject": "{{appName}}: Instruksjoner for tilbakestilling av passord",
"event_declined_subject": "Avslått: {{eventType}} med {{name}} kl. {{date}}",
"event_cancelled_subject": "Avbrutt: {{eventType}} med {{name}} kl. {{date}}",
"event_request_declined": "Din hendelsesforespørsel har blitt avvist",
@@ -52,6 +52,7 @@
"still_waiting_for_approval": "En hendelse venter fremdeles på godkjenning",
"event_is_still_waiting": "Hendelsesforespørsel venter fortsatt: {{attendeeName}} - {{date}} - {{eventType}}",
"no_more_results": "Ingen flere resultater",
"no_results": "Ingen resultater",
"load_more_results": "Last inn flere resultater",
"integration_meeting_id": "{{integrationName}} møte-ID: {{meetingId}}",
"confirmed_event_type_subject": "Bekreftet: {{eventType}} med {{name}} kl. {{date}}",
@@ -99,9 +100,9 @@
"join_team": "Bli med i teamet",
"manage_this_team": "Administrer dette teamet",
"team_info": "Team Info",
"request_another_invitation_email": "Hvis du foretrekker å ikke bruke {{toEmail}} som Cal.com-e-post eller allerede har en Cal.com-konto, vennligst be om en annen invitasjon til denne e-posten.",
"request_another_invitation_email": "Hvis du foretrekker å ikke bruke {{toEmail}} som {{appName}}-e-post eller allerede har en {{appName}}-konto, vennligst be om en annen invitasjon til denne e-posten.",
"you_have_been_invited": "Du har blitt invitert til å bli med i teamet {{teamName}}",
"user_invited_you": "{{user}} inviterte deg til å bli med i teamet {{team}} på Cal.com",
"user_invited_you": "{{user}} inviterte deg til å bli med i teamet {{team}} på {{appName}}",
"hidden_team_member_title": "Du er skjult i dette teamet",
"hidden_team_member_message": "Setet ditt er ikke betalt for, enten oppgrader til PRO eller la teameieren få vite at de kan betale for setet ditt.",
"hidden_team_owner_message": "Du trenger en pro-konto for å bruke team, du er skjult inntil du oppgraderer.",
@@ -113,8 +114,8 @@
"team_upgraded_successfully": "Teamet ditt ble oppgradert!",
"use_link_to_reset_password": "Bruk lenken nedenfor for å tilbakestille passordet ditt",
"hey_there": "Hei der,",
"forgot_your_password_calcom": "Glemt passordet? - Cal.com",
"delete_webhook_confirmation_message": "Er du sikker på at du vil slette denne webhooken? Du vil ikke lenger motta Cal.com møtedata på en spesifisert URL, i sanntid, når en hendelse er planlagt eller avlyst.",
"forgot_your_password_calcom": "Glemt passordet? - {{appName}}",
"delete_webhook_confirmation_message": "Er du sikker på at du vil slette denne webhooken? Du vil ikke lenger motta {{appName}} møtedata på en spesifisert URL, i sanntid, når en hendelse er planlagt eller avlyst.",
"confirm_delete_webhook": "Ja, slett webhook",
"edit_webhook": "Rediger Webhook",
"delete_webhook": "Slett Webhook",
@@ -190,7 +191,7 @@
"30min_meeting": "30 Min Møte",
"secret": "Hemmelighet",
"leave_blank_to_remove_secret": "La stå tomt for å fjerne hemmeligheten",
"webhook_secret_key_description": "Sørg for at serveren din kun mottar de forventede Cal.com-forespørslene av sikkerhetsgrunner",
"webhook_secret_key_description": "Sørg for at serveren din kun mottar de forventede {{appName}}-forespørslene av sikkerhetsgrunner",
"secret_meeting": "Hemmelig Møte",
"login_instead": "Logg på i stedet",
"already_have_an_account": "Har du allerede en bruker?",
@@ -234,13 +235,13 @@
"details": "Detaljer",
"welcome": "Velkommen",
"welcome_back": "Velkommen tilbake",
"welcome_to_calcom": "Velkommen til Cal.com",
"welcome_to_calcom": "Velkommen til {{appName}}",
"welcome_instructions": "Fortell oss hva vi skal kalle deg og gi oss beskjed om hvilken tidssone du er i. Du kan redigere dette senere.",
"connect_caldav": "Koble til CalDav (Beta)",
"credentials_stored_and_encrypted": "Din legitimasjon vil bli lagret og kryptert.",
"connect": "Tilkoble",
"try_for_free": "Prøv det gratis",
"create_booking_link_with_calcom": "Lag din egen booking lenke med Cal.com",
"create_booking_link_with_calcom": "Lag din egen booking lenke med {{appName}}",
"who": "Hvem",
"what": "Hva",
"when": "Når",
@@ -248,6 +249,7 @@
"add_to_calendar": "Legg til i kalender",
"add_another_calendar": "Legg til en annen kalender",
"other": "Annet",
"email_sign_in_subject": "Påloggings-lenken din for {{appName}}",
"emailed_you_and_attendees": "Vi sendte deg og de andre deltakerne en kalenderinvitasjon med alle detaljene.",
"emailed_you_and_attendees_recurring": "Vi sendte deg og de andre deltakerne en kalenderinvitasjon på e-post for den første av disse gjentakende hendelsene.",
"emailed_you_and_any_other_attendees": "Du og eventuelle andre deltakere har fått e-post med denne informasjonen.",
@@ -346,7 +348,7 @@
"dark": "Mørkt",
"automatically_adjust_theme": "Juster tema automatisk basert på den invitertes innstillinger",
"user_dynamic_booking_disabled": "Noen av brukerne i gruppen har for øyeblikket deaktivert dynamiske gruppebookinger",
"allow_dynamic_booking_tooltip": "Gruppebooking-lenker som kan opprettes dynamisk ved å legge til flere brukernavn med en '+'. eksempel: 'cal.com/bailey+peer'",
"allow_dynamic_booking_tooltip": "Gruppebooking-lenker som kan opprettes dynamisk ved å legge til flere brukernavn med en '+'. eksempel: '{{appName}}/bailey+peer'",
"allow_dynamic_booking": "Tillat deltakere å booke deg gjennom dynamiske gruppebookinger",
"email": "E-post",
"email_placeholder": "ola.nordman@eksempel.no",
@@ -366,8 +368,8 @@
"team_webhooks": "Team Webhooker",
"create_new_webhook_to_account": "Opprett en ny webhook til kontoen din",
"new_webhook": "Ny Webhook",
"receive_cal_meeting_data": "Motta Cal-møtedata på en spesifisert URL, i sanntid, når en hendelse er planlagt eller kansellert.",
"receive_cal_event_meeting_data": "Motta Cal-møtedata på en spesifisert URL, i sanntid, når denne hendelsen er planlagt eller kansellert.",
"receive_cal_meeting_data": "Motta {{appName}}-møtedata på en spesifisert URL, i sanntid, når en hendelse er planlagt eller kansellert.",
"receive_cal_event_meeting_data": "Motta {{appName}}-møtedata på en spesifisert URL, i sanntid, når denne hendelsen er planlagt eller kansellert.",
"responsive_fullscreen_iframe": "Responsiv fullskjerms iFrame",
"loading": "Laster inn...",
"deleting": "Sletter...",
@@ -375,7 +377,7 @@
"developer": "Utvikler",
"manage_developer_settings": "Administrer utviklerinnstillingene dine.",
"iframe_embed": "iframe Bygg inn",
"embed_calcom": "Den enkleste måten å bygge inn Cal.com på nettstedet ditt.",
"embed_calcom": "Den enkleste måten å bygge inn {{appName}} på nettstedet ditt.",
"integrate_using_embed_or_webhooks": "Integrer med nettstedet ditt ved å bruke våre innebyggings-alternativer, eller få bookinginformasjon i sanntid ved å bruke egendefinerte webhooks.",
"schedule_a_meeting": "Planlegg et møte",
"view_and_manage_billing_details": "Se og administrer betalingsdetaljene dine",
@@ -511,8 +513,8 @@
"invite_new_member_description": "Merk: Dette vil <1>koste et ekstra sete ($15/m)</1> på abonnementet ditt.",
"invite_new_team_member": "Inviter noen til teamet ditt.",
"change_member_role": "Endre team-medlems-rolle",
"disable_cal_branding": "Deaktiver Cal merkeprofilering",
"disable_cal_branding_description": "Skjul all Cal.com-merkevareprofilering fra de offentlige sidene dine.",
"disable_cal_branding": "Deaktiver {{appName}} merkeprofilering",
"disable_cal_branding_description": "Skjul all {{appName}}-merkevareprofilering fra de offentlige sidene dine.",
"danger_zone": "Faresone",
"back": "Tilbake",
"cancel": "Avbryt",
@@ -632,7 +634,7 @@
"changed_team_billing_info": "Fra januar 2022 tar vi betalt per sete for teammedlemmer. Medlemmer av teamet ditt som hadde PRO gratis, har nå en 14 dagers prøveversjon. Når prøveperioden deres utløper, vil disse medlemmene bli skjult for teamet ditt med mindre du oppgraderer nå.",
"create_manage_teams_collaborative": "Opprett og administrer team for å bruke samarbeidsfunksjoner.",
"only_available_on_pro_plan": "Denne funksjonen er bare tilgjengelig i Pro-planen",
"remove_cal_branding_description": "For å fjerne Cal-merket fra bookingsidene dine, må du oppgradere til en Pro-konto.",
"remove_cal_branding_description": "For å fjerne {{appName}}-merket fra bookingsidene dine, må du oppgradere til en Pro-konto.",
"edit_profile_info_description": "Rediger profilinformasjonen din, som viser på planleggingslenken.",
"change_email_tip": "Du må kanskje logge ut og inn igjen for å se endringen tre i kraft.",
"little_something_about": "Litt om deg selv.",
@@ -681,21 +683,21 @@
"private_link_label": "Privat lenke",
"private_link_hint": "Din private lenke vil regenereres etter hver bruk",
"copy_private_link": "Kopier privat lenke",
"private_link_description": "Generer en privat URL for å dele uten å avsløre Cal-brukernavnet ditt",
"private_link_description": "Generer en privat URL for å dele uten å avsløre {{appName}}-brukernavnet ditt",
"invitees_can_schedule": "Inviterte kan velge tidspunkt",
"date_range": "Datointervall",
"calendar_days": "kalenderdager",
"business_days": "virkedager",
"set_address_place": "Angi en adresse eller sted",
"set_link_meeting": "Angi en lenke til møtet",
"cal_invitee_phone_number_scheduling": "Cal vil be den inviterte om å skrive inn et telefonnummer før valg av tidspunkt.",
"cal_provide_google_meet_location": "Cal vil oppgi en Google Meet-lokasjon.",
"cal_provide_zoom_meeting_url": "Cal vil angi en URL-adresse for Zoom-møte.",
"cal_provide_tandem_meeting_url": "Cal vil angi en URL for Tandem-møtet.",
"cal_provide_video_meeting_url": "Cal vil angi en videomøte-URL.",
"cal_invitee_phone_number_scheduling": "{{appName}} vil be den inviterte om å skrive inn et telefonnummer før valg av tidspunkt.",
"cal_provide_google_meet_location": "{{appName}} vil oppgi en Google Meet-lokasjon.",
"cal_provide_zoom_meeting_url": "{{appName}} vil angi en URL-adresse for Zoom-møte.",
"cal_provide_tandem_meeting_url": "{{appName}} vil angi en URL for Tandem-møtet.",
"cal_provide_video_meeting_url": "{{appName}} vil angi en videomøte-URL.",
"cal_provide_jitsi_meeting_url": "Vi vil generere en Jitsi Meet URL for deg.",
"cal_provide_huddle01_meeting_url": "Cal vil angi en Huddle01 web3 videomøte-URL.",
"cal_provide_teams_meeting_url": "Cal vil angi en URL for MS Teams møte. MERK: MÅ HA EN ARBEIDS- ELLER SKOLEKONTO",
"cal_provide_huddle01_meeting_url": "{{appName}} vil angi en Huddle01 web3 videomøte-URL.",
"cal_provide_teams_meeting_url": "{{appName}} vil angi en URL for MS Teams møte. MERK: MÅ HA EN ARBEIDS- ELLER SKOLEKONTO",
"require_payment": "Krev Betaling",
"commission_per_transaction": "provisjon per transaksjon",
"event_type_updated_successfully_description": "Din hendelsestype har blitt oppdatert.",
@@ -718,7 +720,7 @@
"confirm_delete_event_type": "Ja, slett hendelsestype",
"delete_account": "Slett konto",
"confirm_delete_account": "Ja, slett konto",
"delete_account_confirmation_message": "Er du sikker på at du vil slette Cal.com-kontoen din? Alle du har delt konto-lenken med, vil ikke lenger kunne booke ved å bruke den, og eventuelle innstillinger du har lagret vil gå tapt.",
"delete_account_confirmation_message": "Er du sikker på at du vil slette {{appName}}-kontoen din? Alle du har delt konto-lenken med, vil ikke lenger kunne booke ved å bruke den, og eventuelle innstillinger du har lagret vil gå tapt.",
"integrations": "Integrasjoner",
"apps": "Apper",
"category_apps": "{{category}} apper",
@@ -776,6 +778,7 @@
"trending_apps": "Populære Apper",
"explore_apps": "{{category}} apper",
"installed_apps": "Installerte Apper",
"free_to_use_apps": "Gratis",
"no_category_apps": "Ingen {{category}} apper",
"no_category_apps_description_calendar": "Legg til en kalenderapp for å se etter konflikter for å forhindre dobbelt-bookinger",
"no_category_apps_description_conferencing": "Prøv å legge til en konferanseapp for å integrere videosamtaler med klientene dine",
@@ -814,9 +817,11 @@
"verify_wallet": "Verifiser Lommebok",
"connect_metamask": "Koble til Metamask",
"create_events_on": "Opprett hendelser på",
"enterprise_license": "Dette er en bedriftsfunksjon",
"enterprise_license_description": "For å aktivere denne funksjonen, skaff deg en distribusjonsnøkkel på {{consoleUrl}}-konsollen og legg den til i .env som CALCOM_LICENSE_KEY. Hvis teamet ditt allerede har en lisens, vennligst kontakt {{supportMail}} for å få hjelp.",
"missing_license": "Mangler Lisens",
"signup_requires": "Kommersiell lisens kreves",
"signup_requires_description": "Cal.com, Inc. tilbyr for øyeblikket ikke en gratis åpen kildekode-versjon av registreringssiden. For å få full tilgang til registreringskomponentene må du anskaffe en kommersiell lisens. For personlig bruk anbefaler vi Prisma Data Platform eller et annet Postgres-grensesnitt for å opprette kontoer.",
"signup_requires_description": "{{companyName}} tilbyr for øyeblikket ikke en gratis åpen kildekode-versjon av registreringssiden. For å få full tilgang til registreringskomponentene må du anskaffe en kommersiell lisens. For personlig bruk anbefaler vi Prisma Data Platform eller et annet Postgres-grensesnitt for å opprette kontoer.",
"next_steps": "Neste Skritt",
"acquire_commercial_license": "Skaff en kommersiell lisens",
"the_infrastructure_plan": "Infrastruktur-planen er bruksbasert og har oppstartsvennlige rabatter.",
@@ -919,23 +924,23 @@
"update_location": "Oppdater Sted",
"location_updated": "Sted oppdatert",
"email_validation_error": "Det ser ikke ut som en e-postadresse",
"place_where_cal_widget_appear": "Plasser denne koden i din HTML der du vil at Cal-widgeten skal vises.",
"place_where_cal_widget_appear": "Plasser denne koden i din HTML der du vil at {{appName}}-widgeten skal vises.",
"create_update_react_component": "Opprett eller oppdater en eksisterende React-komponent som vist nedenfor.",
"copy_code": "Kopier Kode",
"code_copied": "Kode kopiert!",
"how_you_want_add_cal_site": "Hvordan vil du legge til Cal på nettstedet ditt?",
"choose_ways_put_cal_site": "Velg en av følgende måter å plassere Cal på nettstedet ditt.",
"how_you_want_add_cal_site": "Hvordan vil du legge til {{appName}} på nettstedet ditt?",
"choose_ways_put_cal_site": "Velg en av følgende måter å plassere {{appName}} på nettstedet ditt.",
"setting_up_zapier": "Sette opp din Zapier-integrasjon",
"generate_api_key": "Generer API nøkkel",
"generate_api_key_description": "Generer en API nøkkel til bruk med Cal.com på",
"generate_api_key_description": "Generer en API nøkkel til bruk med {{appName}} på",
"your_unique_api_key": "Din unike API nøkkel",
"copy_safe_api_key": "Kopier denne API nøkkelen og lagre den et trygt sted. Hvis du mister denne nøkkelen, må du generere en ny.",
"zapier_setup_instructions": "<0>Logg på Zapier-kontoen din og opprett en ny Zap.</0><1>Velg Cal.com som din Trigger-app. Velg også en utløserhendelse.</1><2>Velg kontoen din og skriv deretter inn din unike API nøkkel.</2><3>Test utløseren.</3><4>Du er klar!</4 >",
"zapier_setup_instructions": "<0>Logg på Zapier-kontoen din og opprett en ny Zap.</0><1>Velg {{appName}} som din Trigger-app. Velg også en utløserhendelse.</1><2>Velg kontoen din og skriv deretter inn din unike API nøkkel.</2><3>Test utløseren.</3><4>Du er klar!</4 >",
"install_zapier_app": "Installer først Zapier-appen i app butikken.",
"connect_apple_server": "Koble til Apple Server",
"connect_caldav_server": "Koble til CalDav (Beta)",
"calendar_url": "Kalender URL",
"apple_server_generate_password": "Generer et app-spesifikt passord for bruk med Cal.com på",
"apple_server_generate_password": "Generer et app-spesifikt passord for bruk med {{appName}} på",
"credentials_stored_encrypted": "Din legitimasjon vil bli lagret og kryptert.",
"it_stored_encrypted": "Det vil bli lagret og kryptert.",
"go_to_app_store": "Gå til App Butikken",
@@ -1120,16 +1125,16 @@
"incorrect_2fa": "Feil to-faktor autentiseringskode",
"which_event_type_apply": "Hvilken hendelsestype vil dette gjelde for?",
"no_workflows_description": "Arbeidsflyter muliggjør enkel automatisering for å sende varsler og påminnelser slik at du kan bygge prosesser rundt hendelsene dine.",
"timeformat_profile_hint": "Dette er en intern innstilling og vil ikke påvirke hvordan tidspunkt vises på offentlige bookingsider for deg eller noen som booker deg.",
"create_workflow": "Lag en arbeidsflyt",
"do_this": "Gjør dette",
"turn_off": "Slå av",
"settings_updated_successfully": "Innstillingene ble oppdatert",
"error_updating_settings": "Feil under oppdatering av innstillinger",
"personal_cal_url": "Min personlige Cal URL",
"personal_cal_url": "Min personlige {{appName}} URL",
"bio_hint": "Noen setninger om deg selv. Dette vil vises på din personlige url-side.",
"timeformat_profile_hint": "Dette er en intern innstilling og vil ikke påvirke hvordan tidspunkt vises på offentlige bookingsider for deg eller noen som booker deg.",
"delete_account_modal_title": "Slett Konto",
"confirm_delete_account_modal": "Er du sikker på at du vil slette Cal.com-kontoen din?",
"confirm_delete_account_modal": "Er du sikker på at du vil slette {{appName}}-kontoen din?",
"delete_my_account": "Slett kontoen min",
"start_of_week": "Begynnelsen av uken",
"select_calendars": "Velg hvilke kalendere du vil sjekke for konflikter for å forhindre dobbeltbookinger.",
@@ -1139,7 +1144,7 @@
"custom_brand_colors": "Egendefinerte merkevare-farger",
"customize_your_brand_colors": "Tilpass din egen merkevare-farge på bookingsiden din.",
"pro": "Pro",
"removes_cal_branding": "Fjerner alt av Cal relatert merkeprofilering, f.eks. \"Powered by Cal.\"",
"removes_cal_branding": "Fjerner alt av {{appName}} relatert merkeprofilering, f.eks. \"Powered by {{appName}}.\"",
"profile_picture": "Profilbilde",
"upload": "Last opp",
"add_profile_photo": "Legg til profilbilde",
@@ -1167,7 +1172,7 @@
"embeds": "Innbygginger",
"impersonation": "Etterligning",
"users": "Brukere",
"profile_description": "Administrer innstillinger for Cal profilen din",
"profile_description": "Administrer innstillinger for {{appName}} profilen din",
"general_description": "Administrer innstillinger for språk og tidssone",
"calendars_description": "Konfigurer hvordan hendelsestypene dine samhandler med kalenderne dine",
"appearance_description": "Administrer innstillinger for booking-utseendet",
@@ -1205,7 +1210,7 @@
"create_your_first_form": "Lag ditt første skjema",
"create_your_first_form_description": "Med Viderekoblings-skjema kan du stille kvalifiserende spørsmål og videresende til riktig person eller hendelsestype.",
"create_your_first_webhook": "Lag din første Webhook",
"create_your_first_webhook_description": "Med Webhooks kan du motta møtedata i sanntid når noe skjer i Cal.com.",
"create_your_first_webhook_description": "Med Webhooks kan du motta møtedata i sanntid når noe skjer i {{appName}}.",
"for_a_maximum_of": "For maksimalt",
"event_one": "hendelse",
"event_other": "hendelser",
@@ -1221,7 +1226,7 @@
"workflow_example_4": "Send deltakeren en e-post-påminnelse 1 time før hendelser starter",
"workflow_example_5": "Send verten en tilpasset e-post når en hendelse får nytt tidspunkt",
"workflow_example_6": "Send verten en tilpasset SMS når en ny hendelse er booket",
"welcome_to_cal_header": "Velkommen til Cal.com!",
"welcome_to_cal_header": "Velkommen til {{appName}}!",
"edit_form_later_subtitle": "Du kan redigere dette senere.",
"connect_calendar_later": "Jeg kobler til kalenderen min senere",
"set_my_availability_later": "Jeg setter opp min tilgjengelighet senere",
@@ -1231,7 +1236,7 @@
"booking_appearance": "Booking Utseende",
"appearance_team_description": "Administrer innstillinger for teamets booking-utseende",
"only_owner_change": "Kun eieren av dette teamet kan gjøre endringer i teamets booking ",
"team_disable_cal_branding_description": "Fjerner alle Cal relaterte varemerker, f.eks. \"Powered by Cal\"",
"team_disable_cal_branding_description": "Fjerner alle {{appName}} relaterte varemerker, f.eks. \"Powered by {{appName}}\"",
"invited_by_team": "{{teamName}} har invitert deg til å bli med i teamet deres som en {{role}}",
"token_invalid_expired": "Token er enten ugyldig eller utløpt.",
"exchange_add": "Koble til Microsoft Exchange",
@@ -1251,13 +1256,13 @@
"theme_dark": "Mørkt",
"theme_system": "System standard",
"add_a_team": "Legg til et team",
"add_webhook_description": "Motta møtedata i sanntid når noe skjer i Cal.com",
"add_webhook_description": "Motta møtedata i sanntid når noe skjer i {{appName}}",
"triggers_when": "Utløses når",
"test_webhook": "Vennligst ping-test før du oppretter.",
"enable_webhook": "Aktiver Webhook",
"add_webhook": "Legg til Webhook",
"webhook_edited_successfully": "Webhook lagret",
"webhooks_description": "Motta møtedata i sanntid når noe skjer i Cal.com",
"webhooks_description": "Motta møtedata i sanntid når noe skjer i {{appName}}",
"api_keys_description": "Generer API nøkler for å få tilgang til din egen konto",
"new_api_key": "Ny API nøkkel",
"active": "aktiv",
@@ -1266,7 +1271,7 @@
"embeds_title": "HTML iframe-innbygging",
"embeds_description": "Bygg inn alle hendelsestypene dine på nettstedet ditt",
"create_first_api_key": "Lag din første API nøkkel",
"create_first_api_key_description": "API nøkler lar andre apper kommunisere med Cal.com",
"create_first_api_key_description": "API nøkler lar andre apper kommunisere med {{appName}}",
"back_to_signin": "Tilbake til innlogging",
"reset_link_sent": "Lenke for tilbakestilling er sendt",
"password_reset_email": "En e-post er på vei til {{email}} med instruksjoner for å tilbakestille passordet.",
@@ -1274,14 +1279,14 @@
"password_updated": "Passord oppdatert!",
"pending_payment": "Venter på betaling",
"confirmation_page_rainbow": "Token vokter hendelsen din med tokens eller NFT-er på Ethereum, Polygon og mer.",
"not_on_cal": "Ikke på Cal.com",
"not_on_cal": "Ikke på {{appName}}",
"no_calendar_installed": "Ingen kalender installert",
"no_calendar_installed_description": "Du har ikke koblet til noen av kalenderne dine ennå",
"add_a_calendar": "Legg til en kalender",
"change_email_hint": "Det kan hende du må logge ut og inn igjen for å se at endringer trer i kraft",
"confirm_password_change_email": "Vennligst bekreft passordet ditt før du endrer e-postadressen din",
"seats": "seter",
"every_app_published": "Hver app publisert på Cal.com App Butikken er åpen kildekode og grundig testet via fagfellevurderinger. Cal.com, Inc. godkjenner eller sertifiserer likevel ikke disse appene med mindre de er publisert av Cal.com. Hvis du møter upassende innhold eller oppførsel, vennligst rapporter det.",
"every_app_published": "Hver app publisert på {{appName}} App Butikken er åpen kildekode og grundig testet via fagfellevurderinger. Uansett, {{companyName}} godkjenner eller sertifiserer likevel ikke disse appene med mindre de er publisert av {{appName}}. Hvis du møter upassende innhold eller oppførsel, vennligst rapporter det.",
"report_app": "Rapporter app",
"limit_booking_frequency": "Begrens bookingfrekvens",
"limit_booking_frequency_description": "Begrens hvor mange ganger denne hendelsen kan bookes",
@@ -1384,5 +1389,9 @@
"test_preview_description": "Test viderekoblings-skjemaet ditt uten å sende noen data",
"test_routing": "Test Viderekobling",
"booking_limit_reached": "Booking-grensen for denne hendelsestypen er nådd",
"fill_this_field": "Vennligst fyll ut dette feltet"
"fill_this_field": "Vennligst fyll ut dette feltet",
"options": "Alternativer",
"enter_option": "Angi alternativ {{index}}",
"add_an_option": "Legg til et alternativ",
"radio": "Radio"
}
+17 -17
View File
@@ -16,8 +16,8 @@
"event_request_cancelled": "Twoje zaplanowane wydarzenie zostało anulowane",
"organizer": "Organizator",
"need_to_reschedule_or_cancel": "Potrzebujesz zmienić harmonogram lub anulować?",
"cancellation_reason": "Powód anulowania",
"cancellation_reason_placeholder": "Dlaczego anulujesz? (opcjonalne)",
"cancellation_reason": "Powód anulowania (opcjonalnie)",
"cancellation_reason_placeholder": "Dlaczego anulujesz?",
"rejection_reason": "Powód odrzucenia",
"rejection_reason_title": "Odrzucić prośbę o rezerwację?",
"rejection_reason_description": "Czy jesteś pewien, że chcesz odrzucić prośbę o rezerwację? Damy znać osobie, która próbowała jej dokonać. Poniżej możesz podać powód.",
@@ -419,7 +419,7 @@
"forgotten_secret_description": "Jeśli nie pamiętasz tego wpisu tajnego lub nie masz do niego dostępu, możesz go zmienić, ale pamiętaj, że wszystkie integracje korzystające z tego wpisu tajnego będą musiały zostać zaktualizowane.",
"current_incorrect_password": "Bieżące hasło jest nieprawidłowe",
"password_hint_caplow": "Kombinacja wielkich i małych liter",
"password_hint_min": "Długość co najmniej 7 znaków",
"password_hint_min": "Długość co najmniej 8 znaków",
"password_hint_num": "Zawrzyj co najmniej 1 cyfrę",
"invalid_password_hint": "Hasło musi składać się z co najmniej 7 znaków, zawierać co najmniej jedną cyfrę oraz kombinację wielkich i małych liter",
"incorrect_password": "Hasło jest nieprawidłowe.",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Pokaż ustawienia zaawansowane",
"event_name": "Nazwa wydarzenia",
"event_name_tooltip": "Nazwa, która pojawi się w kalendarzach",
"meeting_with_user": "Spotkanie z {ATTENDEE}",
"meeting_with_user": "Spotkanie z {{attendeeName}}",
"additional_inputs": "Dodatkowe Wejścia",
"additional_input_description": "Wymagaj od osoby układającej harmonogram wprowadzania dodatkowych danych przed potwierdzeniem rezerwacji",
"label": "Etykieta",
@@ -784,7 +784,7 @@
"analytics": "Analityka",
"empty_installed_apps_headline": "Brak zainstalowanych aplikacji",
"empty_installed_apps_description": "Aplikacje umożliwiają znaczne usprawnienie przebiegu pracy i uproszczenie planowania.",
"empty_installed_apps_button": "Przeglądaj sklep App Store lub zainstaluj z poniższych aplikacji",
"empty_installed_apps_button": "Przeglądaj sklep App Store",
"manage_your_connected_apps": "Zarządzaj zainstalowanymi aplikacjami lub zmień ustawienia",
"browse_apps": "Przeglądaj aplikacje",
"features": "Funkcje",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Nieprawidłowy kod uwierzytelnienia dwuskładnikowego",
"which_event_type_apply": "Do jakiego rodzaju wydarzenia będzie się to odnosić?",
"no_workflows_description": "Przepływy pracy umożliwiają prostą automatyzację wysyłania powiadomień i przypomnień, dzięki czemu możesz tworzyć procesy dotyczące Twoich wydarzeń.",
"timeformat_profile_hint": "To jest ustawienie wewnętrzne, które nie będzie miało wpływu na to, jak godziny będą wyświetlane Tobie lub komuś, kto dokonuje u Ciebie rezerwacji, na publicznych stronach rezerwacji.",
"create_workflow": "Utwórz przepływ pracy",
"do_this": "Zrób to",
"turn_off": "Wyłącz",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Błąd podczas aktualizacji ustawień",
"personal_cal_url": "Mój osobisty adres URL aplikacji {{appName}}",
"bio_hint": "Kilka zdań o Tobie. Pojawią się one na Twojej osobistej stronie URL.",
"timeformat_profile_hint": "To jest ustawienie wewnętrzne, które nie będzie miało wpływu na to, jak godziny będą wyświetlane Tobie lub komuś, kto dokonuje u Ciebie rezerwacji, na publicznych stronach rezerwacji.",
"delete_account_modal_title": "Usuń konto",
"confirm_delete_account_modal": "Czy na pewno chcesz usunąć swoje konto {{appName}}?",
"delete_my_account": "Usuń konto",
@@ -1345,17 +1345,17 @@
"billing_frequency": "Częstotliwość rozliczania",
"monthly": "Co miesiąc",
"yearly": "Co rok",
"checkout": "Kasa",
"checkout": "Do kasy",
"your_team_disbanded_successfully": "Twój zespół został rozwiązany.",
"error_creating_team": "Podczas tworzenia zespołu wystąpił błąd.",
"error_creating_team": "Podczas tworzenia zespołu wystąpił błąd",
"you": "Ty",
"send_email": "Wyślij wiadomość e-mail",
"member_already_invited": "Użytkownik został już zaproszony.",
"member_already_invited": "Członek został już zaproszony",
"enter_email_or_username": "Wprowadź adres e-mail lub nazwę użytkownika",
"team_name_taken": "Ta nazwa jest już zajęta.",
"must_enter_team_name": "Musisz podać nazwę zespołu.",
"team_url_required": "Musisz podać adres URL zespołu.",
"team_url_taken": "Ten adres URL jest już używany.",
"team_name_taken": "Ta nazwa jest już zajęta",
"must_enter_team_name": "Musisz wprowadzić nazwę zespołu",
"team_url_required": "Musisz wprowadzić adres URL zespołu",
"team_url_taken": "Ten adres URL jest już zajęty",
"team_publish": "Opublikuj zespół",
"number_sms_notifications": "Numer telefonu (powiadomienia SMS)",
"attendee_email_workflow": "Adres e-mail uczestnika",
@@ -1366,9 +1366,9 @@
"reason": "Powód",
"sender_id": "Identyfikator nadawcy",
"sender_id_error_message": "Dozwolone są tylko litery, cyfry i spacje (maksymalnie 11 znaków)",
"test_routing_form": "Testuj formularz do przekierowania",
"test_preview": "Podgląd testu",
"test_routing_form": "Przetestuj formularz przekierowania",
"test_preview": "Przetestuj podgląd",
"route_to": "Przekieruj do",
"test_preview_description": "Przetestuj swój formularz przekierowania bez przesyłania jakicholwiek danych",
"test_routing": "Testuj przekierowanie"
"test_preview_description": "Przetestuj swój formularz przekierowania bez przesyłania jakichkolwiek danych",
"test_routing": "Przetestuj przekierowanie"
}
@@ -536,7 +536,7 @@
"open_options": "Abrir opções",
"copy_link": "Copiar link do evento",
"share": "Compartilhar",
"share_event": "Você se importa de fazer uma reserva para mim no {{appName}} ou enviar seu link?",
"share_event": "Você se importa de fazer uma reserva para mim no Cal ou enviar seu link?",
"copy_link_team": "Copiar link do time",
"leave_team": "Sair do time",
"confirm_leave_team": "Sim, sair do time",
@@ -654,7 +654,7 @@
"show_advanced_settings": "Mostrar Configurações Avançadas",
"event_name": "Nome do Evento",
"event_name_tooltip": "O nome que aparecerá nos calendários",
"meeting_with_user": "Reunião com {ATTENDEE}",
"meeting_with_user": "Reunião com {{attendeeName}}",
"additional_inputs": "Campos adicionais",
"additional_input_description": "Solicitar que o agendador insira entradas adicionais antes que o pedido seja confirmado",
"label": "Etiqueta",
@@ -686,7 +686,7 @@
"cal_provide_zoom_meeting_url": "{{appName}} fornecerá uma URL de reunião do Zoom.",
"cal_provide_tandem_meeting_url": "{{appName}} fornecerá um URL de reunião do Tandem.",
"cal_provide_video_meeting_url": "O {{appName}} irá fornecer um URL de reunião do Daily video.",
"cal_provide_jitsi_meeting_url": "O {{appName}} fornecerá um URL de reunião do Jitsi Meet.",
"cal_provide_jitsi_meeting_url": "O Cal fornecerá um URL de reunião do Jitsi Meet.",
"cal_provide_huddle01_meeting_url": "O {{appName}} fornecerá um URL de reunião do Huddle01 Web3 video.",
"cal_provide_teams_meeting_url": "O {{appName}} enviará um URL da reunião para o MS Teams. OBSERVAÇÃO: É PRECISO TER UMA CONTA ESCOLAR OU CORPORATIVA",
"require_payment": "Requerer Pagamento",
@@ -1109,6 +1109,7 @@
"incorrect_2fa": "Código de autenticação de dois fatores incorreto",
"which_event_type_apply": "A que tipo de evento isto se aplica?",
"no_workflows_description": "Fluxo de trabalho permitem uma simples automação para enviar notificações e lembretes que permitem que você crie processos em torno de seus eventos.",
"timeformat_profile_hint": "Esta é uma configuração interna e não afetará a quantidade de exibições em páginas públicas de reservas para você ou outra pessoa que estiver fazendo reserva.",
"create_workflow": "Criar fluxo de trabalho",
"do_this": "Faça isso",
"turn_off": "Desligar",
@@ -1116,7 +1117,6 @@
"error_updating_settings": "Erro ao atualizar configurações",
"personal_cal_url": "Meu URL pessoal da {{appName}}",
"bio_hint": "Escreva algumas frases sobre você. Isso aparecerá no URL da sua página pessoal.",
"timeformat_profile_hint": "Esta é uma configuração interna e não afetará a quantidade de exibições em páginas públicas de reservas para você ou outra pessoa que estiver fazendo reserva.",
"delete_account_modal_title": "Excluir conta",
"confirm_delete_account_modal": "Tem certeza de que deseja excluir sua conta {{appName}}?",
"delete_my_account": "Excluir minha conta",
@@ -1325,7 +1325,7 @@
"saml_config_updated_successfully": "Configuração do SAML atualizada com sucesso",
"saml_configuration": "Configuração do SAML",
"delete_saml_configuration": "Remover configuração do SAML",
"delete_saml_configuration_confirmation_message": "Você tem certeza que deseja remover esta configuração SAML? Os membros do seu time que utilizam SAML para fazer login não conseguirão acessar o {{appName}}.",
"delete_saml_configuration_confirmation_message": "Você tem certeza que deseja remover esta configuração SAML? Os membros do seu time que utilizam SAML para fazer login não conseguirão acessar o Cal.com.",
"confirm_delete_saml_configuration": "Sim, remover configuração do SAML",
"saml_not_configured_yet": "O SAML ainda não está configurado",
"saml_configuration_description": "Por favor cole o SAML metadata obtido de seu Provedor de Identidade na caixa de texto a seguir para atualizar sua configuração do SAML.",
@@ -101,7 +101,7 @@
"team_info": "Informações da equipa",
"request_another_invitation_email": "Se não quiser utilizar {{toEmail}} como email do {{appName}}, ou já tem uma conta em {{appName}}, por favor peça outro convite para esse email.",
"you_have_been_invited": "Recebeu um convite para juntar-se à equipa {{teamName}}",
"user_invited_you": "{{user}} enviou um convite para juntar-se à equipa {{teamName}}",
"user_invited_you": "{{user}} enviou um convite para juntar-se à equipa {{team}}",
"hidden_team_member_title": "Está oculto nesta equipa",
"hidden_team_member_message": "O seu lugar não está pago, faça upgrade para PRO ou informe ao proprietário da equipa que pode pagar pelo seu lugar.",
"hidden_team_owner_message": "Precisa de uma conta Pro para usar equipas, ficará oculto até que actualize.",
@@ -504,7 +504,7 @@
"add_team_members_description": "Convidar outros a juntarem-se à sua equipa",
"add_team_member": "Adicionar membro da equipa",
"invite_new_member": "Convidar um Novo Membro",
"invite_new_member_description": "Nota: isto irá ter o <1>custo de um lugar adicional ($15/m)</1> na sua subscrição.",
"invite_new_member_description": "Nota: isto vai ter o <1>custo de um lugar adicional ($15/m)</1> na sua subscrição.",
"invite_new_team_member": "Convide alguém para a sua equipa.",
"change_member_role": "Alterar função de membro da equipa",
"disable_cal_branding": "Desativar a marca {{appName}}",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Mostrar Configurações Avançadas",
"event_name": "Nome do Evento",
"event_name_tooltip": "O nome que será mostrado nos calendários",
"meeting_with_user": "Reunião com {ATTENDEE}",
"meeting_with_user": "Reunião com {{attendeeName}}",
"additional_inputs": "Campos adicionais",
"additional_input_description": "Requerer que o responsável pelo agendamento especifique entradas complementares antes do pedido ser confirmado",
"label": "Etiqueta",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Código de autenticação de dois fatores incorreto",
"which_event_type_apply": "A que tipo de evento isto se aplica?",
"no_workflows_description": "Os fluxos de trabalho permitem automações simples para enviar notificações e lembretes, permitindo criar processos à volta dos seus eventos.",
"timeformat_profile_hint": "Esta é uma configuração interna e que não irá afetar como os horários serão apresentados nas páginas públicas de agendamento, seja para si ou para qualquer pessoa que esteja a fazer uma reserva.",
"create_workflow": "Criar um fluxo de trabalho",
"do_this": "Fazer isto",
"turn_off": "Desligar",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Erro ao atualizar as definições",
"personal_cal_url": "O meu endereço pessoal do {{appName}}",
"bio_hint": "Algumas frases sobre si. Isto irá ser mostrado no endereço da sua página pessoal.",
"timeformat_profile_hint": "Esta é uma configuração interna e que não irá afetar como os horários serão apresentados nas páginas públicas de agendamento, seja para si ou para qualquer pessoa que esteja a fazer uma reserva.",
"delete_account_modal_title": "Eliminar conta",
"confirm_delete_account_modal": "Tem a certeza que pretende eliminar a sua conta {{appName}}?",
"delete_my_account": "Eliminar a minha conta",
@@ -1258,6 +1258,7 @@
"back_to_signin": "Voltar para o início de sessão",
"reset_link_sent": "Ligação de reposição enviada",
"password_reset_email": "Um e-mail está a caminho de {{email}} com instruções para redefinir a sua palavra-passe.",
"password_reset_leading": "Se não receber um e-mail em breve, confirme se o endereço de e-mail especificado está correto, verifique a sua pasta de SPAM ou contacte o apoio se o problema persistir.",
"password_updated": "Palavra-passe atualizada!",
"pending_payment": "Pagamento pendente",
"confirmation_page_rainbow": "Controle o acesso ao seu evento com tokens ou NFT na Ethereum, Polygon e muito mais.",
+25 -24
View File
@@ -16,8 +16,8 @@
"event_request_cancelled": "Evenimentul programat a fost anulat",
"organizer": "Organizator",
"need_to_reschedule_or_cancel": "Trebuie să reprogramați sau să anulați?",
"cancellation_reason": "Motivul anulării",
"cancellation_reason_placeholder": "De ce anulați? (opțional)",
"cancellation_reason": "Motivul anulării (opțional)",
"cancellation_reason_placeholder": "De ce anulați?",
"rejection_reason": "Motivul respingerii",
"rejection_reason_title": "Respingeți solicitarea de rezervare?",
"rejection_reason_description": "Sigur doriți să respingeți rezervarea? Vom anunța persoana care a încercat să rezerve. Puteți specifica un motiv mai jos.",
@@ -101,15 +101,15 @@
"team_info": "Informații echipă",
"request_another_invitation_email": "Dacă preferați să nu utilizați {{toEmail}} ca e-mail {{appName}} sau aveți deja un cont {{appName}}, vă rugăm să solicitați o altă invitație la acel e-mail.",
"you_have_been_invited": "Ați fost invitat să vă alăturați echipei {{teamName}}",
"user_invited_you": "{{user}} v-a invitat să vă alăturați echipei {{teamName}}",
"user_invited_you": "{{user}} v-a invitat să vă alăturați echipei {{team}}",
"hidden_team_member_title": "Sunteți ascuns în această echipă",
"hidden_team_member_message": "Licența dvs. nu este plătită. Fie faceți upgrade la Pro, fie anunțați proprietarul echipei că vă poate plăti licența.",
"hidden_team_owner_message": "Aveți nevoie de un cont Pro pentru a utiliza echipe. Sunteți ascuns până când faceți upgrade.",
"link_expires": "p.s. Expiră în {{expiresIn}} ore.",
"upgrade_to_per_seat": "Faceți upgrade la nivelul Per licență",
"team_upgrade_seats_details": "Printre cei {{memberCount}} (de) membri din echipa dvs., {{unpaidCount}} (de) locuri nu sunt plătite. La {{seatPrice}} USD/lună/licență, costul total estimat al abonamentului dvs. este de {{totalCost}} USD/lună.",
"team_upgrade_banner_description": "Vă mulțumim că ați încercat noul nostru plan pentru echipe. Am observat că echipa dvs. „{{teamName}}” trebuie upgradată.",
"team_upgrade_banner_action": "Upgradați aici",
"team_upgrade_banner_description": "Vă mulțumim că ați încercat noul nostru plan pentru echipe. Am observat că planul echipei dvs. „{{teamName}}” necesită un upgrade.",
"team_upgrade_banner_action": "Realizați upgrade aici",
"team_upgraded_successfully": "Echipa dvs. a fost actualizată cu succes!",
"use_link_to_reset_password": "Utilizați linkul de mai jos pentru a vă reseta parola",
"hey_there": "Bună,",
@@ -419,7 +419,7 @@
"forgotten_secret_description": "Dacă ați pierdut sau ați uitat acest secret, îl puteți modifica, dar rețineți că toate integrările cu acest secret vor trebui actualizate",
"current_incorrect_password": "Parola curentă este incorectă",
"password_hint_caplow": "Combinație de litere mari și litere mici",
"password_hint_min": "Cel puțin 7 caractere",
"password_hint_min": "Cel puțin 8 caractere",
"password_hint_admin_min": "Cel puțin 15 caractere",
"password_hint_num": "Conține cel puțin 1 cifră",
"invalid_password_hint": "Parola trebuie să aibă cel puțin 7 caractere, să conțină cel puțin o cifră și o combinație de litere mari și litere mici",
@@ -505,7 +505,7 @@
"add_team_members_description": "Invitați și alte persoane în echipa dvs.",
"add_team_member": "Adăugați un membru al echipei",
"invite_new_member": "Invitați un nou membru în echipă",
"invite_new_member_description": "Notă: Acest lucru va <1>costa un loc suplimentar (15 $/m)</1> din abonamentul dvs.",
"invite_new_member_description": "Notă: acest lucru va <1>adăuga un loc suplimentar (15 USD/lună)</1> la abonamentul dvs.",
"invite_new_team_member": "Invită pe cineva în echipa ta.",
"change_member_role": "Schimbați rolul de membru al echipei",
"disable_cal_branding": "Dezactivare branding {{appName}}",
@@ -536,7 +536,7 @@
"open_options": "Opțiuni deschise",
"copy_link": "Copiază link-ul la eveniment",
"share": "Distribuire",
"share_event": "Puteți să îmi faceți o rezervare în {{appName}} sau să îmi trimiteți linkul dvs.?",
"share_event": "Puteți să îmi faceți o rezervare în Cal sau să îmi trimiteți linkul dvs.?",
"copy_link_team": "Copiați linkul în echipă",
"leave_team": "Părăsiți echipa",
"confirm_leave_team": "Da, părăsiți echipa",
@@ -654,7 +654,7 @@
"show_advanced_settings": "Afișează setările avansate",
"event_name": "Denumirea evenimentului",
"event_name_tooltip": "Numele care va apărea în calendare",
"meeting_with_user": "Întâlnire cu {ATTENDEE}",
"meeting_with_user": "Întâlnire cu {{attendeeName}}",
"additional_inputs": "Date suplimentare",
"additional_input_description": "Solicitați planificatorului să introducă intrări suplimentare înainte ca rezervarea să fie confirmată",
"label": "Eticheta",
@@ -686,7 +686,7 @@
"cal_provide_zoom_meeting_url": "{{appName}} va oferi un URL pentru ședința de Zoom.",
"cal_provide_tandem_meeting_url": "{{appName}} va oferi un URL pentru ședința de Tandem.",
"cal_provide_video_meeting_url": "{{appName}} va oferi un URL pentru ședința de Daily.",
"cal_provide_jitsi_meeting_url": "{{appName}} va oferi un URL pentru ședința de Jitsi Meet.",
"cal_provide_jitsi_meeting_url": "Cal va oferi un URL pentru ședința de Jitsi Meet.",
"cal_provide_huddle01_meeting_url": "{{appName}} va oferi un URL pentru ședința de Huddle01 Web3.",
"cal_provide_teams_meeting_url": "{{appName}} va pune la dispoziție un URL pentru ședința prin MS Teams. OBSERVAȚIE: TREBUIE SĂ AVEȚI UN CONT PROFESIONAL SAU ȘCOLAR",
"require_payment": "Solicită plata",
@@ -785,7 +785,7 @@
"analytics": "Analiză",
"empty_installed_apps_headline": "Nicio aplicație instalată",
"empty_installed_apps_description": "Aplicațiile vă permit să vă îmbunătățiți în mod semnificativ fluxul de lucru și activitățile legate de programări.",
"empty_installed_apps_button": "Accesați App Store sau instalați o aplicație de mai jos",
"empty_installed_apps_button": "Navigați în App Store",
"manage_your_connected_apps": "Gestionați aplicațiile instalate sau modificați setările",
"browse_apps": "Răsfoiți aplicațiile",
"features": "Caracteristici",
@@ -840,6 +840,7 @@
"redirect_success_booking": "Redirecționare la rezervare ",
"you_are_being_redirected": "Sunteți redirecționat către {{ url }} în $t(second, {\"count\": {{seconds}} }).",
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
"redirect_url_description": "Redirecționați către un URL personalizat după o rezervare reușită",
"duplicate": "Duplicare",
"offer_seats": "Oferiți locuri",
"offer_seats_description": "Opțiunea oferă locuri pentru rezervare și dezactivează automat rezervările pentru oaspeți și cele la alegere.",
@@ -1108,6 +1109,7 @@
"incorrect_2fa": "Cod incorect de autentificare cu doi factori",
"which_event_type_apply": "La ce tip de eveniment se va aplica aceasta?",
"no_workflows_description": "Fluxurile de lucru permit automatizarea simplă pentru a trimite notificări și mementouri, care vă permit să construiți procese în jurul evenimentelor dvs.",
"timeformat_profile_hint": "Aceasta este o setare internă și nu va afecta modul în care sunt afișate orele pe paginile publice de rezervare pentru dvs. sau pentru oricine vă face rezervarea.",
"create_workflow": "Creați un flux de lucru",
"do_this": "Faceți acest lucru",
"turn_off": "Dezactivați",
@@ -1115,7 +1117,6 @@
"error_updating_settings": "Eroare la actualizarea setărilor",
"personal_cal_url": "URL-ul meu personal {{appName}}",
"bio_hint": "Câteva propoziții despre dvs. Acestea vor apărea pe pagina URL-ului dvs. personal.",
"timeformat_profile_hint": "Aceasta este o setare internă și nu va afecta modul în care sunt afișate orele pe paginile publice de rezervare pentru dvs. sau pentru oricine vă face rezervarea.",
"delete_account_modal_title": "Ștergeți contul",
"confirm_delete_account_modal": "Sigur doriți să vă ștergeți contul {{appName}}?",
"delete_my_account": "Ștergeți contul meu",
@@ -1228,8 +1229,8 @@
"exchange_authentication_ntlm": "Autentificare NTLM",
"exchange_compression": "Compresie GZip",
"routing_forms_description": "Puteți vedea aici toate formularele și parcursurile pe care le-ați creat.",
"routing_forms_send_email_owner": "Trimiteți e-mail către proprietar",
"routing_forms_send_email_owner_description": "Trimite un e-mail către proprietar atunci când formularul este trimis",
"routing_forms_send_email_owner": "Trimiteți un e-mail către proprietar",
"routing_forms_send_email_owner_description": "Trimite un e-mail către proprietar atunci când este trimis formularul",
"add_new_form": "Adăugați un formular nou",
"form_description": "Creați formularul pentru direcționarea unei persoane care face rezervare",
"copy_link_to_form": "Copiați linkul în formular",
@@ -1324,7 +1325,7 @@
"saml_config_updated_successfully": "Configurația SAML a fost actualizată cu succes",
"saml_configuration": "Configurație SAML",
"delete_saml_configuration": "Ștergeți configurația SAML",
"delete_saml_configuration_confirmation_message": "Sigur doriți să ștergeți configurația SAML? Membrii echipei dvs. care utilizează conectarea prin SAML nu vor mai putea accesa {{appName}}.",
"delete_saml_configuration_confirmation_message": "Sigur doriți să ștergeți configurația SAML? Membrii echipei dvs. care utilizează conectarea prin SAML nu vor mai putea accesa Cal.com.",
"confirm_delete_saml_configuration": "Da, ștergeți configurația SAML",
"saml_not_configured_yet": "SAML nu este configurat încă",
"saml_configuration_description": "Pentru a actualiza configurația SAML, inserați metadatele SAML generate de furnizorul dvs. de identitate în caseta de text de mai jos.",
@@ -1345,31 +1346,31 @@
"billing_frequency": "Frecvența de facturare",
"monthly": "Lunar",
"yearly": "Anual",
"checkout": "Pagina de plată",
"checkout": "Finalizare cumpărături",
"your_team_disbanded_successfully": "Echipa dvs. a fost desființată cu succes",
"error_creating_team": "Eroare la crearea echipei",
"you": "Dvs.",
"send_email": "Trimiteți e-mail",
"send_email": "Trimiteți un e-mail",
"member_already_invited": "Membrul a fost deja invitat",
"enter_email_or_username": "Introduceți un e-mail sau un nume de utilizator",
"team_name_taken": "Acest nume este deja luat",
"team_name_taken": "Acest nume este folosit deja",
"must_enter_team_name": "Trebuie să introduceți un nume de echipă",
"team_url_required": "Trebuie să introduceți un URL de echipă",
"team_url_taken": "Acest URL este deja luat",
"team_url_taken": "Acest URL este folosit deja",
"team_publish": "Publicați echipa",
"number_sms_notifications": "Număr de telefon (notificări SMS)",
"attendee_email_workflow": "E-mail participant",
"attendee_email_info": "E-mailul persoanei care efectuează rezervarea",
"invalid_credential": "Vai, nu! Se pare că permisiunea a expirat sau a fost revocată. Reinstalați din nou.",
"choose_common_schedule_team_event": "Alegeți un program comun",
"choose_common_schedule_team_event_description": "Activați această opțiune dacă doriți să folosiți un program comun între gazde. Atunci când este dezactivat, fiecare gazdă va fi rezervată în funcție de programul lor implicit.",
"choose_common_schedule_team_event_description": "Activați această opțiune dacă doriți să folosiți un program comun între gazde. Atunci când este dezactivată, fiecare gazdă va fi rezervată în funcție de programul său implicit.",
"reason": "Motiv",
"sender_id": "ID expeditor",
"sender_id_error_message": "Sunt permise doar litere, numere și spații (maxim 11 caractere)",
"test_routing_form": "Formular de redirecționare test",
"test_preview": "Previzualizare test",
"test_routing_form": "Testați formularul de redirecționare",
"test_preview": "Testați previzualizarea",
"route_to": "Direcționați către",
"test_preview_description": "Testați-vă formularul de redirecționare fără a trimite date",
"test_routing": "Redirecționare test",
"booking_limit_reached": "Limita de rezervare pentru acest tip de eveniment a fost atinsă"
"test_routing": "Testați redirecționarea",
"booking_limit_reached": "A fost atinsă limita de rezervare pentru acest tip de eveniment"
}
@@ -101,7 +101,7 @@
"team_info": "Информация о команде",
"request_another_invitation_email": "Если вы не хотите использовать {{toEmail}} как ваш {{appName}} адрес электронной почты или уже есть аккаунт {{appName}}, пожалуйста, запросите другое приглашение на это письмо.",
"you_have_been_invited": "Вас пригласили присоединиться к команде {{teamName}}",
"user_invited_you": "{{user}} приглашает вас присоединиться к команде {{teamName}}",
"user_invited_you": "{{user}} приглашает вас присоединиться к команде {{team}}",
"hidden_team_member_title": "В этой команде вы скрытый пользователь",
"hidden_team_member_message": "Ваше место не оплачено. Перейдите на аккаунт PRO или свяжитесь с руководителем команды, чтобы сообщить ему, что он может оплатить ваше место.",
"hidden_team_owner_message": "Чтобы работать с командами, необходим аккаунт Pro. До перехода на этот тариф Вы остаетесь скрытым пользователем.",
@@ -536,7 +536,7 @@
"open_options": "Открыть настройки",
"copy_link": "Скопировать ссылку на событие",
"share": "Поделиться",
"share_event": "Не могли бы вы забронировать нам встречу в {{appName}} или отправить мне свою ссылку?",
"share_event": "Не могли бы вы забронировать нам встречу в Cal или отправить мне свою ссылку?",
"copy_link_team": "Скопировать ссылку на команду",
"leave_team": "Выйти из команды",
"confirm_leave_team": "Да, выйти из команды",
@@ -654,7 +654,7 @@
"show_advanced_settings": "Показать дополнительные параметры",
"event_name": "Название события",
"event_name_tooltip": "Название, которое будет отображаться в календарях",
"meeting_with_user": "Встреча с {ATTENDEE}",
"meeting_with_user": "Встреча с {{attendeeName}}",
"additional_inputs": "Дополнительные вопросы",
"additional_input_description": "Необходимо ввести в планировщик дополнительную информацию до подтверждения бронирования",
"label": "Название",
@@ -1109,6 +1109,7 @@
"incorrect_2fa": "Неверный код двухфакторной авторизации",
"which_event_type_apply": "К какому типу событий применить?",
"no_workflows_description": "С помощью рабочих процессов можно с легкостью автоматизировать отправку уведомлений и напоминаний, формируя процессы вокруг событий.",
"timeformat_profile_hint": "Это внутренняя настройка. Для вас и других пользователей, оформляющих бронирование, отображение времени на публичных страницах бронирования не изменится.",
"create_workflow": "Создать рабочий процесс",
"do_this": "Сделать",
"turn_off": "Выключить",
@@ -1116,7 +1117,6 @@
"error_updating_settings": "Ошибка при обновлении настроек",
"personal_cal_url": "URL-адрес моего персонального {{appName}}",
"bio_hint": "Несколько предложений о себе. Они будут отображаться на вашей персональной странице.",
"timeformat_profile_hint": "Это внутренняя настройка. Для вас и других пользователей, оформляющих бронирование, отображение времени на публичных страницах бронирования не изменится.",
"delete_account_modal_title": "Удалить аккаунт",
"confirm_delete_account_modal": "Удалить аккаунт {{appName}}?",
"delete_my_account": "Удалить мой аккаунт",
@@ -535,7 +535,7 @@
"open_options": "Otvori opcije",
"copy_link": "Kopiraj link do događaja",
"share": "Podeli",
"share_event": "Da li biste želeli da rezervišete moj {{appName}} ili da mi pošaljete vaš link?",
"share_event": "Da li biste želeli da rezervišete moj Cal ili da mi pošaljete vaš link?",
"copy_link_team": "Kopiraj link do tima",
"leave_team": "Napusti tim",
"confirm_leave_team": "Da, napusti tim",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Pokaži napredna podešavanja",
"event_name": "Ime Događaja",
"event_name_tooltip": "Ime koje će se pojaviti u kalendarima",
"meeting_with_user": "Sastanak sa {ATTENDEE}",
"meeting_with_user": "Sastanak sa {{attendeeName}}",
"additional_inputs": "Dodatni unosi",
"additional_input_description": "Zahtevaj od planera da unese dodatne unose pre potvrde rezervacije",
"label": "Oznaka",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Netačan kôd za dvostruku potvrdu identiteta",
"which_event_type_apply": "Na koji tip događaja će se ovo primeniti?",
"no_workflows_description": "Radni tokovi omogućavaju jednostavnu automatizaciju slanja obaveštenja i podsetnika što vam omogućava da izgradite procese oko vaših događaja.",
"timeformat_profile_hint": "Ovo je interno podešavanje i neće uticati koliko puta će biti prikazano na javnim stranicama za rezervisanje, za vas ili bilo koga ko vas rezerviše.",
"create_workflow": "Kreirajte radni tok",
"do_this": "Uradi ovo",
"turn_off": "Isključi",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Greška pri ažuriranju podešavanja",
"personal_cal_url": "Moj lični {{appName}} URL",
"bio_hint": "Par rečenica o vama. Ovo će se pojaviti na vašoj ličnoj url stranici.",
"timeformat_profile_hint": "Ovo je interno podešavanje i neće uticati koliko puta će biti prikazano na javnim stranicama za rezervisanje, za vas ili bilo koga ko vas rezerviše.",
"delete_account_modal_title": "Izbriši nalog",
"confirm_delete_account_modal": "Jeste li sigurni da želite da izbrišete vaš {{appName}} nalog?",
"delete_my_account": "Izbriši moj nalog",
@@ -1258,6 +1258,7 @@
"back_to_signin": "Nazad na prijavljivanje",
"reset_link_sent": "Veza za resetovanje je poslata",
"password_reset_email": "Imejl je na putu do {{email}} sa instrukcijama za resetovanje vaše lozinke.",
"password_reset_leading": "Ako uskoro ne primite imejl, proverite da li ste uneli ispravnu imejl adresu, proverite vašu fasciklu za neželjenu poštu ili se obratite podršci ako se problem nastavi.",
"password_updated": "Lozinka je ažurirana!",
"pending_payment": "Čeka se na plaćanje",
"confirmation_page_rainbow": "Zaštitite vaš događaj tokenom ili NFT-om na Ethereum-u, Polygon-u, itd.",
+24 -21
View File
@@ -16,8 +16,8 @@
"event_request_cancelled": "Din schemalagda bokning ställdes in",
"organizer": "Arrangör",
"need_to_reschedule_or_cancel": "Behöver du boka om eller avboka?",
"cancellation_reason": "Anledning till avbokning",
"cancellation_reason_placeholder": "Varför avbokar du? (frivilligt)",
"cancellation_reason": "Orsaker till annullering (valfritt)",
"cancellation_reason_placeholder": "Varför avbryter du?",
"rejection_reason": "Anledning till att avböja",
"rejection_reason_title": "Avböj bokningsförfrågan?",
"rejection_reason_description": "Är du säker på att du vill avböja bokningen? Vi kommer att meddela personen som försökte boka. Du kan ange en anledning nedan.",
@@ -108,7 +108,7 @@
"link_expires": "p.s. Den går ut om {{expiresIn}} timmar.",
"upgrade_to_per_seat": "Uppgradera till Per-Seat",
"team_upgrade_seats_details": "Av {{memberCount}} medlemmar i ditt lag är {{unpaidCount}} plats(er) obetalda. Vid ${{seatPrice}}/m per plats är den uppskattade totala kostnaden för ditt medlemskap ${{totalCost}}/m.",
"team_upgrade_banner_description": "Tack för att du testade vår nya lagplan. Vi märkte att ditt team \"{{teamName}}\" måste uppgraderas.",
"team_upgrade_banner_description": "Tack för att du testade vår nya teamplan. Vi märkte att ditt team \"{{teamName}}\" måste uppgraderas.",
"team_upgrade_banner_action": "Uppgradera här",
"team_upgraded_successfully": "Ditt team har uppgraderats!",
"use_link_to_reset_password": "Använd länken nedan för att återställa ditt lösenord",
@@ -419,7 +419,7 @@
"forgotten_secret_description": "Om du tappat bort eller glömt den här hemligheten kan du ändra den, men var medveten om att alla integrationer som använder hemligheten måste uppdateras",
"current_incorrect_password": "Nuvarande lösenord är felaktigt",
"password_hint_caplow": "Blandning av versaler och gemener",
"password_hint_min": "Minst 7 tecken långt",
"password_hint_min": "Minst 8 tecken",
"password_hint_num": "Innehåller minst 1 siffra",
"invalid_password_hint": "Lösenordet måste innehålla minst 7 tecken och har minst en siffra samt en blandning av versaler och gemener",
"incorrect_password": "Lösenordet är felaktigt.",
@@ -504,7 +504,7 @@
"add_team_members_description": "Bjud in andra att gå med i ditt team",
"add_team_member": "Lägg till teammedlem",
"invite_new_member": "Bjud in en ny teammedlem",
"invite_new_member_description": "Notera: Detta kommer att <1>kosta en extra plats ($15/m)</1> på ditt abonnemang.",
"invite_new_member_description": "Obs! Detta kommer att <1>kosta en extra plats (150 kr/mån)</1> i din prenumeration.",
"invite_new_team_member": "Bjud in någon till ditt team.",
"change_member_role": "Ändra teammedlemmens roll",
"disable_cal_branding": "Inaktivera {{appName}}-varumärke",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Visa avancerade inställningar",
"event_name": "Händelsenamn",
"event_name_tooltip": "Namnet som kommer visas i kalendrar",
"meeting_with_user": "Möte med {ATTENDEE}",
"meeting_with_user": "Möte med {{attendeeName}}",
"additional_inputs": "Ytterligare inmatningar",
"additional_input_description": "Kräv schemaläggaren att mata in ytterligare ingångar innan bokningen bekräftas",
"label": "Etikett",
@@ -784,7 +784,7 @@
"analytics": "Analys",
"empty_installed_apps_headline": "Inga appar installerade",
"empty_installed_apps_description": "Med appar kan du förbättra ditt arbetsflöde och din schemaläggning avsevärt.",
"empty_installed_apps_button": "Utforska App Store eller installera från apparna nedan",
"empty_installed_apps_button": "Utforska App Store",
"manage_your_connected_apps": "Hantera dina installerade appar eller ändra inställningar",
"browse_apps": "Bläddra bland appar",
"features": "Egenskaper",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Felaktig tvåfaktorsautentiseringskod",
"which_event_type_apply": "Vilken händelsetyp kommer detta att gälla?",
"no_workflows_description": "Arbetsflöden möjliggör enkel automatisering för att skicka meddelanden och påminnelser så att du kan bygga processer kring dina händelser.",
"timeformat_profile_hint": "Detta är en intern inställning och kommer inte att påverka hur tider visas på offentliga bokningssidor för dig eller någon som bokar dig.",
"create_workflow": "Skapa ett arbetsflöde",
"do_this": "Gör detta",
"turn_off": "Stäng av",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Fel vid uppdatering av inställningar",
"personal_cal_url": "Min personliga {{appName}}-URL",
"bio_hint": "Några meningar om dig själv. Detta kommer att visas på din personliga webbsida.",
"timeformat_profile_hint": "Detta är en intern inställning och kommer inte att påverka hur tider visas på offentliga bokningssidor för dig eller någon som bokar dig.",
"delete_account_modal_title": "Radera konto",
"confirm_delete_account_modal": "Är du säker på att du vill radera ditt {{appName}}-konto?",
"delete_my_account": "Radera mitt konto",
@@ -1171,6 +1171,8 @@
"connect_conference_apps": "Anslut konferensappar",
"connect_calendar_apps": "Anslut kalenderappar",
"connect_payment_apps": "Anslut betalningsappar",
"connect_automation_apps": "Anslut automationsappar",
"connect_analytics_apps": "Anslut analysappar",
"connect_other_apps": "Anslut andra appar",
"current_step_of_total": "Steg {{currentStep}} av {{maxSteps}}",
"add_variable": "Lägg till variabel",
@@ -1256,6 +1258,7 @@
"back_to_signin": "Tillbaka för att logga in",
"reset_link_sent": "Återställningslänk skickad",
"password_reset_email": "Ett e-postmeddelande är på väg till {{email}} med anvisningar för att återställa ditt lösenord.",
"password_reset_leading": "Om du inte fick e-postmeddelandet snart, kontrollera att e-postadressen du angav är korrekt, kontrollera din skräppostmapp eller kontakta kundsupport om problemet kvarstår.",
"password_updated": "Lösenord uppdaterat!",
"pending_payment": "Väntande betalning",
"confirmation_page_rainbow": "Tokenskydda din händelse med tokens eller NFT:er på Ethereum, Polygon med mera.",
@@ -1293,7 +1296,7 @@
"fetching_calendars_error": "Det gick inte att hämta dina kalendrar. <1>Försök igen</1> eller kontakta kundtjänst.",
"calendar_connection_fail": "Det gick inte att ansluta kalender",
"booking_confirmation_success": "Bokningsbekräftelsen lyckades",
"booking_rejection_success": "Avvisning av bokning lyckades",
"booking_rejection_success": "Bokningen avvisades",
"booking_confirmation_fail": "Bokningsbekräftelsen misslyckades",
"we_wont_show_again": "Vi kommer inte att visa detta igen",
"couldnt_update_timezone": "Vi kunde inte uppdatera tidszonen",
@@ -1344,28 +1347,28 @@
"yearly": "Årligen",
"checkout": "Kassa",
"your_team_disbanded_successfully": "Ditt team har upplösts",
"error_creating_team": "Fel vid skapandet av team",
"error_creating_team": "Det gick inte att skapa team",
"you": "Du",
"send_email": "Skicka e-post",
"member_already_invited": "Medlemmen har redan blivit inbjuden",
"member_already_invited": "Medlemmen har redan bjudits in",
"enter_email_or_username": "Ange en e-postadress eller ett användarnamn",
"team_name_taken": "Detta namn är redan upptaget",
"team_name_taken": "Det här namnet används redan",
"must_enter_team_name": "Teamnamn måste anges",
"team_url_required": "Team-URL måste anges",
"team_url_taken": "Denna URL är redan upptagen",
"team_url_taken": "Denna URL används redan",
"team_publish": "Publicera team",
"number_sms_notifications": "Telefonnummer (SMS-notiser)",
"attendee_email_workflow": "Deltagarens e-postadress",
"attendee_email_info": "Personens e-postadress för bokning",
"invalid_credential": "Åh nej! Ser ut som om behörigheten löpte ut eller återkallades. Installera om igen.",
"invalid_credential": "Åh nej! Det verkar som om behörigheten löpt ut eller återkallats. Installera om igen.",
"choose_common_schedule_team_event": "Välj ett gemensamt schema",
"choose_common_schedule_team_event_description": "Aktivera den här funktionen om du vill använda ett gemensamt schema mellan värdarna. När den är inaktiverad bokas varje värd enligt sitt standardschema.",
"reason": "Anledning",
"sender_id": "Avsändarens ID",
"sender_id_error_message": "Endast bokstäver, siffror och mellanslag tillåtna (max. 11 tecken)",
"test_routing_form": "Formulär för routingtest",
"test_preview": "Testförhandsgranskning",
"route_to": "Rutt till",
"test_preview_description": "Testa ditt routing-formulär utan att skicka några data",
"reason": "Orsak",
"sender_id": "Avsändar-ID",
"sender_id_error_message": "Endast bokstäver, siffror och mellanslag tillåts (maximalt 11 tecken)",
"test_routing_form": "Testa routingformulär",
"test_preview": "Testa förhandsgranskning",
"route_to": "Dirigera till",
"test_preview_description": "Testa ditt routingformulär utan att skicka data",
"test_routing": "Testa routing"
}
+23 -22
View File
@@ -16,8 +16,8 @@
"event_request_cancelled": "Planlanan etkinliğiniz iptal edildi",
"organizer": "Organizatör",
"need_to_reschedule_or_cancel": "Yeniden planlamanız veya iptal etmeniz mi gerekiyor?",
"cancellation_reason": "İptal nedeni",
"cancellation_reason_placeholder": "Neden iptal ediyorsunuz? (isteğe bağlı)",
"cancellation_reason": "İptal nedeni (isteğe bağlı)",
"cancellation_reason_placeholder": "Neden iptal ediyorsunuz?",
"rejection_reason": "Ret nedeni",
"rejection_reason_title": "Rezervasyon isteği reddedilsin mi?",
"rejection_reason_description": "Rezervasyonu reddetmek istediğinizden emin misiniz? Rezervasyon yaptırmaya çalışan kişiye haber vereceğiz. Aşağıda bir neden sunabilirsiniz.",
@@ -108,7 +108,7 @@
"link_expires": "Not: Süre {{expiresIn}} saat içinde dolacak.",
"upgrade_to_per_seat": "Koltuk Başına Yükselt",
"team_upgrade_seats_details": "Ekibinizdeki {{memberCount}} üyeden {{unpaidCount}} yer ücretsiz. Alan başına aylık {{seatPrice}} $ ile üyeliğinizin tahmini toplam maliyeti aylık {{totalCost}} $'dır.",
"team_upgrade_banner_description": "Yeni ekip planımızı denediğiniz için teşekkür ederiz. \"{{teamName}}\" ekip planınızın yükseltilmesi gerektiğini fark ettik.",
"team_upgrade_banner_description": "Yeni ekip planımızı denediğiniz için teşekkür ederiz. \"{{teamName}}\" adlı ekibinizin yükseltilmesi gerektiğini fark ettik.",
"team_upgrade_banner_action": "Buradan yükseltin",
"team_upgraded_successfully": "Ekibiniz başarıyla yükseltildi!",
"use_link_to_reset_password": "Şifrenizi sıfırlamak için aşağıdaki bağlantıyı kullanın",
@@ -419,7 +419,7 @@
"forgotten_secret_description": "Bu gizli anahtarı kaybettiyseniz veya unuttuysanız değiştirebilirsiniz ancak bu gizli anahtarı kullanan tüm entegrasyonların güncellenmesi gerekecektir",
"current_incorrect_password": "Mevcut şifre hatalı",
"password_hint_caplow": "Büyük ve küçük harf karışımı",
"password_hint_min": "En az 7 karakter uzunluğunda",
"password_hint_min": "En az 8 karakter uzunluğunda",
"password_hint_num": "En az 1 rakam içermelidir",
"invalid_password_hint": "Şifre en az 7 karakter uzunluğunda olmalı, en az bir rakam içermeli ve büyük ve küçük harflerin karışımından oluşmalıdır",
"incorrect_password": "Şifre hatalı.",
@@ -504,7 +504,7 @@
"add_team_members_description": "Ekibinize diğer kişileri davet edin",
"add_team_member": "Ekip üyesi ekle",
"invite_new_member": "Yeni bir ekip üyesi davet et",
"invite_new_member_description": "Not: Bu, <1>aboneliğiniz için ekstra yer ücretine (15 $/ay)</1> mal olacaktır.",
"invite_new_member_description": "Not: Bu, aboneliğiniz için <1>ekstra yer ücretine (15 $/ay)</1> mal olacak.",
"invite_new_team_member": "Ekibinize birini davet edin.",
"change_member_role": "Ekip üyesi rolünü değiştir",
"disable_cal_branding": "{{appName}} markasını devre dışı bırak",
@@ -535,7 +535,7 @@
"open_options": "Seçenekleri aç",
"copy_link": "Etkinlik bağlantısını kopyala",
"share": "Paylaş",
"share_event": "{{appName}} hesabım üzerinden rezervasyon yapmak veya bana bağlantınızı göndermek ister misiniz?",
"share_event": "Cal hesabım üzerinden rezervasyon yapmak veya bana bağlantınızı göndermek ister misiniz?",
"copy_link_team": "Ekip bağlantısını kopyala",
"leave_team": "Ekipten ayrıl",
"confirm_leave_team": "Evet, ekipten ayrıl",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Gelişmiş ayarları göster",
"event_name": "Etkinlik Adı",
"event_name_tooltip": "Takvimlerde görünecek isim",
"meeting_with_user": "{ATTENDEE} ile toplantı",
"meeting_with_user": "{{attendeeName}} ile toplantı",
"additional_inputs": "Ek Girişler",
"additional_input_description": "Rezervasyon onaylanmadan önce planlayıcının ek veri girişi yapması gereklidir",
"label": "Etiket",
@@ -784,7 +784,7 @@
"analytics": "Analizler",
"empty_installed_apps_headline": "Yüklü uygulama yok",
"empty_installed_apps_description": "Uygulamalar, iş akışınızı iyileştirmenize ve planlama sürecinizi önemli ölçüde geliştirmenize olanak tanır.",
"empty_installed_apps_button": "Uygulama Mağazasını Keşfedin ya da aşağıdaki uygulamaları Yükleyin",
"empty_installed_apps_button": "Uygulama Mağazasına göz atın",
"manage_your_connected_apps": "Yüklü uygulamalarınızı yönetin veya ayarları değiştirin",
"browse_apps": "Uygulamalara göz at",
"features": "Özellikler",
@@ -839,6 +839,7 @@
"redirect_success_booking": "Rezervasyonu yönlendir ",
"you_are_being_redirected": "$t(second, {\"count\": {{seconds}} }) içinde {{ url }} adresine yönlendirileceksiniz.",
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
"redirect_url_description": "Başarılı bir rezervasyondan sonra özel bir URL'ye yönlendirin",
"duplicate": "Çoğalt",
"offer_seats": "Yer teklif et",
"offer_seats_description": "Rezervasyonlar için yer teklif edin. Bu işlem, misafirleri ve rezervasyon onaylarını devre dışı bırakır.",
@@ -1107,6 +1108,7 @@
"incorrect_2fa": "İki adımlı kimlik doğrulama kodu hatalı",
"which_event_type_apply": "Bu hangi etkinlik türü için geçerli olacak?",
"no_workflows_description": "İş akışları, etkinliklerinizle ilgili süreçler oluşturmanıza olanak tanıyan bildirimler ve hatırlatıcılar göndermek için basit otomasyona imkanı tanır.",
"timeformat_profile_hint": "Bu dahili bir ayardır ve sizin yaptığınız veya sizin için rezervasyon yapan herhangi birinin genel rezervasyon sayfalarında saatlerin nasıl görüntülendiğini etkilemez.",
"create_workflow": "Bir iş akışı oluşturun",
"do_this": "Bunu yap",
"turn_off": "Kapat",
@@ -1114,7 +1116,6 @@
"error_updating_settings": "Ayarlar güncellenirken bir hata oluştu",
"personal_cal_url": "Kişisel {{appName}} URL'm",
"bio_hint": "Birkaç cümleyle kendinizden bahsedin. Bu, kişisel URL sayfanızda görünecektir.",
"timeformat_profile_hint": "Bu dahili bir ayardır ve sizin yaptığınız veya sizin için rezervasyon yapan herhangi birinin genel rezervasyon sayfalarında saatlerin nasıl görüntülendiğini etkilemez.",
"delete_account_modal_title": "Hesabı Sil",
"confirm_delete_account_modal": "{{appName}} hesabınızı silmek istediğinizden emin misiniz?",
"delete_my_account": "Hesabımı sil",
@@ -1187,7 +1188,6 @@
"additional_notes_info": "Ek rezervasyon notları",
"attendee_name_info": "Rezervasyon yaptıran kişinin adı",
"to": "Kime",
"attendee_required_enter_number": "Bu, katılımcının rezervasyon yapmak için bir telefon numarası girmesini gerektirecektir",
"workflow_turned_on_successfully": "{{workflowName}} iş akışı başarıyla {{offOn}} hale getirildi",
"download_responses": "Yanıtları İndir",
"create_your_first_form": "İlk formunuzu oluşturun",
@@ -1228,7 +1228,7 @@
"exchange_authentication_ntlm": "NTLM kimlik doğrulama",
"exchange_compression": "GZip sıkıştırma",
"routing_forms_description": "Oluşturduğunuz tüm formları ve rotaları burada görebilirsiniz.",
"routing_forms_send_email_owner": "Sahibine E-posta Gönder",
"routing_forms_send_email_owner": "Sahibine E-posta Gönderin",
"routing_forms_send_email_owner_description": "Form gönderildiğinde sahibine bir e-posta gönderir",
"add_new_form": "Yeni form ekle",
"form_description": "Rezervasyon yapan kişiyi yönlendirmek için formunuzu oluşturun",
@@ -1258,6 +1258,7 @@
"back_to_signin": "Oturum açmak için geri dön",
"reset_link_sent": "Sıfırlama bağlantısı gönderildi",
"password_reset_email": "{{email}} adresine şifrenizi sıfırlama talimatlarını içeren bir e-posta gönderildi.",
"password_reset_leading": "Kısa süre içinde bir e-posta almazsanız, lütfen girdiğiniz e-posta adresinin doğru olup olmadığını ve spam klasörünüzü kontrol edin veya sorunun devam etmesi halinde destek ekibi ile iletişime geçin.",
"password_updated": "Şifre güncellendi!",
"pending_payment": "Bekleyen ödeme",
"confirmation_page_rainbow": "Ethereum, Polygon ve diğer token'lar veya NFT ile etkinliğinize token kapısı ekleyin.",
@@ -1311,7 +1312,7 @@
"how_long_after": "Etkinlik sona erdikten ne kadar sonra?",
"no_available_slots": "Uygun yer yok",
"time_available": "Uygun zaman",
"cant_find_the_right_video_app_visit_our_app_store": "Doğru video uygulamasını bulamıyor musunuz? <1>App Store</1> sayfamızı ziyaret edin.",
"cant_find_the_right_video_app_visit_our_app_store": "Doğru video uygulamasını bulamıyor musunuz? <1>Uygulama Mağazamızı</1> ziyaret edin.",
"install_new_calendar_app": "Yeni takvim uygulamasını yükleyin",
"make_phone_number_required": "Rezervasyon etkinliği için telefon numarasını gerekli hale getirin",
"new_event_type_availability": "{{eventTypeTitle}} Müsaitlik Durumu",
@@ -1323,7 +1324,7 @@
"saml_config_updated_successfully": "SAML yapılandırması başarıyla güncellendi",
"saml_configuration": "SAML yapılandırması",
"delete_saml_configuration": "SAML yapılandırmasını sil",
"delete_saml_configuration_confirmation_message": "SAML yapılandırmasını silmek istediğinizden emin misiniz? SAML girişini kullanan ekip üyeleriniz artık {{appName}}'a erişemeyecek.",
"delete_saml_configuration_confirmation_message": "SAML yapılandırmasını silmek istediğinizden emin misiniz? SAML girişini kullanan ekip üyeleriniz artık Cal.com'a erişemeyecek.",
"confirm_delete_saml_configuration": "Evet, SAML yapılandırmasını sil",
"saml_not_configured_yet": "SAML henüz yapılandırılmadı",
"saml_configuration_description": "SAML yapılandırmanızı güncellemek için lütfen Kimlik Sağlayıcınızın gönderdiği SAML meta verilerini aşağıdaki metin kutusuna yapıştırın.",
@@ -1345,28 +1346,28 @@
"monthly": "Aylık",
"yearly": "Yıllık",
"checkout": "Ödeme yap",
"your_team_disbanded_successfully": "Ekibiniz başarıyla tasfiye edildi",
"your_team_disbanded_successfully": "Ekibiniz başarıyla dağıtıldı",
"error_creating_team": "Ekip oluşturulurken bir hata oluştu",
"you": "Siz",
"send_email": "E-posta gönder",
"member_already_invited": "Üye zaten davet edildi",
"enter_email_or_username": "Bir e-posta veya kullanıcı adı girin",
"team_name_taken": "Bu ad zaten alınmış",
"must_enter_team_name": "Bir ekip adı girilmelidir",
"team_url_required": "Bir ekip URL'si girilmelidir",
"team_url_taken": "Bu URL zaten alınmış",
"team_name_taken": "Bu ad zaten kullanılıyor",
"must_enter_team_name": "Ekip adı girilmelidir",
"team_url_required": "Ekip URL'si girilmelidir",
"team_url_taken": "Bu URL zaten kullanılıyor",
"team_publish": "Ekibi yayınla",
"number_sms_notifications": "Telefon numarası (SMS bildirimleri)",
"attendee_email_workflow": "Katılımcı e-postası",
"attendee_email_info": "Rezervasyon yaptıran kişinin e-postası",
"invalid_credential": "Hata! İznin süresi dolmuş veya iptal edilmiş gibi görünüyor. Lütfen yeniden yükleyin.",
"choose_common_schedule_team_event": "Ortak bir program seçin",
"choose_common_schedule_team_event_description": "Toplantı sahipleri arasında ortak bir plan kullanmak istiyorsanız bunu etkinleştirin. Devre dışı bırakıldığında, her toplantı sahibi varsayılan programlarına göre rezervasyon yapabilir.",
"reason": "Neden",
"choose_common_schedule_team_event_description": "Toplantı sahipleri arasında ortak bir plan kullanmak istiyorsanız bunu etkinleştirin. Devre dışı bırakıldığında, her toplantı sahibi varsayılan programına göre rezerve edilir.",
"reason": "Sebep",
"sender_id": "Gönderici Kimliği",
"sender_id_error_message": "Sadece harflere, sayılara ve boşluklara izin verilir (en fazla 11 karakter)",
"test_routing_form": "Yönlendirme Formunu Test Et",
"test_preview": "Test Önizlemesi",
"test_routing_form": "Yönlendirme Formunu Test Etme",
"test_preview": "Ön İzlemeyi Test Et",
"route_to": "Şuraya yönlendir:",
"test_preview_description": "Herhangi bir veri göndermeden yönlendirme formunuzu test edin",
"test_routing": "Yönlendirmeyi Test Et"
@@ -504,7 +504,7 @@
"add_team_members_description": "Запросіть когось у свою команду",
"add_team_member": "Додати учасника команди",
"invite_new_member": "Запросити нового учасника команди",
"invite_new_member_description": "Зверніть увагу: у вашій підписці потрібно буде доплатити за <1>одне додаткове місце (15 дол./міс.)</1>.",
"invite_new_member_description": "Зверніть увагу: у вашій підписці потрібно буде оплатити <1>одне додаткове місце (15 дол. США)</1>.",
"invite_new_team_member": "Запросіть когось у свою команду.",
"change_member_role": "Змініть роль учасника команди",
"disable_cal_branding": "Вимкнути фірмове оформлення {{appName}}",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Показати додаткові параметри",
"event_name": "Тип заходу",
"event_name_tooltip": "Ім’я, яке показуватиметься в календарях",
"meeting_with_user": "Нарада з користувачем {ATTENDEE}",
"meeting_with_user": "Нарада з користувачем {{attendeeName}}",
"additional_inputs": "Додаткові поля введення",
"additional_input_description": "Вимагати від особи, що хоче створити бронювання, надавати додаткові відомості",
"label": "Мітка",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Неправильний код двоетапної автентифікації",
"which_event_type_apply": "До якого типу заходів це застосовуватиметься?",
"no_workflows_description": "Робочі процеси – це проста автоматизація сповіщень і нагадувань, що дає вам змогу будувати процеси, пов’язані з вашими заходами.",
"timeformat_profile_hint": "Це внутрішній параметр, який не вплине на відображення часу на загальнодоступних сторінках бронювання.",
"create_workflow": "Створити робочий процес",
"do_this": "Зробити це",
"turn_off": "Вимкнути",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Помилка оновлення параметрів",
"personal_cal_url": "Моя персональна URL-адреса {{appName}}",
"bio_hint": "Кілька речень про вас. Ця інформація з’явиться на сторінці за вашою URL-адресою.",
"timeformat_profile_hint": "Це внутрішній параметр, який не вплине на відображення часу на загальнодоступних сторінках бронювання.",
"delete_account_modal_title": "Видалення облікового запису",
"confirm_delete_account_modal": "Справді видалити свій обліковий запис {{appName}}?",
"delete_my_account": "Видалити мій обліковий запис",
@@ -1258,6 +1258,7 @@
"back_to_signin": "Повернутися до входу",
"reset_link_sent": "Посилання для скидання надіслано",
"password_reset_email": "Електронний лист з інструкціями зі скидання пароля надіслано на {{email}}.",
"password_reset_leading": "Якщо ви не отримаєте електронний лист найближчим часом, перевірте, чи правильну адресу електронної пошти введено та перевірте папку спаму. Якщо проблема не зникне, зверніться в нашу службу підтримки.",
"password_updated": "Пароль оновлено!",
"pending_payment": "Очікується оплата",
"confirmation_page_rainbow": "Увімкніть доступ до свого заходу тільки для власників звичайних або невзаємозамінних токенів Ethereum, Polygon тощо.",
@@ -1323,7 +1324,7 @@
"saml_config_updated_successfully": "Конфігурацію SAML оновлено",
"saml_configuration": "Конфігурація SAML",
"delete_saml_configuration": "Видаліть конфігурацію SAML",
"delete_saml_configuration_confirmation_message": "Справді конфігурацію SAML? Учасники вашої команди, які використовують вхід через SAML, утратять доступ до {{appName}}.",
"delete_saml_configuration_confirmation_message": "Справді конфігурацію SAML? Учасники вашої команди, які використовують вхід через SAML, утратять доступ до Cal.com.",
"confirm_delete_saml_configuration": "Так, видалити конфігурацію SAML",
"saml_not_configured_yet": "SAML ще не налаштовано",
"saml_configuration_description": "Вставте метадані SAML від свого постачальника посвідчень у текстове поле нижче, щоб оновити конфігурацію SAML.",
@@ -1365,7 +1366,7 @@
"reason": "Причина",
"sender_id": "Ідентифікатор відправника",
"sender_id_error_message": "Дозволяються тільки літери, цифри та пробіли (макс. 11 символів)",
"test_routing_form": "Перевірити форму переспрямування",
"test_routing_form": "Перевірка форми переспрямування",
"test_preview": "Перевірити попередній перегляд",
"route_to": "Куди переспрямувати",
"test_preview_description": "Перевірка вашої форми переспрямування без надсилання даних",
@@ -504,7 +504,7 @@
"add_team_members_description": "Mời người khác tham gia nhóm của bạn",
"add_team_member": "Thêm thành viên nhóm",
"invite_new_member": "Mời một thành viên mới",
"invite_new_member_description": "Lưu ý: Cái này sẽ <1>tốn khoản phụ trội (15$/tháng)</1> cho gói đăng ký của bạn.",
"invite_new_member_description": "Lưu ý: Cái này sẽ <1>tốn phí thêm thành viên (15$/tháng)</1> cho gói đăng ký của bạn.",
"invite_new_team_member": "Mời ai đó vào nhóm của bạn.",
"change_member_role": "Thay đổi vai trò thành viên trong nhóm",
"disable_cal_branding": "Tắt thương hiệu {{appName}}",
@@ -653,7 +653,7 @@
"show_advanced_settings": "Hiển thị cài đặt nâng cao",
"event_name": "Tên sự kiện",
"event_name_tooltip": "Tên sẽ xuất hiện trong lịch",
"meeting_with_user": "Gặp gỡ với {ATTENDEE}",
"meeting_with_user": "Gặp gỡ với {{attendeeName}}",
"additional_inputs": "Trường bổ sung",
"additional_input_description": "Yêu cầu người đặt lịch hãy nhập thông tin đầu vào bổ sung trước khi lịch hẹn được xác nhận",
"label": "Label",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "Sai mã xác thực hai yếu tố",
"which_event_type_apply": "Cái này sẽ áp dụng cho loại sự kiện nào?",
"no_workflows_description": "Tiến độ công việc giúp đơn giản hoá việc tạo tự động chức năng gửi thông báo & lời nhắc, nhằm giúp bạn có thể lập nên các quy trình xử lí xung quanh các sự kiện.",
"timeformat_profile_hint": "Đây là cài đặt nội bộ và sẽ không ảnh hưởng đến cách hiển thị thời gian trên trang lịch hẹn công cộng cho bạn hoặc cho bất kỳ ai đặt lịch hẹn với bạn.",
"create_workflow": "Tạo một tiến độ công việc",
"do_this": "Làm cái này",
"turn_off": "Tắt",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "Lỗi khi cập nhật cài đặt",
"personal_cal_url": "URL {{appName}} cá nhân của tôi",
"bio_hint": "Nói mấy lời về bản thân. Thông tin này sẽ xuất hiện trên trang url cá nhân của bạn.",
"timeformat_profile_hint": "Đây là cài đặt nội bộ và sẽ không ảnh hưởng đến cách hiển thị thời gian trên trang lịch hẹn công cộng cho bạn hoặc cho bất kỳ ai đặt lịch hẹn với bạn.",
"delete_account_modal_title": "Xoá tài khoản",
"confirm_delete_account_modal": "Bạn có chắc chắn muốn xoá tài khoản {{appName}}?",
"delete_my_account": "Xoá tài khoản của tôi",
@@ -1324,7 +1324,7 @@
"saml_config_updated_successfully": "Đã cập nhật cấu hình SAML thành công",
"saml_configuration": "Cấu hình SAML",
"delete_saml_configuration": "Xóa cấu hình SAML",
"delete_saml_configuration_confirmation_message": "Bạn có chắc chắn muốn xóa cấu hình SAML không? Các thành viên trong nhóm của bạn sử dụng thông tin đăng nhập SAML sẽ không thể truy cập vào {{appName}} được nữa.",
"delete_saml_configuration_confirmation_message": "Bạn có chắc chắn muốn xóa cấu hình SAML không? Các thành viên trong nhóm của bạn sử dụng thông tin đăng nhập SAML sẽ không thể truy cập vào Cal.com được nữa.",
"confirm_delete_saml_configuration": "Có, xóa cấu hình SAML",
"saml_not_configured_yet": "SAML chưa được định cấu hình",
"saml_configuration_description": "Vui lòng dán metadata SAML từ Nhà cung cấp danh tính của bạn vào hộp văn bản bên dưới để cập nhật cấu hình SAML của bạn.",
@@ -1361,7 +1361,7 @@
"attendee_email_workflow": "Email người tham dự",
"attendee_email_info": "Email người tham gia lịch hẹn",
"invalid_credential": "Ôi không! Có vẻ như quyền đã hết hạn hoặc đã bị thu hồi. Vui lòng cài đặt lại.",
"choose_common_schedule_team_event": "Chọn một lịch thông thường",
"choose_common_schedule_team_event": "Chọn một lịch chung",
"choose_common_schedule_team_event_description": "Bật cái này nếu bạn muốn dùng lịch thông thường giữa các chủ sự kiện. Khi tắt đi, mỗi chủ sự kiện sẽ được đặt lịch theo lịch mặc định của họ.",
"reason": "Lý do",
"sender_id": "ID người gửi",
@@ -16,8 +16,8 @@
"event_request_cancelled": "您预约的活动已被取消",
"organizer": "组织者",
"need_to_reschedule_or_cancel": "需要重新安排还是取消?",
"cancellation_reason": "取消原因",
"cancellation_reason_placeholder": "您为什么要取消?(选填)",
"cancellation_reason": "取消原因(选填)",
"cancellation_reason_placeholder": "您为什么要取消?",
"rejection_reason": "拒绝原因",
"rejection_reason_title": "拒绝预约请求?",
"rejection_reason_description": "您确定要拒绝预约吗?我们会通知试图预约的人,您可以在下面解释原因。",
@@ -419,7 +419,7 @@
"forgotten_secret_description": "如果您丢失或忘记此密码,您可以对其进行更改,但请注意,使用此密码的所有集成都需要更新",
"current_incorrect_password": "当前密码不正确",
"password_hint_caplow": "大写和小写字母混合",
"password_hint_min": "至少 7 个字符长",
"password_hint_min": "至少 8 个字符长",
"password_hint_num": "包含至少 1 个数字",
"invalid_password_hint": "密码必须是至少 7 个字符长,包含至少一个数字,并且是大写和小写字母混合",
"incorrect_password": "密码不正确。",
@@ -504,7 +504,7 @@
"add_team_members_description": "邀请其他人加入您的团队",
"add_team_member": "添加团队成员",
"invite_new_member": "邀请新的团队成员",
"invite_new_member_description": "注意:这将在您的订阅的基础上<1>收取一个额外位置的费用(15 美元/月)</1>",
"invite_new_member_description": "注意:这将在您订阅的基础上<1>收取一个额外位置的费用(15 美元/月)</1>",
"invite_new_team_member": "邀请某人加入您的团队。",
"change_member_role": "更改团队成员角色",
"disable_cal_branding": "禁用 {{appName}} 品牌标志",
@@ -601,7 +601,7 @@
"monthly_other": "月",
"yearly_one": "年",
"yearly_other": "年",
"plus_more": "另外 {{count}}",
"plus_more": "另外 {{count}} 个",
"max": "最大",
"single_theme": "主题",
"brand_color": "品牌颜色",
@@ -653,7 +653,7 @@
"show_advanced_settings": "显示高级设置",
"event_name": "活动名称",
"event_name_tooltip": "在日历中显示的名称",
"meeting_with_user": "与 {ATTENDEE} 的会议",
"meeting_with_user": "与 {{attendeeName}} 的会议",
"additional_inputs": "更多输入框",
"additional_input_description": "在确认预约之前,需要预约者输入额外的信息",
"label": "标签",
@@ -772,14 +772,19 @@
"no_category_apps_description_calendar": "添加日历应用以检查冲突,防止重复预约",
"no_category_apps_description_conferencing": "尝试添加会议应用以整合与客户的视频通话",
"no_category_apps_description_payment": "添加支付应用以简化您和客户之间的交易",
"no_category_apps_description_analytics": "为您的预约页面添加分析应用",
"no_category_apps_description_automation": "添加要使用的自动化应用",
"no_category_apps_description_other": "添加任何其他类型的应用以执行各种操作",
"installed_app_calendar_description": "设置日历以检查冲突,防止重复预约。",
"installed_app_conferencing_description": "添加您喜欢的视频会议应用以用于开会",
"installed_app_payment_description": "配置向客户收费时要使用的支付处理服务。",
"installed_app_analytics_description": "配置将用于您的预约页面的分析应用",
"installed_app_other_description": "所有属于其他类别的已安装应用。",
"installed_app_automation_description": "配置要使用的自动化应用",
"analytics": "分析",
"empty_installed_apps_headline": "未安装任何应用",
"empty_installed_apps_description": "通过应用可以显著增强工作流程和改善日程安排生活。",
"empty_installed_apps_button": "浏览 App Store 或从以下应用中选择安装",
"empty_installed_apps_button": "浏览 App Store",
"manage_your_connected_apps": "管理已安装的应用或更改设置",
"browse_apps": "浏览应用",
"features": "功能",
@@ -1103,6 +1108,7 @@
"incorrect_2fa": "两步验证代码不正确",
"which_event_type_apply": "这将适用于哪种活动类型?",
"no_workflows_description": "工作流程可实现简单的自动化来发送通知和提醒,让您可以围绕活动构建流程。",
"timeformat_profile_hint": "这是一项内部设置,不会影响公开预约页面上向您或向预约您的任何人显示时间的方式。",
"create_workflow": "创建工作流程",
"do_this": "执行此操作",
"turn_off": "关闭",
@@ -1110,7 +1116,6 @@
"error_updating_settings": "更新设置时出错",
"personal_cal_url": "我的个人 {{appName}} URL",
"bio_hint": "请写一段简单的自我介绍,该介绍将会展示在您的个人 url 页面上。",
"timeformat_profile_hint": "这是一项内部设置,不会影响公开预约页面上向您或向预约您的任何人显示时间的方式。",
"delete_account_modal_title": "删除账户",
"confirm_delete_account_modal": "您确定要删除您的 {{appName}} 账户吗?",
"delete_my_account": "删除我的账户",
@@ -1253,6 +1258,7 @@
"back_to_signin": "返回以登录",
"reset_link_sent": "重置链接已发送",
"password_reset_email": "正在将包含重设密码说明的电子邮件发送至 {{email}}。",
"password_reset_leading": "如果您没有很快收到该电子邮件,请检查您输入的电子邮件地址是否正确,如果问题仍然存在,请检查垃圾邮件文件夹或联系支持。",
"password_updated": "密码已更新!",
"pending_payment": "待付款",
"confirmation_page_rainbow": "使用 Ethereum、Polygon 等平台的代币或 NFT 对您的活动进行代币门控。",
@@ -1362,7 +1368,7 @@
"sender_id_error_message": "只允许字母、数字和空格(最多 11 个字符)",
"test_routing_form": "测试途径表格",
"test_preview": "测试预览",
"route_to": "途径",
"route_to": "根据途径找到",
"test_preview_description": "测试途径表格而不提交任何数据",
"test_routing": "测试途径"
}
@@ -653,7 +653,7 @@
"show_advanced_settings": "顯示進階設定",
"event_name": "活動名稱",
"event_name_tooltip": "會顯示在行事曆上的名字",
"meeting_with_user": "與 {ATTENDEE} 的會議",
"meeting_with_user": "與 {{attendeeName}} 的會議",
"additional_inputs": "額外輸入欄",
"additional_input_description": "確認預約前,預約者需先輸入額外的內容",
"label": "標籤",
@@ -1108,6 +1108,7 @@
"incorrect_2fa": "兩階段認證代碼不正確",
"which_event_type_apply": "這將套用哪一種活動類型?",
"no_workflows_description": "工作流程可啟用簡易的自動化流程來傳送通知與提醒,讓您為活動打造流程。",
"timeformat_profile_hint": "此為內部設定,您或要預約您時間的使用者在公開預約頁面上看見的時間並不會受到影響。",
"create_workflow": "建立工作流程",
"do_this": "執行此操作",
"turn_off": "關閉",
@@ -1115,7 +1116,6 @@
"error_updating_settings": "更新設定時發生錯誤",
"personal_cal_url": "我的個人 {{appName}} 網址",
"bio_hint": "一些關於自己的句子,會顯示在個人網址頁面。",
"timeformat_profile_hint": "此為內部設定,您或要預約您時間的使用者在公開預約頁面上看見的時間並不會受到影響。",
"delete_account_modal_title": "刪除帳號",
"confirm_delete_account_modal": "確定要刪除您的 {{appName}} 的帳號嗎?",
"delete_my_account": "刪除我的帳號",
@@ -1258,6 +1258,7 @@
"back_to_signin": "返回登入",
"reset_link_sent": "重設連結已傳送",
"password_reset_email": "含有密碼重設說明的電子郵件已在前往 {{email}} 的路上。",
"password_reset_leading": "如果您稍後還是沒有收到電子郵件,請檢查您輸入的電子郵件地址是否正確,並查看您的垃圾郵件資料夾;若問題持續發生,請聯絡支援團隊。",
"password_updated": "密碼已更新!",
"pending_payment": "待付款",
"confirmation_page_rainbow": "使用 Ethereum、Polygon 等的 Token 或 NFT 來以代幣管制您的活動。",
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

+2
View File
@@ -23,6 +23,7 @@
"deploy": "turbo run deploy",
"dev:all": "turbo run dev --scope=\"@calcom/web\" --scope=\"@calcom/website\" --scope=\"@calcom/console\"",
"dev:api": "turbo run dev --scope=\"@calcom/web\" --scope=\"@calcom/api\"",
"dev:api:console": "turbo run dev --scope=\"@calcom/web\" --scope=\"@calcom/api\" --scope=\"@calcom/console\"",
"dev:console": "turbo run dev --scope=\"@calcom/web\" --scope=\"@calcom/console\"",
"dev:swagger": "turbo run dev --scope=\"@calcom/api\" --scope=\"@calcom/swagger\"",
"dev:website": "turbo run dev --scope=\"@calcom/web\" --scope=\"@calcom/website\"",
@@ -59,6 +60,7 @@
},
"devDependencies": {
"@snaplet/copycat": "^0.3.0",
"@types/dompurify": "^2.4.0",
"@types/jest": "^28.1.7",
"dotenv-checker": "^1.1.5",
"husky": "^8.0.1",
@@ -21,7 +21,7 @@ export default function OmniInstallAppButton({ appId, className }: { appId: stri
//TODO: viewer.appById might be replaced with viewer.apps so that a single query needs to be invalidated.
utils.viewer.appById.invalidate({ appId });
utils.viewer.apps.invalidate({ extendsFeature: "EventType" });
if (data.setupPending) return;
if (data?.setupPending) return;
showToast(t("app_successfully_installed"), "success");
},
onError: (error) => {
@@ -18,13 +18,14 @@ type CustomUseMutationOptions =
| Omit<UseMutationOptions<unknown, unknown, unknown, unknown>, "mutationKey" | "mutationFn" | "onSuccess">
| undefined;
type AddAppMutationData = { setupPending: boolean } | void;
type UseAddAppMutationOptions = CustomUseMutationOptions & {
onSuccess: (data: { setupPending: boolean }) => void;
onSuccess: (data: AddAppMutationData) => void;
};
function useAddAppMutation(_type: App["type"] | null, options?: UseAddAppMutationOptions) {
const mutation = useMutation<
{ setupPending: boolean },
AddAppMutationData,
Error,
{ type?: App["type"]; variant?: string; slug?: string; isOmniInstall?: boolean } | ""
>(async (variables) => {
@@ -62,6 +63,7 @@ function useAddAppMutation(_type: App["type"] | null, options?: UseAddAppMutatio
if (!isOmniInstall) {
gotoUrl(json.url, json.newTab);
return;
}
// Skip redirection only if it is an OmniInstall and redirect URL isn't of some other origin
@@ -71,6 +73,7 @@ function useAddAppMutation(_type: App["type"] | null, options?: UseAddAppMutatio
if (externalUrl) {
// TODO: For Omni installation to authenticate and come back to the page where installation was initiated, some changes need to be done in all apps' add callbacks
gotoUrl(json.url, json.newTab);
return;
}
return { setupPending: externalUrl || json.url.endsWith("/setup") };

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