Compare commits

...
60 Commits
Author SHA1 Message Date
GitHub Actions a5639a8290 chore: release v5.2.17
Post release / release (push) Canceled after 0s
2025-05-14 23:10:04 +00:00
Anik Dhabal Babu 44d9c4bcc5 fix: Seated events and round robin - all round robin hosts are being added to the calendar event (#21317)
* fix: add org email into ics

* fix: Seated events and round robin - all round robin hosts are being added to the calendar event

* added test
2025-05-14 22:52:26 +00:00
Anik Dhabal Babu 1b586560f8 fix: userprimaryemail not updating (#21318) 2025-05-14 22:01:43 +00:00
Benny Joo e082cc7d3d refactor: Handle apiv2 team slots in useSchedule hook (#21309) 2025-05-14 10:12:09 -07:00
Keith Williams d411e70ea3 chore: Add @calcom/Consumer as CODEOWNER for ui-playground (#21312) 2025-05-14 16:17:13 +00:00
Keith Williams 8dffa4d371 chore: Back down @calcom/Consumer CODEOWNERS (#21311) 2025-05-14 16:09:58 +00:00
Eunjae Lee b7bf6e80e6 fix: case insensitive filter for attendees on /bookings (#21302) 2025-05-14 15:51:22 +00:00
Eunjae Lee 2a93e661f9 feat: add denormalized table for RoutingFormResponse view (#21009)
* feat: add denormalized table for RoutingFormResponse

* WIP

* improve

* update schema

* update schema

* improvement

* fix type of bookingStatus

* cascading DELETE

* split update trigger

* denormalize fields into a separate table

* error handling

* address feedback

* fix

* fix constraints and relations

* delete rows when rows are deleted in the joined tables

* add tests and make booking nullable in RoutingFormResponseDenormalized

* add tests

* update test

* use e2e tests instead

* fix type error

* address feedback

* move e2e to integration test

* add missing tests

* move index migration to another file

* clean up migrations
2025-05-14 10:41:28 -04:00
Lauris Skraucis bfb51b82b2 fix: useLocale hook is being used outside of App Router & time zone dropdown timeout (#21306) 2025-05-14 14:07:35 +00:00
Keith Williams f50be6c08b chore: Lower number of errors sent to Sentry (#21300) 2025-05-14 12:21:13 +00:00
Hariom Balhara df75df7008 fix: DelegationCredential - Duplicate GoogleMeet and unnecessary serviceAccount key access (#21269)
* Remove unused return statement

* Fix return from fn instead of continuing the loop

* Ensure userId is set for existing records on update

* ensure that serviceAccountKey is only retrieved whenb assked
2025-05-14 09:49:47 +00:00
Eunjae Lee deb55c0536 fix: sticky columns in DataTable (#21278)
* fix: sticky columns in DataTable

* update th color

* remove rounded corner

* border change
2025-05-14 08:34:50 +00:00
Lauris Skraucis 7fc11ff341 fix: v2 bookings with sms reminders (#21191)
* fix: v2 bookings with sms reminders

* fix: falsey booking field values
2025-05-14 10:25:29 +03:00
Lauris Skraucis 1a70f83d34 fix: v2 sentry errors (#21214)
* fix: PATCH, POST event-types Address location must have an address

* fix: GET event-types Address location must have an address

* fix: POST /v2/bookings Address location must have an address

* refactor: GET /v2/slots Invalid time range given.

* fix: POST v2/event-types Cannot read properties of null (reading 'type')

* fix: POST /v2/bookings/:bookingUid/mark-absent Failed to update no-show status
2025-05-14 10:11:35 +03:00
39077a08f1 docs: correct documentation for slot format in 2024-09-04 API (#21196)
Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2025-05-14 06:57:41 +00:00
Benny Joo 9a671f9063 fix: add arg validation to ensureValidPhoneNumber (#21259) 2025-05-13 18:57:00 -07:00
3bc9fa11d0 chore: remove @calcom/lib barrel file (#21267)
* refactor: replace imports from @calcom/lib barrel file with direct imports

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: add deprecated barrel file with warning to support tests

Co-Authored-By: benny@cal.com <benny@cal.com>

* remove barrel file

* fix: restore barrel file with deprecation notice and add CreditType enum export

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: add CreditType enum definition to barrel file

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: add mock for CreditType enum in credit-service test

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: use importOriginal in CreditType enum mock

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: remove barrel file completely

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: restore barrel file with deprecation notice to support tests

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: update test-setup to use direct import from @calcom/ui/classNames

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: completely remove barrel file

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: update package.json to remove references to index.ts

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: remove main and types fields from package.json

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: restore barrel file with deprecation notice to support tests

Co-Authored-By: benny@cal.com <benny@cal.com>

* remove barrel file

* fix

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: benny@cal.com <benny@cal.com>
Co-authored-by: hbjORbj <sldisek783@gmail.com>
2025-05-13 21:55:58 -04:00
Joe Au-Yeung 7e699ab810 fix: Salesforce - fix option to create contact if account exists (#21288)
* Add `onCheckedChange`

* Remove console.logs
2025-05-13 22:17:57 +00:00
GitHub Actions 1bd17ba365 chore: release v5.2.16
Post release / release (push) Canceled after 0s
2025-05-13 21:54:23 +00:00
Benny Joo 4d5246cf4d chore: Remove bcryptjs dependency from @calcom/lib (#21286)
* remove bcryptjs lib

* update yarn lock
2025-05-13 22:41:42 +01:00
devin-ai-integration[bot]andzomars@cal.com 5d988453fa fix: add --ignore-missing flag to sentry-cli set-commits command (#21285)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: zomars@cal.com <zomars@cal.com>
2025-05-13 20:48:14 +00:00
JamieandTushar Bhatt 85b9782264 fix: use actual event duration mins for templated event names (#21263)
* fix: use actual event duration mins for templated names

* fix: use actual event duration mins for templated event name

* fix: use actual event duration for calendar links

* fix: use actual event duration for round robin reassignment

* chore: rm console logs

* fix: use actual event duration for emails and rr reassignment

* chore: remove unnecessary dayjs calls

---------

Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
2025-05-13 18:51:43 +00:00
Udit Takkar c2b091aa67 perf: don't load ring.mp3 on booking page (#21272) 2025-05-13 16:48:14 +00:00
Farhan Javed 7093e1e4c6 fix: corrected path for cron in documentation (#21274)
* path-fix

* path-update2
2025-05-13 16:02:40 +00:00
ead42c1a9c feat: SMS credits for free users (#21245)
* Add credits section to billing

* create seperate router for credits

* add stripe checkout session

* schema changes + code improvements

* rename to creditBalance

* custom quantify input with error message

* add checkout session completed webhook endpoint

* fix typo

* UI fixes

* add payCredits handler

* add error toast message

* allow scheduling sms up as close to 15 minutes in the future

* schedule at most 2 hours in advance

* webhook to pay for sent sms

* continued work on twilio callback

* code clean up

* further implementation for credit handling

* add migration

* object as param for scheduleSMS

* object as param for sendSMS

* fix TrpcSessionUser imports

* fix imports

* add db changes

* add cron job for price setting

* twilio status callback to create expense log

* remove unused code

* set up low credit balance email

* fixes for buying credits

* fixes in api/twilio/webhook

* add test to save credits to credits balance

* fix typos

* add new helper function chargeCredits

* expand twilioProvider

* fix type errors

* adjust tests

* type errors

* clean up

* clean up

* fix subscription active check

* remove some user/org related code

* more changes to remove user/org support

* send emails seperatly to admins

* fixes for team billing page

* fix stripe success url

* fixes to creating expense log

* email imrovements and more

* get monthly team price from stripe

* fix import

* fix monthly credits calculation

* finsih low credit balance warning email

* credit balance limit reached email

* create CreditService

* cancel SMS and send as email instead

* add messageDispatcher

* fix type error

* fix type error

* fix type error

* fix import

* fix unit test

* clean up twilioProvider

* clean up chckSmsPrices/route

* add missing translations

* add skeleton loader

* add admin check to get handler

* code clean up + fixes

* improve scheduling with fallback

* fix type error

* add bookingUid to handleSendingSMS

* add unit tests for creditService

* add more tests to credit-service.test.ts

* add test for cancelScheduledMessagesAndScheduleEmails

* fix test and type error

* add back resolve

* fix empty resolve

* adjust limitReachedAt logic

* address mrge comment on styling

* add getAdminMembership to repository

* twilio/webhook clean up (feedback)

* feedback - clean up

* remove todo comment

* clean up twilio/webhook

* code clean up

* add use client

* add createOneTimeCheckout to stripe service

* refactor repository pattern

* small fixes + clean up

* fix type error

* add missing import

* fix hasAvailableCredits for user

* force-dynamic

* rename credits to creditBalance

* fix stripe import

* remove not needed code

* fix e2e tests

* improve low balance warning email

* dynamic-import CreditService

* index.ts

* add user logic checkSmsPrices endpoint

* fix e2e tests

* remove dynamic import CreditService

* Revert "remove dynamic import CreditService"

This reverts commit e272978a7ff3fc5a04139e656c9f8d2c84a40dda.

* no need to dynamic-import credit service

* Revert "no need to dynamic-import credit service"

This reverts commit ba5ae488d08979a65fb47b5d0722cda9f45d6ea0.

* fix twilio webhook

* add userId support in checkout.session.completed

* clean up code

* only select id in getAdminMembership

* revert billing/package.json

* fix type checks

* fix type checks

* adjust hasAvailableCredits function

* fixes for checkout sessioned completed

* add UI for user

* fix type errors

* adds requires credits badge

* remove team check from update.handler

* clean up inlcude statements

* fix credit-service tests

* add tests

* fix type errors

* fix type errors

* fix and add tests

* imrove badge

* code clean up

* add reminderScheduler test

* add additional credits as title

* fixes for warningSentAt and limitReachedAt

* mock stripe

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: hbjORbj <sldisek783@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2025-05-13 15:55:19 +02:00
Somay Chauhan e669996442 fix: Inconsistent Location Handling for Event Types API - Map office365-video to msteams in Validation Handling (#21255)
* refactor: rename office365-video to msteams across API and platform code

* Revert "refactor: rename office365-video to msteams across API and platform code"

This reverts commit 7a823ab6aa7ecd739da941d3b315735220bd99de.

* Fix: inconsistency in default location values for create and update event-types
2025-05-13 13:04:03 +00:00
Somay Chauhan 0e6f365dc2 fix: dont default to cal-video in case locations is not provided (#21256) 2025-05-13 09:57:16 +00:00
devin-ai-integration[bot]andbenny@cal.com 08b501625d chore: remove @calcom/lib/server/queries barrel file (#21268)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: benny@cal.com <benny@cal.com>
2025-05-13 05:18:00 -04:00
Benny Joo b89ff43921 chore: Remove @calcom/lib/schedules barrel file (#21266) 2025-05-13 05:17:01 -04:00
fadfba8830 feat: Credit System (SMS) (#20126)
* Add credits section to billing

* create seperate router for credits

* add stripe checkout session

* schema changes + code improvements

* rename to creditBalance

* custom quantify input with error message

* add checkout session completed webhook endpoint

* fix typo

* UI fixes

* add payCredits handler

* add error toast message

* allow scheduling sms up as close to 15 minutes in the future

* schedule at most 2 hours in advance

* webhook to pay for sent sms

* continued work on twilio callback

* code clean up

* further implementation for credit handling

* add migration

* object as param for scheduleSMS

* object as param for sendSMS

* fix TrpcSessionUser imports

* fix imports

* add db changes

* add cron job for price setting

* twilio status callback to create expense log

* remove unused code

* set up low credit balance email

* fixes for buying credits

* fixes in api/twilio/webhook

* add test to save credits to credits balance

* fix typos

* add new helper function chargeCredits

* expand twilioProvider

* fix type errors

* adjust tests

* type errors

* clean up

* clean up

* fix subscription active check

* remove some user/org related code

* more changes to remove user/org support

* send emails seperatly to admins

* fixes for team billing page

* fix stripe success url

* fixes to creating expense log

* email imrovements and more

* get monthly team price from stripe

* fix import

* fix monthly credits calculation

* finsih low credit balance warning email

* credit balance limit reached email

* create CreditService

* cancel SMS and send as email instead

* add messageDispatcher

* fix type error

* fix type error

* fix type error

* fix import

* fix unit test

* clean up twilioProvider

* clean up chckSmsPrices/route

* add missing translations

* add skeleton loader

* add admin check to get handler

* code clean up + fixes

* improve scheduling with fallback

* fix type error

* add bookingUid to handleSendingSMS

* add unit tests for creditService

* add more tests to credit-service.test.ts

* add test for cancelScheduledMessagesAndScheduleEmails

* fix test and type error

* add back resolve

* fix empty resolve

* adjust limitReachedAt logic

* address mrge comment on styling

* add getAdminMembership to repository

* twilio/webhook clean up (feedback)

* feedback - clean up

* remove todo comment

* clean up twilio/webhook

* code clean up

* add use client

* add createOneTimeCheckout to stripe service

* refactor repository pattern

* small fixes + clean up

* fix type error

* add missing import

* fix hasAvailableCredits for user

* force-dynamic

* rename credits to creditBalance

* fix stripe import

* remove not needed code

* fix e2e tests

* improve low balance warning email

* dynamic-import CreditService

* index.ts

* fix e2e tests

* remove dynamic import CreditService

* Revert "remove dynamic import CreditService"

This reverts commit e272978a7ff3fc5a04139e656c9f8d2c84a40dda.

* no need to dynamic-import credit service

* Revert "no need to dynamic-import credit service"

This reverts commit ba5ae488d08979a65fb47b5d0722cda9f45d6ea0.

* only select id in getAdminMembership

* revert billing/package.json

* fix type checks

* fix type checks

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: hbjORbj <sldisek783@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
2025-05-13 09:11:44 +02:00
Benny Joo 43be9bd6a8 fix: localStorage error in AvailableTimeSlots (#21265) 2025-05-13 11:31:25 +05:30
Hariom Balhara caf184151d fix: Credentials cron for DelegationCredential not working (#21239)
* Remove unused return statement

* Fix return from fn instead of continuing the loop

* Ensure userId is set for existing records on update
2025-05-13 09:00:08 +05:30
GitHub Actions 22e3338709 chore: release v5.2.15
Post release / release (push) Canceled after 0s
2025-05-12 23:05:02 +00:00
048e56806c feat: useApiV2AvailableSlots (#21138)
* feat: useApiV2AvailableSlots

* feat: useApiV2AvailableSlots

* fix type check

* remove log

* fix unit tests

* simplify

* feat: add missing params to the slots endpoint

* updated documentation

* _shouldServeCache is correct

* fix types

* fix enabled prop

* fix type

* add embedConnectVersion to query key

* add teamId to slot type

* fix

* add fallback to trpc query if apiv2 fails

* add comment

* remove logs

* fix

* refactor: default to isTeamEvent in query params

* fix: only return v2 slots once fetch is success

* fix last e2e failing test

* add feature flag

* add migration sql

* Update packages/prisma/migrations/20250512153630_add_use_api_v2_for_team_slots_feature_flag/migration.sql

---------

Co-authored-by: hbjORbj <sldisek783@gmail.com>
Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com>
Co-authored-by: supalarry <laurisskraucis@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
2025-05-12 20:48:29 +00:00
Calcom BotandLingo.dev ade64c0d09 feat: update translations via @LingoDotDev (#20599)
Co-authored-by: Lingo.dev <support@lingo.dev>
2025-05-12 14:20:33 -04:00
Benny Joo 5beb2943b9 fix: localStorage error in useTheme (#21258) 2025-05-12 17:59:37 +00:00
Omar López b3d3cb1dee refactor: Uses withReporting to force named functions for tracing (#21219) 2025-05-12 13:22:52 -04:00
devin-ai-integration[bot] 79d695236f test: add e2e tests for filter segment functionality (#21160) 2025-05-12 12:52:54 -04:00
luzpazandAlex van Andel 2dbbdc21f2 fix: typos in apps/ui-playground (#21223)
Found via codespell

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2025-05-12 08:49:35 +00:00
luzpazandAlex van Andel e4254ef7cc fix: typos in apps/web (#21224)
Found via codespell

Co-authored-by: Alex van Andel <me@alexvanandel.com>
2025-05-12 08:47:02 +00:00
luzpazandUdit Takkar 7f9709bdaa fix: typos in packages/ (#21216)
Found via codespell

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2025-05-12 09:30:43 +01:00
Morgan 77054d92df feat: add pagination to get bookings endpoints [v2] (#21173)
* feat: add pagination to get bookings endpoints [v2]

* add decorators for pagination

* fix: ensure correct values

* code review comment

* fixup! code review comment
2025-05-12 10:09:56 +02:00
Benny Joo 1277f5e9f7 chore: migrate signup API to appDir (#19975)
* refactor calcomHandler

* refactor selfHostedHandler

* fix

* migrate to appdir

* fix type checks
2025-05-12 09:38:03 +02:00
Rajiv SahalandMorgan 109c303b60 feat: active managed user billing (v1) (#20499)
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
2025-05-10 16:13:09 +00:00
jen chanandamrit a52a0e90e7 feat: add autocomplete to login and signup (#21065)
Co-authored-by: amrit <iamamrit27@gmail.com>
2025-05-10 17:52:27 +02:00
+25 558140fdd6 fix: sentry builds (#20310)
* fix: sentry builds

* Update yarn.lock

* Upgrade Sentry

* Breaking changes

* Discard changes to apps/web/modules/connect-and-join/connect-and-join-view.tsx

* Discard changes to apps/web/modules/signup-view.tsx

* Discard changes to packages/app-store/make/pages/setup/index.tsx

* Discard changes to packages/app-store/zapier/pages/setup/index.tsx

* Discard changes to packages/emails/src/templates/AdminOrganizationNotificationEmail.tsx

* Discard changes to packages/features/eventtypes/components/tabs/apps/EventAppsTab.tsx

* Discard changes to packages/features/eventtypes/components/tabs/assignment/EventTeamAssignmentTab.tsx

* Discard changes to packages/features/eventtypes/components/tabs/webhooks/EventWebhooksTab.tsx

* Discard changes to packages/features/eventtypes/components/tabs/advanced/DisableAllEmailsSetting.tsx

* Discard changes to packages/emails/src/templates/BrokenIntegrationEmail.tsx

* Discard changes to packages/emails/src/templates/OrganizationCreationEmail.tsx

* Discard changes to packages/emails/src/templates/SlugReplacementEmail.tsx

* Discard changes to packages/emails/src/templates/TeamInviteEmail.tsx

* Discard changes to packages/features/bookings/Booker/components/BookEventForm/BookEventForm.tsx

* Discard changes to packages/features/bookings/Booker/components/OutOfOfficeInSlots.tsx

* Discard changes to packages/features/ee/teams/components/MemberInvitationModal.tsx

* Discard changes to packages/features/eventtypes/components/EditWeightsForAllTeamMembers.tsx

* Discard changes to packages/features/eventtypes/components/Locations.tsx

* Discard changes to packages/features/eventtypes/components/dialogs/ManagedEventDialog.tsx

* Discard changes to packages/features/eventtypes/components/tabs/advanced/RequiresConfirmationController.tsx

* Discard changes to packages/features/eventtypes/components/tabs/workflows/EventWorkfowsTab.tsx

* Discard changes to packages/features/settings/BookerLayoutSelector.tsx

* Discard changes to packages/features/settings/outOfOffice/OutOfOfficeEntriesList.tsx

* chore: upgrade dependencies and improve Sentry configuration

- Upgrade @sentry/nextjs to 9.13.0

- Upgrade next.js to 15.3.0

- Upgrade sharp to 0.34.1

- Update Sentry configuration files

- Add Sentry example files for testing

* chore: upgrade dependencies

- Upgrade next.js to 15.3.0

- Upgrade sharp to 0.34.1

* Update next.config.js

* Discard changes to packages/platform/atoms/connect/apple/AppleConnect.tsx

* build(apps/web): enabled Sentry source maps uploading.

* Create sentry-sourcemaps.yml

* fix: buggy skeleton rendering for month view (#20744)

* fix: trigger lingo.dev by removing duplicate value

* fix: buggy skeleton monthly view

* fix: Wrong schedule ID set for child managed event (#20745)

* fix: wrong schule id set for managed event

* Update handleChildrenEventTypes.ts

* feat: v2 book team events using teamSlug & eventTypeSlug (#20585)

* feat: v2 book team events using teamSlug & eventTypeSlug

* fix: tests

* fix: failing e2e test (#20751)

* feat: filter users by assigned attribute options (#20659)

* feat: assigned attributes options base

* feat: assigned attributes options base e2e

* feat: filter assigned options by other assigned options

* feat: filter assigned options by other assigned options

* fixup! feat: filter assigned options by other assigned options

* feat: get org users by assigned attributes

* adding missing input file

* push generated docs

* feat: add filter org users by teamIds

* feat: add filter assigned attribute options by teamIds

* chore; update doc

* chore: remove console log

* chore: minor e2e fix

* chore: minor e2e fix

* chore: improve docs

* fix: assigned options by teamIds + optionIds

* fix: Admin/owner unable to confirm managed bookings (#20743)

* fix: Admin/owner can't confirm managed booking

* Update confirm.handler.ts

* fix: v2 automatic round robin reassign error message (#20755)

* fix: return react fragment from all layout.tsx

* feat: add guards to stripe teams controller (#20540)

* feat: add guards to stripe teams controller

* remove logs and comments

* fix return type status

* refactor: move PlatformSubscription to a dedicated module

* reroute to `organizations/stripe/save` for teams

* fix: type errors

* feat: fixed it for conferencing apps

* feat: Add error handling and fallback URL support in Stripe callback

* Refactor OAuth callback handling and move token validation to service layer

* Add documentation for OAuth callback proxying in conferencing and stripe controllers

* Move OAuthCallbackState type from organizations to stripe service module

* chore: release v5.2.2

* perf: slim down middleware matcher (#20735)

* wip

* wip

* refactor

* add pathname

* fix

* fix: manually construct pathname for metadata functions

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: add pathname parameter to all metadata functions

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix: add pathname parameter to remaining metadata functions

Co-Authored-By: benny@cal.com <benny@cal.com>

* fix

* fix

* fix type checks

* Refactor

* fix

* fix

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: benny@cal.com <benny@cal.com>

* Skip flakey tests (#20761)

* Write UTM params to Salesforce (#20759)

* chore: Add consent message when SMS workflows are related (#20741)

* Add consent message

* Add consent message if using SMS workflow

* Skip flakey tests

* Revert "Skip flakey tests"

This reverts commit 3bd6f3fd71469df4dbd67b69b8e17011657df9d8.

* chore: Remove verbose logging (#20732)

* fix: offer seats broken (#20758)

* Remove trailing } from utm param (#20763)

* fix: only managed users assignable to managed team event (#20754)

* fix: only managed users assignable to managed team event

* chore: bump platform libraries

* feat: make skeleton for booking embed accurate (#20765)

* fix: trigger lingo.dev by removing duplicate value

* feat: make skeleton for booking embed accurate

* fix: calendar connect atoms (#20766)

* fix: header overlaps in month view on short viewport (#20749)

* fix: header overlaps in month view on short viewport

* refactor: Merge classes into same condition

* fix: Remove booker margin top if isEmbed

---------

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
Co-authored-by: amrit <iamamrit27@gmail.com>

* fx 404 for embed (#20120)

* Update rateLimit.ts (#20785)

* fix: v2 Sentry errors (#20788)

* fix: Only Team Event Types are supported for Instant Meeting

* refactor: Cannot read properties of undefined (reading 'timeZone')

* fix: Cannot read properties of undefined (reading 'map')

* refactor: rearrange function order

* refactor: booking_seats_full_error

* fix: invalid_round_robin_host

* refactor: booking_time_out_of_bounds_error

* refactor: Attempting to book a meeting in the past.

* fix: obj.phoneNumber.trim is not a function

* fix: Cannot use 'in' operator to search for 'disabled' in 1

* fix: Org onboarding handle error due to platform team being moved to regular org (#20786)

* Add better error logs and handle platform team

* Add better error logs and handle platform team

* fix: Wrong text EmbedTheme -> Theme (#20790)

* refactor: replace timeZone string validation with timeZoneSchema (#20719)

* refactor: replace timeZone string validation with timeZoneSchema - Replace all instances of timeZone: z.string() with timeZoneSchema - Preserve modifiers (.optional(), .default(), .nullish()) where present - Fix VideoApiAdapter to use organizer's timezone value - Remove redundant isSupportedTimeZone import from booking.ts - Add timeZoneSchema import where needed

* Update index.ts

* fix: conflicts

Signed-off-by: Omar López <zomars@me.com>

* Update yarn.lock

* Discard changes to yarn.lock

* Update booking.ts

* Discard changes to packages/platform/types/me.ts

* Discard changes to packages/platform/types/me/outputs/me.ts

* Discard changes to packages/platform/types/schedules/schedules-2024-04-15/schedules.ts

* Discard changes to packages/features/ee/cal-ai-phone/zod-utils.ts

---------

Signed-off-by: Omar López <zomars@me.com>

* fix: improved 'use-identity-login' error message for users trying to signInn using different provider (#20582)

* improved 'use-identity-login' error message for users trying to signin using different provider

* passing original identity provider as query parameter

* Update packages/features/auth/lib/next-auth-options.ts

* passed different error names for different types of error

---------

Co-authored-by: romit <romitgabani1@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>

* fix: Location not changing when rescheduling (#20404)

* fix: location not chnging

* update

* update

* Update EventManager.ts

* update

* update

* Update reschedule.test.ts

---------

Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>

* fix: sms workflow api v2 (#20795)

* fix: sms workflow api v2

* fixup! fix: sms workflow api v2

* fix: semi-colon in the bottom of layout UI (#20799)

* chore: Add layout.tsx to Foundation team CODEOWNERS (#20802)

* chore: remove swagger app and its dependencies (#20798)

* chore: release v5.2.3

* fix: Convert an error in webhook to info (#20806)

* Convert error to info

* Convert error to info

* feat: add "React (Atom)" to embed generator and rename rest (#20618)

* fix: trigger lingo.dev by removing duplicate value

* feat: add support for React Atom embed options

* fix: update locator for React code tab in embed code generator E2E tests

* fix: update embed tab names to clarify iframe usage

* fix failing test

* fix: indentation and installation commands for atoms

* fix: add note about iframe usage in Preview tab

* refactor: replace Cal component with BookerEmbed in EmbedCodes

* fix: Add EmbedConfig type import in Embed.tsx

- Added missing EmbedConfig type to the existing types import
- Resolves TypeScript error "Cannot find name 'EmbedConfig'"

* fix: update BookerEmbed usage in EmbedCodes component

* fix: enhance BookerEmbed implementation and update installation instructions in EmbedTabs

* fix: improve comments in EmbedCodes for clarity on layout options and styling references

* fix: streamline BookerEmbed usage in EmbedCodes with improved class handling and layout options

* fix: embed type selection

* fix: update layout selection in EmbedCodes to use dynamic configuration

* fix: update embed configuration to use theme instead of layout

* fix: conditionally render embed options based on if we are selecting atom

* fix: use simple props instead of embed specific logic to fix the active embed bug

* Fix double tabs activeness

* Revert isCurrent change

---------

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

* refactor: remove iframe usage note from Preview tab in EmbedTabs component (#20810)

* fix: trigger lingo.dev by removing duplicate value

* refactor: remove iframe usage note from Preview tab in EmbedTabs component

* fix: api v2 license check (#20813)

* fix: api v2 license check

* update cache key to avoid conflicts

* chore: Add more Foundation and Consumer team CODEOWNERS configuration (#20816)

* refactor: forbidden 403 v2 guard messages (#20794)

* refactor: delete unused proxy guard

* refactor: roles.guard.ts

* refactor: is-org.guard.ts

* refactor: permissions.guard.ts

* refactor: oauth-client-guard.ts

* refactor: is-user-event-type-webhook-guard.ts

* refactor: platform-plan.guard.ts

* refactor: roles.guard.ts

* refactor: cache guard result if canAccess=true

* refactor: is-admin-api-enabled.guard.ts

* refactor: is-team-in-org.guard.ts

* refactor: platform-plan.guard.ts

* refactor: is-webhook-in-org.guard.ts

* refactor: is-user-in-org.guard.ts

* refactor: is-user-webhook-guard.ts

* refactor: is-user-in-org-team.guard.ts

* refactor: is-membership-in-org.guard.ts

* refactor: is-oauth-client-webhook-guard.ts

* refactor: is-routing-form-in-team.guard.ts

* refactor: is-managed-org-in-manager-org.guard.ts

* fill the gaps

* refactor: api-auth.strategy.ts

* fix: test

* implement feedback

* fix: tests

* fix: refactor

* fix: test

* feat: update DeleteSegmentDialog to use ConfirmationDialogContent CAL-5399 (#20820)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: eunjae@cal.com <eunjae@cal.com>

* feat: open dropdown right after adding a filter (#20819)

* feat: open dropdown right after adding a filter

* clean up timeout

* fix: remove window usage in not-found client (#20822)

* remove window usage in not-found client

* fix

* fix: user is already part of a team (#20774)

* better error message

* redirect to login if no user session

* fixup

* remove callback url since the same function is used by org and platform both

* remove extra exclamation mark

* implement PR feedback

* refactor: Remove kysely as its unused (#20817)

* perf: Fetch data server-side for Api Keys page (#20677)

* server-side fetching for api keys page

* refactor billing page

* fix

* simplify metadata in /availability/[schedule] route (#20827)

* feat: Optout of SMS workflows (#20769)

* Do not call dub if API key isn't present

* Add `WorkflowOptOutContact` table

* Add `sendTo` column to `WorkflowReminder`

* Add `workflowOptOutContactRepository`

* Add `WorkflowReminderRepository`

* Write `sendTo` number when scheduling SMS messages

* Add `p-limit` package

* Add `determineOptOutType` to `TwilioProvider`

* Add `deleteMultipleScheduledSMS`

* Create `WorkflowOptOutService`

* Add endpoint handler for Twilio SMS responses

* Add `isOptedOut` method to `workflowOptOutContactRepository`

* Verify phone number is not opted out before scheduling SMS

* Use `smsReminderNumber` instead of `sendTo`

* Type fix

* Add .env variable if opt out is available

* Add opt out message to SMS

* Import `pLimit` directly in method

* Address select comment

* Guard against undefined phone number from form

* Add early return to `deleteWorkflowReminders`

* Add request validation from Twilio

* Add fallback message as i18N string

* Only delete SMS attendee scheduled reminders

* chore: release v5.2.4

* fix: caching for sprite.svg (#20832)

* update cache-control header for sprite.svg

* updated regex

* fix: platform org members cannot access their public booking page (#20821)

* fix: platform member event pages

* chore: update slots docs

* refactor: user repository call

* refactor: remove newline

* refactor: Returns 400 error for ZodErrors (#20831)

* fix: eventType filter on /insights (#20823)

* fix: eventType filter on /insights

* remove log

* feat: custom reply To Email (#20771)

Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com>

* feat(insights): add progress indicator to download button on /insights and /insights/routing (CAL-5408) (#20631)

* feat(insights): add progress indicator to routing form responses download button (CAL-5408)

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* fix: address PR feedback - remove initial progress update and ensure no decimal parts in percentage

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* feat(insights): add progress indicator to Download component

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* feat: paginate rawData endpoint and implement batch fetching in Download component

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* refactor: simplify pagination logic in trpc-router.ts

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* show progress on tooltip

* fix download for /insights

* fix download when there is no data

* feat: replace tooltip progress indicator with toast notification

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* fix: remove duplicate ProgressToast component from showToast.tsx

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* fix: export ProgressToast component from index.ts

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* fix: add missing translation for downloading_data

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* update progress toast implementation

* fix error

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: eunjae@cal.com <eunjae@cal.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>

* perf: SSR for /teams  (#20824)

* finish

* improve

* refactor

* add revalidations

* /settings/teams is not needed

* refactor

* rename

* redundant type casting

* perf: SSR - /availablilty/[schedule] (#20829)

* ssr for schedule page

* improve skeleton

* improve skeleton

* improve skeleton

* fix: getBookings max 1 month in the past when no date filters specified (#20911)

* fix: getBookings max 1 month in the past

* bump platform libraries

* Pass customReplyTo as a managed event type prop (#20909)

Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>

* chore: release v5.2.5

* fix: Docs for deleting reserved slot (#20922)

* feat: ability to hide organizer email (#20782)

* feat: hide orgainzer email

* fix type error

* update

* update

* Update schema.prisma

* perf: Slim down trpc queries in Settings Layout   (#20918)

* slim down settings layout by removing server queries

* add check method

* fix type check

* refactor

* perf: remove next.redirect by going straight to event-types (#20920)

* perf: ssr for /settings/organizations/teams/other (#20927)

* refactor: v2 automatic team slugs (#20897)

* refactor: automatic team slugs

* refactor: automatic organizations team slugs

* refactor: automatic managed organizations slugs

* docs

* refactor: test

* feat: add loading component for /apps main page (#20924)

* perf: server-side fetching for /availability (#20804)

* availability

* refactor

* add loader

* improve

* update

* fix loader

* rename

* satisfying types

* refactor

* remove log

* add CTA to skeleton

* refactor

* fix revalidations

* refactor

* update

* finish

* fix: Include ordered attendees in booking select query (#20935)

* fix: correct ordering

* another

* docs: global platform event types and custom booking flows (#20940)

* docs: global event types

* docs: custom booking flow

* chore: release v5.2.6

* fix: v2 sentry errors (#20902)

* refactor: no_available_users_found_error for team event

* fix: hosts_unavailable_for_booking

* fix: Cannot read properties of undefined (reading 'replace')

* fix: Cannot read properties of undefined (reading 'phoneNumber')

* fix: No SelectedCalendar found.

* fix: Cannot read properties of undefined (reading 'length')

* refactor: add bookings errors service

* feat: add membership creation date to Organization Member List table (CAL-5406) (#20595)

* feat: add membership creation date to Organization Member List table (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* feat: add migration for membership creation date (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* feat: make createdAt and updatedAt nullable (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* feat: add updatedAt column to Organization Member List table (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* fix: use type assertion to access createdAt and updatedAt fields (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* fix: display N/A for null date values (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* fix: use proper type assertions for createdAt and updatedAt fields (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* fix: add createdAt and updatedAt to UserTableUser mock in test (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* feat: add PostgreSQL trigger for membership timestamps (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* fix: use empty string instead of N/A and add translations for column headers (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* add i18n text

* clean up type issue

* feat: add translation keys for column headers (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* disable sort

* remove duplicated i18n texts

* feat: add filters for lastActiveAt, createdAt, and updatedAt (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* support date range filter

* fix date range for end date

* hide columns by default

* revert wrong change

* add missing selects

* fix e2e test

* fix: remove PostgreSQL trigger and let application handle timestamps (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* feat: add application-level timestamp handling for Membership model (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* add more timestamp handling

* refactor: use Prisma's built-in decorators for Membership timestamps (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* refactor: remove application-level timestamp handling in favor of Prisma decorators (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* refactor: remove more application-level timestamp handling in favor of Prisma decorators (CAL-5406)

Co-Authored-By: keith@cal.com <keith@cal.com>

* fix e2e test

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: keith@cal.com <keith@cal.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>

* fix: Offset is required but not passed everywhere, default to zero. (#20917)

* fix: exclude email from replyTo (#20953)

* fix: exclude email from replyTo

* update

* Update scheduleEmailReminders.ts

* fix: added order by (#20959)

* fix: double end-date parsing when saving availability (#20963)

* fix: double end-date parsing when saving availablity

Signed-off-by: Omar López <zomars@me.com>

* fix: cache hits in current and next month

* Update CalendarService.test.ts

---------

Signed-off-by: Omar López <zomars@me.com>

* fix: Don't delete Cal video room upon requesting reschedule (#20969)

* Update requestReschedule.handler.ts

* Update requestReschedule.handler.ts

* chore: leverage error.tsx in app router (#20955)

* chore: better code - migrate getServerSideProps file directly to RSC for /apps (#20926)

* migrate getServerSideProps file directly to RSC for /apps

* fix

* fix: dont persist last booking response, temporarily (#20975)

* dont persist last booking response

* remove dead code to fix ts error

* perf: Improve performance of period limits (#20974)

* perf: Improve performance of period limits

* Type fixes

* Fixed correct check for instanceof -> isDayjs

* revert: "feat: add membership creation date to Organization Member List table (CAL-5406) (#20595)" (#20978)

This reverts commit d21f7ccbc8.

* perf: Add credentialId index to selectedCalendar (#20979)

* docs: add JSDoc documentation to FeaturesRepository class and methods (#20980)

* chore: release v5.2.7

* Handle acme.cal.local root path (#20981)

* Update sms-manager.ts (#20985)

* Do not retrieve already persisted data as well (#20982)

* perf: workflows—remove data fetching for metadata (#20734)

* Remove 30 seats minimum text from organization setup page (#20983)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: hariom@cal.com <hariom@cal.com>

* fix: few details not populate (#20987)

* fix: cancel platform subscription on dashboard (#20787)

* add new endpoint to cancel user subscription

* remove comments

* add delete button to frontend

* update correct request method

* fixup

* frontend for cancelling subscription

* better warning message

* better function name

* update locales

* better error handling in case stripe api call fails

* rename teamId to organizationId

---------

Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>

* feat: added `hideOrganizerEmail` to api/v2/event-types (#21005)

* feat: added `hideOrganizerEmail` to api/v2/event-types

* updated docs

* fix: Skip already completed org onboarding, as webhook request can come when invoice is paid again next month (#20984)

* there is nothing to do for repeat invoice payment

* there is nothing to do for repeat invoice payment

* fix: wrong translation value (#17923)

* feat: ability to remove attendees from booking page

* update

* fix

* fix: unable to create meeting with ms teams (#20993)

* fix: few details not populate

* fix: unable to create meeting with ms teams

* Update CrmService.ts

* update

* fix: encoding bug (#21004)

* fix: encoding bug

* fix: use escapeValue

* perf: SSR - /event-types and /event-types/[type] (#20952)

* add revalidation

* ssr for event-types

* wip

* wip

* fix types

* fix skeleton

* better error component

* make skeleton better

* no need to export

* call revalidations early

* remove revalidations if not needed

* address comments

* address

* fix: schedule unscheduled emails with tasker in cron job (#20748)

Co-authored-by: CarinaWolli <wollencarina@gmail.com>

* fix: hide orgnizer email in cal video sidebar (#21011)

* refactor: Use Salesforce GraphQL for account ownership routing (#20655)

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

* fix: Handle calendar-cache with Delegation Credentials

Fixes CAL-5372

# Delegation Credentials with CalendarCache.

Following content is a snapshot of the [internal document](https://calendso.slack.com/docs/T08B8KA2BNF/F08L5JYU3V3)



**Problem-1 :** 

CalendarCache needs SelectedCalendar records to work but SelectedCalendar record is only created when a user connects their calendar and then enables some calendar for conflict checking. Because with Delegation, no manual connection is done by any of the members, we need a way to create SelectedCalendar records automatically.

**Problem-2**

CalendarCache connects to credential(regular credential) which doesn’t exist for Delegation Credential scenario. Also, DelegationCredential is common for all the members(different from Credential which is different for different members) of the organization and we need to identify to which user the CalendarCache belongs.  

**Solution for both problems**
- Create credential records for Delegation Credentials as well - Through Cron(new - we could schedule it every 5mins)
- Now create SelectedCalendar  records for those Credential records -  Through another Cron(new - we could schedule it every 5mins)
- Now CalendarCache records will automatically be created for those SelectedCalendar records -existing cron

## Fixed some Delegation Credentials bugs unrelated to calendar-cache
- If DestinationCalendar wasn't set(which is possible only with Delegation Credentials), then Google Meet wasn't used as a conferencing app - [Added a test]
- If no SelectedCalendar is there but Google Calendar connection exists(possible only with Delegation Credential) then we were not doing conflict checking. It is expected to not do it for Regular Credentials, but for Delegation Credential we must check for conflict in that case too [Added a test]
- Earlier if a user has Regular Credential as well as Delegation Credential for the same external id which is the member email(say member1@acme.com) then availability were retrieved twice because we weren't deduplicating credentials as it wasn't a trivial thing to do. Now that is being done.


**Env Variables:**
Note this PR doesn't introduce any new env variable. The existing env variable has been added to .env.example. But if this env variable isn't already set, it must be set.

`CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY={SAME_AS_SET_FOR_V2_API}`

**Deployment Plan:**
1. Add Observability for SelectedCalendar when _error_ field is set
2. Follow https://github.com/calcom/cal.com/blob/calendar-cache-dwd-support/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/delegation-credential/delegation-credential.md#setting-up-delegation-credential-for-google-calendar-api to enable Delegation Credential for i.cal.com
3. Note that to be able to see the option to enable Delegation Credential for an organization, you need to enable `teamFeature` and `feature` for `delegation-credential`

## Automation Tests
- Introduced tests for calendar-cache.repository.ts
   - Tests all methods of the repository
- Added more tests for handleNewBooking/delegation-credential flow.
   - Added test to verify the bug fix when no DestinationCalendar exists and Google Meet should be used still 
- Added more tests for Google Calendar/CalendarService targeting DelegationCredential
- Added more tests for getCalendarsEvents. 
    - To test the new logic of calling getAvailability still if there are no selectedCalendars in case of Delegation Credential
    - Also introduced tests for `getAvailabitlityWithTimezones` which was an existing function but now has some new changes.
- Added tests for deduplication logic in CalendarManager.ts

## How to Test
Enable Calendar Cache and Delegation Credential feature for acme org through `features` and `teamFeatures` tables.
- Enable Delegation Credential for acme org
- Enable atleast 1 calendar for conflict checking for one of the users(say owner1)
- Ensure GOOGLE_WEBHOOK_TOKEN is set in .env file
- Ensure GOOGLE_WEBHOOK_URL is set to ngrok url of webapp in .env file
- Hit cron endpoint `curl http://localhost:3000/api/calendar-cache/cron\?apiKey\={API_KEY}` that would cache the freebusy result for the selected calendars



Followup 
- https://github.com/calcom/cal.com/pull/20698
- https://github.com/calcom/cal.com/pull/18619/files#r2046795643

* fix: UI Bug - ToggleGroup (#20997)

* fix #20986: UI Bug - ToggleGroup

* some changes

* some changes

* feat: /skip trial for teams (#20753)

* skip team trials

* add loading state

* update mocks

* cleanup

* add import oops

* fix tests files

---------

Co-authored-by: Sean Brydon <sean@Seans-Mac-mini.local>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>

* fix: cleanup html reports when pr is merged/closed (#20089)

Co-authored-by: anik@cal.com <anik@cal.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: allow only platform organisation or non-platform organisation (#20972)

* fix: platform customers cant subscribe to organizations plan

* fix: organization customers cant subscribe to platform plan

* chore: format calendar events to remove oauthClientIds (#21040)

* fix: meeting link fails when host requests to reschedule (#20999)

* fix: meeting link fails when host requests to reschedule

* Update EventManager.ts

* fixes

* Incorportate prisma integration

* Update package.json

* Delete apps/web/app/sentry-example-page/page.tsx

* Discard changes to packages/features/insights/server/trpc-router.ts

* Delete .github/workflows/sentry-sourcemaps.yml

* Delete apps/web/app/api/sentry-example-api/route.ts

* Update turbo.json

* Delete sentry.client.config.ts

* Delete sentry.client.config.ts

* fix

* Update package.json

* Update next.config.js

* Update package.json

* Update yarn.lock

* Discard changes to .env.example

* Discard changes to packages/embeds/embed-react/package.json

* Discard changes to packages/platform/atoms/package.json

* Discard changes to packages/features/ee/teams/components/TeamsListing.tsx

* Update instrumentation-client.ts

* Update instrumentation-client.ts

* Update sentry.edge.config.ts

* Update next.config.js

---------

Signed-off-by: Omar López <zomars@me.com>
Co-authored-by: Yadong Zhang <zhyd007@gmail.com>
Co-authored-by: amrit <iamamrit27@gmail.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Benny Joo <sldisek783@gmail.com>
Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com>
Co-authored-by: GitHub Actions <github-actions@github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: benny@cal.com <benny@cal.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Evan Liu <evanliu.dev@gmail.com>
Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Ronit Raj <ronitrajofficial7@gmail.com>
Co-authored-by: Romit Gabani <85230081+romitg2@users.noreply.github.com>
Co-authored-by: romit <romitgabani1@gmail.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: eunjae@cal.com <eunjae@cal.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Vijay <vijayraghav22@gmail.com>
Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com>
Co-authored-by: keith@cal.com <keith@cal.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
Co-authored-by: hariom@cal.com <hariom@cal.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Sean Brydon <sean@Seans-Mac-mini.local>
Co-authored-by: anik@cal.com <anik@cal.com>
2025-05-09 19:44:48 +00:00
GitHub Actions fa09fd66ff chore: release v5.2.14
Post release / release (push) Canceled after 0s
2025-05-09 17:03:57 +00:00
Joe Au-Yeung b1cbeebe48 feat: Add option to include no shows in RR calculations (#21063)
* Show distribution option for RR scheduling type

* Add `includeNoShowInRRCalculation` to event type schema

* Add `includeNoShowInRRCalculation` initial event type data

* Add FE option for `includeNoShowInRRCalculation`

* Consider `includeNoShowInRRCalculation` when building `where` clause when getting bookings for RR

* Add `includeNoShowInRRCalculation` param to `getAllBookingsForRoundRobin`

* Add `includeNoShow...` param to `GetLuckyUserParams`

* Pass `includeNoShow...` param to `getBookingsOfInterval` calls

* Add FE option for `includeNoShow...` (actual commit)

* Type fixes

* Fix brackets

* Add booking repository test

* Remove unused method

* Add translation

* Type fix

* Type fix

* Test passing

* Fix tests

* Fix tests

* Fix test

* Type fixes
2025-05-09 16:29:57 +00:00
devin-ai-integration[bot] 93bad282d7 feat: add SMS_ATTENDEE action to activateEventType.handler.ts (#21201) 2025-05-09 18:08:21 +02:00
Anik Dhabal Babu 47d941676e fix: add org email into ics when hideorganizer email is true (#21212)
* fix: add org email into ics

* update test
2025-05-09 15:57:24 +00:00
Keith Williams 54c4b0b65e chore: Remove Sentry replay integration (#21211) 2025-05-09 11:44:30 -04:00
Udit Takkar 0f8356f417 chore: add some console logs for debugging (#21130)
* chore: add some console logs for debugging

* chore: log only essential
2025-05-09 08:26:12 +00:00
Hariom BalharaandTushar Bhatt cecfcc7c6f Setup delegation credential related crons (#21176)
Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
2025-05-09 07:59:31 +00:00
amritandTushar Bhatt 0b3f9d06a9 test: add tests for the search dropdown in /bookings/upcoming filter (#21141)
* fix: trigger lingo.dev by removing duplicate value

* feat: add filter dropdown item search tests for bookings list

* refactor: update page navigation to wait for DOM content in bookings list tests and add new filter item search test

* remove comments

---------

Co-authored-by: Tushar Bhatt <95581504+TusharBhatt1@users.noreply.github.com>
2025-05-09 11:12:30 +05:30
Yadong (Adam) ZhangandOmar López 71e7300830 build(apps/web): enabled client code Sentry source maps uploading. (#21108)
Co-authored-by: Omar López <zomars@me.com>
2025-05-08 20:14:47 -07:00
Omar López bccffb328b refactor: removes copy-webpack-plugin (#21200) 2025-05-09 01:01:53 +00:00
Carina WollendorferandCarinaWolli 80fa172f79 feat: add feature flag for sending workflow emails with smtp (#21187)
* add feature flag

* add unit tests

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
2025-05-08 22:39:14 +00:00
Joe Au-Yeung 50173658f8 refactor: Use Iffy for workflow body scanning (#21170)
* Add Iffy API key variable

* WIP using Iffy to scan comments

* Use Iffy for workflow body scanning

* Update entity

* Clean up

* Update test

* Fix client id

* Fix test
2025-05-08 23:38:49 +01:00
Lauris Skraucis dddbd7dad4 feat: v2 membership attributes (#21131)
* refactor: getByUserId.handler.ts

* feat: return org membership attributes

* docs

* export new library function

* test: attributes

* chore: bump libraries

* refactor: value -> option
2025-05-08 23:37:24 +01:00
Benny Joo ae2d85d81b chore: Remove @calcom/features/schedules barrel files (#21199)
* remove barrel files

* update imports
2025-05-08 23:15:51 +01:00
350 changed files with 14170 additions and 2464 deletions
+8 -6
View File
@@ -159,13 +159,17 @@ SENDGRID_EMAIL=
NEXT_PUBLIC_SENDGRID_SENDER_NAME=
# Sentry
SENTRY_ORG=
SENTRY_PROJECT=
SENTRY_AUTH_TOKEN=
# Used for capturing exceptions and logging messages
NEXT_PUBLIC_SENTRY_DSN=
SENTRY_DEBUG=
SENTRY_DISABLE_CLIENT_SOURCE_MAPS=
SENTRY_DISABLE_SERVER_SOURCE_MAPS=
SENTRY_MAX_SPANS=
SENTRY_SAMPLE_RATE=
SENTRY_TRACES_SAMPLE_RATE=
SENTRY_REPLAYS_SESSION_SAMPLE_RATE=
SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE=
# Formbricks Experience Management Integration
NEXT_PUBLIC_FORMBRICKS_HOST_URL=https://app.formbricks.com
@@ -198,6 +202,7 @@ NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE=
NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN=0
NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE=
STRIPE_TEAM_MONTHLY_PRICE_ID=
NEXT_PUBLIC_STRIPE_CREDITS_PRICE_ID=
STRIPE_TEAM_PRODUCT_ID=
# It is a price ID in the product with id STRIPE_ORG_PRODUCT_ID
STRIPE_ORG_MONTHLY_PRICE_ID=
@@ -363,9 +368,6 @@ E2E_TEST_OIDC_USER_PASSWORD=
# ***********************************************************************************************************
# disable setry server source maps
SENTRY_DISABLE_SERVER_WEBPACK_PLUGIN=1
# api v2
NEXT_PUBLIC_API_V2_URL="http://localhost:5555/api/v2"
@@ -425,7 +427,7 @@ DIRECTORY_IDS_TO_LOG=
# Read more about it in the README.md
NEXT_PUBLIC_SINGLE_ORG_SLUG=
AKISMET_API_KEY=
IFFY_API_KEY=
## Env variables related to avoiding booking failures
# Request for checking reservation would be attempted to send every these seconds if the request is stale at that time
-2
View File
@@ -1,8 +1,6 @@
/**/package.json @calcom/Foundation
/apps/api/**/* @calcom/Platform @calcom/Foundation
/apps/ui-playground/**/* @calcom/Consumer @calcom/Foundation
/apps/web/components/**/* @calcom/Consumer @calcom/Foundation
/apps/web/modules/**/* @calcom/Consumer @calcom/Foundation
/apps/web/**/layout.tsx @calcom/Consumer @calcom/Foundation
/apps/web/lib/**/* @calcom/Foundation
/apps/web/middleware.ts @calcom/Foundation
+23
View File
@@ -0,0 +1,23 @@
name: Cron - checkSmsPrices
on:
# "Scheduled workflows run on the latest commit on the default or base branch."
# — https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#schedule
schedule:
# Runs “every minute” (see https://crontab.guru)
- cron: "* * * * *"
jobs:
cron-checkSmsPrices:
env:
APP_URL: ${{ secrets.APP_URL }}
CRON_API_KEY: ${{ secrets.CRON_API_KEY }}
runs-on: ubuntu-latest
steps:
- name: cURL request
if: ${{ env.APP_URL && env.CRON_API_KEY }}
run: |
curl ${{ secrets.APP_URL }}/api/cron/checkSmsPrices \
-X POST \
-H 'content-type: application/json' \
-H 'authorization: ${{ secrets.CRON_API_KEY }}' \
--fail
+2
View File
@@ -0,0 +1,2 @@
undecided:
- "@calcom/prisma"
View File
+2
View File
@@ -0,0 +1,2 @@
undecided:
- "@calcom/prisma"
+2
View File
@@ -0,0 +1,2 @@
undecided:
- "@calcom/prisma"
+1 -1
View File
@@ -30,7 +30,7 @@
"@calcom/lib": "*",
"@calcom/prisma": "*",
"@calcom/trpc": "*",
"@sentry/nextjs": "^8.8.0",
"@sentry/nextjs": "^9.15.0",
"bcryptjs": "^2.4.3",
"memory-cache": "^0.2.0",
"next": "^13.5.9",
-1
View File
@@ -1 +0,0 @@
export {};
+1 -1
View File
@@ -38,7 +38,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.196",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.197",
"@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
@@ -182,7 +182,7 @@ export class BookingsController_2024_08_13 {
): Promise<GetBookingsOutput_2024_08_13> {
const profile = this.usersService.getUserMainProfile(user);
const bookings = await this.bookingsService.getBookings(queryParams, {
const { bookings, pagination } = await this.bookingsService.getBookings(queryParams, {
email: user.email,
id: user.id,
orgId: profile?.organizationId,
@@ -191,6 +191,7 @@ export class BookingsController_2024_08_13 {
return {
status: SUCCESS_STATUS,
data: bookings,
pagination,
};
}
@@ -14,7 +14,7 @@ import { UsersModule } from "@/modules/users/users.module";
import { INestApplication } from "@nestjs/common";
import { NestExpressApplication } from "@nestjs/platform-express";
import { Test } from "@nestjs/testing";
import { EventType, User } from "@prisma/client";
import { EventType, User, Workflow } from "@prisma/client";
import { advanceTo, clear } from "jest-date-mock";
import * as request from "supertest";
import { BookingsRepositoryFixture } from "test/fixtures/repository/bookings.repository.fixture";
@@ -22,6 +22,8 @@ import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-type
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture";
import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.fixture";
import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture";
import { WorkflowReminderRepositoryFixture } from "test/fixtures/repository/workflow-reminder.repository.fixture";
import { WorkflowRepositoryFixture } from "test/fixtures/repository/workflow.repository.fixture";
import { randomString } from "test/utils/randomString";
import { withApiAuth } from "test/utils/withApiAuth";
@@ -32,6 +34,7 @@ import {
VERSION_2024_08_13,
X_CAL_CLIENT_ID,
} from "@calcom/platform-constants";
import { AttendeeScheduledEmail, OrganizerScheduledEmail } from "@calcom/platform-libraries/emails";
import {
CreateEventTypeInput_2024_06_14,
FAILED_EVENT_TYPE_IDENTIFICATION_ERROR_MESSAGE,
@@ -60,6 +63,8 @@ describe("Bookings Endpoints 2024-08-13", () => {
let schedulesService: SchedulesService_2024_04_15;
let eventTypesRepositoryFixture: EventTypesRepositoryFixture;
let oauthClientRepositoryFixture: OAuthClientRepositoryFixture;
let workflowReminderRepositoryFixture: WorkflowReminderRepositoryFixture;
let workflowRepositoryFixture: WorkflowRepositoryFixture;
let oAuthClient: PlatformOAuthClient;
let teamRepositoryFixture: TeamRepositoryFixture;
@@ -68,6 +73,8 @@ describe("Bookings Endpoints 2024-08-13", () => {
let eventTypeId: number;
let eventType: EventType;
let eventTypeWithAttendeeSmsReminder: EventType;
let workflow: Workflow;
const eventTypeSlug = `user-bookings-event-type-${randomString()}`;
let recurringEventTypeId: number;
const recurringEventTypeSlug = `user-bookings-event-type-${randomString()}`;
@@ -97,6 +104,8 @@ describe("Bookings Endpoints 2024-08-13", () => {
oauthClientRepositoryFixture = new OAuthClientRepositoryFixture(moduleRef);
teamRepositoryFixture = new TeamRepositoryFixture(moduleRef);
schedulesService = moduleRef.get<SchedulesService_2024_04_15>(SchedulesService_2024_04_15);
workflowReminderRepositoryFixture = new WorkflowReminderRepositoryFixture(moduleRef);
workflowRepositoryFixture = new WorkflowRepositoryFixture(moduleRef);
organization = await teamRepositoryFixture.create({
name: `user-bookings-organization-${randomString()}`,
@@ -177,6 +186,85 @@ describe("Bookings Endpoints 2024-08-13", () => {
rating: 10,
});
workflow = await workflowRepositoryFixture.create({
user: {
connect: {
id: user.id,
},
},
trigger: "BEFORE_EVENT",
time: 24,
timeUnit: "HOUR",
position: 0,
isActiveOnAll: false,
name: "Attendee SMS Reminder",
steps: {
create: {
stepNumber: 1,
action: "SMS_ATTENDEE",
sendTo: null,
reminderBody:
"Hi {ATTENDEE}, this is a reminder that your meeting ({EVENT_NAME}) with {ORGANIZER} is on {EVENT_DATE_YYYY MMM D} at {EVENT_TIME_h:mma} {TIMEZONE}.",
emailSubject: "Reminder: {EVENT_NAME} - {EVENT_DATE_ddd, MMM D, YYYY h:mma}",
template: "REMINDER",
numberRequired: true,
sender: "Cal",
numberVerificationPending: false,
includeCalendarEvent: false,
verifiedAt: new Date(),
},
},
});
eventTypeWithAttendeeSmsReminder = await eventTypesRepositoryFixture.create(
{
title: "event with attendee sms reminder",
slug: "event-with-attendee-sms-reminder",
length: 15,
bookingFields: [
{
name: "smsReminderNumber",
type: "phone",
sources: [
{
id: String(workflow.id),
type: "workflow",
label: "Workflow",
editUrl: `/workflows/${workflow.id}`,
fieldRequired: true,
},
],
editable: "system",
required: true,
defaultLabel: "number_text_notifications",
defaultPlaceholder: "enter_phone_number",
},
],
metadata: {
disableStandardEmails: {
all: {
attendee: true,
host: true,
},
confirmation: {
host: true,
attendee: true,
},
},
},
workflows: {
create: {
workflow: {
connect: {
id: workflow.id,
},
},
},
},
},
user.id
);
app = moduleRef.createNestApplication();
bootstrap(app as NestExpressApplication);
@@ -1668,7 +1756,6 @@ describe("Bookings Endpoints 2024-08-13", () => {
describe("book by username and event type slug", () => {
it("should not create a booking by if neither event type id nor username and event type slug provided", async () => {
const googleMeetUrl = "https://meet.google.com/abc-def-ghi";
const body = {
start: new Date(Date.UTC(2036, 0, 8, 15, 0, 0)).toISOString(),
attendee: {
@@ -1677,7 +1764,7 @@ describe("Bookings Endpoints 2024-08-13", () => {
timeZone: "Europe/Rome",
language: "it",
},
location: googleMeetUrl,
location: "https://meet.google.com/abc-def-ghi",
bookingFieldsResponses: {
customField: "customValue",
},
@@ -2227,6 +2314,91 @@ describe("Bookings Endpoints 2024-08-13", () => {
});
});
describe("create booking with attendee sms reminder", () => {
it("should not be able create a booking if attendee sms reminder is missing", async () => {
const body: CreateBookingInput_2024_08_13 = {
start: new Date(Date.UTC(2030, 0, 8, 15, 0, 0)).toISOString(),
eventTypeId: eventTypeWithAttendeeSmsReminder.id,
attendee: {
name: "Mr Proper",
email: "mr_proper@gmail.com",
timeZone: "Europe/Rome",
language: "it",
},
};
const response = await request(app.getHttpServer())
.post("/v2/bookings")
.send(body)
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
.expect(400);
expect(response.body.error.message).toEqual(
`Missing attendee phone number - it is required by the event type. Pass it as \"attendee.phoneNumber\" string in the request.`
);
});
it("should be able create a booking if attendee sms reminder is provided", async () => {
const phoneNumber = "+37122222222";
const body: CreateBookingInput_2024_08_13 = {
start: new Date(Date.UTC(2030, 0, 8, 15, 0, 0)).toISOString(),
eventTypeId: eventTypeWithAttendeeSmsReminder.id,
attendee: {
name: "Mr Proper",
email: "mr_proper@gmail.com",
timeZone: "Europe/Rome",
language: "it",
phoneNumber,
},
};
const response = await request(app.getHttpServer())
.post("/v2/bookings")
.send(body)
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
.expect(201);
const responseBody: CreateBookingOutput_2024_08_13 = response.body;
expect(responseBody.status).toEqual(SUCCESS_STATUS);
expect(responseBody.data).toBeDefined();
expect(responseDataIsBooking(responseBody.data)).toBe(true);
if (responseDataIsBooking(responseBody.data)) {
const data: BookingOutput_2024_08_13 = responseBody.data;
expect(data.id).toBeDefined();
expect(data.uid).toBeDefined();
expect(data.hosts.length).toEqual(1);
expect(data.hosts[0].id).toEqual(user.id);
expect(data.status).toEqual("accepted");
expect(data.start).toEqual(body.start);
expect(data.end).toEqual(new Date(Date.UTC(2030, 0, 8, 15, 15, 0)).toISOString());
expect(data.duration).toEqual(15);
expect(data.eventTypeId).toEqual(eventTypeWithAttendeeSmsReminder.id);
expect(data.attendees.length).toEqual(1);
expect(data.attendees[0]).toEqual({
name: body.attendee.name,
email: body.attendee.email,
timeZone: body.attendee.timeZone,
language: body.attendee.language,
phoneNumber: body.attendee.phoneNumber,
absent: false,
});
expect(data.bookingFieldsResponses).toEqual({
name: body.attendee.name,
email: body.attendee.email,
attendeePhoneNumber: body.attendee.phoneNumber,
smsReminderNumber: body.attendee.phoneNumber,
});
const dbBooking = await bookingsRepositoryFixture.getById(data.id);
expect(dbBooking?.smsReminderNumber).toEqual(phoneNumber);
const dbWorkflowReminder = await workflowReminderRepositoryFixture.getByBookingUid(data.uid);
expect(dbWorkflowReminder?.method).toEqual("SMS");
} else {
throw new Error("Invalid response data");
}
});
});
function responseDataIsRecurranceBooking(data: any): data is RecurringBookingOutput_2024_08_13 {
return (
!Array.isArray(data) &&
@@ -20,6 +20,7 @@ import { UsersRepository, UserWithProfile } from "@/modules/users/users.reposito
import { ConflictException, Injectable, Logger, NotFoundException } from "@nestjs/common";
import { BadRequestException } from "@nestjs/common";
import { Request } from "express";
import { DateTime } from "luxon";
import { z } from "zod";
import {
@@ -65,7 +66,7 @@ const eventTypeBookingFieldSchema = z.object({
editable: z.string(),
});
const eventTypeBookingFieldsSchema = z.array(eventTypeBookingFieldSchema);
export const eventTypeBookingFieldsSchema = z.array(eventTypeBookingFieldSchema);
export type EventTypeWithOwnerAndTeam = EventType & { owner: User | null; team: Team | null };
@@ -171,25 +172,30 @@ export class BookingsService_2024_08_13 {
}
async hasRequiredBookingFieldsResponses(body: CreateBookingInput, eventType: EventType | null) {
const bookingFields = { ...body.bookingFieldsResponses, attendeePhoneNumber: body.attendee.phoneNumber };
const bookingFields: Record<string, unknown> = {
...body.bookingFieldsResponses,
attendeePhoneNumber: body.attendee.phoneNumber,
smsReminderNumber: body.attendee.phoneNumber,
};
if (!eventType?.bookingFields) {
return true;
}
// note(Lauris): we filter out system fields, because some of them are set by default and name and email are passed in the body.attendee
// note(Lauris): we filter out system fields, because some of them are set by default and name and email are passed in the body.attendee. Only exception
// is smsReminderNumber, because if it is required and not passed sms workflow won't work.
const eventTypeBookingFields = eventTypeBookingFieldsSchema
.parse(eventType.bookingFields)
.filter((field) => !field.editable.startsWith("system"));
.filter((field) => !field.editable.startsWith("system") || field.name === "smsReminderNumber");
if (!eventTypeBookingFields.length) {
return true;
}
for (const field of eventTypeBookingFields) {
if (field.required && !(field.name in bookingFields)) {
if (field.name === "attendeePhoneNumber") {
if (field.required && (bookingFields[field.name] === null || bookingFields[field.name] === undefined)) {
if (field.name === "attendeePhoneNumber" || field.name === "smsReminderNumber") {
throw new BadRequestException(
`Missing attendee phone number - it is required by the event type. Pass it as "attendee.phoneNumber" in the request.`
`Missing attendee phone number - it is required by the event type. Pass it as "attendee.phoneNumber" string in the request.`
);
}
throw new BadRequestException(
@@ -376,7 +382,7 @@ export class BookingsService_2024_08_13 {
queryParams.attendeeEmail = await this.getAttendeeEmail(queryParams.attendeeEmail, user);
}
const fetchedBookings: { bookings: { id: number }[] } = await getAllUserBookings({
const fetchedBookings: { bookings: { id: number }[]; totalCount: number } = await getAllUserBookings({
bookingListingByStatus: queryParams.status || [],
skip: queryParams.skip ?? 0,
take: queryParams.take ?? 100,
@@ -432,7 +438,29 @@ export class BookingsService_2024_08_13 {
}
}
return formattedBookings;
const skip = Math.abs(queryParams?.skip ?? 0);
const take = Math.abs(queryParams?.take ?? 100);
const itemsPerPage = take;
const totalPages = itemsPerPage !== 0 ? Math.ceil(fetchedBookings.totalCount / itemsPerPage) : 0;
const currentPage = Math.floor(skip / itemsPerPage) + 1;
const hasNextPage = skip + itemsPerPage < fetchedBookings.totalCount;
const hasPreviousPage = skip > 0;
return {
bookings: formattedBookings,
pagination: {
totalItems: fetchedBookings.totalCount,
// clamp remainingItems between 0 and totalCount
remainingItems: Math.min(
Math.max(fetchedBookings.totalCount - (skip + take), 0),
fetchedBookings.totalCount
),
itemsPerPage: itemsPerPage,
currentPage: currentPage,
totalPages: totalPages,
hasNextPage: hasNextPage,
hasPreviousPage: hasPreviousPage,
},
};
}
async getAttendeeEmail(queryParamsAttendeeEmail: string, user: { id: number }) {
@@ -572,6 +600,20 @@ export class BookingsService_2024_08_13 {
async markAbsent(bookingUid: string, bookingOwnerId: number, body: MarkAbsentBookingInput_2024_08_13) {
const bodyTransformed = this.inputService.transformInputMarkAbsentBooking(body);
const bookingBefore = await this.bookingsRepository.getByUid(bookingUid);
if (!bookingBefore) {
throw new NotFoundException(`Booking with uid=${bookingUid} not found.`);
}
const nowUtc = DateTime.utc();
const bookingStartTimeUtc = DateTime.fromJSDate(bookingBefore.startTime, { zone: "utc" });
if (nowUtc < bookingStartTimeUtc) {
throw new BadRequestException(
`Bookings can only be marked as absent after their scheduled start time. Current time in UTC+0: ${nowUtc.toISO()}, Booking start time in UTC+0: ${bookingStartTimeUtc.toISO()}`
);
}
const platformClientParams = bookingBefore?.eventTypeId
? await this.platformBookingsService.getOAuthClientParams(bookingBefore.eventTypeId)
: undefined;
@@ -1,5 +1,8 @@
import { BookingsRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/bookings.repository";
import { EventTypeWithOwnerAndTeam } from "@/ee/bookings/2024-08-13/services/bookings.service";
import {
eventTypeBookingFieldsSchema,
EventTypeWithOwnerAndTeam,
} from "@/ee/bookings/2024-08-13/services/bookings.service";
import {
bookingResponsesSchema,
seatedBookingDataSchema,
@@ -159,6 +162,12 @@ export class InputBookingsService_2024_08_13 {
this.isBookingLocationWithEventTypeLocations(inputLocation, eventType);
const location = inputLocation ? this.transformLocation(inputLocation) : undefined;
const needsSmsReminderNumber = eventType.bookingFields
? eventTypeBookingFieldsSchema
.parse(eventType.bookingFields)
.find((field) => field.name === "smsReminderNumber")
: undefined;
return {
start: startTime.toISO(),
end: endTime.toISO(),
@@ -174,6 +183,7 @@ export class InputBookingsService_2024_08_13 {
name: inputBooking.attendee.name,
email: attendeeEmail ?? "",
attendeePhoneNumber: inputBooking.attendee.phoneNumber,
smsReminderNumber: needsSmsReminderNumber ? inputBooking.attendee.phoneNumber : undefined,
guests,
location,
},
@@ -1,4 +1,4 @@
import { OrganizerIntegrationLocation } from "@calcom/lib";
import { OrganizerIntegrationLocation } from "@calcom/lib/event-types/transformers/internal/locations";
type BaseEventType = {
length: number;
@@ -8,7 +8,6 @@ import { InputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_
import { OutputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/output-event-types.service";
import { SchedulesRepository_2024_06_11 } from "@/ee/schedules/schedules_2024_06_11/schedules.repository";
import { AppsRepository } from "@/modules/apps/apps.repository";
import { ConferencingModule } from "@/modules/conferencing/conferencing.module";
import { CredentialsRepository } from "@/modules/credentials/credentials.repository";
import { MembershipsModule } from "@/modules/memberships/memberships.module";
import { PrismaModule } from "@/modules/prisma/prisma.module";
@@ -19,7 +18,7 @@ import { UsersRepository } from "@/modules/users/users.repository";
import { Module } from "@nestjs/common";
@Module({
imports: [PrismaModule, MembershipsModule, TokensModule, SelectedCalendarsModule, ConferencingModule],
imports: [PrismaModule, MembershipsModule, TokensModule, SelectedCalendarsModule],
providers: [
EventTypesRepository_2024_06_14,
EventTypesService_2024_06_14,
@@ -5,6 +5,9 @@ import { ConferencingService } from "@/modules/conferencing/services/conferencin
import { UserWithProfile } from "@/modules/users/users.repository";
import { Injectable, BadRequestException } from "@nestjs/common";
import { CONFERENCING_APPS } from "@calcom/platform-constants";
import { getUsersCredentials } from "@calcom/platform-libraries";
import { getApps } from "@calcom/platform-libraries/app-store";
import {
transformBookingFieldsApiToInternal,
transformLocationsApiToInternal,
@@ -50,8 +53,7 @@ interface ValidationContext {
export class InputEventTypesService_2024_06_14 {
constructor(
private readonly eventTypesRepository: EventTypesRepository_2024_06_14,
private readonly calendarsService: CalendarsService,
private readonly conferencingService: ConferencingService
private readonly calendarsService: CalendarsService
) {}
async transformAndValidateCreateEventTypeInput(
@@ -104,13 +106,6 @@ export class InputEventTypesService_2024_06_14 {
}
transformInputCreateEventType(inputEventType: CreateEventTypeInput_2024_06_14) {
const defaultLocations: CreateEventTypeInput_2024_06_14["locations"] = [
{
type: "integration",
integration: "cal-video",
},
];
const {
lengthInMinutes,
lengthInMinutesOptions,
@@ -130,10 +125,11 @@ export class InputEventTypesService_2024_06_14 {
} = inputEventType;
const confirmationPolicyTransformed = this.transformInputConfirmationPolicy(confirmationPolicy);
const locationsTransformed = locations?.length ? this.transformInputLocations(locations) : undefined;
const eventType = {
...rest,
length: lengthInMinutes,
locations: this.transformInputLocations(locations || defaultLocations),
locations: locationsTransformed,
bookingFields: this.transformInputBookingFields(bookingFields),
bookingLimits: bookingLimitsCount ? this.transformInputIntervalLimits(bookingLimitsCount) : undefined,
durationLimits: bookingLimitsDuration
@@ -463,10 +459,32 @@ export class InputEventTypesService_2024_06_14 {
if (location.type === "integration") {
// cal-video is global, so we can skip this check
if (location.integration !== "cal-video") {
await this.conferencingService.checkAppIsValidAndConnected(user, location.integration);
await this.checkAppIsValidAndConnected(user, location.integration);
}
}
}) ?? []
);
}
async checkAppIsValidAndConnected(user: UserWithProfile, appSlug: string) {
const conferencingApps = ["google-meet", "office365-video", "zoom"];
if (!conferencingApps.includes(appSlug)) {
throw new BadRequestException("Invalid app, available apps are: ", conferencingApps.join(", "));
}
if (appSlug === "office365-video") {
appSlug = "msteams";
}
const credentials = await getUsersCredentials(user);
const foundApp = getApps(credentials, true).filter((app) => app.slug === appSlug)[0];
const appLocation = foundApp?.appData?.location;
if (!foundApp || !appLocation) {
throw new BadRequestException(`${appSlug} not connected.`);
}
return foundApp.credential;
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ if (process.env.SENTRY_DSN) {
// Ensure to call this before requiring any other modules!
Sentry.init({
dsn: getEnv("SENTRY_DSN"),
integrations: [nodeProfilingIntegration()],
integrations: [nodeProfilingIntegration(), Sentry.prismaIntegration()],
// Performance Monitoring
tracesSampleRate: getEnv("SENTRY_TRACES_SAMPLE_RATE") ?? 1.0, // Capture 100% of the transactions
// Set sampling rate for profiling - this is relative to tracesSampleRate
@@ -1,3 +1,4 @@
import { BookingsRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/bookings.repository";
import { BillingProcessor } from "@/modules/billing/billing.processor";
import { BillingRepository } from "@/modules/billing/billing.repository";
import { BillingController } from "@/modules/billing/controllers/billing.controller";
@@ -5,6 +6,7 @@ import { BillingConfigService } from "@/modules/billing/services/billing.config.
import { BillingService } from "@/modules/billing/services/billing.service";
import { ManagedOrganizationsBillingService } from "@/modules/billing/services/managed-organizations.billing.service";
import { MembershipsModule } from "@/modules/memberships/memberships.module";
import { OAuthClientRepository } from "@/modules/oauth-clients/oauth-client.repository";
import { OrganizationsModule } from "@/modules/organizations/organizations.module";
import { PrismaModule } from "@/modules/prisma/prisma.module";
import { StripeModule } from "@/modules/stripe/stripe.module";
@@ -33,6 +35,8 @@ import { Module } from "@nestjs/common";
BillingRepository,
BillingProcessor,
ManagedOrganizationsBillingService,
OAuthClientRepository,
BookingsRepository_2024_08_13,
],
exports: [BillingService, BillingRepository, ManagedOrganizationsBillingService],
controllers: [BillingController],
@@ -15,12 +15,21 @@ export class BillingRepository {
},
});
async getBillingForTeamBySubscriptionId(subscriptionId: string) {
return this.dbRead.prisma.platformBilling.findFirst({
where: {
subscriptionId,
},
});
}
async updateTeamBilling(
teamId: number,
billingStart: number,
billingEnd: number,
plan: PlatformPlan,
subscriptionId?: string
subscriptionId?: string,
priceId?: string
) {
return this.dbWrite.prisma.platformBilling.update({
where: {
@@ -32,6 +41,7 @@ export class BillingRepository {
subscriptionId,
plan: plan.toString(),
overdue: false,
priceId,
},
});
}
@@ -127,6 +127,9 @@ export class BillingController {
case "customer.subscription.deleted":
await this.billingService.handleStripeSubscriptionDeleted(event);
break;
case "invoice.created":
await this.billingService.handleStripeSubscriptionForActiveManagedUsers(event);
break;
case "invoice.payment_failed":
await this.billingService.handleStripePaymentFailed(event);
break;
@@ -1,10 +1,13 @@
import { AppConfig } from "@/config/type";
import { BookingsRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/bookings.repository";
import { BILLING_QUEUE, INCREMENT_JOB, IncrementJobDataType } from "@/modules/billing/billing.processor";
import { BillingRepository } from "@/modules/billing/billing.repository";
import { BillingConfigService } from "@/modules/billing/services/billing.config.service";
import { PlatformPlan } from "@/modules/billing/types";
import { OAuthClientRepository } from "@/modules/oauth-clients/oauth-client.repository";
import { OrganizationsRepository } from "@/modules/organizations/index/organizations.repository";
import { StripeService } from "@/modules/stripe/stripe.service";
import { UsersRepository } from "@/modules/users/users.repository";
import { InjectQueue } from "@nestjs/bull";
import {
BadRequestException,
@@ -30,6 +33,9 @@ export class BillingService implements OnModuleDestroy {
private readonly billingRepository: BillingRepository,
private readonly configService: ConfigService<AppConfig>,
private readonly billingConfigService: BillingConfigService,
private readonly usersRepository: UsersRepository,
private readonly oAuthClientRepository: OAuthClientRepository,
private readonly bookingsRepository: BookingsRepository_2024_08_13,
@InjectQueue(BILLING_QUEUE) private readonly billingQueue: Queue
) {
this.webAppUrl = this.configService.get("app.baseUrl", { infer: true }) ?? "https://app.cal.com";
@@ -119,7 +125,7 @@ export class BillingService implements OnModuleDestroy {
return url;
}
async setSubscriptionForTeam(teamId: number, subscriptionId: string, plan: PlatformPlan) {
async setPerBookingSubscriptionForTeam(teamId: number, subscriptionId: string, plan: PlatformPlan) {
const billingCycleStart = DateTime.now().get("day");
const billingCycleEnd = DateTime.now().plus({ month: 1 }).get("day");
@@ -132,6 +138,25 @@ export class BillingService implements OnModuleDestroy {
);
}
async setPerActiveUserSubscriptionForTeam(
teamId: number,
subscriptionId: string,
plan: PlatformPlan,
priceId: string
) {
const billingCycleStart = DateTime.now().get("day");
const billingCycleEnd = DateTime.now().plus({ month: 1 }).get("day");
return this.billingRepository.updateTeamBilling(
teamId,
billingCycleStart,
billingCycleEnd,
plan,
subscriptionId,
priceId
);
}
async handleStripeSubscriptionDeleted(event: Stripe.Event) {
const subscription = event.data.object as Stripe.Subscription;
const teamId = subscription?.metadata?.teamId;
@@ -204,9 +229,19 @@ export class BillingService implements OnModuleDestroy {
this.logger.log("Webhook received but not pertaining to Platform, discarding.");
return;
}
const isPriceIdPresent = Boolean(checkoutSession.metadata?.priceId);
if (checkoutSession.mode === "subscription") {
await this.setSubscriptionForTeam(
if (checkoutSession.mode === "subscription" && isPriceIdPresent) {
await this.setPerActiveUserSubscriptionForTeam(
teamId,
checkoutSession.subscription as string,
PlatformPlan[plan.toUpperCase() as keyof typeof PlatformPlan],
checkoutSession.metadata?.priceId
);
}
if (checkoutSession.mode === "subscription" && !isPriceIdPresent) {
await this.setPerBookingSubscriptionForTeam(
teamId,
checkoutSession.subscription as string,
PlatformPlan[plan.toUpperCase() as keyof typeof PlatformPlan]
@@ -220,6 +255,67 @@ export class BillingService implements OnModuleDestroy {
return;
}
async handleStripeSubscriptionForActiveManagedUsers(event: Stripe.Event) {
const invoice = event.data.object as Stripe.Invoice;
const subscriptionId = this.getSubscriptionIdFromInvoice(invoice);
if (!subscriptionId) {
throw new NotFoundException("No subscription found for team");
}
const teamWithBilling = await this.billingRepository.getBillingForTeamBySubscriptionId(subscriptionId);
if (teamWithBilling?.plan === "PER_ACTIVE_USER") {
const activeManagedUsersCount = await this.getActiveManagedUsersCount(
subscriptionId,
new Date(invoice.period_start * 1000),
new Date(invoice.period_end * 1000)
);
await this.stripeService.getStripe().subscriptions.update(subscriptionId, {
items: [
{
quantity: activeManagedUsersCount > 0 ? activeManagedUsersCount : 1,
},
],
});
}
}
async getActiveManagedUsersCount(subscriptionId: string, invoiceStart: Date, invoiceEnd: Date) {
const managedUsersEmails = await this.usersRepository.getOrgsManagedUserEmailsBySubscriptionId(
subscriptionId
);
if (!managedUsersEmails) return 0;
if (!invoiceStart || !invoiceEnd) {
this.logger.log("Invoice period start or end date is null");
return 0;
}
const activeManagedUserEmailsAsHost = await this.usersRepository.getActiveManagedUsersAsHost(
subscriptionId,
invoiceStart,
invoiceEnd
);
const activeHostEmails = activeManagedUserEmailsAsHost.map((email) => email.email);
const notActiveHostEmails = managedUsersEmails
.filter((email) => !activeHostEmails.includes(email.email))
.map((email) => email.email);
if (notActiveHostEmails.length === 0) return activeManagedUserEmailsAsHost.length;
const activeManagedUserEmailsAsAttendee = await this.usersRepository.getActiveManagedUsersAsAttendee(
notActiveHostEmails,
invoiceStart,
invoiceEnd
);
return activeManagedUserEmailsAsAttendee.length + activeManagedUserEmailsAsHost.length;
}
async updateStripeSubscriptionForTeam(teamId: number, plan: PlatformPlan) {
const teamWithBilling = await this.teamsRepository.findByIdIncludeBilling(teamId);
@@ -263,7 +359,7 @@ export class BillingService implements OnModuleDestroy {
proration_behavior: "create_prorations",
});
await this.setSubscriptionForTeam(
await this.setPerBookingSubscriptionForTeam(
teamId,
teamWithBilling?.platformBilling?.subscriptionId,
PlatformPlan[plan.toUpperCase() as keyof typeof PlatformPlan]
+2 -1
View File
@@ -4,6 +4,7 @@ export enum PlatformPlan {
ESSENTIALS = "ESSENTIALS",
SCALE = "SCALE",
ENTERPRISE = "ENTERPRISE",
PER_ACTIVE_USER = "PER_ACTIVE_USER",
}
export type PlatformPlanType = "FREE" | "STARTER" | "ESSENTIALS" | "SCALE" | "ENTERPRISE";
export type PlatformPlanType = "FREE" | "STARTER" | "ESSENTIALS" | "SCALE" | "ENTERPRISE" | "PER_ACTIVE_USER";
@@ -45,7 +45,7 @@ export class OrganizationsBookingsController {
): Promise<GetBookingsOutput_2024_08_13> {
const { userIds, ...restParams } = queryParams;
const bookings = await this.bookingsService.getBookings(
const { bookings, pagination } = await this.bookingsService.getBookings(
{ ...restParams },
{ email: user.email, id: user.id, orgId },
userIds
@@ -54,6 +54,7 @@ export class OrganizationsBookingsController {
return {
status: SUCCESS_STATUS,
data: bookings,
pagination,
};
}
}
@@ -1,4 +1,5 @@
import { InputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/input-event-types.service";
import { ConferencingRepository } from "@/modules/conferencing/repositories/conferencing.repository";
import { OrganizationsConferencingService } from "@/modules/organizations/conferencing/services/organizations-conferencing.service";
import { TeamsEventTypesRepository } from "@/modules/teams/event-types/teams-event-types.repository";
import { TeamsRepository } from "@/modules/teams/teams/teams.repository";
@@ -27,7 +28,8 @@ export class InputOrganizationsEventTypesService {
private readonly teamsRepository: TeamsRepository,
private readonly usersRepository: UsersRepository,
private readonly teamsEventTypesRepository: TeamsEventTypesRepository,
private readonly conferencingService: OrganizationsConferencingService
private readonly conferencingService: OrganizationsConferencingService,
private readonly conferencingRepository: ConferencingRepository
) {}
async transformAndValidateCreateTeamEventTypeInput(
userId: number,
@@ -306,6 +308,22 @@ export class InputOrganizationsEventTypesService {
}) ?? []
);
}
async checkAppIsValidAndConnected(teamId: number, app: string) {
const conferencingApps = ["google-meet", "office365-video", "zoom"];
if (!conferencingApps.includes(app)) {
throw new BadRequestException("Invalid app, available apps are: ", conferencingApps.join(", "));
}
if (app === "office365-video") {
app = "msteams";
}
const credential = await this.conferencingRepository.findTeamConferencingApp(teamId, app);
if (!credential) {
throw new BadRequestException(`${app} not connected.`);
}
return credential;
}
}
function getPriorityValue(priority: keyof typeof HostPriority): number {
@@ -6,6 +6,7 @@ import { CreateOrgMembershipOutput } from "@/modules/organizations/memberships/o
import { DeleteOrgMembership } from "@/modules/organizations/memberships/outputs/delete-membership.output";
import { GetAllOrgMemberships } from "@/modules/organizations/memberships/outputs/get-all-memberships.output";
import { GetOrgMembership } from "@/modules/organizations/memberships/outputs/get-membership.output";
import { OrgUserAttribute } from "@/modules/organizations/memberships/outputs/organization-membership.output";
import { UpdateOrgMembership } from "@/modules/organizations/memberships/outputs/update-membership.output";
import { PrismaModule } from "@/modules/prisma/prisma.module";
import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output";
@@ -14,17 +15,16 @@ import { UsersModule } from "@/modules/users/users.module";
import { INestApplication } from "@nestjs/common";
import { NestExpressApplication } from "@nestjs/platform-express";
import { Test } from "@nestjs/testing";
import { User } from "@prisma/client";
import { Attribute, AttributeOption, User } from "@prisma/client";
import * as request from "supertest";
import { AttributeRepositoryFixture } from "test/fixtures/repository/attributes.repository.fixture";
import { MembershipRepositoryFixture } from "test/fixtures/repository/membership.repository.fixture";
import { OrganizationRepositoryFixture } from "test/fixtures/repository/organization.repository.fixture";
import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.fixture";
import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture";
import { randomString } from "test/utils/randomString";
import { withApiAuth } from "test/utils/withApiAuth";
import { SUCCESS_STATUS } from "@calcom/platform-constants";
import { ApiSuccessResponse } from "@calcom/platform-types";
import { Membership, Team } from "@calcom/prisma/client";
describe("Organizations Memberships Endpoints", () => {
@@ -33,7 +33,8 @@ describe("Organizations Memberships Endpoints", () => {
let userRepositoryFixture: UserRepositoryFixture;
let organizationsRepositoryFixture: OrganizationRepositoryFixture;
let membershipsRepositoryFixture: MembershipRepositoryFixture;
let membershipRepositoryFixture: MembershipRepositoryFixture;
let attributesRepositoryFixture: AttributeRepositoryFixture;
let org: Team;
let membership: Membership;
@@ -49,6 +50,17 @@ describe("Organizations Memberships Endpoints", () => {
let userToInviteViaApi: User;
let textAttribute: Attribute;
let multiSelectAttribute: Attribute;
let numberAttribute: Attribute;
let singleSelectAttribute: Attribute;
let textAttributeOption: AttributeOption;
let multiSelectAttributeOption: AttributeOption;
let multiSelectAttributeOption2: AttributeOption;
let numberAttributeOption: AttributeOption;
let singleSelectAttributeOption: AttributeOption;
const metadata = {
some: "key",
};
@@ -64,7 +76,8 @@ describe("Organizations Memberships Endpoints", () => {
userRepositoryFixture = new UserRepositoryFixture(moduleRef);
organizationsRepositoryFixture = new OrganizationRepositoryFixture(moduleRef);
membershipsRepositoryFixture = new MembershipRepositoryFixture(moduleRef);
membershipRepositoryFixture = new MembershipRepositoryFixture(moduleRef);
attributesRepositoryFixture = new AttributeRepositoryFixture(moduleRef);
user = await userRepositoryFixture.create({
email: userEmail,
@@ -91,16 +104,42 @@ describe("Organizations Memberships Endpoints", () => {
isOrganization: true,
});
membership = await membershipsRepositoryFixture.create({
await setupAttributes();
membership = await membershipRepositoryFixture.create({
role: "ADMIN",
user: { connect: { id: user.id } },
team: { connect: { id: org.id } },
});
membership2 = await membershipsRepositoryFixture.create({
membership2 = await membershipRepositoryFixture.create({
role: "MEMBER",
user: { connect: { id: user2.id } },
team: { connect: { id: org.id } },
AttributeToUser: {
create: [
{
attributeOption: { connect: { id: textAttributeOption.id } },
weight: 100,
},
{
attributeOption: { connect: { id: multiSelectAttributeOption.id } },
weight: 100,
},
{
attributeOption: { connect: { id: multiSelectAttributeOption2.id } },
weight: null,
},
{
attributeOption: { connect: { id: numberAttributeOption.id } },
weight: 100,
},
{
attributeOption: { connect: { id: singleSelectAttributeOption.id } },
weight: 100,
},
],
},
});
app = moduleRef.createNestApplication();
@@ -109,6 +148,87 @@ describe("Organizations Memberships Endpoints", () => {
await app.init();
});
async function setupAttributes() {
textAttribute = await attributesRepositoryFixture.create({
team: { connect: { id: org.id } },
type: "TEXT",
name: "team",
slug: `team-${randomString()}`,
enabled: true,
usersCanEditRelation: false,
isWeightsEnabled: false,
isLocked: false,
});
multiSelectAttribute = await attributesRepositoryFixture.create({
team: { connect: { id: org.id } },
type: "MULTI_SELECT",
name: "skills",
slug: `skills-${randomString()}`,
enabled: true,
usersCanEditRelation: false,
isWeightsEnabled: false,
isLocked: false,
});
numberAttribute = await attributesRepositoryFixture.create({
team: { connect: { id: org.id } },
type: "NUMBER",
name: "age",
slug: `age-${randomString()}`,
enabled: true,
usersCanEditRelation: false,
isWeightsEnabled: false,
isLocked: false,
});
singleSelectAttribute = await attributesRepositoryFixture.create({
team: { connect: { id: org.id } },
type: "SINGLE_SELECT",
name: "frontend",
slug: `frontend-${randomString()}`,
enabled: true,
usersCanEditRelation: false,
isWeightsEnabled: false,
isLocked: false,
});
textAttributeOption = await attributesRepositoryFixture.createOption({
attribute: { connect: { id: textAttribute.id } },
value: "coders",
slug: "coders",
isGroup: false,
});
multiSelectAttributeOption = await attributesRepositoryFixture.createOption({
attribute: { connect: { id: multiSelectAttribute.id } },
value: "javascript",
slug: "javascript",
isGroup: false,
});
multiSelectAttributeOption2 = await attributesRepositoryFixture.createOption({
attribute: { connect: { id: multiSelectAttribute.id } },
value: "typescript",
slug: "typescript",
isGroup: false,
});
numberAttributeOption = await attributesRepositoryFixture.createOption({
attribute: { connect: { id: numberAttribute.id } },
value: "18",
slug: "18",
isGroup: false,
});
singleSelectAttributeOption = await attributesRepositoryFixture.createOption({
attribute: { connect: { id: singleSelectAttribute.id } },
value: "yes",
slug: "yes",
isGroup: false,
});
}
it("should be defined", () => {
expect(userRepositoryFixture).toBeDefined();
expect(organizationsRepositoryFixture).toBeDefined();
@@ -139,9 +259,54 @@ describe("Organizations Memberships Endpoints", () => {
expect(responseBody.data[1].user.email).toEqual(user2.email);
expect(responseBody.data[1].user.username).toEqual(user2.username);
expect(responseBody.data[1].teamId).toEqual(org.id);
userHasCorrectAttributes(responseBody.data[1].attributes);
});
});
function userHasCorrectAttributes(attributes: OrgUserAttribute[]) {
expect(attributes.length).toEqual(4);
const responseNumberAttribute = attributes.find((attr) => attr.type === "number");
const responseSingleSelectAttribute = attributes.find((attr) => attr.type === "singleSelect");
const responseMultiSelectAttribute = attributes.find((attr) => attr.type === "multiSelect");
const responseTextAttribute = attributes.find((attr) => attr.type === "text");
expect(responseNumberAttribute).toEqual({
id: numberAttribute.id,
name: numberAttribute.name,
optionId: numberAttributeOption.id,
option: +numberAttributeOption.value,
type: "number",
});
expect(responseSingleSelectAttribute).toEqual({
id: singleSelectAttribute.id,
name: singleSelectAttribute.name,
optionId: singleSelectAttributeOption.id,
option: singleSelectAttributeOption.value,
type: "singleSelect",
});
expect(responseMultiSelectAttribute).toEqual({
id: multiSelectAttribute.id,
name: multiSelectAttribute.name,
options: [
{
optionId: multiSelectAttributeOption2.id,
option: multiSelectAttributeOption2.value,
},
{
optionId: multiSelectAttributeOption.id,
option: multiSelectAttributeOption.value,
},
],
type: "multiSelect",
});
expect(responseTextAttribute).toEqual({
id: textAttribute.id,
name: textAttribute.name,
optionId: textAttributeOption.id,
option: textAttributeOption.value,
type: "text",
});
}
it("should get all the memberships of the org paginated", async () => {
return request(app.getHttpServer())
.get(`/v2/organizations/${org.id}/memberships?skip=1&take=1`)
@@ -182,6 +347,25 @@ describe("Organizations Memberships Endpoints", () => {
});
});
it("should get the membership of the org", async () => {
return request(app.getHttpServer())
.get(`/v2/organizations/${org.id}/memberships/${membership2.id}`)
.expect(200)
.then((response) => {
const responseBody: GetOrgMembership = response.body;
expect(responseBody.status).toEqual(SUCCESS_STATUS);
expect(responseBody.data.id).toEqual(membership2.id);
expect(responseBody.data.userId).toEqual(user2.id);
expect(responseBody.data.role).toEqual("MEMBER");
expect(responseBody.data.user.bio).toEqual(bio);
expect(responseBody.data.user.metadata).toEqual(metadata);
expect(responseBody.data.user.email).toEqual(user2.email);
expect(responseBody.data.user.username).toEqual(user2.username);
expect(responseBody.data.teamId).toEqual(org.id);
userHasCorrectAttributes(responseBody.data.attributes);
});
});
it("should create the membership of the org", async () => {
return request(app.getHttpServer())
.post(`/v2/organizations/${org.id}/memberships`)
@@ -259,7 +443,8 @@ describe("Organizations Memberships Endpoints", () => {
let userRepositoryFixture: UserRepositoryFixture;
let organizationsRepositoryFixture: OrganizationRepositoryFixture;
let membershipsRepositoryFixture: MembershipRepositoryFixture;
let membershipRepositoryFixture: MembershipRepositoryFixture;
let attributesRepositoryFixture: AttributeRepositoryFixture;
let org: Team;
let membership: Membership;
@@ -277,7 +462,8 @@ describe("Organizations Memberships Endpoints", () => {
userRepositoryFixture = new UserRepositoryFixture(moduleRef);
organizationsRepositoryFixture = new OrganizationRepositoryFixture(moduleRef);
membershipsRepositoryFixture = new MembershipRepositoryFixture(moduleRef);
membershipRepositoryFixture = new MembershipRepositoryFixture(moduleRef);
attributesRepositoryFixture = new AttributeRepositoryFixture(moduleRef);
user = await userRepositoryFixture.create({
email: userEmail,
@@ -289,7 +475,7 @@ describe("Organizations Memberships Endpoints", () => {
isOrganization: true,
});
membership = await membershipsRepositoryFixture.create({
membership = await membershipRepositoryFixture.create({
role: "MEMBER",
user: { connect: { id: user.id } },
team: { connect: { id: org.id } },
@@ -20,7 +20,6 @@ import { GetAllOrgMemberships } from "@/modules/organizations/memberships/output
import { GetOrgMembership } from "@/modules/organizations/memberships/outputs/get-membership.output";
import { UpdateOrgMembership } from "@/modules/organizations/memberships/outputs/update-membership.output";
import { OrganizationsMembershipService } from "@/modules/organizations/memberships/services/organizations-membership.service";
import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output";
import {
Controller,
UseGuards,
@@ -36,7 +35,6 @@ import {
HttpStatus,
} from "@nestjs/common";
import { ApiHeader, ApiOperation, ApiTags as DocsTags } from "@nestjs/swagger";
import { plainToClass } from "class-transformer";
import { SUCCESS_STATUS } from "@calcom/platform-constants";
import { SkipTakePagination } from "@calcom/platform-types";
@@ -70,9 +68,7 @@ export class OrganizationsMembershipsController {
);
return {
status: SUCCESS_STATUS,
data: memberships.map((membership) =>
plainToClass(TeamMembershipOutput, membership, { strategy: "excludeAll" })
),
data: memberships,
};
}
@@ -88,7 +84,7 @@ export class OrganizationsMembershipsController {
const membership = await this.organizationsMembershipService.createOrgMembership(orgId, body);
return {
status: SUCCESS_STATUS,
data: plainToClass(TeamMembershipOutput, membership, { strategy: "excludeAll" }),
data: membership,
};
}
@@ -105,7 +101,7 @@ export class OrganizationsMembershipsController {
const membership = await this.organizationsMembershipService.getOrgMembership(orgId, membershipId);
return {
status: SUCCESS_STATUS,
data: plainToClass(TeamMembershipOutput, membership, { strategy: "excludeAll" }),
data: membership,
};
}
@@ -122,7 +118,7 @@ export class OrganizationsMembershipsController {
const membership = await this.organizationsMembershipService.deleteOrgMembership(orgId, membershipId);
return {
status: SUCCESS_STATUS,
data: plainToClass(TeamMembershipOutput, membership, { strategy: "excludeAll" }),
data: membership,
};
}
@@ -144,7 +140,7 @@ export class OrganizationsMembershipsController {
);
return {
status: SUCCESS_STATUS,
data: plainToClass(TeamMembershipOutput, membership, { strategy: "excludeAll" }),
data: membership,
};
}
}
@@ -4,8 +4,31 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { MembershipUserSelect } from "@/modules/teams/memberships/teams-memberships.repository";
import { Injectable } from "@nestjs/common";
import { Prisma } from "@calcom/prisma/client";
import { UpdateOrgMembershipDto } from "./inputs/update-organization-membership.input";
export type DbOrgMembership = Awaited<ReturnType<OrganizationsMembershipRepository["findOrgMembership"]>>;
const attributeToUserSelect = {
createdByDSyncId: true,
weight: true,
attributeOption: {
select: {
id: true,
value: true,
slug: true,
attribute: {
select: {
id: true,
name: true,
type: true,
},
},
},
},
} as const satisfies Prisma.AttributeToUserSelect;
@Injectable()
export class OrganizationsMembershipRepository {
constructor(private readonly dbRead: PrismaReadService, private readonly dbWrite: PrismaWriteService) {}
@@ -16,7 +39,12 @@ export class OrganizationsMembershipRepository {
id: membershipId,
teamId: organizationId,
},
include: { user: { select: MembershipUserSelect } },
include: {
user: { select: MembershipUserSelect },
AttributeToUser: {
select: attributeToUserSelect,
},
},
});
}
@@ -26,7 +54,12 @@ export class OrganizationsMembershipRepository {
teamId: organizationId,
userId,
},
include: { user: { select: MembershipUserSelect } },
include: {
user: { select: MembershipUserSelect },
AttributeToUser: {
select: attributeToUserSelect,
},
},
});
}
@@ -36,7 +69,12 @@ export class OrganizationsMembershipRepository {
id: membershipId,
teamId: organizationId,
},
include: { user: { select: MembershipUserSelect } },
include: {
user: { select: MembershipUserSelect },
AttributeToUser: {
select: attributeToUserSelect,
},
},
});
}
@@ -45,14 +83,24 @@ export class OrganizationsMembershipRepository {
create: { ...data, teamId: organizationId },
update: { role: data.role, accepted: data.accepted, disableImpersonation: data.disableImpersonation },
where: { userId_teamId: { userId: data.userId, teamId: organizationId } },
include: { user: { select: MembershipUserSelect } },
include: {
user: { select: MembershipUserSelect },
AttributeToUser: {
select: attributeToUserSelect,
},
},
});
}
async updateOrgMembership(organizationId: number, membershipId: number, data: UpdateOrgMembershipDto) {
return this.dbWrite.prisma.membership.update({
data: { ...data },
where: { id: membershipId, teamId: organizationId },
include: { user: { select: MembershipUserSelect } },
include: {
user: { select: MembershipUserSelect },
AttributeToUser: {
select: attributeToUserSelect,
},
},
});
}
@@ -61,7 +109,12 @@ export class OrganizationsMembershipRepository {
where: {
teamId: organizationId,
},
include: { user: { select: MembershipUserSelect } },
include: {
user: { select: MembershipUserSelect },
AttributeToUser: {
select: attributeToUserSelect,
},
},
skip,
take,
});
@@ -1,4 +1,4 @@
import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output";
import { OrganizationMembershipOutput } from "@/modules/organizations/memberships/outputs/organization-membership.output";
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsEnum, IsNotEmptyObject, ValidateNested } from "class-validator";
@@ -11,10 +11,10 @@ export class CreateOrgMembershipOutput {
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
@ApiProperty({
type: TeamMembershipOutput,
type: OrganizationMembershipOutput,
})
@IsNotEmptyObject()
@ValidateNested()
@Type(() => TeamMembershipOutput)
data!: TeamMembershipOutput;
@Type(() => OrganizationMembershipOutput)
data!: OrganizationMembershipOutput;
}
@@ -1,4 +1,4 @@
import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output";
import { OrganizationMembershipOutput } from "@/modules/organizations/memberships/outputs/organization-membership.output";
import { ApiProperty } from "@nestjs/swagger";
import { IsEnum } from "class-validator";
@@ -9,5 +9,5 @@ export class DeleteOrgMembership {
@IsEnum([SUCCESS_STATUS, ERROR_STATUS])
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
data!: TeamMembershipOutput;
data!: OrganizationMembershipOutput;
}
@@ -1,4 +1,4 @@
import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output";
import { OrganizationMembershipOutput } from "@/modules/organizations/memberships/outputs/organization-membership.output";
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsEnum, IsNotEmptyObject, ValidateNested, IsArray } from "class-validator";
@@ -11,11 +11,11 @@ export class GetAllOrgMemberships {
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
@ApiProperty({
type: TeamMembershipOutput,
type: OrganizationMembershipOutput,
})
@IsNotEmptyObject()
@ValidateNested({ each: true })
@Type(() => TeamMembershipOutput)
@Type(() => OrganizationMembershipOutput)
@IsArray()
data!: TeamMembershipOutput[];
data!: OrganizationMembershipOutput[];
}
@@ -1,4 +1,4 @@
import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output";
import { OrganizationMembershipOutput } from "@/modules/organizations/memberships/outputs/organization-membership.output";
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsEnum, IsNotEmptyObject, ValidateNested } from "class-validator";
@@ -11,10 +11,10 @@ export class GetOrgMembership {
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
@ApiProperty({
type: TeamMembershipOutput,
type: OrganizationMembershipOutput,
})
@IsNotEmptyObject()
@ValidateNested()
@Type(() => TeamMembershipOutput)
data!: TeamMembershipOutput;
@Type(() => OrganizationMembershipOutput)
data!: OrganizationMembershipOutput;
}
@@ -0,0 +1,114 @@
import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output";
import { ApiExtraModels, ApiProperty, getSchemaPath } from "@nestjs/swagger";
import { Expose, Type } from "class-transformer";
import { IsArray, IsNumber, IsOptional, IsString, ValidateNested } from "class-validator";
class BaseAttribute {
@IsString()
@Expose()
@ApiProperty()
id!: string;
@IsString()
@Expose()
@ApiProperty()
name!: string;
}
export class TextAttribute extends BaseAttribute {
@IsString()
@Expose()
@ApiProperty()
type!: "text";
@IsString()
@Expose()
@ApiProperty()
option!: string;
@IsString()
@Expose()
@ApiProperty()
optionId!: string;
}
export class NumberAttribute extends BaseAttribute {
@IsString()
@Expose()
@ApiProperty()
type!: "number";
@IsNumber()
@Expose()
@ApiProperty()
option!: number;
@IsString()
@Expose()
@ApiProperty()
optionId!: string;
}
export class SingleSelectAttribute extends BaseAttribute {
@IsString()
@IsString()
@Expose()
@ApiProperty()
type!: "singleSelect";
@IsString()
@Expose()
@ApiProperty()
option!: string;
@IsString()
@Expose()
@ApiProperty()
optionId!: string;
}
class MultiSelectAttributeOption {
@IsString()
@Expose()
@ApiProperty()
optionId!: string;
@IsString()
@Expose()
@ApiProperty()
option!: string;
}
export class MultiSelectAttribute extends BaseAttribute {
@IsString()
@Expose()
@ApiProperty()
type!: "multiSelect";
@IsArray()
@ValidateNested({ each: true })
@Expose()
@ApiProperty()
options!: MultiSelectAttributeOption[];
}
export type OrgUserAttribute = TextAttribute | NumberAttribute | SingleSelectAttribute | MultiSelectAttribute;
@ApiExtraModels(BaseAttribute, TextAttribute, NumberAttribute, SingleSelectAttribute, MultiSelectAttribute)
export class OrganizationMembershipOutput extends TeamMembershipOutput {
@IsArray()
@ValidateNested({ each: true })
@Expose()
@ApiProperty({
required: true,
oneOf: [
{ $ref: getSchemaPath(TextAttribute) },
{ $ref: getSchemaPath(NumberAttribute) },
{ $ref: getSchemaPath(SingleSelectAttribute) },
{ $ref: getSchemaPath(MultiSelectAttribute) },
],
type: "array",
})
@Type(() => Object)
attributes!: OrgUserAttribute[];
}
@@ -1,4 +1,4 @@
import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output";
import { OrganizationMembershipOutput } from "@/modules/organizations/memberships/outputs/organization-membership.output";
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsEnum, IsNotEmptyObject, ValidateNested } from "class-validator";
@@ -11,10 +11,10 @@ export class UpdateOrgMembership {
status!: typeof SUCCESS_STATUS | typeof ERROR_STATUS;
@ApiProperty({
type: TeamMembershipOutput,
type: OrganizationMembershipOutput,
})
@IsNotEmptyObject()
@ValidateNested()
@Type(() => TeamMembershipOutput)
data!: TeamMembershipOutput;
@Type(() => OrganizationMembershipOutput)
data!: OrganizationMembershipOutput;
}
@@ -0,0 +1,89 @@
import { DbOrgMembership } from "@/modules/organizations/memberships/organizations-membership.repository";
import {
MultiSelectAttribute,
NumberAttribute,
OrganizationMembershipOutput,
OrgUserAttribute,
SingleSelectAttribute,
TextAttribute,
} from "@/modules/organizations/memberships/outputs/organization-membership.output";
import { Injectable } from "@nestjs/common";
import { plainToClass } from "class-transformer";
import { groupMembershipAttributes } from "@calcom/platform-libraries";
import type { GroupedAttribute } from "@calcom/platform-libraries";
@Injectable()
export class OrganizationsMembershipOutputService {
getOrgMembershipsOutput(memberships: NonNullable<DbOrgMembership>[]) {
return memberships.map((membership) => this.getOrgMembershipOutput(membership));
}
getOrgMembershipOutput(organizationMembership: NonNullable<DbOrgMembership>) {
const { AttributeToUser, ...orgMembership } = organizationMembership;
const groupedMembershipAttributes: GroupedAttribute[] = groupMembershipAttributes(AttributeToUser);
const attributesOutput = this.getAttributesOutput(groupedMembershipAttributes);
return plainToClass(OrganizationMembershipOutput, { ...orgMembership, attributes: attributesOutput });
}
private getAttributesOutput(attributes: GroupedAttribute[]): OrgUserAttribute[] {
return attributes.map((attribute) => {
switch (attribute.type) {
case "TEXT":
return this.getTextAttributeOutput(attribute);
case "NUMBER":
return this.getNumberAttributeOutput(attribute);
case "SINGLE_SELECT":
return this.getSingleSelectAttributeOutput(attribute);
case "MULTI_SELECT":
return this.getMultiSelectAttributeOutput(attribute);
default:
return this.getTextAttributeOutput(attribute);
}
});
}
private getTextAttributeOutput(attribute: GroupedAttribute): TextAttribute {
return {
id: attribute.id,
name: attribute.name,
optionId: attribute.options[0].id,
option: attribute.options[0].value,
type: "text",
};
}
private getNumberAttributeOutput(attribute: GroupedAttribute): NumberAttribute {
return {
id: attribute.id,
name: attribute.name,
optionId: attribute.options[0].id,
option: +attribute.options[0].value,
type: "number",
};
}
private getSingleSelectAttributeOutput(attribute: GroupedAttribute): SingleSelectAttribute {
return {
id: attribute.id,
name: attribute.name,
optionId: attribute.options[0].id,
option: attribute.options[0].value,
type: "singleSelect",
};
}
private getMultiSelectAttributeOutput(attribute: GroupedAttribute): MultiSelectAttribute {
return {
id: attribute.id,
name: attribute.name,
options: attribute.options.map((option: GroupedAttribute["options"][number]) => ({
optionId: option.id,
option: option.value,
})),
type: "multiSelect",
};
}
}
@@ -1,19 +1,30 @@
import { CreateOrgMembershipDto } from "@/modules/organizations/memberships/inputs/create-organization-membership.input";
import { OrganizationsMembershipRepository } from "@/modules/organizations/memberships/organizations-membership.repository";
import { Injectable } from "@nestjs/common";
import { Injectable, NotFoundException } from "@nestjs/common";
import { UpdateOrgMembershipDto } from "../inputs/update-organization-membership.input";
import { OrganizationsMembershipOutputService } from "./organizations-membership-output.service";
@Injectable()
export class OrganizationsMembershipService {
constructor(private readonly organizationsMembershipRepository: OrganizationsMembershipRepository) {}
constructor(
private readonly organizationsMembershipRepository: OrganizationsMembershipRepository,
private readonly organizationsMembershipOutputService: OrganizationsMembershipOutputService
) {}
async getOrgMembership(organizationId: number, membershipId: number) {
const membership = await this.organizationsMembershipRepository.findOrgMembership(
organizationId,
membershipId
);
return membership;
if (!membership) {
throw new NotFoundException(
`Membership with id ${membershipId} within organization id ${organizationId} not found`
);
}
return this.organizationsMembershipOutputService.getOrgMembershipOutput(membership);
}
async getOrgMembershipByUserId(organizationId: number, userId: number) {
@@ -21,7 +32,13 @@ export class OrganizationsMembershipService {
organizationId,
userId
);
return membership;
if (!membership) {
throw new NotFoundException(
`Membership for user with id ${userId} within organization id ${organizationId} not found`
);
}
return this.organizationsMembershipOutputService.getOrgMembershipOutput(membership);
}
async getPaginatedOrgMemberships(organizationId: number, skip = 0, take = 250) {
@@ -30,7 +47,7 @@ export class OrganizationsMembershipService {
skip,
take
);
return memberships;
return this.organizationsMembershipOutputService.getOrgMembershipsOutput(memberships);
}
async deleteOrgMembership(organizationId: number, membershipId: number) {
@@ -38,7 +55,7 @@ export class OrganizationsMembershipService {
organizationId,
membershipId
);
return membership;
return this.organizationsMembershipOutputService.getOrgMembershipOutput(membership);
}
async updateOrgMembership(organizationId: number, membershipId: number, data: UpdateOrgMembershipDto) {
@@ -47,11 +64,11 @@ export class OrganizationsMembershipService {
membershipId,
data
);
return membership;
return this.organizationsMembershipOutputService.getOrgMembershipOutput(membership);
}
async createOrgMembership(organizationId: number, data: CreateOrgMembershipDto) {
const membership = await this.organizationsMembershipRepository.createOrgMembership(organizationId, data);
return membership;
return this.organizationsMembershipOutputService.getOrgMembershipOutput(membership);
}
}
@@ -32,6 +32,7 @@ import { OrganizationsRepository } from "@/modules/organizations/index/organizat
import { OrganizationsService } from "@/modules/organizations/index/organizations.service";
import { OrganizationsMembershipsController } from "@/modules/organizations/memberships/organizations-membership.controller";
import { OrganizationsMembershipRepository } from "@/modules/organizations/memberships/organizations-membership.repository";
import { OrganizationsMembershipOutputService } from "@/modules/organizations/memberships/services/organizations-membership-output.service";
import { OrganizationsMembershipService } from "@/modules/organizations/memberships/services/organizations-membership.service";
import { OrganizationsOrganizationsModule } from "@/modules/organizations/organizations/organizations-organizations.module";
import { OrganizationsSchedulesController } from "@/modules/organizations/schedules/organizations-schedules.controller";
@@ -98,6 +99,7 @@ import { Module } from "@nestjs/common";
EmailService,
OrganizationsMembershipRepository,
OrganizationsMembershipService,
OrganizationsMembershipOutputService,
OrganizationsEventTypesService,
InputOrganizationsEventTypesService,
OutputOrganizationsEventTypesService,
@@ -4,6 +4,7 @@ import { MembershipsModule } from "@/modules/memberships/memberships.module";
import { MembershipsRepository } from "@/modules/memberships/memberships.repository";
import { OrganizationsRepository } from "@/modules/organizations/index/organizations.repository";
import { OrganizationsMembershipRepository } from "@/modules/organizations/memberships/organizations-membership.repository";
import { OrganizationsMembershipOutputService } from "@/modules/organizations/memberships/services/organizations-membership-output.service";
import { OrganizationsMembershipService } from "@/modules/organizations/memberships/services/organizations-membership.service";
import { ManagedOrganizationsRepository } from "@/modules/organizations/organizations/managed-organizations.repository";
import { OrganizationsOrganizationsController } from "@/modules/organizations/organizations/organizations-organizations.controller";
@@ -23,6 +24,7 @@ import { Module } from "@nestjs/common";
ManagedOrganizationsBillingService,
OrganizationsRepository,
OrganizationsMembershipService,
OrganizationsMembershipOutputService,
OrganizationsMembershipRepository,
ManagedOrganizationsOutputService,
],
@@ -54,7 +54,7 @@ export class OrganizationsTeamsBookingsController {
@Param("orgId", ParseIntPipe) orgId: number,
@GetUser() user: UserWithProfile
): Promise<GetBookingsOutput_2024_08_13> {
const bookings = await this.bookingsService.getBookings(
const { bookings, pagination } = await this.bookingsService.getBookings(
{ ...queryParams, teamId },
{ email: user.email, id: user.id, orgId }
);
@@ -62,6 +62,7 @@ export class OrganizationsTeamsBookingsController {
return {
status: SUCCESS_STATUS,
data: bookings,
pagination,
};
}
@@ -40,7 +40,7 @@ export class OrganizationsUsersBookingsController {
@Param("userId", ParseIntPipe) userId: number,
@Query() query: GetBookingsInput_2024_08_13
): Promise<GetBookingsOutput_2024_08_13> {
const bookings = await this.organizationUsersBookingsService.getOrganizationUserBookings(
const { bookings, pagination } = await this.organizationUsersBookingsService.getOrganizationUserBookings(
orgId,
userId,
query
@@ -49,6 +49,7 @@ export class OrganizationsUsersBookingsController {
return {
status: SUCCESS_STATUS,
data: bookings,
pagination,
};
}
}
@@ -29,6 +29,7 @@ import {
RecurringBookingOutput_2024_08_13,
GetBookingsOutput_2024_08_13,
GetSeatedBookingOutput_2024_08_13,
PaginationMetaDto,
} from "@calcom/platform-types";
import { PlatformOAuthClient, Team } from "@calcom/prisma/client";
@@ -373,17 +374,26 @@ describe("Organizations UsersBookings Endpoints 2024-08-13", () => {
const responseBody: GetBookingsOutput_2024_08_13 = response.body;
expect(responseBody.status).toEqual(SUCCESS_STATUS);
expect(responseBody.data).toBeDefined();
expect(responseBody.pagination).toBeDefined();
const data: (
| BookingOutput_2024_08_13
| RecurringBookingOutput_2024_08_13
| GetSeatedBookingOutput_2024_08_13
)[] = responseBody.data;
const pagination: PaginationMetaDto = responseBody.pagination;
expect(data.length).toEqual(3);
expect(data.find((booking) => booking.id === createdPersonalBooking.id)).toBeDefined();
expect(data.find((booking) => booking.id === createdTeamBooking.id)).toBeDefined();
expect(
data.find((booking) => booking.id === createdPersonalBookingUsingUsername.id)
).toBeDefined();
expect(pagination.totalItems).toEqual(3);
expect(pagination.remainingItems).toEqual(0);
expect(pagination.hasNextPage).toEqual(false);
expect(pagination.hasPreviousPage).toEqual(false);
expect(pagination.itemsPerPage).toEqual(100);
expect(pagination.totalPages).toEqual(1);
expect(pagination.currentPage).toEqual(1);
});
});
});
@@ -4,6 +4,7 @@ import { AppsRepository } from "@/modules/apps/apps.repository";
import { CredentialsRepository } from "@/modules/credentials/credentials.repository";
import { OrganizationsDelegationCredentialRepository } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.repository";
import { OrganizationsMembershipRepository } from "@/modules/organizations/memberships/organizations-membership.repository";
import { OrganizationsMembershipOutputService } from "@/modules/organizations/memberships/services/organizations-membership-output.service";
import { OrganizationsMembershipService } from "@/modules/organizations/memberships/services/organizations-membership.service";
import { PrismaModule } from "@/modules/prisma/prisma.module";
import { SelectedCalendarsController } from "@/modules/selected-calendars/controllers/selected-calendars.controller";
@@ -22,6 +23,7 @@ import { Module } from "@nestjs/common";
CredentialsRepository,
AppsRepository,
OrganizationsMembershipService,
OrganizationsMembershipOutputService,
OrganizationsDelegationCredentialRepository,
OrganizationsMembershipRepository,
SelectedCalendarsService,
@@ -1,7 +1,7 @@
import { SlotsOutputService_2024_04_15 } from "@/modules/slots/slots-2024-04-15/services/slots-output.service";
import type { RangeSlots, TimeSlots } from "@/modules/slots/slots-2024-04-15/services/slots-output.service";
import { SlotsService_2024_04_15 } from "@/modules/slots/slots-2024-04-15/services/slots.service";
import { Query, Body, Controller, Get, Delete, Post, Req, Res } from "@nestjs/common";
import { Query, Body, Controller, Get, Delete, Post, Req, Res, BadRequestException } from "@nestjs/common";
import { ApiExcludeController as DocsExcludeController } from "@nestjs/swagger";
import { ApiTags as DocsTags, ApiCreatedResponse, ApiOkResponse, ApiOperation } from "@nestjs/swagger";
import { Response as ExpressResponse, Request as ExpressRequest } from "express";
@@ -157,7 +157,11 @@ export class SlotsController_2024_04_15 {
@Query() query: GetAvailableSlotsInput_2024_04_15,
@Req() req: ExpressRequest
): Promise<ApiResponse<{ slots: TimeSlots["slots"] | RangeSlots["slots"] }>> {
const isTeamEvent = await this.slotsService.checkIfIsTeamEvent(query.eventTypeId);
try {
const isTeamEvent =
query.isTeamEvent === undefined
? await this.slotsService.checkIfIsTeamEvent(query.eventTypeId)
: query.isTeamEvent;
const availableSlots = await getAvailableSlots({
input: {
...query,
@@ -168,19 +172,29 @@ export class SlotsController_2024_04_15 {
},
});
const { slots } = await this.slotsOutputService.getOutputSlots(
availableSlots,
query.duration,
query.eventTypeId,
query.slotFormat,
query.timeZone
);
const { slots } = await this.slotsOutputService.getOutputSlots(
availableSlots,
query.duration,
query.eventTypeId,
query.slotFormat,
query.timeZone
);
return {
data: {
slots,
},
status: SUCCESS_STATUS,
};
return {
data: {
slots,
},
status: SUCCESS_STATUS,
};
} catch (error) {
if (error instanceof Error) {
if (error.message.includes("Invalid time range given")) {
throw new BadRequestException(
"Invalid time range given - check the 'startTime' and 'endTime' query parameters."
);
}
}
throw error;
}
}
}
@@ -82,7 +82,7 @@ export class SlotsController_2024_09_04 {
Optional parameters are:
- timeZone: Time zone in which the available slots should be returned. Defaults to UTC.
- duration: Only use for event types that allow multiple durations or for dynamic event types. If not passed for multiple duration event types defaults to default duration. For dynamic event types defaults to 30 aka each returned slot is 30 minutes long. So duration=60 means that returned slots will be each 60 minutes long.
- slotFormat: Format of the slots. By default return is an object where each key is date and value is array of slots as string. If you want to get start and end of each slot use "range" as value.
- format: Format of the slots. By default return is an object where each key is date and value is array of slots as string. If you want to get start and end of each slot use "range" as value.
`,
})
@ApiQuery({
@@ -99,7 +99,7 @@ export class SlotsController_2024_09_04 {
example: "60",
})
@ApiQuery({
name: "slotFormat",
name: "format",
required: false,
description:
"Format of slot times in response. Use 'range' to get start and end times. Use 'time' or omit this query parameter to get only start time.",
@@ -42,24 +42,33 @@ export class SlotsService_2024_09_04 {
) {}
async getAvailableSlots(query: GetSlotsInput_2024_09_04) {
const queryTransformed = await this.slotsInputService.transformGetSlotsQuery(query);
try {
const queryTransformed = await this.slotsInputService.transformGetSlotsQuery(query);
const availableSlots: TimeSlots = await getAvailableSlots({
input: {
...queryTransformed,
},
ctx: {},
});
const formatted = await this.slotsOutputService.getAvailableSlots(
availableSlots,
queryTransformed.eventTypeId,
queryTransformed.duration,
query.format,
queryTransformed.timeZone
);
const availableSlots: TimeSlots = await getAvailableSlots({
input: {
...queryTransformed,
},
ctx: {},
});
const formatted = await this.slotsOutputService.getAvailableSlots(
availableSlots,
queryTransformed.eventTypeId,
queryTransformed.duration,
query.format,
queryTransformed.timeZone
);
return formatted;
return formatted;
} catch (error) {
if (error instanceof Error) {
if (error.message.includes("Invalid time range given")) {
throw new BadRequestException(
"Invalid time range given - check the 'start' and 'end' query parameters."
);
}
}
throw error;
}
}
async reserveSlot(input: ReserveSlotInput_2024_09_04, authUserId?: number) {
@@ -1,4 +1,5 @@
import { EventTypesModule_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.module";
import { ConferencingRepository } from "@/modules/conferencing/repositories/conferencing.repository";
import { MembershipsModule } from "@/modules/memberships/memberships.module";
import { OrganizationsConferencingModule } from "@/modules/organizations/conferencing/organizations-conferencing.module";
import { OutputTeamEventTypesResponsePipe } from "@/modules/organizations/event-types/pipes/team-event-types-response.transformer";
@@ -31,6 +32,7 @@ import { Module } from "@nestjs/common";
OrganizationsTeamsRepository,
OutputTeamEventTypesResponsePipe,
OutputOrganizationsEventTypesService,
ConferencingRepository,
],
exports: [TeamsEventTypesRepository, TeamsEventTypesService],
controllers: [TeamsEventTypesController],
@@ -317,4 +317,73 @@ export class UsersRepository {
},
});
}
async getOrgsManagedUserEmailsBySubscriptionId(subscriptionId: string) {
return await this.dbRead.prisma.user.findMany({
distinct: ["email"],
where: {
isPlatformManaged: true,
profiles: {
some: {
organization: {
platformBilling: {
subscriptionId,
},
},
},
},
},
select: {
email: true,
},
});
}
async getActiveManagedUsersAsHost(subscriptionId: string, startTime: Date, endTime: Date) {
return await this.dbRead.prisma.user.findMany({
distinct: ["email"],
where: {
isPlatformManaged: true,
profiles: {
some: {
organization: {
platformBilling: {
subscriptionId,
},
},
},
},
bookings: {
some: {
userId: { not: null },
startTime: {
gte: startTime,
lte: endTime,
},
},
},
},
select: {
email: true,
},
});
}
async getActiveManagedUsersAsAttendee(managedUsersEmails: string[], startTime: Date, endTime: Date) {
return await this.dbRead.prisma.attendee.findMany({
distinct: ["email"],
where: {
email: { in: managedUsersEmails },
booking: {
startTime: {
gte: startTime,
lte: endTime,
},
},
},
select: {
email: true,
},
});
}
}
+418 -158
View File
@@ -1689,6 +1689,7 @@
"description": "The number of items to return",
"example": 10,
"schema": {
"default": 100,
"type": "number"
}
},
@@ -1699,6 +1700,7 @@
"description": "The number of items to skip",
"example": 0,
"schema": {
"default": 0,
"type": "number"
}
},
@@ -5603,6 +5605,7 @@
"description": "The number of items to return",
"example": 10,
"schema": {
"default": 100,
"type": "number"
}
},
@@ -5613,6 +5616,7 @@
"description": "The number of items to skip",
"example": 0,
"schema": {
"default": 0,
"type": "number"
}
}
@@ -6978,6 +6982,7 @@
"description": "The number of items to return",
"example": 10,
"schema": {
"default": 100,
"type": "number"
}
},
@@ -6988,6 +6993,7 @@
"description": "The number of items to skip",
"example": 0,
"schema": {
"default": 0,
"type": "number"
}
},
@@ -10500,7 +10506,7 @@
"get": {
"operationId": "SlotsController_2024_09_04_getAvailableSlots",
"summary": "Find out when is an event type ready to be booked.",
"description": "\n There are 4 ways to get available slots for event type of an individual user:\n\n 1. By event type id. Event type id can be of user and team event types. Example '/v2/slots?eventTypeId=10&start=2050-09-05&end=2050-09-06&timeZone=Europe/Rome'\n\n 2. By event type slug + username. Example '/v2/slots?eventTypeSlug=intro&username=bob&start=2050-09-05&end=2050-09-06'\n\n 3. By event type slug + username + organization slug when searching within an organization. Example '/v2/slots?organizationSlug=org-slug&eventTypeSlug=intro&username=bob&start=2050-09-05&end=2050-09-06'\n\n 4. By usernames only (used for dynamic event type - there is no specific event but you want to know when 2 or more people are available). Example '/v2/slots?usernames=alice,bob&username=bob&organizationSlug=org-slug&start=2050-09-05&end=2050-09-06'. As you see you also need to provide the slug of the organization to which each user in the 'usernames' array belongs.\n\n And 3 ways to get available slots for team event type:\n\n 1. By team event type id. Example '/v2/slots?eventTypeId=10&start=2050-09-05&end=2050-09-06&timeZone=Europe/Rome'\n\n 2. By team event type slug + team slug. Example '/v2/slots?eventTypeSlug=intro&teamSlug=team-slug&start=2050-09-05&end=2050-09-06'\n\n 3. By team event type slug + team slug + organization slug when searching within an organization. Example '/v2/slots?organizationSlug=org-slug&eventTypeSlug=intro&teamSlug=team-slug&start=2050-09-05&end=2050-09-06'\n\n All of them require \"start\" and \"end\" query parameters which define the time range for which available slots should be checked.\n Optional parameters are:\n - timeZone: Time zone in which the available slots should be returned. Defaults to UTC.\n - duration: Only use for event types that allow multiple durations or for dynamic event types. If not passed for multiple duration event types defaults to default duration. For dynamic event types defaults to 30 aka each returned slot is 30 minutes long. So duration=60 means that returned slots will be each 60 minutes long.\n - slotFormat: Format of the slots. By default return is an object where each key is date and value is array of slots as string. If you want to get start and end of each slot use \"range\" as value.\n ",
"description": "\n There are 4 ways to get available slots for event type of an individual user:\n\n 1. By event type id. Event type id can be of user and team event types. Example '/v2/slots?eventTypeId=10&start=2050-09-05&end=2050-09-06&timeZone=Europe/Rome'\n\n 2. By event type slug + username. Example '/v2/slots?eventTypeSlug=intro&username=bob&start=2050-09-05&end=2050-09-06'\n\n 3. By event type slug + username + organization slug when searching within an organization. Example '/v2/slots?organizationSlug=org-slug&eventTypeSlug=intro&username=bob&start=2050-09-05&end=2050-09-06'\n\n 4. By usernames only (used for dynamic event type - there is no specific event but you want to know when 2 or more people are available). Example '/v2/slots?usernames=alice,bob&username=bob&organizationSlug=org-slug&start=2050-09-05&end=2050-09-06'. As you see you also need to provide the slug of the organization to which each user in the 'usernames' array belongs.\n\n And 3 ways to get available slots for team event type:\n\n 1. By team event type id. Example '/v2/slots?eventTypeId=10&start=2050-09-05&end=2050-09-06&timeZone=Europe/Rome'\n\n 2. By team event type slug + team slug. Example '/v2/slots?eventTypeSlug=intro&teamSlug=team-slug&start=2050-09-05&end=2050-09-06'\n\n 3. By team event type slug + team slug + organization slug when searching within an organization. Example '/v2/slots?organizationSlug=org-slug&eventTypeSlug=intro&teamSlug=team-slug&start=2050-09-05&end=2050-09-06'\n\n All of them require \"start\" and \"end\" query parameters which define the time range for which available slots should be checked.\n Optional parameters are:\n - timeZone: Time zone in which the available slots should be returned. Defaults to UTC.\n - duration: Only use for event types that allow multiple durations or for dynamic event types. If not passed for multiple duration event types defaults to default duration. For dynamic event types defaults to 30 aka each returned slot is 30 minutes long. So duration=60 means that returned slots will be each 60 minutes long.\n - format: Format of the slots. By default return is an object where each key is date and value is array of slots as string. If you want to get start and end of each slot use \"range\" as value.\n ",
"parameters": [
{
"name": "cal-api-version",
@@ -10577,7 +10583,7 @@
"schema": {}
},
{
"name": "slotFormat",
"name": "format",
"required": false,
"in": "query",
"description": "Format of slot times in response. Use 'range' to get start and end times. Use 'time' or omit this query parameter to get only start time.",
@@ -17098,154 +17104,6 @@
"data"
]
},
"ConferencingAppsOutputDto": {
"type": "object",
"properties": {
"id": {
"type": "number",
"description": "Id of the conferencing app credentials"
},
"type": {
"type": "string",
"example": "google_video",
"description": "Type of conferencing app"
},
"userId": {
"type": "number",
"description": "Id of the user associated to the conferencing app"
},
"invalid": {
"type": "boolean",
"nullable": true,
"example": true,
"description": "Whether if the connection is working or not."
}
},
"required": [
"id",
"type",
"userId"
]
},
"ConferencingAppOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"success",
"error"
]
},
"data": {
"$ref": "#/components/schemas/ConferencingAppsOutputDto"
}
},
"required": [
"status",
"data"
]
},
"GetConferencingAppsOauthUrlResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
}
},
"required": [
"status"
]
},
"ConferencingAppsOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"success",
"error"
]
},
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ConferencingAppsOutputDto"
}
}
},
"required": [
"status",
"data"
]
},
"SetDefaultConferencingAppOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
}
},
"required": [
"status"
]
},
"DefaultConferencingAppsOutputDto": {
"type": "object",
"properties": {
"appSlug": {
"type": "string"
},
"appLink": {
"type": "string"
}
}
},
"GetDefaultConferencingAppOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
},
"data": {
"$ref": "#/components/schemas/DefaultConferencingAppsOutputDto"
}
},
"required": [
"status"
]
},
"DisconnectConferencingAppOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
}
},
"required": [
"status"
]
},
"OrgTeamOutputDto": {
"type": "object",
"properties": {
@@ -18260,6 +18118,143 @@
"type": "object",
"properties": {}
},
"BaseAttribute": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"id",
"name"
]
},
"TextAttribute": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"option": {
"type": "string"
},
"optionId": {
"type": "string"
}
},
"required": [
"id",
"name",
"type",
"option",
"optionId"
]
},
"NumberAttribute": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"option": {
"type": "number"
},
"optionId": {
"type": "string"
}
},
"required": [
"id",
"name",
"type",
"option",
"optionId"
]
},
"SingleSelectAttribute": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"option": {
"type": "string"
},
"optionId": {
"type": "string"
}
},
"required": [
"id",
"name",
"type",
"option",
"optionId"
]
},
"MultiSelectAttributeOption": {
"type": "object",
"properties": {
"optionId": {
"type": "string"
},
"option": {
"type": "string"
}
},
"required": [
"optionId",
"option"
]
},
"MultiSelectAttribute": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"options": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MultiSelectAttributeOption"
}
}
},
"required": [
"id",
"name",
"type",
"options"
]
},
"MembershipUserOutputDto": {
"type": "object",
"properties": {
@@ -18289,7 +18284,7 @@
"email"
]
},
"TeamMembershipOutput": {
"OrganizationMembershipOutput": {
"type": "object",
"properties": {
"id": {
@@ -18317,6 +18312,25 @@
},
"user": {
"$ref": "#/components/schemas/MembershipUserOutputDto"
},
"attributes": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/TextAttribute"
},
{
"$ref": "#/components/schemas/NumberAttribute"
},
{
"$ref": "#/components/schemas/SingleSelectAttribute"
},
{
"$ref": "#/components/schemas/MultiSelectAttribute"
}
]
}
}
},
"required": [
@@ -18325,7 +18339,8 @@
"teamId",
"accepted",
"role",
"user"
"user",
"attributes"
]
},
"GetAllOrgMemberships": {
@@ -18340,7 +18355,7 @@
]
},
"data": {
"$ref": "#/components/schemas/TeamMembershipOutput"
"$ref": "#/components/schemas/OrganizationMembershipOutput"
}
},
"required": [
@@ -18390,7 +18405,7 @@
]
},
"data": {
"$ref": "#/components/schemas/TeamMembershipOutput"
"$ref": "#/components/schemas/OrganizationMembershipOutput"
}
},
"required": [
@@ -18410,7 +18425,7 @@
]
},
"data": {
"$ref": "#/components/schemas/TeamMembershipOutput"
"$ref": "#/components/schemas/OrganizationMembershipOutput"
}
},
"required": [
@@ -18430,7 +18445,7 @@
]
},
"data": {
"$ref": "#/components/schemas/TeamMembershipOutput"
"$ref": "#/components/schemas/OrganizationMembershipOutput"
}
},
"required": [
@@ -18469,7 +18484,7 @@
]
},
"data": {
"$ref": "#/components/schemas/TeamMembershipOutput"
"$ref": "#/components/schemas/OrganizationMembershipOutput"
}
},
"required": [
@@ -19692,6 +19707,45 @@
"data"
]
},
"TeamMembershipOutput": {
"type": "object",
"properties": {
"id": {
"type": "number"
},
"userId": {
"type": "number"
},
"teamId": {
"type": "number"
},
"accepted": {
"type": "boolean"
},
"role": {
"type": "string",
"enum": [
"MEMBER",
"OWNER",
"ADMIN"
]
},
"disableImpersonation": {
"type": "boolean"
},
"user": {
"$ref": "#/components/schemas/MembershipUserOutputDto"
}
},
"required": [
"id",
"userId",
"teamId",
"accepted",
"role",
"user"
]
},
"OrgTeamMembershipsOutputResponseDto": {
"type": "object",
"properties": {
@@ -20941,6 +20995,154 @@
"data"
]
},
"ConferencingAppsOutputDto": {
"type": "object",
"properties": {
"id": {
"type": "number",
"description": "Id of the conferencing app credentials"
},
"type": {
"type": "string",
"example": "google_video",
"description": "Type of conferencing app"
},
"userId": {
"type": "number",
"description": "Id of the user associated to the conferencing app"
},
"invalid": {
"type": "boolean",
"nullable": true,
"example": true,
"description": "Whether if the connection is working or not."
}
},
"required": [
"id",
"type",
"userId"
]
},
"ConferencingAppOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"success",
"error"
]
},
"data": {
"$ref": "#/components/schemas/ConferencingAppsOutputDto"
}
},
"required": [
"status",
"data"
]
},
"GetConferencingAppsOauthUrlResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
}
},
"required": [
"status"
]
},
"ConferencingAppsOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"success",
"error"
]
},
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ConferencingAppsOutputDto"
}
}
},
"required": [
"status",
"data"
]
},
"SetDefaultConferencingAppOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
}
},
"required": [
"status"
]
},
"DefaultConferencingAppsOutputDto": {
"type": "object",
"properties": {
"appSlug": {
"type": "string"
},
"appLink": {
"type": "string"
}
}
},
"GetDefaultConferencingAppOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
},
"data": {
"$ref": "#/components/schemas/DefaultConferencingAppsOutputDto"
}
},
"required": [
"status"
]
},
"DisconnectConferencingAppOutputResponseDto": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "success",
"enum": [
"success",
"error"
]
}
},
"required": [
"status"
]
},
"GoogleServiceAccountKeyInput": {
"type": "object",
"properties": {
@@ -23941,6 +24143,60 @@
"data"
]
},
"PaginationMetaDto": {
"type": "object",
"properties": {
"totalItems": {
"type": "number",
"minimum": 0,
"description": "The total number of items available across all pages, matching the query criteria.",
"example": 123
},
"remainingItems": {
"type": "number",
"minimum": 0,
"description": "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
"example": 103
},
"itemsPerPage": {
"type": "number",
"minimum": 1,
"description": "The maximum number of items requested per page.",
"example": 10
},
"currentPage": {
"type": "number",
"minimum": 1,
"description": "The current page number being returned.",
"example": 2
},
"totalPages": {
"type": "number",
"minimum": 0,
"description": "The total number of pages available.",
"example": 13
},
"hasNextPage": {
"type": "boolean",
"description": "Indicates if there is a subsequent page available after the current one.",
"example": true
},
"hasPreviousPage": {
"type": "boolean",
"description": "Indicates if there is a preceding page available before the current one.",
"example": true
}
},
"required": [
"totalItems",
"remainingItems",
"itemsPerPage",
"currentPage",
"totalPages",
"hasNextPage",
"hasPreviousPage"
]
},
"GetBookingsOutput_2024_08_13": {
"type": "object",
"properties": {
@@ -23972,13 +24228,17 @@
},
"description": "Array of booking data, which can contain either BookingOutput objects or RecurringBookingOutput objects"
},
"pagination": {
"$ref": "#/components/schemas/PaginationMetaDto"
},
"error": {
"type": "object"
}
},
"required": [
"status",
"data"
"data",
"pagination"
]
},
"RescheduleBookingInput_2024_08_13": {
@@ -0,0 +1,17 @@
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { TestingModule } from "@nestjs/testing";
export class WorkflowReminderRepositoryFixture {
private prismaReadClient: PrismaReadService["prisma"];
private prismaWriteClient: PrismaWriteService["prisma"];
constructor(private readonly module: TestingModule) {
this.prismaReadClient = module.get(PrismaReadService).prisma;
this.prismaWriteClient = module.get(PrismaWriteService).prisma;
}
async getByBookingUid(uid: string) {
return this.prismaReadClient.workflowReminder.findFirst({ where: { bookingUid: uid } });
}
}
@@ -0,0 +1,23 @@
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { TestingModule } from "@nestjs/testing";
import { Prisma } from "@calcom/prisma/client";
export class WorkflowRepositoryFixture {
private prismaReadClient: PrismaReadService["prisma"];
private prismaWriteClient: PrismaWriteService["prisma"];
constructor(private readonly module: TestingModule) {
this.prismaReadClient = module.get(PrismaReadService).prisma;
this.prismaWriteClient = module.get(PrismaWriteService).prisma;
}
async create(data: Prisma.WorkflowCreateInput) {
return this.prismaWriteClient.workflow.create({ data });
}
async delete(id: number) {
return this.prismaWriteClient.workflow.delete({ where: { id } });
}
}
@@ -58,7 +58,7 @@ Buttons can be grouped together using the ButtonGroup component. The ButtonGroup
### Button Group Sizes
#### Seperated
#### Separated
<ButtonGroupSizes/>
@@ -9,7 +9,7 @@ export const SizesExample: React.FC = () => (
<div className="space-y-4 md:w-80">
<div className="space-y-2">
<h3 className="text-emphasis text-sm">Default Height</h3>
<TextAreaField name="deafult" placeholder="Default height textarea..." />
<TextAreaField name="default" placeholder="Default height textarea..." />
</div>
<div className="space-y-2">
+3 -1
View File
@@ -69,4 +69,6 @@ public/embed
# Copied app-store images
public/app-store
certificates
certificates
# Sentry Config File
.env.sentry-build-plugin
@@ -1,8 +1,9 @@
import type { NextApiResponse } from "next";
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseRequestData } from "app/api/parseRequestData";
import { NextResponse, type NextRequest } from "next/server";
import calcomSignupHandler from "@calcom/feature-auth/signup/handlers/calcomHandler";
import selfHostedSignupHandler from "@calcom/feature-auth/signup/handlers/selfHostedHandler";
import { type RequestWithUsernameStatus } from "@calcom/features/auth/signup/username";
import { FeaturesRepository } from "@calcom/features/flags/features.repository";
import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants";
import getIP from "@calcom/lib/getIP";
@@ -11,12 +12,12 @@ import logger from "@calcom/lib/logger";
import { checkCfTurnstileToken } from "@calcom/lib/server/checkCfTurnstileToken";
import { signupSchema } from "@calcom/prisma/zod-utils";
async function ensureSignupIsEnabled(req: RequestWithUsernameStatus) {
async function ensureSignupIsEnabled(body: Record<string, string>) {
const { token } = signupSchema
.pick({
token: true,
})
.parse(req.body);
.parse(body);
// Still allow signups if there is a team invite
if (token) return;
@@ -32,26 +33,17 @@ async function ensureSignupIsEnabled(req: RequestWithUsernameStatus) {
}
}
function ensureReqIsPost(req: RequestWithUsernameStatus) {
if (req.method !== "POST") {
throw new HttpError({
statusCode: 405,
message: "Method not allowed",
});
}
}
export default async function handler(req: RequestWithUsernameStatus, res: NextApiResponse) {
async function handler(req: NextRequest) {
const remoteIp = getIP(req);
// Use a try catch instead of returning res every time
try {
const body = await parseRequestData(req);
await checkCfTurnstileToken({
token: req.headers["cf-access-token"] as string,
token: req.headers.get("cf-access-token") as string,
remoteIp,
});
ensureReqIsPost(req);
await ensureSignupIsEnabled(req);
await ensureSignupIsEnabled(body);
/**
* Im not sure its worth merging these two handlers. They are different enough to be separate.
@@ -61,15 +53,17 @@ export default async function handler(req: RequestWithUsernameStatus, res: NextA
* @zomars: We need to be able to test this with E2E. They way it's done RN it will never run on CI.
*/
if (IS_PREMIUM_USERNAME_ENABLED) {
return await calcomSignupHandler(req, res);
return await calcomSignupHandler(body);
}
return await selfHostedSignupHandler(req, res);
return await selfHostedSignupHandler(body);
} catch (e) {
if (e instanceof HttpError) {
return res.status(e.statusCode).json({ message: e.message });
return NextResponse.json({ message: e.message }, { status: e.statusCode });
}
logger.error(e);
return res.status(500).json({ message: "Internal server error" });
return NextResponse.json({ message: "Internal server error" }, { status: 500 });
}
}
export const POST = defaultResponderForAppDir(handler);
@@ -5,7 +5,8 @@ import { NextResponse } from "next/server";
import dayjs from "@calcom/dayjs";
import { sendOrganizerRequestReminderEmail } from "@calcom/emails";
import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses";
import { isPrismaObjOrUndefined, parseRecurringEvent } from "@calcom/lib";
import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj";
import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
import { getTranslation } from "@calcom/lib/server/i18n";
import prisma, { bookingMinimalSelect } from "@calcom/prisma";
import { BookingStatus, ReminderType } from "@calcom/prisma/enums";
@@ -0,0 +1,117 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import dayjs from "@calcom/dayjs";
import * as twilio from "@calcom/features/ee/workflows/lib/reminders/providers/twilioProvider";
import { IS_SMS_CREDITS_ENABLED } from "@calcom/lib/constants";
import logger from "@calcom/lib/logger";
import prisma from "@calcom/prisma";
import { CreditType } from "@calcom/prisma/enums";
async function postHandler(req: NextRequest) {
const apiKey = req.headers.get("authorization") || req.nextUrl.searchParams.get("apiKey");
if (process.env.CRON_API_KEY !== apiKey) {
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
}
if (!IS_SMS_CREDITS_ENABLED) {
return NextResponse.json({ ok: true, message: "SMS credits not enabled" });
}
const smsLogsWithoutPrice = await prisma.creditExpenseLog.findMany({
where: {
credits: null,
smsSid: {
not: null,
},
date: {
gte: dayjs().subtract(1, "hour").toDate(),
},
},
select: {
smsSid: true,
id: true,
},
});
let pricesUpdated = 0;
const { CreditService } = await import("@calcom/features/ee/billing/credit-service");
const creditService = new CreditService();
await Promise.allSettled(
smsLogsWithoutPrice.map(async (log) => {
if (!log.smsSid) return;
try {
const price = await twilio.getPriceForSMS(log.smsSid);
const credits = price ? creditService.calculateCreditsFromPrice(price) : null;
if (!credits) return;
const updatedLog = await prisma.creditExpenseLog.update({
where: { id: log.id },
data: { credits },
select: {
creditBalance: {
select: {
id: true,
additionalCredits: true,
teamId: true,
userId: true,
},
},
creditType: true,
},
});
if (updatedLog.creditType === CreditType.ADDITIONAL) {
const decrementValue =
credits <= updatedLog.creditBalance.additionalCredits
? credits
: updatedLog.creditBalance.additionalCredits;
await prisma.creditBalance.update({
where: { id: updatedLog.creditBalance.id },
data: {
additionalCredits: {
decrement: decrementValue,
},
},
});
}
if (!updatedLog.creditBalance.teamId && !updatedLog.creditBalance.userId) {
logger.error(`teamId or userId missing for expense log ${log.id}`);
return;
}
const availableCredits = await creditService.getAllCredits({
teamId: updatedLog.creditBalance.teamId,
userId: updatedLog.creditBalance.userId,
});
const remainingMonthlyCredits = Math.max(0, availableCredits.totalRemainingMonthlyCredits);
await creditService.handleLowCreditBalance({
userId: updatedLog.creditBalance.userId,
teamId: updatedLog.creditBalance.teamId,
remainingCredits: remainingMonthlyCredits + availableCredits.additionalCredits,
});
pricesUpdated++;
} catch (err) {
logger.error(`Failed to process SMS log ${log.smsSid}`, err);
await prisma.creditExpenseLog.update({
where: { id: log.id },
data: { credits: 0 },
});
}
})
);
return NextResponse.json({ ok: true, pricesUpdated });
}
export const POST = defaultResponderForAppDir(postHandler);
+18 -6
View File
@@ -1,8 +1,14 @@
/**
* @description This route is used to create and delete Credential records for all members of an organization that has delegation credentials enabled.
*
* It also deletes Credential records for all members of an organization that has delegation credentials disabled.
*/
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { HttpError } from "@calcom/lib/http-error";
import logger from "@calcom/lib/logger";
import { safeStringify } from "@calcom/lib/safeStringify";
import { CredentialRepository } from "@calcom/lib/server/repository/credential";
import { DelegationCredentialRepository } from "@calcom/lib/server/repository/delegationCredential";
@@ -37,7 +43,7 @@ async function handleCreateCredentials() {
log.info(
`Skipping credential creation for workspace platform ${workspacePlatform.slug} - only google is supported`
);
return;
continue;
}
// We can't know by looking at a Credential record in DB, if it has access to the `user.email` calendar in Google Calendar.
@@ -50,15 +56,15 @@ async function handleCreateCredentials() {
});
const existingCredentialUserIds = new Set(existingCredentials.map((cred) => cred.userId));
const membersNeedingCredentials = organization.delegatedMembers.filter(
const delegatedMembers = organization.delegatedMembers;
const membersNeedingCredentials = delegatedMembers.filter(
(member) => !existingCredentialUserIds.has(member.userId)
);
const toProcessMembers = membersNeedingCredentials.slice(0, batchSizeToCreateCredentials);
log.info(
`Creating credentials for ${toProcessMembers.length} members in organization ${organization.id}`
`Creating credentials for ${toProcessMembers.length} members out of ${delegatedMembers.length} delegated members in organization ${organization.id}`
);
const credentialCreationPromises = toProcessMembers.map(async (member) => {
@@ -75,18 +81,24 @@ async function handleCreateCredentials() {
});
log.info(`Created credential for member ${member.userId}`);
} catch (error) {
log.error(`Error creating credential for member ${member.userId}:`, error);
log.error(`Error creating credential for member ${member.userId}:`, safeStringify(error));
throw error;
}
});
const results = await Promise.allSettled(credentialCreationPromises);
const successCount = results.filter((r) => r.status === "fulfilled").length;
const failureCount = results.filter((r) => r.status === "rejected").length;
log.info(
`Created ${successCount} credentials for delegationCredentialId: ${delegationCredential.id} and ${failureCount} failures`
);
totalSuccess += successCount;
totalFailures += failureCount;
}
log.info(
`Completed creating credentials for all delegation credentials. Total Success: ${totalSuccess}, Total Failures: ${totalFailures}`
);
return {
executedAt: new Date().toISOString(),
success: totalSuccess,
@@ -1,3 +1,8 @@
/**
* @description This route is used to create SelectedCalendar records based on Credential records corresponding to Delegation Credentials
*
* It works in conjunction with `/api/cron/credentials` route(which creates the Credential records for all the members of an organization that has delegation credentials enabled)
*/
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -31,8 +36,10 @@ async function handleCreateSelectedCalendars() {
});
if (!allDelegationUserCredentials.length) {
const message = "No delegation credentials found";
log.info(message);
return {
message: "No delegation credentials found",
message,
success: 0,
failures: 0,
};
@@ -153,17 +160,19 @@ async function handleCreateSelectedCalendars() {
);
const successCount = results.filter((r) => r.status === "fulfilled").length;
const failureCount = results.filter((r) => r.status === "rejected").length;
log.info(
`Processed ${successCount} selected calendars for delegationCredentialId: ${delegationCredentialId} and ${failureCount} failures`
);
totalSuccess += successCount;
totalFailures += failureCount;
}
log.info(
`Completed processing all selected calendars. Total Success: ${totalSuccess}, Total Failures: ${totalFailures}`
`Completed creating selected calendars for all delegation credentials. Total Success: ${totalSuccess}, Total Failures: ${totalFailures}`
);
return {
message: "All selected calendars processed",
message: "All selected calendars created",
executedAt: new Date().toISOString(),
success: totalSuccess,
failures: totalFailures,
+2 -2
View File
@@ -1,9 +1,9 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { NextResponse } from "next/server";
import * as pjson from "package.json";
import packageJson from "package.json";
async function getHandler() {
return NextResponse.json({ version: pjson.version });
return NextResponse.json({ version: packageJson.version });
}
export const GET = defaultResponderForAppDir(getHandler);
+5
View File
@@ -1,11 +1,16 @@
"use client";
import * as Sentry from "@sentry/nextjs";
import { type NextPage } from "next";
import { useEffect } from "react";
import CustomError from "./error";
import type { ErrorProps } from "./error";
export const GlobalError: NextPage<ErrorProps> = (props) => {
useEffect(() => {
Sentry.captureException(props.error);
}, [props.error]);
return (
<html>
<body>
+1 -4
View File
@@ -7,7 +7,6 @@ import React from "react";
import { getLocale } from "@calcom/features/auth/lib/getLocale";
import { loadTranslations } from "@calcom/lib/server/i18n";
import { IconSprites } from "@calcom/ui/components/icon";
import { NotificationSoundHandler } from "@calcom/web/components/notification-sound-handler";
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
@@ -152,13 +151,11 @@ export default async function RootLayout({ children }: { children: React.ReactNo
]}
/>
<Providers>
<Providers isEmbed={isEmbed}>
<AppRouterI18nProvider translations={translations} locale={locale} ns={ns}>
{children}
</AppRouterI18nProvider>
</Providers>
{!isEmbed && <NotificationSoundHandler />}
<NotificationSoundHandler />
</body>
</html>
);
+4 -1
View File
@@ -5,20 +5,23 @@ import { SessionProvider } from "next-auth/react";
import CacheProvider from "react-inlinesvg/provider";
import { WebPushProvider } from "@calcom/features/notifications/WebPushContext";
import { NotificationSoundHandler } from "@calcom/web/components/notification-sound-handler";
import useIsBookingPage from "@lib/hooks/useIsBookingPage";
import PlainChat from "@lib/plain/dynamicProvider";
type ProvidersProps = {
isEmbed: boolean;
children: React.ReactNode;
};
export function Providers({ children }: ProvidersProps) {
export function Providers({ isEmbed, children }: ProvidersProps) {
const isBookingPage = useIsBookingPage();
return (
<SessionProvider>
<TrpcProvider>
{!isBookingPage ? <PlainChat /> : null}
{!isEmbed && !isBookingPage && <NotificationSoundHandler />}
{/* @ts-expect-error FIXME remove this comment when upgrading typescript to v5 */}
<CacheProvider>
<WebPushProvider>{children}</WebPushProvider>
@@ -1,6 +1,6 @@
import { useForm } from "react-hook-form";
import { Schedule } from "@calcom/features/schedules";
import Schedule from "@calcom/features/schedules/components/Schedule";
import { DEFAULT_SCHEDULE } from "@calcom/lib/availability";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
+32
View File
@@ -0,0 +1,32 @@
// This file configures the initialization of Sentry on the client.
// The added config here will be used whenever a users loads a page in their browser.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
sampleRate: parseFloat(process.env.SENTRY_SAMPLE_RATE ?? "1.0") || 1.0,
// Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control.
tracesSampleRate: parseFloat(process.env.SENTRY_TRACES_SAMPLE_RATE ?? "0.0") || 0.0,
// Define how likely Replay events are sampled.
// This sets the sample rate to be 10%. You may want this to be 100% while
// in development and sample at a lower rate in production
// replaysSessionSampleRate: parseFloat(process.env.SENTRY_REPLAYS_SESSION_SAMPLE_RATE ?? "0.0") || 0.0,
// Define how likely Replay events are sampled when an error occurs.
// replaysOnErrorSampleRate: parseFloat(process.env.SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE ?? "0.0") || 0.0,
// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: !!process.env.SENTRY_DEBUG,
beforeSend(event) {
event.tags = {
...event.tags,
errorSource: "client",
};
return event;
},
});
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
+4
View File
@@ -1,3 +1,5 @@
import * as Sentry from "@sentry/nextjs";
export async function register() {
if (process.env.NEXT_PUBLIC_SENTRY_DSN && process.env.NEXT_RUNTIME === "nodejs") {
await import("./sentry.server.config");
@@ -7,3 +9,5 @@ export async function register() {
await import("./sentry.edge.config");
}
}
export const onRequestError = Sentry.captureRequestError;
+1 -1
View File
@@ -13,7 +13,7 @@ const enum ThemeSupport {
}
/**
* Returns a unique indentifier that remains same as long as we land on the public page for same entity like event-type/routing-form/dynamic-group-booking etc
* Returns a unique identifier that remains the same as long as we land on the public page for the same entity like event-type/routing-form/dynamic-group-booking etc
* The theme stays same for same identifier.
*/
export function getUniqueIdentifierForBookingPage({ pathname }: { pathname: string }) {
@@ -6,6 +6,7 @@ import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
import { getBookingForReschedule } from "@calcom/features/bookings/lib/get-booking";
import { getSlugOrRequestedSlug, orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
import { getOrganizationSEOSettings } from "@calcom/features/ee/organizations/lib/orgSettings";
import { FeaturesRepository } from "@calcom/features/flags/features.repository";
import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage";
import slugify from "@calcom/lib/slugify";
import prisma from "@calcom/prisma";
@@ -113,8 +114,12 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) =>
const organizationSettings = getOrganizationSEOSettings(team);
const allowSEOIndexing = organizationSettings?.allowSEOIndexing ?? false;
const featureRepo = new FeaturesRepository();
const useApiV2 = await featureRepo.checkIfTeamHasFeature(team.id, "use-api-v2-for-team-slots");
return {
props: {
useApiV2,
eventData: {
eventTypeId,
entity: {
+4 -4
View File
@@ -15,15 +15,14 @@ import { HOSTED_CAL_FEATURES, WEBAPP_URL, WEBSITE_URL } from "@calcom/lib/consta
import { emailRegex } from "@calcom/lib/emailSchema";
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import { useLastUsed, LastUsed } from "@calcom/lib/hooks/useLastUsed";
import { LastUsed, useLastUsed } from "@calcom/lib/hooks/useLastUsed";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { useTelemetry } from "@calcom/lib/hooks/useTelemetry";
import { collectPageParameters, telemetryEventTypes } from "@calcom/lib/telemetry";
import { trpc } from "@calcom/trpc/react";
import { Alert } from "@calcom/ui/components/alert";
import { Button } from "@calcom/ui/components/button";
import { EmailField } from "@calcom/ui/components/form";
import { PasswordField } from "@calcom/ui/components/form";
import { EmailField, PasswordField } from "@calcom/ui/components/form";
import type { inferSSRProps } from "@lib/types/inferSSRProps";
import type { WithNonceProps } from "@lib/withNonce";
@@ -254,12 +253,13 @@ PageProps & WithNonceProps<{}>) {
defaultValue={totpEmail || (searchParams?.get("email") as string)}
placeholder="john.doe@example.com"
required
autoComplete="email"
{...register("email")}
/>
<div className="relative">
<PasswordField
id="password"
autoComplete="off"
autoComplete="current-password"
required={!totpEmail}
className="mb-0"
{...register("password")}
@@ -8,7 +8,8 @@ import { useCallback, useState } from "react";
import { BulkEditDefaultForEventsModal } from "@calcom/features/eventtypes/components/BulkEditDefaultForEventsModal";
import type { BulkUpdatParams } from "@calcom/features/eventtypes/components/BulkEditDefaultForEventsModal";
import { NewScheduleButton, ScheduleListItem } from "@calcom/features/schedules";
import { NewScheduleButton } from "@calcom/features/schedules/components/NewScheduleButton";
import { ScheduleListItem } from "@calcom/features/schedules/components/ScheduleListItem";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { HttpError } from "@calcom/lib/http-error";
@@ -5,8 +5,8 @@ import { z } from "zod";
import { orgDomainConfig } from "@calcom/ee/organizations/lib/orgDomains";
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import getBookingInfo from "@calcom/features/bookings/lib/getBookingInfo";
import { parseRecurringEvent } from "@calcom/lib";
import { getDefaultEvent } from "@calcom/lib/defaultEvents";
import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent";
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
import { maybeGetBookingUidFromSeat } from "@calcom/lib/server/maybeGetBookingUidFromSeat";
import { BookingRepository } from "@calcom/lib/server/repository/booking";
@@ -236,6 +236,7 @@ export default function Success(props: PageProps) {
if (eventType.isDynamic && bookingInfo.responses?.title) {
evtName = bookingInfo.responses.title as string;
}
const eventNameObject = {
attendeeName: bookingInfo.responses.name as z.infer<typeof nameObjectSchema> | string,
eventType: eventType.title,
@@ -243,7 +244,7 @@ export default function Success(props: PageProps) {
host: props.profile.name || "Nameless",
location: location,
bookingFields: bookingInfo.responses,
eventDuration: eventType.length,
eventDuration: dayjs(bookingInfo.endTime).diff(bookingInfo.startTime, "minutes"),
t,
};
@@ -15,7 +15,6 @@ import { EventTypeDescription } from "@calcom/features/eventtypes/components";
import CreateEventTypeDialog from "@calcom/features/eventtypes/components/CreateEventTypeDialog";
import { DuplicateDialog } from "@calcom/features/eventtypes/components/DuplicateDialog";
import { InfiniteSkeletonLoader } from "@calcom/features/eventtypes/components/SkeletonLoader";
import { parseEventTypeColor } from "@calcom/lib";
import { APP_NAME, WEBSITE_URL } from "@calcom/lib/constants";
import { useCopy } from "@calcom/lib/hooks/useCopy";
import { useDebounce } from "@calcom/lib/hooks/useDebounce";
@@ -24,6 +23,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
import { useGetTheme } from "@calcom/lib/hooks/useTheme";
import { useTypedQuery } from "@calcom/lib/hooks/useTypedQuery";
import { HttpError } from "@calcom/lib/http-error";
import { parseEventTypeColor } from "@calcom/lib/isEventTypeColor";
import type { MembershipRole } from "@calcom/prisma/enums";
import { SchedulingType } from "@calcom/prisma/enums";
import type { RouterOutputs } from "@calcom/trpc/react";
@@ -596,7 +596,7 @@ export const InfiniteEventTypeList = ({
variant="icon"
color="secondary"
StartIcon="ellipsis"
// Unsual practice to use radix state open but for some reason this dropdown and only thi dropdown clears the border radius of this button.
// Unusual practice to use radix state open but for some reason this dropdown and only this dropdown clears the border radius of this button.
className="ltr:radix-state-open:rounded-r-[--btn-group-radius] rtl:radix-state-open:rounded-l-[--btn-group-radius]"
/>
</DropdownMenuTrigger>
@@ -9,7 +9,7 @@ export default function MaintenancePage() {
return (
<div className="bg-subtle flex h-screen">
<div className="bg-default m-auto rounded-md p-10 text-right ltr:text-left">
<h1 className="text-emphasis text-2xl font-medium">{t("down_for_maintenance")}</h1>
<h1 className="text-emphasis text-2xl font-medium">{t("under_maintenance")}</h1>
<p className="text-default mb-6 mt-4 max-w-2xl text-sm">{t("maintenance_message")}</p>
<Button href={`${WEBSITE_URL}/support`}>{t("contact_support")}</Button>
</div>
@@ -4,8 +4,10 @@ import { usePathname } from "next/navigation";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button } from "@calcom/ui/components/button";
import classNames from "@calcom/ui/classNames";
import { Button } from "@calcom/ui/components/button";
import BillingCredits from "~/settings/billing/components/BillingCredits";
interface CtaRowProps {
title: string;
@@ -58,9 +60,9 @@ const BillingView = () => {
{t("billing_portal")}
</Button>
</CtaRow>
<hr className="border-subtle" />
</div>
<BillingCredits />
<div className="border-subtle mt-6 space-y-6 rounded-lg border px-6 py-8 text-sm sm:space-y-8">
<CtaRow title={t("need_anything_else")} description={t("further_billing_help")}>
<Button color="secondary" onClick={onContactSupportClick}>
{t("contact_support")}
@@ -0,0 +1,132 @@
"use client";
import { ProgressBar } from "@tremor/react";
import { useRouter } from "next/navigation";
import { useForm } from "react-hook-form";
import { IS_SMS_CREDITS_ENABLED } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { useParamsWithFallback } from "@calcom/lib/hooks/useParamsWithFallback";
import { trpc } from "@calcom/trpc/react";
import { Button } from "@calcom/ui/components/button";
import { TextField, Label, InputError } from "@calcom/ui/components/form";
import { showToast } from "@calcom/ui/toast";
import { BillingCreditsSkeleton } from "./BillingCreditsSkeleton";
export default function BillingCredits() {
const { t } = useLocale();
const router = useRouter();
const {
register,
handleSubmit,
setValue,
formState: { errors },
} = useForm<{ quantity: number }>({ defaultValues: { quantity: 50 } });
const params = useParamsWithFallback();
const teamId = params.id ? Number(params.id) : undefined;
const { data: creditsData, isLoading } = trpc.viewer.credits.getAllCredits.useQuery({ teamId });
const buyCreditsMutation = trpc.viewer.credits.buyCredits.useMutation({
onSuccess: (data) => {
if (data.sessionUrl) {
router.push(data.sessionUrl);
}
},
onError: () => {
showToast(t("credit_purchase_failed"), "error");
},
});
if (!IS_SMS_CREDITS_ENABLED) {
return null;
}
if (isLoading && teamId) return <BillingCreditsSkeleton />;
if (!creditsData) return null;
const onSubmit = (data: { quantity: number }) => {
buyCreditsMutation.mutate({ quantity: data.quantity, teamId });
};
const teamCreditsPercentageUsed =
creditsData.credits.totalMonthlyCredits > 0
? (creditsData.credits.totalRemainingMonthlyCredits / creditsData.credits.totalMonthlyCredits) * 100
: 0;
return (
<div className="border-subtle mt-8 space-y-6 rounded-lg border px-6 py-6 pb-6 text-sm sm:space-y-8">
<div>
<h2 className="text-base font-semibold">{t("credits")}</h2>
<p>{t("view_and_manage_credits_description")}</p>
<div className="-mx-6 mt-6">
<hr className="border-subtle" />
</div>
<div className="mt-6">
{creditsData.credits.totalMonthlyCredits > 0 ? (
<div className="mb-4">
<Label>{t("monthly_credits")}</Label>
<ProgressBar
color="green"
percentageValue={teamCreditsPercentageUsed}
label={`${Math.max(0, Math.round(teamCreditsPercentageUsed))}%`}
/>
<div className="text-subtle">
<div>
{t("total_credits", {
totalCredits: creditsData.credits.totalMonthlyCredits,
})}
</div>
<div>
{t("remaining_credits", {
remainingCredits: creditsData.credits.totalRemainingMonthlyCredits,
})}
</div>
</div>
</div>
) : (
<></>
)}
<Label>
{creditsData.credits.totalMonthlyCredits ? t("additional_credits") : t("available_credits")}
</Label>
<div className="mt-2 text-sm">{creditsData.credits.additionalCredits}</div>
<div className="-mx-6 mb-6 mt-6">
<hr className="border-subtle mb-3 mt-3" />
</div>
<form onSubmit={handleSubmit(onSubmit)} className="flex">
<div className="mr-auto">
<div className="mb-2 font-semibold">{t("buy_additional_credits")}</div>
<div className="flex flex-col">
<TextField
required
type="number"
{...register("quantity", {
required: t("error_required_field"),
min: { value: 50, message: t("minimum_of_credits_required") },
valueAsNumber: true,
})}
label=""
containerClassName="w-60"
onChange={(e) => setValue("quantity", Number(e.target.value))}
min={50}
addOnSuffix={<>{t("credits")}</>}
/>
{errors.quantity && <InputError message={errors.quantity.message ?? t("invalid_input")} />}
</div>
</div>
<div className="mb-1 mt-auto">
<Button color="primary" target="_blank" EndIcon="external-link" type="submit">
{t("buy_credits")}
</Button>
</div>
</form>
</div>
</div>
</div>
);
}
@@ -0,0 +1,63 @@
import { SkeletonText, SkeletonContainer, SkeletonButton } from "@calcom/ui/components/skeleton";
export function BillingCreditsSkeleton() {
return (
<SkeletonContainer>
<div className="border-subtle mt-8 space-y-6 rounded-lg border px-6 py-6 text-sm sm:space-y-8">
{/* Title and Description */}
<div>
<div>
<SkeletonText className="mb-2 h-4 w-20" /> {/* Credits title */}
</div>
<div>
<SkeletonText className="h-4 w-72" /> {/* Description */}
</div>
<div className="-mx-6 mt-6">
<hr className="border-subtle" />
</div>
{/* Monthly credits */}
<div className="mt-[20px]">
<SkeletonText className="mb-4 h-4 w-32" /> {/* Monthly credits label */}
<div className="h-2 w-full rounded-md bg-gray-200" /> {/* Progress bar */}
<div className="text-subtle mt-2">
<div>
<SkeletonText className="h-4 w-40" /> {/* Total credits */}
</div>
<div>
<SkeletonText className="h-4 w-40" /> {/* Remaining credits */}
</div>
</div>
</div>
{/* Additional credits */}
<div className="mt-4">
<div>
<SkeletonText className="mb-2 h-4 w-40" /> {/* Additional credits label */}
</div>
<div>
<SkeletonText className="h-4 w-24" /> {/* Additional credits value */}
</div>
</div>
<div className="-mx-6 mb-6 mt-4">
<hr className="border-subtle mb-3 mt-3" />
</div>
{/* Buy credits form */}
<div className="flex">
<div className="mr-auto">
<div>
<SkeletonText className="mb-2 mt-1 h-5 w-[268px]" /> {/* Buy credits label */}
</div>
<div>
<SkeletonText className="mt-2 h-8 w-[240px] rounded-md" /> {/* Input field */}
</div>
</div>
<div className="mt-auto ">
<SkeletonButton className="h-9 w-[120px] rounded-md" /> {/* Buy button */}
</div>
</div>
</div>
</div>
</SkeletonContainer>
);
}
+4
View File
@@ -408,9 +408,11 @@ export default function Signup({
) : null}
{/* Email */}
<TextField
id="signup-email"
{...register("email")}
label={t("email")}
type="email"
autoComplete="email"
disabled={prepopulateFormValues?.email}
data-testid="signup-emailfield"
/>
@@ -418,7 +420,9 @@ export default function Signup({
{/* Password */}
{!isSamlSignup && (
<PasswordField
id="signup-password"
data-testid="signup-passwordfield"
autoComplete="new-password"
label={t("password")}
{...register("password")}
hintErrors={["caplow", "min", "num"]}
+2
View File
@@ -35,6 +35,7 @@ function Type({
crmOwnerRecordType,
crmAppSlug,
isEmbed,
useApiV2,
}: PageProps) {
const searchParams = useSearchParams();
@@ -42,6 +43,7 @@ function Type({
<BookingPageErrorBoundary>
<main className={getBookerWrapperClasses({ isEmbed: !!isEmbed })}>
<Booker
useApiV2={useApiV2}
username={user}
eventSlug={slug}
bookingData={booking}
+1 -52
View File
@@ -1,9 +1,6 @@
require("dotenv").config({ path: "../../.env" });
const CopyWebpackPlugin = require("copy-webpack-plugin");
const os = require("os");
const englishTranslation = require("./public/static/locales/en/common.json");
const { withAxiom } = require("next-axiom");
const { withSentryConfig } = require("@sentry/nextjs");
const { version } = require("./package.json");
const {
i18n: { locales },
@@ -190,9 +187,8 @@ const nextConfig = {
experimental: {
// externalize server-side node_modules with size > 1mb, to improve dev mode performance/RAM usage
optimizePackageImports: ["@calcom/ui"],
turbo: {},
},
productionBrowserSourceMaps: process.env.SENTRY_DISABLE_CLIENT_SOURCE_MAPS === "0",
productionBrowserSourceMaps: true,
/* We already do type check on GH actions */
typescript: {
ignoreBuildErrors: !!process.env.CI,
@@ -228,10 +224,6 @@ const nextConfig = {
},
webpack: (config, { webpack, buildId, isServer }) => {
if (isServer) {
if (process.env.SENTRY_DISABLE_SERVER_SOURCE_MAPS === "1") {
config.devtool = false;
}
// Module not found fix @see https://github.com/boxyhq/jackson/issues/1535#issuecomment-1704381612
config.plugins.push(
new webpack.IgnorePlugin({
@@ -243,34 +235,6 @@ const nextConfig = {
config.externals.push("formidable");
}
config.plugins.push(
new webpack.DefinePlugin({
__SENTRY_DEBUG__: false,
__SENTRY_TRACING__: false,
})
);
config.plugins.push(
new CopyWebpackPlugin({
patterns: [
{
from: "../../packages/app-store/**/static/**",
to({ context, absoluteFilename }) {
// Adds compatibility for windows path
if (os.platform() === "win32") {
const absoluteFilenameWin = absoluteFilename.replaceAll("\\", "/");
const contextWin = context.replaceAll("\\", "/");
const appName = /app-store\/(.*)\/static/.exec(absoluteFilenameWin);
return Promise.resolve(`${contextWin}/public/app-store/${appName[1]}/[name][ext]`);
}
const appName = /app-store\/(.*)\/static/.exec(absoluteFilename);
return Promise.resolve(`${context}/public/app-store/${appName[1]}/[name][ext]`);
},
},
],
})
);
config.plugins.push(new webpack.DefinePlugin({ "process.env.BUILD_ID": JSON.stringify(buildId) }));
config.resolve.fallback = {
@@ -714,19 +678,4 @@ const nextConfig = {
},
};
if (!!process.env.NEXT_PUBLIC_SENTRY_DSN) {
plugins.push((nextConfig) =>
withSentryConfig(nextConfig, {
autoInstrumentServerFunctions: false,
hideSourceMaps: true,
// disable source map generation for the server code
disableServerWebpackPlugin: !!process.env.SENTRY_DISABLE_SERVER_WEBPACK_PLUGIN,
silent: false,
sourcemaps: {
disable: process.env.SENTRY_DISABLE_SERVER_SOURCE_MAPS === "1",
},
})
);
}
module.exports = () => plugins.reduce((acc, next) => next(acc), nextConfig);
+7 -5
View File
@@ -1,20 +1,22 @@
{
"name": "@calcom/web",
"version": "5.2.13",
"version": "5.2.17",
"private": true,
"scripts": {
"analyze": "ANALYZE=true next build",
"analyze:server": "BUNDLE_ANALYZE=server next build",
"analyze:browser": "BUNDLE_ANALYZE=browser next build",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next",
"dev": "next dev --turbopack",
"dev": "yarn copy-static && next dev --turbopack",
"dev:cron": "ts-node cron-tester.ts",
"dev-https": "NODE_TLS_REJECT_UNAUTHORIZED=0 next dev --experimental-https",
"dx": "yarn dev",
"test-codegen": "yarn playwright codegen http://localhost:3000",
"type-check": "tsc --pretty --noEmit",
"type-check:ci": "tsc-absolute --pretty --noEmit",
"build": "next build",
"sentry:release": "NODE_OPTIONS='--max-old-space-size=6144' node scripts/create-sentry-release.js",
"copy-static": "node scripts/copy-app-store-static.js",
"build": "yarn copy-static && next build && yarn sentry:release",
"start": "next start",
"lint": "eslint . --ignore-path .gitignore",
"lint:fix": "eslint . --ext .ts,.js,.tsx,.jsx --fix",
@@ -69,7 +71,7 @@
"@radix-ui/react-switch": "^1.0.0",
"@radix-ui/react-toggle-group": "^1.0.0",
"@radix-ui/react-tooltip": "^1.0.0",
"@sentry/nextjs": "^9.8.0",
"@sentry/nextjs": "^9.15.0",
"@stripe/react-stripe-js": "^1.10.0",
"@stripe/stripe-js": "^1.35.0",
"@tanstack/react-query": "^5.17.15",
@@ -179,10 +181,10 @@
"@types/stripe": "^8.0.417",
"@types/uuid": "8.3.1",
"autoprefixer": "^10.4.12",
"copy-webpack-plugin": "^11.0.0",
"cron": "^3.1.7",
"detect-port": "^1.3.0",
"env-cmd": "^10.1.0",
"glob": "^10.3.10",
"google-auth-library": "^9.15.0",
"module-alias": "^2.2.2",
"msw": "^0.42.3",
@@ -0,0 +1,4 @@
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
import { creditsRouter } from "@calcom/trpc/server/routers/viewer/credits/_router";
export default createNextApiHandler(creditsRouter);
+167
View File
@@ -0,0 +1,167 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { z } from "zod";
import * as twilio from "@calcom/features/ee/workflows/lib/reminders/providers/twilioProvider";
import { IS_SMS_CREDITS_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId";
import { defaultHandler } from "@calcom/lib/server/defaultHandler";
import prisma from "@calcom/prisma";
const InputSchema = z.object({
userId: z
.string()
.optional()
.transform((val) => {
const num = Number(val);
return isNaN(num) ? undefined : num;
}),
teamId: z
.string()
.optional()
.transform((val) => {
const num = Number(val);
return isNaN(num) ? undefined : num;
}),
bookingUid: z.string().optional(),
});
/*
Twilio status callback: creates expense log when sms is delivered or undelivered
*/
async function handler(req: NextApiRequest, res: NextApiResponse) {
const signature = req.headers["x-twilio-signature"];
const baseUrl = `${WEBAPP_URL}/api/twilio/webhook`;
const queryParams = new URLSearchParams(req.query as Record<string, string>).toString();
const requestUrl = queryParams ? `${baseUrl}?${queryParams}` : baseUrl;
if (typeof signature !== "string") {
return res.status(401).send("Missing Twilio signature");
}
const isSignatureValid = await twilio.validateWebhookRequest({
requestUrl,
signature,
params: req.body,
});
if (!isSignatureValid) {
return res.status(401).send("Invalid Twilio signature");
}
const messageStatus = req.body.MessageStatus;
if (messageStatus !== "delivered" && messageStatus !== "undelivered") {
return res.status(200).send(`SMS not yet delivered/undelivered`);
}
if (!IS_SMS_CREDITS_ENABLED) {
return res.status(200).send(`SMS credits are not enabled.`);
}
const countryCode = await twilio.getCountryCodeForNumber(req.body.To);
const smsSid = req.body.SmsSid;
const {
userId: parsedUserId,
teamId: parsedTeamId,
bookingUid: parsedBookingUid,
} = InputSchema.parse(req.query);
if (!parsedUserId && !parsedTeamId) {
return res.status(401).send("Team or user id is required");
}
const { CreditService } = await import("@calcom/features/ee/billing/credit-service");
const creditService = new CreditService();
if (countryCode === "US" || countryCode === "CA") {
// SMS to US and CA are free on a team plan
let teamIdToCharge = parsedTeamId;
if (!teamIdToCharge && parsedUserId) {
const teamMembership = await prisma.membership.findFirst({
where: {
userId: parsedUserId,
accepted: true,
},
select: {
teamId: true,
},
});
teamIdToCharge = teamMembership?.teamId;
}
await creditService.chargeCredits({
teamId: teamIdToCharge,
userId: !teamIdToCharge ? parsedUserId : undefined,
bookingUid: parsedBookingUid,
smsSid,
credits: 0,
});
return res.status(200).send(`SMS to US and CA are free on a team plan. Credits set to 0`);
}
let orgId;
if (parsedTeamId) {
const team = await prisma.team.findUnique({
where: {
id: parsedTeamId,
},
select: {
isOrganization: true,
id: true,
},
});
orgId = team?.isOrganization ? team.id : undefined;
}
if (!orgId) {
orgId = await getOrgIdFromMemberOrTeamId({
memberId: parsedUserId,
teamId: parsedTeamId,
});
}
if (orgId) {
await creditService.chargeCredits({
teamId: orgId,
bookingUid: parsedBookingUid,
smsSid,
credits: 0,
});
return res.status(200).send(`SMS are free for organizations. Credits set to 0`);
}
const price = await twilio.getPriceForSMS(smsSid);
const credits = price ? creditService.calculateCreditsFromPrice(price) : null;
const chargedUserOrTeamId = await creditService.chargeCredits({
credits,
teamId: parsedTeamId,
userId: parsedUserId,
smsSid,
bookingUid: parsedBookingUid,
});
if (chargedUserOrTeamId) {
return res.status(200).send(
`Expense log with ${credits ? credits : "no"} credits created for
${
chargedUserOrTeamId.teamId
? `teamId ${chargedUserOrTeamId.teamId}`
: `userId ${chargedUserOrTeamId.userId}`
}`
);
}
// this should never happen - even when out of credits we still charge a team
return res.status(500).send("No team or users found to be charged");
}
export default defaultHandler({
POST: Promise.resolve({ default: handler }),
});
+95 -5
View File
@@ -1,4 +1,5 @@
import { expect } from "@playwright/test";
import type { Page } from "@playwright/test";
import prisma from "@calcom/prisma";
import { BookingStatus } from "@calcom/prisma/client";
@@ -72,7 +73,7 @@ test.describe("Bookings", () => {
const bookingsGetResponse = page.waitForResponse((response) =>
/\/api\/trpc\/bookings\/get.*/.test(response.url())
);
await page.goto(`/bookings/upcoming`);
await page.goto(`/bookings/upcoming`, { waitUntil: "domcontentloaded" });
await bookingsGetResponse;
await page.locator('[data-testid="add-filter-button"]').click();
@@ -350,7 +351,7 @@ test.describe("Bookings", () => {
const bookingsGetResponse = page.waitForResponse((response) =>
/\/api\/trpc\/bookings\/get.*/.test(response.url())
);
await page.goto(`/bookings/upcoming`);
await page.goto(`/bookings/upcoming`, { waitUntil: "domcontentloaded" });
await bookingsGetResponse;
await page.locator('[data-testid="add-filter-button"]').click();
@@ -361,7 +362,7 @@ test.describe("Bookings", () => {
(response) => response.url().includes("/api/trpc/bookings/get?batch=1") && response.status() === 200
);
await page
.locator(`[data-testid="multi-select-options-userId"] [role="option"]:has-text("${thirdUser.name}")`)
.locator(`[data-testid="select-filter-options-userId"] [role="option"]:has-text("${thirdUser.name}")`)
.click();
await bookingsGetResponse2;
await expect(page.locator('text="Cancel event"').nth(0)).toBeVisible();
@@ -457,19 +458,108 @@ test.describe("Bookings", () => {
const bookingsGetResponse1 = page.waitForResponse((response) =>
/\/api\/trpc\/bookings\/get.*/.test(response.url())
);
await page.goto("/bookings/upcoming");
await page.goto("/bookings/upcoming", { waitUntil: "domcontentloaded" });
await bookingsGetResponse1;
await page.locator('[data-testid="add-filter-button"]').click();
await page.locator('[data-testid="add-filter-item-userId"]').click();
await page.locator('[data-testid="filter-popover-trigger-userId"]').click();
await page
.locator(`[data-testid="multi-select-options-userId"] [role="option"]:has-text("${anotherUser}")`)
.locator(`[data-testid="select-filter-options-userId"] [role="option"]:has-text("${anotherUser}")`)
.click();
await page.waitForResponse((response) => /\/api\/trpc\/bookings\/get.*/.test(response.url()));
await expect(page.locator('[data-testid="booking-item"]')).toHaveCount(0);
});
test.describe("Filter Dropdown Item Search", () => {
const filterItemsConfig = [
{ key: "eventTypeId", name: "Event Type", testId: "add-filter-item-eventTypeId" },
{ key: "teamId", name: "Team", testId: "add-filter-item-teamId" },
{ key: "userId", name: "Member", testId: "add-filter-item-userId" },
{ key: "attendeeName", name: "Attendees Name", testId: "add-filter-item-attendeeName" },
{ key: "attendeeEmail", name: "Attendee Email", testId: "add-filter-item-attendeeEmail" },
{ key: "dateRange", name: "Date Range", testId: "add-filter-item-dateRange" },
];
const searchInputSelector = "[cmdk-input]";
const getFilterItemLocator = (page: Page, testId: string) => page.locator(`[data-testid="${testId}"]`);
test.beforeEach(async ({ page, users }) => {
const user = await users.create();
await user.apiLogin();
const bookingsGetResponse = page.waitForResponse((response) =>
/\/api\/trpc\/bookings\/get.*/.test(response.url())
);
await page.goto(`/bookings/upcoming`, { waitUntil: "domcontentloaded" });
await bookingsGetResponse;
await page.locator('[data-testid="add-filter-button"]').click();
await expect(page.locator(searchInputSelector)).toBeVisible();
});
test("should show all filter items initially and after clearing search", async ({ page }) => {
const searchInput = page.locator(searchInputSelector);
// Initial check: all defined filter items should be visible
for (const item of filterItemsConfig) {
await expect(
getFilterItemLocator(page, item.testId),
`Item ${item.name} should be visible initially`
).toBeVisible();
}
// Type something and then clear the search
await searchInput.fill("Some text");
await searchInput.clear();
// After clearing: all defined filter items should be visible again
for (const item of filterItemsConfig) {
await expect(
getFilterItemLocator(page, item.testId),
`Item ${item.name} should be visible after clearing search`
).toBeVisible();
}
});
test("search should be case-insensitive", async ({ page }) => {
const searchInput = page.locator(searchInputSelector);
// Search for "member" (lowercase)
await searchInput.fill("member");
await expect(getFilterItemLocator(page, "add-filter-item-userId")).toBeVisible();
await expect(getFilterItemLocator(page, "add-filter-item-eventTypeId")).toBeHidden();
await expect(getFilterItemLocator(page, "add-filter-item-teamId")).toBeHidden();
});
test("should individually find each filter item by its full name", async ({ page }) => {
const searchInput = page.locator(searchInputSelector);
for (const targetItem of filterItemsConfig) {
await searchInput.fill(targetItem.name);
// Check that the target item is visible
await expect(
getFilterItemLocator(page, targetItem.testId),
`Searching for "${targetItem.name}", item "${targetItem.name}" should be visible`
).toBeVisible();
await searchInput.clear();
}
});
test("should show no items for a non-matching search term", async ({ page }) => {
const searchInput = page.locator(searchInputSelector);
const nonExistentTerm = "NonExistentFilterXYZ123";
await searchInput.fill(nonExistentTerm);
for (const item of filterItemsConfig) {
await expect(
getFilterItemLocator(page, item.testId),
`Item ${item.name} should be hidden for non-matching term '${nonExistentTerm}'`
).toBeHidden();
}
});
});
});
async function createBooking({
+123
View File
@@ -0,0 +1,123 @@
import type { Page } from "@playwright/test";
import { expect } from "@playwright/test";
/**
* Select a filter from the filter dropdown
*/
export async function selectFilter(page: Page, columnId: string) {
await page.getByTestId("add-filter-button").click();
await page.getByTestId(`add-filter-item-${columnId}`).click();
}
/**
* Apply a filter with a specific value
*/
export async function applyFilter(page: Page, columnId: string, value: string) {
const existingFilter = page.getByTestId(`filter-popover-trigger-${columnId}`);
if (!(await existingFilter.isVisible())) {
await selectFilter(page, columnId);
}
await page.getByTestId(`filter-popover-trigger-${columnId}`).click();
await page.getByTestId(`select-filter-options-${columnId}`).getByRole("option", { name: value }).click();
await page.keyboard.press("Escape");
}
/**
* Clear all filters
*/
export async function clearFilters(page: Page) {
await page.getByTestId("clear-filters-button").click();
}
/**
* Create a filter segment
*/
export async function createFilterSegment(
page: Page,
name: string,
options: { teamScope?: boolean; teamName?: string } = {}
) {
await page.getByTestId("save-filter-segment-button").click();
await page.getByTestId("save-filter-segment-name").fill(name);
if (options.teamScope) {
await page.getByLabel("Save for team").click();
if (options.teamName) {
await page.getByTestId("save-filter-segment-team-select").click();
await page
.locator('[data-testid="save-filter-segment-dialog"] [id^="react-select-"]')
.getByText(options.teamName)
.click();
}
}
await page.getByTestId("save-filter-segment-dialog").getByRole("button", { name: "Save" }).click();
await expect(page.getByText("Filter segment saved")).toBeVisible();
}
/**
* Select a segment from the dropdown
*/
export async function selectSegment(page: Page, segmentName: string) {
await page.getByTestId("filter-segment-select").click();
await page
.locator('[data-testid="filter-segment-select-content"] [role="menuitem"]')
.filter({ hasText: segmentName })
.click();
}
/**
* Open submenu of a certain segment
*/
export async function openSegmentSubmenu(page: Page, segmentName: string) {
await page.getByTestId("filter-segment-select").click();
await page
.locator('[data-testid="filter-segment-select-content"] [role="menuitem"]')
.filter({ hasText: segmentName })
.locator('[data-testid="filter-segment-select-submenu-button"]')
.click();
}
/**
* Delete a segment
*/
export async function deleteSegment(page: Page, segmentName: string) {
openSegmentSubmenu(page, segmentName);
await page.getByTestId("filter-segment-select-submenu-content").getByText("Delete").click();
await page
.locator('[role="dialog"]')
.filter({ hasText: "Delete Segment" })
.getByRole("button", { name: "Delete" })
.click();
await page.keyboard.press("Escape");
await expect(page.getByText("Filter segment deleted")).toBeVisible();
}
/**
* List all available segments
*/
export async function listSegments(page: Page): Promise<string[]> {
await page.getByTestId("filter-segment-select").click();
const menuItems = page.locator('[data-testid="filter-segment-select-content"] [role="menuitem"]');
const count = await menuItems.count();
const segments: string[] = [];
for (let i = 0; i < count; i++) {
const text = await menuItems.nth(i).innerText();
segments.push(text);
}
await page.keyboard.press("Escape");
return segments;
}
+205
View File
@@ -0,0 +1,205 @@
import { expect } from "@playwright/test";
import { MembershipRole } from "@calcom/prisma/enums";
import {
applyFilter,
createFilterSegment,
selectSegment,
deleteSegment,
listSegments,
clearFilters,
openSegmentSubmenu,
} from "./filter-helpers";
import { test } from "./lib/fixtures";
test.describe.configure({ mode: "parallel" });
test.afterEach(async ({ users, orgs }) => {
await users.deleteAll();
await orgs.deleteAll();
});
test.describe("Filter Segment Functionality", () => {
test("Admin can create, use, and delete filter segments in organization members list", async ({
page,
users,
orgs,
}) => {
const orgOwner = await users.create(undefined, {
hasTeam: true,
isOrg: true,
});
const { team: org } = await orgOwner.getOrgMembership();
const memberUser = await users.create({
roleInOrganization: MembershipRole.MEMBER,
organizationId: org.id,
username: "member-user",
});
const adminUser = await users.create({
roleInOrganization: MembershipRole.ADMIN,
organizationId: org.id,
username: "admin-user",
});
await orgOwner.apiLogin();
await page.goto(`/settings/organizations/${org.slug}/members`);
const dataTable = page.getByTestId("user-list-data-table");
await expect(dataTable).toBeVisible();
const segmentName = "Admin Users";
await test.step("Can apply and save a role filter as a segment", async () => {
await applyFilter(page, "role", "admin");
await expect(page.getByText(adminUser.email)).toBeVisible();
await expect(page.getByText(memberUser.email)).toBeHidden();
await createFilterSegment(page, segmentName);
await clearFilters(page);
await expect(page.getByText(adminUser.email)).toBeVisible();
await expect(page.getByText(memberUser.email)).toBeVisible();
await selectSegment(page, segmentName);
await expect(page.getByText(adminUser.email)).toBeVisible();
await expect(page.getByText(memberUser.email)).toBeHidden();
});
await test.step("Can delete a filter segment", async () => {
await deleteSegment(page, "Admin Users");
const segments = await listSegments(page);
expect(segments.includes(segmentName)).toBe(false);
});
});
test("Filter segments persist across page reloads", async ({ page, users, orgs }) => {
const orgOwner = await users.create(undefined, {
hasTeam: true,
isOrg: true,
});
const { team: org } = await orgOwner.getOrgMembership();
const memberUser = await users.create({
roleInOrganization: MembershipRole.MEMBER,
organizationId: org.id,
username: "member-user",
});
const adminUser = await users.create({
roleInOrganization: MembershipRole.ADMIN,
organizationId: org.id,
username: "admin-user",
});
await orgOwner.apiLogin();
await page.goto(`/settings/organizations/${org.slug}/members`);
const dataTable = page.getByTestId("user-list-data-table");
await expect(dataTable).toBeVisible();
await applyFilter(page, "role", "admin");
const segmentName = "Admin Users Persistent";
await createFilterSegment(page, segmentName);
await page.reload();
await expect(dataTable).toBeVisible();
await selectSegment(page, segmentName);
await expect(page.getByText(adminUser.email)).toBeVisible();
await expect(page.getByText(memberUser.email)).toBeHidden();
await deleteSegment(page, segmentName);
});
test("Admin can create and use team scope filter segments", async ({ page, users, prisma }) => {
const orgOwner = await users.create(undefined, {
hasTeam: true,
isOrg: true,
hasSubteam: true,
});
const { team: org } = await orgOwner.getOrgMembership();
const { team: subTeam } = await orgOwner.getFirstTeamMembership();
const memberUser = await users.create({
roleInOrganization: MembershipRole.MEMBER,
organizationId: org.id,
username: "org-member",
});
const adminUser = await users.create({
roleInOrganization: MembershipRole.ADMIN,
organizationId: org.id,
username: "org-admin",
});
await orgOwner.apiLogin();
await page.goto(`/settings/organizations/${org.slug}/members`);
const dataTable = page.getByTestId("user-list-data-table");
await expect(dataTable).toBeVisible();
const segmentName = "Team Admin Filter";
await test.step("Can create a team scope filter segment", async () => {
await applyFilter(page, "role", "admin");
await createFilterSegment(page, segmentName, {
teamScope: true,
teamName: subTeam.name,
});
await clearFilters(page);
await selectSegment(page, segmentName);
await expect(page.getByText(adminUser.email)).toBeVisible();
await expect(page.getByText(memberUser.email)).toBeHidden();
});
await test.step("Regular member can see but not modify team segments", async () => {
const regularMember = await users.create({
roleInOrganization: MembershipRole.MEMBER,
organizationId: org.id,
username: "regular-member",
});
await prisma.membership.create({
data: {
createdAt: new Date(),
teamId: subTeam.id,
userId: regularMember.id,
role: MembershipRole.MEMBER,
accepted: true,
},
});
await regularMember.apiLogin();
await page.goto(`/settings/organizations/${org.slug}/members`);
await expect(dataTable).toBeVisible();
await selectSegment(page, "Team Admin Filter");
await expect(page.getByText(adminUser.email)).toBeVisible();
await expect(page.getByText(memberUser.email)).toBeHidden();
await openSegmentSubmenu(page, segmentName);
await expect(
page.getByTestId("filter-segment-select-submenu-content").getByText("Delete")
).toBeHidden();
});
});
});
+2 -2
View File
@@ -212,13 +212,13 @@ test.describe("Insights", async () => {
await page.getByTestId("filter-popover-trigger-bookingUserId").click();
await page
.locator('[data-testid="single-select-options-bookingUserId"]')
.locator('[data-testid="select-filter-options-bookingUserId"]')
.getByRole("option")
.nth(0)
.click();
await page
.locator('[data-testid="single-select-options-bookingUserId"]')
.locator('[data-testid="select-filter-options-bookingUserId"]')
.getByRole("option")
.nth(1)
.click();
+115 -8
View File
@@ -620,6 +620,7 @@
"your_full_name": "اسمك الكامل",
"no_name": "لا يوجد اسم",
"enter_number_between_range": "الرجاء إدخال رقم بين 1 و {{maxOccurences}}",
"continue_as_guest_description": "سريع وسهل - لا يتطلب حساباً. مثالي للاجتماعات لمرة واحدة.",
"email_address": "عنوان البريد الإلكتروني",
"enter_valid_email": "يرجى إدخال بريد إلكتروني صالح",
"please_schedule_future_call": " الرجاء جدولة مكالمة مستقبلية إذا لم نكن متاحين خلال {{seconds}} ثانية",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "شخصيًا (عنوان من سيحضر)",
"somewhere_else": "مكان آخر",
"custom_attendee_location": "موقع الحضور المخصص",
"continue_as_guest": "المتابعة كضيف",
"any_location": "أي موقع",
"yes": "نعم",
"no": "لا",
@@ -670,9 +672,14 @@
"team_updated_successfully": "تم تحديث الفريق بنجاح",
"your_team_updated_successfully": "تم تحديث فريقك بنجاح.",
"your_org_updated_successfully": "تم تحديث منظمتك بنجاح.",
"error_copying_to_clipboard": "خطأ في النسخ إلى الحافظة",
"about": "حول",
"team_description": "بضع جمل عن فريقك. ستظهر على صفحة رابط فريقك.",
"organization_id": "معرّف المؤسسة",
"organization_id_copied": "تم نسخ معرّف المؤسسة.",
"org_description": "بضع جمل عن منظمتك. ستظهر على صفحة رابط منظمتك.",
"team_id": "معرّف الفريق",
"team_id_copied": "تم نسخ معرّف الفريق.",
"members": "الأعضاء",
"organization_members": "أعضاء Organization",
"member": "العضو",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "هل تريد بالتأكيد إزالة هذا العضو من الفريق؟",
"confirm_disband_team": "نعم، أريد تفكيك الفريق",
"confirm_remove_member": "نعم، أريد إزالة العضو",
"confirm_subscription_cancellation": "نعم، إلغاء الاشتراك",
"cancel_subscription": "إلغاء الاشتراك",
"cancel_subscription_description": "إلغاء اشتراكك سيؤدي إلى تعطيل خطتك الحالية بشكل دائم. لا يمكن التراجع عن هذا الإجراء.",
"remove_member": "إزالة العضو",
"manage_your_team": "إدارة الفريق",
"no_teams": "ليس لديك أي فرق حتى الآن.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "رابط صفحة الحجز الخاصة بك",
"booking_cancel_redirect_uri": "رابط الصفحة التي يمكن للمستخدمين إلغاء حجزهم منها",
"booking_reschedule_redirect_uri": "رابط الصفحة التي يمكن للمستخدمين إعادة جدولة حجزهم منها",
"booking_conflict_error": "هذا الموعد لم يعد متاحاً. يرجى العودة إلى الصفحة السابقة واختيار وقت آخر.",
"open_invitations": "الدعوات المفتوحة",
"new_team": "فريق جديد",
"create_first_team_and_invite_others": "قم بإنشاء فريقك الأول ودعوة المستخدمين الآخرين للعمل معك.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "تم إنشاء حسابك باستخدام مزود هوية.",
"account_managed_by_identity_provider": "تجري إدارة حسابك بواسطة {{provider}}",
"account_managed_by_identity_provider_description": "لتغيير بريدك الإلكتروني وكلمة المرور وتمكين المصادقة من عاملين والمزيد، يُرجى زيارة إعدادات حساب {{provider}} لديك.",
"account_managed_by_identity_provider_error": "يتم إدارة حسابك بواسطة مزود هوية مختلف. حاول تسجيل الدخول باستخدام {{provider}}.",
"user_creation_error": "خطأ في إنشاء مستخدم جديد. يرجى المحاولة مرة أخرى.",
"signin_with_google": "تسجيل الدخول عبر Google",
"signin_with_saml": "تسجيل الدخول عبر SAML",
"signin_with_saml_oidc": "تسجيل الدخول عبر SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "أنت جاهز!",
"install_zapier_app": "يرجى تثبيت تطبيق Zapier من App Store أولًا.",
"install_make_app": "يرجى تثبيت تطبيق Make من متجر التطبيقات أولًا.",
"app_installation": "تثبيت التطبيق",
"app_not_installed": "التطبيق غير مثبت",
"visit_our_app_store": "عذرًا، هذا التطبيق غير مثبت على حسابك. يرجى زيارة متجر التطبيقات الخاص بنا لاستكشاف واكتشاف هذا وغيره من التطبيقات الرائعة.",
"connect_apple_server": "الاتصال بخادم Apple",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "عند إلغاء هذا الحدث",
"after_hosts_cal_video_no_show": "بعد عدم انضمام المضيفين إلى فيديو Cal",
"after_guests_cal_video_no_show": "بعد عدم انضمام الضيوف إلى فيديو Cal",
"join_video_call": "الانضمام إلى مكالمة الفيديو",
"sign_in_to_cal_com": "تسجيل الدخول إلى حساب Cal.com الخاص بك",
"log_in_to_cal_com": "تسجيل الدخول إلى Cal.com",
"track_your_meetings": "تتبع اجتماعاتك، والحصول على إشعارات، وإدارة جدولك بشكل أكثر فعالية.",
"choose_how_you_d_like_to_join_call": "اختر كيف ترغب في الانضمام إلى هذه المكالمة",
"new_event_trigger": "متى تم حجز الحدث الجديد",
"email_host_action": "إرسال رسالة إلكترونية إلى المضيف",
"email_attendee_action": "إرسال رسالة إلكترونية إلى الحضور",
@@ -1361,6 +1380,8 @@
"custom": "مخصص",
"reminder": "تذكير",
"rescheduled": "تمت إعادة الجدولة",
"rescheduled_by": "تمت إعادة الجدولة بواسطة",
"original_booking": "الحجز الأصلي",
"completed": "تمّ",
"rating": "التقييم",
"reminder_email": "تذكر {{eventType}} مع {{name}} في {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "تم تشغيل {{offOn}} سير العمل {{workflowName}} بنجاح",
"download_responses": "تنزيل الردود",
"download_responses_description": "تنزيل جميع الردود إلى النموذج بتنسيق CSV.",
"view_responses": "عرض الردود",
"download": "التنزيل",
"downloading": "جاري التنزيل",
"download_recording": "تنزيل التسجيل",
"transcription_enabled": "التفريغ النصي مفعّل الآن",
"transcription_stopped": "التفريغ النصي متوقف الآن",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "إضافة نموذج جديد إلى فريقك",
"create_your_first_route": "أنشئ مسارك الأول",
"route_to_the_right_person": "التوجيه إلى الشخص المناسب بناءً على إجابات النموذج الخاص بك",
"form": "نموذج",
"form_description": "قم بإنشاء النموذج الخاص بك لتوجيه صاحب حجز",
"copy_link_to_form": "نسخ الرابط إلى النموذج",
"theme": "سمة صفحة الحجز",
@@ -1862,6 +1886,8 @@
"wrong_code": "رمز التحقق غير صحيح",
"not_verified": "لم يتم التحقق منه بعد",
"no_availability_in_month": "غير متاح في شهر {{month}}",
"no_availability_rolling": "الجدولة متاحة فقط حتى {{days}} مقدماً. يرجى التحقق مرة أخرى قريباً.",
"no_availability_range": "انتهت إمكانية الجدولة في {{date}}. يرجى التحقق مرة أخرى قريبًا.",
"view_previous_month": "عرض الشهر السابق",
"view_next_month": "عرض الشهر التالي",
"send_code": "إرسال الرمز",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "لم يعد الدفع لهذا الحدث ممكنًا",
"booking_with_payment_cancelled_already_paid": "استرداد المبلغ المدفوع لهذا الحجز قيد التنفيذ.",
"booking_with_payment_cancelled_refunded": "تم استرداد مبلغ هذا الحجز.",
"booking_with_payment_cancelled_no_refund": "وفقًا لسياسة استرداد الأموال للفعالية، فإن دفعة الحجز غير قابلة للاسترداد.",
"booking_with_payment_cancelled_refund_window_expired": "انتهت فترة استرداد الأموال للفعالية. وبالتالي، دفعة الحجز غير قابلة للاسترداد.",
"booking_confirmation_failed": "فشل تأكيد الحجز",
"not_enough_seats": "لا توجد مقاعد كافية",
"form_builder_field_already_exists": "يوجد حقل بهذا الاسم بالفعل",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "افتح توافر المستخدمين",
"organization_no_slots_notification_switch_title": "احصل على إشعارات عندما لا يكون لدى فريقك توافر",
"organization_no_slots_notification_switch_description": "سيحصل المسؤولون على إشعارات عبر البريد الإلكتروني عندما يحاول مستخدم حجز عضو في الفريق ويواجه 'عدم التوافر'. نقوم بإرسال هذا البريد الإلكتروني بعد حدوث حالتين ونذكركم كل 7 أيام لكل مستخدم.",
"organization_disable_phone_only_sms_notifications_switch_title": "تعطيل إشعارات الرسائل القصيرة لأنواع الفعاليات التي تعتمد على الهاتف فقط",
"organization_disable_phone_only_sms_notifications_switch_description": "تعطيل إشعارات الرسائل القصيرة التلقائية لأنواع الفعاليات التي تتطلب رقم الهاتف فقط (attendeePhoneNumber) كسؤال إلزامي مع البريد الإلكتروني كخيار اختياري أو غير مطلوب",
"email_team_invite|subject|added_to_org": "{{user}} أضافك إلى المنظمة {{team}} على {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} دعاك للانضمام إلى المنظمة {{team}} على {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} أضافك إلى الفريق {{team}} من المنظمة {{parentTeamName}} على {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "تم تغيير رابطك من {{a0}} إلى {{a1}} ولكن لا تقلق، جميع الروابط السابقة لا تزال تعمل وتعيد التوجيه بشكل مناسب. <br /><br />يرجى ملاحظة: تم نقل جميع أنواع الأحداث الشخصية الخاصة بك إلى مؤسسة <strong>{{teamName}}</strong>، والتي قد تشمل أيضًا رابطًا شخصيًا محتملاً.<br /><br />يرجى تسجيل الدخول والتأكد من عدم وجود أحداث خاصة في حسابك المؤسسي الجديد.<br /><br />للأحداث الشخصية، نوصي بإنشاء حساب جديد باستخدام عنوان بريد إلكتروني شخصي.<br /><br />استمتع برابطك النظيف الجديد: {{a2}}",
"email_organization_created|subject": "تم إنشاء مؤسستك",
"your_current_plan": "خطتك الحالية",
"organization_price_per_user_month": "37 دولارًا لكل مستخدم شهريًا (بحد أدنى 30 مقعدًا)",
"organization_price_per_user_month": "37$ لكل مستخدم شهريًا",
"privacy_organization_description": "إدارة إعدادات الخصوصية لمؤسستك",
"privacy": "الخصوصية",
"team_will_be_under_org": "الفرق الجديدة ستكون تحت مؤسستك",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "بالمتابعة، فإنك توافق على",
"terms": "الشروط",
"always_show_x_days": "دائمًا {{x}} أيام متاحة",
"team_subscription_cancelled_successfully": "تم إلغاء اشتراك الفريق بنجاح",
"team_subscription_cancellation_error": "حدث خطأ أثناء إلغاء اشتراك الفريق",
"unable_to_subscribe_to_the_platform": "حدث خطأ أثناء محاولة الاشتراك في خطة المنصة، يرجى المحاولة مرة أخرى لاحقًا",
"updating_oauth_client_error": "حدث خطأ أثناء تحديث عميل OAuth، يرجى المحاولة مرة أخرى لاحقًا",
"creating_oauth_client_error": "حدث خطأ أثناء إنشاء عميل OAuth، يرجى المحاولة مرة أخرى لاحقًا",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "تخطي إنشاء سجل {{entry}} إذا لم يكن موجودًا في Salesforce",
"salesforce_if_account_does_not_exist": "إذا لم تكن جهة الاتصال موجودة تحت حساب، قم بإنشاء عميل محتمل جديد من المشارك",
"salesforce_create_new_contact_under_account": "إنشاء جهة اتصال جديدة تحت حساب بناءً على نطاق البريد الإلكتروني للمشارك وجهات الاتصال الموجودة",
"salesforce_change_record_owner_on_booking": "تغيير مالك السجل عند الحجز",
"mass_assign_attributes": "تعيين السمات بشكل جماعي",
"reroute_preview_custom_message": "ينتج عنه عرض رسالة مخصصة. حاول تغيير الاستجابة لتوجيه إلى حدث",
"reroute_preview_external_redirect": "ينتج عنه إعادة التوجيه إلى {{externalUrl}}. حاول تغيير الاستجابة لتوجيه إلى حدث",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "تم التوجيه إلى كل فترة",
"per_day": "لكل يوم",
"per_week": "لكل أسبوع",
"per_month": "لكل شهر",
"per_month": "شهريًا",
"routing_form_insights_assignment_reason": "سبب التعيين",
"access_denied": "تم رفض الوصول",
"salesforce_route_to_owner": "سيكون مالك جهة الاتصال هو مضيف Round Robin إذا كان متاحاً",
"salesforce_add_attendees_as": "إضافة الحاضرين الجدد كـ",
"salesforce_do_not_route_to_owner": "لن يتم فرض مالك جهة الاتصال (يمكن أن يظل مضيفاً إذا تطابق مع السمات ومعايير Round Robin)",
"salesforce_route_to_custom_lookup_field": "التوجيه إلى مستخدم يطابق حقل البحث في الحساب",
"salesforce_option": "خيار Salesforce",
@@ -2927,6 +2961,7 @@
"shortfall": "العجز",
"routing_form": "نموذج التوجيه",
"go_back_and_save": "العودة والحفظ",
"save_changes": "حفظ التغييرات",
"leave_without_saving": "المغادرة دون حفظ",
"leave_without_saving_description": "هل أنت متأكد من أنك تريد المغادرة دون حفظ التغييرات في نموذج التوجيه الخاص بك؟",
"something_unexpected_occurred": "حدث خطأ غير متوقع",
@@ -2961,6 +2996,9 @@
"authorize": "تفويض",
"next": "التالي",
"hide": "إخفاء",
"show": "عرض",
"utm_params": "معلمات UTM",
"no_utm_params": "لا توجد معلمات UTM متاحة.",
"asc": "تصاعدي",
"desc": "تنازلي",
"verify_email_change": "تأكيد تغيير البريد الإلكتروني",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "تحتاج إلى الحد الأدنى من الفرق المنشورة",
"you_are_part_of_this_organization_already": "أنت بالفعل جزء من هذه المؤسسة",
"you_are_part_of_another_organization_cannot_create_organization": "أنت جزء من مؤسسة أخرى، لا يمكنك إنشاء مؤسسة جديدة",
"you_are_part_of_another_platform_organization_cannot_create_organization": "أنت جزء من مؤسسة منصة أخرى، لا يمكنك إنشاء مؤسسة جديدة",
"organization_payment_success": "نجاح دفع المؤسسة",
"organization_payment_success_description": "تم إنشاء مؤسستك بنجاح",
"this_may_take_a_few_seconds": "قد يستغرق هذا بضع ثوانٍ...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "تم إكمال تأهيل المؤسسة بالفعل",
"organization_onboarding_already_exists": "تأهيل المؤسسة موجود بالفعل",
"organization_onboarding_not_found": "لم يتم العثور على تأهيل المؤسسة",
"payment_successful": "تم الدفع بنجاح",
"payment_successful": "تمت عملية الدفع بنجاح!",
"handover_onboarding_page_title": "تسليم عملية التأهيل",
"handover_onboarding_page_description": "تسليم عملية التأهيل للمستخدم",
"organization_already_exists_with_this_slug": "المؤسسة موجودة بالفعل بهذا الاسم المختصر",
@@ -3022,6 +3061,9 @@
"tip_username_plus": "نصيحة: يمكنك إضافة '+' بين أسماء المستخدمين: cal.com/anna+brian لإنشاء اجتماع جماعي ديناميكي",
"user_has_no_team_yet": "ليس لديك فريق بعد",
"no_team_members": "ليس لديك أعضاء في الفريق بعد",
"recurring_event_doesnt_support_seats": "الفعالية المتكررة لا تدعم ميزة المقاعد. اجعلها غير متكررة لتمكين المقاعد.",
"seats_doesnt_support_recurring": "ميزة المقاعد لا تدعم الفعاليات المتكررة. قم بتعطيل ميزة المقاعد لجعلها متكررة.",
"recurring_event_seats_error": "الفعالية المتكررة لا تدعم ميزة المقاعد. قم بتعطيل ميزة المقاعد أو اجعل الفعالية غير متكررة.",
"segment": "شريحة",
"rename": "إعادة تسمية",
"rename_segment": "إعادة تسمية الشريحة",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "الحجوزات الأكثر إلغاءً",
"name_or_email": "الاسم أو البريد الإلكتروني",
"salesforce_round_robin_skip_fallback_to_lead_owner": "إذا لم يتم العثور على جهة اتصال، يتم الرجوع إلى مالك العميل المحتمل إذا كان موجودًا",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ أضف السلاسل الجديدة أعلاه هنا ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "التاريخ والوقت",
"email_reminder_upcoming_event_notice" : "هذا تذكير بالحدث القادم.",
"email_reminder_triggered_by_workflow" : "تم تشغيل هذا التذكير بواسطة سير العمل في Cal.",
"enable_delegation_credential": "تمكين بيانات اعتماد التفويض",
"enable_delegation_credential_description": "امنح Cal.com وصولاً تلقائيًا إلى تقويمات جميع أعضاء المؤسسة من خلال تمكين بيانات اعتماد التفويض.",
"disable_delegation_credential": "تعطيل بيانات اعتماد التفويض",
"disable_delegation_credential_description": "بمجرد تعطيل بيانات اعتماد التفويض، سيحتاج أعضاء المؤسسة الذين لم يقوموا بربط تقويماتهم إلى القيام بذلك يدويًا.",
"last_active": "آخر نشاط",
"member_since": "عضو منذ",
"last_updated": "آخر تحديث",
"salesforce_on_cancel_write_to_event": "عند إلغاء الحجز، اكتب في سجل الحدث بدلاً من حذف الحدث",
"salesforce_on_every_cancellation": "عند كل إلغاء",
"report_issue": "الإبلاغ عن مشكلة",
"report_issue_description": "يمكنك تقديم تذكرة على GitHub أو ترقية خطتك لتلقي دعم فوري مع مؤتمرات المطورين",
"open_issue": "فتح مشكلة",
"this_is_your_current_plan": "هذه هي خطتك الحالية",
"schedule_a_time": "جدولة وقت",
"this_includes": "هذا يشمل:",
"oauth_client_updated_successfully": "تم تحديث عميل OAuth بنجاح",
"oauth_client_not_found": "لم يتم العثور على عميل OAuth",
"subscribe_to_platform": "الاشتراك في المنصة",
"error_accessing_webhooks": "حدث خطأ أثناء محاولة الوصول إلى الويب هوكس",
"webhook_update_failed": "فشل تحديث الويب هوك",
"webhook_create_failed": "فشل إنشاء الويب هوك",
"invalid_link": "رابط غير صالح",
"currently_subscribed_to_plan": "أنت مشترك حالياً في خطة {{planFirstLetter}}{{planRest}}",
"user_team": "المستخدم/الفريق",
"client_id_copied": "تم نسخ معرف العميل!",
"client_secret_copied": "تم نسخ سر العميل!",
"maintenance_message": "يقوم فريق Cal.com بإجراء صيانة مجدولة. إذا كان لديك أي أسئلة، يرجى الاتصال بالدعم.",
"your_payment_failed": "فشلت عملية الدفع الخاصة بك",
"check_your_inbox": "تحقق من صندوق الوارد الخاص بك",
"account_created_premium_not_reserved": "تم إنشاء حسابك، ولكن لم يتم حجز اسم المستخدم المميز الخاص بك.",
"email_sent_with_activation_link": "لقد أرسلنا بريدًا إلكترونيًا إلى {{email}} يحتوي على رابط لتفعيل حسابك.",
"activate_account_to_purchase_username": "بمجرد تفعيل حسابك، ستتمكن من محاولة شراء اسم المستخدم المميز الخاص بك مرة أخرى أو اختيار اسم آخر.",
"open_in_gmail": "فتح في Gmail",
"dont_see_email": "لم تستلم بريدًا إلكترونيًا؟",
"resend_in_seconds": "إعادة الإرسال خلال {{seconds}} ثانية",
"resend": "إعادة الإرسال",
"verification_email_sent": "تم إرسال بريد التحقق",
"select_all_members": "اختيار جميع الأعضاء",
"select_all_members_tooltip": "سيؤدي اختيار جميع الأعضاء إلى إضافة جميع أعضاء الفريق المستقبليين عند إضافتهم إلى الفريق.",
"form_settings": "إعدادات النموذج",
"remove_whitelist_status": "إزالة حالة القائمة البيضاء",
"whitelist_user_workflows": "إضافة سير عمل المستخدم إلى القائمة البيضاء",
"user_workflows_whitelisted": "تمت إضافة سير عمل المستخدم إلى القائمة البيضاء",
"user_workflows_unwhitelisted": "تمت إزالة سير عمل المستخدم من القائمة البيضاء",
"date_and_time": "التاريخ والوقت",
"email_reminder_upcoming_event_notice": "هذا تذكير بالحدث القادم.",
"email_reminder_triggered_by_workflow": "تم تشغيل هذا التذكير بواسطة سير العمل في Cal.",
"event_upper_case": "حدث",
"scheduling_by": "جدولة بواسطة",
"experience_review_prompt": "كيف كانت تجربتك الأخيرة؟",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "ما مدى رضاك عن اجتماعك الأخير؟",
"meeting_not_joined_question": "لم تحضر الاجتماع؟",
"reschedule_cta_short": "أعد الجدولة من هنا",
"hide_organizer_email": "إخفاء البريد الإلكتروني للمنظم",
"platform_customer_cant_create_organization": "أنت بالفعل جزء من منظمة منصة ولهذا السبب لا يمكنك إنشاء منظمة جديدة. يمكن لكل مستخدم الانتماء إلى منظمة واحدة فقط. يرجى إنشاء حساب cal.com جديد ببريد إلكتروني مختلف واستخدام هذا الحساب للاشتراك في خطة المنظمات.",
"organization_customer_cant_create_platform": "أنت بالفعل جزء من منظمة ولهذا السبب لا يمكنك إنشاء منظمة منصة. يمكن لكل مستخدم الانتماء إلى منظمة واحدة فقط. يرجى إنشاء حساب cal.com جديد ببريد إلكتروني مختلف واستخدام هذا الحساب للاشتراك في خطة المنصة.",
"hide_organizer_email_description": "إخفاء عنوان البريد الإلكتروني للمنظم من شاشة الحجز وإشعارات البريد الإلكتروني وأحداث التقويم",
"you_and_conjunction": "& أنت",
"email_survey_triggered_by_workflow": "تم تشغيل هذا الاستبيان بواسطة سير العمل في كال."
"select_verified_email": "اختر بريدًا إلكترونيًا تم التحقق منه",
"custom_reply_to_email_title": "بريد إلكتروني مخصص للرد",
"custom_reply_to_email_description": "استخدم عنوان بريد إلكتروني مختلف كعنوان للرد على رسائل التأكيد بدلاً من بريد المنظم",
"email_survey_triggered_by_workflow": "تم تشغيل هذا الاستبيان بواسطة سير العمل في كال.",
"skip_trial": "تخطي الفترة التجريبية",
"team_trials_skipped_successfully": "تم تخطي الفترات التجريبية للفريق بنجاح",
"sms_workflow_consent": "بإدخال رقم هاتفك، فإنك توافق على تلقي رسائل SMS لهذا الحدث. قد تطبق رسوم على رسائل SMS.",
"routing_preview_more_info_found_insights": "يمكن العثور على مزيد من المعلومات في <0>رؤى التوجيه</0>",
"results": "النتائج",
"view_form": "عرض النموذج",
"sms_opt_out_message": "أرسل STOP للإلغاء من رسائل SMS",
"routing_form_next_in_queue": "{{count}} التالي في قائمة الانتظار",
"routing_form_select_members_to_email": "إرسال ردود البريد الإلكتروني إلى",
"routing_incomplete_booking_tab": "الحجوزات غير المكتملة",
"include_no_show_in_rr_calculation": "تضمين الحجوزات التي لم تظهر في حسابات round robin",
"matching": "المطابقة",
"event_redirect": "إعادة توجيه الحدث",
"reset_form": "إعادة تعيين النموذج",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ أضف السلاسل الجديدة أعلاه هنا ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+117 -9
View File
@@ -620,6 +620,7 @@
"your_full_name": "Tam adınız",
"no_name": "Ad yoxdur",
"enter_number_between_range": "Zəhmət olmasa 1 ilə {{maxOccurences}} arasında bir rəqəm daxil edin",
"continue_as_guest_description": "Sürətli və asan - hesab tələb olunmur. Birdəfəlik görüşlər üçün idealdır.",
"email_address": "E-poçt ünvanı",
"enter_valid_email": "Zəhmət olmasa etibarlı bir e-poçt ünvanı daxil edin",
"please_schedule_future_call": "Zəhmət olmasa {{seconds}} saniyə ərzində mövcud deyilsə, gələcək bir zəng planlaşdırın",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Şəxsi (İştirakçının ünvanı)",
"somewhere_else": "Başqa yerdə",
"custom_attendee_location": "Xüsusi iştirakçı yeri",
"continue_as_guest": "Qonaq kimi davam et",
"any_location": "Hər hansı bir yer",
"yes": "Bəli",
"no": "Xeyr",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Komanda uğurla yeniləndi",
"your_team_updated_successfully": "Komandanız uğurla yeniləndi.",
"your_org_updated_successfully": "Təşkilatınız uğurla yeniləndi.",
"error_copying_to_clipboard": "Mübadilə buferinə kopyalamada xəta",
"about": "Haqqında",
"team_description": "Komandanız haqqında bir neçə cümlə. Bu, komandanızın URL səhifəsində görünəcək.",
"organization_id": "Təşkilat ID",
"organization_id_copied": "Təşkilat ID kopyalandı.",
"org_description": "Təşkilatınız haqqında bir neçə cümlə. Bu, təşkilatınızın URL səhifəsində görünəcək.",
"team_id": "Komanda ID",
"team_id_copied": "Komanda ID kopyalandı.",
"members": "Üzvlər",
"organization_members": "Təşkilat üzvləri",
"member": "Üzv",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Bu üzvü komandadan çıxarmaq istədiyinizə əminsinizmi?",
"confirm_disband_team": "Bəli, komandayı ləğv et",
"confirm_remove_member": "Bəli, üzvü çıxar",
"confirm_subscription_cancellation": "Bəli, abunəliyi ləğv et",
"cancel_subscription": "Abunəliyi ləğv et",
"cancel_subscription_description": "Abunəliyinizi ləğv etmək cari planınızı daimi olaraq deaktiv edəcək. Bu əməliyyat geri qaytarıla bilməz.",
"remove_member": "Üzvü çıxar",
"manage_your_team": "Komandanızı idarə edin",
"no_teams": "Hələ heç bir komandanız yoxdur.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "Rezervasiya səhifənizin URL-i",
"booking_cancel_redirect_uri": "İstifadəçilərinizin rezervasiyanı ləğv edə biləcəyi səhifənin URL-i",
"booking_reschedule_redirect_uri": "İstifadəçilərinizin rezervasiyanı yenidən planlaşdıra biləcəyi səhifənin URL-i",
"booking_conflict_error": "Bu vaxt artıq mövcud deyil. Zəhmət olmasa əvvəlki səhifəyə qayıdın və başqa vaxt seçin.",
"open_invitations": "Açıq Dəvətlər",
"new_team": "Yeni Komanda",
"create_first_team_and_invite_others": "İlk komandanızı yaradın və digər istifadəçiləri əməkdaşlığa dəvət edin.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Hesabınız bir Kimlik Sağlayıcı istifadə edilərək yaradılıb.",
"account_managed_by_identity_provider": "Hesabınız {{provider}} tərəfindən idarə olunur",
"account_managed_by_identity_provider_description": "E-poçtunuzu, şifrənizi dəyişmək, iki faktorlu autentifikasiyanı aktivləşdirmək və daha çox şey üçün, zəhmət olmasa {{provider}} hesab ayarlarınıza daxil olun.",
"account_managed_by_identity_provider_error": "Hesabınız fərqli kimlik təminatçısı tərəfindən idarə olunur. {{provider}} ilə daxil olmağı sınayın.",
"user_creation_error": "Yeni istifadəçi yaratmada xəta. Zəhmət olmasa yenidən cəhd edin.",
"signin_with_google": "Google ilə daxil olun",
"signin_with_saml": "SAML ilə daxil olun",
"signin_with_saml_oidc": "SAML/OIDC ilə daxil olun",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Hazırsınız!",
"install_zapier_app": "Zəhmət olmasa əvvəlcə Zapier Tətbiqini tətbiq mağazasında quraşdırın.",
"install_make_app": "Zəhmət olmasa əvvəlcə Make Tətbiqini tətbiq mağazasında quraşdırın.",
"app_installation": "Tətbiq Quraşdırması",
"app_not_installed": "Tətbiq quraşdırılmayıb",
"visit_our_app_store": "Bağışlayın, bu tətbiq hesabınızda quraşdırılmayıb. Zəhmət olmasa tətbiq mağazamızı ziyarət edin və bu və digər əla tətbiqləri kəşf edin.",
"connect_apple_server": "Apple Serverinə qoşulun",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "tədbir ləğv edildikdə",
"after_hosts_cal_video_no_show": "Təşkilatçılar Cal video görüşünə qoşulmadıqdan sonra",
"after_guests_cal_video_no_show": "Qonaqlar Cal video görüşünə qoşulmadıqdan sonra",
"join_video_call": "Video zəngə qoşulun",
"sign_in_to_cal_com": "Cal.com hesabınıza daxil olun",
"log_in_to_cal_com": "Cal.com-a daxil olun",
"track_your_meetings": "Görüşlərinizi izləyin, bildirişlər alın və cədvəlinizi daha effektiv idarə edin.",
"choose_how_you_d_like_to_join_call": "Bu zəngə necə qoşulmaq istədiyinizi seçin",
"new_event_trigger": "yeni tədbir sifariş edildikdə",
"email_host_action": "ev sahibinə e-poçt göndərin",
"email_attendee_action": "iştirakçılara e-poçt göndərin",
@@ -1361,6 +1380,8 @@
"custom": "Fərdi",
"reminder": "Xatırlatma",
"rescheduled": "Yenidən planlaşdırıldı",
"rescheduled_by": "Tərəfindən yenidən planlaşdırıldı",
"original_booking": "Orijinal rezervasiya",
"completed": "Tamamlandı",
"rating": "Reytinq",
"reminder_email": "Xatırlatma: {{eventType}} {{name}} ilə {{date}} tarixində",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "{{workflowName}} iş axını uğurla {{offOn}} edildi",
"download_responses": "Cavabları yüklə",
"download_responses_description": "Formunuza verilən bütün cavabları CSV formatında yükləyin.",
"view_responses": "Cavablara baxın",
"download": "Yüklə",
"downloading": "Yüklənir",
"download_recording": "Qeydi yüklə",
"transcription_enabled": "Transkripsiyalar indi aktivdir",
"transcription_stopped": "Transkripsiyalar dayandırıldı",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Komandanıza yeni forma əlavə edin",
"create_your_first_route": "İlk marşrutunuzu yaradın",
"route_to_the_right_person": "Formunuza verdiyiniz cavablara əsasən düzgün şəxsə yönləndirin",
"form": "Form",
"form_description": "Rezervasiya edən şəxsi yönləndirmək üçün formanızı yaradın",
"copy_link_to_form": "Formanın linkini kopyalayın",
"theme": "Rezervasiya səhifəsinin teması",
@@ -1862,6 +1886,8 @@
"wrong_code": "Yanlış təsdiq kodu",
"not_verified": "Hələ təsdiqlənməyib",
"no_availability_in_month": "{{month}} ayında əlçatanlıq yoxdur",
"no_availability_rolling": "Planlaşdırma yalnız {{days}} gün əvvəlcədən mümkündür. Zəhmət olmasa tezliklə yenidən yoxlayın.",
"no_availability_range": "Planlaşdırma {{date}} tarixində başa çatdı. Zəhmət olmasa, tezliklə yenidən yoxlayın.",
"view_previous_month": "Əvvəlki aya baxın",
"view_next_month": "Növbəti aya bax",
"send_code": "Kodu göndər",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Bu tədbir üçün ödəniş artıq mümkün deyil",
"booking_with_payment_cancelled_already_paid": "Bu rezervasiya ödənişi üçün geri ödəmə yoldadır.",
"booking_with_payment_cancelled_refunded": "Bu rezervasiya ödənişi geri ödənilib.",
"booking_with_payment_cancelled_no_refund": "Tədbirin geri ödəmə siyasətinə əsasən, rezervasiya ödənişi geri qaytarılmır.",
"booking_with_payment_cancelled_refund_window_expired": "Tədbirin geri ödəmə müddəti başa çatıb. Buna görə də, rezervasiya ödənişi geri qaytarılmır.",
"booking_confirmation_failed": "Rezervasiya təsdiqi uğursuz oldu",
"not_enough_seats": "Kifayət qədər oturacaq yoxdur",
"form_builder_field_already_exists": "Bu adla bir sahə artıq mövcuddur",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "İstifadəçilərin mövcudluğunu açın",
"organization_no_slots_notification_switch_title": "Komandanızın mövcudluğu olmadıqda bildirişlər alın",
"organization_no_slots_notification_switch_description": "İstifadəçi komanda üzvünü rezervasiya etməyə çalışdıqda və 'Mövcudluq yoxdur' ilə qarşılaşdıqda administratorlar e-poçt bildirişləri alacaqlar. Bu e-poçtu iki hadisədən sonra tetikleyirik və hər istifadəçi üçün hər 7 gündə bir xatırladırıq.",
"organization_disable_phone_only_sms_notifications_switch_title": "Yalnız telefon tədbirləri üçün SMS bildirişlərini deaktiv edin",
"organization_disable_phone_only_sms_notifications_switch_description": "Yalnız telefon nömrəsi (attendeePhoneNumber) tələb olunan sual kimi, e-poçt isə istəyə bağlı və ya tələb olunmayan tədbir növləri üçün avtomatik SMS bildirişlərini deaktiv edin",
"email_team_invite|subject|added_to_org": "{{user}} sizi {{appName}} üzərində {{team}} təşkilatına əlavə etdi",
"email_team_invite|subject|invited_to_org": "{{user}} sizi {{appName}} üzərində {{team}} təşkilatına qoşulmağa dəvət etdi",
"email_team_invite|subject|added_to_subteam": "{{user}} sizi {{appName}} üzərində {{parentTeamName}} təşkilatının {{team}} komandasına əlavə etdi",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Linkiniz {{a0}}-dan {{a1}}-a dəyişdirilib, lakin narahat olmayın, bütün əvvəlki linklər hələ də işləyir və müvafiq şəkildə yönləndirilir. <br /><br />Qeyd edək ki: Bütün şəxsi tədbir növləriniz <strong>{{teamName}}</strong> təşkilatına köçürülüb, bura potensial şəxsi link də daxil ola bilər.<br /><br />Zəhmət olmasa daxil olun və yeni təşkilat hesabınızda şəxsi tədbirlərinizin olmadığından əmin olun.<br /><br />Şəxsi tədbirlər üçün şəxsi e-poçt ünvanı ilə yeni hesab yaratmağı tövsiyə edirik.<br /><br />Yeni təmiz linkinizin keyfini çıxarın: {{a2}}",
"email_organization_created|subject": "Təşkilatınız yaradıldı",
"your_current_plan": "Cari planınız",
"organization_price_per_user_month": "Hər istifadəçi üçün ayda 37 dollar (minimum 30 yer)",
"organization_price_per_user_month": "Ayda istifadəçi başına $37",
"privacy_organization_description": "Təşkilatınız üçün məxfilik parametrlərini idarə edin",
"privacy": "Məxfilik",
"team_will_be_under_org": "Yeni komandalar təşkilatınızın tərkibində olacaq",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Davam etməklə, bizim",
"terms": "Şərtlər",
"always_show_x_days": "Həmişə {{x}} gün mövcuddur",
"team_subscription_cancelled_successfully": "Komanda abunəliyi uğurla ləğv edildi",
"team_subscription_cancellation_error": "Komanda abunəliyini ləğv edərkən xəta baş verdi",
"unable_to_subscribe_to_the_platform": "Platforma planına abunə olmağa çalışarkən bir səhv baş verdi, zəhmət olmasa bir az sonra yenidən cəhd edin",
"updating_oauth_client_error": "OAuth müştərisini yeniləyərkən bir səhv baş verdi, zəhmət olmasa bir az sonra yenidən cəhd edin",
"creating_oauth_client_error": "OAuth müştərisi yaradılarkən bir səhv baş verdi, zəhmət olmasa bir az sonra yenidən cəhd edin",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Əgər {{entry}} Salesforce-da mövcud deyilsə, qeyd yaratmağı keçin",
"salesforce_if_account_does_not_exist": "Əgər əlaqə hesab altında mövcud deyilsə, iştirakçıdan yeni potensial müştəri yaradın",
"salesforce_create_new_contact_under_account": "İştirakçının email domeni və mövcud əlaqələr əsasında hesab altında yeni əlaqə yaradın",
"salesforce_change_record_owner_on_booking": "Rezervasiya zamanı qeyd sahibini dəyişdirin",
"mass_assign_attributes": "Atributları kütləvi təyin et",
"reroute_preview_custom_message": "Bu, xüsusi mesajın göstərilməsi ilə nəticələnir. Cavabı bir tədbir üçün marşruta dəyişdirməyə çalışın",
"reroute_preview_external_redirect": "Bu, {{externalUrl}} ünvanına yönləndirmə ilə nəticələnir. Cavabı bir tədbir üçün marşruta dəyişdirməyə çalışın",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Dövr üzrə yönləndirilmə",
"per_day": "Gün üzrə",
"per_week": "Həftə üzrə",
"per_month": "Ay üzrə",
"per_month": "aylıq",
"routing_form_insights_assignment_reason": "Təyin edilmə səbəbi",
"access_denied": "Giriş qadağandır",
"salesforce_route_to_owner": "Əlaqə sahibi mövcud olduqda Round Robin ev sahibi olacaq",
"salesforce_add_attendees_as": "Yeni iştirakçıları belə əlavə edin",
"salesforce_do_not_route_to_owner": "Əlaqə sahibi məcbur edilməyəcək (əgər atributlara və Round Robin meyarlarına uyğun gəlirsə, yenə də ev sahibi ola bilər)",
"salesforce_route_to_custom_lookup_field": "Hesabda axtarış sahəsinə uyğun gələn istifadəçiyə yönləndir",
"salesforce_option": "Salesforce Seçimi",
@@ -2927,6 +2961,7 @@
"shortfall": "Çatışmazlıq",
"routing_form": "Marşrutlama forması",
"go_back_and_save": "Geri qayıt və yadda saxla",
"save_changes": "Dəyişiklikləri saxla",
"leave_without_saving": "Yadda saxlamadan çıx",
"leave_without_saving_description": "Marşrutlaşdırma formanızdakı dəyişiklikləri yadda saxlamadan çıxmaq istədiyinizə əminsiniz?",
"something_unexpected_occurred": "Gözlənilməz bir xəta baş verdi",
@@ -2961,6 +2996,9 @@
"authorize": "İcazə ver",
"next": "Növbəti",
"hide": "Gizlət",
"show": "Göstər",
"utm_params": "UTM parametrləri",
"no_utm_params": "UTM parametrləri mövcud deyil.",
"asc": "Artan",
"desc": "Azalan",
"verify_email_change": "E-poçt dəyişikliyini təsdiqlə",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Minimum sayda dərc edilmiş komandalarınız olmalıdır",
"you_are_part_of_this_organization_already": "Siz artıq bu təşkilatın üzvüsünüz",
"you_are_part_of_another_organization_cannot_create_organization": "Siz başqa bir təşkilatın üzvüsünüz, yeni təşkilat yarada bilməzsiniz",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Siz başqa bir platforma təşkilatının üzvüsünüz, yeni təşkilat yarada bilməzsiniz",
"organization_payment_success": "Təşkilat ödənişi uğurludur",
"organization_payment_success_description": "Təşkilatınız uğurla yaradılıb",
"this_may_take_a_few_seconds": "Bu bir neçə saniyə çəkə bilər...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Təşkilat qeydiyyatı artıq tamamlanıb",
"organization_onboarding_already_exists": "Təşkilat qeydiyyatı artıq mövcuddur",
"organization_onboarding_not_found": "Təşkilat qeydiyyatı tapılmadı",
"payment_successful": "Ödəniş uğurlu oldu",
"payment_successful": "Ödəniş uğurlu oldu!",
"handover_onboarding_page_title": "Qeydiyyatın təhvil verilməsi",
"handover_onboarding_page_description": "İstifadəçiyə qeydiyyatın təhvil verilməsi",
"organization_already_exists_with_this_slug": "Bu slug ilə təşkilat artıq mövcuddur",
@@ -3019,9 +3058,12 @@
"link": "Link",
"rows_per_page": "səhifə başına sətir",
"pagination_status": "{{totalItems}} içərisindən {{currentRange}}",
"tip_username_plus": "Məsləhət: Dinamik qrup görüşü yaratmaq üçün istifadəçi adları arasında '+' işarəsi istifadə edə bilərsiniz: cal.com/anna+brian",
"tip_username_plus": "Məsləhət: İstifadəçi adları arasında '+' əlavə edə bilərsiniz: cal.com/anna+brian dinamik qrup görüşü yaratmaq üçün",
"user_has_no_team_yet": "Hələ komandanız yoxdur",
"no_team_members": "Hələ komanda üzvləriniz yoxdur",
"recurring_event_doesnt_support_seats": "Təkrarlanan tədbir yerlər funksiyasını dəstəkləmir. Yerləri aktivləşdirmək üçün onu təkrarlanmayan edin.",
"seats_doesnt_support_recurring": "Yerlər funksiyası təkrarlanan tədbiri dəstəkləmir. Təkrarlanma funksiyasını aktivləşdirmək üçün yerlər funksiyasını deaktiv edin.",
"recurring_event_seats_error": "Təkrarlanan tədbir yerlər funksiyasını dəstəkləmir. Yerlər funksiyasını deaktiv edin və ya tədbiri təkrarlanmayan edin.",
"segment": "Seqment",
"rename": "Adını dəyişdir",
"rename_segment": "Seqmentin adını dəyişdir",
@@ -3053,16 +3095,82 @@
"most_cancelled_bookings": "Ən çox ləğv edilmiş rezervasiyalar",
"name_or_email": "Ad və ya E-poçt",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Əgər əlaqə tapılmazsa, mövcud olduğu təqdirdə potensial müştəri sahibinə qayıt",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni sətirləri bura əlavə edin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Tarix & Saat",
"email_reminder_upcoming_event_notice" : "Bu, qarşıdan gələn tədbiriniz haqqında xatırlatmadır.",
"email_reminder_triggered_by_workflow" : "Bu xatırladıcı Calda iş axını ilə işə salınıb.",
"enable_delegation_credential": "Nümayəndəlik etimadnaməsini aktivləşdirin",
"enable_delegation_credential_description": "Nümayəndəlik etimadnaməsini aktivləşdirməklə Cal.com-a bütün təşkilat üzvlərinin təqvimlərinə avtomatik giriş imkanı verin.",
"disable_delegation_credential": "Nümayəndəlik etimadnaməsini deaktiv edin",
"disable_delegation_credential_description": "Nümayəndəlik etimadnaməsi deaktiv edildikdən sonra, təqvimlərini qoşmamış təşkilat üzvləri bunu əl ilə etməli olacaqlar.",
"last_active": "Son aktivlik",
"member_since": "Üzvlük tarixi",
"last_updated": "Son yenilənmə",
"salesforce_on_cancel_write_to_event": "Rezervasiya ləğv edildikdə, tədbiri silmək əvəzinə tədbir qeydinə yazın",
"salesforce_on_every_cancellation": "Hər ləğv zamanı",
"report_issue": "Problemi bildirin",
"report_issue_description": "GitHub-da bilet təqdim edə və ya tərtibatçı konfransları ilə real vaxt dəstəyi almaq üçün planınızı yüksəldə bilərsiniz",
"open_issue": "Problemi açın",
"this_is_your_current_plan": "Bu sizin cari planınızdır",
"schedule_a_time": "Vaxt təyin edin",
"this_includes": "Buna daxildir:",
"oauth_client_updated_successfully": "OAuth müştərisi uğurla yeniləndi",
"oauth_client_not_found": "OAuth müştərisi tapılmadı.",
"subscribe_to_platform": "Platformaya abunə olun",
"error_accessing_webhooks": "Vebhuklara giriş zamanı xəta baş verdi.",
"webhook_update_failed": "Vebhuku yeniləmək mümkün olmadı.",
"webhook_create_failed": "Vebhuk yaratmaq mümkün olmadı.",
"invalid_link": "Yanlış link",
"currently_subscribed_to_plan": "Hal-hazırda {{planFirstLetter}}{{planRest}} planına abunəsiniz",
"user_team": "İstifadəçi/Komanda",
"client_id_copied": "Müştəri ID-si kopyalandı!",
"client_secret_copied": "Müştəri sirri kopyalandı!",
"maintenance_message": "Cal.com komandası planlaşdırılmış texniki xidmət işləri aparır. Hər hansı sualınız varsa, dəstəklə əlaqə saxlayın.",
"your_payment_failed": "Ödənişiniz uğursuz oldu",
"check_your_inbox": "Gələnlər qutunuzu yoxlayın",
"account_created_premium_not_reserved": "Hesabınız yaradıldı, lakin premium adınız rezerv edilmədi.",
"email_sent_with_activation_link": "{{email}} ünvanına hesabınızı aktivləşdirmək üçün link göndərdik.",
"activate_account_to_purchase_username": "Hesabınızı aktivləşdirdikdən sonra premium istifadəçi adınızı yenidən almağa cəhd edə və ya fərqli bir ad seçə bilərsiniz.",
"open_in_gmail": "Gmail-də açın",
"dont_see_email": "E-poçt görmürsünüz?",
"resend_in_seconds": "{{seconds}} saniyə sonra yenidən göndər",
"resend": "Yenidən göndər",
"verification_email_sent": "Doğrulama e-poçtu göndərildi",
"select_all_members": "Bütün üzvləri seçin",
"select_all_members_tooltip": "Bütün üzvləri seçmək, gələcəkdə komandaya əlavə edilən bütün üzvləri də əlavə edəcək.",
"form_settings": "Form Parametrləri",
"remove_whitelist_status": "Ağ siyahı statusunu silin",
"whitelist_user_workflows": "İstifadəçi iş axınlarını ağ siyahıya əlavə edin",
"user_workflows_whitelisted": "İstifadəçi iş axınları ağ siyahıya əlavə edildi",
"user_workflows_unwhitelisted": "İstifadəçi iş axınları ağ siyahıdan çıxarıldı",
"date_and_time": "Tarix & Saat",
"email_reminder_upcoming_event_notice": "Bu, qarşıdan gələn tədbiriniz haqqında xatırlatmadır.",
"email_reminder_triggered_by_workflow": "Bu xatırladıcı Calda iş axını ilə işə salınıb.",
"event_upper_case": "Hadisə",
"scheduling_by": "Təqvimləşdirmə edən",
"experience_review_prompt": "Son təcrübəniz necə oldu?",
"improve_customer_experience_message": "Həmişə müştəri təcrübəsini yaxşılaşdırmağa çalışırıq.",
"meeting_satisfaction_question": "Son görüşünüzdən nə qədər məmnun qaldınız?",
"meeting_not_joined_question": "görüşə qoşulmadınız?",
"reschedule_cta_short": "Buradan yenidən təyin edin.",
"hide_organizer_email": "Təşkilatçının e-poçtunu gizlədin",
"platform_customer_cant_create_organization": "Siz artıq bir platforma təşkilatının üzvü olduğunuz üçün yeni təşkilat yarada bilməzsiniz. Hər istifadəçi yalnız bir təşkilata aid ola bilər. Zəhmət olmasa, fərqli bir e-poçt ilə yeni bir cal.com hesabı yaradın və həmin hesabdan təşkilat planına abunə olun.",
"organization_customer_cant_create_platform": "Siz artıq bir təşkilatın üzvü olduğunuz üçün platforma təşkilatı yarada bilməzsiniz. Hər istifadəçi yalnız bir təşkilata aid ola bilər. Zəhmət olmasa, fərqli bir e-poçt ilə yeni bir cal.com hesabı yaradın və həmin hesabdan platforma planına abunə olun.",
"hide_organizer_email_description": "Təşkilatçının e-poçt ünvanını rezervasiya ekranından, e-poçt bildirişlərindən və təqvim tədbirlərindən gizlədin",
"you_and_conjunction": "Siz &",
"email_survey_triggered_by_workflow": "Bu sorğu Cal-da Workflow tərəfindən başladıldı."
"select_verified_email": "Təsdiqlənmiş e-poçt seçin",
"custom_reply_to_email_title": "Xüsusi 'Cavab-Ünvanı' e-poçtu",
"custom_reply_to_email_description": "Təsdiq e-poçtları üçün təşkilatçının e-poçtu əvəzinə fərqli bir e-poçt ünvanını cavab ünvanı kimi istifadə edin",
"email_survey_triggered_by_workflow": "Bu sorğu Cal-da Workflow tərəfindən başladıldı.",
"skip_trial": "Sınaq müddətini keçin",
"team_trials_skipped_successfully": "Komanda sınaqları uğurla keçildi",
"sms_workflow_consent": "Telefon nömrənizi daxil etməklə bu tədbir üçün SMS mesajları almağa razılıq verirsiniz. SMS tarifləri tətbiq oluna bilər.",
"routing_preview_more_info_found_insights": "Daha çox məlumatı <0>Marşrutlama Təhlilləri</0> bölməsində tapa bilərsiniz",
"results": "Nəticələr",
"view_form": "Formaya baxın",
"sms_opt_out_message": "SMS mesajlarından imtina etmək üçün STOP yazın",
"routing_form_next_in_queue": "Növbədə {{count}} növbəti",
"routing_form_select_members_to_email": "E-poçt cavablarını göndərmək üçün üzvləri seçin",
"routing_incomplete_booking_tab": "Tamamlanmamış rezervasiyalar",
"include_no_show_in_rr_calculation": "Round robin hesablamalarında gəlməyən rezervasiyaları daxil edin",
"matching": "Uyğunlaşdırma",
"event_redirect": "Tədbir yönləndirməsi",
"reset_form": "Formanı sıfırlayın",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Yeni sətirləri bura əlavə edin ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+115 -8
View File
@@ -620,6 +620,7 @@
"your_full_name": "Вашето пълно име",
"no_name": "Без име",
"enter_number_between_range": "Моля, въведете число между 1 и {{maxOccurences}}",
"continue_as_guest_description": "Бързо и лесно - не се изисква акаунт. Идеално за еднократни срещи.",
"email_address": "Имейл адрес",
"enter_valid_email": "Моля, въведете валиден имейл",
"please_schedule_future_call": "Моля, планирайте бъдеща среща, ако не сме свободни в следващите {{seconds}} секунди",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "На място (адрес на участника)",
"somewhere_else": "Друго място",
"custom_attendee_location": "Персонализирана локация на участника",
"continue_as_guest": "Продължи като гост",
"any_location": "Всяка локация",
"yes": "Да",
"no": "Не",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Екипът е обновен успешно",
"your_team_updated_successfully": "Вашият екип беше обновен успешно.",
"your_org_updated_successfully": "Вашата организация беше обновена успешно.",
"error_copying_to_clipboard": "Грешка при копиране в клипборда",
"about": "За нас",
"team_description": "Няколко изречения за вашия екип. Това ще се показва на URL страницата на екипа ви.",
"organization_id": "Идентификатор на организацията",
"organization_id_copied": "Идентификаторът на организацията е копиран.",
"org_description": "Няколко изречения за вашата организация. Това ще се показва на URL страницата на организацията ви.",
"team_id": "Идентификатор на екипа",
"team_id_copied": "Идентификаторът на екипа е копиран.",
"members": "Членове",
"organization_members": "Членове на организацията",
"member": "Член",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Сигурни ли сте, че искате да премахнете този член от екипа?",
"confirm_disband_team": "Да, разформировай екипа",
"confirm_remove_member": "Да, премахни члена",
"confirm_subscription_cancellation": "Да, отказвам абонамента",
"cancel_subscription": "Отказване на абонамент",
"cancel_subscription_description": "Отказването на абонамента ви ще деактивира окончателно текущия ви план. Това действие не може да бъде отменено.",
"remove_member": "Премахни член",
"manage_your_team": "Управление на вашия екип",
"no_teams": "Все още нямате екипи.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "URL адрес на вашата страница за резервации",
"booking_cancel_redirect_uri": "URL адрес на страницата, където потребителите могат да отменят резервацията си",
"booking_reschedule_redirect_uri": "URL адрес на страницата, където потребителите могат да пренасрочат резервацията си",
"booking_conflict_error": "Този слот вече не е наличен. Моля, върнете се на предишната страница и изберете друго време.",
"open_invitations": "Отворени покани",
"new_team": "Нов екип",
"create_first_team_and_invite_others": "Създайте първия си екип и поканете други потребители за съвместна работа.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Акаунтът ви е създаден с помощта на доставчик на идентичност.",
"account_managed_by_identity_provider": "Акаунтът ви се управлява от {{provider}}",
"account_managed_by_identity_provider_description": "За да промените имейла си, паролата, да активирате двуфакторна автентикация и други, моля, посетете настройките на вашия {{provider}} акаунт.",
"account_managed_by_identity_provider_error": "Вашият акаунт се управлява от друг доставчик на идентичност. Опитайте да влезете с {{provider}}.",
"user_creation_error": "Грешка при създаване на нов потребител. Моля, опитайте отново.",
"signin_with_google": "Вход с Google",
"signin_with_saml": "Вход със SAML",
"signin_with_saml_oidc": "Вход със SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Готово сте!",
"install_zapier_app": "Моля, първо инсталирайте Zapier приложението от магазина за приложения.",
"install_make_app": "Моля, първо инсталирайте Make приложението от магазина за приложения.",
"app_installation": "Инсталиране на приложение",
"app_not_installed": "Приложението не е инсталирано",
"visit_our_app_store": "Съжаляваме, това приложение не е инсталирано на вашия акаунт. Моля, посетете нашия магазин за приложения, за да разгледате това и други страхотни приложения.",
"connect_apple_server": "Свързване с Apple сървър",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "когато събитието е отменено",
"after_hosts_cal_video_no_show": "След като домакините не се присъединиха към Cal видеото",
"after_guests_cal_video_no_show": "След като гостите не се присъединиха към Cal видеото",
"join_video_call": "Присъединете се към видео разговора",
"sign_in_to_cal_com": "Влезте във вашия Cal.com акаунт",
"log_in_to_cal_com": "Влезте в Cal.com",
"track_your_meetings": "Проследявайте срещите си, получавайте известия и управлявайте графика си по-ефективно.",
"choose_how_you_d_like_to_join_call": "Изберете как искате да се присъедините към този разговор",
"new_event_trigger": "когато е резервирано ново събитие",
"email_host_action": "изпращане на имейл до домакина",
"email_attendee_action": "изпращане на имейл до участниците",
@@ -1361,6 +1380,8 @@
"custom": "По избор",
"reminder": "Напомняне",
"rescheduled": "Пренасрочено",
"rescheduled_by": "Пренасрочено от",
"original_booking": "Първоначална резервация",
"completed": "Завършено",
"rating": "Оценка",
"reminder_email": "Напомняне: {{eventType}} с {{name}} на {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "Работният процес {{workflowName}} е {{offOn}} успешно",
"download_responses": "Изтегли отговорите",
"download_responses_description": "Изтегли всички отговори от формуляра в CSV формат.",
"view_responses": "Преглед на отговорите",
"download": "Изтегли",
"downloading": "Изтегляне",
"download_recording": "Изтегли записа",
"transcription_enabled": "Транскрипциите са активирани",
"transcription_stopped": "Транскрипциите са спрени",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Добавяне на нов формуляр към вашия екип",
"create_your_first_route": "Създайте първия си маршрут",
"route_to_the_right_person": "Насочване към правилния човек според отговорите във формуляра",
"form": "Формуляр",
"form_description": "Създайте формуляр за маршрутизиране на резервации",
"copy_link_to_form": "Копиране на линк към формуляра",
"theme": "Тема на страницата за резервации",
@@ -1862,6 +1886,8 @@
"wrong_code": "Грешен код за потвърждение",
"not_verified": "Все още не е потвърдено",
"no_availability_in_month": "Няма свободно време през {{month}}",
"no_availability_rolling": "Планирането е възможно само до {{days}} дни напред. Моля, проверете отново скоро.",
"no_availability_range": "Планирането приключи на {{date}}. Моля, проверете отново скоро.",
"view_previous_month": "Преглед на предишния месец",
"view_next_month": "Преглед на следващия месец",
"send_code": "Изпращане на код",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Плащането за това събитие вече не е възможно",
"booking_with_payment_cancelled_already_paid": "Възстановяването на сумата за тази резервация е в процес на обработка.",
"booking_with_payment_cancelled_refunded": "Плащането за тази резервация е възстановено.",
"booking_with_payment_cancelled_no_refund": "Съгласно политиката за възстановяване на средства за събитието, плащането за резервацията не подлежи на възстановяване.",
"booking_with_payment_cancelled_refund_window_expired": "Периодът за възстановяване на средства за събитието е изтекъл. Следователно плащането за резервацията не подлежи на възстановяване.",
"booking_confirmation_failed": "Потвърждението на резервацията е неуспешно",
"not_enough_seats": "Няма достатъчно места",
"form_builder_field_already_exists": "Поле с това име вече съществува",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Open users availability",
"organization_no_slots_notification_switch_title": "Получавайте известия, когато вашият екип няма свободна заетост",
"organization_no_slots_notification_switch_description": "Администраторите ще получават имейл известия, когато потребител се опита да резервира член на екипа и се сблъска с 'Няма свободна заетост'. Изпращаме този имейл след две появявания и ви напомняме на всеки 7 дни за потребител.",
"organization_disable_phone_only_sms_notifications_switch_title": "Деактивиране на SMS известия за типове събития само с телефон",
"organization_disable_phone_only_sms_notifications_switch_description": "Деактивиране на автоматичните SMS известия за типове събития, които изискват само телефонен номер (attendeePhoneNumber) като задължителен въпрос, с имейл като незадължителен или не изискван",
"email_team_invite|subject|added_to_org": "{{user}} ви добави към организацията {{team}} в {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} ви покани да се присъедините към организацията {{team}} в {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} ви добави към екипа {{team}} от организацията {{parentTeamName}} в {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Вашата връзка беше променена от {{a0}} на {{a1}}, но не се притеснявайте, всички предишни връзки все още работят и пренасочват правилно. <br /><br />Моля, имайте предвид: Всички ваши лични типове събития са преместени в организацията <strong>{{teamName}}</strong>, което може да включва и потенциална лична връзка.<br /><br />Моля, влезте и се уверете, че нямате лични събития в новия си организационен акаунт.<br /><br />За лични събития препоръчваме да създадете нов акаунт с личен имейл адрес.<br /><br />Насладете се на новата си чиста връзка: {{a2}}",
"email_organization_created|subject": "Вашата организация е създадена",
"your_current_plan": "Вашият текущ план",
"organization_price_per_user_month": "$37 на потребител на месец (минимум 30 места)",
"organization_price_per_user_month": "$37 на потребител на месец",
"privacy_organization_description": "Управлявайте настройките за поверителност на вашата организация",
"privacy": "Поверителност",
"team_will_be_under_org": "Новите екипи ще бъдат под вашата организация",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "С продължаването си, вие се съгласявате с нашите",
"terms": "Условия",
"always_show_x_days": "Винаги показвай {{x}} свободни дни",
"team_subscription_cancelled_successfully": "Абонаментът на екипа е отменен успешно",
"team_subscription_cancellation_error": "Грешка при отмяна на абонамента на екипа",
"unable_to_subscribe_to_the_platform": "Възникна грешка при опит за абониране за плана на платформата, моля опитайте отново по-късно",
"updating_oauth_client_error": "Възникна грешка при актуализиране на OAuth клиента, моля опитайте отново по-късно",
"creating_oauth_client_error": "Възникна грешка при създаване на OAuth клиента, моля опитайте отново по-късно",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Пропусни създаването на запис {{entry}}, ако не съществува в Salesforce",
"salesforce_if_account_does_not_exist": "Ако контактът не съществува под акаунт, създай нов лийд от участника",
"salesforce_create_new_contact_under_account": "Създай нов контакт под акаунт базиран на имейл домейна на участника и съществуващите контакти",
"salesforce_change_record_owner_on_booking": "Промяна на собственика на записа при резервация",
"mass_assign_attributes": "Масово задаване на атрибути",
"reroute_preview_custom_message": "Това води до показване на персонализирано съобщение. Опитайте да промените отговора, за да пренасочите към събитие",
"reroute_preview_external_redirect": "Това води до пренасочване към {{externalUrl}}. Опитайте да промените отговора, за да пренасочите към събитие",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Пренасочени към за период",
"per_day": "За ден",
"per_week": "За седмица",
"per_month": "За месец",
"per_month": "на месец",
"routing_form_insights_assignment_reason": "Причина за назначаване",
"access_denied": "Достъпът е отказан",
"salesforce_route_to_owner": "Собственикът на контакта ще бъде Round Robin домакин, ако е наличен",
"salesforce_add_attendees_as": "Добавяне на нови участници като",
"salesforce_do_not_route_to_owner": "Собственикът на контакта няма да бъде принудително избран (все пак може да бъде домакин, ако отговаря на атрибутите и критериите за Round Robin)",
"salesforce_route_to_custom_lookup_field": "Пренасочване към потребител, който съответства на поле за търсене в акаунта",
"salesforce_option": "Salesforce опция",
@@ -2927,6 +2961,7 @@
"shortfall": "Недостиг",
"routing_form": "Форма за маршрутизиране",
"go_back_and_save": "Върни се и запази",
"save_changes": "Запази промените",
"leave_without_saving": "Излез без да запазиш",
"leave_without_saving_description": "Сигурни ли сте, че искате да излезете без да запазите промените във вашата форма за маршрутизиране?",
"something_unexpected_occurred": "Възникна неочаквана грешка",
@@ -2961,6 +2996,9 @@
"authorize": "Упълномощаване",
"next": "Напред",
"hide": "Скрий",
"show": "Покажи",
"utm_params": "UTM параметри",
"no_utm_params": "Няма налични UTM параметри.",
"asc": "Възх",
"desc": "Низх",
"verify_email_change": "Потвърди промяната на имейл",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Трябва да имате минимален брой публикувани екипи",
"you_are_part_of_this_organization_already": "Вече сте част от тази организация",
"you_are_part_of_another_organization_cannot_create_organization": "Вие сте част от друга организация, не можете да създадете нова организация",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Вие сте част от друга платформена организация, не можете да създадете нова организация",
"organization_payment_success": "Успешно плащане за организацията",
"organization_payment_success_description": "Вашата организация е създадена успешно",
"this_may_take_a_few_seconds": "Това може да отнеме няколко секунди...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Въвеждането в организацията вече е завършено",
"organization_onboarding_already_exists": "Въвеждането в организацията вече съществува",
"organization_onboarding_not_found": "Въвеждането в организацията не е намерено",
"payment_successful": "Успешно плащане",
"payment_successful": "Плащането е успешно!",
"handover_onboarding_page_title": "Предаване на въвеждането",
"handover_onboarding_page_description": "Предаване на въвеждането на потребителя",
"organization_already_exists_with_this_slug": "Вече съществува организация с този слъг",
@@ -3022,6 +3061,9 @@
"tip_username_plus": "Съвет: Можете да добавите '+' между потребителските имена: cal.com/anna+brian, за да създадете динамична групова среща",
"user_has_no_team_yet": "Все още нямате екип",
"no_team_members": "Все още нямате членове на екипа",
"recurring_event_doesnt_support_seats": "Повтарящото се събитие не поддържа функцията за места. Направете го неповтарящо се, за да активирате места.",
"seats_doesnt_support_recurring": "Функцията за места не поддържа повтарящи се събития. Деактивирайте функцията за места, за да го направите повтарящо се.",
"recurring_event_seats_error": "Повтарящото се събитие не поддържа функцията за места. Деактивирайте функцията за места или направете събитието неповтарящо се.",
"segment": "Сегмент",
"rename": "Преименуване",
"rename_segment": "Преименуване на сегмент",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Най-много отменени резервации",
"name_or_email": "Име или имейл",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Ако не е намерен контакт, връщане към собственика на лийда, ако съществува",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Добавете новите си низове над този ред ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Дата и час",
"email_reminder_upcoming_event_notice" : "Това е напомняне за предстоящото ви събитие.",
"email_reminder_triggered_by_workflow" : "Това напомняне е задействано от работен процес в Cal.",
"enable_delegation_credential": "Активиране на делегирани идентификационни данни",
"enable_delegation_credential_description": "Предоставете на Cal.com автоматичен достъп до календарите на всички членове на организацията чрез активиране на делегирани идентификационни данни.",
"disable_delegation_credential": "Деактивиране на делегирани идентификационни данни",
"disable_delegation_credential_description": "След деактивиране на делегираните идентификационни данни, членовете на организацията, които не са свързали календарите си, ще трябва да го направят ръчно.",
"last_active": "Последна активност",
"member_since": "Член от",
"last_updated": "Последно обновено",
"salesforce_on_cancel_write_to_event": "При отменена резервация, запиши в записа на събитието вместо да изтриеш събитието",
"salesforce_on_every_cancellation": "При всяка отмяна",
"report_issue": "Докладвай проблем",
"report_issue_description": "Можете да подадете билет в GitHub или да надградите плана си, за да получите поддръжка в реално време с конференции за разработчици",
"open_issue": "Отвори проблем",
"this_is_your_current_plan": "Това е текущият ви план",
"schedule_a_time": "Планирайте време",
"this_includes": "Това включва:",
"oauth_client_updated_successfully": "OAuth клиентът е актуализиран успешно",
"oauth_client_not_found": "OAuth клиентът не е намерен.",
"subscribe_to_platform": "Абонирайте се за платформата",
"error_accessing_webhooks": "Грешка при опит за достъп до уебхуки.",
"webhook_update_failed": "Неуспешно актуализиране на уебхук.",
"webhook_create_failed": "Неуспешно създаване на уебхук.",
"invalid_link": "Невалидна връзка",
"currently_subscribed_to_plan": "В момента сте абонирани за плана {{planFirstLetter}}{{planRest}}",
"user_team": "Потребител/Екип",
"client_id_copied": "Идентификаторът на клиента е копиран!",
"client_secret_copied": "Клиентската тайна е копирана!",
"maintenance_message": "Екипът на Cal.com извършва планирана поддръжка. Ако имате въпроси, моля, свържете се с поддръжката.",
"your_payment_failed": "Плащането ви не бе успешно",
"check_your_inbox": "Проверете входящата си поща",
"account_created_premium_not_reserved": "Вашият акаунт е създаден, но премиум потребителското име не е запазено.",
"email_sent_with_activation_link": "Изпратихме имейл до {{email}} с връзка за активиране на вашия акаунт.",
"activate_account_to_purchase_username": "След като активирате акаунта си, ще можете да опитате отново да закупите премиум потребителското си име или да изберете друго.",
"open_in_gmail": "Отворете в Gmail",
"dont_see_email": "Не виждате имейл?",
"resend_in_seconds": "Повторно изпращане след {{seconds}} секунди",
"resend": "Изпрати отново",
"verification_email_sent": "Имейлът за потвърждение е изпратен",
"select_all_members": "Изберете всички членове",
"select_all_members_tooltip": "Избирането на всички членове ще добави всички бъдещи членове на екипа, когато бъдат добавени към екипа.",
"form_settings": "Настройки на формуляра",
"remove_whitelist_status": "Премахване на статус в белия списък",
"whitelist_user_workflows": "Добавяне на потребителски работни процеси в белия списък",
"user_workflows_whitelisted": "Потребителските работни процеси са добавени в белия списък",
"user_workflows_unwhitelisted": "Потребителските работни процеси са премахнати от белия списък",
"date_and_time": "Дата и час",
"email_reminder_upcoming_event_notice": "Това е напомняне за предстоящото ви събитие.",
"email_reminder_triggered_by_workflow": "Това напомняне е задействано от работен процес в Cal.",
"event_upper_case": "Събитие",
"scheduling_by": "График от",
"experience_review_prompt": "Как бе вашето последно преживяване?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Колко сте доволни от последната си среща?",
"meeting_not_joined_question": "не присъствахте на срещата?",
"reschedule_cta_short": "Пренасрочете тук.",
"hide_organizer_email": "Скриване на имейла на организатора",
"platform_customer_cant_create_organization": "Вече сте част от платформена организация, поради което не можете да създадете нова организация. Всеки потребител може да принадлежи само към една организация. Моля, създайте нов акаунт в cal.com с различен имейл и използвайте този акаунт, за да се абонирате за плана за организации.",
"organization_customer_cant_create_platform": "Вече сте част от организация, поради което не можете да създадете платформена организация. Всеки потребител може да принадлежи само към една организация. Моля, създайте нов акаунт в cal.com с различен имейл и използвайте този акаунт, за да се абонирате за платформения план.",
"hide_organizer_email_description": "Скриване на имейл адреса на организатора от екрана за резервации, имейл известията и календарните събития",
"you_and_conjunction": "Вие &",
"email_survey_triggered_by_workflow": "Тази анкета беше стартирана от Workflow в Cal."
"select_verified_email": "Изберете потвърден имейл",
"custom_reply_to_email_title": "Персонализиран имейл за отговор",
"custom_reply_to_email_description": "Използвайте различен имейл адрес като адрес за отговор в имейлите за потвърждение вместо имейла на организатора",
"email_survey_triggered_by_workflow": "Тази анкета беше стартирана от Workflow в Cal.",
"skip_trial": "Пропускане на пробния период",
"team_trials_skipped_successfully": "Пробните периоди на екипа са пропуснати успешно",
"sms_workflow_consent": "С въвеждането на вашия телефонен номер давате съгласие да получавате SMS съобщения за това събитие. Може да се начислят такси за SMS.",
"routing_preview_more_info_found_insights": "Повече информация може да бъде намерена в <0>Анализи на маршрутизацията</0>",
"results": "Резултати",
"view_form": "Преглед на формуляра",
"sms_opt_out_message": "Изпратете STOP, за да се отпишете от SMS съобщенията",
"routing_form_next_in_queue": "{{count}} следващи на опашката",
"routing_form_select_members_to_email": "Изпращане на имейл отговори до",
"routing_incomplete_booking_tab": "Незавършени резервации",
"include_no_show_in_rr_calculation": "Включване на неявилите се резервации в изчисленията на round robin",
"matching": "Съвпадение",
"event_redirect": "Пренасочване на събитие",
"reset_form": "Нулиране на формуляра",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Добавете новите си низове над този ред ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+113 -6
View File
@@ -620,6 +620,7 @@
"your_full_name": "El teu nom complet",
"no_name": "Sense nom",
"enter_number_between_range": "Si us plau, introdueix un número entre 1 i {{maxOccurences}}",
"continue_as_guest_description": "Ràpid i fàcil - no cal compte. Perfecte per a reunions puntuals.",
"email_address": "Adreça de correu electrònic",
"enter_valid_email": "Si us plau, introdueix un correu electrònic vàlid",
"please_schedule_future_call": "Si us plau, programa una trucada futura si no estem disponibles en {{seconds}} segons",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Presencial (adreça de l'assistent)",
"somewhere_else": "Un altre lloc",
"custom_attendee_location": "Ubicació personalitzada de l'assistent",
"continue_as_guest": "Continua com a convidat",
"any_location": "Qualsevol ubicació",
"yes": "Sí",
"no": "No",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Equip actualitzat correctament",
"your_team_updated_successfully": "El teu equip s'ha actualitzat correctament.",
"your_org_updated_successfully": "La teva organització s'ha actualitzat correctament.",
"error_copying_to_clipboard": "Error en copiar al porta-retalls",
"about": "Sobre",
"team_description": "Unes quantes frases sobre el teu equip. Això apareixerà a la pàgina URL del teu equip.",
"organization_id": "ID de l'organització",
"organization_id_copied": "ID de l'organització copiat.",
"org_description": "Unes quantes frases sobre la teva organització. Això apareixerà a la pàgina URL de la teva organització.",
"team_id": "ID de l'equip",
"team_id_copied": "ID de l'equip copiat.",
"members": "Membres",
"organization_members": "Membres de l'organització",
"member": "Membre",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Estàs segur que vols eliminar aquest membre de l'equip?",
"confirm_disband_team": "Sí, dissoldre l'equip",
"confirm_remove_member": "Sí, eliminar membre",
"confirm_subscription_cancellation": "Sí, cancel·la la subscripció",
"cancel_subscription": "Cancel·la la subscripció",
"cancel_subscription_description": "Cancel·lar la teva subscripció desactivarà permanentment el teu pla actual. Aquesta acció no es pot desfer.",
"remove_member": "Eliminar membre",
"manage_your_team": "Gestiona el teu equip",
"no_teams": "Encara no tens cap equip.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "URL de la teva pàgina de reserves",
"booking_cancel_redirect_uri": "URL de la pàgina on els teus usuaris poden cancel·lar la seva reserva",
"booking_reschedule_redirect_uri": "URL de la pàgina on els teus usuaris poden reprogramar la seva reserva",
"booking_conflict_error": "Aquest horari ja no està disponible. Si us plau, torna a la pàgina anterior i selecciona un altre moment.",
"open_invitations": "Invitacions obertes",
"new_team": "Nou equip",
"create_first_team_and_invite_others": "Crea el teu primer equip i convida altres usuaris a treballar junts.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "El teu compte s'ha creat utilitzant un proveïdor d'identitat",
"account_managed_by_identity_provider": "El teu compte està gestionat per {{provider}}",
"account_managed_by_identity_provider_description": "Per canviar el teu correu electrònic, contrasenya, activar l'autenticació de dos factors i més, visita la configuració del teu compte de {{provider}}",
"account_managed_by_identity_provider_error": "El teu compte està gestionat per un proveïdor d'identitat diferent. Prova d'iniciar sessió amb {{provider}}.",
"user_creation_error": "Error en crear un nou usuari. Si us plau, torna-ho a provar.",
"signin_with_google": "Inicia sessió amb Google",
"signin_with_saml": "Inicia sessió amb SAML",
"signin_with_saml_oidc": "Inicia sessió amb SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Ja està tot llest!",
"install_zapier_app": "Si us plau, primer instal·la l'aplicació de Zapier a la botiga d'aplicacions",
"install_make_app": "Si us plau, primer instal·la l'aplicació de Make a la botiga d'aplicacions",
"app_installation": "Instal·lació de l'aplicació",
"app_not_installed": "Aplicació no instal·lada",
"visit_our_app_store": "Ho sentim, aquesta aplicació no està instal·lada al teu compte. Visita la nostra botiga d'aplicacions per explorar i descobrir aquesta i altres aplicacions genials",
"connect_apple_server": "Connecta amb el servidor d'Apple",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "quan es cancel·la l'esdeveniment",
"after_hosts_cal_video_no_show": "Després que els amfitrions no s'hagin unit al vídeo de Cal",
"after_guests_cal_video_no_show": "Després que els convidats no s'hagin unit al vídeo de Cal",
"join_video_call": "Uneix-te a la videotrucada",
"sign_in_to_cal_com": "Inicia sessió al teu compte de Cal.com",
"log_in_to_cal_com": "Inicia sessió a Cal.com",
"track_your_meetings": "Fes seguiment de les teves reunions, rep notificacions i gestiona la teva agenda de manera més efectiva.",
"choose_how_you_d_like_to_join_call": "Tria com vols unir-te a aquesta trucada",
"new_event_trigger": "quan es reserva un nou esdeveniment",
"email_host_action": "enviar correu a l'amfitrió",
"email_attendee_action": "enviar correu als assistents",
@@ -1361,6 +1380,8 @@
"custom": "Personalitzat",
"reminder": "Recordatori",
"rescheduled": "Reprogramat",
"rescheduled_by": "Reprogramat per",
"original_booking": "Reserva original",
"completed": "Completat",
"rating": "Valoració",
"reminder_email": "Recordatori: {{eventType}} amb {{name}} el {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "El flux de treball {{workflowName}} s'ha {{offOn}} correctament",
"download_responses": "Descarrega les respostes",
"download_responses_description": "Descarrega totes les respostes del teu formulari en format CSV",
"view_responses": "Veure respostes",
"download": "Descarrega",
"downloading": "Descarregant",
"download_recording": "Descarrega l'enregistrament",
"transcription_enabled": "Les transcripcions estan activades ara",
"transcription_stopped": "Les transcripcions s'han aturat ara",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Afegeix un nou formulari al teu equip",
"create_your_first_route": "Crea la teva primera ruta",
"route_to_the_right_person": "Dirigeix a la persona adequada segons les respostes del formulari",
"form": "Formulari",
"form_description": "Crea el teu formulari per encaminar una reserva",
"copy_link_to_form": "Copia l'enllaç al formulari",
"theme": "Tema de la pàgina de reserves",
@@ -1862,6 +1886,8 @@
"wrong_code": "Codi de verificació incorrecte",
"not_verified": "Encara no verificat",
"no_availability_in_month": "No hi ha disponibilitat al {{month}}",
"no_availability_rolling": "La programació només està disponible fins a {{days}} dies per endavant. Si us plau, torna a comprovar-ho aviat.",
"no_availability_range": "La programació va finalitzar el {{date}}. Si us plau, torneu a comprovar-ho aviat.",
"view_previous_month": "Veure el mes anterior",
"view_next_month": "Veure el mes següent",
"send_code": "Enviar codi",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Ja no és possible pagar per aquest esdeveniment",
"booking_with_payment_cancelled_already_paid": "El reemborsament d'aquest pagament de reserva està en camí.",
"booking_with_payment_cancelled_refunded": "S'ha reemborsat el pagament d'aquesta reserva.",
"booking_with_payment_cancelled_no_refund": "Segons la política de reemborsament de l'esdeveniment, el pagament de la reserva no és reemborsable.",
"booking_with_payment_cancelled_refund_window_expired": "El període de reemborsament de l'esdeveniment ha caducat. Per tant, el pagament de la reserva no és reemborsable.",
"booking_confirmation_failed": "La confirmació de la reserva ha fallat",
"not_enough_seats": "No hi ha prou places",
"form_builder_field_already_exists": "Ja existeix un camp amb aquest nom",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Obre la disponibilitat dels usuaris",
"organization_no_slots_notification_switch_title": "Rep notificacions quan el teu equip no tingui disponibilitat",
"organization_no_slots_notification_switch_description": "Els administradors rebran notificacions per correu electrònic quan un usuari intenti reservar amb un membre de l'equip i es trobi amb 'Sense disponibilitat'. Activem aquest correu després de dues ocurrències i t'ho recordem cada 7 dies per usuari.",
"organization_disable_phone_only_sms_notifications_switch_title": "Desactivar les notificacions SMS per a tipus d'esdeveniments només amb telèfon",
"organization_disable_phone_only_sms_notifications_switch_description": "Desactivar les notificacions SMS automatitzades per a tipus d'esdeveniments que només tenen el número de telèfon (attendeePhoneNumber) com a pregunta obligatòria amb el correu electrònic com a opcional o no requerit",
"email_team_invite|subject|added_to_org": "{{user}} t'ha afegit a l'organització {{team}} a {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} t'ha convidat a unir-te a l'organització {{team}} a {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} t'ha afegit a l'equip {{team}} de l'organització {{parentTeamName}} a {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "El teu enllaç ha canviat de {{a0}} a {{a1}}, però no et preocupis, tots els enllaços anteriors segueixen funcionant i redirigint adequadament. <br /><br />Tingues en compte: Tots els teus tipus d'esdeveniments personals s'han mogut a l'organització <strong>{{teamName}}</strong>, que també pot incloure un possible enllaç personal.<br /><br />Si us plau, inicia sessió i assegura't que no tens esdeveniments privats al teu nou compte d'organització.<br /><br />Per a esdeveniments personals, recomanem crear un nou compte amb una adreça de correu electrònic personal.<br /><br />Gaudeix del teu nou enllaç net: {{a2}}",
"email_organization_created|subject": "S'ha creat la teva organització",
"your_current_plan": "El teu pla actual",
"organization_price_per_user_month": "37$ per usuari al mes (mínim 30 usuaris)",
"organization_price_per_user_month": "37$ per usuari al mes",
"privacy_organization_description": "Gestiona la configuració de privacitat de la teva organització",
"privacy": "Privadesa",
"team_will_be_under_org": "Els nous equips estaran sota la vostra organització",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "En continuar, acceptes les nostres",
"terms": "Condicions",
"always_show_x_days": "Sempre {{x}} dies disponibles",
"team_subscription_cancelled_successfully": "Subscripció d'equip cancel·lada amb èxit",
"team_subscription_cancellation_error": "Error en cancel·lar la subscripció d'equip",
"unable_to_subscribe_to_the_platform": "S'ha produït un error en intentar subscriure's al pla de la plataforma, torna-ho a provar més tard",
"updating_oauth_client_error": "S'ha produït un error en actualitzar el client OAuth, torna-ho a provar més tard",
"creating_oauth_client_error": "S'ha produït un error en crear el client OAuth, torna-ho a provar més tard",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Omet la creació del registre {{entry}} si no existeix a Salesforce",
"salesforce_if_account_does_not_exist": "Si el contacte no existeix sota un compte, crea un nou lead de l'assistent",
"salesforce_create_new_contact_under_account": "Crea un nou contacte sota un compte basat en el domini de correu de l'assistent i els contactes existents",
"salesforce_change_record_owner_on_booking": "Canviar el propietari del registre en la reserva",
"mass_assign_attributes": "Assignació massiva d'atributs",
"reroute_preview_custom_message": "Això resulta en mostrar un missatge personalitzat. Prova de canviar la resposta per redirigir a un esdeveniment",
"reroute_preview_external_redirect": "Això resulta en redirigir a {{externalUrl}}. Prova de canviar la resposta per redirigir a un esdeveniment",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Redirigit a per període",
"per_day": "Per dia",
"per_week": "Per setmana",
"per_month": "Per mes",
"per_month": "al mes",
"routing_form_insights_assignment_reason": "Motiu d'assignació",
"access_denied": "Accés denegat",
"salesforce_route_to_owner": "El propietari del contacte serà l'amfitrió del Round Robin si està disponible",
"salesforce_add_attendees_as": "Afegir nous assistents com a",
"salesforce_do_not_route_to_owner": "El propietari del contacte no serà forçat (pot ser amfitrió si coincideix amb els atributs i criteris del Round Robin)",
"salesforce_route_to_custom_lookup_field": "Redirigir a un usuari que coincideixi amb un camp de cerca en un compte",
"salesforce_option": "Opció de Salesforce",
@@ -2927,6 +2961,7 @@
"shortfall": "Dèficit",
"routing_form": "Formulari d'encaminament",
"go_back_and_save": "Torna enrere i desa",
"save_changes": "Desar canvis",
"leave_without_saving": "Surt sense desar",
"leave_without_saving_description": "Estàs segur que vols sortir sense desar els canvis al formulari de rutes?",
"something_unexpected_occurred": "S'ha produït un error inesperat",
@@ -2961,6 +2996,9 @@
"authorize": "Autoritzar",
"next": "Següent",
"hide": "Amaga",
"show": "Mostrar",
"utm_params": "Paràmetres UTM",
"no_utm_params": "No hi ha paràmetres UTM disponibles.",
"asc": "Asc",
"desc": "Desc",
"verify_email_change": "Verifica el canvi de correu electrònic",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Necessiteu tenir un mínim d'equips publicats",
"you_are_part_of_this_organization_already": "Ja formeu part d'aquesta organització",
"you_are_part_of_another_organization_cannot_create_organization": "Formeu part d'una altra organització, no podeu crear-ne una de nova",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Formeu part d'una altra organització de plataforma, no podeu crear-ne una de nova",
"organization_payment_success": "Pagament de l'organització realitzat amb èxit",
"organization_payment_success_description": "La vostra organització s'ha creat correctament",
"this_may_take_a_few_seconds": "Això pot trigar uns segons...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "La incorporació de l'organització ja s'ha completat",
"organization_onboarding_already_exists": "La incorporació de l'organització ja existeix",
"organization_onboarding_not_found": "No s'ha trobat la incorporació de l'organització",
"payment_successful": "Pagament realitzat amb èxit",
"payment_successful": "Pagament realitzat amb èxit!",
"handover_onboarding_page_title": "Traspàs d'incorporació",
"handover_onboarding_page_description": "Traspàs d'incorporació a l'usuari",
"organization_already_exists_with_this_slug": "Ja existeix una organització amb aquest slug",
@@ -3019,9 +3058,12 @@
"link": "Enllaç",
"rows_per_page": "files per pàgina",
"pagination_status": "{{currentRange}} de {{totalItems}}",
"tip_username_plus": "Consell: Pots afegir un '+' entre noms d'usuari: cal.com/anna+brian per crear una reunió de grup dinàmica",
"tip_username_plus": "Consell: Podeu afegir un '+' entre noms d'usuari: cal.com/anna+brian per crear una reunió de grup dinàmica",
"user_has_no_team_yet": "Encara no tens cap equip",
"no_team_members": "Encara no tens membres a l'equip",
"recurring_event_doesnt_support_seats": "Els esdeveniments recurrents no admeten la funció de seients. Feu-lo no recurrent per habilitar els seients.",
"seats_doesnt_support_recurring": "La funció de seients no admet esdeveniments recurrents. Desactiveu la funció de seients per fer-lo recurrent.",
"recurring_event_seats_error": "Els esdeveniments recurrents no admeten la funció de seients. Desactiveu la funció de seients o feu que l'esdeveniment no sigui recurrent.",
"segment": "Segment",
"rename": "Canviar el nom",
"rename_segment": "Canviar el nom del segment",
@@ -3053,7 +3095,50 @@
"most_cancelled_bookings": "Reserves més cancel·lades",
"name_or_email": "Nom o correu electrònic",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Si no es troba cap contacte, recorre al propietari del lead si existeix",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Afegiu les vostres noves cadenes a dalt ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"enable_delegation_credential": "Activar credencial de delegació",
"enable_delegation_credential_description": "Concediu a Cal.com accés automàtic als calendaris de tots els membres de l'organització activant la credencial de delegació.",
"disable_delegation_credential": "Desactivar credencial de delegació",
"disable_delegation_credential_description": "Un cop desactivada la credencial de delegació, els membres de l'organització que no hagin connectat els seus calendaris hauran de fer-ho manualment.",
"last_active": "Última activitat",
"member_since": "Membre des de",
"last_updated": "Última actualització",
"salesforce_on_cancel_write_to_event": "En cancel·lar la reserva, escriu al registre d'esdeveniments en lloc d'eliminar l'esdeveniment",
"salesforce_on_every_cancellation": "En cada cancel·lació",
"report_issue": "Informar d'un problema",
"report_issue_description": "Pots enviar un tiquet a GitHub o actualitzar el teu pla per rebre suport en temps real amb conferències de desenvolupadors",
"open_issue": "Obrir incidència",
"this_is_your_current_plan": "Aquest és el teu pla actual",
"schedule_a_time": "Programa una hora",
"this_includes": "Això inclou:",
"oauth_client_updated_successfully": "Client OAuth actualitzat correctament",
"oauth_client_not_found": "Client OAuth no trobat.",
"subscribe_to_platform": "Subscriu-te a la plataforma",
"error_accessing_webhooks": "Error en intentar accedir als webhooks.",
"webhook_update_failed": "No s'ha pogut actualitzar el webhook.",
"webhook_create_failed": "No s'ha pogut crear el webhook.",
"invalid_link": "Enllaç no vàlid",
"currently_subscribed_to_plan": "Actualment estàs subscrit al pla {{planFirstLetter}}{{planRest}}",
"user_team": "Usuari/Equip",
"client_id_copied": "ID de client copiat!",
"client_secret_copied": "Secret de client copiat!",
"maintenance_message": "L'equip de Cal.com està realitzant un manteniment programat. Si tens alguna pregunta, contacta amb el suport.",
"your_payment_failed": "El teu pagament ha fallat",
"check_your_inbox": "Comprova la teva safata d'entrada",
"account_created_premium_not_reserved": "S'ha creat el teu compte, però el teu premium no s'ha reservat.",
"email_sent_with_activation_link": "Hem enviat un correu electrònic a {{email}} amb un enllaç per activar el teu compte.",
"activate_account_to_purchase_username": "Un cop activis el teu compte, podràs intentar comprar el teu nom d'usuari premium de nou o seleccionar-ne un de diferent.",
"open_in_gmail": "Obre a Gmail",
"dont_see_email": "No veus cap correu electrònic?",
"resend_in_seconds": "Torna a enviar en {{seconds}} segons",
"resend": "Torna a enviar",
"verification_email_sent": "Correu de verificació enviat",
"select_all_members": "Selecciona tots els membres",
"select_all_members_tooltip": "Seleccionar tots els membres afegirà tots els futurs membres de l'equip quan s'afegeixin a l'equip.",
"form_settings": "Configuració del formulari",
"remove_whitelist_status": "Elimina l'estat de llista blanca",
"whitelist_user_workflows": "Afegeix fluxos d'usuari a la llista blanca",
"user_workflows_whitelisted": "Fluxos d'usuari afegits a la llista blanca",
"user_workflows_unwhitelisted": "Fluxos d'usuari eliminats de la llista blanca",
"date_and_time": "Data i hora",
"email_reminder_upcoming_event_notice": "Aquest és un recordatori del vostre proper esdeveniment.",
"email_reminder_triggered_by_workflow": "Aquest recordatori s'ha activat per un flux de treball a Cal.",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Què satisfet esteu amb la vostra última reunió?",
"meeting_not_joined_question": "no vas assistir a la reunió?",
"reschedule_cta_short": "Reprograma aquí.",
"hide_organizer_email": "Amaga el correu electrònic de l'organitzador",
"platform_customer_cant_create_organization": "Ja formes part d'una organització de plataforma, per això no pots crear una nova organització. Cada usuari només pot pertànyer a una organització. Si us plau, crea un nou compte de cal.com amb un correu electrònic diferent i utilitza aquest compte per subscriure't al pla d'organitzacions.",
"organization_customer_cant_create_platform": "Ja formes part d'una organització, per això no pots crear una organització de plataforma. Cada usuari només pot pertànyer a una organització. Si us plau, crea un nou compte de cal.com amb un correu electrònic diferent i utilitza aquest compte per subscriure't al pla de plataforma.",
"hide_organizer_email_description": "Amaga l'adreça de correu electrònic de l'organitzador de la pantalla de reserva, les notificacions per correu electrònic i els esdeveniments del calendari",
"you_and_conjunction": "Vosaltres &",
"email_survey_triggered_by_workflow": "Aquesta enquesta va ser activada per un Workflow a Cal."
"select_verified_email": "Selecciona un correu electrònic verificat",
"custom_reply_to_email_title": "Correu electrònic personalitzat de 'Respondre a'",
"custom_reply_to_email_description": "Utilitza una adreça de correu electrònic diferent com a resposta per als correus de confirmació en lloc del correu de l'organitzador",
"email_survey_triggered_by_workflow": "Aquesta enquesta va ser activada per un Workflow a Cal.",
"skip_trial": "Salta el període de prova",
"team_trials_skipped_successfully": "Períodes de prova d'equip saltats amb èxit",
"sms_workflow_consent": "En introduir el teu número de telèfon, consents rebre missatges SMS per a aquest esdeveniment. Es poden aplicar tarifes de SMS.",
"routing_preview_more_info_found_insights": "Podeu trobar més informació a <0>Estadístiques de rutes</0>",
"results": "Resultats",
"view_form": "Veure formulari",
"sms_opt_out_message": "Envieu STOP per cancel·lar la subscripció als missatges SMS",
"routing_form_next_in_queue": "{{count}} següent a la cua",
"routing_form_select_members_to_email": "Enviar respostes per correu electrònic a",
"routing_incomplete_booking_tab": "Reserves incompletes",
"include_no_show_in_rr_calculation": "Incloure les reserves sense assistència en els càlculs de round robin",
"matching": "Coincidència",
"event_redirect": "Redirecció d'esdeveniments",
"reset_form": "Restablir formulari",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Afegiu les vostres noves cadenes a dalt ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+116 -9
View File
@@ -620,6 +620,7 @@
"your_full_name": "Vaše celé jméno",
"no_name": "Žádné jméno",
"enter_number_between_range": "Zadejte prosím číslo v rozpětí 1 a {{maxOccurences}}",
"continue_as_guest_description": "Rychlé a snadné - není potřeba účet. Ideální pro jednorázové schůzky.",
"email_address": "E-mailová adresa",
"enter_valid_email": "Zadejte platný e-mail",
"please_schedule_future_call": "Naplánujte prosím budoucí hovor, pokud nebudeme dostupní za {{seconds}} sekund",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Osobně (adresa účastníka)",
"somewhere_else": "Jiné místo",
"custom_attendee_location": "Vlastní místo účastníka",
"continue_as_guest": "Pokračovat jako host",
"any_location": "Jakékoliv místo",
"yes": "Ano",
"no": "Ne",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Tým byl úspěšně aktualizován",
"your_team_updated_successfully": "Váš tým byl úspěšně aktualizován.",
"your_org_updated_successfully": "Vaše organizace byla aktualizována.",
"error_copying_to_clipboard": "Chyba při kopírování do schránky",
"about": "O aplikaci",
"team_description": "Pár vět o vašem týmu. Objeví se na URL stránce vašeho týmu.",
"organization_id": "ID organizace",
"organization_id_copied": "ID organizace zkopírováno.",
"org_description": "Několik vět o vaší organizaci. Zobrazí se na adrese URL vaší organizace.",
"team_id": "ID týmu",
"team_id_copied": "ID týmu zkopírováno.",
"members": "Členové",
"organization_members": "Členové organizace",
"member": "Člen",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Opravdu chcete odstranit tohoto člena z týmu?",
"confirm_disband_team": "Ano, rozpustit tým",
"confirm_remove_member": "Ano, odebrat člena",
"confirm_subscription_cancellation": "Ano, zrušit předplatné",
"cancel_subscription": "Zrušit předplatné",
"cancel_subscription_description": "Zrušením předplatného trvale deaktivujete váš současný plán. Tuto akci nelze vrátit zpět.",
"remove_member": "Odebrat člena",
"manage_your_team": "Správa týmu",
"no_teams": "Zatím nemáte žádné týmy.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "URL vaší rezervační stránky",
"booking_cancel_redirect_uri": "URL stránky, kde mohou uživatelé zrušit svou rezervaci",
"booking_reschedule_redirect_uri": "URL stránky, kde mohou uživatelé přeplánovat svou rezervaci",
"booking_conflict_error": "Tento termín již není k dispozici. Vraťte se prosím na předchozí stránku a vyberte jiný čas.",
"open_invitations": "Otevřené pozvánky",
"new_team": "Nový tým",
"create_first_team_and_invite_others": "Vytvořte svůj první tým a pozvěte ostatní uživatele ke spolupráci.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Váš účet byl vytvořen pomocí Identity Providera.",
"account_managed_by_identity_provider": "Váš účet spravuje {{provider}}",
"account_managed_by_identity_provider_description": "Pro změnu e-mailu, hesla, dvoufázového ověřování apod. prosím přejděte do nastavení účtu {{provider}}.",
"account_managed_by_identity_provider_error": "Váš účet je spravován jiným poskytovatelem identity. Zkuste se přihlásit pomocí {{provider}}.",
"user_creation_error": "Chyba při vytváření nového uživatele. Zkuste to prosím znovu.",
"signin_with_google": "Přihlásit se pomocí Googlu",
"signin_with_saml": "Přihlásit se pomocí SAML",
"signin_with_saml_oidc": "Přihlášení pomocí SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Máte hotovo!",
"install_zapier_app": "Nejdřív si z App Store nainstalujte aplikaci Zapier.",
"install_make_app": "Nejprve si nainstalujte aplikaci Make z obchodu s aplikacemi.",
"app_installation": "Instalace aplikace",
"app_not_installed": "Aplikace není nainstalována",
"visit_our_app_store": "Omlouváme se, tato aplikace není nainstalována na vašem účtu. Navštivte náš obchod s aplikacemi a objevte tuto a další skvělé aplikace.",
"connect_apple_server": "Připojit se k serveru Apple",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "při zrušení události",
"after_hosts_cal_video_no_show": "Poté, co se hostitelé nepřipojili k video hovoru",
"after_guests_cal_video_no_show": "Poté, co se hosté nepřipojili k video hovoru",
"join_video_call": "Připojit se k videohovoru",
"sign_in_to_cal_com": "Přihlaste se ke svému účtu Cal.com",
"log_in_to_cal_com": "Přihlásit se do Cal.com",
"track_your_meetings": "Sledujte své schůzky, dostávejte oznámení a efektivněji spravujte svůj rozvrh.",
"choose_how_you_d_like_to_join_call": "Vyberte, jak se chcete připojit k tomuto hovoru",
"new_event_trigger": "při rezervaci nové události",
"email_host_action": "odeslání e-mailu hostiteli",
"email_attendee_action": "odeslat e-mail účastníkům",
@@ -1361,6 +1380,8 @@
"custom": "Vlastní",
"reminder": "Upomínka",
"rescheduled": "Změna termínu",
"rescheduled_by": "Přeplánováno uživatelem",
"original_booking": "Původní rezervace",
"completed": "Dokončeno",
"rating": "Hodnocení",
"reminder_email": "Upomínka: událost {{eventType}} s uživatelem {{name}} dne {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "Pracovní postup {{workflowName}} byl {{offOn}}",
"download_responses": "Stáhnout odpovědi",
"download_responses_description": "Stáhněte si všechny odpovědi do formuláře ve formátu CSV.",
"view_responses": "Zobrazit odpovědi",
"download": "Stáhnout",
"downloading": "Stahování",
"download_recording": "Stáhnout nahrávku",
"transcription_enabled": "Přepisy jsou nyní povoleny",
"transcription_stopped": "Přepisy byly zastaveny",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Přidání nového formuláře do vašeho týmu",
"create_your_first_route": "Vytvořte svoje první směrování",
"route_to_the_right_person": "Nasměrovat té správné osobě na základě odpovědí ve vašem formuláři",
"form": "Formulář",
"form_description": "Vytvořte vlastní formulář, který adresujete rezervující osobě",
"copy_link_to_form": "Kopírovat odkaz na formulář",
"theme": "Motiv stránky pro rezervace",
@@ -1862,6 +1886,8 @@
"wrong_code": "Nesprávný ověřovací kód",
"not_verified": "Zatím neověřeno",
"no_availability_in_month": "Žádná dostupnost pro {{month}}",
"no_availability_rolling": "Plánování je dostupné pouze {{days}} dní dopředu. Zkontrolujte to prosím brzy znovu.",
"no_availability_range": "Plánování skončilo dne {{date}}. Zkontrolujte prosím brzy znovu.",
"view_previous_month": "Zobrazit předchozí měsíc",
"view_next_month": "Zobrazit další měsíc",
"send_code": "Odeslat kód",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Platba za tuto událost již není možná",
"booking_with_payment_cancelled_already_paid": "Vrácení peněz za tuto rezervační platbu je na cestě.",
"booking_with_payment_cancelled_refunded": "Tato rezervační platba byla vrácena.",
"booking_with_payment_cancelled_no_refund": "Podle pravidel pro vrácení peněz této události není platba za rezervaci vratná.",
"booking_with_payment_cancelled_refund_window_expired": "Lhůta pro vrácení peněz za událost vypršela. Proto platba za rezervaci není vratná.",
"booking_confirmation_failed": "Potvrzení rezervace se nezdařilo",
"not_enough_seats": "Nedostatek míst",
"form_builder_field_already_exists": "Pole s tímto názvem již existuje",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Otevřít dostupnost uživatelů",
"organization_no_slots_notification_switch_title": "Dostávejte upozornění, když váš tým nemá žádnou dostupnost",
"organization_no_slots_notification_switch_description": "Administrátoři budou dostávat e-mailová upozornění, když se uživatel pokusí rezervovat člena týmu a zjistí, že není žádná dostupnost. Tento e-mail spustíme po dvou výskytech a připomeneme vám to každých 7 dní na uživatele.",
"organization_disable_phone_only_sms_notifications_switch_title": "Zakázat SMS oznámení pro typy událostí pouze s telefonem",
"organization_disable_phone_only_sms_notifications_switch_description": "Zakázat automatická SMS oznámení pro typy událostí, které vyžadují pouze telefonní číslo (attendeePhoneNumber) jako povinnou otázku s e-mailem jako volitelným nebo nevyžadovaným",
"email_team_invite|subject|added_to_org": "{{user}} vás přidal(a) do organizace {{team}} na {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} vás pozval(a) k připojení do organizace {{team}} na {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} vás přidal(a) do týmu {{team}} v organizaci {{parentTeamName}} na {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Váš odkaz byl změněn z {{a0}} na {{a1}}, ale nebojte se, všechny předchozí odkazy stále fungují a správně přesměrovávají. <br /><br />Upozorňujeme: Všechny vaše osobní typy událostí byly přesunuty do organizace <strong>{{teamName}}</strong>, což může zahrnovat i potenciální osobní odkaz.<br /><br />Přihlaste se a ujistěte se, že na svém novém organizačním účtu nemáte žádné soukromé události.<br /><br />Pro osobní události doporučujeme vytvořit nový účet s osobní e-mailovou adresou.<br /><br />Užijte si svůj nový čistý odkaz: {{a2}}",
"email_organization_created|subject": "Vaše organizace byla vytvořena",
"your_current_plan": "Váš aktuální plán",
"organization_price_per_user_month": "$37 za uživatele měsíčně (minimálně 30 míst)",
"organization_price_per_user_month": "$37 za uživatele za měsíc",
"privacy_organization_description": "Spravujte nastavení soukromí pro vaši organizaci",
"privacy": "Ochrana soukromí",
"team_will_be_under_org": "Nové týmy budou pod vaší organizací",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Pokračováním souhlasíte s našimi",
"terms": "Podmínkami",
"always_show_x_days": "Vždy dostupné {{x}} dní",
"team_subscription_cancelled_successfully": "Předplatné týmu bylo úspěšně zrušeno",
"team_subscription_cancellation_error": "Chyba při rušení předplatného týmu",
"unable_to_subscribe_to_the_platform": "Při pokusu o přihlášení k plánu platformy došlo k chybě, zkuste to prosím znovu později",
"updating_oauth_client_error": "Při aktualizaci OAuth klienta došlo k chybě, zkuste to prosím znovu později",
"creating_oauth_client_error": "Při vytváření OAuth klienta došlo k chybě, zkuste to prosím znovu později",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Přeskočit vytvoření záznamu {{entry}}, pokud neexistuje v Salesforce",
"salesforce_if_account_does_not_exist": "Pokud kontakt neexistuje pod účtem, vytvořte nový lead z účastníka",
"salesforce_create_new_contact_under_account": "Vytvořte nový kontakt pod účtem na základě e-mailové domény účastníka a existujících kontaktů",
"salesforce_change_record_owner_on_booking": "Změnit vlastníka záznamu při rezervaci",
"mass_assign_attributes": "Hromadné přiřazení atributů",
"reroute_preview_custom_message": "Výsledkem je zobrazení vlastní zprávy. Zkuste změnit odpověď na přesměrování na událost",
"reroute_preview_external_redirect": "Výsledkem je přesměrování na {{externalUrl}}. Zkuste změnit odpověď na přesměrování na událost",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Přesměrováno za období",
"per_day": "Za den",
"per_week": "Za týden",
"per_month": "Za měsíc",
"per_month": "za měsíc",
"routing_form_insights_assignment_reason": "Důvod přiřazení",
"access_denied": "Přístup odepřen",
"salesforce_route_to_owner": "Vlastník kontaktu bude hostem Round Robin, pokud je k dispozici",
"salesforce_add_attendees_as": "Přidat nové účastníky jako",
"salesforce_do_not_route_to_owner": "Vlastník kontaktu nebude nucen (stále může být hostem, pokud odpovídá atributům a kritériím Round Robin)",
"salesforce_route_to_custom_lookup_field": "Přiřadit uživateli, který odpovídá vyhledávacímu poli na účtu",
"salesforce_option": "Možnost Salesforce",
@@ -2927,6 +2961,7 @@
"shortfall": "Nedostatek",
"routing_form": "Směrovací formulář",
"go_back_and_save": "Vrátit se a uložit",
"save_changes": "Uložit změny",
"leave_without_saving": "Odejít bez uložení",
"leave_without_saving_description": "Opravdu chcete odejít bez uložení změn ve vašem směrovacím formuláři?",
"something_unexpected_occurred": "Došlo k neočekávané chybě",
@@ -2961,6 +2996,9 @@
"authorize": "Autorizovat",
"next": "Další",
"hide": "Skrýt",
"show": "Zobrazit",
"utm_params": "UTM parametry",
"no_utm_params": "Žádné UTM parametry nejsou k dispozici.",
"asc": "Vzestupně",
"desc": "Sestupně",
"verify_email_change": "Ověřit změnu e-mailu",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Musíte mít minimální počet publikovaných týmů",
"you_are_part_of_this_organization_already": "Již jste součástí této organizace",
"you_are_part_of_another_organization_cannot_create_organization": "Jste součástí jiné organizace, nelze vytvořit novou organizaci",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Jste součástí jiné platformové organizace, nelze vytvořit novou organizaci",
"organization_payment_success": "Platba za organizaci byla úspěšná",
"organization_payment_success_description": "Vaše organizace byla úspěšně vytvořena",
"this_may_take_a_few_seconds": "Toto může trvat několik sekund...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Úvodní zaškolení organizace již bylo dokončeno",
"organization_onboarding_already_exists": "Úvodní zaškolení organizace již existuje",
"organization_onboarding_not_found": "Úvodní zaškolení organizace nebylo nalezeno",
"payment_successful": "Platba byla úspěšná",
"payment_successful": "Platba úspěšná!",
"handover_onboarding_page_title": "Předání úvodního zaškolení",
"handover_onboarding_page_description": "Předání úvodního zaškolení uživateli",
"organization_already_exists_with_this_slug": "Organizace s tímto slugem již existuje",
@@ -3019,9 +3058,12 @@
"link": "Odkaz",
"rows_per_page": "řádků na stránku",
"pagination_status": "{{currentRange}} z {{totalItems}}",
"tip_username_plus": "Tip: Mezi uživatelská jména můžete vložit '+': cal.com/anna+brian pro vytvoření dynamické skupinové schůzky",
"tip_username_plus": "Tip: Mezi uživatelská jména můžete přidat '+': cal.com/anna+brian pro vytvoření dynamické skupinové schůzky",
"user_has_no_team_yet": "Zatím nemáte žádný tým",
"no_team_members": "Zatím nemáte žádné členy týmu",
"recurring_event_doesnt_support_seats": "Opakující se událost nepodporuje funkci míst. Změňte ji na neopakující se pro povolení míst.",
"seats_doesnt_support_recurring": "Funkce míst nepodporuje opakující se události. Zakažte funkci míst pro vytvoření opakující se události.",
"recurring_event_seats_error": "Opakující se událost nepodporuje funkci míst. Zakažte funkci míst nebo změňte událost na neopakující se.",
"segment": "Segment",
"rename": "Přejmenovat",
"rename_segment": "Přejmenovat segment",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Nejčastěji zrušené rezervace",
"name_or_email": "Jméno nebo e-mail",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Pokud není nalezen žádný kontakt, použít vlastníka leadu, pokud existuje",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Přidejte své nové řetězce nahoru ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Datum a čas",
"email_reminder_upcoming_event_notice" : "Toto je připomínka vaší nadcházející události.",
"email_reminder_triggered_by_workflow" : "Toto připomenutí bylo spuštěno pracovním postupem v Cal.",
"enable_delegation_credential": "Povolit delegované pověření",
"enable_delegation_credential_description": "Udělte Cal.com automatický přístup ke kalendářům všech členů organizace povolením delegovaného pověření.",
"disable_delegation_credential": "Zakázat delegované pověření",
"disable_delegation_credential_description": "Jakmile je delegované pověření zakázáno, členové organizace, kteří nepropojili své kalendáře, to budou muset udělat ručně.",
"last_active": "Naposledy aktivní",
"member_since": "Členem od",
"last_updated": "Naposledy aktualizováno",
"salesforce_on_cancel_write_to_event": "Při zrušení rezervace zapsat do záznamu události místo smazání události",
"salesforce_on_every_cancellation": "Při každém zrušení",
"report_issue": "Nahlásit problém",
"report_issue_description": "Můžete odeslat ticket na GitHubu nebo upgradovat svůj plán pro získání podpory v reálném čase s vývojářskými konferencemi",
"open_issue": "Otevřít problém",
"this_is_your_current_plan": "Toto je váš aktuální plán",
"schedule_a_time": "Naplánovat čas",
"this_includes": "Toto zahrnuje:",
"oauth_client_updated_successfully": "OAuth klient byl úspěšně aktualizován",
"oauth_client_not_found": "OAuth klient nebyl nalezen.",
"subscribe_to_platform": "Přihlásit se k odběru platformy",
"error_accessing_webhooks": "Chyba při pokusu o přístup k webhookům.",
"webhook_update_failed": "Aktualizace webhooku se nezdařila.",
"webhook_create_failed": "Vytvoření webhooku se nezdařilo.",
"invalid_link": "Neplatný odkaz",
"currently_subscribed_to_plan": "Aktuálně máte předplacený plán {{planFirstLetter}}{{planRest}}",
"user_team": "Uživatel/Tým",
"client_id_copied": "ID klienta zkopírováno!",
"client_secret_copied": "Tajný klíč klienta zkopírován!",
"maintenance_message": "Tým Cal.com provádí plánovanou údržbu. Pokud máte jakékoli dotazy, kontaktujte podporu.",
"your_payment_failed": "Vaše platba se nezdařila",
"check_your_inbox": "Zkontrolujte svou e-mailovou schránku",
"account_created_premium_not_reserved": "Váš účet byl vytvořen, ale vaše prémiové uživatelské jméno nebylo rezervováno.",
"email_sent_with_activation_link": "Poslali jsme e-mail na adresu {{email}} s odkazem pro aktivaci vašeho účtu.",
"activate_account_to_purchase_username": "Jakmile aktivujete svůj účet, budete moci znovu zkusit zakoupit své prémiové uživatelské jméno nebo vybrat jiné.",
"open_in_gmail": "Otevřít v Gmailu",
"dont_see_email": "Nevidíte e-mail?",
"resend_in_seconds": "Znovu odeslat za {{seconds}} sekund",
"resend": "Znovu odeslat",
"verification_email_sent": "Ověřovací e-mail odeslán",
"select_all_members": "Vybrat všechny členy",
"select_all_members_tooltip": "Výběr všech členů přidá všechny budoucí členy týmu, když budou přidáni do týmu.",
"form_settings": "Nastavení formuláře",
"remove_whitelist_status": "Odebrat status na whitelist",
"whitelist_user_workflows": "Přidat uživatelské workflow na whitelist",
"user_workflows_whitelisted": "Uživatelské workflow přidáno na whitelist",
"user_workflows_unwhitelisted": "Uživatelské workflow odebráno z whitelist",
"date_and_time": "Datum a čas",
"email_reminder_upcoming_event_notice": "Toto je připomínka vaší nadcházející události.",
"email_reminder_triggered_by_workflow": "Toto připomenutí bylo spuštěno pracovním postupem v Cal.",
"event_upper_case": "Událost",
"scheduling_by": "Plánování podle",
"experience_review_prompt": "Jaké byly vaše nedávné zkušenosti?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Jak jste spokojeni s vaším posledním jednáním?",
"meeting_not_joined_question": "nejste se zúčastnili schůzky?",
"reschedule_cta_short": "Přeplánujte zde.",
"hide_organizer_email": "Skrýt e-mail organizátora",
"platform_customer_cant_create_organization": "Jste již součástí platformní organizace, proto nemůžete vytvořit novou organizaci. Každý uživatel může patřit pouze do jedné organizace. Vytvořte si prosím nový účet cal.com s jiným e-mailem a použijte tento účet k předplacení organizačního plánu.",
"organization_customer_cant_create_platform": "Jste již součástí organizace, proto nemůžete vytvořit platformní organizaci. Každý uživatel může patřit pouze do jedné organizace. Vytvořte si prosím nový účet cal.com s jiným e-mailem a použijte tento účet k předplacení platformního plánu.",
"hide_organizer_email_description": "Skrýt e-mailovou adresu organizátora na obrazovce rezervace, v e-mailových oznámeních a událostech kalendáře",
"you_and_conjunction": "Vy &",
"email_survey_triggered_by_workflow": "Tento průzkum byl spuštěn pracovním postupem v Cal."
"select_verified_email": "Vyberte ověřený e-mail",
"custom_reply_to_email_title": "Vlastní e-mail pro odpověď",
"custom_reply_to_email_description": "Použít jinou e-mailovou adresu jako adresu pro odpověď v potvrzovacích e-mailech místo e-mailu organizátora",
"email_survey_triggered_by_workflow": "Tento průzkum byl spuštěn pracovním postupem v Cal.",
"skip_trial": "Přeskočit zkušební období",
"team_trials_skipped_successfully": "Zkušební období týmu úspěšně přeskočeno",
"sms_workflow_consent": "Zadáním svého telefonního čísla souhlasíte s přijímáním SMS zpráv pro tuto událost. Mohou být účtovány poplatky za SMS.",
"routing_preview_more_info_found_insights": "Více informací najdete v <0>Přehledu směrování</0>",
"results": "Výsledky",
"view_form": "Zobrazit formulář",
"sms_opt_out_message": "Odešlete STOP pro odhlášení z SMS zpráv",
"routing_form_next_in_queue": "{{count}} další ve frontě",
"routing_form_select_members_to_email": "Odeslat e-mailové odpovědi na",
"routing_incomplete_booking_tab": "Nedokončené rezervace",
"include_no_show_in_rr_calculation": "Zahrnout nedostavené rezervace do výpočtů round robin",
"matching": "Odpovídající",
"event_redirect": "Přesměrování události",
"reset_form": "Resetovat formulář",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Přidejte své nové řetězce nahoru ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+115 -8
View File
@@ -620,6 +620,7 @@
"your_full_name": "Dit fulde navn",
"no_name": "Intet navn",
"enter_number_between_range": "Indtast venligst et nummer mellem 1 og {{maxOccurences}}",
"continue_as_guest_description": "Hurtigt og nemt - ingen konto nødvendig. Perfekt til engangsmøder.",
"email_address": "E-mail adresse",
"enter_valid_email": "Indtast venligst en gyldig e-mail",
"please_schedule_future_call": "Planlæg venligst et fremtidigt opkald, hvis vi ikke er tilgængelige om {{seconds}} sekunder",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Personlig (Deltageradresse)",
"somewhere_else": "Et andet sted",
"custom_attendee_location": "Brugerdefineret deltagerlokation",
"continue_as_guest": "Fortsæt som gæst",
"any_location": "Enhver lokation",
"yes": "Ja",
"no": "Nej",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Team opdateret",
"your_team_updated_successfully": "Dit team er blevet opdateret.",
"your_org_updated_successfully": "Din organisation er blevet opdateret med succes.",
"error_copying_to_clipboard": "Fejl ved kopiering til udklipsholder",
"about": "Om",
"team_description": "Et par sætninger om dit team. Dette vil blive vist på dit teams url side.",
"organization_id": "Organisations-ID",
"organization_id_copied": "Organisations-ID kopieret.",
"org_description": "Et par sætninger om din organisation. Dette vil fremgå på din organisations URL-side.",
"team_id": "Team-ID",
"team_id_copied": "Team-ID kopieret.",
"members": "Medlemmer",
"organization_members": "Organisationsmedlemmer",
"member": "Medlem",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Er du sikker på du vil fjerne dette medlem fra teamet?",
"confirm_disband_team": "Ja, opløs holdet",
"confirm_remove_member": "Ja, fjern medlem",
"confirm_subscription_cancellation": "Ja, annuller abonnement",
"cancel_subscription": "Annuller abonnement",
"cancel_subscription_description": "Annullering af dit abonnement vil permanent deaktivere din nuværende plan. Denne handling kan ikke fortrydes.",
"remove_member": "Fjern medlem",
"manage_your_team": "Administrér dit team",
"no_teams": "Du har ikke nogen teams endnu.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "URL til din bookingside",
"booking_cancel_redirect_uri": "URL til siden hvor dine brugere kan aflyse deres booking",
"booking_reschedule_redirect_uri": "URL til siden hvor dine brugere kan ombooke deres aftale",
"booking_conflict_error": "Denne tid er ikke længere tilgængelig. Gå tilbage til den forrige side og vælg et andet tidspunkt.",
"open_invitations": "Åbne Invitationer",
"new_team": "Nyt Team",
"create_first_team_and_invite_others": "Opret dit første team og inviter andre brugere til at arbejde sammen.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Din konto blev oprettet ved hjælp af en Identitetsudbyder.",
"account_managed_by_identity_provider": "Din konto administreres af {{provider}}",
"account_managed_by_identity_provider_description": "For at ændre din e-mail, adgangskode, aktivere to-faktor autentificering og mere, besøg venligst dine {{provider}} kontoindstillinger.",
"account_managed_by_identity_provider_error": "Din konto administreres af en anden identitetsudbyder. Prøv at logge ind med {{provider}}.",
"user_creation_error": "Fejl ved oprettelse af ny bruger. Prøv igen.",
"signin_with_google": "Log ind med Google",
"signin_with_saml": "Log ind med SAML",
"signin_with_saml_oidc": "Log ind med SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Du er klar!",
"install_zapier_app": "Du skal først installere Zapier appen i App Store.",
"install_make_app": "Installer venligst først Make-appen i app-butikken.",
"app_installation": "Appinstallation",
"app_not_installed": "App ikke installeret",
"visit_our_app_store": "Beklager, denne app er ikke installeret på din konto. Besøg venligst vores app-butik for at udforske og opdage denne og andre fantastiske apps.",
"connect_apple_server": "Forbind til Apple Server",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "når begivenheden er aflyst",
"after_hosts_cal_video_no_show": "Efter værterne ikke deltog i cal-videomødet",
"after_guests_cal_video_no_show": "Efter gæsterne ikke deltog i cal-videomødet",
"join_video_call": "Deltag i videoopkaldet",
"sign_in_to_cal_com": "Log ind på din Cal.com-konto",
"log_in_to_cal_com": "Log ind på Cal.com",
"track_your_meetings": "Følg dine møder, få notifikationer og administrer din tidsplan mere effektivt.",
"choose_how_you_d_like_to_join_call": "Vælg, hvordan du vil deltage i dette opkald",
"new_event_trigger": "når ny begivenhed er booket",
"email_host_action": "send e-mail til vært",
"email_attendee_action": "send e-mail til deltagere",
@@ -1361,6 +1380,8 @@
"custom": "Brugerdefineret",
"reminder": "Påmindelse",
"rescheduled": "Omplanlagt",
"rescheduled_by": "Omplanlagt af",
"original_booking": "Oprindelig booking",
"completed": "Fuldført",
"rating": "Bedømmelse",
"reminder_email": "Påmindelse: {{eventType}} med {{name}} den {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "{{workflowName}} workflow er nu slået {{offOn}}",
"download_responses": "Download Svar",
"download_responses_description": "Download alle svar på din formular i CSV-format.",
"view_responses": "Se svar",
"download": "Download",
"downloading": "Downloader",
"download_recording": "Download optagelse",
"transcription_enabled": "Transskriptioner er nu aktiveret",
"transcription_stopped": "Transskriptioner er nu stoppet",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Tilføj ny formular til dit team",
"create_your_first_route": "Opret din første rute",
"route_to_the_right_person": "Rute til den rette person baseret på svarene på din formular",
"form": "Formular",
"form_description": "Opret din formular for at rute en booker",
"copy_link_to_form": "Kopiér link til formular",
"theme": "Tema for bookingside",
@@ -1862,6 +1886,8 @@
"wrong_code": "Forkert bekræftelseskode",
"not_verified": "Endnu ikke bekræftet",
"no_availability_in_month": "Ingen tilgængelighed i {{month}}",
"no_availability_rolling": "Planlægning er kun tilgængelig op til {{days}} dage i forvejen. Kom snart tilbage.",
"no_availability_range": "Planlægning sluttede den {{date}}. Tjek venligst igen snart.",
"view_previous_month": "Se forrige måned",
"view_next_month": "Vis næste måned",
"send_code": "Send kode",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Det er ikke længere muligt at betale for denne begivenhed",
"booking_with_payment_cancelled_already_paid": "En tilbagebetaling for denne booking betaling er på vej.",
"booking_with_payment_cancelled_refunded": "Denne booking betaling er blevet refunderet.",
"booking_with_payment_cancelled_no_refund": "I henhold til arrangementets refunderingspolitik er betalingen for bookingen ikke refunderbar.",
"booking_with_payment_cancelled_refund_window_expired": "Arrangementets refunderingsperiode er udløbet. Derfor er betalingen for bookingen ikke refunderbar.",
"booking_confirmation_failed": "Reservationsbekræftelse mislykkedes",
"not_enough_seats": "Ikke nok pladser",
"form_builder_field_already_exists": "Et felt med dette navn findes allerede",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Åbn brugernes tilgængelighed",
"organization_no_slots_notification_switch_title": "Få besked, når dit team ikke har nogen tilgængelighed",
"organization_no_slots_notification_switch_description": "Administratorer vil få e-mailbeskeder, når en bruger forsøger at booke et teammedlem og møder 'Ingen tilgængelighed'. Vi udløser denne e-mail efter to forekomster og minder dig om det hver 7. dag pr. bruger.",
"organization_disable_phone_only_sms_notifications_switch_title": "Deaktiver SMS-notifikationer for kun telefonbaserede begivenhedstyper",
"organization_disable_phone_only_sms_notifications_switch_description": "Deaktiver automatiske SMS-notifikationer for begivenhedstyper, der kun har telefonnummer (attendeePhoneNumber) som obligatorisk spørgsmål, hvor e-mail er valgfri eller ikke påkrævet",
"email_team_invite|subject|added_to_org": "{{user}} har tilføjet dig til organisationen {{team}} på {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} har inviteret dig til at deltage i organisationen {{team}} på {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} har tilføjet dig til teamet {{team}} i organisationen {{parentTeamName}} på {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Dit link er blevet ændret fra {{a0}} til {{a1}}, men bare rolig, alle tidligere links fungerer stadig og omdirigerer korrekt. <br /><br />Bemærk venligst: Alle dine personlige begivenhedstyper er blevet flyttet til <strong>{{teamName}}</strong> organisationen, hvilket også kan omfatte potentielle personlige links.<br /><br />Log venligst ind og sørg for, at du ikke har private begivenheder på din nye organisationskonto.<br /><br />Til personlige begivenheder anbefaler vi at oprette en ny konto med en personlig e-mailadresse.<br /><br />Nyd dit nye rene link: {{a2}}",
"email_organization_created|subject": "Din organisation er blevet oprettet",
"your_current_plan": "Din nuværende plan",
"organization_price_per_user_month": "$37 per bruger pr. måned (minimum 30 pladser)",
"organization_price_per_user_month": "$37 pr. bruger pr. måned",
"privacy_organization_description": "Administrer privatlivsindstillinger for din organisation",
"privacy": "Privatliv",
"team_will_be_under_org": "Nye teams vil være under din organisation",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Ved at fortsætte accepterer du vores",
"terms": "Vilkår",
"always_show_x_days": "Vis altid {{x}} dage tilgængelige",
"team_subscription_cancelled_successfully": "Teamabonnement annulleret med succes",
"team_subscription_cancellation_error": "Fejl under annullering af teamabonnement",
"unable_to_subscribe_to_the_platform": "Der opstod en fejl under forsøget på at abonnere på platformplanen, prøv venligst igen senere",
"updating_oauth_client_error": "Der opstod en fejl under opdatering af OAuth-klienten, prøv venligst igen senere",
"creating_oauth_client_error": "Der opstod en fejl under oprettelse af OAuth-klienten, prøv venligst igen senere",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Spring oprettelse af {{entry}}-post over, hvis de ikke findes i Salesforce",
"salesforce_if_account_does_not_exist": "Hvis kontakten ikke findes under en konto, opret nyt lead fra deltager",
"salesforce_create_new_contact_under_account": "Opret en ny kontakt under en konto baseret på deltagerens e-maildomæne og eksisterende kontakter",
"salesforce_change_record_owner_on_booking": "Skift ejer af post ved booking",
"mass_assign_attributes": "Masse tildel attributter",
"reroute_preview_custom_message": "Det resulterer i at vise en tilpasset besked. Prøv at ændre svaret til at omdirigere til en begivenhed",
"reroute_preview_external_redirect": "Det resulterer i en omdirigering til {{externalUrl}}. Prøv at ændre svaret til at omdirigere til en begivenhed",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Dirigeret til pr. periode",
"per_day": "Pr. dag",
"per_week": "Pr. uge",
"per_month": "Pr. måned",
"per_month": "pr. måned",
"routing_form_insights_assignment_reason": "Tildelingsårsag",
"access_denied": "Adgang nægtet",
"salesforce_route_to_owner": "Kontaktens ejer vil være Round Robin-vært, hvis tilgængelig",
"salesforce_add_attendees_as": "Tilføj nye deltagere som",
"salesforce_do_not_route_to_owner": "Kontaktens ejer vil ikke blive tvunget (kan stadig være vært, hvis det matcher attributterne og Round Robin-kriterierne)",
"salesforce_route_to_custom_lookup_field": "Rute til en bruger, der matcher et opslagfelt på en konto",
"salesforce_option": "Salesforce-indstilling",
@@ -2927,6 +2961,7 @@
"shortfall": "Underskud",
"routing_form": "Routing-formular",
"go_back_and_save": "Gå tilbage og gem",
"save_changes": "Gem ændringer",
"leave_without_saving": "Forlad uden at gemme",
"leave_without_saving_description": "Er du sikker på, at du vil forlade siden uden at gemme ændringerne i din rutningsformular?",
"something_unexpected_occurred": "Der opstod en uventet fejl",
@@ -2961,6 +2996,9 @@
"authorize": "Godkend",
"next": "Næste",
"hide": "Skjul",
"show": "Vis",
"utm_params": "UTM-parametre",
"no_utm_params": "Ingen UTM-parametre tilgængelige.",
"asc": "Stigende",
"desc": "Faldende",
"verify_email_change": "Bekræft ændring af e-mail",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Du skal have et minimum af offentliggjorte teams",
"you_are_part_of_this_organization_already": "Du er allerede en del af denne organisation",
"you_are_part_of_another_organization_cannot_create_organization": "Du er en del af en anden organisation, kan ikke oprette en ny organisation",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Du er en del af en anden platformorganisation, kan ikke oprette en ny organisation",
"organization_payment_success": "Organisationsbetaling gennemført",
"organization_payment_success_description": "Din organisation er blevet oprettet med succes",
"this_may_take_a_few_seconds": "Dette kan tage et par sekunder...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Organisationens onboarding er allerede gennemført",
"organization_onboarding_already_exists": "Organisationens onboarding eksisterer allerede",
"organization_onboarding_not_found": "Organisationens onboarding blev ikke fundet",
"payment_successful": "Betaling gennemført",
"payment_successful": "Betaling gennemført!",
"handover_onboarding_page_title": "Overdragelse af onboarding",
"handover_onboarding_page_description": "Overdragelse af onboarding til brugeren",
"organization_already_exists_with_this_slug": "En organisation med dette slug findes allerede",
@@ -3022,6 +3061,9 @@
"tip_username_plus": "Tip: Du kan tilføje et '+' mellem brugernavne: cal.com/anna+brian for at lave et dynamisk gruppemøde",
"user_has_no_team_yet": "Du har ikke et team endnu",
"no_team_members": "Du har ikke nogen teammedlemmer endnu",
"recurring_event_doesnt_support_seats": "Tilbagevendende begivenheder understøtter ikke sædefunktionen. Gør den ikke-tilbagevendende for at aktivere sæder.",
"seats_doesnt_support_recurring": "Sædefunktionen understøtter ikke tilbagevendende begivenheder. Deaktiver sædefunktionen for at gøre den tilbagevendende.",
"recurring_event_seats_error": "Tilbagevendende begivenheder understøtter ikke sædefunktionen. Deaktiver sædefunktionen eller gør begivenheden ikke-tilbagevendende.",
"segment": "Segment",
"rename": "Omdøb",
"rename_segment": "Omdøb segment",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Flest annullerede bookinger",
"name_or_email": "Navn eller e-mail",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Hvis ingen kontakt findes, fald tilbage til lead-ejeren, hvis denne eksisterer",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Tilføj dine nye strenge ovenfor her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Dato og tid",
"email_reminder_upcoming_event_notice" : "Dette er en påmindelse om din kommende begivenhed.",
"email_reminder_triggered_by_workflow" : "Denne påmindelse blev udløst af en arbejdsgang i Cal.",
"enable_delegation_credential": "Aktivér delegationslegitimation",
"enable_delegation_credential_description": "Giv Cal.com automatisk adgang til kalendere for alle organisationsmedlemmer ved at aktivere delegationslegitimation.",
"disable_delegation_credential": "Deaktiver delegationslegitimation",
"disable_delegation_credential_description": "Når delegationslegitimation er deaktiveret, skal organisationsmedlemmer, der ikke har forbundet deres kalendere, gøre det manuelt.",
"last_active": "Sidst aktiv",
"member_since": "Medlem siden",
"last_updated": "Sidst opdateret",
"salesforce_on_cancel_write_to_event": "Ved aflyst booking, skriv til begivenhedsoptegnelsen i stedet for at slette begivenheden",
"salesforce_on_every_cancellation": "Ved hver aflysning",
"report_issue": "Rapportér problem",
"report_issue_description": "Du kan indsende en ticket på GitHub eller opgradere din plan for at modtage realtidsstøtte med udviklerkonferencer",
"open_issue": "Åbn problem",
"this_is_your_current_plan": "Dette er din nuværende plan",
"schedule_a_time": "Planlæg et tidspunkt",
"this_includes": "Dette inkluderer:",
"oauth_client_updated_successfully": "OAuth-klient opdateret med succes",
"oauth_client_not_found": "OAuth-klient ikke fundet.",
"subscribe_to_platform": "Abonner på platformen",
"error_accessing_webhooks": "Fejl ved forsøg på at få adgang til webhooks.",
"webhook_update_failed": "Kunne ikke opdatere webhook.",
"webhook_create_failed": "Kunne ikke oprette webhook.",
"invalid_link": "Ugyldigt link",
"currently_subscribed_to_plan": "Du abonnerer i øjeblikket på {{planFirstLetter}}{{planRest}}-planen",
"user_team": "Bruger/Team",
"client_id_copied": "Klient-ID kopieret!",
"client_secret_copied": "Klienthemmelighed kopieret!",
"maintenance_message": "Cal.com-teamet udfører planlagt vedligeholdelse. Hvis du har spørgsmål, bedes du kontakte support.",
"your_payment_failed": "Din betaling mislykkedes",
"check_your_inbox": "Tjek din indbakke",
"account_created_premium_not_reserved": "Din konto er blevet oprettet, men din premium er ikke blevet reserveret.",
"email_sent_with_activation_link": "Vi har sendt en e-mail til {{email}} med et link til at aktivere din konto.",
"activate_account_to_purchase_username": "Når du aktiverer din konto, vil du kunne prøve at købe dit premium-brugernavn igen eller vælge et andet.",
"open_in_gmail": "Åbn i Gmail",
"dont_see_email": "Kan du ikke se en e-mail?",
"resend_in_seconds": "Send igen om {{seconds}} sekunder",
"resend": "Send igen",
"verification_email_sent": "Bekræftelses-e-mail sendt",
"select_all_members": "Vælg alle medlemmer",
"select_all_members_tooltip": "Hvis du vælger alle medlemmer, tilføjes alle fremtidige teammedlemmer, når de bliver en del af teamet.",
"form_settings": "Formularindstillinger",
"remove_whitelist_status": "Fjern whitelist-status",
"whitelist_user_workflows": "Whitelist brugerarbejdsgange",
"user_workflows_whitelisted": "Brugerarbejdsgange whitelisted",
"user_workflows_unwhitelisted": "Brugerarbejdsgange fjernet fra whitelist",
"date_and_time": "Dato og tid",
"email_reminder_upcoming_event_notice": "Dette er en påmindelse om din kommende begivenhed.",
"email_reminder_triggered_by_workflow": "Denne påmindelse blev udløst af en arbejdsgang i Cal.",
"event_upper_case": "Begivenhed",
"scheduling_by": "Planlægning af",
"experience_review_prompt": "Hvordan var din seneste oplevelse?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Hvor tilfreds var du med dit seneste møde?",
"meeting_not_joined_question": "deltog ikke i mødet?",
"reschedule_cta_short": "Planlæg igen her.",
"hide_organizer_email": "Skjul arrangørens e-mail",
"platform_customer_cant_create_organization": "Du er allerede en del af en platformorganisation, og derfor kan du ikke oprette en ny organisation. Hver bruger kan kun tilhøre én organisation. Opret venligst en ny cal.com-konto med en anden e-mail og brug den konto til at abonnere på organisationsplanen.",
"organization_customer_cant_create_platform": "Du er allerede en del af en organisation, og derfor kan du ikke oprette en platformorganisation. Hver bruger kan kun tilhøre én organisation. Opret venligst en ny cal.com-konto med en anden e-mail og brug den konto til at abonnere på platformplanen.",
"hide_organizer_email_description": "Skjul arrangørens e-mailadresse fra bookingskærmen, e-mailnotifikationer og kalenderbegivenheder",
"you_and_conjunction": "Du &",
"email_survey_triggered_by_workflow": "Denne undersøgelse blev udløst af en Arbejdsgang i Cal."
"select_verified_email": "Vælg en verificeret e-mail",
"custom_reply_to_email_title": "Brugerdefineret 'Svar-til'-e-mail",
"custom_reply_to_email_description": "Brug en anden e-mailadresse som svar-til for bekræftelses-e-mails i stedet for arrangørens e-mail",
"email_survey_triggered_by_workflow": "Denne undersøgelse blev udløst af en Arbejdsgang i Cal.",
"skip_trial": "Spring prøveperioden over",
"team_trials_skipped_successfully": "Teamets prøveperioder blev springet over med succes",
"sms_workflow_consent": "Ved at indtaste dit telefonnummer giver du samtykke til at modtage SMS-beskeder for denne begivenhed. SMS-takster kan gælde.",
"routing_preview_more_info_found_insights": "Flere oplysninger kan findes i <0>Routing Insights</0>",
"results": "Resultater",
"view_form": "Vis formular",
"sms_opt_out_message": "Send STOP for at framelde SMS-beskeder",
"routing_form_next_in_queue": "{{count}} næste i køen",
"routing_form_select_members_to_email": "Send e-mail-svar til",
"routing_incomplete_booking_tab": "Ufuldstændige bookinger",
"include_no_show_in_rr_calculation": "Inkluder udeblivelser i round robin-beregninger",
"matching": "Matchning",
"event_redirect": "Begivenheds-omdirigering",
"reset_form": "Nulstil formular",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Tilføj dine nye strenge ovenfor her ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+116 -9
View File
@@ -620,6 +620,7 @@
"your_full_name": "Ihr vollständiger Name",
"no_name": "Kein Name",
"enter_number_between_range": "Bitte geben Sie eine Zahl zwischen 1 und {{maxOccurences}} ein",
"continue_as_guest_description": "Schnell und einfach - kein Konto erforderlich. Perfekt für einmalige Meetings.",
"email_address": "E-Mail Adresse",
"enter_valid_email": "Bitte geben Sie eine gültige Emaildresse ein",
"please_schedule_future_call": " Bitte planen Sie einen Anruf in der Zukunft ein, falls wir nicht innerhalb von {{seconds}} Sekunden verfügbar sind",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Vor Ort (Adresse von Ihnen)",
"somewhere_else": "Anderer Ort",
"custom_attendee_location": "Benutzerdefinierter Teilnehmerort",
"continue_as_guest": "Als Gast fortfahren",
"any_location": "Beliebiger Ort",
"yes": "Ja",
"no": "Nein",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Team erfolgreich aktualisiert",
"your_team_updated_successfully": "Ihr Team wurde erfolgreich aktualisiert.",
"your_org_updated_successfully": "Ihre Org wurde erfolgreich aktualisiert.",
"error_copying_to_clipboard": "Fehler beim Kopieren in die Zwischenablage",
"about": "Beschreibung",
"team_description": "Ein paar Sätze über Ihr Team auf der öffentlichen Teamseite.",
"organization_id": "Organisations-ID",
"organization_id_copied": "Organisations-ID kopiert.",
"org_description": "Ein paar Sätze zu Ihrer Organisation. Dies wird auf der URL-Seite Ihrer Organisation erscheinen.",
"team_id": "Team-ID",
"team_id_copied": "Team-ID kopiert.",
"members": "Mitglieder",
"organization_members": "Mitglieder der Organization",
"member": "Mitglied",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Sind Sie sicher, dass Sie dieses Mitglied aus dem Team entfernen möchten?",
"confirm_disband_team": "Ja, Team auflösen",
"confirm_remove_member": "Ja, Mitglied entfernen",
"confirm_subscription_cancellation": "Ja, Abonnement kündigen",
"cancel_subscription": "Abonnement kündigen",
"cancel_subscription_description": "Durch die Kündigung Ihres Abonnements wird Ihr aktueller Plan dauerhaft deaktiviert. Diese Aktion kann nicht rückgängig gemacht werden.",
"remove_member": "Mitglied entfernen",
"manage_your_team": "Team verwalten",
"no_teams": "Sie haben noch keine Teams.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "URL Ihrer Buchungsseite",
"booking_cancel_redirect_uri": "URL der Seite, auf der Ihre Nutzer ihre Buchung stornieren können",
"booking_reschedule_redirect_uri": "URL der Seite, auf der Ihre Nutzer ihre Buchung umplanen können",
"booking_conflict_error": "Dieser Zeitraum ist nicht mehr verfügbar. Bitte kehren Sie zur vorherigen Seite zurück und wählen Sie eine andere Zeit.",
"open_invitations": "Offene Einladungen",
"new_team": "Neues Team",
"create_first_team_and_invite_others": "Erstellen Sie Ihr erstes Team und laden Sie andere Benutzer ein, zusammenzuarbeiten.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Ihr Konto wurde mit einem Identitäts-Anbieter erstellt.",
"account_managed_by_identity_provider": "Ihr Konto wird verwaltet von {{provider}}",
"account_managed_by_identity_provider_description": "Um Ihre E-Mail-Adresse, Ihr Passwort, die Zwei-Faktor-Authentifizierung und sonstiges zu ändern, besuchen Sie bitte Ihre {{provider}} -Kontoeinstellungen.",
"account_managed_by_identity_provider_error": "Ihr Konto wird von einem anderen Identitätsanbieter verwaltet. Versuchen Sie, sich mit {{provider}} anzumelden.",
"user_creation_error": "Fehler beim Erstellen eines neuen Benutzers. Bitte versuchen Sie es erneut.",
"signin_with_google": "Mit Google anmelden",
"signin_with_saml": "Anmelden mit SAML",
"signin_with_saml_oidc": "Anmelden mit SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Du bist fertig!",
"install_zapier_app": "Bitte installieren Sie zuerst die Zapier-App im App Store.",
"install_make_app": "Bitte installieren Sie zuerst die Make-App im App Store.",
"app_installation": "App-Installation",
"app_not_installed": "App nicht installiert",
"visit_our_app_store": "Entschuldigung, diese App ist nicht auf Ihrem Konto installiert. Bitte besuchen Sie unseren App-Store, um diese und andere großartige Apps zu entdecken und zu erkunden.",
"connect_apple_server": "Mit Apple-Server verbinden",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "wenn der Termin abgesagt wird",
"after_hosts_cal_video_no_show": "Nachdem die Gastgeber nicht am Cal-Video teilgenommen haben",
"after_guests_cal_video_no_show": "Nachdem die Gäste nicht am Cal-Video teilgenommen haben",
"join_video_call": "Am Videoanruf teilnehmen",
"sign_in_to_cal_com": "Bei Ihrem Cal.com-Konto anmelden",
"log_in_to_cal_com": "Bei Cal.com anmelden",
"track_your_meetings": "Verfolgen Sie Ihre Meetings, erhalten Sie Benachrichtigungen und verwalten Sie Ihren Zeitplan effektiver.",
"choose_how_you_d_like_to_join_call": "Wählen Sie, wie Sie an diesem Anruf teilnehmen möchten",
"new_event_trigger": "wenn ein neuer Termin gebucht wird",
"email_host_action": "E-Mail an den Veranstalter senden",
"email_attendee_action": "E-Mail an Teilnehmende senden",
@@ -1361,6 +1380,8 @@
"custom": "Benutzerdefiniert",
"reminder": "Erinnerung",
"rescheduled": "Neu geplant",
"rescheduled_by": "Neu geplant von",
"original_booking": "Ursprüngliche Buchung",
"completed": "Erledigt",
"rating": "Bewertung",
"reminder_email": "Erinnerung: {{eventType}} mit {{name}} bei {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "{{workflowName}} Workflow erfolgreich {{offOn}}geschaltet",
"download_responses": "Antworten herunterladen",
"download_responses_description": "Laden Sie alle Antworten zu Ihrem Formular im CSV-Format herunter.",
"view_responses": "Antworten anzeigen",
"download": "Herunterladen",
"downloading": "Wird heruntergeladen",
"download_recording": "Aufnahme herunterladen",
"transcription_enabled": "Transkriptionen sind jetzt aktiviert",
"transcription_stopped": "Transkriptionen werden jetzt gestoppt",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Neues Formular zu Ihrem Team hinzufügen",
"create_your_first_route": "Erstellen Sie Ihre erste Weiterleitung",
"route_to_the_right_person": "Anhand der Formularantworten an die richtige Person weiterleiten",
"form": "Formular",
"form_description": "Erstellen Sie Ihr Formular, um einen Bucher zu anzuleiten",
"copy_link_to_form": "Link in Formular kopieren",
"theme": "Design der Buchungsseite",
@@ -1862,6 +1886,8 @@
"wrong_code": "Bestätigungscode falsch",
"not_verified": "Noch nicht bestätigt",
"no_availability_in_month": "Keine Verfügbarkeit im {{month}}",
"no_availability_rolling": "Terminplanung ist nur bis zu {{days}} im Voraus verfügbar. Bitte schauen Sie bald wieder vorbei.",
"no_availability_range": "Die Terminplanung endete am {{date}}. Bitte schauen Sie bald wieder vorbei.",
"view_previous_month": "Vormonat anzeigen",
"view_next_month": "Nächsten Monat anzeigen",
"send_code": "Code senden",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Zahlung für dieses Ereignis ist nicht mehr möglich",
"booking_with_payment_cancelled_already_paid": "Eine Rückerstattung für diese Buchungszahlung ist auf dem Weg.",
"booking_with_payment_cancelled_refunded": "Diese Buchungszahlung wurde zurückerstattet.",
"booking_with_payment_cancelled_no_refund": "Gemäß der Rückerstattungsrichtlinie des Events ist die Buchungszahlung nicht erstattungsfähig.",
"booking_with_payment_cancelled_refund_window_expired": "Das Rückerstattungsfenster für das Event ist abgelaufen. Daher ist die Buchungszahlung nicht erstattungsfähig.",
"booking_confirmation_failed": "Buchungsbestätigung fehlgeschlagen",
"not_enough_seats": "Nicht genügend Plätze",
"form_builder_field_already_exists": "Ein Feld mit diesem Namen ist bereits vorhanden",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Benutzerverfügbarkeit öffnen",
"organization_no_slots_notification_switch_title": "Erhalten Sie Benachrichtigungen, wenn Ihr Team keine Verfügbarkeiten hat",
"organization_no_slots_notification_switch_description": "Admins erhalten E-Mail-Benachrichtigungen, wenn ein Benutzer versucht, ein Teammitglied zu buchen, und „Keine Verfügbarkeit“ sieht. Wir lösen diese E-Mail nach zwei Vorfällen aus und erinnern Sie alle 7 Tage pro Benutzer. ",
"organization_disable_phone_only_sms_notifications_switch_title": "SMS-Benachrichtigungen für reine Telefon-Eventtypen deaktivieren",
"organization_disable_phone_only_sms_notifications_switch_description": "Automatische SMS-Benachrichtigungen für Eventtypen deaktivieren, die nur Telefonnummer (attendeePhoneNumber) als Pflichtfrage haben, wobei E-Mail optional oder nicht erforderlich ist",
"email_team_invite|subject|added_to_org": "{{user}} hat Sie zur Organisation {{team}} auf {{appName}} hinzugefügt",
"email_team_invite|subject|invited_to_org": "{{user}} hat Sie eingeladen, der Organisation {{team}} auf {{appName}} beizutreten",
"email_team_invite|subject|added_to_subteam": "{{user}} hat Sie zum Team {{team}} der Organisation {{parentTeamName}} auf {{appName}} hinzugefügt",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Dein Link wurde von {{a0}} zu {{a1}} geändert, aber keine Sorge, alle vorherigen Links funktionieren weiterhin und leiten entsprechend weiter. <br /><br />Bitte beachte: Alle deine persönlichen Ereignistypen wurden in die <strong>{{teamName}}</strong> Organisation verschoben, was auch potenzielle persönliche Links einschließen kann.<br /><br />Bitte melde dich an und stelle sicher, dass du keine privaten Ereignisse in deinem neuen Organisationskonto hast.<br /><br />Für persönliche Ereignisse empfehlen wir, ein neues Konto mit einer persönlichen E-Mail-Adresse zu erstellen.<br /><br />Genieße deinen neuen übersichtlichen Link: {{a2}}",
"email_organization_created|subject": "Ihre Organisation wurde erstellt",
"your_current_plan": "Ihr aktueller Tarif",
"organization_price_per_user_month": "37 $ pro Nutzer im Monat (mindestens 30 Sitzplätze)",
"organization_price_per_user_month": "37 $ pro Benutzer pro Monat",
"privacy_organization_description": "Privatsphäre-Einstellungen für Ihre Organisation verwalten",
"privacy": "Datenschutz",
"team_will_be_under_org": "Neue Teams werden unter Ihrer Organisation sein",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Indem Sie fortfahren, stimmen Sie unseren",
"terms": "Nutzungsbedingungen",
"always_show_x_days": "Immer für {{x}} Tage verfügbar",
"team_subscription_cancelled_successfully": "Team-Abonnement erfolgreich gekündigt",
"team_subscription_cancellation_error": "Fehler bei der Kündigung des Team-Abonnements",
"unable_to_subscribe_to_the_platform": "Beim Abonnieren des Platform-Plans ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut",
"updating_oauth_client_error": "Beim Aktualisieren des OAuth-Clients ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut",
"creating_oauth_client_error": "Beim Erstellen des OAuth-Clients ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Überspringen Sie die Erstellung eines {{entry}}-Datensatzes, wenn dieser nicht in Salesforce existiert",
"salesforce_if_account_does_not_exist": "Wenn der Kontakt nicht unter einem Account existiert, erstellen Sie einen neuen Lead aus dem Teilnehmer",
"salesforce_create_new_contact_under_account": "Erstellen Sie einen neuen Kontakt unter einem Account basierend auf der E-Mail-Domain des Teilnehmers und bestehenden Kontakten",
"salesforce_change_record_owner_on_booking": "Datensatzinhaber bei Buchung ändern",
"mass_assign_attributes": "Attribute massenweise zuweisen",
"reroute_preview_custom_message": "Es führt zur Anzeige einer benutzerdefinierten Nachricht. Versuchen Sie, die Antwort zu ändern, um zu einem Ereignis weiterzuleiten",
"reroute_preview_external_redirect": "Es führt zur Weiterleitung auf {{externalUrl}}. Versuchen Sie, die Antwort zu ändern, um zu einem Ereignis weiterzuleiten",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Weitergeleitet pro Zeitraum",
"per_day": "Pro Tag",
"per_week": "Pro Woche",
"per_month": "Pro Monat",
"per_month": "pro Monat",
"routing_form_insights_assignment_reason": "Zuweisungsgrund",
"access_denied": "Zugriff verweigert",
"salesforce_route_to_owner": "Der Kontaktinhaber wird der Round Robin Host sein, falls verfügbar",
"salesforce_add_attendees_as": "Neue Teilnehmer hinzufügen als",
"salesforce_do_not_route_to_owner": "Der Kontaktinhaber wird nicht erzwungen (kann trotzdem Host sein, wenn die Attribute und Round Robin Kriterien übereinstimmen)",
"salesforce_route_to_custom_lookup_field": "Weiterleitung an einen Benutzer, der mit einem Lookup-Feld eines Accounts übereinstimmt",
"salesforce_option": "Salesforce-Option",
@@ -2927,6 +2961,7 @@
"shortfall": "Fehlmenge",
"routing_form": "Routing-Formular",
"go_back_and_save": "Zurück und speichern",
"save_changes": "Änderungen speichern",
"leave_without_saving": "Ohne speichern verlassen",
"leave_without_saving_description": "Sind Sie sicher, dass Sie die Änderungen an Ihrem Routing-Formular nicht speichern möchten?",
"something_unexpected_occurred": "Ein unerwarteter Fehler ist aufgetreten",
@@ -2961,6 +2996,9 @@
"authorize": "Autorisieren",
"next": "Weiter",
"hide": "Ausblenden",
"show": "Anzeigen",
"utm_params": "UTM-Parameter",
"no_utm_params": "Keine UTM-Parameter verfügbar.",
"asc": "Aufsteigend",
"desc": "Absteigend",
"verify_email_change": "E-Mail-Änderung bestätigen",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Sie müssen mindestens veröffentlichte Teams haben",
"you_are_part_of_this_organization_already": "Sie sind bereits Teil dieser Organisation",
"you_are_part_of_another_organization_cannot_create_organization": "Sie sind Teil einer anderen Organisation und können keine neue Organisation erstellen",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Sie sind Teil einer anderen Plattformorganisation und können keine neue Organisation erstellen",
"organization_payment_success": "Organisationszahlung erfolgreich",
"organization_payment_success_description": "Ihre Organisation wurde erfolgreich erstellt",
"this_may_take_a_few_seconds": "Dies kann einige Sekunden dauern...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Organisations-Onboarding bereits abgeschlossen",
"organization_onboarding_already_exists": "Organisations-Onboarding existiert bereits",
"organization_onboarding_not_found": "Organisations-Onboarding nicht gefunden",
"payment_successful": "Zahlung erfolgreich",
"payment_successful": "Zahlung erfolgreich!",
"handover_onboarding_page_title": "Übergabe-Onboarding",
"handover_onboarding_page_description": "Übergabe des Onboardings an den Benutzer",
"organization_already_exists_with_this_slug": "Eine organisation mit diesem slug existiert bereits",
@@ -3019,9 +3058,12 @@
"link": "Link",
"rows_per_page": "Zeilen pro Seite",
"pagination_status": "{{currentRange}} von {{totalItems}}",
"tip_username_plus": "Tipp: Sie können ein '+' zwischen Benutzernamen setzen: cal.com/anna+brian, um ein dynamisches Gruppenmeeting zu erstellen",
"tip_username_plus": "Tipp: Sie können ein '+' zwischen Benutzernamen einfügen: cal.com/anna+brian, um ein dynamisches Gruppenmeeting zu erstellen",
"user_has_no_team_yet": "Sie haben noch kein Team",
"no_team_members": "Sie haben noch keine Teammitglieder",
"recurring_event_doesnt_support_seats": "Wiederkehrende Events unterstützen die Sitzplatzfunktion nicht. Machen Sie es zu einem einmaligen Event, um Sitzplätze zu aktivieren.",
"seats_doesnt_support_recurring": "Die Sitzplatzfunktion unterstützt keine wiederkehrenden Events. Deaktivieren Sie die Sitzplatzfunktion, um es wiederkehrend zu machen.",
"recurring_event_seats_error": "Wiederkehrende Events unterstützen die Sitzplatzfunktion nicht. Deaktivieren Sie die Sitzplatzfunktion oder machen Sie das Event nicht wiederkehrend.",
"segment": "Segment",
"rename": "Umbenennen",
"rename_segment": "Segment umbenennen",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Am häufigsten abgesagte Termine",
"name_or_email": "Name oder E-Mail",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Wenn kein Kontakt gefunden wird, auf den Lead-Eigentümer zurückgreifen, falls vorhanden",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Fügen Sie Ihre neuen Code-Zeilen über dieser hinzu ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Datum und Uhrzeit",
"email_reminder_upcoming_event_notice" : "Dies ist eine Erinnerung an Ihre bevorstehende Veranstaltung.",
"email_reminder_triggered_by_workflow" : "Diese Erinnerung wurde durch einen Workflow in Cal ausgelöst.",
"enable_delegation_credential": "Delegierungsnachweis aktivieren",
"enable_delegation_credential_description": "Gewähren Sie Cal.com automatischen Zugriff auf die Kalender aller Organisationsmitglieder, indem Sie den Delegierungsnachweis aktivieren.",
"disable_delegation_credential": "Delegierungsnachweis deaktivieren",
"disable_delegation_credential_description": "Sobald der Delegierungsnachweis deaktiviert ist, müssen Organisationsmitglieder, die ihre Kalender noch nicht verbunden haben, dies manuell tun.",
"last_active": "Zuletzt aktiv",
"member_since": "Mitglied seit",
"last_updated": "Zuletzt aktualisiert",
"salesforce_on_cancel_write_to_event": "Bei stornierter Buchung in den Ereignisdatensatz schreiben, anstatt das Ereignis zu löschen",
"salesforce_on_every_cancellation": "Bei jeder Stornierung",
"report_issue": "Problem melden",
"report_issue_description": "Sie können ein Ticket auf GitHub einreichen oder Ihren Plan upgraden, um Echtzeit-Support mit Entwicklerkonferenzen zu erhalten",
"open_issue": "Problem öffnen",
"this_is_your_current_plan": "Dies ist Ihr aktueller Plan",
"schedule_a_time": "Einen Termin vereinbaren",
"this_includes": "Dies beinhaltet:",
"oauth_client_updated_successfully": "OAuth-Client erfolgreich aktualisiert",
"oauth_client_not_found": "OAuth-Client nicht gefunden.",
"subscribe_to_platform": "Plattform abonnieren",
"error_accessing_webhooks": "Fehler beim Zugriff auf Webhooks.",
"webhook_update_failed": "Aktualisierung des Webhooks fehlgeschlagen.",
"webhook_create_failed": "Erstellung des Webhooks fehlgeschlagen.",
"invalid_link": "Ungültiger Link",
"currently_subscribed_to_plan": "Sie haben derzeit den {{planFirstLetter}}{{planRest}}-Plan abonniert",
"user_team": "Benutzer/Team",
"client_id_copied": "Client-ID kopiert!",
"client_secret_copied": "Client-Secret kopiert!",
"maintenance_message": "Das Cal.com-Team führt geplante Wartungsarbeiten durch. Bei Fragen wenden Sie sich bitte an den Support.",
"your_payment_failed": "Ihre Zahlung ist fehlgeschlagen",
"check_your_inbox": "Überprüfen Sie Ihren Posteingang",
"account_created_premium_not_reserved": "Dein Konto wurde erstellt, aber dein Premium-Name wurde nicht reserviert.",
"email_sent_with_activation_link": "Wir haben eine E-Mail an {{email}} mit einem Link zur Aktivierung deines Kontos gesendet.",
"activate_account_to_purchase_username": "Sobald du dein Konto aktiviert hast, kannst du erneut versuchen, deinen Premium-Benutzernamen zu kaufen oder einen anderen auswählen.",
"open_in_gmail": "In Gmail öffnen",
"dont_see_email": "Keine E-Mail erhalten?",
"resend_in_seconds": "Erneut senden in {{seconds}} Sekunden",
"resend": "Erneut senden",
"verification_email_sent": "Bestätigungs-E-Mail gesendet",
"select_all_members": "Alle Mitglieder auswählen",
"select_all_members_tooltip": "Wenn du alle Mitglieder auswählst, werden alle zukünftigen Teammitglieder hinzugefügt, sobald sie dem Team beitreten.",
"form_settings": "Formulareinstellungen",
"remove_whitelist_status": "Whitelist-Status entfernen",
"whitelist_user_workflows": "Benutzer-Workflows zur Whitelist hinzufügen",
"user_workflows_whitelisted": "Benutzer-Workflows zur Whitelist hinzugefügt",
"user_workflows_unwhitelisted": "Benutzer-Workflows von der Whitelist entfernt",
"date_and_time": "Datum und Uhrzeit",
"email_reminder_upcoming_event_notice": "Dies ist eine Erinnerung an Ihre bevorstehende Veranstaltung.",
"email_reminder_triggered_by_workflow": "Diese Erinnerung wurde durch einen Workflow in Cal ausgelöst.",
"event_upper_case": "Ereignis",
"scheduling_by": "Terminplanung durch",
"experience_review_prompt": "Wie war Ihre letzte Erfahrung?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Wie zufrieden waren Sie mit Ihrer letzten Besprechung?",
"meeting_not_joined_question": "nicht am Meeting teilgenommen?",
"reschedule_cta_short": "Hier neu planen.",
"hide_organizer_email": "E-Mail-Adresse des Organisators verbergen",
"platform_customer_cant_create_organization": "Du bist bereits Teil einer Plattform-Organisation, weshalb du keine neue Organisation erstellen kannst. Jeder Benutzer kann nur einer Organisation angehören. Bitte erstelle ein neues Cal.com-Konto mit einer anderen E-Mail-Adresse und verwende dieses Konto, um das Organisations-Abonnement abzuschließen.",
"organization_customer_cant_create_platform": "Du bist bereits Teil einer Organisation, weshalb du keine Plattform-Organisation erstellen kannst. Jeder Benutzer kann nur einer Organisation angehören. Bitte erstelle ein neues Cal.com-Konto mit einer anderen E-Mail-Adresse und verwende dieses Konto, um das Plattform-Abonnement abzuschließen.",
"hide_organizer_email_description": "E-Mail-Adresse des Organisators im Buchungsbildschirm, in E-Mail-Benachrichtigungen und Kalenderereignissen verbergen",
"you_and_conjunction": "Sie &",
"email_survey_triggered_by_workflow": "Diese Umfrage wurde durch einen Workflow in Cal ausgelöst."
"select_verified_email": "Verifizierte E-Mail-Adresse auswählen",
"custom_reply_to_email_title": "Benutzerdefinierte 'Antwort an'-E-Mail",
"custom_reply_to_email_description": "Verwende eine andere E-Mail-Adresse als 'Antwort an' für Bestätigungs-E-Mails anstelle der E-Mail-Adresse des Organisators",
"email_survey_triggered_by_workflow": "Diese Umfrage wurde durch einen Workflow in Cal ausgelöst.",
"skip_trial": "Testphase überspringen",
"team_trials_skipped_successfully": "Team-Testphasen erfolgreich übersprungen",
"sms_workflow_consent": "Durch die Eingabe deiner Telefonnummer stimmst du zu, SMS-Nachrichten für dieses Event zu erhalten. Es können SMS-Gebühren anfallen.",
"routing_preview_more_info_found_insights": "Weitere Informationen finden Sie in den <0>Routing-Einblicken</0>",
"results": "Ergebnisse",
"view_form": "Formular anzeigen",
"sms_opt_out_message": "Senden Sie STOP, um sich von SMS-Nachrichten abzumelden",
"routing_form_next_in_queue": "{{count}} nächste in der Warteschlange",
"routing_form_select_members_to_email": "E-Mail-Antworten senden an",
"routing_incomplete_booking_tab": "Unvollständige Buchungen",
"include_no_show_in_rr_calculation": "Nicht erschienene Buchungen in Round-Robin-Berechnungen einbeziehen",
"matching": "Übereinstimmung",
"event_redirect": "Event-Weiterleitung",
"reset_form": "Formular zurücksetzen",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Fügen Sie Ihre neuen Code-Zeilen über dieser hinzu ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+116 -9
View File
@@ -620,6 +620,7 @@
"your_full_name": "Το πλήρες όνομά σας",
"no_name": "Χωρίς όνομα",
"enter_number_between_range": "Παρακαλώ εισάγετε έναν αριθμό μεταξύ 1 και {{maxOccurences}}",
"continue_as_guest_description": "Γρήγορα και εύκολα - δεν απαιτείται λογαριασμός. Ιδανικό για συναντήσεις μίας φοράς.",
"email_address": "Διεύθυνση ηλεκτρονικού ταχυδρομείου",
"enter_valid_email": "Παρακαλώ εισάγετε ένα έγκυρο email",
"please_schedule_future_call": "Παρακαλώ προγραμματίστε μια μελλοντική κλήση εάν δεν είμαστε διαθέσιμοι σε {{seconds}} δευτερόλεπτα",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Διά ζώσης (Διεύθυνση συμμετέχοντα)",
"somewhere_else": "Κάπου αλλού",
"custom_attendee_location": "Προσαρμοσμένη τοποθεσία συμμετέχοντα",
"continue_as_guest": "Συνέχεια ως επισκέπτης",
"any_location": "Οποιαδήποτε τοποθεσία",
"yes": "Ναί",
"no": "Όχι",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Επιτυχής ενημέρωση ομάδας",
"your_team_updated_successfully": "Η ομάδα σας ενημερώθηκε με επιτυχία.",
"your_org_updated_successfully": "Ο οργανισμός σας ενημερώθηκε με επιτυχία.",
"error_copying_to_clipboard": "Σφάλμα αντιγραφής στο πρόχειρο",
"about": "Σχετικά",
"team_description": "Μερικές προτάσεις σχετικά με την ομάδα σας. Αυτό θα εμφανίζεται στη σελίδα url της ομάδας σας.",
"organization_id": "Αναγνωριστικό οργανισμού",
"organization_id_copied": "Το αναγνωριστικό οργανισμού αντιγράφηκε.",
"org_description": "Μερικές προτάσεις σχετικά με τον οργανισμό σας. Αυτό θα εμφανίζεται στη σελίδα url του οργανισμού σας.",
"team_id": "Αναγνωριστικό ομάδας",
"team_id_copied": "Το αναγνωριστικό ομάδας αντιγράφηκε.",
"members": "Μέλη",
"organization_members": "Μέλη οργανισμού",
"member": "Μέλος",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Είστε βέβαιοι ότι θέλετε να αφαιρέσετε αυτό το μέλος από την ομάδα;",
"confirm_disband_team": "Ναι, διάλυση ομάδας",
"confirm_remove_member": "Ναι, αφαίρεση μέλους",
"confirm_subscription_cancellation": "Ναι, ακύρωση συνδρομής",
"cancel_subscription": "Ακύρωση συνδρομής",
"cancel_subscription_description": "Η ακύρωση της συνδρομής σας θα απενεργοποιήσει μόνιμα το τρέχον πρόγραμμά σας. Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.",
"remove_member": "Αφαίρεση μέλους",
"manage_your_team": "Διαχείριση ομάδας",
"no_teams": "Δεν έχετε καμία ομάδα ακόμη.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "URL της σελίδας κράτησής σας",
"booking_cancel_redirect_uri": "URL της σελίδας όπου οι χρήστες σας μπορούν να ακυρώσουν την κράτησή τους",
"booking_reschedule_redirect_uri": "URL της σελίδας όπου οι χρήστες σας μπορούν να επαναπρογραμματίσουν την κράτησή τους",
"booking_conflict_error": "Αυτή η χρονοθυρίδα δεν είναι πλέον διαθέσιμη. Παρακαλώ επιστρέψτε στην προηγούμενη σελίδα και επιλέξτε άλλη ώρα.",
"open_invitations": "Ανοιχτές προσκλήσεις",
"new_team": "Νέα Ομάδα",
"create_first_team_and_invite_others": "Δημιουργήστε την πρώτη σας ομάδα και προσκαλέστε άλλους χρήστες για συνεργασία.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Ο λογαριασμός σας δημιουργήθηκε χρησιμοποιώντας έναν Πάροχο Ταυτότητας.",
"account_managed_by_identity_provider": "Ο λογαριασμός σας διαχειρίζεται από το {{provider}}",
"account_managed_by_identity_provider_description": "Για να αλλάξετε το email σας, τον κωδικό πρόσβασης, να ενεργοποιήσετε τον έλεγχο ταυτότητας δύο παραγόντων και άλλα, παρακαλούμε επισκεφθείτε τις ρυθμίσεις του λογαριασμού σας στο {{provider}}.",
"account_managed_by_identity_provider_error": "Ο λογαριασμός σας διαχειρίζεται από διαφορετικό πάροχο ταυτότητας. Δοκιμάστε να συνδεθείτε με {{provider}}.",
"user_creation_error": "Σφάλμα κατά τη δημιουργία νέου χρήστη. Παρακαλώ δοκιμάστε ξανά.",
"signin_with_google": "Σύνδεση με Google",
"signin_with_saml": "Σύνδεση με SAML",
"signin_with_saml_oidc": "Σύνδεση με SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Είστε έτοιμοι!",
"install_zapier_app": "Παρακαλούμε εγκαταστήστε πρώτα την εφαρμογή Zapier από το app store.",
"install_make_app": "Παρακαλούμε εγκαταστήστε πρώτα την εφαρμογή Make από το app store.",
"app_installation": "Εγκατάσταση εφαρμογής",
"app_not_installed": "Η εφαρμογή δεν έχει εγκατασταθεί",
"visit_our_app_store": "Συγγνώμη, αυτή η εφαρμογή δεν είναι εγκατεστημένη στον λογαριασμό σας. Παρακαλούμε επισκεφθείτε το app store μας για να εξερευνήσετε και να ανακαλύψετε αυτή και άλλες εξαιρετικές εφαρμογές.",
"connect_apple_server": "Σύνδεση με τον διακομιστή της Apple",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "όταν το συμβάν ακυρωθεί",
"after_hosts_cal_video_no_show": "Αφού οι διοργανωτές δεν συνδέθηκαν στο cal video",
"after_guests_cal_video_no_show": "Αφού οι καλεσμένοι δεν συνδέθηκαν στο cal video",
"join_video_call": "Συμμετοχή στη βιντεοκλήση",
"sign_in_to_cal_com": "Συνδεθείτε στον λογαριασμό σας στο Cal.com",
"log_in_to_cal_com": "Σύνδεση στο Cal.com",
"track_your_meetings": "Παρακολουθήστε τις συναντήσεις σας, λάβετε ειδοποιήσεις και διαχειριστείτε το πρόγραμμά σας πιο αποτελεσματικά.",
"choose_how_you_d_like_to_join_call": "Επιλέξτε πώς θέλετε να συμμετάσχετε σε αυτήν την κλήση",
"new_event_trigger": "όταν γίνει κράτηση νέου συμβάντος",
"email_host_action": "αποστολή email στον διοργανωτή",
"email_attendee_action": "αποστολή email στους συμμετέχοντες",
@@ -1361,6 +1380,8 @@
"custom": "Προσαρμοσμένο",
"reminder": "Υπενθύμιση",
"rescheduled": "Επαναπρογραμματίστηκε",
"rescheduled_by": "Επαναπρογραμματίστηκε από",
"original_booking": "Αρχική κράτηση",
"completed": "Ολοκληρώθηκε",
"rating": "Αξιολόγηση",
"reminder_email": "Υπενθύμιση: {{eventType}} με {{name}} στις {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "Η ροή εργασίας {{workflowName}} {{offOn}} με επιτυχία",
"download_responses": "Λήψη απαντήσεων",
"download_responses_description": "Κατεβάστε όλες τις απαντήσεις της φόρμας σας σε μορφή CSV.",
"view_responses": "Προβολή απαντήσεων",
"download": "Λήψη",
"downloading": "Γίνεται λήψη",
"download_recording": "Λήψη εγγραφής",
"transcription_enabled": "Οι απομαγνητοφωνήσεις ενεργοποιήθηκαν",
"transcription_stopped": "Οι απομαγνητοφωνήσεις σταμάτησαν",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Προσθήκη νέας φόρμας στην ομάδα σας",
"create_your_first_route": "Δημιουργήστε την πρώτη σας διαδρομή",
"route_to_the_right_person": "Δρομολόγηση στο κατάλληλο άτομο με βάση τις απαντήσεις της φόρμας σας",
"form": "Φόρμα",
"form_description": "Δημιουργήστε τη φόρμα σας για τη δρομολόγηση κρατήσεων",
"copy_link_to_form": "Αντιγραφή συνδέσμου φόρμας",
"theme": "Θέμα σελίδας κρατήσεων",
@@ -1862,6 +1886,8 @@
"wrong_code": "Λάθος κωδικός επαλήθευσης",
"not_verified": "Δεν έχει επαληθευτεί ακόμα",
"no_availability_in_month": "Καμία διαθεσιμότητα τον {{month}}",
"no_availability_rolling": "Ο προγραμματισμός είναι διαθέσιμος μόνο έως και {{days}} ημέρες εκ των προτέρων. Παρακαλώ ελέγξτε ξανά σύντομα.",
"no_availability_range": "Ο προγραμματισμός έληξε στις {{date}}. Παρακαλώ ελέγξτε ξανά σύντομα.",
"view_previous_month": "Προβολή προηγούμενου μήνα",
"view_next_month": "Προβολή επόμενου μήνα",
"send_code": "Αποστολή κωδικού",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Η πληρωμή για αυτή την εκδήλωση δεν είναι πλέον δυνατή",
"booking_with_payment_cancelled_already_paid": "Η επιστροφή χρημάτων για αυτή την κράτηση βρίσκεται σε εξέλιξη.",
"booking_with_payment_cancelled_refunded": "Η πληρωμή για αυτή την κράτηση έχει επιστραφεί.",
"booking_with_payment_cancelled_no_refund": "Σύμφωνα με την πολιτική επιστροφής χρημάτων της εκδήλωσης, η πληρωμή της κράτησης δεν επιστρέφεται.",
"booking_with_payment_cancelled_refund_window_expired": "Το χρονικό περιθώριο επιστροφής χρημάτων της εκδήλωσης έχει λήξει. Συνεπώς, η πληρωμή της κράτησης δεν επιστρέφεται.",
"booking_confirmation_failed": "Η επιβεβαίωση της κράτησης απέτυχε",
"not_enough_seats": "Δεν υπάρχουν αρκετές θέσεις",
"form_builder_field_already_exists": "Υπάρχει ήδη ένα πεδίο με αυτό το όνομα",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Άνοιγμα διαθεσιμότητας χρηστών",
"organization_no_slots_notification_switch_title": "Λάβετε ειδοποιήσεις όταν η ομάδα σας δεν έχει διαθεσιμότητα",
"organization_no_slots_notification_switch_description": "Οι διαχειριστές θα λαμβάνουν ειδοποιήσεις μέσω email όταν ένας χρήστης προσπαθεί να κλείσει ραντεβού με μέλος της ομάδας και αντιμετωπίζει 'Καμία διαθεσιμότητα'. Στέλνουμε αυτό το email μετά από δύο περιστατικά και σας υπενθυμίζουμε κάθε 7 ημέρες ανά χρήστη.",
"organization_disable_phone_only_sms_notifications_switch_title": "Απενεργοποίηση ειδοποιήσεων SMS για τύπους εκδηλώσεων μόνο με τηλέφωνο",
"organization_disable_phone_only_sms_notifications_switch_description": "Απενεργοποίηση αυτόματων ειδοποιήσεων SMS για τύπους εκδηλώσεων που απαιτούν μόνο αριθμό τηλεφώνου (attendeePhoneNumber) ως υποχρεωτική ερώτηση με το email ως προαιρετικό ή μη απαιτούμενο",
"email_team_invite|subject|added_to_org": "{{user}} added you to the organization {{team}} on {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} invited you to join the organization {{team}} on {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} added you to the team {{team}} of organization {{parentTeamName}} on {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Ο σύνδεσμός σας έχει αλλάξει από {{a0}} σε {{a1}} αλλά μην ανησυχείτε, όλοι οι προηγούμενοι σύνδεσμοι εξακολουθούν να λειτουργούν και να ανακατευθύνουν κατάλληλα. <br /><br />Παρακαλώ σημειώστε: Όλοι οι προσωπικοί τύποι εκδηλώσεών σας έχουν μεταφερθεί στον οργανισμό <strong>{{teamName}}</strong>, που μπορεί επίσης να περιλαμβάνει πιθανό προσωπικό σύνδεσμο.<br /><br />Παρακαλώ συνδεθείτε και βεβαιωθείτε ότι δεν έχετε ιδιωτικές εκδηλώσεις στον νέο οργανωτικό σας λογαριασμό.<br /><br />Για προσωπικές εκδηλώσεις συνιστούμε τη δημιουργία νέου λογαριασμού με προσωπική διεύθυνση email.<br /><br />Απολαύστε τον νέο καθαρό σύνδεσμό σας: {{a2}}",
"email_organization_created|subject": "Ο οργανισμός σας έχει δημιουργηθεί",
"your_current_plan": "Το τρέχον πλάνο σας",
"organization_price_per_user_month": "$37 ανά χρήστη ανά μήνα (ελάχιστο 30 θέσεις)",
"organization_price_per_user_month": "$37 ανά χρήστη ανά μήνα",
"privacy_organization_description": "Διαχειριστείτε τις ρυθμίσεις απορρήτου για τον οργανισμό σας",
"privacy": "Απόρρητο",
"team_will_be_under_org": "Οι νέες ομάδες θα υπάγονται στον οργανισμό σας",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Προχωρώντας, συμφωνείτε με τους",
"terms": "Όρους",
"always_show_x_days": "Πάντα {{x}} διαθέσιμες ημέρες",
"team_subscription_cancelled_successfully": "Η συνδρομή ομάδας ακυρώθηκε με επιτυχία",
"team_subscription_cancellation_error": "Σφάλμα κατά την ακύρωση της συνδρομής ομάδας",
"unable_to_subscribe_to_the_platform": "Παρουσιάστηκε σφάλμα κατά την εγγραφή στο πρόγραμμα της πλατφόρμας, παρακαλώ δοκιμάστε ξανά αργότερα",
"updating_oauth_client_error": "Παρουσιάστηκε σφάλμα κατά την ενημέρωση του OAuth client, παρακαλώ δοκιμάστε ξανά αργότερα",
"creating_oauth_client_error": "Παρουσιάστηκε σφάλμα κατά τη δημιουργία του OAuth client, παρακαλώ δοκιμάστε ξανά αργότερα",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Παράλειψη δημιουργίας εγγραφής {{entry}} εάν δεν υπάρχει στο Salesforce",
"salesforce_if_account_does_not_exist": "Εάν η επαφή δεν υπάρχει υπό κάποιο λογαριασμό, δημιούργησε νέο lead από τον συμμετέχοντα",
"salesforce_create_new_contact_under_account": "Δημιούργησε νέα επαφή υπό λογαριασμό με βάση το domain email του συμμετέχοντα και τις υπάρχουσες επαφές",
"salesforce_change_record_owner_on_booking": "Αλλαγή ιδιοκτήτη εγγραφής κατά την κράτηση",
"mass_assign_attributes": "Μαζική εκχώρηση χαρακτηριστικών",
"reroute_preview_custom_message": "Αυτό έχει ως αποτέλεσμα την εμφάνιση προσαρμοσμένου μηνύματος. Δοκιμάστε να αλλάξετε την απάντηση για να δρομολογηθείτε σε ένα συμβάν",
"reroute_preview_external_redirect": "Αυτό έχει ως αποτέλεσμα την ανακατεύθυνση στο {{externalUrl}}. Δοκιμάστε να αλλάξετε την απάντηση για να δρομολογηθείτε σε ένα συμβάν",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Δρομολογήθηκαν ανά περίοδο",
"per_day": "Ανά ημέρα",
"per_week": "Ανά εβδομάδα",
"per_month": "Ανά μήνα",
"per_month": "ανά μήνα",
"routing_form_insights_assignment_reason": "Αιτία ανάθεσης",
"access_denied": "Δεν επιτρέπεται η πρόσβαση",
"salesforce_route_to_owner": "Ο κάτοχος της επαφής θα είναι ο round robin διοργανωτής εάν είναι διαθέσιμος",
"salesforce_add_attendees_as": "Προσθήκη νέων συμμετεχόντων ως",
"salesforce_do_not_route_to_owner": "Ο κάτοχος της επαφής δεν θα είναι υποχρεωτικός (μπορεί ακόμα να είναι διοργανωτής εάν ταιριάζει με τα χαρακτηριστικά και τα κριτήρια round robin)",
"salesforce_route_to_custom_lookup_field": "Δρομολόγηση σε χρήστη που ταιριάζει με ένα πεδίο αναζήτησης σε λογαριασμό",
"salesforce_option": "Επιλογή Salesforce",
@@ -2927,6 +2961,7 @@
"shortfall": "Έλλειμμα",
"routing_form": "Φόρμα δρομολόγησης",
"go_back_and_save": "Επιστροφή και αποθήκευση",
"save_changes": "Αποθήκευση αλλαγών",
"leave_without_saving": "Έξοδος χωρίς αποθήκευση",
"leave_without_saving_description": "Είστε βέβαιοι ότι θέλετε να αποχωρήσετε χωρίς να αποθηκεύσετε τις αλλαγές στη φόρμα δρομολόγησης;",
"something_unexpected_occurred": "Συνέβη κάτι απρόσμενο",
@@ -2961,6 +2996,9 @@
"authorize": "Εξουσιοδότηση",
"next": "Επόμενο",
"hide": "Απόκρυψη",
"show": "Εμφάνιση",
"utm_params": "Παράμετροι UTM",
"no_utm_params": "Δεν υπάρχουν διαθέσιμες παράμετροι UTM.",
"asc": "Αύξουσα",
"desc": "Φθίνουσα",
"verify_email_change": "Επαλήθευση αλλαγής email",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Πρέπει να έχετε τον ελάχιστο αριθμό δημοσιευμένων ομάδων",
"you_are_part_of_this_organization_already": "Είστε ήδη μέλος αυτού του οργανισμού",
"you_are_part_of_another_organization_cannot_create_organization": "Είστε μέλος άλλου οργανισμού, δεν μπορείτε να δημιουργήσετε νέο οργανισμό",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Είστε μέλος άλλου οργανισμού πλατφόρμας, δεν μπορείτε να δημιουργήσετε νέο οργανισμό",
"organization_payment_success": "Επιτυχής πληρωμή οργανισμού",
"organization_payment_success_description": "Ο οργανισμός σας δημιουργήθηκε με επιτυχία",
"this_may_take_a_few_seconds": "Αυτό μπορεί να διαρκέσει μερικά δευτερόλεπτα...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Η εισαγωγή οργανισμού έχει ήδη ολοκληρωθεί",
"organization_onboarding_already_exists": "Η εισαγωγή οργανισμού υπάρχει ήδη",
"organization_onboarding_not_found": "Η εισαγωγή οργανισμού δεν βρέθηκε",
"payment_successful": "Επιτυχής πληρωμή",
"payment_successful": "Επιτυχής πληρωμή!",
"handover_onboarding_page_title": "Παράδοση εισαγωγής",
"handover_onboarding_page_description": "Παράδοση εισαγωγής στον χρήστη",
"organization_already_exists_with_this_slug": "Υπάρχει ήδη οργανισμός με αυτό το slug",
@@ -3019,9 +3058,12 @@
"link": "Σύνδεσμος",
"rows_per_page": "γραμμές ανά σελίδα",
"pagination_status": "{{currentRange}} από {{totalItems}}",
"tip_username_plus": "Συμβουλή: Μπορείτε να προσθέσετε ένα '+' μεταξύ των ονομάτων χρήστη: cal.com/anna+brian για να δημιουργήσετε μια δυναμική ομαδική συνάντηση",
"tip_username_plus": "Συμβουλή: Μπορείτε να προσθέσετε ένα '+' μεταξύ των ονομάτων χρηστών: cal.com/anna+brian για να δημιουργήσετε μια δυναμική ομαδική συνάντηση",
"user_has_no_team_yet": "Δεν έχετε ακόμη ομάδα",
"no_team_members": "Δεν έχετε ακόμη μέλη ομάδας",
"recurring_event_doesnt_support_seats": "Η επαναλαμβανόμενη εκδήλωση δεν υποστηρίζει τη λειτουργία θέσεων. Κάντε την μη επαναλαμβανόμενη για να ενεργοποιήσετε τις θέσεις.",
"seats_doesnt_support_recurring": "Η λειτουργία θέσεων δεν υποστηρίζει επαναλαμβανόμενη εκδήλωση. Απενεργοποιήστε τη λειτουργία θέσεων για να την κάνετε επαναλαμβανόμενη.",
"recurring_event_seats_error": "Η επαναλαμβανόμενη εκδήλωση δεν υποστηρίζει τη λειτουργία θέσεων. Απενεργοποιήστε τη λειτουργία θέσεων ή κάντε την εκδήλωση μη επαναλαμβανόμενη.",
"segment": "Τμήμα",
"rename": "Μετονομασία",
"rename_segment": "Μετονομασία τμήματος",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Περισσότερες ακυρωμένες κρατήσεις",
"name_or_email": "Όνομα ή Email",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Αν δεν βρεθεί επαφή, επιστροφή στον ιδιοκτήτη του lead εάν υπάρχει",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Προσθέστε τις νέες συμβολοσειρές σας πάνω από εδώ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Ημερομηνία & Ώρα",
"email_reminder_upcoming_event_notice" : "Αυτή είναι μια υπενθύμιση για την επερχόμενη εκδήλωσή σας.",
"email_reminder_triggered_by_workflow" : "Αυτή η υπενθύμιση ενεργοποιήθηκε από μια ροή εργασίας στο Cal.",
"enable_delegation_credential": "Ενεργοποίηση διαπιστευτηρίου εξουσιοδότησης",
"enable_delegation_credential_description": "Παραχωρήστε στο Cal.com αυτόματη πρόσβαση στα ημερολόγια όλων των μελών του οργανισμού ενεργοποιώντας το διαπιστευτήριο εξουσιοδότησης.",
"disable_delegation_credential": "Απενεργοποίηση διαπιστευτηρίου εξουσιοδότησης",
"disable_delegation_credential_description": "Μόλις απενεργοποιηθεί το διαπιστευτήριο εξουσιοδότησης, τα μέλη του οργανισμού που δεν έχουν συνδέσει τα ημερολόγιά τους θα πρέπει να το κάνουν χειροκίνητα.",
"last_active": "Τελευταία ενεργός",
"member_since": "Μέλος από",
"last_updated": "Τελευταία ενημέρωση",
"salesforce_on_cancel_write_to_event": "Σε ακύρωση κράτησης, εγγραφή στο αρχείο συμβάντος αντί για διαγραφή συμβάντος",
"salesforce_on_every_cancellation": "Σε κάθε ακύρωση",
"report_issue": "Αναφορά προβλήματος",
"report_issue_description": "Μπορείτε να υποβάλετε ένα αίτημα στο GitHub ή να αναβαθμίσετε το πρόγραμμά σας για να λάβετε υποστήριξη σε πραγματικό χρόνο με συνεδρίες προγραμματιστών",
"open_issue": "Άνοιγμα ζητήματος",
"this_is_your_current_plan": "Αυτό είναι το τρέχον πρόγραμμά σας",
"schedule_a_time": "Προγραμματίστε μια ώρα",
"this_includes": "Αυτό περιλαμβάνει:",
"oauth_client_updated_successfully": "Ο πελάτης OAuth ενημερώθηκε με επιτυχία",
"oauth_client_not_found": "Ο πελάτης OAuth δεν βρέθηκε.",
"subscribe_to_platform": "Εγγραφή στην πλατφόρμα",
"error_accessing_webhooks": "Σφάλμα κατά την προσπάθεια πρόσβασης στα webhooks.",
"webhook_update_failed": "Αποτυχία ενημέρωσης του webhook.",
"webhook_create_failed": "Αποτυχία δημιουργίας του webhook.",
"invalid_link": "Μη έγκυρος σύνδεσμος",
"currently_subscribed_to_plan": "Είστε συνδρομητής στο πρόγραμμα {{planFirstLetter}}{{planRest}}",
"user_team": "Χρήστης/Ομάδα",
"client_id_copied": "Το αναγνωριστικό πελάτη αντιγράφηκε!",
"client_secret_copied": "Το μυστικό πελάτη αντιγράφηκε!",
"maintenance_message": "Η ομάδα του Cal.com πραγματοποιεί προγραμματισμένη συντήρηση. Εάν έχετε ερωτήσεις, επικοινωνήστε με την υποστήριξη.",
"your_payment_failed": "Η πληρωμή σας απέτυχε",
"check_your_inbox": "Ελέγξτε τα εισερχόμενά σας",
"account_created_premium_not_reserved": "Ο λογαριασμός σας έχει δημιουργηθεί, αλλά το premium όνομα χρήστη σας δεν έχει δεσμευτεί.",
"email_sent_with_activation_link": "Έχουμε στείλει ένα email στο {{email}} με έναν σύνδεσμο για την ενεργοποίηση του λογαριασμού σας.",
"activate_account_to_purchase_username": "Μόλις ενεργοποιήσετε τον λογαριασμό σας, θα μπορείτε να προσπαθήσετε να αγοράσετε ξανά το premium όνομα χρήστη σας ή να επιλέξετε ένα διαφορετικό.",
"open_in_gmail": "Άνοιγμα στο Gmail",
"dont_see_email": "Δεν βλέπετε κάποιο email;",
"resend_in_seconds": "Επαναποστολή σε {{seconds}} δευτερόλεπτα",
"resend": "Επαναποστολή",
"verification_email_sent": "Το email επαλήθευσης εστάλη",
"select_all_members": "Επιλογή όλων των μελών",
"select_all_members_tooltip": "Η επιλογή όλων των μελών θα προσθέσει όλα τα μελλοντικά μέλη της ομάδας όταν προστεθούν στην ομάδα.",
"form_settings": "Ρυθμίσεις φόρμας",
"remove_whitelist_status": "Αφαίρεση κατάστασης λευκής λίστας",
"whitelist_user_workflows": "Προσθήκη ροών εργασίας χρήστη στη λευκή λίστα",
"user_workflows_whitelisted": "Οι ροές εργασίας χρήστη προστέθηκαν στη λευκή λίστα",
"user_workflows_unwhitelisted": "Οι ροές εργασίας χρήστη αφαιρέθηκαν από τη λευκή λίστα",
"date_and_time": "Ημερομηνία & Ώρα",
"email_reminder_upcoming_event_notice": "Αυτή είναι μια υπενθύμιση για την επερχόμενη εκδήλωσή σας.",
"email_reminder_triggered_by_workflow": "Αυτή η υπενθύμιση ενεργοποιήθηκε από μια ροή εργασίας στο Cal.",
"event_upper_case": "Γεγονός",
"scheduling_by": "Προγραμματισμός από",
"experience_review_prompt": "Πώς ήταν η πρόσφατη εμπειρία σας;",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Πόσο ικανοποιημένοι ήσασταν με την τελευταία σας συνάντηση;",
"meeting_not_joined_question": "δεν συμμετείχατε στη συνάντηση;",
"reschedule_cta_short": "Επαναπρογραμματίστε εδώ.",
"hide_organizer_email": "Απόκρυψη email διοργανωτή",
"platform_customer_cant_create_organization": "Είστε ήδη μέλος ενός οργανισμού πλατφόρμας, γι' αυτό δεν μπορείτε να δημιουργήσετε νέο οργανισμό. Κάθε χρήστης μπορεί να ανήκει μόνο σε έναν οργανισμό. Παρακαλούμε, δημιουργήστε έναν νέο λογαριασμό cal.com με διαφορετικό email και χρησιμοποιήστε αυτόν τον λογαριασμό για να εγγραφείτε στο πρόγραμμα οργανισμών.",
"organization_customer_cant_create_platform": "Είστε ήδη μέλος ενός οργανισμού, γι' αυτό δεν μπορείτε να δημιουργήσετε οργανισμό πλατφόρμας. Κάθε χρήστης μπορεί να ανήκει μόνο σε έναν οργανισμό. Παρακαλούμε, δημιουργήστε έναν νέο λογαριασμό cal.com με διαφορετικό email και χρησιμοποιήστε αυτόν τον λογαριασμό για να εγγραφείτε στο πρόγραμμα πλατφόρμας.",
"hide_organizer_email_description": "Απόκρυψη της διεύθυνσης email του διοργανωτή από την οθόνη κράτησης, τις ειδοποιήσεις email και τα συμβάντα ημερολογίου",
"you_and_conjunction": "Εσείς &",
"email_survey_triggered_by_workflow": "Αυτή η έρευνα ενεργοποιήθηκε από μια ροή εργασίας στο Cal."
"select_verified_email": "Επιλογή επαληθευμένου email",
"custom_reply_to_email_title": "Προσαρμοσμένο email 'Απάντησης-Προς'",
"custom_reply_to_email_description": "Χρησιμοποιήστε διαφορετική διεύθυνση email ως replyTo για τα email επιβεβαίωσης αντί για το email του διοργανωτή",
"email_survey_triggered_by_workflow": "Αυτή η έρευνα ενεργοποιήθηκε από μια ροή εργασίας στο Cal.",
"skip_trial": "Παράλειψη δοκιμαστικής περιόδου",
"team_trials_skipped_successfully": "Οι δοκιμαστικές περίοδοι ομάδας παραλείφθηκαν με επιτυχία",
"sms_workflow_consent": "Εισάγοντας τον αριθμό τηλεφώνου σας, συναινείτε να λαμβάνετε μηνύματα SMS για αυτό το συμβάν. Ενδέχεται να ισχύουν χρεώσεις SMS.",
"routing_preview_more_info_found_insights": "Περισσότερες πληροφορίες μπορείτε να βρείτε στα <0>Στατιστικά Δρομολόγησης</0>",
"results": "Αποτελέσματα",
"view_form": "Προβολή φόρμας",
"sms_opt_out_message": "Στείλτε STOP για να διακόψετε τα μηνύματα SMS",
"routing_form_next_in_queue": "{{count}} επόμενα στην ουρά",
"routing_form_select_members_to_email": "Αποστολή απαντήσεων email σε",
"routing_incomplete_booking_tab": "Ημιτελείς Κρατήσεις",
"include_no_show_in_rr_calculation": "Συμπερίληψη κρατήσεων χωρίς εμφάνιση στους υπολογισμούς round robin",
"matching": "Αντιστοίχιση",
"event_redirect": "Ανακατεύθυνση εκδήλωσης",
"reset_form": "Επαναφορά φόρμας",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Προσθέστε τις νέες συμβολοσειρές σας πάνω από εδώ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+26 -1
View File
@@ -3021,6 +3021,12 @@
"asc": "Asc",
"desc": "Desc",
"verify_email_change": "Verify email change",
"buy_credits": "Buy Credits",
"credits": "Credits",
"view_and_manage_credits": "View and manage credits",
"view_and_manage_credits_description": "View and manage credits for sending SMS messages. One credit is worth 1¢ (USD)",
"buy_additional_credits": "Buy additional credits ($0.01 per credit)",
"overview": "Overview",
"organization_slug_taken": "Organization slug is already taken",
"you_cannot_create_an_organization_as_you_are_already_part_of_an_organization": "You cannot create an organization as you are already a part of an organization",
"you_need_to_complete_user_onboarding_before_creating_an_organization": "You need to complete user onboarding before creating an organization",
@@ -3114,6 +3120,8 @@
"most_cancelled_bookings": "Most Cancelled Bookings",
"name_or_email": "Name or Email",
"salesforce_round_robin_skip_fallback_to_lead_owner": "If no contact is found, fallback to lead owner if it exists",
"credit_purchase_failed": "Credit purchase failed. Please try again or contact support.",
"minimum_of_credits_required": "Minimum of 50 credits required",
"enable_delegation_credential": "Enable Delegation Credential",
"enable_delegation_credential_description": "Grant Cal.com automatic access to the calendars of all organization members by enabling delegation credential.",
"disable_delegation_credential": "Disable Delegation Credential",
@@ -3141,7 +3149,6 @@
"user_team": "User/Team",
"client_id_copied": "Client ID copied!",
"client_secret_copied": "Client secret copied!",
"down_for_maintenance": "Down for maintenance",
"maintenance_message": "The Cal.com team are performing scheduled maintenance. If you have any questions, please contact support.",
"your_payment_failed": "Your payment failed",
"payment_successful": "Payment successful!",
@@ -3187,11 +3194,29 @@
"results": "Results",
"view_form": "View Form",
"sms_opt_out_message": "Text STOP to opt-out of SMS messages",
"team_credits_low_warning": "Your team {{teamName}} is running low on credits",
"user_credits_low_warning": "You are running low on credits",
"action_required_out_of_credits": "[Action Required] Your team {{teamName}} has run out of credits",
"action_required_user_out_of_credits": "[Action Required] You have run out of credits",
"low_credits_warning_message": "Your Cal.com team {{teamName}} is running low on credits. To avoid any disruption in service, please purchase additional credits. If your balance runs out, SMS messages will stop sending and will be sent as emails instead.",
"low_credits_warning_message_user": "Your Cal.com account is running low on credits. To avoid any disruption in service, please purchase additional credits. If your balance runs out, SMS messages will stop sending and will be sent as emails instead.",
"credit_limit_reached_message": "Your Cal.com team {{teamName}} has run out of credits. As a result, SMS messages are now being sent via email instead. To resume sending SMS, please purchase additional credits.",
"credit_limit_reached_message_user": "Your Cal.com account has run out of credits. As a result, SMS messages are now being sent via email instead. To resume sending SMS, please purchase additional credits.",
"current_credit_balance": "Current balance: {{balance}} credits",
"notification_about_your_booking": "Notification about your booking",
"monthly_credits": "Monthly credits",
"total_credits": "Total credits: {{totalCredits}}",
"remaining_credits": "Remaining credits: {{remainingCredits}}",
"additional_credits": "Additional credits",
"routing_form_next_in_queue": "{{count}} next in queue",
"routing_form_select_members_to_email": "Send email responses to",
"routing_incomplete_booking_tab": "Incomplete Bookings",
"include_no_show_in_rr_calculation": "Include no show bookings in round robin calculations",
"matching": "Matching",
"event_redirect": "Event Redirect",
"reset_form": "Reset Form",
"requires_credits": "Requires credits",
"requires_credits_tooltip": "You need enough credits in your account to use this feature",
"available_credits": "Available credits",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
@@ -620,6 +620,7 @@
"your_full_name": "Tu nombre completo",
"no_name": "Sin nombre",
"enter_number_between_range": "Por favor, ingresa un número entre 1 y {{maxOccurences}}",
"continue_as_guest_description": "Rápido y fácil - no se requiere cuenta. Perfecto para reuniones únicas.",
"email_address": "Correo electrónico",
"enter_valid_email": "Por favor, ingresa un correo electrónico válido",
"please_schedule_future_call": "Por favor, programa una llamada futura si no estamos disponibles en {{seconds}} segundos",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "En persona (Dirección del asistente)",
"somewhere_else": "En otro lugar",
"custom_attendee_location": "Ubicación personalizada del asistente",
"continue_as_guest": "Continuar como invitado",
"any_location": "Cualquier ubicación",
"yes": "Sí",
"no": "No",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Equipo actualizado con éxito",
"your_team_updated_successfully": "Tu equipo ha sido actualizado con éxito.",
"your_org_updated_successfully": "Tu organización ha sido actualizada con éxito.",
"error_copying_to_clipboard": "Error al copiar al portapapeles",
"about": "Acerca de",
"team_description": "Unas pocas oraciones sobre tu equipo. Esto aparecerá en la página de la URL de tu equipo.",
"organization_id": "ID de la organización",
"organization_id_copied": "ID de la organización copiado.",
"org_description": "Unas pocas oraciones sobre tu organización. Esto aparecerá en la página de la URL de tu organización.",
"team_id": "ID del equipo",
"team_id_copied": "ID del equipo copiado.",
"members": "Miembros",
"organization_members": "Miembros de la organización",
"member": "Miembro",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "¿Estás seguro de que quieres eliminar a este miembro del equipo?",
"confirm_disband_team": "Sí, disolver equipo",
"confirm_remove_member": "Sí, eliminar miembro",
"confirm_subscription_cancellation": "Sí, cancelar suscripción",
"cancel_subscription": "Cancelar suscripción",
"cancel_subscription_description": "Al cancelar tu suscripción desactivarás permanentemente tu plan actual. Esta acción no se puede deshacer.",
"remove_member": "Eliminar miembro",
"manage_your_team": "Gestiona tu equipo",
"no_teams": "Aún no tienes equipos.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "URL de tu página de reservas",
"booking_cancel_redirect_uri": "URL de la página donde tus usuarios pueden cancelar su reserva",
"booking_reschedule_redirect_uri": "URL de la página donde tus usuarios pueden reprogramar su reserva",
"booking_conflict_error": "Este horario ya no está disponible. Por favor regresa a la página anterior y selecciona otro horario.",
"open_invitations": "Invitaciones Abiertas",
"new_team": "Nuevo Equipo",
"create_first_team_and_invite_others": "Crea tu primer equipo e invita a otros usuarios a trabajar juntos.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Tu cuenta fue creada usando un Proveedor de Identidad.",
"account_managed_by_identity_provider": "Tu cuenta es gestionada por {{provider}}",
"account_managed_by_identity_provider_description": "Para cambiar tu correo electrónico, contraseña, habilitar la autenticación de dos factores y más, por favor visita la configuración de tu cuenta de {{provider}}.",
"account_managed_by_identity_provider_error": "Tu cuenta es administrada por un proveedor de identidad diferente. Intenta iniciar sesión con {{provider}}.",
"user_creation_error": "Error al crear un nuevo usuario. Por favor intenta de nuevo.",
"signin_with_google": "Iniciar sesión con Google",
"signin_with_saml": "Iniciar sesión con SAML",
"signin_with_saml_oidc": "Iniciar sesión con SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "¡Todo listo!",
"install_zapier_app": "Por favor, primero instala la aplicación de Zapier en la tienda de aplicaciones.",
"install_make_app": "Por favor, primero instala la aplicación de Make en la tienda de aplicaciones.",
"app_installation": "Instalación de la aplicación",
"app_not_installed": "Aplicación no instalada",
"visit_our_app_store": "Lo sentimos, esta aplicación no está instalada en tu cuenta. Por favor, visita nuestra tienda de aplicaciones para explorar y descubrir esta y otras excelentes aplicaciones.",
"connect_apple_server": "Conectar al servidor de Apple",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "cuando el evento está cancelado",
"after_hosts_cal_video_no_show": "Después de que los anfitriones no se unieron a la videollamada",
"after_guests_cal_video_no_show": "Después de que los invitados no se unieron a la videollamada",
"join_video_call": "Unirse a la videollamada",
"sign_in_to_cal_com": "Inicia sesión en tu cuenta de Cal.com",
"log_in_to_cal_com": "Iniciar sesión en Cal.com",
"track_your_meetings": "Rastrea tus reuniones, recibe notificaciones y administra tu agenda de manera más efectiva.",
"choose_how_you_d_like_to_join_call": "Elige cómo te gustaría unirte a esta llamada",
"new_event_trigger": "cuando se reserva un nuevo evento",
"email_host_action": "enviar correo electrónico al anfitrión",
"email_attendee_action": "enviar correo electrónico a los asistentes",
@@ -1361,6 +1380,8 @@
"custom": "Personalizado",
"reminder": "Recordatorio",
"rescheduled": "Reprogramado",
"rescheduled_by": "Reprogramado por",
"original_booking": "Reserva original",
"completed": "Completado",
"rating": "Calificación",
"reminder_email": "Recordatorio: {{eventType}} con {{name}} a las {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "El flujo de trabajo {{workflowName}} se ha {{offOn}} con éxito",
"download_responses": "Descargar respuestas",
"download_responses_description": "Descarga todas las respuestas a tu formulario en formato CSV.",
"view_responses": "Ver respuestas",
"download": "Descargar",
"downloading": "Descargando",
"download_recording": "Descargar grabación",
"transcription_enabled": "Las transcripciones están habilitadas ahora",
"transcription_stopped": "Las transcripciones se han detenido ahora",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Agregar nuevo formulario a su equipo",
"create_your_first_route": "Cree su primera ruta",
"route_to_the_right_person": "Dirija a la persona correcta según las respuestas de su formulario",
"form": "Formulario",
"form_description": "Cree su formulario para dirigir a un reservador",
"copy_link_to_form": "Copiar enlace al formulario",
"theme": "Tema de la página de reservas",
@@ -1862,6 +1886,8 @@
"wrong_code": "Código de verificación incorrecto",
"not_verified": "Aún no verificado",
"no_availability_in_month": "No hay disponibilidad en {{month}}",
"no_availability_rolling": "La programación solo está disponible hasta {{days}} días por adelantado. Por favor revisa nuevamente pronto.",
"no_availability_range": "La programación terminó el {{date}}. Por favor, revisa de nuevo pronto.",
"view_previous_month": "Ver mes anterior",
"view_next_month": "Ver el próximo mes",
"send_code": "Enviar código",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Pagar por este evento ya no es posible",
"booking_with_payment_cancelled_already_paid": "Un reembolso para este pago de reserva está en camino.",
"booking_with_payment_cancelled_refunded": "Este pago de reserva ha sido reembolsado.",
"booking_with_payment_cancelled_no_refund": "Según la política de reembolso del evento, el pago de la reserva no es reembolsable.",
"booking_with_payment_cancelled_refund_window_expired": "El período de reembolso del evento ha expirado. Por lo tanto, el pago de la reserva no es reembolsable.",
"booking_confirmation_failed": "La confirmación de la reserva falló",
"not_enough_seats": "No hay suficientes asientos",
"form_builder_field_already_exists": "Ya existe un campo con este nombre",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Abrir disponibilidad de usuarios",
"organization_no_slots_notification_switch_title": "Recibir notificaciones cuando tu equipo no tenga disponibilidad",
"organization_no_slots_notification_switch_description": "Los administradores recibirán notificaciones por correo electrónico cuando un usuario intente reservar con un miembro del equipo y se enfrente a 'Sin disponibilidad'. Enviamos este correo después de dos ocurrencias y te recordamos cada 7 días por usuario.",
"organization_disable_phone_only_sms_notifications_switch_title": "Desactivar notificaciones SMS para tipos de eventos solo con teléfono",
"organization_disable_phone_only_sms_notifications_switch_description": "Desactivar notificaciones SMS automáticas para tipos de eventos que solo tienen número de teléfono (attendeePhoneNumber) como pregunta obligatoria con correo electrónico opcional o no requerido",
"email_team_invite|subject|added_to_org": "{{user}} te agregó a la organización {{team}} en {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} te invitó a unirte a la organización {{team}} en {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} te agregó al equipo {{team}} de la organización {{parentTeamName}} en {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Tu enlace ha cambiado de {{a0}} a {{a1}}, pero no te preocupes, todos los enlaces anteriores siguen funcionando y redireccionando adecuadamente. <br /><br />Ten en cuenta: Todos tus tipos de eventos personales se han movido a la organización <strong>{{teamName}}</strong>, lo que también puede incluir un posible enlace personal.<br /><br />Por favor, inicia sesión y asegúrate de no tener eventos privados en tu nueva cuenta organizacional.<br /><br />Para eventos personales, recomendamos crear una nueva cuenta con una dirección de correo electrónico personal.<br /><br />Disfruta de tu nuevo enlace limpio: {{a2}}",
"email_organization_created|subject": "Tu organización ha sido creada",
"your_current_plan": "Tu plan actual",
"organization_price_per_user_month": "$37 por usuario al mes (mínimo 30 asientos)",
"organization_price_per_user_month": "$37 por usuario al mes",
"privacy_organization_description": "Gestiona la configuración de privacidad de tu organización",
"privacy": "Privacidad",
"team_will_be_under_org": "Los nuevos equipos estarán bajo tu organización",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Al continuar, aceptas nuestros",
"terms": "Términos",
"always_show_x_days": "Siempre {{x}} días disponibles",
"team_subscription_cancelled_successfully": "Suscripción del equipo cancelada con éxito",
"team_subscription_cancellation_error": "Error al cancelar la suscripción del equipo",
"unable_to_subscribe_to_the_platform": "Ocurrió un error al intentar suscribirse al plan de la plataforma, por favor intenta de nuevo más tarde",
"updating_oauth_client_error": "Ocurrió un error al actualizar el cliente OAuth, por favor intenta de nuevo más tarde",
"creating_oauth_client_error": "Ocurrió un error al crear el cliente OAuth, por favor intenta de nuevo más tarde",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Omitir la creación del registro de {{entry}} si no existe en Salesforce",
"salesforce_if_account_does_not_exist": "Si el contacto no existe bajo una cuenta, crear un nuevo cliente potencial a partir del asistente",
"salesforce_create_new_contact_under_account": "Crear un nuevo contacto bajo una cuenta basado en el dominio de correo electrónico del asistente y los contactos existentes",
"salesforce_change_record_owner_on_booking": "Cambiar propietario del registro en la reserva",
"mass_assign_attributes": "Asignar atributos en masa",
"reroute_preview_custom_message": "Resulta en mostrar un mensaje personalizado. Intenta cambiar la respuesta para redirigir a un evento",
"reroute_preview_external_redirect": "Resulta en redirigir a {{externalUrl}}. Intenta cambiar la respuesta para redirigir a un evento",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Enrutadas por período",
"per_day": "Por día",
"per_week": "Por semana",
"per_month": "Por mes",
"per_month": "por mes",
"routing_form_insights_assignment_reason": "Motivo de asignación",
"access_denied": "Acceso denegado",
"salesforce_route_to_owner": "El propietario del contacto será el anfitrión de Round Robin si está disponible",
"salesforce_add_attendees_as": "Agregar nuevos asistentes como",
"salesforce_do_not_route_to_owner": "El propietario del contacto no será forzado (aún puede ser anfitrión si coincide con los atributos y criterios de Round Robin)",
"salesforce_route_to_custom_lookup_field": "Dirigir a un usuario que coincida con un campo de búsqueda en una cuenta",
"salesforce_option": "Opción de Salesforce",
@@ -2927,6 +2961,7 @@
"shortfall": "Déficit",
"routing_form": "Formulario de enrutamiento",
"go_back_and_save": "Volver y guardar",
"save_changes": "Guardar cambios",
"leave_without_saving": "Salir sin guardar",
"leave_without_saving_description": "¿Estás seguro de que quieres salir sin guardar los cambios en tu formulario de enrutamiento?",
"something_unexpected_occurred": "Ocurrió algo inesperado",
@@ -2961,6 +2996,9 @@
"authorize": "Autorizar",
"next": "Siguiente",
"hide": "Ocultar",
"show": "Mostrar",
"utm_params": "Parámetros UTM",
"no_utm_params": "No hay parámetros UTM disponibles.",
"asc": "Asc",
"desc": "Desc",
"verify_email_change": "Verificar cambio de correo electrónico",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Necesitas tener un mínimo de equipos publicados",
"you_are_part_of_this_organization_already": "Ya eres parte de esta organización",
"you_are_part_of_another_organization_cannot_create_organization": "Eres parte de otra organización, no puedes crear una nueva organización",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Eres parte de otra organización de plataforma, no puedes crear una nueva organización",
"organization_payment_success": "Pago de la organización exitoso",
"organization_payment_success_description": "Tu organización ha sido creada exitosamente",
"this_may_take_a_few_seconds": "Esto puede tomar unos segundos...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "La incorporación de la organización ya se completó",
"organization_onboarding_already_exists": "La incorporación de la organización ya existe",
"organization_onboarding_not_found": "No se encontró la incorporación de la organización",
"payment_successful": "Pago exitoso",
"payment_successful": "¡Pago exitoso!",
"handover_onboarding_page_title": "Traspaso de incorporación",
"handover_onboarding_page_description": "Traspaso de incorporación al usuario",
"organization_already_exists_with_this_slug": "Ya existe una organización con este slug",
@@ -3019,9 +3058,12 @@
"link": "Enlace",
"rows_per_page": "filas por página",
"pagination_status": "{{currentRange}} de {{totalItems}}",
"tip_username_plus": "Consejo: Puedes usar un '+' entre nombres de usuario: cal.com/anna+brian para crear una reunión grupal dinámica",
"tip_username_plus": "Consejo: Puedes agregar un '+' entre nombres de usuario: cal.com/anna+brian para crear una reunión grupal dinámica",
"user_has_no_team_yet": "Aún no tienes un equipo",
"no_team_members": "Aún no tienes miembros en tu equipo",
"recurring_event_doesnt_support_seats": "Los eventos recurrentes no admiten la función de asientos. Hazlo no recurrente para habilitar asientos.",
"seats_doesnt_support_recurring": "La función de asientos no admite eventos recurrentes. Desactiva la función de asientos para hacerlo recurrente.",
"recurring_event_seats_error": "Los eventos recurrentes no admiten la función de asientos. Desactiva la función de asientos o haz que el evento no sea recurrente.",
"segment": "Segmento",
"rename": "Renombrar",
"rename_segment": "Renombrar segmento",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Reservas más canceladas",
"name_or_email": "Nombre o correo electrónico",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Si no se encuentra ningún contacto, recurrir al propietario del lead si existe",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agrega tus nuevas cadenas arriba de esta línea ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Fecha y hora",
"email_reminder_upcoming_event_notice" : "Este es un recordatorio sobre tu próximo evento.",
"email_reminder_triggered_by_workflow" : "Este recordatorio fue activado por un Workflow en Cal.",
"enable_delegation_credential": "Habilitar credencial de delegación",
"enable_delegation_credential_description": "Otorga a Cal.com acceso automático a los calendarios de todos los miembros de la organización habilitando la credencial de delegación.",
"disable_delegation_credential": "Deshabilitar credencial de delegación",
"disable_delegation_credential_description": "Una vez que se deshabilita la credencial de delegación, los miembros de la organización que no hayan conectado sus calendarios deberán hacerlo manualmente.",
"last_active": "Última actividad",
"member_since": "Miembro desde",
"last_updated": "Última actualización",
"salesforce_on_cancel_write_to_event": "Al cancelar una reserva, escribir en el registro del evento en lugar de eliminarlo",
"salesforce_on_every_cancellation": "En cada cancelación",
"report_issue": "Reportar problema",
"report_issue_description": "Puedes enviar un ticket en GitHub o actualizar tu plan para recibir soporte en tiempo real con conferencias de desarrolladores",
"open_issue": "Abrir problema",
"this_is_your_current_plan": "Este es tu plan actual",
"schedule_a_time": "Programar una hora",
"this_includes": "Esto incluye:",
"oauth_client_updated_successfully": "Cliente OAuth actualizado correctamente",
"oauth_client_not_found": "Cliente OAuth no encontrado.",
"subscribe_to_platform": "Suscribirse a la plataforma",
"error_accessing_webhooks": "Error al intentar acceder a los webhooks.",
"webhook_update_failed": "No se pudo actualizar el webhook.",
"webhook_create_failed": "No se pudo crear el webhook.",
"invalid_link": "Enlace inválido",
"currently_subscribed_to_plan": "Actualmente estás suscrito al plan {{planFirstLetter}}{{planRest}}",
"user_team": "Usuario/Equipo",
"client_id_copied": "¡ID del cliente copiado!",
"client_secret_copied": "¡Secreto del cliente copiado!",
"maintenance_message": "El equipo de Cal.com está realizando mantenimiento programado. Si tienes alguna pregunta, por favor contacta a soporte.",
"your_payment_failed": "Tu pago falló",
"check_your_inbox": "Revisa tu bandeja de entrada",
"account_created_premium_not_reserved": "Tu cuenta ha sido creada, pero tu premium no ha sido reservado.",
"email_sent_with_activation_link": "Hemos enviado un correo electrónico a {{email}} con un enlace para activar tu cuenta.",
"activate_account_to_purchase_username": "Una vez que actives tu cuenta, podrás intentar comprar tu nombre de usuario premium nuevamente o seleccionar uno diferente.",
"open_in_gmail": "Abrir en Gmail",
"dont_see_email": "¿No ves un correo electrónico?",
"resend_in_seconds": "Reenviar en {{seconds}} segundos",
"resend": "Reenviar",
"verification_email_sent": "Correo de verificación enviado",
"select_all_members": "Seleccionar todos los miembros",
"select_all_members_tooltip": "Seleccionar todos los miembros agregará a todos los futuros miembros del equipo cuando se añadan al equipo.",
"form_settings": "Configuración del formulario",
"remove_whitelist_status": "Eliminar estado de lista blanca",
"whitelist_user_workflows": "Incluir flujos de trabajo de usuario en lista blanca",
"user_workflows_whitelisted": "Flujos de trabajo de usuario incluidos en lista blanca",
"user_workflows_unwhitelisted": "Flujos de trabajo de usuario eliminados de lista blanca",
"date_and_time": "Fecha y hora",
"email_reminder_upcoming_event_notice": "Este es un recordatorio sobre tu próximo evento.",
"email_reminder_triggered_by_workflow": "Este recordatorio fue activado por un Workflow en Cal.",
"event_upper_case": "Evento",
"scheduling_by": "Programado por",
"experience_review_prompt": "¿Cómo fue tu última experiencia?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "¿Qué tan satisfecho estuviste con tu última reunión?",
"meeting_not_joined_question": "¿no asististe a la reunión?",
"reschedule_cta_short": "Reprograma aquí.",
"hide_organizer_email": "Ocultar correo del organizador",
"platform_customer_cant_create_organization": "Ya formas parte de una organización de plataforma, por lo que no puedes crear una nueva organización. Cada usuario solo puede pertenecer a una organización. Por favor, crea una nueva cuenta de cal.com con un correo electrónico diferente y usa esa cuenta para suscribirte al plan de organizaciones.",
"organization_customer_cant_create_platform": "Ya formas parte de una organización, por lo que no puedes crear una organización de plataforma. Cada usuario solo puede pertenecer a una organización. Por favor, crea una nueva cuenta de cal.com con un correo electrónico diferente y usa esa cuenta para suscribirte al plan de plataforma.",
"hide_organizer_email_description": "Ocultar la dirección de correo electrónico del organizador en la pantalla de reserva, notificaciones por correo electrónico y eventos del calendario",
"you_and_conjunction": "Tú &",
"email_survey_triggered_by_workflow": "Esta encuesta se activó mediante un Workflow en Cal."
"select_verified_email": "Seleccionar un correo electrónico verificado",
"custom_reply_to_email_title": "Correo 'Responder a' personalizado",
"custom_reply_to_email_description": "Usar una dirección de correo electrónico diferente como destinatario de respuesta para los correos de confirmación en lugar del correo del organizador",
"email_survey_triggered_by_workflow": "Esta encuesta se activó mediante un Workflow en Cal.",
"skip_trial": "Omitir período de prueba",
"team_trials_skipped_successfully": "Períodos de prueba del equipo omitidos exitosamente",
"sms_workflow_consent": "Al ingresar tu número de teléfono, consientes recibir mensajes SMS para este evento. Pueden aplicarse tarifas de SMS.",
"routing_preview_more_info_found_insights": "Más información disponible en <0>Estadísticas de enrutamiento</0>",
"results": "Resultados",
"view_form": "Ver formulario",
"sms_opt_out_message": "Envía STOP para cancelar los mensajes SMS",
"routing_form_next_in_queue": "{{count}} siguiente(s) en cola",
"routing_form_select_members_to_email": "Enviar respuestas por correo electrónico a",
"routing_incomplete_booking_tab": "Reservas incompletas",
"include_no_show_in_rr_calculation": "Incluir reservas sin asistencia en los cálculos de round robin",
"matching": "Coincidencia",
"event_redirect": "Redirección de evento",
"reset_form": "Restablecer formulario",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agrega tus nuevas cadenas arriba de esta línea ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+116 -9
View File
@@ -620,6 +620,7 @@
"your_full_name": "Su nombre completo",
"no_name": "Sin nombre",
"enter_number_between_range": "Introduzca un número entre 1 y {{maxOccurences}}",
"continue_as_guest_description": "Rápido y sencillo - no se requiere cuenta. Perfecto para reuniones puntuales.",
"email_address": "Email",
"enter_valid_email": "Ingresa un correo electrónico válido",
"please_schedule_future_call": "Por favor, programa una llamada futura si no estamos disponibles en {{seconds}} segundos",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "En persona (dirección del asistente)",
"somewhere_else": "Otro lugar",
"custom_attendee_location": "Ubicación personalizada del asistente",
"continue_as_guest": "Continuar como invitado",
"any_location": "Cualquier ubicación",
"yes": "Sí",
"no": "No",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Equipo Actualizado Correctamente",
"your_team_updated_successfully": "Tu equipo ha sido actualizado con éxito.",
"your_org_updated_successfully": "Su organización se ha actualizado correctamente.",
"error_copying_to_clipboard": "Error al copiar al portapapeles",
"about": "Acerca de",
"team_description": "Comentarios sobre tu equipo. Esta información aparecerá en la página de la URL de tu equipo.",
"organization_id": "ID de la organización",
"organization_id_copied": "ID de la organización copiado.",
"org_description": "Algunas frases sobre su organización. Esto aparecerá en la página de la URL de su organización.",
"team_id": "ID del equipo",
"team_id_copied": "ID del equipo copiado.",
"members": "Miembros",
"organization_members": "Miembros de Organization",
"member": "Miembro",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "¿Estás seguro de que quieres eliminar este miembro del equipo?",
"confirm_disband_team": "Sí, Disolver Equipo",
"confirm_remove_member": "Sí, Eliminar Miembro",
"confirm_subscription_cancellation": "Sí, cancelar suscripción",
"cancel_subscription": "Cancelar suscripción",
"cancel_subscription_description": "Al cancelar tu suscripción se desactivará permanentemente tu plan actual. Esta acción no se puede deshacer.",
"remove_member": "Eliminar Miembro",
"manage_your_team": "Administra tu Equipo",
"no_teams": "Todavía no tienes ningún equipo.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "URL de tu página de reservas",
"booking_cancel_redirect_uri": "URL de la página donde tus usuarios pueden cancelar su reserva",
"booking_reschedule_redirect_uri": "URL de la página donde tus usuarios pueden reprogramar su reserva",
"booking_conflict_error": "Este horario ya no está disponible. Por favor, regresa a la página anterior y selecciona otro horario.",
"open_invitations": "Invitaciones Abiertas",
"new_team": "Nuevo Equipo",
"create_first_team_and_invite_others": "Cree su primer equipo e invite a otros usuarios a trabajar juntos.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Tu cuenta se creó mediante un Proveedor de Identidad.",
"account_managed_by_identity_provider": "Tu cuenta es administrada por {{provider}}",
"account_managed_by_identity_provider_description": "Para cambiar tu correo electrónico, contraseña, habilitar la autenticación de doble factor y más, por favor visita la configuración de tu cuenta de {{provider}}.",
"account_managed_by_identity_provider_error": "Tu cuenta está gestionada por un proveedor de identidad diferente. Intenta iniciar sesión con {{provider}}.",
"user_creation_error": "Error al crear un nuevo usuario. Por favor, inténtalo de nuevo.",
"signin_with_google": "Iniciar sesión con Google",
"signin_with_saml": "Iniciar sesión con SAML",
"signin_with_saml_oidc": "Inicie sesión con SAML/OIDC",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "¡Ya está listo!",
"install_zapier_app": "Instale primero la aplicación Zapier desde la App Store.",
"install_make_app": "Instale primero la aplicación Make desde la App Store.",
"app_installation": "Instalación de la aplicación",
"app_not_installed": "Aplicación no instalada",
"visit_our_app_store": "Lo sentimos, esta aplicación no está instalada en tu cuenta. Por favor visita nuestra tienda de aplicaciones para explorar y descubrir esta y otras grandes aplicaciones.",
"connect_apple_server": "Conectar con Apple Server",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "cuando se cancela el evento",
"after_hosts_cal_video_no_show": "Después de que los anfitriones no se unieron al video de Cal",
"after_guests_cal_video_no_show": "Después de que los invitados no se unieron al video de Cal",
"join_video_call": "Unirse a la videollamada",
"sign_in_to_cal_com": "Inicia sesión en tu cuenta de Cal.com",
"log_in_to_cal_com": "Iniciar sesión en Cal.com",
"track_your_meetings": "Haz seguimiento de tus reuniones, recibe notificaciones y gestiona tu agenda de manera más efectiva.",
"choose_how_you_d_like_to_join_call": "Elige cómo te gustaría unirte a esta llamada",
"new_event_trigger": "cuando se reserva un nuevo evento",
"email_host_action": "enviar correo electrónico al anfitrión",
"email_attendee_action": "enviar correo electrónico a los asistentes",
@@ -1361,6 +1380,8 @@
"custom": "Personalizado",
"reminder": "Recordatorio",
"rescheduled": "Reprogramado",
"rescheduled_by": "Reprogramado por",
"original_booking": "Reserva original",
"completed": "Completado",
"rating": "Calificación",
"reminder_email": "Recordatorio: {{eventType}} con {{name}} el {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "El flujo de trabajo {{workflowName}} se ha activado {{offOn}} con éxito",
"download_responses": "Descargar respuestas",
"download_responses_description": "Descargue todas las respuestas de su formulario en formato CSV.",
"view_responses": "Ver respuestas",
"download": "Descargar",
"downloading": "Descargando",
"download_recording": "Descargar grabación",
"transcription_enabled": "Las transcripciones están habilitadas ahora",
"transcription_stopped": "Las transcripciones están detenidas ahora",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Añada un nuevo formulario a su equipo",
"create_your_first_route": "Cree su primera ruta",
"route_to_the_right_person": "Ruta a la persona adecuada en función de las respuestas a su formulario",
"form": "Formulario",
"form_description": "Crea tu formulario para dirigirlo a un agente de reservas",
"copy_link_to_form": "Copiar enlace al formulario",
"theme": "Tema de la página de reserva",
@@ -1862,6 +1886,8 @@
"wrong_code": "Código de verificación incorrecto",
"not_verified": "Aún no se ha verificado",
"no_availability_in_month": "Sin disponibilidad en {{month}}",
"no_availability_rolling": "La programación solo está disponible hasta {{days}} días por adelantado. Por favor, vuelve a consultar pronto.",
"no_availability_range": "La programación terminó el {{date}}. Por favor, comprueba de nuevo pronto.",
"view_previous_month": "Ver mes anterior",
"view_next_month": "Ver el próximo mes",
"send_code": "Enviar código",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Ya no es posible pagar por este evento",
"booking_with_payment_cancelled_already_paid": "Un reembolso por el pago de esta reserva está en camino.",
"booking_with_payment_cancelled_refunded": "El pago de esta reserva se ha reembolsado.",
"booking_with_payment_cancelled_no_refund": "Según la política de reembolso del evento, el pago de la reserva no es reembolsable.",
"booking_with_payment_cancelled_refund_window_expired": "El período de reembolso del evento ha expirado. Por lo tanto, el pago de la reserva no es reembolsable.",
"booking_confirmation_failed": "Error al confirmar la reserva",
"not_enough_seats": "No hay suficientes plazas",
"form_builder_field_already_exists": "Ya existe un campo con este nombre",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Abrir disponibilidad de usuarios",
"organization_no_slots_notification_switch_title": "Recibir notificaciones cuando tu equipo no tenga disponibilidad",
"organization_no_slots_notification_switch_description": "Los administradores recibirán notificaciones por correo electrónico cuando un usuario intente reservar con un miembro del equipo y no haya disponibilidad. Enviamos este correo después de dos intentos y te recordamos cada 7 días por usuario.",
"organization_disable_phone_only_sms_notifications_switch_title": "Desactivar notificaciones SMS para tipos de eventos solo con teléfono",
"organization_disable_phone_only_sms_notifications_switch_description": "Desactivar notificaciones SMS automáticas para tipos de eventos que solo tienen número de teléfono (attendeePhoneNumber) como pregunta obligatoria con correo electrónico opcional o no requerido",
"email_team_invite|subject|added_to_org": "{{user}} te ha añadido a la organización {{team}} en {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} te ha invitado a unirte a la organización {{team}} en {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} te ha añadido al equipo {{team}} de la organización {{parentTeamName}} en {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Tu enlace ha cambiado de {{a0}} a {{a1}} pero no te preocupes, todos los enlaces anteriores siguen funcionando y redireccionando adecuadamente. <br /><br />Ten en cuenta: Todos tus tipos de eventos personales se han movido a la organización <strong>{{teamName}}</strong>, lo que también puede incluir un posible enlace personal.<br /><br />Por favor, inicia sesión y asegúrate de que no tienes eventos privados en tu nueva cuenta organizacional.<br /><br />Para eventos personales, recomendamos crear una nueva cuenta con una dirección de correo electrónico personal.<br /><br />Disfruta de tu nuevo enlace limpio: {{a2}}",
"email_organization_created|subject": "Tu organización ha sido creada",
"your_current_plan": "Tu plan actual",
"organization_price_per_user_month": "$37 por usuario al mes (mínimo 30 asientos)",
"organization_price_per_user_month": "$37 por usuario al mes",
"privacy_organization_description": "Gestiona la configuración de privacidad para tu organización",
"privacy": "Privacidad",
"team_will_be_under_org": "Los nuevos equipos estarán bajo tu organización",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Al continuar, aceptas nuestros",
"terms": "Términos",
"always_show_x_days": "Siempre {{x}} días disponibles",
"team_subscription_cancelled_successfully": "Suscripción del equipo cancelada con éxito",
"team_subscription_cancellation_error": "Error al cancelar la suscripción del equipo",
"unable_to_subscribe_to_the_platform": "Ocurrió un error al intentar suscribirse al plan de la plataforma, por favor intente de nuevo más tarde",
"updating_oauth_client_error": "Ocurrió un error al actualizar el cliente OAuth, por favor intente de nuevo más tarde",
"creating_oauth_client_error": "Ocurrió un error al crear el cliente OAuth, por favor intente de nuevo más tarde",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Omitir la creación del registro de {{entry}} si no existe en Salesforce",
"salesforce_if_account_does_not_exist": "Si el contacto no existe bajo una cuenta, crear un nuevo cliente potencial a partir del asistente",
"salesforce_create_new_contact_under_account": "Crear un nuevo contacto bajo una cuenta basado en el dominio de correo electrónico del asistente y los contactos existentes",
"salesforce_change_record_owner_on_booking": "Cambiar propietario del registro en la reserva",
"mass_assign_attributes": "Asignar atributos en masa",
"reroute_preview_custom_message": "Resulta en mostrar un mensaje personalizado. Intenta cambiar la respuesta para redirigir a un evento",
"reroute_preview_external_redirect": "Resulta en redirigir a {{externalUrl}}. Intenta cambiar la respuesta para redirigir a un evento",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Enrutado a por período",
"per_day": "Por día",
"per_week": "Por semana",
"per_month": "Por mes",
"per_month": "al mes",
"routing_form_insights_assignment_reason": "Motivo de asignación",
"access_denied": "Acceso denegado",
"salesforce_route_to_owner": "El propietario del contacto será el anfitrión de Round Robin si está disponible",
"salesforce_add_attendees_as": "Añadir nuevos asistentes como",
"salesforce_do_not_route_to_owner": "No se forzará al propietario del contacto (aún puede ser anfitrión si coincide con los atributos y criterios de Round Robin)",
"salesforce_route_to_custom_lookup_field": "Dirigir a un usuario que coincida con un campo de búsqueda en una cuenta",
"salesforce_option": "Opción de Salesforce",
@@ -2927,6 +2961,7 @@
"shortfall": "Déficit",
"routing_form": "Formulario de enrutamiento",
"go_back_and_save": "Volver y guardar",
"save_changes": "Guardar cambios",
"leave_without_saving": "Salir sin guardar",
"leave_without_saving_description": "¿Estás seguro de que quieres salir sin guardar los cambios en tu formulario de enrutamiento?",
"something_unexpected_occurred": "Algo inesperado ha ocurrido",
@@ -2961,6 +2996,9 @@
"authorize": "Autorizar",
"next": "Siguiente",
"hide": "Ocultar",
"show": "Mostrar",
"utm_params": "Parámetros UTM",
"no_utm_params": "No hay parámetros UTM disponibles.",
"asc": "Asc",
"desc": "Desc",
"verify_email_change": "Verificar cambio de correo electrónico",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Necesitas tener un mínimo de equipos publicados",
"you_are_part_of_this_organization_already": "Ya formas parte de esta organización",
"you_are_part_of_another_organization_cannot_create_organization": "Formas parte de otra organización, no puedes crear una nueva",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Formas parte de otra organización de plataforma, no puedes crear una nueva organización",
"organization_payment_success": "Pago de la organización exitoso",
"organization_payment_success_description": "Tu organización se ha creado con éxito",
"this_may_take_a_few_seconds": "Esto puede tardar unos segundos...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "La incorporación de la organización ya se ha completado",
"organization_onboarding_already_exists": "La incorporación de la organización ya existe",
"organization_onboarding_not_found": "No se encontró la incorporación de la organización",
"payment_successful": "Pago exitoso",
"payment_successful": "¡Pago exitoso!",
"handover_onboarding_page_title": "Traspaso de incorporación",
"handover_onboarding_page_description": "Traspaso de incorporación al usuario",
"organization_already_exists_with_this_slug": "Ya existe una organización con este slug",
@@ -3019,9 +3058,12 @@
"link": "Enlace",
"rows_per_page": "filas por página",
"pagination_status": "{{currentRange}} de {{totalItems}}",
"tip_username_plus": "Consejo: Puedes usar un '+' entre nombres de usuario: cal.com/anna+brian para crear una reunión de grupo dinámica",
"tip_username_plus": "Consejo: Puedes añadir un '+' entre nombres de usuario: cal.com/anna+brian para crear una reunión grupal dinámica",
"user_has_no_team_yet": "Aún no tienes un equipo",
"no_team_members": "Aún no tienes miembros en tu equipo",
"recurring_event_doesnt_support_seats": "Los eventos recurrentes no admiten la función de asientos. Hazlo no recurrente para habilitar asientos.",
"seats_doesnt_support_recurring": "La función de asientos no admite eventos recurrentes. Desactiva la función de asientos para hacerlo recurrente.",
"recurring_event_seats_error": "Los eventos recurrentes no admiten la función de asientos. Desactiva la función de asientos o haz que el evento no sea recurrente.",
"segment": "Segmento",
"rename": "Renombrar",
"rename_segment": "Renombrar segmento",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Reservas más canceladas",
"name_or_email": "Nombre o correo electrónico",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Si no se encuentra ningún contacto, recurrir al propietario del lead si existe",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agregue sus nuevas cadenas arriba ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Fecha y hora",
"email_reminder_upcoming_event_notice" : "Este es un recordatorio sobre su próximo evento.",
"email_reminder_triggered_by_workflow" : "Este recordatorio fue activado por un flujo de trabajo en Cal.",
"enable_delegation_credential": "Habilitar credencial de delegación",
"enable_delegation_credential_description": "Concede a Cal.com acceso automático a los calendarios de todos los miembros de la organización habilitando la credencial de delegación.",
"disable_delegation_credential": "Deshabilitar credencial de delegación",
"disable_delegation_credential_description": "Una vez que se deshabilita la credencial de delegación, los miembros de la organización que no hayan conectado sus calendarios deberán hacerlo manualmente.",
"last_active": "Última actividad",
"member_since": "Miembro desde",
"last_updated": "Última actualización",
"salesforce_on_cancel_write_to_event": "Al cancelar la reserva, escribir en el registro del evento en lugar de eliminarlo",
"salesforce_on_every_cancellation": "En cada cancelación",
"report_issue": "Informar de un problema",
"report_issue_description": "Puedes enviar un ticket en GitHub o actualizar tu plan para recibir soporte en tiempo real con conferencias de desarrolladores",
"open_issue": "Abrir incidencia",
"this_is_your_current_plan": "Este es tu plan actual",
"schedule_a_time": "Programar una hora",
"this_includes": "Esto incluye:",
"oauth_client_updated_successfully": "Cliente OAuth actualizado correctamente",
"oauth_client_not_found": "Cliente OAuth no encontrado.",
"subscribe_to_platform": "Suscribirse a la plataforma",
"error_accessing_webhooks": "Error al intentar acceder a los webhooks.",
"webhook_update_failed": "Error al actualizar el webhook.",
"webhook_create_failed": "Error al crear el webhook.",
"invalid_link": "Enlace no válido",
"currently_subscribed_to_plan": "Actualmente estás suscrito al plan {{planFirstLetter}}{{planRest}}",
"user_team": "Usuario/Equipo",
"client_id_copied": "¡ID de cliente copiado!",
"client_secret_copied": "¡Secreto de cliente copiado!",
"maintenance_message": "El equipo de Cal.com está realizando mantenimiento programado. Si tienes alguna pregunta, contacta con soporte.",
"your_payment_failed": "Tu pago ha fallado",
"check_your_inbox": "Revisa tu bandeja de entrada",
"account_created_premium_not_reserved": "Tu cuenta ha sido creada, pero tu premium no ha sido reservado.",
"email_sent_with_activation_link": "Hemos enviado un correo electrónico a {{email}} con un enlace para activar tu cuenta.",
"activate_account_to_purchase_username": "Una vez que actives tu cuenta, podrás intentar comprar tu nombre de usuario premium nuevamente o seleccionar uno diferente.",
"open_in_gmail": "Abrir en Gmail",
"dont_see_email": "¿No ves un correo electrónico?",
"resend_in_seconds": "Reenviar en {{seconds}} segundos",
"resend": "Reenviar",
"verification_email_sent": "Correo de verificación enviado",
"select_all_members": "Seleccionar todos los miembros",
"select_all_members_tooltip": "Al seleccionar todos los miembros se añadirán todos los futuros miembros del equipo cuando se agreguen al equipo.",
"form_settings": "Configuración del formulario",
"remove_whitelist_status": "Eliminar estado de lista blanca",
"whitelist_user_workflows": "Incluir flujos de trabajo de usuario en lista blanca",
"user_workflows_whitelisted": "Flujos de trabajo de usuario incluidos en lista blanca",
"user_workflows_unwhitelisted": "Flujos de trabajo de usuario eliminados de lista blanca",
"date_and_time": "Fecha y hora",
"email_reminder_upcoming_event_notice": "Este es un recordatorio sobre su próximo evento.",
"email_reminder_triggered_by_workflow": "Este recordatorio fue activado por un flujo de trabajo en Cal.",
"event_upper_case": "Evento",
"scheduling_by": "Programado por",
"experience_review_prompt": "¿Cómo fue tu experiencia reciente?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "¿Qué tan satisfecho estuvo con su última reunión?",
"meeting_not_joined_question": "¿no asististe a la reunión?",
"reschedule_cta_short": "Reprogramar aquí.",
"hide_organizer_email": "Ocultar correo electrónico del organizador",
"platform_customer_cant_create_organization": "Ya formas parte de una organización de plataforma, por lo que no puedes crear una nueva organización. Cada usuario solo puede pertenecer a una organización. Por favor, crea una nueva cuenta de cal.com con un correo electrónico diferente y usa esa cuenta para suscribirte al plan de organizaciones.",
"organization_customer_cant_create_platform": "Ya formas parte de una organización, por lo que no puedes crear una organización de plataforma. Cada usuario solo puede pertenecer a una organización. Por favor, crea una nueva cuenta de cal.com con un correo electrónico diferente y usa esa cuenta para suscribirte al plan de plataforma.",
"hide_organizer_email_description": "Ocultar la dirección de correo electrónico del organizador en la pantalla de reserva, notificaciones por correo electrónico y eventos del calendario",
"you_and_conjunction": "Tú &",
"email_survey_triggered_by_workflow": "Esta encuesta fue activada por un Workflow en Cal."
"select_verified_email": "Seleccionar un correo electrónico verificado",
"custom_reply_to_email_title": "Correo electrónico personalizado para 'Responder a'",
"custom_reply_to_email_description": "Usar una dirección de correo electrónico diferente como destinatario de respuesta para los correos de confirmación en lugar del correo del organizador",
"email_survey_triggered_by_workflow": "Esta encuesta fue activada por un Workflow en Cal.",
"skip_trial": "Omitir período de prueba",
"team_trials_skipped_successfully": "Períodos de prueba del equipo omitidos con éxito",
"sms_workflow_consent": "Al ingresar tu número de teléfono, consientes recibir mensajes SMS para este evento. Pueden aplicarse tarifas de SMS.",
"routing_preview_more_info_found_insights": "Más información disponible en <0>Estadísticas de enrutamiento</0>",
"results": "Resultados",
"view_form": "Ver formulario",
"sms_opt_out_message": "Envía STOP para cancelar los mensajes SMS",
"routing_form_next_in_queue": "{{count}} siguiente(s) en cola",
"routing_form_select_members_to_email": "Enviar respuestas por correo electrónico a",
"routing_incomplete_booking_tab": "Reservas incompletas",
"include_no_show_in_rr_calculation": "Incluir reservas no presentadas en los cálculos de round robin",
"matching": "Coincidencia",
"event_redirect": "Redirección de evento",
"reset_form": "Restablecer formulario",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Agregue sus nuevas cadenas arriba ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+116 -9
View File
@@ -620,6 +620,7 @@
"your_full_name": "Teie täisnimi",
"no_name": "Nimetu",
"enter_number_between_range": "Palun sisestage arv vahemikus 1 kuni {{maxOccurences}}",
"continue_as_guest_description": "Kiire ja lihtne - kontot pole vaja. Ideaalne ühekordseteks kohtumisteks.",
"email_address": "E-posti aadress",
"enter_valid_email": "Palun sisesta kehtiv email",
"please_schedule_future_call": "Palun planeerige tulevane kõne, kui me pole {{seconds}} sekundi pärast saadaval",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Isiklikult (osaleja aadress)",
"somewhere_else": "Mujal",
"custom_attendee_location": "Kohandatud osaleja asukoht",
"continue_as_guest": "Jätka külalisena",
"any_location": "Mis tahes asukoht",
"yes": "Jah",
"no": "Ei",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Meeskonda värskendati edukalt",
"your_team_updated_successfully": "Teie meeskonda on edukalt värskendatud.",
"your_org_updated_successfully": "Teie organisatsiooni värskendamine õnnestus.",
"error_copying_to_clipboard": "Viga lõikelauale kopeerimisel",
"about": "Umbes",
"team_description": "Paar lauset teie meeskonna kohta. See kuvatakse teie meeskonna URL-i lehel.",
"organization_id": "Organisatsiooni ID",
"organization_id_copied": "Organisatsiooni ID kopeeritud.",
"org_description": "Paar lauset teie organisatsiooni kohta. See kuvatakse teie organisatsiooni URL-i lehel.",
"team_id": "Meeskonna ID",
"team_id_copied": "Meeskonna ID kopeeritud.",
"members": "Liikmed",
"organization_members": "Organisatsiooni liikmed",
"member": "liige",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Kas olete kindel, et soovite selle liikme meeskonnast eemaldada?",
"confirm_disband_team": "Jah, saada meeskond laiali",
"confirm_remove_member": "Jah, eemalda liige",
"confirm_subscription_cancellation": "Jah, tühista tellimus",
"cancel_subscription": "Tühista tellimus",
"cancel_subscription_description": "Tellimuse tühistamine deaktiveerib teie praeguse plaani jäädavalt. Seda toimingut ei saa tagasi võtta.",
"remove_member": "Eemalda liige",
"manage_your_team": "Juhtige oma meeskonda",
"no_teams": "Teil pole veel ühtegi meeskonda.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "Sinu broneerimislehe URL",
"booking_cancel_redirect_uri": "URL lehele, kus kasutajad saavad oma broneeringu tühistada",
"booking_reschedule_redirect_uri": "URL lehele, kus kasutajad saavad oma broneeringut ümber planeerida",
"booking_conflict_error": "See aeg pole enam saadaval. Palun minge tagasi eelmisele lehele ja valige teine aeg.",
"open_invitations": "Avatud kutsed",
"new_team": "Uus meeskond",
"create_first_team_and_invite_others": "Looge oma esimene meeskond ja kutsuge teisi kasutajaid koos töötama.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Teie konto loodi identiteedipakkuja abil.",
"account_managed_by_identity_provider": "Teie kontot haldab {{provider}}",
"account_managed_by_identity_provider_description": "E-posti aadressi, parooli muutmiseks, kahefaktorilise autentimise ja muu lubamiseks külastage oma teenusepakkuja {{provider}} konto seadeid.",
"account_managed_by_identity_provider_error": "Teie kontot haldab teine identiteedipakkuja. Proovige sisse logida teenuse {{provider}} abil.",
"user_creation_error": "Viga uue kasutaja loomisel. Palun proovige uuesti.",
"signin_with_google": "Logi sisse Google'iga",
"signin_with_saml": "Logi sisse SAML-iga",
"signin_with_saml_oidc": "Logi sisse SAML-i/OIDC-ga",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Kõik on valmis!",
"install_zapier_app": "Palun installige esmalt rakenduste poest Zapieri rakendus.",
"install_make_app": "Palun esmalt installige rakendus Make App rakenduste poest.",
"app_installation": "Rakenduse installimine",
"app_not_installed": "Rakendus pole installitud",
"visit_our_app_store": "Vabandust, see rakendus pole teie kontole installitud. Palun külastage meie rakenduste poodi, et uurida ja avastada seda ja teisi suurepäraseid rakendusi.",
"connect_apple_server": "Ühenda Apple Serveriga",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "Kui sündmus tühistatakse",
"after_hosts_cal_video_no_show": "Pärast seda, kui võõrustajad ei liitunud cal videoga",
"after_guests_cal_video_no_show": "Pärast seda, kui külalised ei liitunud cal videoga",
"join_video_call": "Liitu videokõnega",
"sign_in_to_cal_com": "Logige sisse oma Cal.com kontole",
"log_in_to_cal_com": "Logi sisse Cal.com-i",
"track_your_meetings": "Jälgige oma kohtumisi, saage teavitusi ja hallake oma ajakava tõhusamalt.",
"choose_how_you_d_like_to_join_call": "Valige, kuidas soovite selle kõnega liituda",
"new_event_trigger": "kui uus sündmus on broneeritud",
"email_host_action": "saada e-kiri hostile",
"email_attendee_action": "saada osalejatele e-kiri",
@@ -1361,6 +1380,8 @@
"custom": "Kohandatud",
"reminder": "Meeldetuletus",
"rescheduled": "Ümber ajastatud",
"rescheduled_by": "Uuesti ajastatud isiku poolt",
"original_booking": "Algne broneering",
"completed": "Lõpetatud",
"rating": "Hinnang",
"reminder_email": "Meeldetuletus: {{eventType}} kasutajaga {{name}} kell {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "{{workflowName}} töövoog lülitati {{offOn}} edukalt sisse",
"download_responses": "Laadi vastused alla",
"download_responses_description": "Laadige kõik vastused oma vormile alla CSV-vormingus.",
"view_responses": "Vaata vastuseid",
"download": "Lae alla",
"downloading": "Allalaadimine",
"download_recording": "Laadi salvestis alla",
"transcription_enabled": "Transkriptsioonid on nüüd lubatud",
"transcription_stopped": "Transkriptsioonid on nüüd peatatud",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Lisage oma meeskonda uus vorm",
"create_your_first_route": "Loo oma esimene marsruut",
"route_to_the_right_person": "Tee vormi vastuste põhjal marsruut õigele inimesele",
"form": "Vorm",
"form_description": "Loo oma vorm broneerija suunamiseks",
"copy_link_to_form": "Kopeeri link vormile",
"theme": "Broneerimislehe kujundus",
@@ -1862,6 +1886,8 @@
"wrong_code": "Vale kinnituskood",
"not_verified": "Pole veel kinnitatud",
"no_availability_in_month": "Pole saadaval {{kuus}}",
"no_availability_rolling": "Ajastamine on saadaval ainult kuni {{days}} ette. Palun kontrollige varsti uuesti.",
"no_availability_range": "Aja broneerimine lõppes {{date}}. Palun kontrollige peagi uuesti.",
"view_previous_month": "Vaata eelmist kuud",
"view_next_month": "Vaata järgmist kuud",
"send_code": "Saada kood",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Selle sündmuse eest tasumine pole enam võimalik",
"booking_with_payment_cancelled_already_paid": "Selle broneeringu makse tagasimakse on teel.",
"booking_with_payment_cancelled_refunded": "See broneeringu makse on tagastatud.",
"booking_with_payment_cancelled_no_refund": "Vastavalt sündmuse tagasimaksepoliitikale ei ole broneeringu makse tagastatav.",
"booking_with_payment_cancelled_refund_window_expired": "Sündmuse tagasimakseperiood on lõppenud. Seetõttu ei ole broneeringu makse tagastatav.",
"booking_confirmation_failed": "Broneeringu kinnitamine ebaõnnestus",
"not_enough_seats": "Pole piisavalt kohti",
"form_builder_field_already_exists": "Selle nimega väli on juba olemas",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Ava kasutajate saadavus",
"organization_no_slots_notification_switch_title": "Saage märguandeid, kui teie meeskond pole saadaval",
"organization_no_slots_notification_switch_description": "Administraatorid saavad meilimärguandeid, kui kasutaja üritab broneerida meeskonnaliiget ja seisab silmitsi olekuga 'Saadaval puudub'. Saadame selle meili pärast kahte juhtumit ja tuletame teile meelde iga 7 päeva tagant kasutaja kohta. ",
"organization_disable_phone_only_sms_notifications_switch_title": "Keela SMS-teavitused ainult telefoninumbri sündmuste jaoks",
"organization_disable_phone_only_sms_notifications_switch_description": "Keela automaatsed SMS-teavitused sündmuste jaoks, kus on kohustuslik ainult telefoninumber (attendeePhoneNumber) ja e-post on valikuline või mitte nõutav.",
"email_team_invite|subject|added_to_org": "{{user}} lisas teid rakenduses {{appName}} organisatsiooni {{team}}",
"email_team_invite|subject|invited_to_org": "{{user}} kutsus teid liituma organisatsiooniga {{team}} rakenduses {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} lisas teid organisatsiooni {{parentTeamName}} meeskonda {{team}} rakenduses {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Sinu link on muudetud {{a0}}-lt {{a1}}-ks, kuid ära muretse, kõik varasemad lingid töötavad endiselt ja suunavad vastavalt ümber. <br /><br />Palun pane tähele: Kõik sinu isiklikud sündmuste tüübid on viidud <strong>{{teamName}}</strong> organisatsiooni, mis võib sisaldada ka potentsiaalset isiklikku linki.<br /><br />Palun logi sisse ja veendu, et sul pole uuel organisatsiooni kontol privaatseid sündmusi.<br /><br />Isiklike sündmuste jaoks soovitame luua uue konto isikliku e-posti aadressiga.<br /><br />Naudi oma uut puhast linki: {{a2}}",
"email_organization_created|subject": "Teie organisatsioon on loodud",
"your_current_plan": "Teie praegune plaan",
"organization_price_per_user_month": "37 dollarit kasutaja kohta kuus (minimaalselt 30 kohta)",
"organization_price_per_user_month": "$37 kasutaja kohta kuus",
"privacy_organization_description": "Oma organisatsiooni privaatsusseadete haldamine",
"privacy": "Privaatsus",
"team_will_be_under_org": "Teie organisatsiooni alla kuuluvad uued meeskonnad",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Jätkates nõustute meie",
"terms": "Tingimustega",
"always_show_x_days": "Alati {{x}} päeva saadaval",
"team_subscription_cancelled_successfully": "Meeskonna tellimus tühistati edukalt",
"team_subscription_cancellation_error": "Viga meeskonna tellimuse tühistamisel",
"unable_to_subscribe_to_the_platform": "Platvormipaketi tellimisel ilmnes viga, proovige hiljem uuesti",
"updating_oauth_client_error": "OAuthi kliendi värskendamisel ilmnes viga, proovige hiljem uuesti",
"creating_oauth_client_error": "OAuthi kliendi loomisel ilmnes viga, proovige hiljem uuesti",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Jäta {{entry}} kirje loomata, kui seda Salesforce'is ei eksisteeri",
"salesforce_if_account_does_not_exist": "Kui kontakti ei eksisteeri konto all, loo osaleja andmetest uus müügivihje",
"salesforce_create_new_contact_under_account": "Loo uus kontakt konto alla, põhinedes osaleja e-posti domeenile ja olemasolevatele kontaktidele",
"salesforce_change_record_owner_on_booking": "Muuda broneeringu kirje omanikku",
"mass_assign_attributes": "Massiline atribuutide määramine",
"reroute_preview_custom_message": "See toob kaasa kohandatud sõnumi kuvamise. Proovi muuta vastust, et suunata sündmusele",
"reroute_preview_external_redirect": "See toob kaasa ümbersuunamise aadressile {{externalUrl}}. Proovi muuta vastust, et suunata sündmusele",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Suunatud perioodi kohta",
"per_day": "Päevas",
"per_week": "Nädalas",
"per_month": "Kuus",
"per_month": "kuus",
"routing_form_insights_assignment_reason": "Määramise põhjus",
"access_denied": "Juurdepääs keelatud",
"salesforce_route_to_owner": "Kontakti omanik on round robin host, kui saadaval",
"salesforce_add_attendees_as": "Lisa uued osalejad kui",
"salesforce_do_not_route_to_owner": "Kontakti omanikku ei sunnita (võib siiski olla host, kui vastab atribuutidele ja round robin kriteeriumitele)",
"salesforce_route_to_custom_lookup_field": "Suuna kasutajale, kes vastab konto otsinguväljale",
"salesforce_option": "Salesforce'i valik",
@@ -2927,6 +2961,7 @@
"shortfall": "Puudujääk",
"routing_form": "Marsruutimise vorm",
"go_back_and_save": "Mine tagasi ja salvesta",
"save_changes": "Salvesta muudatused",
"leave_without_saving": "Lahku salvestamata",
"leave_without_saving_description": "Kas oled kindel, et soovid lahkuda marsruutimisvormi muudatusi salvestamata?",
"something_unexpected_occurred": "Midagi ootamatut juhtus",
@@ -2961,6 +2996,9 @@
"authorize": "Autoriseeri",
"next": "Edasi",
"hide": "Peida",
"show": "Näita",
"utm_params": "UTM parameetrid",
"no_utm_params": "UTM parameetrid pole saadaval.",
"asc": "Kasvav",
"desc": "Kahanev",
"verify_email_change": "Kinnita e-posti aadressi muutmine",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Teil peab olema minimaalne arv avaldatud meeskondi",
"you_are_part_of_this_organization_already": "Te olete juba selle organisatsiooni liige",
"you_are_part_of_another_organization_cannot_create_organization": "Te olete osa teisest organisatsioonist, uut organisatsiooni ei saa luua",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Te olete osa teisest platvormi organisatsioonist, uut organisatsiooni ei saa luua.",
"organization_payment_success": "Organisatsiooni makse õnnestus",
"organization_payment_success_description": "Teie organisatsioon on edukalt loodud",
"this_may_take_a_few_seconds": "See võib võtta mõne sekundi...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Organisatsiooni liitumisprotsess on juba lõpetatud",
"organization_onboarding_already_exists": "Organisatsiooni liitumisprotsess on juba olemas",
"organization_onboarding_not_found": "Organisatsiooni liitumisprotsessi ei leitud",
"payment_successful": "Makse õnnestus",
"payment_successful": "Makse õnnestus!",
"handover_onboarding_page_title": "Liitumisprotsessi üleandmine",
"handover_onboarding_page_description": "Liitumisprotsessi üleandmine kasutajale",
"organization_already_exists_with_this_slug": "Selle lühilingiga organisatsioon on juba olemas",
@@ -3019,9 +3058,12 @@
"link": "Link",
"rows_per_page": "rida lehel",
"pagination_status": "{{currentRange}} / {{totalItems}}",
"tip_username_plus": "Nõuanne: Saate kasutajanimede vahele lisada '+': cal.com/anna+brian, et luua dünaamiline grupikohtumise",
"tip_username_plus": "Nõuanne: saate lisada '+' kasutajanimede vahele: cal.com/anna+brian, et luua dünaamiline grupikoosolek.",
"user_has_no_team_yet": "Teil pole veel meeskonda",
"no_team_members": "Teil pole veel meeskonnaliikmeid",
"recurring_event_doesnt_support_seats": "Korduv sündmus ei toeta kohtade funktsiooni. Muutke see mittekorduvaks, et lubada kohtade funktsioon.",
"seats_doesnt_support_recurring": "Kohtade funktsioon ei toeta korduvat sündmust. Keelake kohtade funktsioon, et muuta see korduvaks.",
"recurring_event_seats_error": "Korduv sündmus ei toeta kohtade funktsiooni. Keelake kohtade funktsioon või muutke sündmus mittekorduvaks.",
"segment": "Segment",
"rename": "Nimeta ümber",
"rename_segment": "Nimeta segment ümber",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Enim tühistatud broneeringud",
"name_or_email": "Nimi või e-post",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Kui kontakti ei leita, kasuta võimalusel liidi omanikku",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Kuupäev ja kellaaeg",
"email_reminder_upcoming_event_notice" : "See on meeldetuletus teie eelseisva sündmuse kohta.",
"email_reminder_triggered_by_workflow" : "Selle meeldetuletuse käivitas Cali töövoog.",
"enable_delegation_credential": "Luba delegeerimise volitus",
"enable_delegation_credential_description": "Andke Cal.com-ile automaatne juurdepääs kõigi organisatsiooni liikmete kalendritele, lubades delegeerimise volituse.",
"disable_delegation_credential": "Keela delegeerimise volitus",
"disable_delegation_credential_description": "Kui delegeerimise volitus on keelatud, peavad organisatsiooni liikmed, kes pole oma kalendreid ühendanud, seda käsitsi tegema.",
"last_active": "Viimati aktiivne",
"member_since": "Liige alates",
"last_updated": "Viimati uuendatud",
"salesforce_on_cancel_write_to_event": "Tühistatud broneeringu korral kirjutage sündmuse kirjesse selle asemel, et sündmus kustutada",
"salesforce_on_every_cancellation": "Iga tühistamise korral",
"report_issue": "Teata probleemist",
"report_issue_description": "Saate esitada pileti GitHubis või uuendada oma plaani, et saada reaalajas tuge arendajate konverentsidel",
"open_issue": "Ava probleem",
"this_is_your_current_plan": "See on teie praegune plaan",
"schedule_a_time": "Planeeri aeg",
"this_includes": "See sisaldab:",
"oauth_client_updated_successfully": "OAuth klient edukalt uuendatud",
"oauth_client_not_found": "OAuth klienti ei leitud.",
"subscribe_to_platform": "Telli platvorm",
"error_accessing_webhooks": "Viga veebikonksudele juurdepääsemisel.",
"webhook_update_failed": "Veebikonksu uuendamine ebaõnnestus.",
"webhook_create_failed": "Veebikonksu loomine ebaõnnestus.",
"invalid_link": "Kehtetu link",
"currently_subscribed_to_plan": "Olete praegu tellinud {{planFirstLetter}}{{planRest}} plaani",
"user_team": "Kasutaja/Meeskond",
"client_id_copied": "Kliendi ID kopeeritud!",
"client_secret_copied": "Kliendi saladus kopeeritud!",
"maintenance_message": "Cal.com meeskond teostab plaanilist hooldust. Kui teil on küsimusi, võtke ühendust toega.",
"your_payment_failed": "Teie makse ebaõnnestus",
"check_your_inbox": "Kontrollige oma postkasti",
"account_created_premium_not_reserved": "Teie konto on loodud, kuid teie premium ei ole reserveeritud.",
"email_sent_with_activation_link": "Oleme saatnud e-kirja aadressile {{email}} koos lingiga teie konto aktiveerimiseks.",
"activate_account_to_purchase_username": "Kui aktiveerite oma konto, saate uuesti proovida oma premium kasutajanime osta või valida teise.",
"open_in_gmail": "Ava Gmailis",
"dont_see_email": "Ei näe e-kirja?",
"resend_in_seconds": "Saada uuesti {{seconds}} sekundi pärast",
"resend": "Saada uuesti",
"verification_email_sent": "Kinnituskiri saadetud",
"select_all_members": "Vali kõik liikmed",
"select_all_members_tooltip": "Kõigi liikmete valimine lisab kõik tulevased meeskonnaliikmed, kui nad meeskonda lisatakse.",
"form_settings": "Vormi seaded",
"remove_whitelist_status": "Eemalda lubatud nimekirja staatus",
"whitelist_user_workflows": "Lisa kasutaja töövood lubatud nimekirja",
"user_workflows_whitelisted": "Kasutaja töövood lisatud lubatud nimekirja",
"user_workflows_unwhitelisted": "Kasutaja töövood eemaldatud lubatud nimekirjast",
"date_and_time": "Kuupäev ja kellaaeg",
"email_reminder_upcoming_event_notice": "See on meeldetuletus teie eelseisva sündmuse kohta.",
"email_reminder_triggered_by_workflow": "Selle meeldetuletuse käivitas Cali töövoog.",
"event_upper_case": "Sündmus",
"scheduling_by": "Plaanitud",
"experience_review_prompt": "Kuidas oli teie hiljutine kogemus?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Kui rahul olite oma viimase kohtumisega?",
"meeting_not_joined_question": "ei osalenud koosolekul?",
"reschedule_cta_short": "Broneeri uuesti siit.",
"hide_organizer_email": "Peida korraldaja e-posti aadress",
"platform_customer_cant_create_organization": "Te olete juba osa platvormi organisatsioonist, mistõttu te ei saa luua uut organisatsiooni. Iga kasutaja saab kuuluda ainult ühte organisatsiooni. Palun looge uus cal.com konto teise e-posti aadressiga ja kasutage seda kontot organisatsiooni plaaniga liitumiseks.",
"organization_customer_cant_create_platform": "Te olete juba osa organisatsioonist, mistõttu te ei saa luua platvormi organisatsiooni. Iga kasutaja saab kuuluda ainult ühte organisatsiooni. Palun looge uus cal.com konto teise e-posti aadressiga ja kasutage seda kontot platvormi plaaniga liitumiseks.",
"hide_organizer_email_description": "Peida korraldaja e-posti aadress broneerimisekraanil, e-posti teavitustes ja kalendrisündmustes.",
"you_and_conjunction": "Sina &",
"email_survey_triggered_by_workflow": "See küsitlus käivitati Cali töövooga."
"select_verified_email": "Vali kinnitatud e-posti aadress",
"custom_reply_to_email_title": "Kohandatud 'Vasta-aadress' e-post",
"custom_reply_to_email_description": "Kasutage kinnituskirjade jaoks vastuse aadressina teist e-posti aadressi, mitte korraldaja e-posti aadressi.",
"email_survey_triggered_by_workflow": "See küsitlus käivitati Cali töövooga.",
"skip_trial": "Jäta prooviperiood vahele",
"team_trials_skipped_successfully": "Meeskonna prooviperioodid edukalt vahele jäetud",
"sms_workflow_consent": "Sisestades oma telefoninumbri, annate nõusoleku saada selle sündmuse kohta SMS-sõnumeid. Võivad kehtida SMS-i tariifid.",
"routing_preview_more_info_found_insights": "Lisateavet leiate <0>marsruutimise ülevaadetest</0>",
"results": "Tulemused",
"view_form": "Vaata vormi",
"sms_opt_out_message": "SMS-sõnumitest loobumiseks saatke tekst STOP",
"routing_form_next_in_queue": "{{count}} järgmine järjekorras",
"routing_form_select_members_to_email": "Saada e-posti vastused",
"routing_incomplete_booking_tab": "Lõpetamata broneeringud",
"include_no_show_in_rr_calculation": "Kaasa mitteilmunud broneeringud round robin arvutustesse",
"matching": "Sobitamine",
"event_redirect": "Sündmuse ümbersuunamine",
"reset_form": "Lähtesta vorm",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+116 -9
View File
@@ -620,6 +620,7 @@
"your_full_name": "Zure izen osoa",
"no_name": "Izenik ez",
"enter_number_between_range": "Mesedez sartu 1 eta {{maxOccurences}} arteko zenbaki bat",
"continue_as_guest_description": "Azkarra eta erraza - ez da konturik behar. Perfektua aldi bakarreko bileretarako.",
"email_address": "Email helbidea",
"enter_valid_email": "Mesedez, adierazi baliozko email helbide bat",
"please_schedule_future_call": "Mesedez, programatu etorkizuneko dei bat {{seconds}} segundotan eskuragarri ez bagaude",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Aurrez aurre (partaidearen helbidean)",
"somewhere_else": "Beste nonbait",
"custom_attendee_location": "Parte-hartzailearen kokapen pertsonalizatua",
"continue_as_guest": "Jarraitu gonbidatu gisa",
"any_location": "Edozein kokapen",
"yes": "Bai",
"no": "Ez",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Taldea egoki eguneratu da",
"your_team_updated_successfully": "Zure taldea egoki eguneratu da.",
"your_org_updated_successfully": "Zure erakundea egoki eguneratu da.",
"error_copying_to_clipboard": "Errorea arbelera kopiatzean",
"about": "Honi buruz",
"team_description": "Esaldi gutxi batzuk zure taldeari buruz. Zure taldearen orrialdean agertuko dira.",
"organization_id": "Erakundearen IDa",
"organization_id_copied": "Erakundearen IDa kopiatua.",
"org_description": "Esaldi gutxi batzuk zure erakundeari buruz. Zure erakundearen orrialdean agertuko dira.",
"team_id": "Taldearen IDa",
"team_id_copied": "Taldearen IDa kopiatua.",
"members": "Kideak",
"organization_members": "Erakundeko kideak",
"member": "Kidea",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Ziur zaude kide hau taldetik kendu nahi duzula?",
"confirm_disband_team": "Bai, taldea desegin",
"confirm_remove_member": "Bai, ezabatu kidea",
"confirm_subscription_cancellation": "Bai, ezeztatu harpidetza",
"cancel_subscription": "Ezeztatu harpidetza",
"cancel_subscription_description": "Zure harpidetza ezeztatzeak zure oraingo plana betiko desaktibatuko du. Ekintza hau ezin da desegin.",
"remove_member": "Ezabatu kidea",
"manage_your_team": "Kudeatu zure taldea",
"no_teams": "Oraindik ez daukazu talderik.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "Zure erreserba orriaren URLa",
"booking_cancel_redirect_uri": "Zure erabiltzaileek erreserba bertan behera uzteko orriaren URLa",
"booking_reschedule_redirect_uri": "Zure erabiltzaileek erreserba berriz programatzeko orriaren URLa",
"booking_conflict_error": "Tarte hau ez dago jada eskuragarri. Mesedez, itzuli aurreko orrira eta aukeratu beste ordu bat.",
"open_invitations": "Gonbidapen irekiak",
"new_team": "Talde berria",
"create_first_team_and_invite_others": "Sortu zure lehen taldea eta gonbidatu beste erabiltzaileak elkarlanean aritzera.",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Zure kontua identitate-hornitzaile baten bidez sortu zen.",
"account_managed_by_identity_provider": "Zure kontua {{provider}}-k kudeatzen du",
"account_managed_by_identity_provider_description": "Zure emaila, pasahitza aldatzeko, bi faktoreko autentifikazioa gaitzeko eta gehiagorako, joan zure {{provider}} kontuaren ezarpenetara.",
"account_managed_by_identity_provider_error": "Zure kontua beste identitate-hornitzaile batek kudeatzen du. Saiatu {{provider}} bidez sartzen.",
"user_creation_error": "Errorea erabiltzaile berria sortzean. Mesedez, saiatu berriro.",
"signin_with_google": "Hasi saioa Googlerekin",
"signin_with_saml": "Hasi saioa SAMLrekin",
"signin_with_saml_oidc": "Hasi saioa SAML/OIDCrekin",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Prest zaude!",
"install_zapier_app": "Mesedez, lehenik instalatu Zapier App-a app store-an.",
"install_make_app": "Mesedez, lehenik instalatu Make App-a app store-an.",
"app_installation": "Aplikazioaren instalazioa",
"app_not_installed": "Aplikazioa ez dago instalatuta",
"visit_our_app_store": "Barkatu, aplikazio hau ez dago instalatuta zure kontuan. Mesedez, bisitatu gure app store-a hau eta beste aplikazio bikain batzuk ezagutzeko.",
"connect_apple_server": "Konektatu Apple zerbitzarira",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "gertaera bertan behera geratzen denean",
"after_hosts_cal_video_no_show": "Ostalariak Cal bideora batu ez direnean",
"after_guests_cal_video_no_show": "Gonbidatuak Cal bideora batu ez direnean",
"join_video_call": "Batu bideo-deira",
"sign_in_to_cal_com": "Hasi saioa zure Cal.com kontuan",
"log_in_to_cal_com": "Hasi saioa Cal.com-en",
"track_your_meetings": "Jarraitu zure bilerak, jaso jakinarazpenak, eta kudeatu zure egutegia modu eraginkorragoan.",
"choose_how_you_d_like_to_join_call": "Aukeratu nola nahi duzun dei honetara batzea",
"new_event_trigger": "gertaera berri bat erreserbatzen denean",
"email_host_action": "bidali emaila anfitrioiari",
"email_attendee_action": "bidali emaila partaideei",
@@ -1361,6 +1380,8 @@
"custom": "Pertsonalizatua",
"reminder": "Gogorarazlea",
"rescheduled": "Berrantolatua",
"rescheduled_by": "Honek berrantolatua",
"original_booking": "Jatorrizko erreserba",
"completed": "Osatuta",
"rating": "Balorazioa",
"reminder_email": "Gogorarazpena: {{eventType}} {{name}}(r)ekin {{date}}(e)an",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "{{workflowName}} lan-fluxua arrakastaz {{offOn}}",
"download_responses": "Deskargatu erantzunak",
"download_responses_description": "Deskargatu zure formularioko erantzun guztiak CSV formatuan",
"view_responses": "Ikusi erantzunak",
"download": "Deskargatu",
"downloading": "Deskargatzen",
"download_recording": "Deskargatu grabaketa",
"transcription_enabled": "Transkripzioak aktibatuta daude orain",
"transcription_stopped": "Transkripzioak gelditu dira orain",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Gehitu inprimaki berria zure taldeari",
"create_your_first_route": "Sortu zure lehen bideratzea",
"route_to_the_right_person": "Bideratu pertsona egokiarengana inprimakiaren erantzunen arabera",
"form": "Inprimakia",
"form_description": "Sortu zure inprimakia erreserbatzailea bideratzeko",
"copy_link_to_form": "Kopiatu inprimakiaren esteka",
"theme": "Erreserba orriaren itxura",
@@ -1862,6 +1886,8 @@
"wrong_code": "Egiaztapen kode okerra",
"not_verified": "Oraindik egiaztatu gabe",
"no_availability_in_month": "Ez dago erabilgarritasunik {{month}} hilabetean",
"no_availability_rolling": "Programazioa {{days}} egun aurretik bakarrik dago eskuragarri. Mesedez, begiratu berriro laster.",
"no_availability_range": "Hitzorduak {{date}} datan amaitu ziren. Mesedez, begiratu berriro laster.",
"view_previous_month": "Ikusi aurreko hilabetea",
"view_next_month": "Ikusi hurrengo hilabetea",
"send_code": "Bidali kodea",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Ezin da ekitaldi honengatik ordaindu",
"booking_with_payment_cancelled_already_paid": "Erreserba honen ordainketaren itzulketa bidean dago.",
"booking_with_payment_cancelled_refunded": "Erreserba honen ordainketa itzuli da.",
"booking_with_payment_cancelled_no_refund": "Ekitaldiaren itzulketa-politikaren arabera, erreserba ordainketa ez da itzulgarria.",
"booking_with_payment_cancelled_refund_window_expired": "Ekitaldiaren itzulketa-leihoa iraungi da. Beraz, erreserba ordainketa ez da itzulgarria.",
"booking_confirmation_failed": "Erreserba berrespena huts egin du",
"not_enough_seats": "Ez dago nahikoa eserleku",
"form_builder_field_already_exists": "Izen hori duen eremu bat existitzen da dagoeneko",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Open users availability",
"organization_no_slots_notification_switch_title": "Jaso jakinarazpenak zure taldeak eskuragarritasunik ez duenean",
"organization_no_slots_notification_switch_description": "Administratzaileek mezu elektronikoak jasoko dituzte erabiltzaile batek taldekide bat erreserbatu nahi duenean eta 'Ez dago eskuragarritasunik' mezua agertzen denean. Mezu hau bi aldiz gertatu ondoren bidaltzen dugu eta 7 egunero gogorarazten dizugu erabiltzaile bakoitzeko.",
"organization_disable_phone_only_sms_notifications_switch_title": "Desgaitu SMS jakinarazpenak telefono-zenbaki soileko ekitaldi-motetan",
"organization_disable_phone_only_sms_notifications_switch_description": "Desgaitu SMS jakinarazpen automatikoak telefono zenbakia soilik (attendeePhoneNumber) beharrezko galdera gisa duten ekitaldi-motetan, posta elektronikoa aukerakoa edo ez beharrezkoa izanik",
"email_team_invite|subject|added_to_org": "{{user}} added you to the organization {{team}} on {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} invited you to join the organization {{team}} on {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} added you to the team {{team}} of organization {{parentTeamName}} on {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Zure esteka {{a0}}-tik {{a1}}-ra aldatu da, baina ez kezkatu, aurreko esteka guztiek funtzionatzen jarraitzen dute eta behar bezala birbideratzen dira. <br /><br />Kontuan izan: Zure gertaera mota pertsonal guztiak <strong>{{teamName}}</strong> erakundera mugitu dira, eta horrek esteka pertsonal posibleak ere barne har ditzake.<br /><br />Mesedez, hasi saioa eta ziurtatu ez duzula gertaera pribaturik zure erakundeko kontu berrian.<br /><br />Gertaera pertsonaletarako, helbide elektroniko pertsonal batekin kontu berri bat sortzea gomendatzen dugu.<br /><br />Gozatu zure esteka garbi berriaz: {{a2}}",
"email_organization_created|subject": "Zure erakundea sortu da",
"your_current_plan": "Zure oraingo plana",
"organization_price_per_user_month": "37$ erabiltzaile bakoitzeko hilabetean (gutxienez 30 erabiltzaile)",
"organization_price_per_user_month": "37$ erabiltzaile bakoitzeko hilabetero",
"privacy_organization_description": "Kudeatu zure erakundearen pribatutasun-ezarpenak",
"privacy": "Pribatutasuna",
"team_will_be_under_org": "Talde berriak zure erakundearen barruan egongo dira",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Jarraituz gero, gure honekin ados zaudela adierazten duzu",
"terms": "Baldintzak",
"always_show_x_days": "Beti {{x}} egun erabilgarri",
"team_subscription_cancelled_successfully": "Taldearen harpidetza behar bezala ezeztatu da",
"team_subscription_cancellation_error": "Errorea gertatu da taldearen harpidetza ezeztatzean",
"unable_to_subscribe_to_the_platform": "Errore bat gertatu da plataformaren planera harpidetzen saiatzean, saiatu berriro geroago",
"updating_oauth_client_error": "Errore bat gertatu da OAuth bezeroa eguneratzean, saiatu berriro geroago",
"creating_oauth_client_error": "Errore bat gertatu da OAuth bezeroa sortzean, saiatu berriro geroago",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Saltatu {{entry}} erregistroa sortzea Salesforce-n ez badago",
"salesforce_if_account_does_not_exist": "Kontaktua ez badago kontu baten azpian, sortu lead berria parte-hartzailearekin",
"salesforce_create_new_contact_under_account": "Sortu kontaktu berria kontu baten azpian parte-hartzailearen email domeinuan eta existitzen diren kontaktuetan oinarrituta",
"salesforce_change_record_owner_on_booking": "Aldatu erregistroaren jabea erreserban",
"mass_assign_attributes": "Masiboki esleitu atributuak",
"reroute_preview_custom_message": "Mezu pertsonalizatua erakusten du. Saiatu erantzuna aldatzen gertaera batera bideratzeko",
"reroute_preview_external_redirect": "{{externalUrl}}-ra birbideratzen du. Saiatu erantzuna aldatzen gertaera batera bideratzeko",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Epealdi bakoitzeko birbideratutakoak",
"per_day": "Eguneko",
"per_week": "Asteko",
"per_month": "Hileko",
"per_month": "hilabeteko",
"routing_form_insights_assignment_reason": "Esleitzeko arrazoia",
"access_denied": "Sarbidea ukatuta",
"salesforce_route_to_owner": "Kontaktuaren jabea Round Robin ostalaria izango da posible bada",
"salesforce_add_attendees_as": "Gehitu parte-hartzaile berriak honela",
"salesforce_do_not_route_to_owner": "Kontaktuaren jabea ez da behartuko (ostalaria izan daiteke atributuak eta Round Robin irizpideak betetzen baditu)",
"salesforce_route_to_custom_lookup_field": "Kontu bateko bilaketa eremua betetzen duen erabiltzaile batengana bideratu",
"salesforce_option": "Salesforce aukera",
@@ -2927,6 +2961,7 @@
"shortfall": "Gabezia",
"routing_form": "Bideratze-formularioa",
"go_back_and_save": "Itzuli eta gorde",
"save_changes": "Gorde aldaketak",
"leave_without_saving": "Irten gorde gabe",
"leave_without_saving_description": "Ziur zaude bideratzeko inprimakian egindako aldaketak gorde gabe irten nahi duzula?",
"something_unexpected_occurred": "Ustekabeko zerbait gertatu da",
@@ -2961,6 +2996,9 @@
"authorize": "Baimendu",
"next": "Hurrengoa",
"hide": "Ezkutatu",
"show": "Erakutsi",
"utm_params": "UTM parametroak",
"no_utm_params": "Ez dago UTM parametrorik eskuragarri.",
"asc": "Gorantz",
"desc": "Beherantz",
"verify_email_change": "Egiaztatu posta elektronikoaren aldaketa",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Argitaratutako gutxieneko talde kopurua izan behar duzu",
"you_are_part_of_this_organization_already": "Dagoeneko erakunde honen parte zara",
"you_are_part_of_another_organization_cannot_create_organization": "Beste erakunde baten parte zara, ezin duzu erakunde berri bat sortu",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Beste plataforma-erakunde baten parte zara, ezin duzu erakunde berri bat sortu",
"organization_payment_success": "Erakundearen ordainketa arrakastatsua",
"organization_payment_success_description": "Zure erakundea arrakastaz sortu da",
"this_may_take_a_few_seconds": "Honek segundo batzuk har ditzake...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Erakundearen hasierako prozesua dagoeneko amaituta dago",
"organization_onboarding_already_exists": "Erakundearen hasierako prozesua dagoeneko existitzen da",
"organization_onboarding_not_found": "Erakundearen hasierako prozesua ez da aurkitu",
"payment_successful": "Ordainketa arrakastatsua",
"payment_successful": "Ordainketa arrakastatsua!",
"handover_onboarding_page_title": "Hasierako prozesuaren eskualdaketa",
"handover_onboarding_page_description": "Hasierako prozesua erabiltzaileari eskualdatu",
"organization_already_exists_with_this_slug": "Erakunde bat dagoeneko existitzen da slug honekin",
@@ -3019,9 +3058,12 @@
"link": "Esteka",
"rows_per_page": "errenkada orrialdeko",
"pagination_status": "{{currentRange}} / {{totalItems}}",
"tip_username_plus": "Aholkua: '+' bat jar dezakezu erabiltzaile-izenen artean: cal.com/anna+brian talde-bilera dinamiko bat sortzeko",
"tip_username_plus": "Aholkua: '+' bat gehitu dezakezu erabiltzaile-izenen artean: cal.com/anna+brian talde-bilera dinamiko bat sortzeko",
"user_has_no_team_yet": "Oraindik ez duzu talderik",
"no_team_members": "Oraindik ez dituzu taldekiderik",
"recurring_event_doesnt_support_seats": "Ekitaldi errepikakorrak ez du eserlekuen ezaugarria onartzen. Ez-errepikakor bihurtu eserlekuak gaitzeko.",
"seats_doesnt_support_recurring": "Eserlekuen ezaugarriak ez du ekitaldi errepikakorrik onartzen. Desgaitu eserlekuen ezaugarria errepikakor egiteko.",
"recurring_event_seats_error": "Ekitaldi errepikakorrak ez du eserlekuen ezaugarria onartzen. Desgaitu eserlekuen ezaugarria edo egin ekitaldia ez-errepikakor.",
"segment": "Segmentua",
"rename": "Berrizendatu",
"rename_segment": "Berrizendatu segmentua",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Bertan behera utzitako erreserba gehienak",
"name_or_email": "Izena edo helbide elektronikoa",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Kontakturik aurkitzen ez bada, itzuli bezeroen arduradunera existitzen bada",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Gehitu zure kate berriak honen gainean ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Data eta ordua",
"email_reminder_upcoming_event_notice" : "Hau zure hurrengo ekitaldiari buruzko abisua da.",
"email_reminder_triggered_by_workflow" : "Abisu hau Cal-eko lan-fluxu batek abiarazi zuen.",
"enable_delegation_credential": "Gaitu eskuordetze kredentzialak",
"enable_delegation_credential_description": "Eman Cal.com-i erakundeko kide guztien egutegietarako sarbide automatikoa eskuordetze kredentzialak gaituz.",
"disable_delegation_credential": "Desgaitu eskuordetze kredentzialak",
"disable_delegation_credential_description": "Eskuordetze kredentzialak desgaitzen direnean, beren egutegiak konektatu ez dituzten erakundeko kideek eskuz egin beharko dute.",
"last_active": "Azken aldiz aktibo",
"member_since": "Kide noiztik",
"last_updated": "Azken eguneratzea",
"salesforce_on_cancel_write_to_event": "Erreserba bertan behera uztean, idatzi gertaera erregistroan gertaera ezabatu beharrean",
"salesforce_on_every_cancellation": "Bertan behera uzte bakoitzean",
"report_issue": "Arazoa jakinarazi",
"report_issue_description": "GitHub-en ticket bat bidali dezakezu edo zure plana eguneratu denbora errealeko laguntza eta garatzaile-konferentziak jasotzeko",
"open_issue": "Ireki arazoa",
"this_is_your_current_plan": "Hau da zure oraingo plana",
"schedule_a_time": "Programatu ordua",
"this_includes": "Honek barne hartzen du:",
"oauth_client_updated_successfully": "OAuth bezeroa ondo eguneratu da",
"oauth_client_not_found": "OAuth bezeroa ez da aurkitu.",
"subscribe_to_platform": "Harpidetu plataformara",
"error_accessing_webhooks": "Errorea webhook-ak atzitzean.",
"webhook_update_failed": "Webhook-a eguneratzeak huts egin du.",
"webhook_create_failed": "Webhook-a sortzeak huts egin du.",
"invalid_link": "Esteka baliogabea",
"currently_subscribed_to_plan": "Une honetan {{planFirstLetter}}{{planRest}} planaren harpideduna zara",
"user_team": "Erabiltzailea/Taldea",
"client_id_copied": "Bezeroaren IDa kopiatu da!",
"client_secret_copied": "Bezeroaren sekretua kopiatu da!",
"maintenance_message": "Cal.com taldea programatutako mantentze-lanak egiten ari da. Galderarik baduzu, jarri harremanetan laguntzarekin.",
"your_payment_failed": "Zure ordainketak huts egin du",
"check_your_inbox": "Begiratu zure sarrera-ontzia",
"account_created_premium_not_reserved": "Zure kontua sortu da, baina zure premium ez da erreserbatu.",
"email_sent_with_activation_link": "Mezu elektroniko bat bidali dugu {{email}} helbidera zure kontua aktibatzeko esteka batekin.",
"activate_account_to_purchase_username": "Behin zure kontua aktibatuta, zure premium erabiltzaile-izena berriro erosten saiatu ahal izango zara edo beste bat hautatu.",
"open_in_gmail": "Ireki Gmail-en",
"dont_see_email": "Ez duzu mezurik ikusten?",
"resend_in_seconds": "Berriz bidali {{seconds}} segundotan",
"resend": "Berriz bidali",
"verification_email_sent": "Egiaztapen mezua bidali da",
"select_all_members": "Hautatu kide guztiak",
"select_all_members_tooltip": "Kide guztiak hautatzean, etorkizuneko taldekide guztiak gehituko dira taldera gehitzen direnean.",
"form_settings": "Inprimaki ezarpenak",
"remove_whitelist_status": "Kendu zerrenda zuriaren egoera",
"whitelist_user_workflows": "Zerrenda zurian sartu erabiltzaile-fluxuak",
"user_workflows_whitelisted": "Erabiltzaile-fluxuak zerrenda zurian daude",
"user_workflows_unwhitelisted": "Erabiltzaile-fluxuak zerrenda zuritik kendu dira",
"date_and_time": "Data eta ordua",
"email_reminder_upcoming_event_notice": "Hau zure hurrengo ekitaldiari buruzko abisua da.",
"email_reminder_triggered_by_workflow": "Abisu hau Cal-eko lan-fluxu batek abiarazi zuen.",
"event_upper_case": "Gertaera",
"scheduling_by": "Antolatzailea",
"experience_review_prompt": "Zein izan da zure azken esperientzia?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Zenbat pozik zaude azken bilerarekin?",
"meeting_not_joined_question": "ez zenuen bileran parte hartu?",
"reschedule_cta_short": "Berriz programatu hemen.",
"hide_organizer_email": "Ezkutatu antolatzailearen helbide elektronikoa",
"platform_customer_cant_create_organization": "Dagoeneko plataforma-erakunde bateko kide zarenez, ezin duzu erakunde berri bat sortu. Erabiltzaile bakoitza erakunde bakar batekoa izan daiteke. Mesedez, sortu cal.com kontu berri bat beste helbide elektroniko batekin eta erabili kontu hori erakundeen planera harpidetzeko.",
"organization_customer_cant_create_platform": "Dagoeneko erakunde bateko kide zarenez, ezin duzu plataforma-erakunde bat sortu. Erabiltzaile bakoitza erakunde bakar batekoa izan daiteke. Mesedez, sortu cal.com kontu berri bat beste helbide elektroniko batekin eta erabili kontu hori plataforma-planera harpidetzeko.",
"hide_organizer_email_description": "Ezkutatu antolatzailearen helbide elektronikoa erreserba pantailatik, mezu elektronikoetatik eta egutegiko ekitaldietatik",
"you_and_conjunction": "Zu &",
"email_survey_triggered_by_workflow": "Galdeketa hau Cal-eko Workflow baten bidez aktibatu da."
"select_verified_email": "Hautatu egiaztatutako helbide elektronikoa",
"custom_reply_to_email_title": "'Erantzun' helbide elektroniko pertsonalizatua",
"custom_reply_to_email_description": "Erabili beste helbide elektroniko bat baieztapen mezuen erantzun-helbide gisa antolatzailearen helbidearen ordez",
"email_survey_triggered_by_workflow": "Galdeketa hau Cal-eko Workflow baten bidez aktibatu da.",
"skip_trial": "Saltatu proba aldia",
"team_trials_skipped_successfully": "Taldeen probak arrakastaz saltatu dira",
"sms_workflow_consent": "Zure telefono zenbakia sartuz, ekitaldi honetarako SMS mezuak jasotzeko baimena ematen duzu. SMS tarifak aplika daitezke.",
"routing_preview_more_info_found_insights": "Informazio gehiago <0>Bideratze Estatistiketan</0> aurki daiteke",
"results": "Emaitzak",
"view_form": "Formularioa Ikusi",
"sms_opt_out_message": "Bidali STOP SMS mezuetatik baja emateko",
"routing_form_next_in_queue": "{{count}} hurrengo ilaran",
"routing_form_select_members_to_email": "Bidali posta elektroniko erantzunak honi",
"routing_incomplete_booking_tab": "Osatu gabeko Erreserbak",
"include_no_show_in_rr_calculation": "Sartu ez agertzeko erreserbak round robin kalkuluetan",
"matching": "Bat egitea",
"event_redirect": "Gertaera Birbideratzea",
"reset_form": "Formularioa Berrezarri",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Gehitu zure kate berriak honen gainean ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
+115 -8
View File
@@ -620,6 +620,7 @@
"your_full_name": "Koko nimesi",
"no_name": "Ei nimeä",
"enter_number_between_range": "Anna numero väliltä 1-{{maxOccurences}}",
"continue_as_guest_description": "Nopeaa ja helppoa - tiliä ei tarvita. Täydellinen kertaluontoisiin tapaamisiin.",
"email_address": "Sähköpostiosoite",
"enter_valid_email": "Anna kelvollinen sähköpostiosoite",
"please_schedule_future_call": "Varaa uusi aika, jos emme ole tavoitettavissa {{seconds}} sekunnin kuluessa",
@@ -629,6 +630,7 @@
"in_person_attendee_address": "Läsnä (osallistujan osoite)",
"somewhere_else": "Jossain muualla",
"custom_attendee_location": "Mukautettu osallistujan sijainti",
"continue_as_guest": "Jatka vieraana",
"any_location": "Mikä tahansa sijainti",
"yes": "Kyllä",
"no": "Ei",
@@ -670,9 +672,14 @@
"team_updated_successfully": "Tiimi päivitetty onnistuneesti",
"your_team_updated_successfully": "Tiimisi on päivitetty onnistuneesti.",
"your_org_updated_successfully": "Organisaatiosi on päivitetty onnistuneesti.",
"error_copying_to_clipboard": "Virhe kopioitaessa leikepöydälle",
"about": "Tietoja",
"team_description": "Muutama lause tiimistäsi. Tämä näkyy tiimisi URL-sivulla.",
"organization_id": "Organisaation tunnus",
"organization_id_copied": "Organisaation tunnus kopioitu.",
"org_description": "Muutama lause organisaatiostasi. Tämä näkyy organisaatiosi URL-sivulla.",
"team_id": "Tiimin tunnus",
"team_id_copied": "Tiimin tunnus kopioitu.",
"members": "Jäsenet",
"organization_members": "Organisaation jäsenet",
"member": "Jäsen",
@@ -720,6 +727,9 @@
"remove_member_confirmation_message": "Haluatko varmasti poistaa tämän jäsenen tiimistä?",
"confirm_disband_team": "Kyllä, hajota tiimi",
"confirm_remove_member": "Kyllä, poista jäsen",
"confirm_subscription_cancellation": "Kyllä, peruuta tilaus",
"cancel_subscription": "Peruuta tilaus",
"cancel_subscription_description": "Tilauksen peruuttaminen poistaa nykyisen suunnitelmasi pysyvästi käytöstä. Tätä toimintoa ei voi kumota.",
"remove_member": "Poista jäsen",
"manage_your_team": "Hallinnoi tiimiäsi",
"no_teams": "Sinulla ei ole vielä yhtään tiimiä.",
@@ -838,6 +848,7 @@
"booking_redirect_uri": "Varaussivusi URL-osoite",
"booking_cancel_redirect_uri": "Varauksen peruutussivun URL-osoite",
"booking_reschedule_redirect_uri": "Varauksen uudelleenajoitussivun URL-osoite",
"booking_conflict_error": "Tämä aika ei ole enää saatavilla. Palaa edelliselle sivulle ja valitse toinen aika.",
"open_invitations": "Avoimet kutsut",
"new_team": "Uusi tiimi",
"create_first_team_and_invite_others": "Luo ensimmäinen tiimisi ja kutsu muita käyttäjiä yhteistyöhön",
@@ -1019,6 +1030,8 @@
"account_created_with_identity_provider": "Tilisi luotiin käyttäen identiteetintarjoajaa.",
"account_managed_by_identity_provider": "Tiliäsi hallinnoi {{provider}}",
"account_managed_by_identity_provider_description": "Muuttaaksesi sähköpostiosoitettasi, salasanaasi, ottaaksesi käyttöön kaksivaiheisen tunnistautumisen ja muuta, käy {{provider}}-tilisi asetuksissa.",
"account_managed_by_identity_provider_error": "Tiliäsi hallinnoi eri identiteetintarjoaja. Yritä kirjautua sisään palvelulla {{provider}}.",
"user_creation_error": "Virhe uuden käyttäjän luomisessa. Yritä uudelleen.",
"signin_with_google": "Kirjaudu Google-tilillä",
"signin_with_saml": "Kirjaudu SAML-tunnuksilla",
"signin_with_saml_oidc": "Kirjaudu SAML/OIDC-tunnuksilla",
@@ -1234,6 +1247,7 @@
"make_setup_instructions_6": "Kaikki on valmista!",
"install_zapier_app": "Asenna ensin Zapier-sovellus sovelluskaupasta",
"install_make_app": "Asenna ensin Make-sovellus sovelluskaupasta",
"app_installation": "Sovelluksen asennus",
"app_not_installed": "Sovellusta ei ole asennettu",
"visit_our_app_store": "Pahoittelut, tätä sovellusta ei ole asennettu tilillesi. Tutustu sovelluskauppaamme löytääksesi tämän ja muita hyödyllisiä sovelluksia",
"connect_apple_server": "Yhdistä Apple-palvelimeen",
@@ -1285,6 +1299,11 @@
"event_cancelled_trigger": "kun tapahtuma perutaan",
"after_hosts_cal_video_no_show": "Kun järjestäjät eivät liittyneet cal-videoon",
"after_guests_cal_video_no_show": "Kun vieraat eivät liittyneet cal-videoon",
"join_video_call": "Liity videopuheluun",
"sign_in_to_cal_com": "Kirjaudu Cal.com-tilillesi",
"log_in_to_cal_com": "Kirjaudu Cal.comiin",
"track_your_meetings": "Seuraa tapaamisiasi, saa ilmoituksia ja hallitse aikatauluasi tehokkaammin.",
"choose_how_you_d_like_to_join_call": "Valitse, miten haluat liittyä tähän puheluun",
"new_event_trigger": "kun uusi tapahtuma varataan",
"email_host_action": "lähetä sähköposti järjestäjälle",
"email_attendee_action": "lähetä sähköposti osallistujille",
@@ -1361,6 +1380,8 @@
"custom": "Mukautettu",
"reminder": "Muistutus",
"rescheduled": "Uudelleenajoitettu",
"rescheduled_by": "Uudelleenajoittaja",
"original_booking": "Alkuperäinen varaus",
"completed": "Valmis",
"rating": "Arvostelu",
"reminder_email": "Muistutus: {{eventType}} henkilön {{name}} kanssa {{date}}",
@@ -1552,7 +1573,9 @@
"workflow_turned_on_successfully": "{{workflowName}}-työnkulku {{offOn}} onnistuneesti",
"download_responses": "Lataa vastaukset",
"download_responses_description": "Lataa kaikki lomakkeen vastaukset CSV-muodossa",
"view_responses": "Näytä vastaukset",
"download": "Lataa",
"downloading": "Ladataan",
"download_recording": "Lataa tallenne",
"transcription_enabled": "Litterointi on nyt käytössä",
"transcription_stopped": "Litterointi on nyt pysäytetty",
@@ -1621,6 +1644,7 @@
"add_new_team_form": "Lisää uusi lomake tiimillesi",
"create_your_first_route": "Luo ensimmäinen reittisi",
"route_to_the_right_person": "Ohjaa oikealle henkilölle lomakkeen vastausten perusteella",
"form": "Lomake",
"form_description": "Luo lomake varaajan ohjaamiseksi",
"copy_link_to_form": "Kopioi lomakkeen linkki",
"theme": "Varaussivun teema",
@@ -1862,6 +1886,8 @@
"wrong_code": "Väärä vahvistuskoodi",
"not_verified": "Ei vielä vahvistettu",
"no_availability_in_month": "Ei vapaita aikoja {{month}}",
"no_availability_rolling": "Ajanvaraus on mahdollista vain {{days}} päivää eteenpäin. Tarkista pian uudelleen.",
"no_availability_range": "Ajanvaraus päättyi {{date}}. Tarkista pian uudelleen.",
"view_previous_month": "Näytä edellinen kuukausi",
"view_next_month": "Näytä seuraava kuukausi",
"send_code": "Lähetä koodi",
@@ -1981,6 +2007,8 @@
"booking_with_payment_cancelled": "Tämän tapahtuman maksaminen ei ole enää mahdollista",
"booking_with_payment_cancelled_already_paid": "Varauksen maksu palautetaan pian.",
"booking_with_payment_cancelled_refunded": "Tämän varauksen maksu on palautettu.",
"booking_with_payment_cancelled_no_refund": "Tapahtuman palautuskäytännön mukaisesti varausmaksu ei ole palautettavissa.",
"booking_with_payment_cancelled_refund_window_expired": "Tapahtuman palautusaika on umpeutunut. Siksi varausmaksua ei palauteta.",
"booking_confirmation_failed": "Varauksen vahvistaminen epäonnistui",
"not_enough_seats": "Ei tarpeeksi paikkoja",
"form_builder_field_already_exists": "Tämänniminen kenttä on jo olemassa",
@@ -2551,6 +2579,8 @@
"org_admin_no_slots|cta": "Open users availability",
"organization_no_slots_notification_switch_title": "Vastaanota ilmoituksia, kun tiimilläsi ei ole saatavuutta",
"organization_no_slots_notification_switch_description": "Ylläpitäjät saavat sähköposti-ilmoituksen, kun käyttäjä yrittää varata tiimin jäsenen aikaa ja kohtaa 'Ei saatavilla' -tilanteen. Lähetämme tämän sähköpostin kahden tapauksen jälkeen ja muistutamme siitä 7 päivän välein per käyttäjä.",
"organization_disable_phone_only_sms_notifications_switch_title": "Poista tekstiviesti-ilmoitukset käytöstä vain puhelinnumeroa käyttävissä tapahtumatyypeissä",
"organization_disable_phone_only_sms_notifications_switch_description": "Poista käytöstä automaattiset tekstiviesti-ilmoitukset tapahtumatyypeissä, joissa vain puhelinnumero (attendeePhoneNumber) on pakollinen kysymys ja sähköposti on valinnainen tai ei pakollinen",
"email_team_invite|subject|added_to_org": "{{user}} added you to the organization {{team}} on {{appName}}",
"email_team_invite|subject|invited_to_org": "{{user}} invited you to join the organization {{team}} on {{appName}}",
"email_team_invite|subject|added_to_subteam": "{{user}} added you to the team {{team}} of organization {{parentTeamName}} on {{appName}}",
@@ -2570,7 +2600,7 @@
"email|existing_user_added_link_changed": "Linkkisi on muutettu osoitteesta {{a0}} osoitteeseen {{a1}}, mutta älä huoli, kaikki aiemmat linkit toimivat edelleen ja ohjaavat asianmukaisesti. <br /><br />Huomaa: Kaikki henkilökohtaiset tapahtumatyyppisi on siirretty <strong>{{teamName}}</strong> -organisaatioon, mikä saattaa sisältää myös mahdollisen henkilökohtaisen linkin.<br /><br />Kirjaudu sisään ja varmista, ettei uudella organisaatiotiililläsi ole yksityisiä tapahtumia.<br /><br />Henkilökohtaisia tapahtumia varten suosittelemme luomaan uuden tilin henkilökohtaisella sähköpostiosoitteella.<br /><br />Nauti uudesta selkeästä linkistäsi: {{a2}}",
"email_organization_created|subject": "Organisaatiosi on luotu",
"your_current_plan": "Nykyinen tilauksesi",
"organization_price_per_user_month": "37 $ käyttäjää kohden kuukaudessa (vähintään 30 käyttäjää)",
"organization_price_per_user_month": "37 $ käyttäjää kohti kuukaudessa",
"privacy_organization_description": "Hallitse organisaatiosi yksityisyysasetuksia",
"privacy": "Yksityisyys",
"team_will_be_under_org": "Uudet tiimit tulevat olemaan organisaatiosi alla",
@@ -2666,6 +2696,8 @@
"proceeding_agreement": "Jatkamalla hyväksyt meidän",
"terms": "Käyttöehdot",
"always_show_x_days": "Aina {{x}} päivää saatavilla",
"team_subscription_cancelled_successfully": "Tiimin tilaus peruutettu onnistuneesti",
"team_subscription_cancellation_error": "Virhe tiimin tilauksen peruuttamisessa",
"unable_to_subscribe_to_the_platform": "Tilausta alustaan ei voitu tehdä, yritä myöhemmin uudelleen",
"updating_oauth_client_error": "OAuth-asiakkaan päivityksessä tapahtui virhe, yritä myöhemmin uudelleen",
"creating_oauth_client_error": "OAuth-asiakkaan luonnissa tapahtui virhe, yritä myöhemmin uudelleen",
@@ -2769,6 +2801,7 @@
"salesforce_skip_entry_creation": "Ohita {{entry}}-tietueen luominen, jos sitä ei ole Salesforcessa",
"salesforce_if_account_does_not_exist": "Jos yhteyshenkilöä ei ole tilin alla, luo uusi liidi osallistujasta",
"salesforce_create_new_contact_under_account": "Luo uusi yhteyshenkilö tilin alle osallistujan sähköpostin domainin ja olemassa olevien yhteyshenkilöiden perusteella",
"salesforce_change_record_owner_on_booking": "Vaihda tietueen omistaja varauksessa",
"mass_assign_attributes": "Määritä ominaisuudet massana",
"reroute_preview_custom_message": "Tämä näyttää mukautetun viestin. Kokeile muuttaa vastaus reitittämään tapahtumaan",
"reroute_preview_external_redirect": "Tämä uudelleenohjaa osoitteeseen {{externalUrl}}. Kokeile muuttaa vastaus reitittämään tapahtumaan",
@@ -2861,10 +2894,11 @@
"routed_to_per_period": "Reititetty kohteeseen ajanjaksolla",
"per_day": "Päivittäin",
"per_week": "Viikoittain",
"per_month": "Kuukausittain",
"per_month": "kuukaudessa",
"routing_form_insights_assignment_reason": "Kohdistamisen syy",
"access_denied": "Pääsy estetty",
"salesforce_route_to_owner": "Yhteyshenkilön omistajasta tulee Round Robin -isäntä, jos mahdollista",
"salesforce_add_attendees_as": "Lisää uudet osallistujat nimellä",
"salesforce_do_not_route_to_owner": "Yhteyshenkilön omistajaa ei pakoteta (voi silti olla isäntä, jos vastaa määritettyjä ominaisuuksia ja Round Robin -kriteerejä)",
"salesforce_route_to_custom_lookup_field": "Reititä käyttäjälle, joka vastaa tilin hakukenttää",
"salesforce_option": "Salesforce-asetus",
@@ -2927,6 +2961,7 @@
"shortfall": "Vajaus",
"routing_form": "Reitityskaavake",
"go_back_and_save": "Palaa takaisin ja tallenna",
"save_changes": "Tallenna muutokset",
"leave_without_saving": "Poistu tallentamatta",
"leave_without_saving_description": "Haluatko varmasti poistua tallentamatta muutoksia reitityslomaakkeeseesi?",
"something_unexpected_occurred": "Jotain odottamatonta tapahtui",
@@ -2961,6 +2996,9 @@
"authorize": "Valtuuta",
"next": "Seuraava",
"hide": "Piilota",
"show": "Näytä",
"utm_params": "UTM-parametrit",
"no_utm_params": "UTM-parametreja ei ole saatavilla.",
"asc": "Nouseva",
"desc": "Laskeva",
"verify_email_change": "Vahvista sähköpostin muutos",
@@ -2972,6 +3010,7 @@
"you_need_to_have_minimum_published_teams": "Sinulla täytyy olla vähimmäismäärä julkaistuja tiimejä",
"you_are_part_of_this_organization_already": "Olet jo osa tätä organisaatiota",
"you_are_part_of_another_organization_cannot_create_organization": "Olet osa toista organisaatiota, et voi luoda uutta organisaatiota",
"you_are_part_of_another_platform_organization_cannot_create_organization": "Olet osa toista alustaorganisaatiota, et voi luoda uutta organisaatiota",
"organization_payment_success": "Organisaation maksu onnistui",
"organization_payment_success_description": "Organisaatiosi on luotu onnistuneesti",
"this_may_take_a_few_seconds": "Tämä saattaa kestää muutaman sekunnin...",
@@ -2983,7 +3022,7 @@
"organization_onboarding_already_completed": "Organisaation perehdytys on jo suoritettu",
"organization_onboarding_already_exists": "Organisaation perehdytys on jo olemassa",
"organization_onboarding_not_found": "Organisaation perehdytystä ei löydy",
"payment_successful": "Maksu onnistui",
"payment_successful": "Maksu onnistui!",
"handover_onboarding_page_title": "Perehdytyksen luovutus",
"handover_onboarding_page_description": "Perehdytyksen luovutus käyttäjälle",
"organization_already_exists_with_this_slug": "Organisaatio on jo olemassa tällä verkko-osoitteella",
@@ -3022,6 +3061,9 @@
"tip_username_plus": "Vinkki: Voit lisätä '+'-merkin käyttäjänimien väliin: cal.com/anna+brian luodaksesi dynaamisen ryhmätapaamisen",
"user_has_no_team_yet": "Sinulla ei ole vielä tiimiä",
"no_team_members": "Sinulla ei ole vielä tiimin jäseniä",
"recurring_event_doesnt_support_seats": "Toistuva tapahtuma ei tue paikkaominaisuutta. Tee siitä ei-toistuva ottaaksesi paikat käyttöön.",
"seats_doesnt_support_recurring": "Paikkaominaisuus ei tue toistuvaa tapahtumaa. Poista paikkaominaisuus käytöstä tehdäksesi siitä toistuvan.",
"recurring_event_seats_error": "Toistuva tapahtuma ei tue paikkaominaisuutta. Poista paikkaominaisuus käytöstä tai tee tapahtumasta ei-toistuva.",
"segment": "Segmentti",
"rename": "Nimeä uudelleen",
"rename_segment": "Nimeä segmentti uudelleen",
@@ -3053,10 +3095,53 @@
"most_cancelled_bookings": "Eniten perutut varaukset",
"name_or_email": "Nimi tai sähköposti",
"salesforce_round_robin_skip_fallback_to_lead_owner": "Jos yhteyshenkilöä ei löydy, käytä liidin omistajaa, jos sellainen on olemassa",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Lisää uudet merkkijonot tämän yläpuolelle ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑",
"date_and_time" : "Päivämäärä ja aika",
"email_reminder_upcoming_event_notice" : "Tämä on muistutus tulevasta tapahtumastasi.",
"email_reminder_triggered_by_workflow" : "Tämän muistutuksen laukaisi Cal.",
"enable_delegation_credential": "Ota delegointitunniste käyttöön",
"enable_delegation_credential_description": "Myönnä Cal.comille automaattinen pääsy kaikkien organisaation jäsenten kalentereihin ottamalla delegointitunniste käyttöön.",
"disable_delegation_credential": "Poista delegointitunniste käytöstä",
"disable_delegation_credential_description": "Kun delegointitunniste on poistettu käytöstä, organisaation jäsenten, jotka eivät ole yhdistäneet kalentereitaan, on tehtävä se manuaalisesti.",
"last_active": "Viimeksi aktiivinen",
"member_since": "Jäsen alkaen",
"last_updated": "Viimeksi päivitetty",
"salesforce_on_cancel_write_to_event": "Peruutetun varauksen yhteydessä kirjoita tapahtuman tietueeseen tapahtuman poistamisen sijaan",
"salesforce_on_every_cancellation": "Jokaisessa peruutuksessa",
"report_issue": "Ilmoita ongelmasta",
"report_issue_description": "Voit lähettää tukipyynnön GitHubissa tai päivittää tilauksesi saadaksesi reaaliaikaista tukea kehittäjäkonferenssien kanssa",
"open_issue": "Avaa ongelma",
"this_is_your_current_plan": "Tämä on nykyinen tilauksesi",
"schedule_a_time": "Varaa aika",
"this_includes": "Tämä sisältää:",
"oauth_client_updated_successfully": "OAuth-asiakas päivitetty onnistuneesti",
"oauth_client_not_found": "OAuth-asiakasta ei löytynyt.",
"subscribe_to_platform": "Tilaa alusta",
"error_accessing_webhooks": "Virhe webhookien käytössä.",
"webhook_update_failed": "Webhookin päivitys epäonnistui.",
"webhook_create_failed": "Webhookin luonti epäonnistui.",
"invalid_link": "Virheellinen linkki",
"currently_subscribed_to_plan": "Olet tällä hetkellä tilannut {{planFirstLetter}}{{planRest}}-tilauksen",
"user_team": "Käyttäjä/Tiimi",
"client_id_copied": "Asiakas-ID kopioitu!",
"client_secret_copied": "Asiakassalaisuus kopioitu!",
"maintenance_message": "Cal.com-tiimi suorittaa suunniteltua huoltoa. Jos sinulla on kysyttävää, ota yhteyttä tukeen.",
"your_payment_failed": "Maksusi epäonnistui",
"check_your_inbox": "Tarkista saapuneet viestisi",
"account_created_premium_not_reserved": "Tilisi on luotu, mutta premium-käyttäjänimeä ei ole varattu.",
"email_sent_with_activation_link": "Olemme lähettäneet sähköpostin osoitteeseen {{email}} linkillä tilisi aktivoimiseksi.",
"activate_account_to_purchase_username": "Kun aktivoit tilisi, voit yrittää ostaa premium-käyttäjänimesi uudelleen tai valita toisen.",
"open_in_gmail": "Avaa Gmailissa",
"dont_see_email": "Etkö näe sähköpostia?",
"resend_in_seconds": "Lähetä uudelleen {{seconds}} sekunnin kuluttua",
"resend": "Lähetä uudelleen",
"verification_email_sent": "Vahvistussähköposti lähetetty",
"select_all_members": "Valitse kaikki jäsenet",
"select_all_members_tooltip": "Kaikkien jäsenten valinta lisää myös kaikki tulevat tiimin jäsenet, kun heidät lisätään tiimiin.",
"form_settings": "Lomakkeen asetukset",
"remove_whitelist_status": "Poista sallittujen listalta",
"whitelist_user_workflows": "Lisää käyttäjän työnkulut sallittujen listalle",
"user_workflows_whitelisted": "Käyttäjän työnkulut lisätty sallittujen listalle",
"user_workflows_unwhitelisted": "Käyttäjän työnkulut poistettu sallittujen listalta",
"date_and_time": "Päivämäärä ja aika",
"email_reminder_upcoming_event_notice": "Tämä on muistutus tulevasta tapahtumastasi.",
"email_reminder_triggered_by_workflow": "Tämän muistutuksen laukaisi Cal.",
"event_upper_case": "Tapahtuma",
"scheduling_by": "Aikatauluttaja",
"experience_review_prompt": "Minkälainen oli viimeisin kokemuksesi?",
@@ -3064,6 +3149,28 @@
"meeting_satisfaction_question": "Kuinka tyytyväinen olit viime kokoukseen?",
"meeting_not_joined_question": "et osallistunut kokoukseen?",
"reschedule_cta_short": "Uudelleenaikatauluta tästä.",
"hide_organizer_email": "Piilota järjestäjän sähköposti",
"platform_customer_cant_create_organization": "Olet jo osa alusta-organisaatiota, minkä vuoksi et voi luoda uutta organisaatiota. Jokainen käyttäjä voi kuulua vain yhteen organisaatioon. Luo uusi cal.com-tili eri sähköpostiosoitteella ja käytä sitä tiliä organisaatiosuunnitelman tilaamiseen.",
"organization_customer_cant_create_platform": "Olet jo osa organisaatiota, minkä vuoksi et voi luoda alusta-organisaatiota. Jokainen käyttäjä voi kuulua vain yhteen organisaatioon. Luo uusi cal.com-tili eri sähköpostiosoitteella ja käytä sitä tiliä alustasuunnitelman tilaamiseen.",
"hide_organizer_email_description": "Piilota järjestäjän sähköpostiosoite varausnäytöltä, sähköposti-ilmoituksista ja kalenteritapahtumista",
"you_and_conjunction": "Sinä &",
"email_survey_triggered_by_workflow": "Tämä kysely käynnistettiin Workflow-ohjelmalla Cal-palvelussa."
"select_verified_email": "Valitse vahvistettu sähköposti",
"custom_reply_to_email_title": "Mukautettu 'Vastaa'-sähköposti",
"custom_reply_to_email_description": "Käytä eri sähköpostiosoitetta vastausosoitteena vahvistussähköposteissa järjestäjän sähköpostin sijaan",
"email_survey_triggered_by_workflow": "Tämä kysely käynnistettiin Workflow-ohjelmalla Cal-palvelussa.",
"skip_trial": "Ohita kokeilujakso",
"team_trials_skipped_successfully": "Tiimin kokeilujaksot ohitettu onnistuneesti",
"sms_workflow_consent": "Antamalla puhelinnumerosi suostut vastaanottamaan tekstiviestejä tästä tapahtumasta. Tekstiviesteistä voidaan veloittaa operaattorin mukainen maksu.",
"routing_preview_more_info_found_insights": "Lisätietoja löytyy <0>Reitityksen tiedoista</0>",
"results": "Tulokset",
"view_form": "Näytä lomake",
"sms_opt_out_message": "Lähetä STOP peruuttaaksesi SMS-viestit",
"routing_form_next_in_queue": "{{count}} seuraavana jonossa",
"routing_form_select_members_to_email": "Lähetä sähköpostivastaukset henkilöille",
"routing_incomplete_booking_tab": "Keskeneräiset varaukset",
"include_no_show_in_rr_calculation": "Sisällytä no-show-varaukset round robin -laskelmiin",
"matching": "Vastaavuus",
"event_redirect": "Tapahtuman uudelleenohjaus",
"reset_form": "Nollaa lomake",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Lisää uudet merkkijonot tämän yläpuolelle ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}

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