Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code dc6c6c16c9 fix: gracefully handle missing identifier chip generator for custom objects
https://sonarly.com/issue/22439?type=bug

When a custom object (e.g., "deliverable") is referenced via a relation field, the UI crashes with an unhandled throw if no identifier chip generator exists for that object. The user sees the error on `/objects/projects` page when the table tries to render relation chips.

Fix: Restored the graceful fallback in `useRecordChipData` when an identifier chip generator is missing for an object.

The commit 98e199c01d ("Support Full Name as Record Text Identifier") replaced the previous graceful fallback with a hard `throw new Error(...)`. This causes a React crash whenever a custom object's chip generator is missing from the pre-computed map — which can happen when:
- A custom object's label identifier field is misconfigured
- Metadata store has objects loaded before their fields (localStorage race condition)
- A custom object's label identifier field was deleted

The fix restores the original pattern: when a chip generator is not found for an object, fall back to `generateDefaultRecordChipData()` which produces a reasonable chip using the record's `name` field. This utility already exists and is used by `useRelationFromManyFieldDisplay` and `useRelationToOneFieldDisplay` for the same purpose.

This matches the team's established pattern (see commit 6e7d2db58f by Charles Bochet: "Fix From Many relation for deleted notes crashing") where the approach is to gracefully degrade rather than crash when metadata is incomplete.
2026-04-07 13:29:14 +00:00
WeikoandGitHub 6e23ca35e6 Pagelayout backfill command standard app (#19380)
## Context
Due to the chosen strategy for "Reset to default" feature for page
layouts. Those overridable entities need to be associated to the
Standard app to work properly (there is no "Default" state for custom
entities). Until we find a better implementation, I'm changing the
backfill command to reflect that
2026-04-07 12:49:35 +00:00
96a242eb7d fix(messaging): create messageThread.subject field metadata + column in 1-21 backfill (#19394)
## Summary
- The 1-21 \`upgrade:1-21:backfill-message-thread-subject\` command
assumed the legacy \`sync-metadata\` flow would create the new
\`messageThread.subject\` field metadata and column on existing
workspaces. That sync was removed, so the column was never added and the
backfill silently skipped.
- The command now ensures the field exists by computing the standard
\`messageThread.subject\` flat field from the twenty-standard
application and running it through
\`WorkspaceMigrationValidateBuildAndRunService\` (same pattern used by
the page-layout / command-menu-item backfills). This creates both the
field metadata row and the workspace schema column.
- After ensuring the field, the existing \`UPDATE messageThread SET
subject = ...\` runs as before.

## Test plan
- [ ] On a workspace with no \`subject\` column on \`messageThread\`,
run \`yarn command:prod upgrade:1-21:backfill-message-thread-subject\`
and confirm:
  - the field metadata row is created in \`core.\"fieldMetadata\"\`
- the \`subject\` column is created on \`workspace_<id>.messageThread\`
  - existing message threads are backfilled from the most recent message
- [ ] Re-run on the same workspace and confirm it is a no-op (field
already exists, no rows to update)
- [ ] Run on a workspace that already has the column but \`NULL\`
subjects and confirm only the backfill runs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-04-07 14:42:20 +02:00
d97a1cfc27 i18n - docs translations (#19399)
Created by Github action

Co-authored-by: github-actions <[email protected]>
2026-04-07 14:39:30 +02:00
c844109ffc i18n - translations (#19398)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-07 14:35:24 +02:00
neo773andGitHub dd2a09576b Imap-smtp-caldav form fixes (#19392)
/closes #19273
2026-04-07 12:18:11 +00:00
martmullandGitHub fe07de63b0 Enterprise plan required for private app sharing (#19393)
## before

<img width="1512" height="696" alt="image"
src="https://github.com/user-attachments/assets/d57f398e-6ac3-4ce0-a54b-a23ae41b1890"
/>


## after

<img width="923" height="448" alt="image"
src="https://github.com/user-attachments/assets/f4fea42e-1019-4287-9302-42da143ee878"
/>
2026-04-07 12:17:59 +00:00
Paul RastoinandGitHub 1c9fc94c1f Workspace commands writes inupgradeMigration (#19379)
# Introduction
As for the instance commands we want to keep a track of what has been
run for the workspace commands
Note that the history will be updated only when the workspace command
has been run through the upgrade directly and not when run atomically

## What's next
Later we will use this history in order to determine the current
workspace's version and instance's version getting rid of the version in
database, that will be the last stone
2026-04-07 12:15:06 +00:00
d10ef156c1 i18n - translations (#19395)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-07 14:17:20 +02:00
nitinandGitHub d3ec64072b [AI] Improve AI System Prompt page layout and token display (#19391)
closes
https://discord.com/channels/1130383047699738754/1480982048050249900

<img width="1438" height="1315" alt="CleanShot 2026-04-07 at 17 02 09"
src="https://github.com/user-attachments/assets/43c5a16f-6dd0-49da-8138-a11a7476e612"
/>
2026-04-07 11:52:48 +00:00
EtienneandGitHub 1b14e7e1f1 Fix - Update package.json (#19390)
https://github.com/twentyhq/twenty/pull/19383#discussion_r3044330450
2026-04-07 11:44:23 +00:00
neo773andGitHub 6ad9566043 Add messaging upgrade command 1 21 (#19389)
```
[Nest] 50057  - 04/07/2026, 4:14:10 PM     LOG [WorkspaceIteratorService] Running on workspace 20202020-1c25-4d02-bf25-6aeccf7ea419 1/2
[Nest] 50057  - 04/07/2026, 4:14:10 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Migrated 5 connected accounts for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419
[Nest] 50057  - 04/07/2026, 4:14:10 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Migrated 6 message channels for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419
[Nest] 50057  - 04/07/2026, 4:14:10 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Migrated 6 calendar channels for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419
[Nest] 50057  - 04/07/2026, 4:14:10 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Migrated 5 message folders for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419
[Nest] 50057  - 04/07/2026, 4:14:10 PM     LOG [WorkspaceIteratorService] Running on workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db 2/2
[Nest] 50057  - 04/07/2026, 4:14:10 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Migrated 5 connected accounts for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 50057  - 04/07/2026, 4:14:11 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Migrated 4 message channels for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 50057  - 04/07/2026, 4:14:11 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Migrated 4 calendar channels for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 50057  - 04/07/2026, 4:14:11 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Migrated 10 message folders for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db
[Nest] 50057  - 04/07/2026, 4:14:11 PM     LOG [MigrateMessagingInfrastructureToMetadataCommand] Command completed!
```
2026-04-07 11:21:27 +00:00
Félix MalfaitandGitHub f39fccc3c4 fix(messaging): split thread create/update statements and stop clobbering accumulator (#19388)
## Summary

Fixes two bugs in
`MessagingMessageService.saveMessagesWithinTransaction`.

### Bug 1 — `ON CONFLICT DO UPDATE command cannot affect row a second
time`

Reported in production logs from `MessagingMessagesImportService`.
Postgres rejects a single `INSERT … ON CONFLICT DO UPDATE` when the same
conflict target appears twice in the values list, and that's exactly
what was happening to `messageThread`.

Where it came from: #19351 added the message-thread subject refresh
feature and, in doing so, switched the existing thread `insert` to a
bulk `upsert(['id'])` over a list built by concatenating two sources:

```ts
const threadsToUpsert = [
  ...messageThreadsToCreate,        // brand-new thread rows
  ...threadSubjectUpdates entries,  // subject refreshes for existing threads
];
await messageThreadRepository.upsert(threadsToUpsert, ['id'], txManager);
```

Each list is internally unique, but they are **not disjoint**.
`enrichMessageAccumulatorWithMessageThreadToCreate`, when it sees two
messages in the same batch sharing a brand-new thread external id,
copies the first sibling's freshly-minted thread id into the second
sibling's `existingThreadInDB`. The subject-update gate later in the
loop then trusts that field and queues a subject refresh for that id —
which is also already in `messageThreadsToCreate`. Same id, same
statement, two rows → Postgres aborts the transaction and the import
retries forever on the same batch.

**Fix:** stop merging the two lists. Issue creates and subject updates
as two separate statements within the same transaction:

```ts
if (messageThreadsToCreate.length > 0) {
  await messageThreadRepository.insert(messageThreadsToCreate, txManager);
}
if (threadSubjectUpdates.size > 0) {
  await messageThreadRepository.upsert(
    Array.from(threadSubjectUpdates.entries()).map(([id, { subject }]) => ({ id, subject })),
    ['id'],
    txManager,
  );
}
```

This is closer to the pre-#19351 shape (`insert` for new rows) and
side-steps the duplicate-row constraint entirely: each statement is
internally unique (creates use freshly minted UUIDs; updates are keyed
by a `Map<id, …>`), and within the same transaction Postgres happily
applies a subject update to a row inserted by a previous statement.

### Bug 2 —
`enrichMessageAccumulatorWithExistingMessageChannelMessageAssociations`
clobbers the accumulator

Independent latent bug spotted while tracing the flow. The helper did:

```ts
if (existingMessageChannelMessageAssociation) {
  messageAccumulatorMap.set(message.externalId, {
    existingMessageInDB: existingMessage,
    existingMessageChannelMessageAssociationInDB: existingMessageChannelMessageAssociation,
  });
}
```

i.e. it **replaces** the accumulator object, dropping the
`existingThreadInDB` set just before by
`enrichMessageAccumulatorWithExistingMessageThreadIds`.

The branch only fires when re-encountering a message that's already been
fully synced on this channel (matched on `headerMessageId` AND already
has an association row) — i.e. routinely on Gmail/IMAP incremental syncs
whenever the connector re-delivers an existing message (label change,
read/unread, archive, full-resync after error, …).

When it fires, the next enrichment step sees `existingThreadInDB` as
`undefined`, falls into the "create a new thread" branch, mints a fresh
`threadToCreate`, but the main loop never queues a `messageToCreate` or
association for it (because both `existingMessageInDB` and the existing
association are still set). Net effect: **one orphan `messageThread` row
inserted per re-encountered message, with nothing referencing it.**

The existing message in the DB keeps pointing at its real thread, so
this is invisible to users — no thread fragmentation, no UI symptoms, no
error logs. Just slow accumulation of orphan thread rows that no query
joins onto. Probably worth running

```sql
SELECT COUNT(*)
FROM "messageThread" mt
WHERE NOT EXISTS (
  SELECT 1 FROM message m WHERE m."messageThreadId" = mt.id
);
```

on a busy production workspace once this lands to size whether a cleanup
migration is warranted.

**Fix:** mutate the existing accumulator in place instead of replacing
it.

## Test plan

- [x] `oxlint --type-aware` clean on touched file
- [x] `prettier` clean

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-07 13:23:31 +02:00
EtienneandGitHub ac1ec91f25 Direct execution - Remove conditional schema (#19383) 2026-04-07 10:22:56 +00:00
Abdullah.andGitHub d324bbfc25 Styled illustrations for Hero, ThreeCards, Helped sections. (#19387)
This PR adds styles and animations to illustrations for Hero, ThreeCards
and Helped sections.
2026-04-07 10:17:32 +00:00
7c2a9abed4 fix: prevent NaN in health indicator calculations (#19378)
## Summary

Fixes #19377

- **Redis health**: The hit rate calculation divides by zero when both
`keyspace_hits` and `keyspace_misses` are `"0"` (common on fresh
instances). The string `"0"` is truthy so the guard
`statsData.keyspace_hits ? ...` doesn't catch this case, resulting in
`0/0 = NaN`. Fixed by computing the total first and checking it's a
valid non-zero number.
- **Database health**: The cache hit ratio query returns `null` when
`pg_statio_user_tables` is empty (no user tables). `parseFloat(null)` →
`NaN`. Fixed by adding a null check.

## Test plan

- [ ] Verify health indicators display correctly on a fresh instance
with no Redis keyspace activity
- [ ] Verify health indicators display correctly on a database with no
user tables
- [ ] Existing tests in `redis.health.spec.ts` still pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: easonysliu <[email protected]>
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: Charles Bochet <[email protected]>
2026-04-07 10:01:49 +00:00
c0c0cbb896 i18n - translations (#19382)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-07 11:50:21 +02:00
WeikoandGitHub a2188cb0eb Reset Fields widget implementation (#19283)
## Context
This PR implements the first steps for overridable entities resets.

<img width="1277" height="568" alt="Screenshot 2026-04-02 at 18 58 04"
src="https://github.com/user-attachments/assets/4c7f93b1-c453-4905-a919-cd6af11e0e16"
/>
2026-04-07 09:34:44 +00:00
Paul RastoinandGitHub 23874848a4 Instance commands and upgrade_migrations table (#19356)
# Introduction
Now only using typeorm to generate migrations up and down statement
We handle and maintain our own migration table history

## What's new
Now all the instance commands will live within the same module and
folder than the upgrade commands
Sequentiality comes from the timestamp located in the filename
Same sequentiality also applies to the workspace commands in the future,
for the moment still expected a as code explicit declaration

( below screen is an example see below section )
<img width="1382" height="634" alt="image"
src="https://github.com/user-attachments/assets/5610a246-4eae-485e-99f4-98fb89ad5ac8"
/>

## Existing 1.21 migrations
We won't start following this pattern in 1.21 yet at least not with the
migration that has already been released as typeorm migrations in cloud
production as they would rerun


## Small duplication
Duplicating the legacy typeorm and instance commands run in the
`run-instance-commands` to avoid any merge of interest for the moment

## Concurrency
Not handling any run in parrallel of the upgrade for the moment
2026-04-07 08:55:17 +00:00
b23d2b4e73 messaging post migration cleanup (#19365)
Co-authored-by: Charles Bochet <[email protected]>
2026-04-07 10:56:49 +02:00
Paul RastoinandGitHub 601dc02ed7 Fix s3 driver empty objects (#19361)
`undefined === 0` breaks the early return
2026-04-07 08:20:56 +00:00
Abdullah.andGitHub 2d552fc9fd Remove hover and scroll transitions from website. (#19369)
This PR removes hover and scroll transitions from the website. 

Per the conversation with Thomas, we should introduce them one by one
for each section.
2026-04-07 07:58:40 +00:00
f33ad53e72 chore: remove registeredCoreMigration (#19376)
Co-authored-by: Félix Malfait <[email protected]>
2026-04-07 10:02:07 +02:00
7053e1bbc5 fix: bypass permission checks in 1.21 backfill-message-thread-subject command (#19375)
## Summary
- `upgrade:1-21:backfill-message-thread-subject` was failing on every
workspace with `Method not allowed because permissions are not
implemented at datasource level`.
- The global workspace datasource gates raw `query()` calls behind
`shouldBypassPermissionChecks`. Both the column-existence probe and the
UPDATE in this command now pass that flag, matching the pattern used by
the other 1.20/1.21 upgrade commands.

## Test plan
- [ ] Re-run `yarn command:prod
upgrade:1-21:backfill-message-thread-subject` and confirm all workspaces
complete without the permissions error
- [ ] Spot-check a workspace to confirm `messageThread.subject` is
backfilled from the most recent message

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-04-07 09:59:30 +02:00
955aa9191f fix: unify settings layout prep when entering settings from outside (#19373)
## Summary

Clicking **Compose** in the emails tab without a connected account
redirects to the New Account settings page, but the settings nav drawer
was left in its previous (collapsed / "main") state — producing a
visibly half-broken transition.

### Root cause

The "enter settings" preparation (memorize previous URL + drawer state,
expand the desktop drawer, switch the mobile drawer to `'settings'`) was
duplicated **inline in three different places**:
- `NavigationDrawerOtherSection.handleSettingsClick`
- `MultiWorkspaceDropdownDefaultComponents` Settings link
- Implicitly expected (but missing) from every `useNavigateSettings`
caller

Every other entry point — `ComposeEmailButton`, `ComposeEmailCommand`,
`AIChatCreditsExhaustedMessage`, several workflow/role components — just
called `navigateSettings(...)` and skipped the prep entirely,
reproducing the bug.

### Fix

- Move the full prep into `useOpenSettingsMenu`, with a
`useIsSettingsPage()` short-circuit so internal navigation doesn't
clobber the memorized return target.
- `useNavigateSettings` delegates to `openSettingsMenu()` before
navigating — fixing every caller in one place.
- Collapse the duplicated inline logic in `NavigationDrawerOtherSection`
and `MultiWorkspaceDropdownDefaultComponents` to a single call.

Net **−9 lines**, single source of truth, no behavior change for the
existing happy paths.

## Test plan

- [x] \`nx typecheck twenty-front\` passes
- [x] \`oxlint\` + \`prettier\` clean on all 4 changed files
- [x] Existing \`useNavigateSettings\` tests pass (4/4)
- [ ] Manual: Compose button on a Person/Company/Opportunity emails tab
with no connected account → settings drawer renders fully expanded,
"Exit Settings" returns to the record
- [ ] Manual: "Settings" entry in the main nav drawer still works
(return path memorized)
- [ ] Manual: "Settings" entry in the multi-workspace dropdown still
works, and right-click → open in new tab still works (kept
\`UndecoratedLink\`)
- [ ] Manual: Navigating between settings pages does not overwrite the
memorized return URL

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-04-07 09:50:31 +02:00
3f87d27d5d fix: use AND instead of OR in neq filter for null-equivalent values (#19071)
Fixes #19070

The `neq` operator in `compute-where-condition-parts.ts` uses `OR` where
it should use `AND` when handling null-equivalent values.

Currently generates:
```sql
field != '' OR field IS NOT NULL
```

For a row where `field = ''`:
- `'' != ''` = false
- `'' IS NOT NULL` = true
- `false OR true` = true -- row incorrectly passes the filter

The `eq` operator correctly uses `OR field IS NULL` because it's
additive (match value or its null equivalent). By De Morgan's law, the
negation `neq` needs `AND field IS NOT NULL` -- exclude if the value
doesn't match AND is not a null equivalent.

With the fix:
```sql
field != '' AND field IS NOT NULL
```
- `'' != ''` = false, `'' IS NOT NULL` = true, `false AND true` = false
-- correctly excluded
- `NULL != ''` = NULL, `NULL IS NOT NULL` = false, `NULL AND false` =
false -- correctly excluded
- `'Alice' != ''` = true, `'Alice' IS NOT NULL` = true, `true AND true`
= true -- correctly included

Affects `neq` filters on TEXT fields and all composite sub-fields
(firstName, lastName, primaryEmail, primaryPhoneNumber, address
sub-fields, etc.) when filtering against null-equivalent values.

Co-authored-by: Etienne <[email protected]>
2026-04-07 07:36:41 +00:00
Abdullah.andGitHub 68cd2f6d61 fix: node-tar symlink path traversal via drive-relative linkpath (#19360)
Resolves [Dependabot Alert
619](https://github.com/twentyhq/twenty/security/dependabot/619) and
[Dependabot Alert
629](https://github.com/twentyhq/twenty/security/dependabot/629).
2026-04-07 07:15:55 +00:00
Abdullah.andGitHub 8c9228cb2b fix: SVGO DoS through entity expansion in DOCTYPE (#19359)
Resolves [Dependabot Alert
604](https://github.com/twentyhq/twenty/security/dependabot/604) and
[Dependabot Alert
605](https://github.com/twentyhq/twenty/security/dependabot/605).
2026-04-07 07:15:35 +00:00
Abdullah.andGitHub 35b76539cc fix: minimatch related dependabot alerts. (#19357)
Resolves [Dependabot Alert
491](https://github.com/twentyhq/twenty/security/dependabot/491).

Expecting it to resolve a few other minimatch generated alerts too, but
merging shall confirm which ones since minimatch has a lot of different
versions being imported by different packages as a transitive
dependency.
2026-04-07 07:15:08 +00:00
Thomas des FrancsandGitHub ea4ef99565 Salesforce section (#19366)
## Summary
- add the retro `VT323` font to the marketing site and apply it across
the Salesforce pricing card and popups
- expand the Salesforce pricing simulator with per-row metadata, unique
popup messages, dynamic price calculation, enterprise shared-cost
handling, and fixed-cost totals
- align the Salesforce card UI with the wireframes: sticky pricing
header, updated checkbox states, popup styling/behavior, add-on link,
and footer cleanup
- remove obsolete shared popup constants and quote form logic tied to
the Salesforce card
- refresh nearby pricing page UI details, including sticky menu behavior
and related pricing section polish

## Testing
- `yarn workspace twenty-website-new build`
2026-04-07 07:14:31 +00:00
c7d1cd11e0 i18n - translations (#19370)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-07 08:50:50 +02:00
83d30f8b76 feat: Send email from UI — inline reply composer & SendEmail mutation (#19363)
## Summary

- **Inline email reply**: Replace external email client redirects
(Gmail/Outlook deeplinks) with an in-app email composer. Users can reply
to email threads directly from the email thread widget or via the
command menu.
- **SendEmail GraphQL mutation**: New backend mutation that reuses
`EmailComposerService` for body sanitization, recipient validation, and
SMTP dispatch via the existing outbound messaging infrastructure.
- **Side panel compose page**: Command menu "Reply" action now opens a
side-panel compose email page with pre-filled To, Subject, and
In-Reply-To fields.

### Backend
- `SendEmailResolver` with `SendEmailInput` / `SendEmailOutputDTO`
- `SendEmailModule` wired into `CoreEngineModule`
- Reuses `EmailComposerService` + `MessagingMessageOutboundService`

### Frontend
- `EmailComposer` / `EmailComposerFields` components
- `useSendEmail`, `useReplyContext`, `useEmailComposerState` hooks
- `useOpenComposeEmailInSidePanel` + `SidePanelComposeEmailPage`
- `EmailThreadWidget` inline Reply bar with toggle composer
- `ReplyToEmailThreadCommand` now opens side-panel instead of external
links

### Seeds
- Added `handle` field to message participant seeds for realistic email
addresses
- Seed `connectedAccount` and `messageChannel` in correct batch order

## Test plan

- [ ] Open an email thread on a person/company record → verify
"Reply..." bar appears below the last message
- [ ] Click "Reply..." → composer opens inline with pre-filled To and
Subject
- [ ] Type a message and click Send → email is sent via SMTP, composer
closes
- [ ] Use command menu Reply action → side panel opens with compose
email page
- [ ] Verify Send/Cancel buttons work correctly in side panel
- [ ] Test with Cc/Bcc toggle in composer fields
- [ ] Verify error handling: invalid recipients, missing connected
account


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-04-07 08:43:48 +02:00
aec43da1e2 i18n - translations (#19355)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-06 12:13:17 +02:00
646edec104 i18n - translations (#19354)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-06 12:08:11 +02:00
Félix MalfaitGitHubClaude Opus 4.6claude[bot] <41898282+claude[bot]@users.noreply.github.com>
ea572975d8 feat: generic web search driver abstraction with Exa support and billing (#19341)
## Summary

- Introduces a pluggable `WebSearchDriver` abstraction (interface,
factory, service, module) so web search is no longer tied to native
provider tools (Anthropic/OpenAI)
- **Exa** is the first driver implementation with support for
category-filtered search (company, people, news, research paper, etc.) —
particularly useful for CRM workflows
- Per-query billing for both Exa ($0.007/query) and native provider
surcharges ($0.01/query for Anthropic/OpenAI) via the existing
`USAGE_RECORDED` pipeline
- New config variables: `WEB_SEARCH_DRIVER` (EXA/DISABLED),
`EXA_API_KEY`, `WEB_SEARCH_PREFER_NATIVE` (default false — prefers Exa
over native when both available)
- `WEB_SEARCH` operation type added for usage tracking and Stripe
metering

### Architecture

```
WebSearchDriver (interface)
├── ExaDriver          — Exa neural search with category support
└── DisabledDriver     — throws when search is disabled

WebSearchDriverFactory (extends DriverFactoryBase)
└── creates driver based on WEB_SEARCH_DRIVER config

WebSearchService (facade)
├── search(query, options?, billingContext?)
├── isEnabled()
└── emits USAGE_RECORDED events per query

WebSearchTool (Tool implementation)
└── registered in ActionToolProvider, available via tool catalog
```

### Native search billing gap fixed

Anthropic and OpenAI both charge $0.01/search on top of token costs. The
token costs were already billed, but the per-call surcharge was not.
Added `countNativeWebSearchCallsFromSteps` utility +
`billNativeWebSearchUsage` to `AiBillingService`, wired into both chat
and workflow agent paths.

## Test plan

- [ ] Set `WEB_SEARCH_DRIVER=EXA` + `EXA_API_KEY=...` and verify AI chat
can search the web
- [ ] Verify category parameter works (ask about a specific
company/person)
- [ ] Set `WEB_SEARCH_DRIVER=DISABLED` and verify search tool is not
exposed
- [ ] Set `WEB_SEARCH_PREFER_NATIVE=true` with Anthropic model and
verify native search is used
- [ ] Verify usage events are emitted in ClickHouse for both Exa and
native search paths
- [ ] Verify existing billing tests pass (`npx jest
ai-billing.service.spec.ts`)


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
2026-04-06 12:02:46 +02:00
8acfacc69c Add email thread widget and message thread record page layout (#19351)
## Summary
- Move email thread display from side panel to a dedicated record page
with a new `EMAIL_THREAD` widget type
- Add message thread as a standard object with page layout, subject
field, and backfill command
- Add reply-to-email command menu item for message thread records
- Remove old side panel message thread components in favor of the new
widget-based approach

## Type fixes
- Add `EMAIL_THREAD` to `WidgetConfigurationType`, `WidgetType`, and all
configuration/validator maps
- Create `EmailThreadConfigurationDTO` and shared
`EmailThreadConfiguration` type
- Register EMAIL_THREAD in widget type validators, configuration
resolvers, and standard widget mappings

## Test plan
- [ ] Verify message thread record pages render with the email thread
widget
- [ ] Verify email thread preview navigates to the record page instead
of opening side panel
- [ ] Verify reply-to-email command appears for message thread records
- [ ] Verify typecheck passes for both twenty-front and twenty-server
- [ ] Run existing test suites to check for regressions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-04-06 12:02:04 +02:00
Thomas des FrancsandGitHub 4aa1d71b12 few website improvements (#19353)
## Summary
- refine the home so it scrolls after home illustration scroll right
- Added few tweaks to pricing hero
2026-04-06 09:52:40 +00:00
BOHEUSandGitHub 7bf309ba73 Update last interaction app (#19332)
Rewrite to 0.8.0 SDK
2026-04-06 09:22:24 +00:00
8d61bb9ae6 Migrate messageFolder parentFolderId from UUID to externalId (#19348)
This PR migrates `messageFolder`.`parentFolderId` from an internal
`UUID` reference to external provider id.
Eliminates unnecessary lookup and complexity

---------

Co-authored-by: Charles Bochet <[email protected]>
2026-04-06 09:12:44 +00:00
0d44d7c6d7 i18n - translations (#19352)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-06 10:28:59 +02:00
neo773GitHubmartmullgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>github-actionsClaude Sonnet 4.6Charles Bochet
d3f0162cf5 Remove connected account feature flag (#19286)
Co-authored-by: martmull <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions <[email protected]>
Co-authored-by: Claude Sonnet 4.6 <[email protected]>
Co-authored-by: Charles Bochet <[email protected]>
2026-04-06 08:13:41 +00:00
Abdullah.andGitHub 3a1e112b86 Fixes and updates to the website. (#19350)
This PR implements a whole lot of fixes and updates to the website. It
adds a release-notes page, terms and conditions page, privacy policy
page, while fixing HomeStepper, ProductStepper, and WhyTwentyStepper. 3D
models still need to be styled and their sizes need to be fixed.
2026-04-06 09:42:30 +02:00
Paul RastoinandGitHub e062343802 Refactor typeorm migration lifecycle and generation (#19275)
# Introduction

Typeorm migration are now associated to a given twenty-version from the
`UPGRADE_COMMAND_SUPPORTED_VERSIONS` that the current twenty core engine
handles

This way when we upgrade we retrieve the migrations that need to be run,
this will be useful for the cross-version incremental upgrade so we
preserve sequentiality

## What's new

To generate
```sh
npx nx database:migrate:generate twenty-server -- --name add-index-to-users
```

To apply all
```sh
npx nx database:migrate twenty-server
```

## Next
Introduce slow and fast typeorm migration in order to get rid of the
save point pattern in our code base
Create a clean and dedicated `InstanceUpgradeService` abstraction
2026-04-06 07:11:47 +00:00
3747af4b5a Fix readonly date still editable (#19334)
Fixes #19319

---------

Co-authored-by: Charles Bochet <[email protected]>
2026-04-06 06:42:25 +00:00
bad488494f Fix dark mode text color on permissions tab empty stat (#19336) (#19340)
Before: black text in dark mode
<img width="1224" height="860" alt="image"
src="https://github.com/user-attachments/assets/a419ef77-9358-4588-ad19-a15b57448682"
/>


After updated styling: the correct grey text in dark mode
<img width="638" height="249" alt="Screenshot 2026-04-05 at 2 47 24 PM"
src="https://github.com/user-attachments/assets/bf736464-d33c-40f1-8244-2cf5d93b7e9c"
/>

---------

Co-authored-by: Charles Bochet <[email protected]>
2026-04-05 19:46:10 +00:00
Charles BochetandGitHub f25e040712 fix: replace npm pkg set with node script in set-local-version target (#19344)
## Summary

- Replaces `npm pkg set version=X` with a direct `node -e` script in the
`set-local-version` Nx target
- Fixes `CI Create App E2E minimal` workflow failures on fork PRs where
`npm pkg set` fails with `EJSONPARSE: Unexpected end of JSON input while
parsing empty string`

The `npm` command has unreliable `package.json` resolution in certain CI
checkout contexts (shallow clones of fork PR merge refs). Using `node`
directly to read/write the JSON file avoids this entirely.
2026-04-05 18:56:37 +00:00
265b2582ee Fix zh-CN sidebar translations in minimalMetadata API (#19342)
The minimalMetadata query was returning untranslated English labels for
standard objects (Companies, People, Opportunities, etc.) when users
requested zh-CN locale. This fix adds translation logic to
MinimalMetadataService using the existing I18nService.

Changes:
- Add translateLabel() method to translate standard object labels
- Pass locale from GraphQL context through resolver to service
- Only translate non-custom objects (custom objects use user-defined
labels)

Co-authored-by: Kevin Yu <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-04-05 20:14:20 +02:00
ed912ec548 chore: sync AI model catalog from models.dev (#19339)
Automated daily sync of `ai-providers.json` from
[models.dev](https://models.dev).

This PR updates pricing, context windows, and model availability based
on the latest data.
New models meeting inclusion criteria (tool calling, pricing data,
context limits) are added automatically.
Deprecated models are detected based on cost-efficiency within the same
model family.

**Please review before merging** — verify no critical models were
incorrectly deprecated.

Co-authored-by: FelixMalfait <[email protected]>
2026-04-05 08:22:58 +02:00
563e27831b Clean up tool output architecture: remove wrappers, enforce ToolOutput everywhere (#19321)
## Summary

- **Remove `ExecuteToolResult` wrapper** — `execute_tool` is now a
transparent dispatcher that returns the raw `ToolOutput` from underlying
tools. No more `{ toolName, result }` envelope.
- **Type the entire execution chain as `Promise<ToolOutput>`** — from
`ToolExecutorService.dispatch()` through `resolveAndExecute()` to
`execute_tool.execute()`. Zero `Promise<unknown>` remaining in the tool
layer.
- **Use `Extract<ToolExecutionRef, ...>`** for dispatch methods,
enabling exhaustive switch checking and removing `as never` casts.
- **Relax `ToolOutput.result` to accept `null`** — removes `??
undefined` hacks at the boundary with logic function results.
- **Enforce 1-export-per-file** across tool type/interface files (split
`tool-descriptor.type.ts`, `tool-provider.interface.ts`, `tool.type.ts`,
`tool-output.type.ts`, `tool-executor.service.ts`).
- **Simplify error handling** — `wrapWithErrorHandler` and all
meta-errors (tool not found, tool excluded) now return consistent
`ToolOutput` shape with `error` as a plain string.
- **Frontend reads output directly** — removed `unwrapToolOutput`
utility; `ToolStepRenderer` and `ThinkingStepsDisplay` extract
`message`/`error` from the raw output with simple type guards.
- **Add permission error detection** for email tools via
`isInsufficientPermissionsError`, guiding the AI model to suggest
account reconnection instead of hallucinating about visibility settings.

## Test plan

- [ ] AI chat tool calls return visible output (not "null") in the UI
- [ ] Tool errors display correctly in the JSON tree
- [ ] Email draft/send tools return actionable permission errors
- [ ] Code interpreter output renders correctly
- [ ] Thinking steps display tool outputs properly


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-04-04 14:05:42 +02:00
9cc794ddb6 i18n - translations (#19330)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-04 09:34:32 +02:00
martmullandGitHub 80c5cfc2ec Add npm packages app settings list (#19324)
solves
https://discord.com/channels/1130383047699738754/1488499318762635344
2026-04-04 07:20:11 +00:00
martmullandGitHub 804e0539d9 Publish 0.8.0 (#19323)
as title
2026-04-04 06:05:51 +00:00
4db7ae20c4 i18n - translations (#19329)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-04 08:11:17 +02:00
Félix MalfaitGitHubclaude[bot] <41898282+claude[bot]@users.noreply.github.com>Claude Opus 4.6
8da69e0f77 Fix stored XSS via unsafe URL protocols in href attributes (#19282)
## Summary

- Fixes **GHSA-7w89-7q26-gj7q**: stored XSS via `javascript:` URIs in
BlockNote `FileBlock` `props.url`, rendered as a clickable `<a href>`.
- Audited the full codebase and hardened **all** surfaces where
user-controlled URLs are rendered as `href` or passed to `window.open`.
- Applies defense-in-depth: server-side input validation + client-side
render-time checks + lint rules to prevent regressions.

### Changes

**New utility** — `isSafeUrl` (`~/utils/isSafeUrl.ts`):  
Allowlists `http:`, `https:`, `mailto:`, `tel:` protocols and relative
paths (`/`). Returns `false` for `javascript:`, `data:`, `vbscript:`,
etc.

**Server-side** — `validateBlocknoteFieldOrThrow`:  
- Recursively walks all blocks and validates `props.url` and inline link
`href` values
- Rejects payloads with unsafe URL protocols at save time (before data
is stored)

**Client-side** — 8 components hardened:
| Component | Fix |
|-----------|-----|
| `FileBlock` (reported vuln) | `isSafeUrl` gate, fixed
`target="__blank"` → `_blank`, added `rel="noopener noreferrer"` |
| `LazyMarkdownRenderer` | `isSafeUrl` gate on markdown `<a href>`,
added `target`/`rel` |
| `EditLinkPopover` (TipTap) | Validates + auto-prefixes `https://`,
rejects unsafe URLs |
| `LinkBubbleMenu` (TipTap) | `isSafeUrl` gate on `window.open`, added
`noopener,noreferrer` |
| `AttachmentRow` | `isSafeUrl` gate on file attachment `href` |
| `URLDisplay` / `LinkDisplay` | `isSafeUrl` as second check after
`startsWith('http')` |
| `IframeWidget` | `isSafeUrl` gate on `src`, shows error state for
unsafe URLs |
| `InformationBannerMaintenance` | `isSafeUrl` gate on `window.open` |

**Lint rules** — `.oxlintrc.json`:
- `no-script-url: error` — catches `javascript:` string literals
- `react/jsx-no-script-url: error` — catches `javascript:` in JSX href
attributes

## Test plan

- [ ] Create a note via GraphQL mutation with `"url":
"javascript:void(alert(1))"` in a file block — should be rejected by
server validation
- [ ] Verify existing file attachments in notes still render and are
clickable
- [ ] Verify TipTap link insertion works for normal `https://` URLs
- [ ] Verify TipTap link insertion rejects `javascript:` URIs
- [ ] Verify markdown links in AI chat render correctly for safe URLs
- [ ] Verify URL/Link field displays still work for normal URLs
- [ ] Verify iframe widget rejects non-http(s) URLs


Made with [Cursor](https://cursor.com)

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <[email protected]>
2026-04-04 08:05:27 +02:00
282ee9ac42 i18n - docs translations (#19320)
Created by Github action

Co-authored-by: github-actions <[email protected]>
2026-04-03 18:27:51 +02:00
neo773andGitHub 0b44c9e4e5 Remove connected account upgrade command (#19316) 2026-04-03 18:01:21 +02:00
e1a58df140 i18n - translations (#19318)
Created by Github action

Co-authored-by: github-actions <[email protected]>
2026-04-03 17:44:32 +02:00
93c0c98495 i18n - translations (#19317)
Created by Github action

---------

Co-authored-by: github-actions <[email protected]>
2026-04-03 17:38:09 +02:00
martmullandGitHub f8c3960cf2 Disable setting tab when empty (#19315)
## before
<img width="1063" height="520" alt="image"
src="https://github.com/user-attachments/assets/db92432b-a30c-49e8-9246-a09d0815e6c9"
/>


## after
<img width="1049" height="490" alt="image"
src="https://github.com/user-attachments/assets/e926b065-6a65-417b-b802-0e1df6ca638f"
/>
2026-04-03 15:27:17 +00:00
EtienneandGitHub d562a384c2 Remove direct execution feature flag - WIP (#19254)
Bug fixes exposed by always-on direct execution
1. GraphQL spec compliance — data[field] = null on resolver error
direct-execution.service.ts — Changed from Promise.allSettled (which
lost the responseKey on rejection) to Promise.all with per-field
try/catch; errors now set data[responseKey] = null per spec
2. Empty object arguments skipped (extractArgumentsFromAst)
extract-arguments-from-ast.util.ts — Removed isEmptyObject check;
filter: {}, data: {} now correctly passed to resolvers instead of
silently dropped (which caused permissions to never be checked)
3. orderBy: {} factory default treated as "no ordering"
direct-execution.service.ts — Before calling the resolver, strips
orderBy: {} and orderByForRecords: {} (empty-object factory defaults
that mean "no ordering")
assert-find-many-args.util.ts / assert-group-by-args.util.ts — Accept {}
for orderBy without throwing
4. orderBy: { field: '...' } object auto-coerced to [{ field: '...' }]
array
direct-execution.service.ts — Applies GraphQL list coercion: a
non-array, non-empty orderBy object is wrapped in an array before
assertion and resolver call
5. totalCount and aggregate fields returned as strings from PostgreSQL
graphql-format-result-from-selected-fields.util.ts — Added
coerceAggregateValue that parses numeric strings to numbers for
totalCount, sum*, avg*, min*, max*, count*, percentageOf* fields
Test updates
nested-relation-queries.integration-spec.ts — Updated expected error
message from Yoga schema-validation message to direct execution resolver
message
~30 snapshot files — Updated to reflect direct execution's error
messages (different from Yoga schema-validation messages for input type
errors)
2026-04-03 15:23:01 +00:00
Thomas TrompetteandGitHub 90597e47ca Add redis cache for cron triggers (#19306)
- WorkflowCronTriggerCronJob was querying every active workspace (~700)
sequentially every minute to find cron triggers, causing regular CPU
spikes to 100% on worker pods

- Added a Redis hashset cache that stores cron triggers. On cache miss
(TTL expired, cold start, or explicit invalidation), a full scan
rebuilds the cache

- Creating/deleting a new cron trigger updates the cache, only if exists
2026-04-03 15:08:31 +00:00
Raphaël BosiandGitHub b55765a991 Fix delete/restore/destroy commands unavailable in select-all mode (#19311)
Fixes https://github.com/twentyhq/twenty/issues/19309

In exclusion mode (select all), selectedRecords is always [] since
individual record IDs aren't tracked. The noneDefined()/everyDefined()
checks return false on empty arrays by design, which hides the delete,
restore, and destroy commands from the command menu.

- Wrap selectedRecords array checks with (isSelectAll or ...) to bypass
when in exclusion mode
- Remove the `numberOfSelectedRecords < 10000` limit
- Add `upgrade:1-21:fix-select-all-command-menu-items` command to
backfill existing workspaces
- Add tests
2026-04-03 15:03:45 +00:00
0b8421a45a i18n - docs translations (#19314)
Created by Github action

Co-authored-by: github-actions <[email protected]>
2026-04-03 16:31:55 +02:00
Thomas TrompetteandGitHub 4ba2f3b184 Read cache value for total event stream count (#19313)
As title
2026-04-03 14:19:57 +00:00
Raphaël BosiandGitHub 8543576dae Dynamic icon for command menu items (#19307)
Allow for dynamic icons in command menu items. For instance
`${objectMetadataItem.icon}` will resolve the object metadata item icon
2026-04-03 13:41:56 +00:00
989 changed files with 31417 additions and 18305 deletions
+1 -1
View File
@@ -158,7 +158,7 @@ jobs:
timeout-minutes: 30
runs-on: ubuntu-latest
env:
NODE_OPTIONS: '--max-old-space-size=4096'
NODE_OPTIONS: '--max-old-space-size=6144'
TASK_CACHE_KEY: front-task-${{ matrix.task }}
strategy:
matrix:
+4 -4
View File
@@ -144,15 +144,15 @@ jobs:
exit 1
- name: Server / Check for Pending Migrations
run: |
CORE_MIGRATION_OUTPUT=$(npx nx run twenty-server:typeorm migration:generate core-migration-check -d src/database/typeorm/core/core.datasource.ts || true)
CORE_MIGRATION_OUTPUT=$(npx nx database:migrate:generate twenty-server -- --name core-migration-check || true)
CORE_MIGRATION_FILE=$(ls packages/twenty-server/*core-migration-check.ts 2>/dev/null || echo "")
CORE_MIGRATION_FILE=$(ls packages/twenty-server/src/database/typeorm/core/migrations/common/*core-migration-check.ts 2>/dev/null || echo "")
if [ -n "$CORE_MIGRATION_FILE" ]; then
echo "::error::Unexpected migration files were generated. Please create a proper migration manually."
echo "::error::Unexpected migration files were generated. Please run 'npx nx database:migrate:generate twenty-server -- --name <migration-name>' and commit the result."
echo "$CORE_MIGRATION_OUTPUT"
rm -f packages/twenty-server/*core-migration-check.ts
rm -f packages/twenty-server/src/database/typeorm/core/migrations/common/*core-migration-check.ts
exit 1
fi
+1 -1
View File
@@ -141,7 +141,7 @@
"cache": false,
"options": {
"cwd": "{projectRoot}",
"command": "npm pkg set version={args.releaseVersion}"
"command": "node -e \"const fs=require('fs'),p=JSON.parse(fs.readFileSync('package.json','utf8'));p.version='{args.releaseVersion}';fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\\n');\""
}
},
"storybook:build": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "create-twenty-app",
"version": "0.8.0-canary.9",
"version": "0.8.0",
"description": "Command-line interface to create Twenty application",
"main": "dist/cli.cjs",
"bin": "dist/cli.cjs",
@@ -0,0 +1,38 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn
# codegen
generated
# testing
/coverage
# dev
/dist/
.twenty
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# typescript
*.tsbuildinfo
*.d.ts
@@ -0,0 +1 @@
24.5.0
@@ -0,0 +1,19 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["typescript"],
"categories": {
"correctness": "off"
},
"ignorePatterns": ["node_modules", "dist"],
"rules": {
"no-unused-vars": "off",
"typescript/no-unused-vars": [
"warn",
{
"argsIgnorePattern": "^_"
}
],
"typescript/no-explicit-any": "off"
}
}
@@ -2,22 +2,18 @@
Updates Last interaction and Interaction status fields based on last email date
## Requirements
- an `apiKey` - go to Settings > API & Webhooks to generate one
## Setup
1. Add and synchronize app
Add and synchronize app
```bash
cd packages/twenty-apps/community/last-email-interaction
yarn auth
yarn sync
yarn twenty remote add
yarn twenty install
```
2. Go to Settings > Integrations > Last email interaction > Settings and add required variables
## Flow
- Checks if fields are created, if not, creates them on fly
- Extracts the datetime of message and calculates the last interaction status
- Fetches all users and companies connected to them and updates their Last interaction and Interaction status fields
- Extracts the datetime of fetched message and calculates the last interaction status
- Fetches all users and companies connected to the message and updates their Last interaction and Interaction status fields
## Todo:
- update app with generated Twenty object once extending objects is possible
## Notes
- Upon install, creates fields to Person and Company objects
- Every day at midnight app goes through all companies and people records and updates their Interaction status based on Last interaction date
@@ -1,23 +0,0 @@
import { type ApplicationConfig } from 'twenty-sdk';
const config: ApplicationConfig = {
universalIdentifier: '718ed9ab-53fc-49c8-8deb-0cff78ecf0d2',
displayName: 'Last email interaction',
description:
'Updates Last interaction and Interaction status fields based on last received email',
icon: "IconMailFast",
applicationVariables: {
TWENTY_API_KEY: {
universalIdentifier: 'aae3f523-4c1f-4805-b3ee-afeb676c381e',
isSecret: true,
description: 'Required to send requests to Twenty',
},
TWENTY_API_URL: {
universalIdentifier: '6d19bb04-45bb-46aa-a4e5-4a2682c7b19d',
isSecret: false,
description: 'Optional, defaults to cloud API URL',
},
},
};
export default config;
@@ -9,19 +9,23 @@
},
"packageManager": "[email protected]",
"dependencies": {
"axios": "^1.12.2",
"twenty-sdk": "0.2.4"
},
"devDependencies": {
"@types/node": "^24.7.2"
"axios": "1.14.0",
"twenty-sdk": "0.8.0"
},
"scripts": {
"auth": "twenty auth login",
"dev": "twenty app dev",
"sync": "twenty app sync",
"uninstall": "twenty app uninstall",
"logs": "twenty app logs",
"create-entity": "twenty app add",
"help": "twenty --help"
"twenty": "twenty",
"lint": "oxlint -c .oxlintrc.json .",
"lint:fix": "oxlint --fix -c .oxlintrc.json .",
"test": "vitest run",
"test:watch": "vitest"
},
"devDependencies": {
"@types/node": "^24.7.2",
"@types/react": "^18.2.0",
"oxlint": "^0.16.0",
"react": "^18.2.0",
"typescript": "^5.9.3",
"vite-tsconfig-paths": "^4.2.1",
"vitest": "^3.1.1"
}
}
@@ -0,0 +1,10 @@
import { defineApplication } from 'twenty-sdk';
export default defineApplication({
universalIdentifier: '718ed9ab-53fc-49c8-8deb-0cff78ecf0d2',
displayName: 'Last email interaction',
description:
'Updates Last interaction and Interaction status fields based on last received email',
icon: "IconMailFast",
defaultRoleUniversalIdentifier: '7a66af97-5056-45b2-96a9-c89f0fd181d1',
});
@@ -0,0 +1,41 @@
import { defineField, FieldType, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS } from 'twenty-sdk';
export default defineField({
universalIdentifier: '9378751e-c23b-4e84-887d-2905cb8359b4',
name: 'interactionStatus',
label: 'Interaction status',
type: FieldType.SELECT,
objectUniversalIdentifier:
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier,
description: 'Indicates the health of relation',
options: [
{
id: '39d54a6b-5a0e-4209-9a59-2a2d7b8c462b',
color: 'green',
label: 'Recent',
value: 'RECENT',
position: 1,
},
{
id: '7377d6c5-a75c-453e-a1a1-63fb9cba4e26',
color: 'yellow',
label: 'Active',
value: 'ACTIVE',
position: 2,
},
{
id: 'a8b99246-237f-4715-b21f-94a3ae14994e',
color: 'sky',
label: 'Cooling',
value: 'COOLING',
position: 3,
},
{
id: '1f05d528-eaab-4639-aba1-328050a87220',
color: 'gray',
label: 'Dormant',
value: 'DORMANT',
position: 4,
},
],
});
@@ -0,0 +1,14 @@
import {
defineField,
FieldType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
export default defineField({
universalIdentifier: '2f195c4c-1db1-4bbe-80b6-25c2f63168b0',
name: 'lastInteraction',
label: 'Last interaction',
type: FieldType.DATE_TIME,
objectUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier,
description: 'Date when the last interaction happened',
});
@@ -0,0 +1,41 @@
import { defineField, FieldType, STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS } from 'twenty-sdk';
export default defineField({
universalIdentifier: 'fa342e26-9742-4db8-85b4-4d78ba18482f',
name: 'interactionStatus',
label: 'Interaction status',
type: FieldType.SELECT,
objectUniversalIdentifier:
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.person.universalIdentifier,
description: 'Indicates the health of relation',
options: [
{
id: '1dfbfa99-35fb-43af-8c14-74e682a8121b',
color: 'green',
label: 'Recent',
value: 'RECENT',
position: 1,
},
{
id: '955788e8-6d64-45ba-80ea-a1a5446a0ae7',
color: 'yellow',
label: 'Active',
value: 'ACTIVE',
position: 2,
},
{
id: '7b84ca72-fac5-4c6d-ab08-b148e4b3efdf',
color: 'sky',
label: 'Cooling',
value: 'COOLING',
position: 3,
},
{
id: '04dea3e5-ec26-41cf-b23f-37abab67827a',
color: 'gray',
label: 'Dormant',
value: 'DORMANT',
position: 4,
},
],
});
@@ -0,0 +1,14 @@
import {
defineField,
FieldType,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
export default defineField({
universalIdentifier: 'bec14de7-6683-4784-91ba-62d83b5f30f7',
name: 'lastInteraction',
label: 'Last interaction',
type: FieldType.DATE_TIME,
objectUniversalIdentifier: STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.person.universalIdentifier,
description: 'Date when the last interaction happened',
});
@@ -1,270 +0,0 @@
import axios from 'axios';
import { type FunctionConfig } from 'twenty-sdk';
const TWENTY_API_KEY = process.env.TWENTY_API_KEY ?? '';
const TWENTY_URL =
process.env.TWENTY_API_URL !== '' && process.env.TWENTY_API_URL !== undefined
? `${process.env.TWENTY_API_URL}/rest`
: 'https://api.twenty.com/rest';
const create_last_interaction = (id: string) => {
return {
method: 'POST',
url: `${TWENTY_URL}/metadata/fields`,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${TWENTY_API_KEY}`,
},
data: {
type: 'DATE_TIME',
objectMetadataId: `${id}`,
name: 'lastInteraction',
label: 'Last interaction',
description: 'Date when the last interaction happened',
icon: 'IconCalendarClock',
defaultValue: null,
isNullable: true,
settings: {},
},
};
};
const create_interaction_status = (id: string) => {
return {
method: 'POST',
url: `${TWENTY_URL}/metadata/fields`,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${TWENTY_API_KEY}`,
},
data: {
type: 'SELECT',
objectMetadataId: `${id}`,
name: 'interactionStatus',
label: 'Interaction status',
description: 'Indicates the health of relation',
icon: 'IconProgress',
defaultValue: null,
isNullable: true,
settings: {},
options: [
{
color: 'green',
label: 'Recent',
value: 'RECENT',
position: 1,
},
{
color: 'yellow',
label: 'Active',
value: 'ACTIVE',
position: 2,
},
{
color: 'sky',
label: 'Cooling',
value: 'COOLING',
position: 3,
},
{
color: 'gray',
label: 'Dormant',
value: 'DORMANT',
position: 4,
},
],
},
};
};
const calculateStatus = (date: string) => {
const day = 1000 * 60 * 60 * 24;
const now = Date.now();
const messageDate = Date.parse(date);
const deltaTime = now - messageDate;
return deltaTime < 7 * day
? 'RECENT'
: deltaTime < 30 * day
? 'ACTIVE'
: deltaTime < 90 * day
? 'COOLING'
: 'DORMANT';
};
const updateInteractionStatus = async (objectName: string, id: string, messageDate: string, status: string) => {
const options = {
method: 'PATCH',
url: `${TWENTY_URL}/${objectName}/${id}`,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${TWENTY_API_KEY}`,
},
data: {
lastInteraction: messageDate,
interactionStatus: status
}
};
try {
const response = await axios.request(options);
if (response.status === 200) {
console.log('Successfully updated company last interaction field');
}
} catch (error) {
if (axios.isAxiosError(error)) {
throw error;
}
throw error;
}
}
const fetchRelatedCompanyId = async (id: string) => {
const options = {
method: 'GET',
url: `${TWENTY_URL}/people/${id}`,
headers: {
Authorization: `Bearer ${TWENTY_API_KEY}`,
},
};
try {
const req = await axios.request(options);
if (req.status === 200 && req.data.person.companyId !== null && req.data.person.companyId !== undefined) {
return req.data.person.companyId;
}
} catch (error) {
if (axios.isAxiosError(error)) {
throw error;
}
throw error;
}
}
export const main = async (params: {
properties: Record<string, any>;
recordId: string;
userId: string;
}): Promise<object | undefined> => {
if (TWENTY_API_KEY === '') {
console.log("Function exited as API key or URL hasn't been set properly");
return {};
}
const { properties, recordId } = params;
// Check if fields are created
const options = {
method: 'GET',
url: `${TWENTY_URL}/metadata/objects`,
headers: {
Authorization: `Bearer ${TWENTY_API_KEY}`,
},
};
try {
const response = await axios.request(options);
const objects = response.data.data.objects;
const company_object = objects.find(
(object: any) => object.nameSingular === 'company',
);
const company_last_interaction = company_object.fields.find(
(field: any) => field.name === 'lastInteraction',
);
const company_interaction_status = company_object.fields.find(
(field: any) => field.name === 'interactionStatus',
);
const person_object = objects.find(
(object: any) => object.nameSingular === 'person',
);
const person_last_interaction = person_object.fields.find(
(field: any) => field.name === 'lastInteraction',
);
const person_interaction_status = person_object.fields.find(
(field: any) => field.name === 'interactionStatus',
);
// If not, create them
if (company_last_interaction === undefined) {
const response2 = await axios.request(
create_last_interaction(company_object.id),
);
if (response2.status === 201) {
console.log('Successfully created company last interaction field');
}
}
if (company_interaction_status === undefined) {
const response2 = await axios.request(
create_interaction_status(company_object.id),
);
if (response2.status === 201) {
console.log('Successfully created company interaction status field');
}
}
if (person_last_interaction === undefined) {
const response2 = await axios.request(
create_last_interaction(person_object.id),
);
if (response2.status === 201) {
console.log('Successfully created person last interaction field');
}
}
if (person_interaction_status === undefined) {
const response2 = await axios.request(
create_interaction_status(person_object.id),
);
if (response2.status === 201) {
console.log('Successfully created person interaction status field');
}
}
// Extract the timestamp of message
const messageDate = properties.after.receivedAt;
const interactionStatus = calculateStatus(messageDate);
// Get the details of person and related company
const messageOptions = {
method: 'GET',
url: `${TWENTY_URL}/messages/${recordId}?depth=1`,
headers: {
Authorization: `Bearer ${TWENTY_API_KEY}`,
},
};
const messageDetails = await axios.request(messageOptions);
const peopleIds: string[] = [];
for (const participant of messageDetails.data.messages
.messageParticipants) {
peopleIds.push(participant.personId);
}
const companiesIds = [];
for (const id of peopleIds) {
companiesIds.push(await fetchRelatedCompanyId(id));
}
// Update the field value depending on the timestamp
for (const id of peopleIds) {
await updateInteractionStatus("people", id, messageDate, interactionStatus);
}
for (const id of companiesIds) {
await updateInteractionStatus("companies", id, messageDate, interactionStatus);
}
} catch (error) {
if (axios.isAxiosError(error)) {
console.error(error.message);
return {};
}
console.error(error);
return {};
}
};
export const config: FunctionConfig = {
universalIdentifier: '683966a0-b60a-424e-86b1-7448c9191bde',
name: 'test',
triggers: [
{
universalIdentifier: 'f4f1e127-87f0-4dcf-99fe-8061adf5cbe6',
type: 'databaseEvent',
eventName: 'message.created',
},
{
universalIdentifier: '4c17878f-b6b3-4d0a-8de6-967b1cb55002',
type: 'databaseEvent',
eventName: 'message.updated',
},
],
};
@@ -0,0 +1,126 @@
import { defineLogicFunction } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-client-sdk/core';
import { calculateStatus } from '../shared/calculate-status';
const fetchAllPeople = async () => {
const client = new CoreApiClient();
const result = await client.query({
people: {
__args: {
filter: {
/*
lastInteraction: {
is: 'NOT_NULL',
},
*/
},
},
edges: {
node: {
id: true,
lastInteraction: true,
interactionStatus: true,
},
},
},
});
if (!result.people) {
throw new Error('Could not find any people');
}
return result.people.edges;
}
const fetchAllCompanies = async () => {
const client = new CoreApiClient();
const result = await client.query({
companies: {
__args: {
filter: {
/* how to fetch fields added in fields folder?
lastInteraction: {
is: 'NOT_NULL',
},
*/
},
},
edges: {
node: {
id: true,
lastInteraction: true,
interactionStatus: true,
},
},
},
});
if (!result.companies) {
throw new Error('Could not find any companies');
}
return result.companies.edges;
}
const updateCompany = async (
companyId: string,
updateData: Record<string, string>,
) => {
const client = new CoreApiClient();
const result = await client.mutation({
updateCompany: {
__args: {
id: companyId,
data: updateData,
},
id: true,
},
});
if (!result.updateCompany) {
throw new Error(`Failed to update company ${companyId}`);
}
};
const updatePerson = async (
personId: string,
updateData: Record<string, string>,
) => {
const client = new CoreApiClient();
const result = await client.mutation({
updatePerson: {
__args: {
id: personId,
data: updateData,
},
id: true,
},
});
if (!result.updatePerson) {
throw new Error(`Failed to update person ${personId}`);
}
};
const handler = async () => {
const people = await fetchAllPeople();
for (const person of people) {
const interactionStatus = calculateStatus(person.node.lastInteraction as string);
if (interactionStatus !== person.node.interactionStatus) {
await updatePerson(person.node.id, {interactionStatus: interactionStatus});
}
}
const companies = await fetchAllCompanies();
for (const company of companies) {
const interactionStatus = calculateStatus(company.node.lastInteraction as string);
if (interactionStatus !== company.node.interactionStatus) {
await updateCompany(company.node.id, {interactionStatus: interactionStatus});
}
}
};
export default defineLogicFunction({
universalIdentifier: 'c79f1f30-f369-4264-9e5b-c183577bc709',
name: 'on-cron-job',
description:
'Runs daily at midnight and updates all companies and people with correct interaction status',
timeoutSeconds: 5,
handler,
cronTriggerSettings: {
pattern: '0 0 * * *', // runs daily at midnight
},
});
@@ -0,0 +1,143 @@
import {
DatabaseEventPayload,
defineLogicFunction,
ObjectRecordCreateEvent,
} from 'twenty-sdk';
import { CoreApiClient } from 'twenty-client-sdk/core';
import { calculateStatus } from '../shared/calculate-status';
const fetchMessageParticipants = async (messageId: string) => {
const client = new CoreApiClient();
const result = await client.query({
messageParticipants: {
__args: {
filter: {
messageId: {
eq: messageId,
},
},
},
edges: {
node: {
personId: true,
},
},
},
});
let people: string[] = [];
if (result.messageParticipants === undefined) {
return people;
}
for (const person of result.messageParticipants.edges) {
if (person.node.personId !== undefined) {
people.push(person.node.personId);
}
}
return people;
};
const fetchRelatedCompany = async (personId: string) => {
const client = new CoreApiClient();
const result = await client.query({
people: {
__args: {
filter: {
id: {
eq: personId,
},
},
},
edges: {
node: {
company: {
id: true,
},
},
},
},
});
if (
result.people === undefined ||
result.people.edges[0].node.company === undefined
) {
throw new Error(`Failed to fetch related company of person ${personId}`);
}
return result.people.edges[0].node.company.id;
};
const updateCompany = async (
companyId: string,
updateData: Record<string, string>,
) => {
const client = new CoreApiClient();
const result = await client.mutation({
updateCompany: {
__args: {
id: companyId,
data: updateData,
},
id: true,
},
});
if (!result.updateCompany) {
throw new Error(`Failed to update company ${companyId}`);
}
};
const updatePerson = async (
personId: string,
updateData: Record<string, string>,
) => {
const client = new CoreApiClient();
const result = await client.mutation({
updatePerson: {
__args: {
id: personId,
data: updateData,
},
id: true,
},
});
if (!result.updatePerson) {
throw new Error(`Failed to update person ${personId}`);
}
};
type Message = {
receivedAt: string;
};
type MessageCreatedEvent = DatabaseEventPayload<
ObjectRecordCreateEvent<Message>
>;
const handler = async (
event: MessageCreatedEvent,
): Promise<object | undefined> => {
const { properties, recordId } = event;
const interactionStatus = calculateStatus(properties.after.receivedAt);
const peopleIds: string[] = [];
peopleIds.push(...(await fetchMessageParticipants(recordId)));
const updateData = {
lastInteraction: properties.after.receivedAt,
interactionStatus: interactionStatus,
};
for (const person of peopleIds) {
const companyId = await fetchRelatedCompany(person);
await updatePerson(person, updateData);
await updateCompany(companyId, updateData);
}
return {};
};
export default defineLogicFunction({
universalIdentifier: '543432c2-6509-4ee9-90ec-15ffb4d7abfc',
name: 'on-message-created',
description: 'Triggered when new message is created',
timeoutSeconds: 5,
handler,
databaseEventTriggerSettings: {
eventName: 'message.created',
},
});
@@ -0,0 +1,143 @@
import {
DatabaseEventPayload,
defineLogicFunction,
ObjectRecordCreateEvent,
} from 'twenty-sdk';
import { CoreApiClient } from 'twenty-client-sdk/core';
import { calculateStatus } from '../shared/calculate-status';
const fetchMessageParticipants = async (messageId: string) => {
const client = new CoreApiClient();
const result = await client.query({
messageParticipants: {
__args: {
filter: {
messageId: {
eq: messageId,
},
},
},
edges: {
node: {
personId: true,
},
},
},
});
let people: string[] = [];
if (result.messageParticipants === undefined) {
return people;
}
for (const person of result.messageParticipants.edges) {
if (person.node.personId !== undefined) {
people.push(person.node.personId);
}
}
return people;
};
const fetchRelatedCompany = async (personId: string) => {
const client = new CoreApiClient();
const result = await client.query({
people: {
__args: {
filter: {
id: {
eq: personId,
},
},
},
edges: {
node: {
company: {
id: true,
},
},
},
},
});
if (
result.people === undefined ||
result.people.edges[0].node.company === undefined
) {
throw new Error(`Failed to fetch related company of person ${personId}`);
}
return result.people.edges[0].node.company.id;
};
const updateCompany = async (
companyId: string,
updateData: Record<string, string>,
) => {
const client = new CoreApiClient();
const result = await client.mutation({
updateCompany: {
__args: {
id: companyId,
data: updateData,
},
id: true,
},
});
if (!result.updateCompany) {
throw new Error(`Failed to update company ${companyId}`);
}
};
const updatePerson = async (
personId: string,
updateData: Record<string, string>,
) => {
const client = new CoreApiClient();
const result = await client.mutation({
updatePerson: {
__args: {
id: personId,
data: updateData,
},
id: true,
},
});
if (!result.updatePerson) {
throw new Error(`Failed to update person ${personId}`);
}
};
type Message = {
receivedAt: string;
};
type MessageCreatedEvent = DatabaseEventPayload<
ObjectRecordCreateEvent<Message>
>;
const handler = async (
event: MessageCreatedEvent,
): Promise<object | undefined> => {
const { properties, recordId } = event;
const interactionStatus = calculateStatus(properties.after.receivedAt);
const peopleIds: string[] = [];
peopleIds.push(...(await fetchMessageParticipants(recordId)));
const updateData = {
lastInteraction: properties.after.receivedAt,
interactionStatus: interactionStatus,
};
for (const person of peopleIds) {
const companyId = await fetchRelatedCompany(person);
await updatePerson(person, updateData);
await updateCompany(companyId, updateData);
}
return {};
};
export default defineLogicFunction({
universalIdentifier: '9bfcb3e4-9119-4b65-b6e9-d395d0764ce5',
name: 'on-message-updated',
description: 'Triggered when message is updated',
timeoutSeconds: 5,
handler,
databaseEventTriggerSettings: {
eventName: 'message.updated',
},
});
@@ -0,0 +1,13 @@
export const calculateStatus = (date: string) => {
const day = 1000 * 60 * 60 * 24;
const now = Date.now();
const messageDate = Date.parse(date);
const deltaTime = now - messageDate;
return deltaTime < 7 * day
? 'RECENT'
: deltaTime < 30 * day
? 'ACTIVE'
: deltaTime < 90 * day
? 'COOLING'
: 'DORMANT';
};
@@ -0,0 +1,17 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"composite": true,
"types": [
"vitest/globals"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules",
"dist"
]
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-client-sdk",
"version": "0.8.0-canary.9",
"version": "0.8.0",
"sideEffects": false,
"license": "AGPL-3.0",
"scripts": {
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { getIntrospectionQuery, buildClientSchema, printSchema } from 'graphql';
import { buildClientSchema, getIntrospectionQuery, printSchema } from 'graphql';
import { generateMetadataClient } from '../src/generate/generate-metadata-client';
@@ -921,6 +921,7 @@ enum WidgetType {
WORKFLOW_RUN
FRONT_COMPONENT
RECORD_TABLE
EMAIL_THREAD
}
union PageLayoutWidgetPosition = PageLayoutWidgetGridPosition | PageLayoutWidgetVerticalListPosition | PageLayoutWidgetCanvasPosition
@@ -948,7 +949,7 @@ type PageLayoutWidgetCanvasPosition {
layoutMode: PageLayoutTabLayoutMode!
}
union WidgetConfiguration = AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration
union WidgetConfiguration = AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | EmailThreadConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration
type AggregateChartConfiguration {
configurationType: WidgetConfigurationType!
@@ -989,6 +990,7 @@ enum WidgetConfigurationType {
WORKFLOW_RUN
FRONT_COMPONENT
RECORD_TABLE
EMAIL_THREAD
}
type StandaloneRichTextConfiguration {
@@ -1154,6 +1156,10 @@ type EmailsConfiguration {
configurationType: WidgetConfigurationType!
}
type EmailThreadConfiguration {
configurationType: WidgetConfigurationType!
}
type FieldConfiguration {
configurationType: WidgetConfigurationType!
fieldMetadataId: String!
@@ -1724,16 +1730,16 @@ enum FeatureFlagKey {
IS_AI_ENABLED
IS_COMMAND_MENU_ITEM_ENABLED
IS_MARKETPLACE_ENABLED
IS_MARKETPLACE_SETTING_TAB_VISIBLE
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED
IS_PUBLIC_DOMAIN_ENABLED
IS_EMAILING_DOMAIN_ENABLED
IS_JUNCTION_RELATIONS_ENABLED
IS_DRAFT_EMAIL_ENABLED
IS_CONNECTED_ACCOUNT_MIGRATED
IS_USAGE_ANALYTICS_ENABLED
IS_RICH_TEXT_V1_MIGRATED
IS_DIRECT_GRAPHQL_EXECUTION_ENABLED
IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED
IS_CONNECTED_ACCOUNT_MIGRATED
IS_RECORD_TABLE_WIDGET_ENABLED
IS_DATASOURCE_MIGRATED
}
@@ -2542,7 +2548,7 @@ type ConnectedImapSmtpCaldavAccount {
id: UUID!
handle: String!
provider: String!
accountOwnerId: UUID!
userWorkspaceId: UUID!
connectionParameters: ImapSmtpCaldavConnectionParameters
}
@@ -2633,6 +2639,8 @@ enum EngineComponentKey {
VIEW_PREVIOUS_AI_CHATS
TRIGGER_WORKFLOW_VERSION
FRONT_COMPONENT_RENDERER
REPLY_TO_EMAIL_THREAD
COMPOSE_EMAIL
DELETE_SINGLE_RECORD
DELETE_MULTIPLE_RECORDS
RESTORE_SINGLE_RECORD
@@ -2756,6 +2764,26 @@ type DuplicatedDashboard {
updatedAt: String!
}
type ConnectedAccountDTO {
id: UUID!
handle: String!
provider: String!
lastCredentialsRefreshedAt: DateTime
authFailedAt: DateTime
handleAliases: [String!]
scopes: [String!]
connectionParameters: ImapSmtpCaldavConnectionParameters
lastSignedInAt: DateTime
userWorkspaceId: UUID!
createdAt: DateTime!
updatedAt: DateTime!
}
type SendEmailOutput {
success: Boolean!
error: String
}
type EventLogRecord {
event: String!
timestamp: DateTime!
@@ -2924,20 +2952,6 @@ enum CalendarChannelContactAutoCreationPolicy {
NONE
}
type ConnectedAccountDTO {
id: UUID!
handle: String!
provider: String!
lastCredentialsRefreshedAt: DateTime
authFailedAt: DateTime
handleAliases: [String!]
scopes: [String!]
lastSignedInAt: DateTime
userWorkspaceId: UUID!
createdAt: DateTime!
updatedAt: DateTime!
}
type MessageChannel {
id: UUID!
visibility: MessageChannelVisibility!
@@ -3013,7 +3027,7 @@ type MessageFolder {
name: String
isSentFolder: Boolean!
isSynced: Boolean!
parentFolderId: UUID
parentFolderId: String
externalId: String
pendingSyncAction: MessageFolderPendingSyncAction!
messageChannelId: UUID!
@@ -3220,7 +3234,6 @@ type Query {
findApplicationRegistrationStats(id: String!): ApplicationRegistrationStats!
findApplicationRegistrationVariables(applicationRegistrationId: String!): [ApplicationRegistrationVariable!]!
applicationRegistrationTarballUrl(id: String!): String
getApplicationShareLink(id: String!): String!
currentUser: User!
currentWorkspace: Workspace!
getPublicWorkspaceDataByDomain(origin: String): PublicWorkspaceData!
@@ -3370,6 +3383,7 @@ enum UsageOperationType {
AI_WORKFLOW_TOKEN
WORKFLOW_EXECUTION
CODE_EXECUTION
WEB_SEARCH
}
type Mutation {
@@ -3445,6 +3459,7 @@ type Mutation {
updatePageLayout(id: String!, input: UpdatePageLayoutInput!): PageLayout!
destroyPageLayout(id: String!): Boolean!
updatePageLayoutWithTabsAndWidgets(id: String!, input: UpdatePageLayoutWithTabsInput!): PageLayout!
resetPageLayoutWidgetToDefault(id: String!): PageLayoutWidget!
createPageLayoutWidget(input: CreatePageLayoutWidgetInput!): PageLayoutWidget!
updatePageLayoutWidget(id: String!, input: UpdatePageLayoutWidgetInput!): PageLayoutWidget!
destroyPageLayoutWidget(id: String!): Boolean!
@@ -3545,6 +3560,7 @@ type Mutation {
deleteSSOIdentityProvider(input: DeleteSsoInput!): DeleteSso!
editSSOIdentityProvider(input: EditSsoInput!): EditSso!
impersonate(userId: UUID!, workspaceId: UUID!): Impersonate!
sendEmail(input: SendEmailInput!): SendEmailOutput!
startChannelSync(connectedAccountId: UUID!): ChannelSyncSuccess!
saveImapSmtpCaldavAccount(accountOwnerId: UUID!, handle: String!, connectionParameters: EmailAccountConnectionParameters!, id: UUID): ImapSmtpCaldavConnectionSuccess!
updateLabPublicFeatureFlag(input: UpdateLabPublicFeatureFlagInput!): FeatureFlag!
@@ -4515,6 +4531,16 @@ input EditSsoInput {
status: SSOIdentityProviderStatus!
}
input SendEmailInput {
connectedAccountId: String!
to: String!
cc: String
bcc: String
subject: String!
body: String!
inReplyTo: String
}
input EmailAccountConnectionParameters {
IMAP: ConnectionParameters
SMTP: ConnectionParameters
@@ -676,7 +676,7 @@ export interface PageLayoutWidget {
__typename: 'PageLayoutWidget'
}
export type WidgetType = 'VIEW' | 'IFRAME' | 'FIELD' | 'FIELDS' | 'GRAPH' | 'STANDALONE_RICH_TEXT' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE'
export type WidgetType = 'VIEW' | 'IFRAME' | 'FIELD' | 'FIELDS' | 'GRAPH' | 'STANDALONE_RICH_TEXT' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE' | 'EMAIL_THREAD'
export type PageLayoutWidgetPosition = (PageLayoutWidgetGridPosition | PageLayoutWidgetVerticalListPosition | PageLayoutWidgetCanvasPosition) & { __isUnion?: true }
@@ -702,7 +702,7 @@ export interface PageLayoutWidgetCanvasPosition {
__typename: 'PageLayoutWidgetCanvasPosition'
}
export type WidgetConfiguration = (AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration) & { __isUnion?: true }
export type WidgetConfiguration = (AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | EmailThreadConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration) & { __isUnion?: true }
export interface AggregateChartConfiguration {
configurationType: WidgetConfigurationType
@@ -721,7 +721,7 @@ export interface AggregateChartConfiguration {
__typename: 'AggregateChartConfiguration'
}
export type WidgetConfigurationType = 'AGGREGATE_CHART' | 'GAUGE_CHART' | 'PIE_CHART' | 'BAR_CHART' | 'LINE_CHART' | 'IFRAME' | 'STANDALONE_RICH_TEXT' | 'VIEW' | 'FIELD' | 'FIELDS' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE'
export type WidgetConfigurationType = 'AGGREGATE_CHART' | 'GAUGE_CHART' | 'PIE_CHART' | 'BAR_CHART' | 'LINE_CHART' | 'IFRAME' | 'STANDALONE_RICH_TEXT' | 'VIEW' | 'FIELD' | 'FIELDS' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE' | 'EMAIL_THREAD'
export interface StandaloneRichTextConfiguration {
configurationType: WidgetConfigurationType
@@ -869,6 +869,11 @@ export interface EmailsConfiguration {
__typename: 'EmailsConfiguration'
}
export interface EmailThreadConfiguration {
configurationType: WidgetConfigurationType
__typename: 'EmailThreadConfiguration'
}
export interface FieldConfiguration {
configurationType: WidgetConfigurationType
fieldMetadataId: Scalars['String']
@@ -1424,7 +1429,7 @@ export interface PublicFeatureFlag {
__typename: 'PublicFeatureFlag'
}
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED'
export type FeatureFlagKey = 'IS_UNIQUE_INDEXES_ENABLED' | 'IS_JSON_FILTER_ENABLED' | 'IS_AI_ENABLED' | 'IS_COMMAND_MENU_ITEM_ENABLED' | 'IS_MARKETPLACE_ENABLED' | 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' | 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' | 'IS_PUBLIC_DOMAIN_ENABLED' | 'IS_EMAILING_DOMAIN_ENABLED' | 'IS_JUNCTION_RELATIONS_ENABLED' | 'IS_DRAFT_EMAIL_ENABLED' | 'IS_CONNECTED_ACCOUNT_MIGRATED' | 'IS_USAGE_ANALYTICS_ENABLED' | 'IS_RICH_TEXT_V1_MIGRATED' | 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' | 'IS_RECORD_TABLE_WIDGET_ENABLED' | 'IS_DATASOURCE_MIGRATED'
export interface ClientConfigMaintenanceMode {
startAt: Scalars['DateTime']
@@ -2250,7 +2255,7 @@ export interface ConnectedImapSmtpCaldavAccount {
id: Scalars['UUID']
handle: Scalars['String']
provider: Scalars['String']
accountOwnerId: Scalars['UUID']
userWorkspaceId: Scalars['UUID']
connectionParameters?: ImapSmtpCaldavConnectionParameters
__typename: 'ConnectedImapSmtpCaldavAccount'
}
@@ -2290,7 +2295,7 @@ export interface CommandMenuItem {
__typename: 'CommandMenuItem'
}
export type EngineComponentKey = 'NAVIGATE_TO_NEXT_RECORD' | 'NAVIGATE_TO_PREVIOUS_RECORD' | 'CREATE_NEW_RECORD' | 'DELETE_RECORDS' | 'RESTORE_RECORDS' | 'DESTROY_RECORDS' | 'ADD_TO_FAVORITES' | 'REMOVE_FROM_FAVORITES' | 'EXPORT_NOTE_TO_PDF' | 'EXPORT_RECORDS' | 'UPDATE_MULTIPLE_RECORDS' | 'MERGE_MULTIPLE_RECORDS' | 'IMPORT_RECORDS' | 'EXPORT_VIEW' | 'SEE_DELETED_RECORDS' | 'CREATE_NEW_VIEW' | 'HIDE_DELETED_RECORDS' | 'GO_TO_PEOPLE' | 'GO_TO_COMPANIES' | 'GO_TO_DASHBOARDS' | 'GO_TO_OPPORTUNITIES' | 'GO_TO_SETTINGS' | 'GO_TO_TASKS' | 'GO_TO_NOTES' | 'EDIT_RECORD_PAGE_LAYOUT' | 'EDIT_DASHBOARD_LAYOUT' | 'SAVE_DASHBOARD_LAYOUT' | 'CANCEL_DASHBOARD_LAYOUT' | 'DUPLICATE_DASHBOARD' | 'GO_TO_WORKFLOWS' | 'ACTIVATE_WORKFLOW' | 'DEACTIVATE_WORKFLOW' | 'DISCARD_DRAFT_WORKFLOW' | 'TEST_WORKFLOW' | 'SEE_ACTIVE_VERSION_WORKFLOW' | 'SEE_RUNS_WORKFLOW' | 'SEE_VERSIONS_WORKFLOW' | 'ADD_NODE_WORKFLOW' | 'TIDY_UP_WORKFLOW' | 'DUPLICATE_WORKFLOW' | 'GO_TO_RUNS' | 'SEE_VERSION_WORKFLOW_RUN' | 'SEE_WORKFLOW_WORKFLOW_RUN' | 'STOP_WORKFLOW_RUN' | 'SEE_RUNS_WORKFLOW_VERSION' | 'SEE_WORKFLOW_WORKFLOW_VERSION' | 'USE_AS_DRAFT_WORKFLOW_VERSION' | 'SEE_VERSIONS_WORKFLOW_VERSION' | 'SEARCH_RECORDS' | 'SEARCH_RECORDS_FALLBACK' | 'ASK_AI' | 'VIEW_PREVIOUS_AI_CHATS' | 'TRIGGER_WORKFLOW_VERSION' | 'FRONT_COMPONENT_RENDERER' | 'DELETE_SINGLE_RECORD' | 'DELETE_MULTIPLE_RECORDS' | 'RESTORE_SINGLE_RECORD' | 'RESTORE_MULTIPLE_RECORDS' | 'DESTROY_SINGLE_RECORD' | 'DESTROY_MULTIPLE_RECORDS' | 'EXPORT_FROM_RECORD_INDEX' | 'EXPORT_FROM_RECORD_SHOW' | 'EXPORT_MULTIPLE_RECORDS'
export type EngineComponentKey = 'NAVIGATE_TO_NEXT_RECORD' | 'NAVIGATE_TO_PREVIOUS_RECORD' | 'CREATE_NEW_RECORD' | 'DELETE_RECORDS' | 'RESTORE_RECORDS' | 'DESTROY_RECORDS' | 'ADD_TO_FAVORITES' | 'REMOVE_FROM_FAVORITES' | 'EXPORT_NOTE_TO_PDF' | 'EXPORT_RECORDS' | 'UPDATE_MULTIPLE_RECORDS' | 'MERGE_MULTIPLE_RECORDS' | 'IMPORT_RECORDS' | 'EXPORT_VIEW' | 'SEE_DELETED_RECORDS' | 'CREATE_NEW_VIEW' | 'HIDE_DELETED_RECORDS' | 'GO_TO_PEOPLE' | 'GO_TO_COMPANIES' | 'GO_TO_DASHBOARDS' | 'GO_TO_OPPORTUNITIES' | 'GO_TO_SETTINGS' | 'GO_TO_TASKS' | 'GO_TO_NOTES' | 'EDIT_RECORD_PAGE_LAYOUT' | 'EDIT_DASHBOARD_LAYOUT' | 'SAVE_DASHBOARD_LAYOUT' | 'CANCEL_DASHBOARD_LAYOUT' | 'DUPLICATE_DASHBOARD' | 'GO_TO_WORKFLOWS' | 'ACTIVATE_WORKFLOW' | 'DEACTIVATE_WORKFLOW' | 'DISCARD_DRAFT_WORKFLOW' | 'TEST_WORKFLOW' | 'SEE_ACTIVE_VERSION_WORKFLOW' | 'SEE_RUNS_WORKFLOW' | 'SEE_VERSIONS_WORKFLOW' | 'ADD_NODE_WORKFLOW' | 'TIDY_UP_WORKFLOW' | 'DUPLICATE_WORKFLOW' | 'GO_TO_RUNS' | 'SEE_VERSION_WORKFLOW_RUN' | 'SEE_WORKFLOW_WORKFLOW_RUN' | 'STOP_WORKFLOW_RUN' | 'SEE_RUNS_WORKFLOW_VERSION' | 'SEE_WORKFLOW_WORKFLOW_VERSION' | 'USE_AS_DRAFT_WORKFLOW_VERSION' | 'SEE_VERSIONS_WORKFLOW_VERSION' | 'SEARCH_RECORDS' | 'SEARCH_RECORDS_FALLBACK' | 'ASK_AI' | 'VIEW_PREVIOUS_AI_CHATS' | 'TRIGGER_WORKFLOW_VERSION' | 'FRONT_COMPONENT_RENDERER' | 'REPLY_TO_EMAIL_THREAD' | 'COMPOSE_EMAIL' | 'DELETE_SINGLE_RECORD' | 'DELETE_MULTIPLE_RECORDS' | 'RESTORE_SINGLE_RECORD' | 'RESTORE_MULTIPLE_RECORDS' | 'DESTROY_SINGLE_RECORD' | 'DESTROY_MULTIPLE_RECORDS' | 'EXPORT_FROM_RECORD_INDEX' | 'EXPORT_FROM_RECORD_SHOW' | 'EXPORT_MULTIPLE_RECORDS'
export type CommandMenuItemAvailabilityType = 'GLOBAL' | 'RECORD_SELECTION' | 'FALLBACK'
@@ -2411,6 +2416,28 @@ export interface DuplicatedDashboard {
__typename: 'DuplicatedDashboard'
}
export interface ConnectedAccountDTO {
id: Scalars['UUID']
handle: Scalars['String']
provider: Scalars['String']
lastCredentialsRefreshedAt?: Scalars['DateTime']
authFailedAt?: Scalars['DateTime']
handleAliases?: Scalars['String'][]
scopes?: Scalars['String'][]
connectionParameters?: ImapSmtpCaldavConnectionParameters
lastSignedInAt?: Scalars['DateTime']
userWorkspaceId: Scalars['UUID']
createdAt: Scalars['DateTime']
updatedAt: Scalars['DateTime']
__typename: 'ConnectedAccountDTO'
}
export interface SendEmailOutput {
success: Scalars['Boolean']
error?: Scalars['String']
__typename: 'SendEmailOutput'
}
export interface EventLogRecord {
event: Scalars['String']
timestamp: Scalars['DateTime']
@@ -2570,21 +2597,6 @@ export type CalendarChannelVisibility = 'METADATA' | 'SHARE_EVERYTHING'
export type CalendarChannelContactAutoCreationPolicy = 'AS_PARTICIPANT_AND_ORGANIZER' | 'AS_PARTICIPANT' | 'AS_ORGANIZER' | 'NONE'
export interface ConnectedAccountDTO {
id: Scalars['UUID']
handle: Scalars['String']
provider: Scalars['String']
lastCredentialsRefreshedAt?: Scalars['DateTime']
authFailedAt?: Scalars['DateTime']
handleAliases?: Scalars['String'][]
scopes?: Scalars['String'][]
lastSignedInAt?: Scalars['DateTime']
userWorkspaceId: Scalars['UUID']
createdAt: Scalars['DateTime']
updatedAt: Scalars['DateTime']
__typename: 'ConnectedAccountDTO'
}
export interface MessageChannel {
id: Scalars['UUID']
visibility: MessageChannelVisibility
@@ -2628,7 +2640,7 @@ export interface MessageFolder {
name?: Scalars['String']
isSentFolder: Scalars['Boolean']
isSynced: Scalars['Boolean']
parentFolderId?: Scalars['UUID']
parentFolderId?: Scalars['String']
externalId?: Scalars['String']
pendingSyncAction: MessageFolderPendingSyncAction
messageChannelId: Scalars['UUID']
@@ -2774,7 +2786,6 @@ export interface Query {
findApplicationRegistrationStats: ApplicationRegistrationStats
findApplicationRegistrationVariables: ApplicationRegistrationVariable[]
applicationRegistrationTarballUrl?: Scalars['String']
getApplicationShareLink: Scalars['String']
currentUser: User
currentWorkspace: Workspace
getPublicWorkspaceDataByDomain: PublicWorkspaceData
@@ -2819,7 +2830,7 @@ export type SortNulls = 'NULLS_FIRST' | 'NULLS_LAST'
export type EventLogTable = 'WORKSPACE_EVENT' | 'PAGEVIEW' | 'OBJECT_EVENT' | 'USAGE_EVENT'
export type UsageOperationType = 'AI_CHAT_TOKEN' | 'AI_WORKFLOW_TOKEN' | 'WORKFLOW_EXECUTION' | 'CODE_EXECUTION'
export type UsageOperationType = 'AI_CHAT_TOKEN' | 'AI_WORKFLOW_TOKEN' | 'WORKFLOW_EXECUTION' | 'CODE_EXECUTION' | 'WEB_SEARCH'
export interface Mutation {
addQueryToEventStream: Scalars['Boolean']
@@ -2894,6 +2905,7 @@ export interface Mutation {
updatePageLayout: PageLayout
destroyPageLayout: Scalars['Boolean']
updatePageLayoutWithTabsAndWidgets: PageLayout
resetPageLayoutWidgetToDefault: PageLayoutWidget
createPageLayoutWidget: PageLayoutWidget
updatePageLayoutWidget: PageLayoutWidget
destroyPageLayoutWidget: Scalars['Boolean']
@@ -2994,6 +3006,7 @@ export interface Mutation {
deleteSSOIdentityProvider: DeleteSso
editSSOIdentityProvider: EditSso
impersonate: Impersonate
sendEmail: SendEmailOutput
startChannelSync: ChannelSyncSuccess
saveImapSmtpCaldavAccount: ImapSmtpCaldavConnectionSuccess
updateLabPublicFeatureFlag: FeatureFlag
@@ -3790,6 +3803,7 @@ export interface WidgetConfigurationGenqlSelection{
on_CalendarConfiguration?:CalendarConfigurationGenqlSelection,
on_FrontComponentConfiguration?:FrontComponentConfigurationGenqlSelection,
on_EmailsConfiguration?:EmailsConfigurationGenqlSelection,
on_EmailThreadConfiguration?:EmailThreadConfigurationGenqlSelection,
on_FieldConfiguration?:FieldConfigurationGenqlSelection,
on_FieldRichTextConfiguration?:FieldRichTextConfigurationGenqlSelection,
on_FieldsConfiguration?:FieldsConfigurationGenqlSelection,
@@ -3958,6 +3972,12 @@ export interface EmailsConfigurationGenqlSelection{
__scalar?: boolean | number
}
export interface EmailThreadConfigurationGenqlSelection{
configurationType?: boolean | number
__typename?: boolean | number
__scalar?: boolean | number
}
export interface FieldConfigurationGenqlSelection{
configurationType?: boolean | number
fieldMetadataId?: boolean | number
@@ -5431,7 +5451,7 @@ export interface ConnectedImapSmtpCaldavAccountGenqlSelection{
id?: boolean | number
handle?: boolean | number
provider?: boolean | number
accountOwnerId?: boolean | number
userWorkspaceId?: boolean | number
connectionParameters?: ImapSmtpCaldavConnectionParametersGenqlSelection
__typename?: boolean | number
__scalar?: boolean | number
@@ -5603,6 +5623,30 @@ export interface DuplicatedDashboardGenqlSelection{
__scalar?: boolean | number
}
export interface ConnectedAccountDTOGenqlSelection{
id?: boolean | number
handle?: boolean | number
provider?: boolean | number
lastCredentialsRefreshedAt?: boolean | number
authFailedAt?: boolean | number
handleAliases?: boolean | number
scopes?: boolean | number
connectionParameters?: ImapSmtpCaldavConnectionParametersGenqlSelection
lastSignedInAt?: boolean | number
userWorkspaceId?: boolean | number
createdAt?: boolean | number
updatedAt?: boolean | number
__typename?: boolean | number
__scalar?: boolean | number
}
export interface SendEmailOutputGenqlSelection{
success?: boolean | number
error?: boolean | number
__typename?: boolean | number
__scalar?: boolean | number
}
export interface EventLogRecordGenqlSelection{
event?: boolean | number
timestamp?: boolean | number
@@ -5770,22 +5814,6 @@ export interface CalendarChannelGenqlSelection{
__scalar?: boolean | number
}
export interface ConnectedAccountDTOGenqlSelection{
id?: boolean | number
handle?: boolean | number
provider?: boolean | number
lastCredentialsRefreshedAt?: boolean | number
authFailedAt?: boolean | number
handleAliases?: boolean | number
scopes?: boolean | number
lastSignedInAt?: boolean | number
userWorkspaceId?: boolean | number
createdAt?: boolean | number
updatedAt?: boolean | number
__typename?: boolean | number
__scalar?: boolean | number
}
export interface MessageChannelGenqlSelection{
id?: boolean | number
visibility?: boolean | number
@@ -5988,7 +6016,6 @@ export interface QueryGenqlSelection{
findApplicationRegistrationStats?: (ApplicationRegistrationStatsGenqlSelection & { __args: {id: Scalars['String']} })
findApplicationRegistrationVariables?: (ApplicationRegistrationVariableGenqlSelection & { __args: {applicationRegistrationId: Scalars['String']} })
applicationRegistrationTarballUrl?: { __args: {id: Scalars['String']} }
getApplicationShareLink?: { __args: {id: Scalars['String']} }
currentUser?: UserGenqlSelection
currentWorkspace?: WorkspaceGenqlSelection
getPublicWorkspaceDataByDomain?: (PublicWorkspaceDataGenqlSelection & { __args?: {origin?: (Scalars['String'] | null)} })
@@ -6127,6 +6154,7 @@ export interface MutationGenqlSelection{
updatePageLayout?: (PageLayoutGenqlSelection & { __args: {id: Scalars['String'], input: UpdatePageLayoutInput} })
destroyPageLayout?: { __args: {id: Scalars['String']} }
updatePageLayoutWithTabsAndWidgets?: (PageLayoutGenqlSelection & { __args: {id: Scalars['String'], input: UpdatePageLayoutWithTabsInput} })
resetPageLayoutWidgetToDefault?: (PageLayoutWidgetGenqlSelection & { __args: {id: Scalars['String']} })
createPageLayoutWidget?: (PageLayoutWidgetGenqlSelection & { __args: {input: CreatePageLayoutWidgetInput} })
updatePageLayoutWidget?: (PageLayoutWidgetGenqlSelection & { __args: {id: Scalars['String'], input: UpdatePageLayoutWidgetInput} })
destroyPageLayoutWidget?: { __args: {id: Scalars['String']} }
@@ -6227,6 +6255,7 @@ export interface MutationGenqlSelection{
deleteSSOIdentityProvider?: (DeleteSsoGenqlSelection & { __args: {input: DeleteSsoInput} })
editSSOIdentityProvider?: (EditSsoGenqlSelection & { __args: {input: EditSsoInput} })
impersonate?: (ImpersonateGenqlSelection & { __args: {userId: Scalars['UUID'], workspaceId: Scalars['UUID']} })
sendEmail?: (SendEmailOutputGenqlSelection & { __args: {input: SendEmailInput} })
startChannelSync?: (ChannelSyncSuccessGenqlSelection & { __args: {connectedAccountId: Scalars['UUID']} })
saveImapSmtpCaldavAccount?: (ImapSmtpCaldavConnectionSuccessGenqlSelection & { __args: {accountOwnerId: Scalars['UUID'], handle: Scalars['String'], connectionParameters: EmailAccountConnectionParameters, id?: (Scalars['UUID'] | null)} })
updateLabPublicFeatureFlag?: (FeatureFlagGenqlSelection & { __args: {input: UpdateLabPublicFeatureFlagInput} })
@@ -6577,6 +6606,8 @@ export interface DeleteSsoInput {identityProviderId: Scalars['UUID']}
export interface EditSsoInput {id: Scalars['UUID'],status: SSOIdentityProviderStatus}
export interface SendEmailInput {connectedAccountId: Scalars['String'],to: Scalars['String'],cc?: (Scalars['String'] | null),bcc?: (Scalars['String'] | null),subject: Scalars['String'],body: Scalars['String'],inReplyTo?: (Scalars['String'] | null)}
export interface EmailAccountConnectionParameters {IMAP?: (ConnectionParameters | null),SMTP?: (ConnectionParameters | null),CALDAV?: (ConnectionParameters | null)}
export interface ConnectionParameters {host: Scalars['String'],port: Scalars['Float'],username?: (Scalars['String'] | null),password: Scalars['String'],secure?: (Scalars['Boolean'] | null)}
@@ -6956,7 +6987,7 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const WidgetConfiguration_possibleTypes: string[] = ['AggregateChartConfiguration','StandaloneRichTextConfiguration','PieChartConfiguration','LineChartConfiguration','IframeConfiguration','GaugeChartConfiguration','BarChartConfiguration','CalendarConfiguration','FrontComponentConfiguration','EmailsConfiguration','FieldConfiguration','FieldRichTextConfiguration','FieldsConfiguration','FilesConfiguration','NotesConfiguration','TasksConfiguration','TimelineConfiguration','ViewConfiguration','RecordTableConfiguration','WorkflowConfiguration','WorkflowRunConfiguration','WorkflowVersionConfiguration']
const WidgetConfiguration_possibleTypes: string[] = ['AggregateChartConfiguration','StandaloneRichTextConfiguration','PieChartConfiguration','LineChartConfiguration','IframeConfiguration','GaugeChartConfiguration','BarChartConfiguration','CalendarConfiguration','FrontComponentConfiguration','EmailsConfiguration','EmailThreadConfiguration','FieldConfiguration','FieldRichTextConfiguration','FieldsConfiguration','FilesConfiguration','NotesConfiguration','TasksConfiguration','TimelineConfiguration','ViewConfiguration','RecordTableConfiguration','WorkflowConfiguration','WorkflowRunConfiguration','WorkflowVersionConfiguration']
export const isWidgetConfiguration = (obj?: { __typename?: any } | null): obj is WidgetConfiguration => {
if (!obj?.__typename) throw new Error('__typename is missing in "isWidgetConfiguration"')
return WidgetConfiguration_possibleTypes.includes(obj.__typename)
@@ -7044,6 +7075,14 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const EmailThreadConfiguration_possibleTypes: string[] = ['EmailThreadConfiguration']
export const isEmailThreadConfiguration = (obj?: { __typename?: any } | null): obj is EmailThreadConfiguration => {
if (!obj?.__typename) throw new Error('__typename is missing in "isEmailThreadConfiguration"')
return EmailThreadConfiguration_possibleTypes.includes(obj.__typename)
}
const FieldConfiguration_possibleTypes: string[] = ['FieldConfiguration']
export const isFieldConfiguration = (obj?: { __typename?: any } | null): obj is FieldConfiguration => {
if (!obj?.__typename) throw new Error('__typename is missing in "isFieldConfiguration"')
@@ -8476,6 +8515,22 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const ConnectedAccountDTO_possibleTypes: string[] = ['ConnectedAccountDTO']
export const isConnectedAccountDTO = (obj?: { __typename?: any } | null): obj is ConnectedAccountDTO => {
if (!obj?.__typename) throw new Error('__typename is missing in "isConnectedAccountDTO"')
return ConnectedAccountDTO_possibleTypes.includes(obj.__typename)
}
const SendEmailOutput_possibleTypes: string[] = ['SendEmailOutput']
export const isSendEmailOutput = (obj?: { __typename?: any } | null): obj is SendEmailOutput => {
if (!obj?.__typename) throw new Error('__typename is missing in "isSendEmailOutput"')
return SendEmailOutput_possibleTypes.includes(obj.__typename)
}
const EventLogRecord_possibleTypes: string[] = ['EventLogRecord']
export const isEventLogRecord = (obj?: { __typename?: any } | null): obj is EventLogRecord => {
if (!obj?.__typename) throw new Error('__typename is missing in "isEventLogRecord"')
@@ -8604,14 +8659,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const ConnectedAccountDTO_possibleTypes: string[] = ['ConnectedAccountDTO']
export const isConnectedAccountDTO = (obj?: { __typename?: any } | null): obj is ConnectedAccountDTO => {
if (!obj?.__typename) throw new Error('__typename is missing in "isConnectedAccountDTO"')
return ConnectedAccountDTO_possibleTypes.includes(obj.__typename)
}
const MessageChannel_possibleTypes: string[] = ['MessageChannel']
export const isMessageChannel = (obj?: { __typename?: any } | null): obj is MessageChannel => {
if (!obj?.__typename) throw new Error('__typename is missing in "isMessageChannel"')
@@ -8912,7 +8959,8 @@ export const enumWidgetType = {
WORKFLOW_VERSION: 'WORKFLOW_VERSION' as const,
WORKFLOW_RUN: 'WORKFLOW_RUN' as const,
FRONT_COMPONENT: 'FRONT_COMPONENT' as const,
RECORD_TABLE: 'RECORD_TABLE' as const
RECORD_TABLE: 'RECORD_TABLE' as const,
EMAIL_THREAD: 'EMAIL_THREAD' as const
}
export const enumPageLayoutTabLayoutMode = {
@@ -8943,7 +8991,8 @@ export const enumWidgetConfigurationType = {
WORKFLOW_VERSION: 'WORKFLOW_VERSION' as const,
WORKFLOW_RUN: 'WORKFLOW_RUN' as const,
FRONT_COMPONENT: 'FRONT_COMPONENT' as const,
RECORD_TABLE: 'RECORD_TABLE' as const
RECORD_TABLE: 'RECORD_TABLE' as const,
EMAIL_THREAD: 'EMAIL_THREAD' as const
}
export const enumObjectRecordGroupByDateGranularity = {
@@ -9092,16 +9141,16 @@ export const enumFeatureFlagKey = {
IS_AI_ENABLED: 'IS_AI_ENABLED' as const,
IS_COMMAND_MENU_ITEM_ENABLED: 'IS_COMMAND_MENU_ITEM_ENABLED' as const,
IS_MARKETPLACE_ENABLED: 'IS_MARKETPLACE_ENABLED' as const,
IS_MARKETPLACE_SETTING_TAB_VISIBLE: 'IS_MARKETPLACE_SETTING_TAB_VISIBLE' as const,
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED: 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED' as const,
IS_PUBLIC_DOMAIN_ENABLED: 'IS_PUBLIC_DOMAIN_ENABLED' as const,
IS_EMAILING_DOMAIN_ENABLED: 'IS_EMAILING_DOMAIN_ENABLED' as const,
IS_JUNCTION_RELATIONS_ENABLED: 'IS_JUNCTION_RELATIONS_ENABLED' as const,
IS_DRAFT_EMAIL_ENABLED: 'IS_DRAFT_EMAIL_ENABLED' as const,
IS_CONNECTED_ACCOUNT_MIGRATED: 'IS_CONNECTED_ACCOUNT_MIGRATED' as const,
IS_USAGE_ANALYTICS_ENABLED: 'IS_USAGE_ANALYTICS_ENABLED' as const,
IS_RICH_TEXT_V1_MIGRATED: 'IS_RICH_TEXT_V1_MIGRATED' as const,
IS_DIRECT_GRAPHQL_EXECUTION_ENABLED: 'IS_DIRECT_GRAPHQL_EXECUTION_ENABLED' as const,
IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED: 'IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED' as const,
IS_CONNECTED_ACCOUNT_MIGRATED: 'IS_CONNECTED_ACCOUNT_MIGRATED' as const,
IS_RECORD_TABLE_WIDGET_ENABLED: 'IS_RECORD_TABLE_WIDGET_ENABLED' as const,
IS_DATASOURCE_MIGRATED: 'IS_DATASOURCE_MIGRATED' as const
}
@@ -9252,6 +9301,8 @@ export const enumEngineComponentKey = {
VIEW_PREVIOUS_AI_CHATS: 'VIEW_PREVIOUS_AI_CHATS' as const,
TRIGGER_WORKFLOW_VERSION: 'TRIGGER_WORKFLOW_VERSION' as const,
FRONT_COMPONENT_RENDERER: 'FRONT_COMPONENT_RENDERER' as const,
REPLY_TO_EMAIL_THREAD: 'REPLY_TO_EMAIL_THREAD' as const,
COMPOSE_EMAIL: 'COMPOSE_EMAIL' as const,
DELETE_SINGLE_RECORD: 'DELETE_SINGLE_RECORD' as const,
DELETE_MULTIPLE_RECORDS: 'DELETE_MULTIPLE_RECORDS' as const,
RESTORE_SINGLE_RECORD: 'RESTORE_SINGLE_RECORD' as const,
@@ -9408,7 +9459,8 @@ export const enumUsageOperationType = {
AI_CHAT_TOKEN: 'AI_CHAT_TOKEN' as const,
AI_WORKFLOW_TOKEN: 'AI_WORKFLOW_TOKEN' as const,
WORKFLOW_EXECUTION: 'WORKFLOW_EXECUTION' as const,
CODE_EXECUTION: 'CODE_EXECUTION' as const
CODE_EXECUTION: 'CODE_EXECUTION' as const,
WEB_SEARCH: 'WEB_SEARCH' as const
}
export const enumAnalyticsType = {
File diff suppressed because it is too large Load Diff
@@ -52,7 +52,11 @@ yarn twenty deploy
### Sharing a deployed app
Tarball apps are not listed in the public marketplace, so other workspaces on the same server won't discover them by browsing. To share a deployed app:
<Warning>
Sharing private (tarball) apps across workspaces is an **Enterprise** feature. The **Distribution** tab will show an upgrade prompt instead of the share controls until your workspace has a valid Enterprise key. See [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to activate it.
</Warning>
Tarball apps are not listed in the public marketplace, so other workspaces on the same server won't discover them by browsing. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. Go to **Settings > Applications > Registrations** and open your app
2. In the **Distribution** tab, click **Copy share link**
@@ -60,10 +64,6 @@ Tarball apps are not listed in the public marketplace, so other workspaces on th
The share link uses the server's base URL (without any workspace subdomain) so it works for any workspace on the server.
<Warning>
Sharing private apps is an Enterprise feature. Go to [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to enable it.
</Warning>
### Version management
To release an update:
@@ -81,7 +81,7 @@ import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
universalIdentifier: '39783023-bcac-41e3-b0d2-ff1944d8465d',
displayName: 'My Twenty App',
description: 'My first Twenty app',
icon: 'IconWorld',
@@ -716,6 +716,13 @@ yarn twenty exec --postInstall
المكوّنات الأمامية هي مكوّنات React تُعرَض مباشرة داخل واجهة مستخدم Twenty. تعمل ضمن **Web Worker** معزول باستخدام Remote DOM — تكون شيفرتك في صندوق عزل لكنها تُعرَض أصيلًا داخل الصفحة، وليس ضمن iframe.
#### أين يمكن استخدام مكوّنات الواجهة الأمامية
يمكن عرض مكوّنات الواجهة الأمامية في موقعين داخل Twenty:
* **اللوحة الجانبية** — المكوّنات غير عديمة الرأس تفتح في اللوحة الجانبية اليمنى. هذا هو السلوك الافتراضي عندما يتم تشغيل مكوّن واجهة أمامية من قائمة الأوامر.
* **الويدجت (لوحات المعلومات وصفحات السجلات)** — يمكن تضمين مكوّنات الواجهة الأمامية كويدجت داخل تخطيطات الصفحات. عند تكوين لوحة معلومات أو تخطيط صفحة سجل، يمكن للمستخدمين إضافة ويدجت لمكوّن واجهة أمامية.
#### مثال أساسي
أسرع طريقة لرؤية مكوّن أمامي قيد العمل هي تسجيله كأمر. إضافة حقل `command` مع `isPinned: true` يجعلُه يظهر كزر إجراء سريع في الزاوية العلوية اليمنى من الصفحة — دون الحاجة إلى تخطيط صفحة:
@@ -773,9 +780,13 @@ export default defineFrontComponent({
إضافةً إلى الأوامر، يمكنك تضمين مكوّن أمامي مباشرةً في صفحة سجل عبر إضافته كودجت في **تخطيط صفحة**. راجع قسم [definePageLayout](#definepagelayout) للتفاصيل.
#### مكوّنات عديمة الواجهة (`isHeadless: true`)
#### عديم الرأس مقابل غير عديم الرأس
المكوّنات عديمة الواجهة لا تُظهر واجهة مرئية لكنها ما تزال تُشغِّل منطق React. يكون هذا مفيدًا لـ **مكوّنات التأثير** — وهي مكوّنات تُجري تأثيرات جانبية عند التثبيت، مثل مزامنة البيانات، بدء مؤقّت، الاستماع إلى الأحداث، أو إطلاق إشعار.
تأتي مكوّنات الواجهة الأمامية بوضعَي عرض يتحكّم بهما الخيار `isHeadless`:
**غير عديم الرأس (افتراضي)** — يعرض المكوّن واجهة مستخدم مرئية. عند تشغيله من قائمة الأوامر يفتح في اللوحة الجانبية. هذا هو السلوك الافتراضي عندما تكون `isHeadless` تساوي `false` أو يتم تجاهلها.
**عديم الرأس (`isHeadless: true`)** — يتم تركيب المكوّن بشكل غير مرئي في الخلفية. لا يفتح اللوحة الجانبية. تم تصميم المكوّنات عديمة الرأس لإجراءات تنفّذ منطقًا ثم تُزيل تركيبها ذاتيًا — على سبيل المثال، تشغيل مهمة غير متزامنة، أو الانتقال إلى صفحة، أو إظهار نافذة تأكيد منبثقة. تتوافق بشكل طبيعي مع مكوّنات Command في SDK الموصوفة أدناه.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
@@ -802,6 +813,89 @@ export default defineFrontComponent({
نظرًا لأن المكوّن يُرجع `null`، فإن Twenty يتخطّى عرض حاوية له — ولن تظهر مساحة فارغة في التخطيط. لا يزال لدى المكوّن إمكانية الوصول إلى جميع الخطافات وواجهة برمجة الاتصال مع المضيف.
#### مكوّنات Command في SDK
توفر حزمة `twenty-sdk` أربعة مكوّنات مساعدة من نوع Command مصممة للمكوّنات عديمة الرأس في الواجهة الأمامية. كل مكوّن ينفّذ إجراءً عند التركيب، ويتعامل مع الأخطاء بعرض إشعار Snackbar، ويزيل تركيب مكوّن الواجهة الأمامية تلقائيًا عند الانتهاء.
استوردها من `twenty-sdk/command`:
* **`Command`** — يشغّل رد نداء غير متزامن عبر الخاصية `execute`.
* **`CommandLink`** — ينتقل إلى مسار في التطبيق. الخصائص: `to`، `params`، `queryParams`، `options`.
* **`CommandModal`** — يفتح نافذة تأكيد منبثقة. إذا أكّد المستخدم، ينفّذ رد النداء `execute`. الخصائص: `title`، `subtitle`، `execute`، `confirmButtonText`، `confirmButtonAccent`.
* **`CommandOpenSidePanelPage`** — يفتح صفحة محدّدة في اللوحة الجانبية. الخصائص: `page`، `pageTitle`، `pageIcon`.
فيما يلي مثال كامل لمكوّن واجهة أمامية عديم الرأس يستخدم `Command` لتشغيل إجراء من قائمة الأوامر:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
command: {
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
},
});
```
ومثال يستخدم `CommandModal` لطلب التأكيد قبل التنفيذ:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
const execute = async () => {
// perform the deletion
};
return (
<CommandModal
title="Delete draft?"
subtitle="This action cannot be undone."
execute={execute}
confirmButtonText="Delete"
confirmButtonAccent="danger"
/>
);
};
export default defineFrontComponent({
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
name: 'delete-draft',
description: 'Deletes a draft with confirmation',
component: DeleteDraft,
isHeadless: true,
command: {
universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
label: 'Delete draft',
icon: 'IconTrash',
},
});
```
#### الوصول إلى سياق وقت التشغيل
داخل مكوّنك، استخدم خطافات SDK للوصول إلى المستخدم الحالي، والسجل، ومثيل المكوّن:
@@ -858,6 +952,50 @@ export default defineFrontComponent({
| `unmountFrontComponent()` | إلغاء تركيب المكوّن |
| `updateProgress(progress)` | تحديث مؤشّر التقدّم |
فيما يلي مثال يستخدم واجهة برمجة تطبيقات المضيف لعرض Snackbar وإغلاق اللوحة الجانبية بعد اكتمال الإجراء:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
const recordId = useRecordId();
const handleArchive = async () => {
const client = new CoreApiClient();
await client.mutation({
updateTask: {
__args: { id: recordId, data: { status: 'ARCHIVED' } },
id: true,
},
});
await enqueueSnackbar({
message: 'Record archived',
variant: 'success',
});
await closeSidePanel();
};
return (
<div style={{ padding: '20px' }}>
<p>Archive this record?</p>
<button onClick={handleArchive}>Archive</button>
</div>
);
};
export default defineFrontComponent({
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
name: 'archive-record',
description: 'Archives the current record',
component: ArchiveRecord,
});
```
#### خيارات الأوامر
إضافة حقل `command` إلى `defineFrontComponent` تُسجِّل المكوّن في قائمة الأوامر (Cmd+K). إذا كانت قيمة `isPinned` هي `true`، فسيظهر أيضًا كزر إجراء سريع في الزاوية العلوية اليمنى من الصفحة.
@@ -1712,3 +1850,86 @@ yarn twenty uninstall
# Skip the confirmation prompt
yarn twenty uninstall --yes
```
## إدارة الريموتات
**الريموت** هو خادم Twenty يتصل به تطبيقك. أثناء الإعداد، تُنشئ أداة إنشاء الهيكل واحدًا لك تلقائيًا. يمكنك إضافة ريموتات أخرى أو التبديل بينها في أي وقت.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
تُخزَّن بيانات اعتمادك في `~/.twenty/config.json`.
## التكامل المستمر (CI) باستخدام GitHub Actions
تولّد أداة إنشاء الهيكل سير عمل GitHub Actions جاهزًا للاستخدام في `.github/workflows/ci.yml`. يشغّل اختبارات التكامل لديك تلقائيًا عند كل دفع إلى `main` وعلى طلبات السحب.
سير العمل:
1. يجلب الشيفرة الخاصة بك
2. يشغّل خادم Twenty مؤقتًا باستخدام الإجراء `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. يثبّت التبعيات باستخدام `yarn install --immutable`
4. يشغّل `yarn test` مع حقن `TWENTY_API_URL` و`TWENTY_API_KEY` من مخرجات الإجراء
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
لا تحتاج إلى تهيئة أي أسرار — إذ يبدأ إجراء `spawn-twenty-docker-image` خادم Twenty عابرًا مباشرة في المشغّل ويُخرِج تفاصيل الاتصال. يتم توفير السر `GITHUB_TOKEN` تلقائيًا من قِبل GitHub.
لتثبيت إصدار محدّد من Twenty بدلًا من `latest`، غيّر متغير البيئة `TWENTY_VERSION` في أعلى سير العمل.
@@ -7,7 +7,9 @@ description: أنشئ أول تطبيق Twenty خلال دقائق.
التطبيقات حاليًا في مرحلة الألفا. الميزة تعمل لكنها لا تزال قيد التطور.
</Warning>
تتيح لك التطبيقات توسيع Twenty باستخدام كائنات وحقول ووظائف منطقية ومهارات ذكاء اصطناعي ومكونات واجهة مستخدم مخصصة — جميعها تُدار ككود.
## ما هي التطبيقات؟
تتيح لك التطبيقات توسيع Twenty باستخدام كائنات وحقول مخصّصة ووظائف منطقية ومكوّنات الواجهة الأمامية ومهارات الذكاء الاصطناعي وغير ذلك — جميعها تُدار ككود. بدلًا من تكوين كل شيء عبر واجهة المستخدم، تعرّف نموذج بياناتك ومنطقك في TypeScript وتقوم بنشره إلى مساحة عمل واحدة أو أكثر.
## المتطلبات الأساسية
@@ -17,7 +19,9 @@ description: أنشئ أول تطبيق Twenty خلال دقائق.
* **Yarn 4** — يأتي مع Node.js عبر Corepack. قم بتمكينه عبر تشغيل `corepack enable`
* **Docker** — [نزّل من هنا](https://www.docker.com/products/docker-desktop/). مطلوب لتشغيل مثيل محلي من Twenty. غير مطلوب إذا كان لديك خادم Twenty قيد التشغيل بالفعل.
## الخطوة 1: إنشاء هيكل تطبيقك
## قم بإنشاء تطبيقك الأول
### أنشئ هيكل تطبيقك
افتح الطرفية وشغّل:
@@ -29,18 +33,7 @@ npx create-twenty-app@latest my-twenty-app
سيؤدي ذلك إلى إنشاء مجلد جديد باسم `my-twenty-app` يحتوي على كل ما تحتاجه.
<Note>
أداة إنشاء الهيكل تدعم الأعلام التالية:
* `--minimal` — إنشاء الهيكل للملفات الأساسية فقط، بدون أمثلة (افتراضي)
* `--exhaustive` — إنشاء الهيكل لجميع كيانات الأمثلة
* `--name <name>` — تعيين اسم التطبيق (يتخطى المطالبة)
* `--display-name <displayName>` — تعيين اسم العرض (يتخطى المطالبة)
* `--description <description>` — تعيين الوصف (يتخطى المطالبة)
* `--skip-local-instance` — تخطي مطالبة إعداد الخادم المحلي
</Note>
## الخطوة 2: إعداد مثيل محلي من Twenty
### إعداد مثيل محلي من Twenty
ستسأل أداة إنشاء الهيكل:
@@ -53,7 +46,7 @@ npx create-twenty-app@latest my-twenty-app
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="هل يجب بدء المثيل المحلي؟" />
</div>
## الخطوة 3: سجّل الدخول إلى مساحة العمل الخاصة بك
### سجّل الدخول إلى مساحة العمل الخاصة بك
بعد ذلك، ستُفتح نافذة متصفح تعرض صفحة تسجيل الدخول الخاصة بـ Twenty. سجّل الدخول باستخدام حساب العرض التوضيحي المُجهَّز مسبقًا:
@@ -64,7 +57,7 @@ npx create-twenty-app@latest my-twenty-app
<img src="/images/docs/developers/extends/apps/login.png" alt="شاشة تسجيل الدخول إلى Twenty" />
</div>
## الخطوة 4: تفويض التطبيق
### قم بتفويض التطبيق
بعد تسجيل الدخول، ستظهر لك شاشة تفويض. يتيح هذا لتطبيقك التفاعل مع مساحة العمل الخاصة بك.
@@ -80,7 +73,7 @@ npx create-twenty-app@latest my-twenty-app
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="تم إنشاء هيكل التطبيق بنجاح" />
</div>
## الخطوة 5: ابدأ التطوير
### ابدأ التطوير
انتقل إلى مجلد تطبيقك الجديد وابدأ خادم التطوير:
@@ -105,7 +98,7 @@ yarn twenty dev --verbose
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="مخرجات الطرفية في وضع التطوير" />
</div>
## الخطوة 6: اعرض تطبيقك في Twenty
### اعرض تطبيقك في Twenty
افتح [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) في متصفحك. انتقل إلى **Settings > Apps** واختر علامة التبويب **Developer**. يُفترض أن ترى تطبيقك مُدرجًا تحت **Your Apps**:
@@ -133,13 +126,28 @@ yarn twenty dev --verbose
أنت جاهز تمامًا! حرّر أي ملف في `src/` وسيتم التقاط التغييرات تلقائيًا.
انتقل إلى [بناء التطبيقات](/l/ar/developers/extend/apps/building) للحصول على دليل مفصّل حول إنشاء الكائنات، ودوال المنطق، ومكونات الواجهة الأمامية، والمهارات، والمزيد.
---
## ما الذي يمكنك بناؤه
تتكون التطبيقات من **كيانات** — يُعرَّف كل منها كملف TypeScript يحتوي على `export default` واحد:
| كيان | ماذا يفعل |
| ---------------------- | ------------------------------------------------------------------------------------------------- |
| **الكائنات والحقول** | عرّف نماذج بيانات مخصّصة (مثل Post Card، Invoice) مع حقول محددة النوع |
| **الوظائف المنطقية** | دوال TypeScript على جانب الخادم يتم تشغيلها عبر مسارات HTTP، وجداول cron، أو أحداث قاعدة البيانات |
| **المكوّنات الأمامية** | مكوّنات React تُعرَض داخل واجهة مستخدم Twenty (اللوحة الجانبية، الودجات، قائمة الأوامر) |
| **المهارات والوكلاء** | قدرات الذكاء الاصطناعي — تعليمات قابلة لإعادة الاستخدام ومساعدون مستقلون ذاتيًا |
| **طرق العرض والتنقّل** | طرق عرض القوائم مُعدّة مسبقًا وعناصر قائمة الشريط الجانبي لكائناتك |
| **تخطيطات الصفحات** | صفحات تفاصيل سجلات مخصصة تتضمن علامات تبويب وعناصر واجهة |
انتقل إلى [بناء التطبيقات](/l/ar/developers/extend/apps/building) للاطلاع على دليل مفصّل لكل نوع من الكيانات.
---
## هيكل المشروع
تولّد أداة إنشاء الهيكل بنية الملفات التالية (مُبيّنة بوضع `--exhaustive` الذي يتضمن أمثلة لكل نوع من الكيانات):
تولّد أداة إنشاء الهيكل بنية الملفات التالية:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -148,160 +156,50 @@ my-twenty-app/
.gitignore
.nvmrc
.yarnrc.yml
.yarn/
install-state.gz
.oxlintrc.json
tsconfig.json
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
LLMS.md
README.md
.github/
└── workflows/
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
src/
├── application-config.ts # Required — main application configuration
├── __tests__/
├── setup-test.ts # Test setup (server health check, config)
│ └── app-install.integration-test.ts # Example integration test
── roles/
── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── create-hello-world-company.ts # Example logic function using CoreApiClient
│ ├── pre-install.ts # Runs before installation
│ └── post-install.ts # Runs after installation
├── front-components/
│ └── hello-world.tsx # Example front component
├── page-layouts/
│ └── example-record-page-layout.ts # Example page layout with front component
├── views/
│ └── example-view.ts # Example saved view definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
├── skills/
│ └── example-skill.ts # Example AI agent skill definition
└── agents/
└── example-agent.ts # Example AI agent definition
├── application-config.ts # Required — main application configuration
├── default-role.ts # Default role for logic functions
├── constants/
│ └── universal-identifiers.ts # Auto-generated UUIDs and app metadata
── __tests__/
── setup-test.ts # Test setup (server health check, config)
└── app-install.integration-test.ts # Integration test
```
افتراضيًا (`--minimal`)، تُنشأ الملفات الأساسية فقط: `application-config.ts`، `roles/default-role.ts`، `logic-functions/pre-install.ts`، و`logic-functions/post-install.ts`. استخدم `--exhaustive` لتضمين جميع ملفات الأمثلة الموضّحة أعلاه.
### البدء من مثال
للبدء من مثال أكثر اكتمالًا يضم كائنات وحقولًا مخصّصة، ودوال المنطق، ومكوّنات الواجهة الأمامية، وغير ذلك، استخدم الخيار `--example`:
```bash filename="Terminal"
npx create-twenty-app@latest my-twenty-app --example postcard
```
تُستمد الأمثلة من الدليل [twenty-apps/examples](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples) على GitHub. يمكنك أيضًا إنشاء هيكل لكيانات فردية داخل مشروع قائم باستخدام `yarn twenty add` (انظر [بناء التطبيقات](/l/ar/developers/extend/apps/building#scaffolding-entities-with-yarn-twenty-add)).
### الملفات الرئيسية
| ملف / مجلد | الغرض |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `package.json` | يصرّح باسم تطبيقك وإصداره واعتماداته. يتضمن نصًا برمجيًا باسم `twenty` بحيث يمكنك تشغيل `yarn twenty help` للاطلاع على جميع الأوامر. |
| `src/application-config.ts` | **مطلوب.** ملف الإعداد الرئيسي لتطبيقك. |
| `src/roles/` | يعرِّف الأدوار التي تتحكم بما يمكن لدوال المنطق الوصول إليه. |
| `src/logic-functions/` | دوال على جانب الخادم يتم تشغيلها عبر المسارات، وجداول cron، أو أحداث قاعدة البيانات. |
| `src/front-components/` | مكونات React تُعرَض داخل واجهة مستخدم Twenty. |
| `src/objects/` | تعريفات كائنات مخصّصة لتوسيع نموذج البيانات لديك. |
| `src/fields/` | حقول مخصّصة تُضاف إلى الكائنات الموجودة. |
| `src/views/` | تكوينات العروض المحفوظة. |
| `src/navigation-menu-items/` | روابط مخصّصة في شريط التنقل الجانبي. |
| `src/skills/` | مهارات توسّع قدرات وكلاء الذكاء الاصطناعي في Twenty. |
| `src/agents/` | وكلاء ذكاء اصطناعي مع موجهات مخصّصة. |
| `src/page-layouts/` | تخطيطات صفحات مخصّصة لعرض السجلات. |
| `src/__tests__/` | اختبارات تكامل (إعداد + اختبار مثال). |
| `public/` | أصول ثابتة (صور، خطوط) تُقدَّم مع تطبيقك. |
| ملف / مجلد | الغرض |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `package.json` | يصرّح باسم تطبيقك وإصداره واعتماداته. يتضمن نصًا برمجيًا باسم `twenty` بحيث يمكنك تشغيل `yarn twenty help` للاطلاع على جميع الأوامر. |
| `src/application-config.ts` | **مطلوب.** ملف الإعداد الرئيسي لتطبيقك. |
| `src/default-role.ts` | الدور الافتراضي الذي يتحكم بما يمكن لدوال المنطق الوصول إليه. |
| `src/constants/universal-identifiers.ts` | معرّفات UUID وبيانات التعريف للتطبيق، والمولَّدة تلقائيًا (اسم العرض، الوصف). |
| `src/__tests__/` | اختبارات تكامل (إعداد + اختبار مثال). |
| `public/` | أصول ثابتة (صور، خطوط) تُقدَّم مع تطبيقك. |
## إدارة الريموتات
## خادم التطوير المحلي
**الريموت** هو خادم Twenty يتصل به تطبيقك. أثناء الإعداد، تُنشئ أداة إنشاء الهيكل واحدًا لك تلقائيًا. يمكنك إضافة ريموتات أخرى أو التبديل بينها في أي وقت.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
تُخزَّن بيانات اعتمادك في `~/.twenty/config.json`.
## خادم التطوير المحلي (`yarn twenty server`)
يمكن لأداة سطر الأوامر (CLI) إدارة خادم Twenty محلي يعمل داخل Docker. هذا هو الخادم نفسه الذي يبدأ تلقائيًا عند إنشاء هيكل تطبيق باستخدام `create-twenty-app`، لكن يمكنك أيضًا إدارته يدويًا.
### بدء الخادم
```bash filename="Terminal"
yarn twenty server start
```
سيؤدي ذلك إلى سحب صورة Docker `twentycrm/twenty-app-dev:latest` (إن لم تكن موجودة بالفعل)، وإنشاء حاوية باسم `twenty-app-dev`، وبدء تشغيلها على المنفذ **2020**. تنتظر أداة CLI حتى يجتاز الخادم فحص السلامة قبل الإنهاء.
يتم إنشاء حجمين في Docker للاحتفاظ بالبيانات بين عمليات إعادة التشغيل:
* `twenty-app-dev-data` — قاعدة بيانات PostgreSQL
* `twenty-app-dev-storage` — تخزين ملفات
إذا كان المنفذ 2020 مستخدمًا بالفعل، يمكنك البدء على منفذ مختلف:
```bash filename="Terminal"
yarn twenty server start --port 3030
```
تقوم أداة CLI تلقائيًا بتهيئة قيم `NODE_PORT` و`SERVER_URL` الداخلية في الحاوية لتطابق المنفذ المختار، بحيث تعمل دوال المنطق وOAuth وكل الشبكات الداخلية الأخرى بشكل صحيح.
بمجرد البدء، يُسجَّل الخادم تلقائيًا كـ `local` remote في إعدادات CLI لديك.
### التحقق من حالة الخادم
```bash filename="Terminal"
yarn twenty server status
```
يعرض ما إذا كان الخادم قيد التشغيل، وعنوان URL الخاص به، وبيانات اعتماد تسجيل الدخول الافتراضية (`[email protected]` / `[email protected]`).
### عرض سجلات الخادم
```bash filename="Terminal"
yarn twenty server logs
```
يبث سجلات الحاوية. استخدم `--lines` للتحكّم بعدد الأسطر الحديثة المراد عرضها:
```bash filename="Terminal"
yarn twenty server logs --lines 100
```
### إيقاف الخادم
```bash filename="Terminal"
yarn twenty server stop
```
يوقف الحاوية. تُحفَظ بياناتك في أحجام Docker — وستُستأنف الحالة مع عملية `start` التالية من حيث توقفت.
### إعادة تعيين الخادم
```bash filename="Terminal"
yarn twenty server reset
```
يزيل الحاوية **و** يحذف كلا حجمي Docker، ممّا يمحو جميع البيانات. ستنشئ عملية `start` التالية مثيلًا جديدًا من البداية.
<Note>
يتطلّب الخادم أن يكون **Docker** قيد التشغيل. إذا ظهرت لك رسالة خطأ "Docker not running"، فتأكّد من تشغيل Docker Desktop (أو خادوم Docker).
</Note>
### مرجع الأوامر
لقد قامت أداة إنشاء الهيكل بالفعل بتشغيل خادم Twenty محليًا لك. لإدارته لاحقًا، استخدم `yarn twenty server`:
| أمر | الوصف |
| -------------------------------------- | --------------------------------------------- |
@@ -313,65 +211,11 @@ yarn twenty server reset
| `yarn twenty server logs --lines 100` | عرض آخر 100 سطر من السجلات |
| `yarn twenty server reset` | حذف جميع البيانات والبدء من جديد |
## التكامل المستمر (CI) باستخدام GitHub Actions
يتم الاحتفاظ بالبيانات عبر عمليات إعادة التشغيل في وحدتي تخزين Docker (`twenty-app-dev-data` لـ PostgreSQL، و`twenty-app-dev-storage` للملفات). استخدم `reset` لمسح كل شيء والبدء من جديد.
تولّد أداة إنشاء الهيكل سير عمل GitHub Actions جاهزًا للاستخدام في `.github/workflows/ci.yml`. يشغّل اختبارات التكامل لديك تلقائيًا عند كل دفع إلى `main` وعلى طلبات السحب.
سير العمل:
1. يجلب الشيفرة الخاصة بك
2. يشغّل خادم Twenty مؤقتًا باستخدام الإجراء `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. يثبّت الاعتمادات باستخدام `yarn install --immutable`
4. يشغّل `yarn test` مع حقن `TWENTY_API_URL` و`TWENTY_API_KEY` من مخرجات الإجراء
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
لا تحتاج إلى تهيئة أي أسرار — إذ يبدأ إجراء `spawn-twenty-docker-image` خادم Twenty عابرًا مباشرة في المشغّل ويُخرِج تفاصيل الاتصال. يتم توفير السر `GITHUB_TOKEN` تلقائيًا من قِبل GitHub.
لتثبيت إصدار محدّد من Twenty بدلًا من `latest`، غيّر متغير البيئة `TWENTY_VERSION` في أعلى سير العمل.
<Note>
يتطلّب الخادم أن يكون **Docker** قيد التشغيل. إذا ظهرت لك رسالة خطأ "Docker not running"، فتأكّد من تشغيل Docker Desktop (أو خادوم Docker).
</Note>
## إعداد يدوي (بدون المهيئ)
@@ -52,7 +52,11 @@ yarn twenty deploy
### مشاركة تطبيق منشور
تطبيقات tarball لا تُدرَج في السوق العامة، لذا لن تكتشفها مساحات العمل الأخرى على الخادم نفسه عبر الاستعراض. لمشاركة تطبيق منشور:
<Warning>
تُعد مشاركة التطبيقات الخاصة (tarball) عبر مساحات العمل ميزة ضمن **Enterprise**. ستعرض علامة التبويب **Distribution** مطالبة بالترقية بدلًا من عناصر التحكم في المشاركة حتى تحتوي مساحة العمل لديك على مفتاح Enterprise صالح. اطلع على [الإعدادات > لوحة الإدارة > Enterprise](/settings/admin-panel#enterprise) لتنشيطه.
</Warning>
تطبيقات tarball لا تُدرَج في السوق العامة، لذا لن تكتشفها مساحات العمل الأخرى على الخادم نفسه عبر الاستعراض. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. اذهب إلى **الإعدادات > التطبيقات > التسجيلات** وافتح تطبيقك
2. في علامة التبويب **التوزيع**، انقر **نسخ رابط المشاركة**
@@ -60,10 +64,6 @@ yarn twenty deploy
يستخدم رابط المشاركة عنوان URL الأساسي للخادم (من دون أي نطاق فرعي لمساحة عمل)، لذا يعمل مع أي مساحة عمل على الخادم.
<Warning>
مشاركة التطبيقات الخاصة هي ميزة ضمن باقة Enterprise. اذهب إلى [الإعدادات > لوحة الإدارة > Enterprise](/settings/admin-panel#enterprise) لتمكينها.
</Warning>
### إدارة الإصدارات
لطرح تحديث:
@@ -81,7 +81,7 @@ import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
universalIdentifier: '39783023-bcac-41e3-b0d2-ff1944d8465d',
displayName: 'My Twenty App',
description: 'My first Twenty app',
icon: 'IconWorld',
@@ -717,6 +717,13 @@ Hlavní body:
Frontendové komponenty jsou React komponenty, které se vykreslují přímo v uživatelském rozhraní Twenty. Běží v **izolovaném Web Workeru** s využitím Remote DOM — váš kód je sandboxovaný, ale vykresluje se nativně na stránce, nikoli v iframu.
#### Kde lze použít front komponenty
Front komponenty se mohou vykreslovat na dvou místech v rámci Twenty:
* **Postranní panel** — Ne-headless front komponenty se otevírají v pravém postranním panelu. Toto je výchozí chování, když je front komponenta vyvolána z menu příkazů.
* **Widgety (nástěnky a stránky záznamů)** — Front komponenty lze vkládat jako widgety do rozložení stránek. Při konfiguraci nástěnky nebo rozložení stránky záznamu mohou uživatelé přidat widget front komponenty.
#### Základní příklad
Nejrychlejší způsob, jak vidět frontendovou komponentu v akci, je zaregistrovat ji jako **příkaz**. Přidáním pole `command` s `isPinned: true` se zobrazí jako tlačítko rychlé akce v pravém horním rohu stránky — není potřeba žádné rozvržení stránky:
@@ -774,9 +781,13 @@ Kliknutím na něj vykreslíte komponentu přímo ve stránce.
Mimo příkazy můžete frontendovou komponentu vložit přímo na stránku záznamu přidáním jako widget v **rozvržení stránky**. Podrobnosti viz sekce [definePageLayout](#definepagelayout).
#### Headless komponenty (`isHeadless: true`)
#### Headless vs. ne-headless
Headless komponenty nevykreslují viditelné UI, ale stále spouštějí logiku Reactu. To je užitečné pro **efektové komponenty** — komponenty, které po připojení provádějí vedlejší efekty, jako je synchronizace dat, spuštění časovače, naslouchání událostem nebo vyvolání oznámení.
Front komponenty existují ve dvou režimech vykreslování řízených volbou `isHeadless`:
**Ne-headless (výchozí)** — Komponenta vykreslí viditelné uživatelské rozhraní. Po vyvolání z menu příkazů se otevře v postranním panelu. Toto je výchozí chování, když je `isHeadless` `false` nebo když tato volba není uvedena.
**Headless (`isHeadless: true`)** — Komponenta se neviditelně inicializuje na pozadí. Neotevírá postranní panel. Headless komponenty jsou určené pro akce, které provedou logiku a poté se odpojí — například spuštění asynchronního úkolu, navigaci na stránku nebo zobrazení potvrzovacího modálního okna. Přirozeně se hodí ke komponentám SDK Command popsaným níže.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
@@ -803,6 +814,89 @@ export default defineFrontComponent({
Protože komponenta vrací `null`, Twenty přeskočí vykreslení kontejneru — v rozvržení se neobjeví žádné prázdné místo. Komponenta má však stále přístup ke všem hookům a API komunikace s hostitelem.
#### Komponenty SDK Command
Balíček `twenty-sdk` poskytuje čtyři pomocné komponenty Command navržené pro headless front komponenty. Každá komponenta při připojení provede akci, chyby zpracuje zobrazením oznámení ve snackbaru a po dokončení automaticky odpojí front komponentu.
Importujte je z `twenty-sdk/command`:
* **`Command`** — Spustí asynchronní callback přes prop `execute`.
* **`CommandLink`** — Naviguje na cestu v aplikaci. Props: `to`, `params`, `queryParams`, `options`.
* **`CommandModal`** — Otevře potvrzovací modální okno. Pokud uživatel potvrdí, provede callback `execute`. Props: `title`, `subtitle`, `execute`, `confirmButtonText`, `confirmButtonAccent`.
* **`CommandOpenSidePanelPage`** — Otevře konkrétní stránku postranního panelu. Props: `page`, `pageTitle`, `pageIcon`.
Zde je kompletní příklad headless front komponenty, která pomocí `Command` spouští akci z menu příkazů:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
command: {
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
},
});
```
A příklad s použitím `CommandModal` k vyžádání potvrzení před provedením:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
const execute = async () => {
// perform the deletion
};
return (
<CommandModal
title="Delete draft?"
subtitle="This action cannot be undone."
execute={execute}
confirmButtonText="Delete"
confirmButtonAccent="danger"
/>
);
};
export default defineFrontComponent({
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
name: 'delete-draft',
description: 'Deletes a draft with confirmation',
component: DeleteDraft,
isHeadless: true,
command: {
universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
label: 'Delete draft',
icon: 'IconTrash',
},
});
```
#### Přístup k běhovému kontextu
Uvnitř komponenty použijte hooky SDK pro přístup k aktuálnímu uživateli, záznamu a instanci komponenty:
@@ -859,6 +953,50 @@ Frontendové komponenty mohou pomocí funkcí z `twenty-sdk` vyvolávat navigaci
| `unmountFrontComponent()` | Odmontovat komponentu |
| `updateProgress(progress)` | Aktualizovat indikátor průběhu |
Zde je příklad, který používá hostitelské API k zobrazení snackbaru a zavření postranního panelu po dokončení akce:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
const recordId = useRecordId();
const handleArchive = async () => {
const client = new CoreApiClient();
await client.mutation({
updateTask: {
__args: { id: recordId, data: { status: 'ARCHIVED' } },
id: true,
},
});
await enqueueSnackbar({
message: 'Record archived',
variant: 'success',
});
await closeSidePanel();
};
return (
<div style={{ padding: '20px' }}>
<p>Archive this record?</p>
<button onClick={handleArchive}>Archive</button>
</div>
);
};
export default defineFrontComponent({
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
name: 'archive-record',
description: 'Archives the current record',
component: ArchiveRecord,
});
```
#### Možnosti příkazu
Přidání pole `command` do `defineFrontComponent` zaregistruje komponentu v příkazovém menu (Cmd+K). Pokud je `isPinned` nastaveno na `true`, zobrazí se také jako tlačítko rychlé akce v pravém horním rohu stránky.
@@ -1713,3 +1851,86 @@ yarn twenty uninstall
# Skip the confirmation prompt
yarn twenty uninstall --yes
```
## Správa vzdálených serverů
**Remote** je server Twenty, ke kterému se vaše aplikace připojuje. Během nastavení jej generátor kostry automaticky vytvoří. Můžete kdykoli přidat další vzdálené servery nebo mezi nimi přepínat.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Vaše přihlašovací údaje jsou uloženy v `~/.twenty/config.json`.
## CI s GitHub Actions
Generátor kostry vytvoří připravený k použití workflow GitHub Actions v `.github/workflows/ci.yml`. Automaticky spouští integrační testy při každém pushi do `main` a u pull requestů.
Workflow:
1. Načte váš kód (checkout).
2. Spustí dočasný server Twenty pomocí akce `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Nainstaluje závislosti pomocí `yarn install --immutable`
4. Spustí `yarn test` s proměnnými `TWENTY_API_URL` a `TWENTY_API_KEY` vloženými z výstupů akce
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Není potřeba konfigurovat žádné secrets — akce `spawn-twenty-docker-image` spustí efemérní server Twenty přímo v runneru a vypíše podrobnosti připojení. Secret `GITHUB_TOKEN` je poskytován GitHubem automaticky.
Chcete-li připnout konkrétní verzi Twenty místo `latest`, změňte proměnnou prostředí `TWENTY_VERSION` na začátku workflow.
@@ -7,7 +7,9 @@ description: Vytvořte svou první aplikaci Twenty během několika minut.
Aplikace jsou aktuálně v alfa fázi. Funkce funguje, ale stále se vyvíjí.
</Warning>
Aplikace vám umožňují rozšířit Twenty o vlastní objekty, pole, logické funkce, AI schopnosti a komponenty uživatelského rozhraní — vše je spravováno jako kód.
## Co jsou aplikace?
Aplikace vám umožňují rozšířit Twenty o vlastní objekty, pole, logické funkce, frontendové komponenty, AI schopnosti a další — vše je spravováno jako kód. Místo konfigurace všeho přes uživatelské rozhraní definujete v TypeScriptu svůj datový model a logiku a nasadíte je do jednoho nebo více pracovních prostorů.
## Předpoklady
@@ -17,7 +19,9 @@ Než začnete, ujistěte se, že máte ve svém počítači nainstalováno násl
* **Yarn 4** — Dodává se s Node.js prostřednictvím Corepacku. Povolte jej spuštěním `corepack enable`
* **Docker** — [Stáhnout zde](https://www.docker.com/products/docker-desktop/). Nutné pro spuštění lokální instance Twenty. Není potřeba, pokud už máte spuštěný server Twenty.
## Krok 1: Vytvořte kostru své aplikace
## Vytvořte svou první aplikaci
### Vytvořte kostru své aplikace
Otevřete terminál a spusťte:
@@ -29,18 +33,7 @@ Budete vyzváni k zadání názvu a popisu své aplikace. Stisknutím **Enter**
Tím se vytvoří nová složka s názvem `my-twenty-app` se vším potřebným.
<Note>
Generátor kostry podporuje tyto přepínače:
* `--minimal` — vygeneruje pouze nezbytné soubory, bez příkladů (výchozí)
* `--exhaustive` — vygeneruje všechny ukázkové entity
* `--name <name>` — nastaví název aplikace (přeskočí výzvu)
* `--display-name <displayName>` — nastaví zobrazovaný název (přeskočí výzvu)
* `--description <description>` — nastaví popis (přeskočí výzvu)
* `--skip-local-instance` — přeskočí výzvu k nastavení lokálního serveru
</Note>
## Krok 2: Nastavte lokální instanci Twenty
### Nastavte lokální instanci Twenty
Generátor kostry se zeptá:
@@ -53,7 +46,7 @@ Generátor kostry se zeptá:
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Spustit lokální instanci?" />
</div>
## Krok 3: Přihlaste se do svého pracovního prostoru
### Přihlaste se do svého pracovního prostoru
Poté se otevře okno prohlížeče se stránkou přihlášení do Twenty. Přihlaste se předpřipraveným demo účtem:
@@ -64,7 +57,7 @@ Poté se otevře okno prohlížeče se stránkou přihlášení do Twenty. Přih
<img src="/images/docs/developers/extends/apps/login.png" alt="Přihlašovací obrazovka Twenty" />
</div>
## Krok 4: Autorizujte aplikaci
### Autorizujte aplikaci
Po přihlášení uvidíte autorizační obrazovku. Tím umožníte vaší aplikaci pracovat s vaším pracovním prostorem.
@@ -80,7 +73,7 @@ Po autorizaci váš terminál potvrdí, že je vše nastaveno.
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="Aplikace byla úspěšně vygenerována" />
</div>
## Krok 5: Začněte vyvíjet
### Začněte vyvíjet
Přejděte do nové složky aplikace a spusťte vývojový server:
@@ -105,7 +98,7 @@ Vývojový režim je k dispozici pouze na instancích Twenty běžících v rež
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Výstup terminálu ve vývojovém režimu" />
</div>
## Krok 6: Zobrazte svou aplikaci v Twenty
### Zobrazte svou aplikaci v Twenty
Otevřete ve svém prohlížeči [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer). Přejděte do **Settings > Apps** a vyberte kartu **Developer**. Vaše aplikace by měla být uvedena v části **Your Apps**:
@@ -133,13 +126,28 @@ Přepněte na kartu **Content**, abyste viděli vše, co vaše aplikace poskytuj
Vše je připraveno! Upravte libovolný soubor v `src/` a změny se automaticky projeví.
Přejděte na [Tvorba aplikací](/l/cs/developers/extend/apps/building) pro podrobný průvodce vytvářením objektů, logických funkcí, frontendových komponent, dovedností a dalšího.
---
## Co můžete vytvořit
Aplikace se skládají z **entit** — každá je definována jako soubor TypeScriptu s jediným `export default`:
| Entita | K čemu slouží |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| **Objekty a pole** | Definujte vlastní datové modely (např. Post Card, Invoice) s typovanými poli |
| **Logické funkce** | Serverové funkce v TypeScriptu spouštěné HTTP trasami, plánovačem cron nebo událostmi databáze |
| **Frontendové komponenty** | Komponenty Reactu, které se vykreslují v uživatelském rozhraní Twenty (postranní panel, widgety, příkazová nabídka) |
| **Dovednosti a agenti** | Schopnosti AI — opakovaně použitelné pokyny a autonomní asistenti |
| **Pohledy a navigace** | Předkonfigurované seznamové pohledy a položky postranní nabídky pro vaše objekty |
| **Rozvržení stránek** | Vlastní stránky detailu záznamu s kartami a widgety |
Přejděte na [Tvorba aplikací](/l/cs/developers/extend/apps/building) pro podrobný průvodce každým typem entity.
---
## Struktura projektu
Generátor kostry vytvoří následující strukturu souborů (zobrazeno v režimu `--exhaustive`, který zahrnuje příklady pro každý typ entity):
Nástroj pro vytvoření kostry vygeneruje následující strukturu souborů:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -148,160 +156,50 @@ my-twenty-app/
.gitignore
.nvmrc
.yarnrc.yml
.yarn/
install-state.gz
.oxlintrc.json
tsconfig.json
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
LLMS.md
README.md
.github/
└── workflows/
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
src/
├── application-config.ts # Required — main application configuration
├── __tests__/
├── setup-test.ts # Test setup (server health check, config)
│ └── app-install.integration-test.ts # Example integration test
── roles/
── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── create-hello-world-company.ts # Example logic function using CoreApiClient
│ ├── pre-install.ts # Runs before installation
│ └── post-install.ts # Runs after installation
├── front-components/
│ └── hello-world.tsx # Example front component
├── page-layouts/
│ └── example-record-page-layout.ts # Example page layout with front component
├── views/
│ └── example-view.ts # Example saved view definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
├── skills/
│ └── example-skill.ts # Example AI agent skill definition
└── agents/
└── example-agent.ts # Example AI agent definition
├── application-config.ts # Required — main application configuration
├── default-role.ts # Default role for logic functions
├── constants/
│ └── universal-identifiers.ts # Auto-generated UUIDs and app metadata
── __tests__/
── setup-test.ts # Test setup (server health check, config)
└── app-install.integration-test.ts # Integration test
```
Ve výchozím nastavení (`--minimal`) se vytvoří pouze základní soubory: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` a `logic-functions/post-install.ts`. Pro zahrnutí všech ukázkových souborů výše použijte `--exhaustive`.
### Začínáme s příkladem
Chcete-li začít s úplnějším příkladem s vlastními objekty, poli, logickými funkcemi, frontendovými komponentami a dalšími, použijte přepínač `--example`:
```bash filename="Terminal"
npx create-twenty-app@latest my-twenty-app --example postcard
```
Příklady pocházejí z adresáře [twenty-apps/examples](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples) na GitHubu. Můžete také vytvořit kostru jednotlivých entit v existujícím projektu pomocí `yarn twenty add` (viz [Tvorba aplikací](/l/cs/developers/extend/apps/building#scaffolding-entities-with-yarn-twenty-add)).
### Klíčové soubory
| Soubor / Složka | Účel |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Definuje název, verzi a závislosti vaší aplikace. Obsahuje skript `twenty`, takže můžete spustit `yarn twenty help` a zobrazit všechny příkazy. |
| `src/application-config.ts` | **Povinné.** Hlavní konfigurační soubor vaší aplikace. |
| `src/roles/` | Definuje role, které určují, k čemu mají vaše logické funkce přístup. |
| `src/logic-functions/` | Serverové funkce spouštěné trasami, plánovačem cron nebo událostmi databáze. |
| `src/front-components/` | Komponenty Reactu, které se vykreslují uvnitř uživatelského rozhraní Twenty. |
| `src/objects/` | Vlastní definice objektů pro rozšíření vašeho datového modelu. |
| `src/fields/` | Vlastní pole přidaná k existujícím objektům. |
| `src/views/` | Konfigurace uložených zobrazení. |
| `src/navigation-menu-items/` | Vlastní odkazy v postranní navigaci. |
| `src/skills/` | Dovednosti, které rozšiřují možnosti AI agentů Twenty. |
| `src/agents/` | AI agenti s vlastními prompty. |
| `src/page-layouts/` | Vlastní rozvržení stránek pro zobrazení záznamů. |
| `src/__tests__/` | Integrační testy (nastavení + ukázkový test). |
| `public/` | Statická aktiva (obrázky, písma) poskytovaná s vaší aplikací. |
| Soubor / Složka | Účel |
| ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Definuje název, verzi a závislosti vaší aplikace. Obsahuje skript `twenty`, takže můžete spustit `yarn twenty help` a zobrazit všechny příkazy. |
| `src/application-config.ts` | **Povinné.** Hlavní konfigurační soubor vaší aplikace. |
| `src/default-role.ts` | Výchozí role, která určuje, k čemu mají vaše logické funkce přístup. |
| `src/constants/universal-identifiers.ts` | Automaticky generovaná UUID a metadata aplikace (zobrazovaný název, popis). |
| `src/__tests__/` | Integrační testy (nastavení + ukázkový test). |
| `public/` | Statická aktiva (obrázky, písma) poskytovaná s vaší aplikací. |
## Správa vzdálených serverů
## Lokální vývojový server
**Remote** je server Twenty, ke kterému se vaše aplikace připojuje. Během nastavení jej generátor kostry automaticky vytvoří. Můžete kdykoli přidat další vzdálené servery nebo mezi nimi přepínat.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Vaše přihlašovací údaje jsou uloženy v `~/.twenty/config.json`.
## Lokální vývojový server (`yarn twenty server`)
CLI může spravovat lokální server Twenty běžící v Dockeru. Jde o stejný server, který se spustí automaticky při vytvoření kostry aplikace pomocí `create-twenty-app`, ale můžete jej spravovat i ručně.
### Spuštění serveru
```bash filename="Terminal"
yarn twenty server start
```
Stáhne image Dockeru `twentycrm/twenty-app-dev:latest` (pokud již není k dispozici), vytvoří kontejner s názvem `twenty-app-dev` a spustí jej na portu **2020**. CLI čeká, dokud server neprojde kontrolou stavu, než vrátí řízení.
Vytvoří se dva svazky Dockeru pro zachování dat mezi restartováními:
* `twenty-app-dev-data` — databáze PostgreSQL
* `twenty-app-dev-storage` — úložiště souborů
Pokud je port 2020 již používán, můžete spustit na jiném portu:
```bash filename="Terminal"
yarn twenty server start --port 3030
```
CLI automaticky nakonfiguruje interní `NODE_PORT` a `SERVER_URL` kontejneru tak, aby odpovídaly zvolenému portu, takže logické funkce, OAuth a veškerá ostatní vnitřní síťová komunikace fungují správně.
Po spuštění je server automaticky zaregistrován jako `local` remote ve vaší konfiguraci CLI.
### Kontrola stavu serveru
```bash filename="Terminal"
yarn twenty server status
```
Zobrazí, zda server běží, jeho URL a výchozí přihlašovací údaje (`[email protected]` / `[email protected]`).
### Zobrazení protokolů serveru
```bash filename="Terminal"
yarn twenty server logs
```
Streamuje protokoly kontejneru. Pomocí `--lines` ovládnete, kolik posledních řádků se má zobrazit:
```bash filename="Terminal"
yarn twenty server logs --lines 100
```
### Zastavení serveru
```bash filename="Terminal"
yarn twenty server stop
```
Zastaví kontejner. Vaše data jsou zachována ve svazcích Dockeru — další `start` naváže tam, kde jste skončili.
### Resetování serveru
```bash filename="Terminal"
yarn twenty server reset
```
Odstraní kontejner **a** smaže oba svazky Dockeru, čímž vymaže všechna data. Další `start` vytvoří čistou instanci.
<Note>
Server vyžaduje, aby **Docker** běžel. Pokud vidíte chybu "Docker not running", ujistěte se, že je spuštěný Docker Desktop (nebo démon Dockeru).
</Note>
### Přehled příkazů
Nástroj pro vytvoření kostry vám již spustil lokální server Twenty. Pro jeho správu později použijte `yarn twenty server`:
| Příkaz | Popis |
| -------------------------------------- | ------------------------------------------------------ |
@@ -313,65 +211,11 @@ Odstraní kontejner **a** smaže oba svazky Dockeru, čímž vymaže všechna da
| `yarn twenty server logs --lines 100` | Zobrazí posledních 100 řádků logu |
| `yarn twenty server reset` | Smaže všechna data a začne znovu |
## CI s GitHub Actions
Data přetrvávají při restartech ve dvou svazcích Dockeru (`twenty-app-dev-data` pro PostgreSQL, `twenty-app-dev-storage` pro soubory). Pomocí `reset` vymažte vše a začněte znovu.
Generátor kostry vytvoří připravený k použití workflow GitHub Actions v `.github/workflows/ci.yml`. Automaticky spouští integrační testy při každém pushi do `main` a u pull requestů.
Workflow:
1. Načte váš kód (checkout).
2. Spustí dočasný server Twenty pomocí akce `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Nainstaluje závislosti pomocí `yarn install --immutable`
4. Spustí `yarn test` s proměnnými `TWENTY_API_URL` a `TWENTY_API_KEY` vloženými z výstupů akce
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Není potřeba konfigurovat žádné secrets — akce `spawn-twenty-docker-image` spustí efemérní server Twenty přímo v runneru a vypíše podrobnosti připojení. Secret `GITHUB_TOKEN` je poskytován GitHubem automaticky.
Chcete-li připnout konkrétní verzi Twenty místo `latest`, změňte proměnnou prostředí `TWENTY_VERSION` na začátku workflow.
<Note>
Server vyžaduje, aby **Docker** běžel. Pokud vidíte chybu "Docker not running", ujistěte se, že je spuštěný Docker Desktop (nebo démon Dockeru).
</Note>
## Ruční nastavení (bez scaffolderu)
@@ -52,7 +52,11 @@ yarn twenty deploy
### Sdílení nasazené aplikace
Aplikace ve formě tarball nejsou uvedeny ve veřejném tržišti, takže je ostatní pracovní prostory na tomtéž serveru procházením neobjeví. Chcete-li sdílet nasazenou aplikaci:
<Warning>
Sdílení soukromých (tarball) aplikací napříč pracovními prostory je funkcí plánu **Enterprise**. Karta **Distribution** bude místo ovládacích prvků sdílení zobrazovat výzvu k upgradu, dokud váš pracovní prostor nebude mít platný klíč Enterprise. Přejděte do [Nastavení > Admin Panel > Enterprise](/settings/admin-panel#enterprise) a aktivujte ji.
</Warning>
Aplikace ve formě tarball nejsou uvedeny ve veřejném tržišti, takže je ostatní pracovní prostory na tomtéž serveru procházením neobjeví. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. Přejděte do **Nastavení > Aplikace > Registrace** a otevřete svou aplikaci
2. Na kartě **Distribuce** klikněte na **Zkopírovat odkaz ke sdílení**
@@ -60,10 +64,6 @@ Aplikace ve formě tarball nejsou uvedeny ve veřejném tržišti, takže je ost
Odkaz ke sdílení používá základní adresu URL serveru (bez jakékoli subdomény pracovního prostoru), takže funguje pro libovolný pracovní prostor na serveru.
<Warning>
Sdílení soukromých aplikací je funkce Enterprise. Přejděte do [Nastavení > Admin Panel > Enterprise](/settings/admin-panel#enterprise) a povolte ji.
</Warning>
### Správa verzí
Chcete-li vydat aktualizaci:
@@ -81,7 +81,7 @@ import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
universalIdentifier: '39783023-bcac-41e3-b0d2-ff1944d8465d',
displayName: 'My Twenty App',
description: 'My first Twenty app',
icon: 'IconWorld',
@@ -716,6 +716,13 @@ Hauptpunkte:
Frontend-Komponenten sind React-Komponenten, die direkt innerhalb der Twenty-UI gerendert werden. Sie laufen in einem **isolierten Web Worker** unter Verwendung von Remote DOM — Ihr Code wird in einer Sandbox ausgeführt, rendert jedoch nativ auf der Seite, nicht in einem iframe.
#### Wo Front-Komponenten verwendet werden können
Front-Komponenten können an zwei Stellen innerhalb von Twenty gerendert werden:
* **Seitenpanel** — Nicht-Headless-Front-Komponenten werden im rechten Seitenpanel geöffnet. Dies ist das Standardverhalten, wenn eine Front-Komponente über das Befehlsmenü ausgelöst wird.
* **Widgets (Dashboards und Datensatzseiten)** — Front-Komponenten können als Widgets in Seitenlayouts eingebettet werden. Beim Konfigurieren eines Dashboards oder eines Datensatzseiten-Layouts können Benutzer ein Front-Komponenten-Widget hinzufügen.
#### Einfaches Beispiel
Der schnellste Weg, eine Frontend-Komponente in Aktion zu sehen, ist, sie als Befehl zu registrieren. Das Hinzufügen eines `command`-Felds mit `isPinned: true` lässt sie als Schnellaktionsschaltfläche oben rechts auf der Seite erscheinen — kein Seitenlayout erforderlich:
@@ -773,9 +780,13 @@ Klicken Sie darauf, um die Komponente inline zu rendern.
Über Befehle hinaus können Sie eine Frontend-Komponente direkt in eine Datensatzseite einbetten, indem Sie sie als Widget in einem **Seitenlayout** hinzufügen. Details finden Sie im Abschnitt [definePageLayout](#definepagelayout).
#### Headless-Komponenten (`isHeadless: true`)
#### Headless vs. Nicht-Headless
Headless-Komponenten rendern keine sichtbare UI, führen aber dennoch React-Logik aus. Dies ist nützlich für **Effekt-Komponenten** — Komponenten, die beim Mounten Seiteneffekte ausführen, wie z. B. das Synchronisieren von Daten, Starten eines Timers, Lauschen auf Ereignisse oder Auslösen einer Benachrichtigung.
Front-Komponenten gibt es in zwei Rendering-Modi, die durch die Option `isHeadless` gesteuert werden:
**Nicht-Headless (Standard)** — Die Komponente rendert eine sichtbare UI. Wird sie über das Befehlsmenü ausgelöst, öffnet sie sich im Seitenpanel. Dies ist das Standardverhalten, wenn `isHeadless` `false` ist oder weggelassen wird.
**Headless (`isHeadless: true`)** — Die Komponente wird unsichtbar im Hintergrund gemountet. Sie öffnet das Seitenpanel nicht. Headless-Komponenten sind für Aktionen konzipiert, die Logik ausführen und sich anschließend selbst unmounten — zum Beispiel das Ausführen einer asynchronen Aufgabe, das Navigieren zu einer Seite oder das Anzeigen eines Bestätigungsdialogs. Sie lassen sich gut mit den unten beschriebenen SDK-Command-Komponenten kombinieren.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
@@ -802,6 +813,89 @@ export default defineFrontComponent({
Da die Komponente `null` zurückgibt, überspringt Twenty das Rendern eines Containers dafür — im Layout entsteht kein Leerraum. Die Komponente hat dennoch Zugriff auf alle Hooks und die Host-Kommunikations-API.
#### SDK-Command-Komponenten
Das Paket `twenty-sdk` stellt vier Command-Hilfskomponenten bereit, die für Headless-Front-Komponenten ausgelegt sind. Jede Komponente führt beim Mounten eine Aktion aus, behandelt Fehler durch Anzeige einer Snackbar-Benachrichtigung und unmountet die Front-Komponente nach Abschluss automatisch.
Importieren Sie sie aus `twenty-sdk/command`:
* **`Command`** — Führt einen asynchronen Callback über das Prop `execute` aus.
* **`CommandLink`** — Navigiert zu einem App-Pfad. Props: `to`, `params`, `queryParams`, `options`.
* **`CommandModal`** — Öffnet einen Bestätigungsdialog. Bestätigt der Benutzer, wird der Callback `execute` ausgeführt. Props: `title`, `subtitle`, `execute`, `confirmButtonText`, `confirmButtonAccent`.
* **`CommandOpenSidePanelPage`** — Öffnet eine bestimmte Seite im Seitenpanel. Props: `page`, `pageTitle`, `pageIcon`.
Hier ist ein vollständiges Beispiel einer Headless-Front-Komponente, die `Command` verwendet, um eine Aktion aus dem Befehlsmenü auszuführen:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
command: {
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
},
});
```
Und ein Beispiel, das `CommandModal` verwendet, um vor der Ausführung um Bestätigung zu bitten:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
const execute = async () => {
// perform the deletion
};
return (
<CommandModal
title="Delete draft?"
subtitle="This action cannot be undone."
execute={execute}
confirmButtonText="Delete"
confirmButtonAccent="danger"
/>
);
};
export default defineFrontComponent({
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
name: 'delete-draft',
description: 'Deletes a draft with confirmation',
component: DeleteDraft,
isHeadless: true,
command: {
universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
label: 'Delete draft',
icon: 'IconTrash',
},
});
```
#### Zugriff auf den Laufzeitkontext
Verwenden Sie innerhalb Ihrer Komponente SDK-Hooks, um auf den aktuellen Benutzer, den Datensatz und die Komponenteninstanz zuzugreifen:
@@ -858,6 +952,50 @@ Frontend-Komponenten können Navigation, Modals und Benachrichtigungen mittels F
| `unmountFrontComponent()` | Die Komponente entfernen |
| `updateProgress(progress)` | Einen Fortschrittsindikator aktualisieren |
Hier ist ein Beispiel, das die Host-API verwendet, um nach Abschluss einer Aktion eine Snackbar anzuzeigen und das Seitenpanel zu schließen:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
const recordId = useRecordId();
const handleArchive = async () => {
const client = new CoreApiClient();
await client.mutation({
updateTask: {
__args: { id: recordId, data: { status: 'ARCHIVED' } },
id: true,
},
});
await enqueueSnackbar({
message: 'Record archived',
variant: 'success',
});
await closeSidePanel();
};
return (
<div style={{ padding: '20px' }}>
<p>Archive this record?</p>
<button onClick={handleArchive}>Archive</button>
</div>
);
};
export default defineFrontComponent({
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
name: 'archive-record',
description: 'Archives the current record',
component: ArchiveRecord,
});
```
#### Befehlsoptionen
Das Hinzufügen eines `command`-Felds zu `defineFrontComponent` registriert die Komponente im Befehlsmenü (Cmd+K). Wenn `isPinned` `true` ist, erscheint sie außerdem als Schnellaktionsschaltfläche oben rechts auf der Seite.
@@ -1712,3 +1850,86 @@ yarn twenty uninstall
# Skip the confirmation prompt
yarn twenty uninstall --yes
```
## Remotes verwalten
Ein **Remote** ist ein Twenty-Server, mit dem sich Ihre App verbindet. Während der Einrichtung erstellt das Scaffolding-Tool automatisch eines für Sie. Sie können jederzeit weitere Remotes hinzufügen oder zwischen ihnen wechseln.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Ihre Anmeldedaten werden in `~/.twenty/config.json` gespeichert.
## CI mit GitHub Actions
Das Scaffolding-Tool erzeugt einen einsatzbereiten GitHub-Actions-Workflow in `.github/workflows/ci.yml`. Er führt Ihre Integrationstests automatisch bei jedem Push auf `main` und bei Pull Requests aus.
Der Workflow:
1. Checkt Ihren Code aus
2. Startet einen temporären Twenty-Server mit der Aktion `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Installiert Abhängigkeiten mit `yarn install --immutable`
4. Führt `yarn test` aus, wobei `TWENTY_API_URL` und `TWENTY_API_KEY` aus den Aktionsausgaben injiziert werden.
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Sie müssen keine Secrets konfigurieren — die Aktion `spawn-twenty-docker-image` startet einen flüchtigen Twenty-Server direkt im Runner und gibt die Verbindungsdetails aus. Das Secret `GITHUB_TOKEN` wird automatisch von GitHub bereitgestellt.
Um eine bestimmte Twenty-Version statt `latest` festzulegen, ändern Sie die Umgebungsvariable `TWENTY_VERSION` oben im Workflow.
@@ -7,7 +7,9 @@ description: Erstellen Sie in wenigen Minuten Ihre erste Twenty-App.
Apps befinden sich derzeit in der Alpha-Phase. Die Funktion ist funktionsfähig, entwickelt sich jedoch noch weiter.
</Warning>
Apps ermöglichen es Ihnen, Twenty mit benutzerdefinierten Objekten, Feldern, Logikfunktionen, KI-Fähigkeiten und UI-Komponenten zu erweitern — alles als Code verwaltet.
## Was sind Apps?
Apps ermöglichen es Ihnen, Twenty mit benutzerdefinierten Objekten, Feldern, Logikfunktionen, Frontend-Komponenten, KI-Fähigkeiten und mehr zu erweitern — alles als Code verwaltet. Anstatt alles über die UI zu konfigurieren, definieren Sie Ihr Datenmodell und Ihre Logik in TypeScript und stellen es in einem oder mehreren Workspaces bereit.
## Voraussetzungen
@@ -17,7 +19,9 @@ Bevor Sie beginnen, stellen Sie sicher, dass Folgendes auf Ihrem Rechner install
* **Yarn 4** — Wird mit Node.js über Corepack mitgeliefert. Aktivieren Sie es, indem Sie `corepack enable` ausführen
* **Docker** — [Hier herunterladen](https://www.docker.com/products/docker-desktop/). Erforderlich, um eine lokale Twenty-Instanz auszuführen. Nicht erforderlich, wenn bereits ein Twenty-Server läuft.
## Schritt 1: App-Gerüst erstellen
## Erstellen Sie Ihre erste App
### App-Gerüst erstellen
Öffnen Sie ein Terminal und führen Sie Folgendes aus:
@@ -29,18 +33,7 @@ Sie werden aufgefordert, einen Namen und eine Beschreibung für Ihre App einzuge
Dadurch wird ein neuer Ordner namens `my-twenty-app` mit allem erstellt, was Sie benötigen.
<Note>
Das Scaffolding-Tool unterstützt diese Flags:
* `--minimal` — erstellt nur die wesentlichen Dateien, keine Beispiele (Standard)
* `--exhaustive` — erstellt alle Beispiel-Entitäten
* `--name <name>` — legt den App-Namen fest (überspringt die Abfrage)
* `--display-name <displayName>` — legt den Anzeigenamen fest (überspringt die Abfrage)
* `--description <description>` — legt die Beschreibung fest (überspringt die Abfrage)
* `--skip-local-instance` — überspringt die Eingabeaufforderung zur Einrichtung des lokalen Servers
</Note>
## Schritt 2: Lokale Twenty-Instanz einrichten
### Lokale Twenty-Instanz einrichten
Das Scaffolding-Tool fragt:
@@ -53,7 +46,7 @@ Das Scaffolding-Tool fragt:
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Soll die lokale Instanz gestartet werden?" />
</div>
## Schritt 3: Bei Ihrem Arbeitsbereich anmelden
### Melden Sie sich bei Ihrem Arbeitsbereich an
Anschließend öffnet sich ein Browserfenster mit der Twenty-Anmeldeseite. Melden Sie sich mit dem vorab eingerichteten Demo-Konto an:
@@ -64,7 +57,7 @@ Anschließend öffnet sich ein Browserfenster mit der Twenty-Anmeldeseite. Melde
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty-Anmeldebildschirm" />
</div>
## Schritt 4: Die App autorisieren
### Autorisieren Sie die App
Nach der Anmeldung sehen Sie einen Autorisierungsbildschirm. Dadurch kann Ihre App mit Ihrem Arbeitsbereich interagieren.
@@ -80,7 +73,7 @@ Nach der Autorisierung bestätigt Ihr Terminal, dass alles eingerichtet ist.
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="App-Gerüst erfolgreich erstellt" />
</div>
## Schritt 5: Mit der Entwicklung beginnen
### Beginnen Sie mit der Entwicklung
Wechseln Sie in Ihren neuen App-Ordner und starten Sie den Entwicklungsserver:
@@ -105,7 +98,7 @@ Der Dev-Modus ist nur auf Twenty-Instanzen verfügbar, die im Entwicklungsmodus
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Terminalausgabe im Dev-Modus" />
</div>
## Schritt 6: Ihre App in Twenty ansehen
### Sehen Sie sich Ihre App in Twenty an
Öffnen Sie [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) in Ihrem Browser. Navigieren Sie zu **Settings > Apps** und wählen Sie die Registerkarte **Developer**. Unter **Your Apps** sollte Ihre App aufgeführt sein:
@@ -133,13 +126,28 @@ Wechseln Sie zur Registerkarte **Content**, um alles zu sehen, was Ihre App bere
Alles erledigt! Bearbeiten Sie eine beliebige Datei in `src/`, und die Änderungen werden automatisch übernommen.
Wechseln Sie zu [Apps erstellen](/l/de/developers/extend/apps/building) für eine ausführliche Anleitung zum Erstellen von Objekten, Logikfunktionen, Frontend-Komponenten, Skills und mehr.
---
## Was Sie erstellen können
Apps bestehen aus **Entitäten** — jede ist als TypeScript-Datei mit einem einzigen `export default` definiert:
| Entität | Was sie macht |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Objekte & Felder** | Definieren Sie benutzerdefinierte Datenmodelle (wie Post Card, Invoice) mit typisierten Feldern |
| **Logikfunktionen** | Serverseitige TypeScript-Funktionen, die durch HTTP-Routen, Cron-Zeitpläne oder Datenbankereignisse ausgelöst werden |
| **Frontend-Komponenten** | React-Komponenten, die in der UI von Twenty gerendert werden (Seitenleiste, Widgets, Befehlsmenü) |
| **Fähigkeiten & Agenten** | KI-Funktionen — wiederverwendbare Anweisungen und autonome Assistenten |
| **Ansichten & Navigation** | Vorkonfigurierte Listenansichten und Seitenleisteneinträge für Ihre Objekte |
| **Seitenlayouts** | Benutzerdefinierte Datensatz-Detailseiten mit Tabs und Widgets |
Wechseln Sie zu [Apps erstellen](/l/de/developers/extend/apps/building) für eine ausführliche Anleitung zu jedem Entitätstyp.
---
## Projektstruktur
Das Scaffolding-Tool erzeugt die folgende Verzeichnisstruktur (gezeigt im Modus `--exhaustive`, der Beispiele für jeden Entitätstyp enthält):
Der Scaffolder erzeugt die folgende Verzeichnisstruktur:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -148,160 +156,50 @@ my-twenty-app/
.gitignore
.nvmrc
.yarnrc.yml
.yarn/
install-state.gz
.oxlintrc.json
tsconfig.json
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
LLMS.md
README.md
.github/
└── workflows/
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
src/
├── application-config.ts # Required — main application configuration
├── __tests__/
├── setup-test.ts # Test setup (server health check, config)
│ └── app-install.integration-test.ts # Example integration test
── roles/
── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── create-hello-world-company.ts # Example logic function using CoreApiClient
│ ├── pre-install.ts # Runs before installation
│ └── post-install.ts # Runs after installation
├── front-components/
│ └── hello-world.tsx # Example front component
├── page-layouts/
│ └── example-record-page-layout.ts # Example page layout with front component
├── views/
│ └── example-view.ts # Example saved view definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
├── skills/
│ └── example-skill.ts # Example AI agent skill definition
└── agents/
└── example-agent.ts # Example AI agent definition
├── application-config.ts # Required — main application configuration
├── default-role.ts # Default role for logic functions
├── constants/
│ └── universal-identifiers.ts # Auto-generated UUIDs and app metadata
── __tests__/
── setup-test.ts # Test setup (server health check, config)
└── app-install.integration-test.ts # Integration test
```
Standardmäßig (`--minimal`) werden nur die Kerndateien erstellt: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` und `logic-functions/post-install.ts`. Verwenden Sie `--exhaustive`, um alle oben gezeigten Beispieldateien einzuschließen.
### Mit einem Beispiel beginnen
Um mit einem umfassenderen Beispiel mit benutzerdefinierten Objekten, Feldern, Logikfunktionen, Frontend-Komponenten und mehr zu starten, verwenden Sie die Option `--example`:
```bash filename="Terminal"
npx create-twenty-app@latest my-twenty-app --example postcard
```
Die Beispiele stammen aus dem Verzeichnis [twenty-apps/examples](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples) auf GitHub. Sie können auch einzelne Entitäten in einem bestehenden Projekt mit `yarn twenty add` erzeugen (siehe [Apps erstellen](/l/de/developers/extend/apps/building#scaffolding-entities-with-yarn-twenty-add)).
### Wichtige Dateien
| Datei / Ordner | Zweck |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `package.json` | Deklariert den App-Namen, die Version und Abhängigkeiten. Enthält ein `twenty`-Skript, sodass Sie `yarn twenty help` ausführen können, um alle Befehle anzuzeigen. |
| `src/application-config.ts` | **Erforderlich.** Die Hauptkonfigurationsdatei für Ihre App. |
| `src/roles/` | Definiert Rollen, die steuern, worauf Ihre Logikfunktionen zugreifen können. |
| `src/logic-functions/` | Serverseitige Funktionen, die durch Routen, Cron-Zeitpläne oder Datenbankereignisse ausgelöst werden. |
| `src/front-components/` | React-Komponenten, die innerhalb der Twenty-UI gerendert werden. |
| `src/objects/` | Benutzerdefinierte Objektdefinitionen zur Erweiterung Ihres Datenmodells. |
| `src/fields/` | Benutzerdefinierte Felder, die vorhandenen Objekten hinzugefügt werden. |
| `src/views/` | Konfigurationen gespeicherter Ansichten. |
| `src/navigation-menu-items/` | Benutzerdefinierte Links in der Seitenleisten-Navigation. |
| `src/skills/` | Skills, die die KI-Agenten von Twenty erweitern. |
| `src/agents/` | KI-Agenten mit benutzerdefinierten Prompts. |
| `src/page-layouts/` | Benutzerdefinierte Seitenlayouts für Datensatzansichten. |
| `src/__tests__/` | Integrationstests (Setup + Beispieltest). |
| `public/` | Statische Assets (Bilder, Schriftarten), die mit Ihrer App ausgeliefert werden. |
| Datei / Ordner | Zweck |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `package.json` | Deklariert den App-Namen, die Version und Abhängigkeiten. Enthält ein `twenty`-Skript, sodass Sie `yarn twenty help` ausführen können, um alle Befehle anzuzeigen. |
| `src/application-config.ts` | **Erforderlich.** Die Hauptkonfigurationsdatei für Ihre App. |
| `src/default-role.ts` | Standardrolle, die steuert, worauf Ihre Logikfunktionen zugreifen können. |
| `src/constants/universal-identifiers.ts` | Automatisch erzeugte UUIDs und App-Metadaten (Anzeigename, Beschreibung). |
| `src/__tests__/` | Integrationstests (Setup + Beispieltest). |
| `public/` | Statische Assets (Bilder, Schriftarten), die mit Ihrer App ausgeliefert werden. |
## Remotes verwalten
## Lokaler Entwicklungsserver
Ein **Remote** ist ein Twenty-Server, mit dem sich Ihre App verbindet. Während der Einrichtung erstellt das Scaffolding-Tool automatisch eines für Sie. Sie können jederzeit weitere Remotes hinzufügen oder zwischen ihnen wechseln.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Ihre Anmeldedaten werden in `~/.twenty/config.json` gespeichert.
## Lokaler Entwicklungsserver (`yarn twenty server`)
Die CLI kann einen lokalen, in Docker laufenden Twenty-Server verwalten. Dies ist derselbe Server, der automatisch gestartet wird, wenn Sie mit `create-twenty-app` eine App aufsetzen, aber Sie können ihn auch manuell verwalten.
### Server starten
```bash filename="Terminal"
yarn twenty server start
```
Dadurch wird das Docker-Image `twentycrm/twenty-app-dev:latest` heruntergeladen (falls nicht bereits vorhanden), ein Container namens `twenty-app-dev` erstellt und auf Port **2020** gestartet. Die CLI wartet, bis der Server seinen Health-Check bestanden hat, bevor sie zurückkehrt.
Es werden zwei Docker-Volumes erstellt, um Daten zwischen Neustarts beizubehalten:
* `twenty-app-dev-data` — PostgreSQL-Datenbank
* `twenty-app-dev-storage` — Dateispeicher
Wenn Port 2020 bereits verwendet wird, können Sie auf einem anderen Port starten:
```bash filename="Terminal"
yarn twenty server start --port 3030
```
Die CLI konfiguriert automatisch die internen Werte `NODE_PORT` und `SERVER_URL` des Containers passend zum gewählten Port, sodass Logikfunktionen, OAuth und alle anderen internen Netzwerkfunktionen korrekt arbeiten.
Nach dem Start wird der Server automatisch als `local`-Remote in Ihrer CLI-Konfiguration registriert.
### Serverstatus prüfen
```bash filename="Terminal"
yarn twenty server status
```
Zeigt an, ob der Server läuft, seine URL und die Standard-Anmeldedaten (`[email protected]` / `[email protected]`).
### Serverprotokolle anzeigen
```bash filename="Terminal"
yarn twenty server logs
```
Streamt die Containerprotokolle. Verwenden Sie `--lines`, um zu steuern, wie viele der letzten Zeilen angezeigt werden:
```bash filename="Terminal"
yarn twenty server logs --lines 100
```
### Server stoppen
```bash filename="Terminal"
yarn twenty server stop
```
Stoppt den Container. Ihre Daten bleiben in den Docker-Volumes erhalten — der nächste `start` macht dort weiter, wo Sie aufgehört haben.
### Server zurücksetzen
```bash filename="Terminal"
yarn twenty server reset
```
Entfernt den Container **und** löscht beide Docker-Volumes, wobei alle Daten gelöscht werden. Der nächste `start` erstellt eine frische Instanz.
<Note>
Der Server erfordert, dass **Docker** läuft. Wenn der Fehler "Docker not running" angezeigt wird, stellen Sie sicher, dass Docker Desktop (oder der Docker-Daemon) gestartet ist.
</Note>
### Befehlsreferenz
Der Scaffolder hat bereits einen lokalen Twenty-Server für Sie gestartet. Um ihn später zu verwalten, verwenden Sie `yarn twenty server`:
| Befehl | Beschreibung |
| -------------------------------------- | ----------------------------------------------------------- |
@@ -313,65 +211,11 @@ Entfernt den Container **und** löscht beide Docker-Volumes, wobei alle Daten ge
| `yarn twenty server logs --lines 100` | Die letzten 100 Protokollzeilen anzeigen |
| `yarn twenty server reset` | Alle Daten löschen und neu starten |
## CI mit GitHub Actions
Daten bleiben über Neustarts hinweg in zwei Docker-Volumes bestehen (`twenty-app-dev-data` für PostgreSQL, `twenty-app-dev-storage` für Dateien). Verwenden Sie `reset`, um alles zu löschen und neu zu beginnen.
Das Scaffolding-Tool erzeugt einen einsatzbereiten GitHub-Actions-Workflow in `.github/workflows/ci.yml`. Er führt Ihre Integrationstests automatisch bei jedem Push auf `main` und bei Pull Requests aus.
Der Workflow:
1. Checkt Ihren Code aus
2. Startet einen temporären Twenty-Server mit der Aktion `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Installiert Abhängigkeiten mit `yarn install --immutable`
4. Führt `yarn test` aus, wobei `TWENTY_API_URL` und `TWENTY_API_KEY` aus den Aktionsausgaben injiziert werden.
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Sie müssen keine Secrets konfigurieren — die Aktion `spawn-twenty-docker-image` startet einen flüchtigen Twenty-Server direkt im Runner und gibt die Verbindungsdetails aus. Das Secret `GITHUB_TOKEN` wird automatisch von GitHub bereitgestellt.
Um eine bestimmte Twenty-Version statt `latest` festzulegen, ändern Sie die Umgebungsvariable `TWENTY_VERSION` oben im Workflow.
<Note>
Der Server erfordert, dass **Docker** läuft. Wenn der Fehler "Docker not running" angezeigt wird, stellen Sie sicher, dass Docker Desktop (oder der Docker-Daemon) gestartet ist.
</Note>
## Manuelle Einrichtung (ohne Scaffolder)
@@ -52,7 +52,11 @@ yarn twenty deploy
### Eine bereitgestellte App freigeben
Tarball-Apps werden nicht im öffentlichen Marktplatz gelistet, daher entdecken andere Arbeitsbereiche auf demselben Server sie nicht durch Stöbern. So geben Sie eine bereitgestellte App frei:
<Warning>
Sharing private (tarball) apps across workspaces is an **Enterprise** feature. The **Distribution** tab will show an upgrade prompt instead of the share controls until your workspace has a valid Enterprise key. See [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to activate it.
</Warning>
Tarball-Apps werden nicht im öffentlichen Marktplatz gelistet, daher entdecken andere Arbeitsbereiche auf demselben Server sie nicht durch Stöbern. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. Gehen Sie zu **Einstellungen > Anwendungen > Registrierungen** und öffnen Sie Ihre App
2. Klicken Sie im Tab **Distribution** auf **Freigabelink kopieren**
@@ -60,10 +64,6 @@ Tarball-Apps werden nicht im öffentlichen Marktplatz gelistet, daher entdecken
Der Freigabelink verwendet die Basis-URL des Servers (ohne Workspace-Subdomain), sodass er für jeden Arbeitsbereich auf dem Server funktioniert.
<Warning>
Das Teilen privater Apps ist eine Enterprise-Funktion. Gehen Sie zu [Einstellungen > Admin-Panel > Enterprise](/settings/admin-panel#enterprise), um es zu aktivieren.
</Warning>
### Versionsverwaltung
So veröffentlichen Sie ein Update:
@@ -81,7 +81,7 @@ import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
universalIdentifier: '39783023-bcac-41e3-b0d2-ff1944d8465d',
displayName: 'My Twenty App',
description: 'My first Twenty app',
icon: 'IconWorld',
@@ -716,6 +716,13 @@ Punti chiave:
I componenti front-end sono componenti React che vengono renderizzati direttamente all'interno della UI di Twenty. Vengono eseguiti in un **Web Worker** isolato utilizzando Remote DOM — il tuo codice è in sandbox ma viene renderizzato in modo nativo nella pagina, non in un iframe.
#### Dove possono essere utilizzati i componenti front.
I componenti front possono essere renderizzati in due posizioni all'interno di Twenty:
* **Pannello laterale** — I componenti front non headless si aprono nel pannello laterale destro. Questo è il comportamento predefinito quando un componente front viene avviato dal menu comandi.
* **Widget (dashboard e pagine dei record)** — I componenti front possono essere incorporati come widget all'interno dei layout di pagina. Quando si configura una dashboard o il layout di una pagina record, gli utenti possono aggiungere un widget del componente front.
#### Esempio di base
Il modo più rapido per vedere in azione un componente front-end è registrarlo come **comando**. Aggiungere un campo `command` con `isPinned: true` lo fa apparire come pulsante di azione rapida nell'angolo in alto a destra della pagina — nessun layout di pagina necessario:
@@ -773,9 +780,13 @@ Fai clic per renderizzare il componente in linea.
Oltre ai comandi, puoi incorporare un componente front-end direttamente in una pagina di record aggiungendolo come widget in un **layout di pagina**. Vedi la sezione [definePageLayout](#definepagelayout) per i dettagli.
#### Componenti headless (`isHeadless: true`)
#### Headless vs non headless
I componenti headless non renderizzano alcuna UI visibile ma eseguono comunque la logica React. Questo è utile per i componenti di effetto — componenti che eseguono effetti collaterali quando vengono montati, come sincronizzare dati, avviare un timer, ascoltare eventi o attivare una notifica.
I componenti front prevedono due modalità di rendering controllate dall'opzione `isHeadless`:
**Non headless (predefinito)** — Il componente renderizza un'interfaccia utente visibile. Quando viene avviato dal menu comandi, si apre nel pannello laterale. Questo è il comportamento predefinito quando `isHeadless` è `false` o omesso.
**Headless (`isHeadless: true`)** — Il componente viene montato in modo invisibile in background. Non apre il pannello laterale. I componenti headless sono pensati per azioni che eseguono una logica e poi si smontano — ad esempio, eseguire un'attività asincrona, navigare a una pagina o mostrare una finestra modale di conferma. Si abbinano naturalmente ai componenti Command dell'SDK descritti di seguito.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
@@ -802,6 +813,89 @@ export default defineFrontComponent({
Poiché il componente restituisce `null`, Twenty evita di renderizzare un contenitore per esso — non appare alcuno spazio vuoto nel layout. Il componente ha comunque accesso a tutti gli hook e all'API di comunicazione con l'host.
#### Componenti Command dell'SDK
Il pacchetto `twenty-sdk` fornisce quattro componenti di supporto Command progettati per i componenti front headless. Ogni componente esegue un'azione al montaggio, gestisce gli errori mostrando una notifica snackbar e smonta automaticamente il componente front al termine.
Importali da `twenty-sdk/command`:
* **`Command`** — Esegue una callback asincrona tramite la prop `execute`.
* **`CommandLink`** — Naviga verso un percorso dell'app. Props: `to`, `params`, `queryParams`, `options`.
* **`CommandModal`** — Apre una finestra modale di conferma. Se l'utente conferma, esegue la callback `execute`. Props: `title`, `subtitle`, `execute`, `confirmButtonText`, `confirmButtonAccent`.
* **`CommandOpenSidePanelPage`** — Apre una specifica pagina del pannello laterale. Props: `page`, `pageTitle`, `pageIcon`.
Ecco un esempio completo di componente front headless che usa `Command` per eseguire un'azione dal menu comandi:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
command: {
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
},
});
```
E un esempio che usa `CommandModal` per chiedere conferma prima di eseguire:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
const execute = async () => {
// perform the deletion
};
return (
<CommandModal
title="Delete draft?"
subtitle="This action cannot be undone."
execute={execute}
confirmButtonText="Delete"
confirmButtonAccent="danger"
/>
);
};
export default defineFrontComponent({
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
name: 'delete-draft',
description: 'Deletes a draft with confirmation',
component: DeleteDraft,
isHeadless: true,
command: {
universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
label: 'Delete draft',
icon: 'IconTrash',
},
});
```
#### Accesso al contesto di runtime
All'interno del tuo componente, usa gli hook dell'SDK per accedere all'utente corrente, al record e all'istanza del componente:
@@ -858,6 +952,50 @@ I componenti front-end possono attivare navigazione, modali e notifiche utilizza
| `unmountFrontComponent()` | Smonta il componente |
| `updateProgress(progress)` | Aggiorna un indicatore di avanzamento |
Ecco un esempio che usa l'API host per mostrare una snackbar e chiudere il pannello laterale dopo il completamento di un'azione:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
const recordId = useRecordId();
const handleArchive = async () => {
const client = new CoreApiClient();
await client.mutation({
updateTask: {
__args: { id: recordId, data: { status: 'ARCHIVED' } },
id: true,
},
});
await enqueueSnackbar({
message: 'Record archived',
variant: 'success',
});
await closeSidePanel();
};
return (
<div style={{ padding: '20px' }}>
<p>Archive this record?</p>
<button onClick={handleArchive}>Archive</button>
</div>
);
};
export default defineFrontComponent({
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
name: 'archive-record',
description: 'Archives the current record',
component: ArchiveRecord,
});
```
#### Opzioni del comando
Aggiungere un campo `command` a `defineFrontComponent` registra il componente nel menu comandi (Cmd+K). Se `isPinned` è `true`, compare anche come pulsante di azione rapida nell'angolo in alto a destra della pagina.
@@ -1712,3 +1850,86 @@ yarn twenty uninstall
# Skip the confirmation prompt
yarn twenty uninstall --yes
```
## Gestione dei remoti
Un **remoto** è un server Twenty a cui la tua app si connette. Durante la configurazione, lo strumento di scaffolding ne crea uno automaticamente per te. Puoi aggiungere altri remoti o passare da uno all'altro in qualsiasi momento.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Le tue credenziali sono archiviate in `~/.twenty/config.json`.
## CI con GitHub Actions
Lo strumento di scaffolding genera un workflow GitHub Actions pronto all'uso in `.github/workflows/ci.yml`. Esegue automaticamente i test di integrazione a ogni push su `main` e sulle pull request.
Il workflow:
1. Esegue il checkout del tuo codice
2. Avvia un server Twenty temporaneo utilizzando l'azione `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Installa le dipendenze con `yarn install --immutable`
4. Esegue `yarn test` con `TWENTY_API_URL` e `TWENTY_API_KEY` iniettati dagli output dell'azione
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Non è necessario configurare alcun secret — l'azione `spawn-twenty-docker-image` avvia un server Twenty effimero direttamente nel runner e fornisce i dettagli di connessione. Il secret `GITHUB_TOKEN` è fornito automaticamente da GitHub.
Per fissare una versione specifica di Twenty invece di `latest`, modifica la variabile d'ambiente `TWENTY_VERSION` all'inizio del workflow.
@@ -7,7 +7,9 @@ description: Crea la tua prima app Twenty in pochi minuti.
Le app sono attualmente in fase alfa. La funzionalità funziona ma è ancora in evoluzione.
</Warning>
Le app ti permettono di estendere Twenty con oggetti, campi, funzioni logiche, competenze IA e componenti UI personalizzati — il tutto gestito come codice.
## Cosa sono le app?
Le app ti consentono di estendere Twenty con oggetti, campi, funzioni logiche, componenti front-end, competenze IA e altro ancora — il tutto gestito come codice. Invece di configurare tutto tramite l'interfaccia utente, definisci in TypeScript il modello dati e la logica e li distribuisci in uno o più spazi di lavoro.
## Prerequisiti
@@ -17,7 +19,9 @@ Prima di iniziare, assicurati che quanto segue sia installato sul tuo computer:
* **Yarn 4** — Incluso con Node.js tramite Corepack. Abilitalo eseguendo `corepack enable`
* **Docker** — [Scarica qui](https://www.docker.com/products/docker-desktop/). Necessario per eseguire un'istanza locale di Twenty. Non necessario se hai già un server Twenty in esecuzione.
## Passaggio 1: Crea lo scheletro della tua app
## Crea la tua prima app
### Crea lo scheletro della tua app
Apri un terminale ed esegui:
@@ -29,18 +33,7 @@ Ti verrà chiesto di inserire un nome e una descrizione per la tua app. Premi **
Questo crea una nuova cartella chiamata `my-twenty-app` con tutto il necessario.
<Note>
Lo strumento di scaffolding supporta questi flag:
* `--minimal` — genera solo i file essenziali, senza esempi (predefinito)
* `--exhaustive` — genera tutte le entità di esempio
* `--name <name>` — imposta il nome dell'app (salta la richiesta)
* `--display-name <displayName>` — imposta il nome visualizzato (salta la richiesta)
* `--description <description>` — imposta la descrizione (salta la richiesta)
* `--skip-local-instance` — salta la richiesta di configurazione del server locale
</Note>
## Passaggio 2: Configura un'istanza locale di Twenty
### Configura un'istanza locale di Twenty
Lo strumento di scaffolding chiederà:
@@ -53,7 +46,7 @@ Lo strumento di scaffolding chiederà:
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Avviare l'istanza locale?" />
</div>
## Passaggio 3: Accedi al tuo spazio di lavoro
### Accedi al tuo spazio di lavoro
Successivamente si aprirà una finestra del browser con la pagina di accesso di Twenty. Accedi con l'account demo preconfigurato:
@@ -64,7 +57,7 @@ Successivamente si aprirà una finestra del browser con la pagina di accesso di
<img src="/images/docs/developers/extends/apps/login.png" alt="Schermata di accesso di Twenty" />
</div>
## Passaggio 4: Autorizza l'app
### Autorizza l'app
Dopo l'accesso, vedrai una schermata di autorizzazione. Questo consente alla tua app di interagire con il tuo spazio di lavoro.
@@ -80,7 +73,7 @@ Una volta autorizzato, il terminale confermerà che tutto è configurato.
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="App creata con successo" />
</div>
## Passaggio 5: Inizia a sviluppare
### Inizia a sviluppare
Entra nella nuova cartella della tua app e avvia il server di sviluppo:
@@ -105,7 +98,7 @@ La modalità di sviluppo è disponibile solo sulle istanze di Twenty in esecuzio
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Output del terminale in modalità sviluppo" />
</div>
## Passaggio 6: Visualizza la tua app in Twenty
### Visualizza la tua app in Twenty
Apri [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) nel browser. Vai su **Settings > Apps** e seleziona la scheda **Developer**. Dovresti vedere la tua app elencata in **Your Apps**:
@@ -133,13 +126,28 @@ Passa alla scheda **Content** per vedere tutto ciò che la tua app fornisce —
È tutto pronto! Modifica qualsiasi file in `src/` e le modifiche verranno rilevate automaticamente.
Vai a [Creare app](/l/it/developers/extend/apps/building) per una guida dettagliata sulla creazione di oggetti, funzioni logiche, componenti front-end, skill e altro.
---
## Cosa puoi creare
Le app sono composte da **entità** — ciascuna definita come un file TypeScript con un singolo `export default`:
| Entità | Cosa fa |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| **Oggetti e campi** | Definisci modelli di dati personalizzati (come Post Card, Invoice) con campi tipizzati |
| **Funzioni logiche** | Funzioni TypeScript lato server attivate da route HTTP, pianificazioni cron o eventi del database |
| **Componenti front-end** | Componenti React che vengono renderizzati all'interno dell'UI di Twenty (pannello laterale, widget, menu comandi) |
| **Skill e agenti** | Funzionalità di IA — istruzioni riutilizzabili e assistenti autonomi |
| **Viste e navigazione** | Viste elenco preconfigurate e voci di menu della barra laterale per i tuoi oggetti |
| **Layout di pagina** | Pagine di dettaglio dei record personalizzate con schede e widget |
Vai a [Creare app](/l/it/developers/extend/apps/building) per una guida dettagliata su ogni tipo di entità.
---
## Struttura del progetto
Lo strumento di scaffolding genera la seguente struttura di file (mostrata con la modalità `--exhaustive`, che include esempi per ogni tipo di entità):
Lo scaffolder genera la seguente struttura dei file:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -148,160 +156,50 @@ my-twenty-app/
.gitignore
.nvmrc
.yarnrc.yml
.yarn/
install-state.gz
.oxlintrc.json
tsconfig.json
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
LLMS.md
README.md
.github/
└── workflows/
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
src/
├── application-config.ts # Required — main application configuration
├── __tests__/
├── setup-test.ts # Test setup (server health check, config)
│ └── app-install.integration-test.ts # Example integration test
── roles/
── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── create-hello-world-company.ts # Example logic function using CoreApiClient
│ ├── pre-install.ts # Runs before installation
│ └── post-install.ts # Runs after installation
├── front-components/
│ └── hello-world.tsx # Example front component
├── page-layouts/
│ └── example-record-page-layout.ts # Example page layout with front component
├── views/
│ └── example-view.ts # Example saved view definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
├── skills/
│ └── example-skill.ts # Example AI agent skill definition
└── agents/
└── example-agent.ts # Example AI agent definition
├── application-config.ts # Required — main application configuration
├── default-role.ts # Default role for logic functions
├── constants/
│ └── universal-identifiers.ts # Auto-generated UUIDs and app metadata
── __tests__/
── setup-test.ts # Test setup (server health check, config)
└── app-install.integration-test.ts # Integration test
```
Per impostazione predefinita (`--minimal`), vengono creati solo i file principali: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` e `logic-functions/post-install.ts`. Usa `--exhaustive` per includere tutti i file di esempio mostrati sopra.
### Partire da un esempio
Per iniziare da un esempio più completo con oggetti personalizzati, campi, funzioni logiche, componenti front-end e altro, usa il flag `--example`:
```bash filename="Terminal"
npx create-twenty-app@latest my-twenty-app --example postcard
```
Gli esempi provengono dalla directory [twenty-apps/examples](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples) su GitHub. Puoi anche aggiungere singole entità a un progetto esistente con `yarn twenty add` (vedi [Creare app](/l/it/developers/extend/apps/building#scaffolding-entities-with-yarn-twenty-add)).
### File principali
| File / Cartella | Scopo |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Dichiara il nome, la versione e le dipendenze della tua app. Include uno script `twenty` così puoi eseguire `yarn twenty help` per vedere tutti i comandi. |
| `src/application-config.ts` | **Obbligatorio.** Il file di configurazione principale della tua app. |
| `src/roles/` | Definisce i ruoli che controllano a cosa possono accedere le tue funzioni logiche. |
| `src/logic-functions/` | Funzioni lato server attivate da route, pianificazioni cron o eventi del database. |
| `src/front-components/` | Componenti React che vengono renderizzati all'interno della UI di Twenty. |
| `src/objects/` | Definizioni di oggetti personalizzati per estendere il tuo modello dati. |
| `src/fields/` | Campi personalizzati aggiunti a oggetti esistenti. |
| `src/views/` | Configurazioni di viste salvate. |
| `src/navigation-menu-items/` | Link personalizzati nella navigazione laterale. |
| `src/skills/` | Abilità che estendono gli agenti IA di Twenty. |
| `src/agents/` | Agenti IA con prompt personalizzati. |
| `src/page-layouts/` | Layout di pagina personalizzati per le viste dei record. |
| `src/__tests__/` | Test di integrazione (setup + test di esempio). |
| `public/` | Asset statici (immagini, font) serviti insieme alla tua app. |
| File / Cartella | Scopo |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Dichiara il nome, la versione e le dipendenze della tua app. Include uno script `twenty` così puoi eseguire `yarn twenty help` per vedere tutti i comandi. |
| `src/application-config.ts` | **Obbligatorio.** Il file di configurazione principale della tua app. |
| `src/default-role.ts` | Ruolo predefinito che controlla a cosa possono accedere le tue funzioni logiche. |
| `src/constants/universal-identifiers.ts` | UUID generati automaticamente e metadati dell'app (nome visualizzato, descrizione). |
| `src/__tests__/` | Test di integrazione (setup + test di esempio). |
| `public/` | Asset statici (immagini, font) serviti insieme alla tua app. |
## Gestione dei remoti
## Server di sviluppo locale
Un **remoto** è un server Twenty a cui la tua app si connette. Durante la configurazione, lo strumento di scaffolding ne crea uno automaticamente per te. Puoi aggiungere altri remoti o passare da uno all'altro in qualsiasi momento.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Le tue credenziali sono archiviate in `~/.twenty/config.json`.
## Server di sviluppo locale (`yarn twenty server`)
La CLI può gestire un server Twenty locale in esecuzione in Docker. Questo è lo stesso server avviato automaticamente quando crei lo scheletro di un'app con `create-twenty-app`, ma puoi anche gestirlo manualmente.
### Avvio del server
```bash filename="Terminal"
yarn twenty server start
```
Questo scarica l'immagine Docker `twentycrm/twenty-app-dev:latest` (se non è già presente), crea un container chiamato `twenty-app-dev` e lo avvia sulla porta **2020**. La CLI attende che il server superi il controllo di integrità prima di restituire il controllo.
Vengono creati due volumi Docker per mantenere i dati tra i riavvii:
* `twenty-app-dev-data` — database PostgreSQL
* `twenty-app-dev-storage` — archiviazione file
Se la porta 2020 è già in uso, puoi avviare su una porta diversa:
```bash filename="Terminal"
yarn twenty server start --port 3030
```
La CLI configura automaticamente le variabili interne del container `NODE_PORT` e `SERVER_URL` per corrispondere alla porta scelta, in modo che funzioni logiche, OAuth e tutto il resto del networking interno funzionino correttamente.
Una volta avviato, il server viene registrato automaticamente come remoto `local` nella configurazione della CLI.
### Verifica dello stato del server
```bash filename="Terminal"
yarn twenty server status
```
Mostra se il server è in esecuzione, il suo URL e le credenziali di accesso predefinite (`[email protected]` / `[email protected]`).
### Visualizzazione dei log del server
```bash filename="Terminal"
yarn twenty server logs
```
Trasmette in streaming i log del container. Usa `--lines` per controllare quante righe recenti mostrare:
```bash filename="Terminal"
yarn twenty server logs --lines 100
```
### Arresto del server
```bash filename="Terminal"
yarn twenty server stop
```
Arresta il container. I tuoi dati vengono conservati nei volumi Docker — il prossimo `start` riprenderà da dove avevi lasciato.
### Reimpostazione del server
```bash filename="Terminal"
yarn twenty server reset
```
Rimuove il container **e** elimina entrambi i volumi Docker, cancellando tutti i dati. Il prossimo `start` crea un'istanza nuova.
<Note>
Il server richiede che **Docker** sia in esecuzione. Se vedi l'errore "Docker not running", assicurati che Docker Desktop (o il demone Docker) sia avviato.
</Note>
### Riferimento ai comandi
Lo scaffolder ha già avviato per te un server Twenty locale. Per gestirlo in seguito, usa `yarn twenty server`:
| Comando | Descrizione |
| -------------------------------------- | --------------------------------------------------------- |
@@ -313,65 +211,11 @@ Rimuove il container **e** elimina entrambi i volumi Docker, cancellando tutti i
| `yarn twenty server logs --lines 100` | Mostra le ultime 100 righe di log |
| `yarn twenty server reset` | Elimina tutti i dati e riparti da zero |
## CI con GitHub Actions
I dati vengono mantenuti tra i riavvii in due volumi Docker (`twenty-app-dev-data` per PostgreSQL, `twenty-app-dev-storage` per i file). Usa `reset` per cancellare tutto e ripartire da zero.
Lo strumento di scaffolding genera un workflow GitHub Actions pronto all'uso in `.github/workflows/ci.yml`. Esegue automaticamente i test di integrazione a ogni push su `main` e sulle pull request.
Il workflow:
1. Esegue il checkout del tuo codice
2. Avvia un server Twenty temporaneo utilizzando l'azione `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Installa le dipendenze con `yarn install --immutable`
4. Esegue `yarn test` con `TWENTY_API_URL` e `TWENTY_API_KEY` iniettati dagli output dell'azione
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Non è necessario configurare alcun secret — l'azione `spawn-twenty-docker-image` avvia un server Twenty effimero direttamente nel runner e fornisce i dettagli di connessione. Il secret `GITHUB_TOKEN` è fornito automaticamente da GitHub.
Per fissare una versione specifica di Twenty invece di `latest`, modifica la variabile d'ambiente `TWENTY_VERSION` all'inizio del workflow.
<Note>
Il server richiede che **Docker** sia in esecuzione. Se vedi l'errore "Docker not running", assicurati che Docker Desktop (o il demone Docker) sia avviato.
</Note>
## Configurazione manuale (senza lo scaffolder)
@@ -52,7 +52,11 @@ yarn twenty deploy
### Condivisione di un'app distribuita
Le app in formato tarball non sono elencate nel marketplace pubblico, quindi altri spazi di lavoro sullo stesso server non le troveranno navigando. Per condividere un'app distribuita:
<Warning>
Sharing private (tarball) apps across workspaces is an **Enterprise** feature. The **Distribution** tab will show an upgrade prompt instead of the share controls until your workspace has a valid Enterprise key. See [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to activate it.
</Warning>
Le app in formato tarball non sono elencate nel marketplace pubblico, quindi altri spazi di lavoro sullo stesso server non le troveranno navigando. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. Vai su **Impostazioni > Applicazioni > Registrazioni** e apri la tua app
2. Nella scheda **Distribuzione**, fai clic su **Copia link di condivisione**
@@ -60,10 +64,6 @@ Le app in formato tarball non sono elencate nel marketplace pubblico, quindi alt
Il link di condivisione utilizza l'URL di base del server (senza alcun sottodominio dello spazio di lavoro) così funziona per qualsiasi spazio di lavoro sul server.
<Warning>
La condivisione delle app private è una funzionalità Enterprise. Vai a [Impostazioni > Pannello di amministrazione > Enterprise](/settings/admin-panel#enterprise) per abilitarla.
</Warning>
### Gestione delle versioni
Per rilasciare un aggiornamento:
@@ -81,7 +81,7 @@ import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
universalIdentifier: '39783023-bcac-41e3-b0d2-ff1944d8465d',
displayName: 'My Twenty App',
description: 'My first Twenty app',
icon: 'IconWorld',
@@ -716,6 +716,13 @@ Pontos-chave:
Componentes de front-end são componentes React que renderizam diretamente dentro da UI do Twenty. Eles são executados em um Web Worker isolado usando Remote DOM — seu código é sandboxed, mas renderiza nativamente na página, não em um iframe.
#### Onde os componentes de front-end podem ser usados
Os componentes de front-end podem ser renderizados em dois locais dentro do Twenty:
* **Painel lateral** — Componentes de front-end não headless abrem no painel lateral direito. Este é o comportamento padrão quando um componente de front-end é acionado pelo menu de comandos.
* **Widgets (painéis e páginas de registro)** — Componentes de front-end podem ser incorporados como widgets nos layouts de página. Ao configurar um painel ou o layout de uma página de registro, os usuários podem adicionar um widget de componente de front-end.
#### Exemplo básico
A maneira mais rápida de ver um componente de front-end em ação é registrá-lo como um **comando**. Adicionar um campo `command` com `isPinned: true` faz com que ele apareça como um botão de ação rápida no canto superior direito da página — não é necessário layout de página:
@@ -773,9 +780,13 @@ Clique nele para renderizar o componente inline.
Além de comandos, você pode incorporar um componente de front-end diretamente em uma página de registro adicionando-o como um widget em um **layout de página**. Veja a seção [definePageLayout](#definepagelayout) para obter detalhes.
#### Componentes sem interface (`isHeadless: true`)
#### Headless vs não headless
Componentes sem interface não renderizam nenhuma UI visível, mas ainda executam a lógica do React. Isso é útil para **componentes de efeito** — componentes que executam efeitos colaterais quando montados, como sincronizar dados, iniciar um temporizador, ouvir eventos ou disparar uma notificação.
Os componentes de front-end têm dois modos de renderização controlados pela opção `isHeadless`:
**Não headless (padrão)** — O componente renderiza uma interface visível. Quando acionado pelo menu de comandos, ele é aberto no painel lateral. Este é o comportamento padrão quando `isHeadless` é `false` ou omitido.
**Headless (`isHeadless: true`)** — The component mounts invisibly in the background. Ele não abre o painel lateral. Componentes headless são projetados para ações que executam lógica e, em seguida, se desmontam — por exemplo, executar uma tarefa assíncrona, navegar para uma página ou exibir um modal de confirmação. Eles se combinam naturalmente com os componentes Command do SDK descritos abaixo.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
@@ -802,6 +813,89 @@ export default defineFrontComponent({
Como o componente retorna `null`, o Twenty ignora renderizar um contêiner para ele — nenhum espaço vazio aparece no layout. O componente ainda tem acesso a todos os hooks e à API de comunicação do host.
#### Componentes Command do SDK
O pacote `twenty-sdk` fornece quatro componentes auxiliares Command projetados para componentes de front-end headless. Cada componente executa uma ação ao montar, trata erros exibindo uma notificação de snackbar e desmonta automaticamente o componente de front-end ao concluir.
Importe-os de `twenty-sdk/command`:
* **`Command`** — Executa um callback assíncrono via a prop `execute`.
* **`CommandLink`** — Navega para um caminho do app. Props: `to`, `params`, `queryParams`, `options`.
* **`CommandModal`** — Abre um modal de confirmação. Se o usuário confirmar, executa o callback `execute`. Props: `title`, `subtitle`, `execute`, `confirmButtonText`, `confirmButtonAccent`.
* **`CommandOpenSidePanelPage`** — Abre uma página específica do painel lateral. Props: `page`, `pageTitle`, `pageIcon`.
Aqui está um exemplo completo de um componente de front-end headless usando `Command` para executar uma ação a partir do menu de comandos:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
command: {
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
},
});
```
E um exemplo usando `CommandModal` para solicitar confirmação antes de executar:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
const execute = async () => {
// perform the deletion
};
return (
<CommandModal
title="Delete draft?"
subtitle="This action cannot be undone."
execute={execute}
confirmButtonText="Delete"
confirmButtonAccent="danger"
/>
);
};
export default defineFrontComponent({
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
name: 'delete-draft',
description: 'Deletes a draft with confirmation',
component: DeleteDraft,
isHeadless: true,
command: {
universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
label: 'Delete draft',
icon: 'IconTrash',
},
});
```
#### Acessando o contexto de execução
Dentro do seu componente, use hooks do SDK para acessar o usuário atual, o registro e a instância do componente:
@@ -858,6 +952,50 @@ Componentes de front-end podem acionar navegação, modais e notificações usan
| `unmountFrontComponent()` | Desmontar o componente |
| `updateProgress(progress)` | Atualizar um indicador de progresso |
Aqui está um exemplo que usa a API do host para exibir um snackbar e fechar o painel lateral após a conclusão de uma ação:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
const recordId = useRecordId();
const handleArchive = async () => {
const client = new CoreApiClient();
await client.mutation({
updateTask: {
__args: { id: recordId, data: { status: 'ARCHIVED' } },
id: true,
},
});
await enqueueSnackbar({
message: 'Record archived',
variant: 'success',
});
await closeSidePanel();
};
return (
<div style={{ padding: '20px' }}>
<p>Archive this record?</p>
<button onClick={handleArchive}>Archive</button>
</div>
);
};
export default defineFrontComponent({
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
name: 'archive-record',
description: 'Archives the current record',
component: ArchiveRecord,
});
```
#### Opções de comando
Adicionar um campo `command` a `defineFrontComponent` registra o componente no menu de comandos (Cmd+K). Se `isPinned` for `true`, ele também aparece como um botão de ação rápida no canto superior direito da página.
@@ -1712,3 +1850,86 @@ yarn twenty uninstall
# Skip the confirmation prompt
yarn twenty uninstall --yes
```
## Gerenciando remotos
Um **remoto** é um servidor Twenty ao qual seu aplicativo se conecta. Durante a configuração, o gerador de scaffold cria um para você automaticamente. Você pode adicionar mais remotos ou alternar entre eles a qualquer momento.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Suas credenciais são armazenadas em `~/.twenty/config.json`.
## CI com GitHub Actions
O gerador de scaffold cria um workflow do GitHub Actions pronto para uso em `.github/workflows/ci.yml`. Ele executa seus testes de integração automaticamente a cada push para `main` e em pull requests.
O workflow:
1. Faz checkout do seu código
2. Inicializa um servidor Twenty temporário usando a ação `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Instala as dependências com `yarn install --immutable`
4. Executa `yarn test` com `TWENTY_API_URL` e `TWENTY_API_KEY` injetados a partir das saídas da ação
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Você não precisa configurar nenhum segredo — a ação `spawn-twenty-docker-image` inicia um servidor Twenty efêmero diretamente no runner e fornece os detalhes de conexão. O segredo `GITHUB_TOKEN` é fornecido automaticamente pelo GitHub.
Para fixar uma versão específica do Twenty em vez de `latest`, altere a variável de ambiente `TWENTY_VERSION` no topo do workflow.
@@ -7,7 +7,9 @@ description: Crie seu primeiro app do Twenty em minutos.
Os aplicativos estão atualmente em testes alfa. O recurso é funcional, mas ainda está evoluindo.
</Warning>
Os apps permitem que você estenda o Twenty com objetos, campos, funções de lógica, habilidades de IA e componentes de UI personalizados — tudo gerenciado como código.
## O que são aplicativos?
Os aplicativos permitem que você estenda o Twenty com objetos e campos personalizados, funções lógicas, componentes de front-end, habilidades de IA e mais — tudo gerenciado como código. Em vez de configurar tudo pela UI, você define seu modelo de dados e a lógica em TypeScript e implanta em um ou mais workspaces.
## Pré-requisitos
@@ -17,7 +19,9 @@ Antes de começar, verifique se o seguinte está instalado na sua máquina:
* **Yarn 4** — Vem com o Node.js via Corepack. Ative-o executando `corepack enable`
* **Docker** — [Baixe aqui](https://www.docker.com/products/docker-desktop/). Necessário para executar uma instância local do Twenty. Não é necessário se você já tiver um servidor Twenty em execução.
## Passo 1: Gere o scaffold do seu aplicativo
## Crie seu primeiro aplicativo
### Gere o scaffold do seu aplicativo
Abra um terminal e execute:
@@ -29,18 +33,7 @@ Será solicitado que você informe um nome e uma descrição para o seu aplicati
Isso cria uma nova pasta chamada `my-twenty-app` com tudo de que você precisa.
<Note>
O gerador de scaffold oferece suporte a estas flags:
* `--minimal` — gera apenas os arquivos essenciais, sem exemplos (padrão)
* `--exhaustive` — gera todas as entidades de exemplo
* `--name <name>` — define o nome do aplicativo (pula o prompt)
* `--display-name <displayName>` — define o nome de exibição (pula o prompt)
* `--description <description>` — define a descrição (pula o prompt)
* `--skip-local-instance` — ignora o prompt de configuração do servidor local
</Note>
## Passo 2: Configure uma instância local do Twenty
### Configure uma instância local do Twenty
O gerador de scaffold perguntará:
@@ -53,7 +46,7 @@ O gerador de scaffold perguntará:
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Deve iniciar instância local?" />
</div>
## Passo 3: Faça login no seu espaço de trabalho
### Faça login no seu espaço de trabalho
Em seguida, uma janela do navegador será aberta com a página de login do Twenty. Faça login com a conta de demonstração pré-configurada:
@@ -64,7 +57,7 @@ Em seguida, uma janela do navegador será aberta com a página de login do Twent
<img src="/images/docs/developers/extends/apps/login.png" alt="Tela de login do Twenty" />
</div>
## Passo 4: Autorize o aplicativo
### Autorize o aplicativo
Após fazer login, você verá uma tela de autorização. Isso permite que seu aplicativo interaja com seu espaço de trabalho.
@@ -80,7 +73,7 @@ Depois de autorizado, seu terminal confirmará que tudo está configurado.
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="Scaffold do aplicativo criado com sucesso" />
</div>
## Passo 5: Comece a desenvolver
### Comece a desenvolver
Entre na nova pasta do seu aplicativo e inicie o servidor de desenvolvimento:
@@ -105,7 +98,7 @@ O modo de desenvolvimento só está disponível em instâncias do Twenty em modo
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Saída do terminal no modo de desenvolvimento" />
</div>
## Passo 6: Veja seu aplicativo no Twenty
### Veja seu aplicativo no Twenty
Abra [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) no seu navegador. Navegue até **Settings > Apps** e selecione a aba **Developer**. Você deverá ver seu aplicativo listado em **Your Apps**:
@@ -133,13 +126,28 @@ Altere para a aba **Content** para ver tudo o que seu aplicativo oferece — obj
Tudo pronto! Edite qualquer arquivo em `src/` e as alterações serão detectadas automaticamente.
Acesse [Criando aplicativos](/l/pt/developers/extend/apps/building) para um guia detalhado sobre criação de objetos, funções de lógica, componentes de front-end, habilidades e mais.
---
## O que você pode criar
Os aplicativos são compostos por **entidades** — cada uma definida como um arquivo TypeScript com um único `export default`:
| Entidade | O que faz |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| **Objetos e campos** | Defina modelos de dados personalizados (como cartão postal, fatura) com campos tipados |
| **Funções lógicas** | Funções TypeScript do lado do servidor acionadas por rotas HTTP, agendamentos do cron ou eventos de banco de dados |
| **Componentes de front-end** | Componentes React que são renderizados na UI do Twenty (painel lateral, widgets, menu de comandos) |
| **Habilidades e agentes** | Recursos de IA — instruções reutilizáveis e assistentes autônomos |
| **Exibições e navegação** | Exibições de lista pré-configuradas e itens de menu da barra lateral para seus objetos |
| **Layouts de página** | Páginas de detalhes de registros personalizadas com abas e widgets |
Acesse [Criando aplicativos](/l/pt/developers/extend/apps/building) para um guia detalhado sobre cada tipo de entidade.
---
## Estrutura do projeto
O gerador de scaffold cria a seguinte estrutura de arquivos (mostrada com o modo `--exhaustive`, que inclui exemplos para cada tipo de entidade):
A ferramenta de scaffolding gera a seguinte estrutura de arquivos:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -148,160 +156,50 @@ my-twenty-app/
.gitignore
.nvmrc
.yarnrc.yml
.yarn/
install-state.gz
.oxlintrc.json
tsconfig.json
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
LLMS.md
README.md
.github/
└── workflows/
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
src/
├── application-config.ts # Required — main application configuration
├── __tests__/
├── setup-test.ts # Test setup (server health check, config)
│ └── app-install.integration-test.ts # Example integration test
── roles/
── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── create-hello-world-company.ts # Example logic function using CoreApiClient
│ ├── pre-install.ts # Runs before installation
│ └── post-install.ts # Runs after installation
├── front-components/
│ └── hello-world.tsx # Example front component
├── page-layouts/
│ └── example-record-page-layout.ts # Example page layout with front component
├── views/
│ └── example-view.ts # Example saved view definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
├── skills/
│ └── example-skill.ts # Example AI agent skill definition
└── agents/
└── example-agent.ts # Example AI agent definition
├── application-config.ts # Required — main application configuration
├── default-role.ts # Default role for logic functions
├── constants/
│ └── universal-identifiers.ts # Auto-generated UUIDs and app metadata
── __tests__/
── setup-test.ts # Test setup (server health check, config)
└── app-install.integration-test.ts # Integration test
```
Por padrão (`--minimal`), apenas os arquivos principais são criados: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` e `logic-functions/post-install.ts`. Use `--exhaustive` para incluir todos os arquivos de exemplo mostrados acima.
### Começando a partir de um exemplo
Para começar a partir de um exemplo mais completo com objetos, campos, funções de lógica, componentes de front-end e mais, use a opção `--example`:
```bash filename="Terminal"
npx create-twenty-app@latest my-twenty-app --example postcard
```
Os exemplos são obtidos do diretório [twenty-apps/examples](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples) no GitHub. Você também pode criar o scaffolding de entidades individuais em um projeto existente com `yarn twenty add` (veja [Criando aplicativos](/l/pt/developers/extend/apps/building#scaffolding-entities-with-yarn-twenty-add)).
### Arquivos principais
| Arquivo / Pasta | Finalidade |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Declara o nome, a versão e as dependências do seu aplicativo. Inclui um script `twenty` para que você possa executar `yarn twenty help` e ver todos os comandos. |
| `src/application-config.ts` | **Obrigatório.** O principal arquivo de configuração do seu aplicativo. |
| `src/roles/` | Define papéis que controlam o que suas funções de lógica podem acessar. |
| `src/logic-functions/` | Funções do lado do servidor acionadas por rotas, agendamentos do cron ou eventos de banco de dados. |
| `src/front-components/` | Componentes React que renderizam dentro da interface do Twenty. |
| `src/objects/` | Definições de objetos personalizados para estender seu modelo de dados. |
| `src/fields/` | Campos personalizados adicionados a objetos existentes. |
| `src/views/` | Configurações de visualizações salvas. |
| `src/navigation-menu-items/` | Links personalizados na navegação da barra lateral. |
| `src/skills/` | Habilidades que estendem os agentes de IA do Twenty. |
| `src/agents/` | Agentes de IA com prompts personalizados. |
| `src/page-layouts/` | Layouts de página personalizados para visualizações de registros. |
| `src/__tests__/` | Testes de integração (configuração + teste de exemplo). |
| `public/` | Recursos estáticos (imagens, fontes) servidos com seu aplicativo. |
| Arquivo / Pasta | Finalidade |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Declara o nome, a versão e as dependências do seu aplicativo. Inclui um script `twenty` para que você possa executar `yarn twenty help` e ver todos os comandos. |
| `src/application-config.ts` | **Obrigatório.** O principal arquivo de configuração do seu aplicativo. |
| `src/default-role.ts` | Papel padrão que controla o que suas funções de lógica podem acessar. |
| `src/constants/universal-identifiers.ts` | UUIDs gerados automaticamente e metadados do aplicativo (nome de exibição, descrição). |
| `src/__tests__/` | Testes de integração (configuração + teste de exemplo). |
| `public/` | Recursos estáticos (imagens, fontes) servidos com seu aplicativo. |
## Gerenciando remotos
## Servidor de desenvolvimento local
Um **remoto** é um servidor Twenty ao qual seu aplicativo se conecta. Durante a configuração, o gerador de scaffold cria um para você automaticamente. Você pode adicionar mais remotos ou alternar entre eles a qualquer momento.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Suas credenciais são armazenadas em `~/.twenty/config.json`.
## Servidor de desenvolvimento local (`yarn twenty server`)
A CLI pode gerenciar um servidor Twenty local em execução no Docker. Este é o mesmo servidor iniciado automaticamente quando você cria o scaffold de um aplicativo com `create-twenty-app`, mas você também pode gerenciá-lo manualmente.
### Iniciando o servidor
```bash filename="Terminal"
yarn twenty server start
```
Isso baixa a imagem Docker `twentycrm/twenty-app-dev:latest` (se ainda não estiver presente), cria um contêiner chamado `twenty-app-dev` e o inicia na porta **2020**. A CLI aguarda até que o servidor passe na verificação de integridade antes de retornar.
Dois volumes do Docker são criados para persistir os dados entre reinicializações:
* `twenty-app-dev-data` — banco de dados PostgreSQL
* `twenty-app-dev-storage` — armazenamento de arquivos
Se a porta 2020 já estiver em uso, você pode iniciar em uma porta diferente:
```bash filename="Terminal"
yarn twenty server start --port 3030
```
A CLI configura automaticamente as variáveis internas do contêiner `NODE_PORT` e `SERVER_URL` para corresponderem à porta escolhida, para que as funções de lógica, o OAuth e toda a comunicação interna de rede funcionem corretamente.
Depois de iniciado, o servidor é registrado automaticamente como o remoto `local` na configuração da sua CLI.
### Verificando o status do servidor
```bash filename="Terminal"
yarn twenty server status
```
Exibe se o servidor está em execução, sua URL e as credenciais de login padrão (`[email protected]` / `[email protected]`).
### Visualizando os logs do servidor
```bash filename="Terminal"
yarn twenty server logs
```
Transmite os logs do contêiner. Use `--lines` para controlar quantas linhas recentes mostrar:
```bash filename="Terminal"
yarn twenty server logs --lines 100
```
### Parando o servidor
```bash filename="Terminal"
yarn twenty server stop
```
Interrompe o contêiner. Seus dados são preservados nos volumes do Docker — o próximo `start` continua de onde você parou.
### Redefinindo o servidor
```bash filename="Terminal"
yarn twenty server reset
```
Remove o contêiner **e** exclui os dois volumes do Docker, apagando todos os dados. O próximo `start` cria uma instância nova.
<Note>
O servidor requer que o **Docker** esteja em execução. Se você vir um erro "Docker not running", certifique-se de que o Docker Desktop (ou o daemon do Docker) esteja iniciado.
</Note>
### Referência de comandos
A ferramenta de scaffolding já iniciou um servidor local do Twenty para você. Para gerenciá-lo depois, use `yarn twenty server`:
| Comando | Descrição |
| -------------------------------------- | ------------------------------------------------------ |
@@ -313,65 +211,11 @@ Remove o contêiner **e** exclui os dois volumes do Docker, apagando todos os da
| `yarn twenty server logs --lines 100` | Mostra as últimas 100 linhas de log |
| `yarn twenty server reset` | Exclui todos os dados e inicia do zero |
## CI com GitHub Actions
Os dados são persistidos entre reinicializações em dois volumes do Docker (`twenty-app-dev-data` para PostgreSQL, `twenty-app-dev-storage` para arquivos). Use `reset` para apagar tudo e começar do zero.
O gerador de scaffold cria um workflow do GitHub Actions pronto para uso em `.github/workflows/ci.yml`. Ele executa seus testes de integração automaticamente a cada push para `main` e em pull requests.
O workflow:
1. Faz checkout do seu código
2. Inicializa um servidor Twenty temporário usando a ação `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Instala as dependências com `yarn install --immutable`
4. Executa `yarn test` com `TWENTY_API_URL` e `TWENTY_API_KEY` injetados a partir das saídas da ação
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Você não precisa configurar nenhum segredo — a ação `spawn-twenty-docker-image` inicia um servidor Twenty efêmero diretamente no runner e fornece os detalhes de conexão. O segredo `GITHUB_TOKEN` é fornecido automaticamente pelo GitHub.
Para fixar uma versão específica do Twenty em vez de `latest`, altere a variável de ambiente `TWENTY_VERSION` no topo do workflow.
<Note>
O servidor requer que o **Docker** esteja em execução. Se você vir um erro "Docker not running", certifique-se de que o Docker Desktop (ou o daemon do Docker) esteja iniciado.
</Note>
## Configuração manual (sem o gerador)
@@ -52,7 +52,11 @@ yarn twenty deploy
### Compartilhando um aplicativo implantado
Aplicativos em tarball não são listados no marketplace público, então outros espaços de trabalho no mesmo servidor não os descobrirão ao navegar. Para compartilhar um aplicativo implantado:
<Warning>
Sharing private (tarball) apps across workspaces is an **Enterprise** feature. The **Distribution** tab will show an upgrade prompt instead of the share controls until your workspace has a valid Enterprise key. See [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to activate it.
</Warning>
Aplicativos em tarball não são listados no marketplace público, então outros espaços de trabalho no mesmo servidor não os descobrirão ao navegar. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. Vá para **Configurações > Aplicações > Registros** e abra seu aplicativo
2. Na guia **Distribuição**, clique em **Copiar link de compartilhamento**
@@ -60,10 +64,6 @@ Aplicativos em tarball não são listados no marketplace público, então outros
O link de compartilhamento usa a URL base do servidor (sem qualquer subdomínio de espaço de trabalho), para funcionar em qualquer espaço de trabalho no servidor.
<Warning>
Compartilhar apps privados é um recurso do plano Enterprise. Vá para [Configurações > Painel de Administração > Enterprise](/settings/admin-panel#enterprise) para ativá-lo.
</Warning>
### Gerenciamento de versões
Para lançar uma atualização:
@@ -81,7 +81,7 @@ import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
universalIdentifier: '39783023-bcac-41e3-b0d2-ff1944d8465d',
displayName: 'My Twenty App',
description: 'My first Twenty app',
icon: 'IconWorld',
@@ -717,6 +717,13 @@ Puncte cheie:
Componentele front-end sunt componente React care se afișează direct în interfața Twenty. Rulează într-un **Web Worker** izolat folosind Remote DOM — codul este izolat (sandboxed), dar se redă nativ în pagină, nu într-un iframe.
#### Unde pot fi utilizate componentele frontale
Componentele frontale pot fi afișate în două locații în cadrul Twenty:
* **Panou lateral** — Componentele frontale care nu sunt headless se deschid în panoul lateral din dreapta. Acesta este comportamentul implicit atunci când o componentă frontală este declanșată din meniul de comenzi.
* **Widgeturi (tablouri de bord și pagini de înregistrare)** — Componentele frontale pot fi încorporate ca widgeturi în machetele de pagină. La configurarea unui tablou de bord sau a machetei unei pagini de înregistrare, utilizatorii pot adăuga un widget de componentă frontală.
#### Exemplu de bază
Cel mai rapid mod de a vedea o componentă front-end în acțiune este să o înregistrați ca o **comandă**. Adăugarea unui câmp `command` cu `isPinned: true` o face să apară ca un buton de acțiune rapidă în colțul din dreapta sus al paginii — nu este nevoie de layout de pagină:
@@ -774,9 +781,13 @@ Faceți clic pe el pentru a afișa componenta inline.
Dincolo de comenzi, puteți încorpora o componentă front-end direct într-o pagină de înregistrare adăugând-o ca widget într-un **layout de pagină**. Consultați secțiunea [definePageLayout](#definepagelayout) pentru detalii.
#### Componente headless (`isHeadless: true`)
#### Headless vs non-headless
Componentele headless nu redau nicio interfață vizibilă, dar rulează în continuare logica React. Acest lucru este util pentru **componente de efect** — componente care execută efecte secundare la montare, cum ar fi sincronizarea datelor, pornirea unui cronometru, ascultarea evenimentelor sau declanșarea unei notificări.
Componentele frontale au două moduri de randare controlate de opțiunea `isHeadless`:
**Non-headless (implicit)** — Componenta afișează o interfață vizibilă. Când este declanșat din meniul de comenzi, se deschide în panoul lateral. Acesta este comportamentul implicit când `isHeadless` este `false` sau omis.
**Headless (`isHeadless: true`)** — Componenta se montează invizibil în fundal. Nu deschide panoul lateral. Componentele headless sunt concepute pentru acțiuni care execută logică și apoi se demontează — de exemplu, rularea unei sarcini asincrone, navigarea la o pagină sau afișarea unui modal de confirmare. Se potrivesc în mod natural cu componentele Command din SDK descrise mai jos.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
@@ -803,6 +814,89 @@ export default defineFrontComponent({
Deoarece componenta returnează `null`, Twenty omite redarea unui container pentru ea — nu apare spațiu gol în layout. Componenta are în continuare acces la toate hook-urile și la API-ul de comunicare cu gazda.
#### Componentele Command din SDK
Pachetul `twenty-sdk` oferă patru componente ajutătoare Command, concepute pentru componente front-end headless. Fiecare componentă execută o acțiune la montare, gestionează erorile afișând o notificare snackbar și demontează automat componenta de interfață la final.
Importă-le din `twenty-sdk/command`:
* **`Command`** — Rulează un callback asincron prin prop-ul `execute`.
* **`CommandLink`** — Navighează către o rută a aplicației. Props: `to`, `params`, `queryParams`, `options`.
* **`CommandModal`** — Deschide un modal de confirmare. Dacă utilizatorul confirmă, execută callback-ul `execute`. Props: `title`, `subtitle`, `execute`, `confirmButtonText`, `confirmButtonAccent`.
* **`CommandOpenSidePanelPage`** — Deschide o anumită pagină din panoul lateral. Props: `page`, `pageTitle`, `pageIcon`.
Iată un exemplu complet de componentă front-end headless care folosește `Command` pentru a rula o acțiune din meniul de comenzi:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
command: {
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
},
});
```
Și un exemplu care folosește `CommandModal` pentru a cere confirmarea înainte de execuție:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
const execute = async () => {
// perform the deletion
};
return (
<CommandModal
title="Delete draft?"
subtitle="This action cannot be undone."
execute={execute}
confirmButtonText="Delete"
confirmButtonAccent="danger"
/>
);
};
export default defineFrontComponent({
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
name: 'delete-draft',
description: 'Deletes a draft with confirmation',
component: DeleteDraft,
isHeadless: true,
command: {
universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
label: 'Delete draft',
icon: 'IconTrash',
},
});
```
#### Accesarea contextului de rulare
În interiorul componentei, folosiți hook-urile SDK pentru a accesa utilizatorul curent, înregistrarea curentă și instanța componentei:
@@ -859,6 +953,50 @@ Componentele front-end pot declanșa navigare, ferestre modale și notificări f
| `unmountFrontComponent()` | Demontați componenta |
| `updateProgress(progress)` | Actualizați un indicator de progres |
Iată un exemplu care folosește API-ul gazdă pentru a afișa un snackbar și a închide panoul lateral după finalizarea unei acțiuni:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
const recordId = useRecordId();
const handleArchive = async () => {
const client = new CoreApiClient();
await client.mutation({
updateTask: {
__args: { id: recordId, data: { status: 'ARCHIVED' } },
id: true,
},
});
await enqueueSnackbar({
message: 'Record archived',
variant: 'success',
});
await closeSidePanel();
};
return (
<div style={{ padding: '20px' }}>
<p>Archive this record?</p>
<button onClick={handleArchive}>Archive</button>
</div>
);
};
export default defineFrontComponent({
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
name: 'archive-record',
description: 'Archives the current record',
component: ArchiveRecord,
});
```
#### Opțiuni pentru comandă
Adăugarea unui câmp `command` la `defineFrontComponent` înregistrează componenta în meniul de comenzi (Cmd+K). Dacă `isPinned` este `true`, apare și ca buton de acțiune rapidă în colțul din dreapta sus al paginii.
@@ -1713,3 +1851,86 @@ yarn twenty uninstall
# Skip the confirmation prompt
yarn twenty uninstall --yes
```
## Gestionarea remote-urilor
Un „remote” este un server Twenty la care se conectează aplicația. În timpul configurării, generatorul de schelet creează automat unul pentru dvs. Puteți adăuga mai multe remote-uri sau comuta între ele oricând.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Acreditările dvs. sunt stocate în `~/.twenty/config.json`.
## CI cu GitHub Actions
Scaffolderul generează un workflow GitHub Actions gata de utilizare în `.github/workflows/ci.yml`. Rulează automat testele de integrare la fiecare push pe `main` și la pull request-uri.
Workflow-ul:
1. Preia codul
2. Pornește un server Twenty temporar folosind acțiunea `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Instalează dependențele cu `yarn install --immutable`
4. Rulează `yarn test` cu `TWENTY_API_URL` și `TWENTY_API_KEY` injectate din rezultatele acțiunii
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Nu trebuie să configurați niciun secret — acțiunea `spawn-twenty-docker-image` pornește un server Twenty efemer direct în runner și oferă detaliile de conectare. Secretul `GITHUB_TOKEN` este furnizat automat de GitHub.
Pentru a fixa o versiune Twenty specifică în loc de `latest`, modificați variabila de mediu `TWENTY_VERSION` din partea de sus a workflow-ului.
@@ -7,7 +7,9 @@ description: Creați prima dvs. aplicație Twenty în câteva minute.
Aplicațiile sunt în prezent în testare alfa. Caracteristica funcționează, dar este încă în dezvoltare.
</Warning>
Aplicațiile vă permit să extindeți Twenty cu obiecte personalizate, câmpuri, funcții logice, abilități IA și componente UI — toate gestionate ca cod.
## Ce sunt aplicațiile?
Aplicațiile vă permit să extindeți Twenty cu obiecte personalizate, câmpuri, funcții logice, componente front-end, abilități IA și altele — toate gestionate ca cod. În loc să configurați totul prin interfața de utilizator (UI), vă definiți modelul de date și logica în TypeScript și le implementați în unul sau mai multe spații de lucru.
## Cerințe
@@ -17,7 +19,9 @@ Aplicațiile vă permit să extindeți Twenty cu obiecte personalizate, câmpuri
* **Yarn 4** — Vine împreună cu Node.js prin Corepack. Activați-l rulând `corepack enable`
* **Docker** — [Descărcați aici](https://www.docker.com/products/docker-desktop/). Necesar pentru a rula o instanță Twenty locală. Nu este necesar dacă aveți deja un server Twenty care rulează.
## Pasul 1: Creați scheletul aplicației
## Creați prima dvs. aplicație
### Creați scheletul aplicației
Deschideți un terminal și rulați:
@@ -29,18 +33,7 @@ Vi se va cere să introduceți un nume și o descriere pentru aplicația dvs. Ap
Aceasta creează un folder nou numit `my-twenty-app` cu tot ce aveți nevoie.
<Note>
Generatorul de schelet acceptă următoarele opțiuni:
* `--minimal` — generează doar fișierele esențiale, fără exemple (implicit)
* `--exhaustive` — generează toate entitățile de exemplu
* `--name <name>` — setează numele aplicației (omite solicitarea)
* `--display-name <displayName>` — setează numele afișat (omite solicitarea)
* `--description <description>` — setează descrierea (omite solicitarea)
* `--skip-local-instance` — omite solicitarea de configurare a serverului local
</Note>
## Pasul 2: Configurați o instanță Twenty locală
### Configurați o instanță Twenty locală
Generatorul de schelet va întreba:
@@ -53,7 +46,7 @@ Generatorul de schelet va întreba:
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Porniți instanța locală?" />
</div>
## Pasul 3: Autentificați-vă în spațiul dvs. de lucru
### Autentificați-vă în spațiul dvs. de lucru
În continuare, se va deschide o fereastră de browser cu pagina de autentificare Twenty. Autentificați-vă cu contul demo preconfigurat:
@@ -64,7 +57,7 @@ Generatorul de schelet va întreba:
<img src="/images/docs/developers/extends/apps/login.png" alt="Ecranul de autentificare Twenty" />
</div>
## Pasul 4: Autorizați aplicația
### Autorizați aplicația
După autentificare, veți vedea un ecran de autorizare. Acest lucru permite aplicației dvs. să interacționeze cu spațiul dvs. de lucru.
@@ -80,7 +73,7 @@ După autorizare, terminalul va confirma că totul este configurat.
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="Aplicația a fost creată cu succes" />
</div>
## Pasul 5: Începeți dezvoltarea
### Începeți dezvoltarea
Intrați în noul folder al aplicației și porniți serverul de dezvoltare:
@@ -105,7 +98,7 @@ Modul de dezvoltare este disponibil doar pe instanțele Twenty care rulează în
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Ieșirea terminalului în modul de dezvoltare" />
</div>
## Pasul 6: Vedeți aplicația în Twenty
### Vedeți aplicația în Twenty
Deschideți [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) în browser. Navigați la **Settings > Apps** și selectați fila **Developer**. Ar trebui să vedeți aplicația listată la **Your Apps**:
@@ -133,13 +126,28 @@ Comutați la fila **Content** pentru a vedea tot ceea ce oferă aplicația — o
Totul este gata! Editați orice fișier din `src/`, iar modificările vor fi preluate automat.
Accesați [Construirea aplicațiilor](/l/ro/developers/extend/apps/building) pentru un ghid detaliat despre crearea de obiecte, funcții logice, componente front-end, abilități și altele.
---
## Ce puteți construi
Aplicațiile sunt compuse din **entități** — fiecare definită într-un fișier TypeScript cu un singur `export default`:
| Entitate | Ce face |
| --------------------------- | ----------------------------------------------------------------------------------------------------- |
| **Obiecte și câmpuri** | Definiți modele de date personalizate (cum ar fi Post Card, Invoice) cu câmpuri de tip definit |
| **Funcții logice** | Funcții TypeScript pe server declanșate de rute HTTP, programări cron sau evenimente din baza de date |
| **Componente front-end** | Componente React care se afișează în UI-ul Twenty (panou lateral, widgeturi, meniul de comenzi) |
| **Abilități și agenți** | Capabilități AI — instrucțiuni reutilizabile și asistenți autonomi |
| **Vizualizări și navigare** | Vizualizări de listă preconfigurate și elemente de meniu în bara laterală pentru obiectele dvs. |
| **Layouturi de pagină** | Pagini personalizate de detalii ale înregistrărilor cu file și widgeturi |
Accesați [Construirea aplicațiilor](/l/ro/developers/extend/apps/building) pentru un ghid detaliat despre fiecare tip de entitate.
---
## Structura proiectului
Generatorul de schelet generează următoarea structură de fișiere (afișată cu modul `--exhaustive`, care include exemple pentru fiecare tip de entitate):
Generatorul de schelete generează următoarea structură de fișiere:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -148,160 +156,50 @@ my-twenty-app/
.gitignore
.nvmrc
.yarnrc.yml
.yarn/
install-state.gz
.oxlintrc.json
tsconfig.json
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
LLMS.md
README.md
.github/
└── workflows/
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
src/
├── application-config.ts # Required — main application configuration
├── __tests__/
├── setup-test.ts # Test setup (server health check, config)
│ └── app-install.integration-test.ts # Example integration test
── roles/
── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── create-hello-world-company.ts # Example logic function using CoreApiClient
│ ├── pre-install.ts # Runs before installation
│ └── post-install.ts # Runs after installation
├── front-components/
│ └── hello-world.tsx # Example front component
├── page-layouts/
│ └── example-record-page-layout.ts # Example page layout with front component
├── views/
│ └── example-view.ts # Example saved view definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
├── skills/
│ └── example-skill.ts # Example AI agent skill definition
└── agents/
└── example-agent.ts # Example AI agent definition
├── application-config.ts # Required — main application configuration
├── default-role.ts # Default role for logic functions
├── constants/
│ └── universal-identifiers.ts # Auto-generated UUIDs and app metadata
── __tests__/
── setup-test.ts # Test setup (server health check, config)
└── app-install.integration-test.ts # Integration test
```
În mod implicit (`--minimal`), sunt create doar fișierele de bază: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` și `logic-functions/post-install.ts`. Folosiți `--exhaustive` pentru a include toate fișierele de exemplu prezentate mai sus.
### Pornind de la un exemplu
Pentru a porni de la un exemplu mai complet cu obiecte, câmpuri, funcții logice, componente front-end și altele, folosiți opțiunea `--example`:
```bash filename="Terminal"
npx create-twenty-app@latest my-twenty-app --example postcard
```
Exemplele sunt preluate din directorul [twenty-apps/examples](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples) de pe GitHub. Puteți, de asemenea, să creați scheletul entităților individuale într-un proiect existent cu `yarn twenty add` (consultați [Construirea aplicațiilor](/l/ro/developers/extend/apps/building#scaffolding-entities-with-yarn-twenty-add)).
### Fișiere cheie
| Fișier / Folder | Scop |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Declară numele aplicației, versiunea și dependențele. Include un script `twenty` astfel încât să puteți rula `yarn twenty help` pentru a vedea toate comenzile. |
| `src/application-config.ts` | **Necesar.** Fișierul principal de configurare pentru aplicație. |
| `src/roles/` | Definește roluri care controlează la ce pot avea acces funcțiile logice. |
| `src/logic-functions/` | Funcții pe server declanșate de rute, programări cron sau evenimente din baza de date. |
| `src/front-components/` | Componente React care se afișează în interfața Twenty. |
| `src/objects/` | Definiții de obiecte personalizate pentru a extinde modelul de date. |
| `src/fields/` | Câmpuri personalizate adăugate obiectelor existente. |
| `src/views/` | Configurații pentru vizualizări salvate. |
| `src/navigation-menu-items/` | Linkuri personalizate în bara laterală de navigare. |
| `src/skills/` | Abilități care extind capabilitățile agenților AI ai Twenty. |
| `src/agents/` | Agenți AI cu prompturi personalizate. |
| `src/page-layouts/` | Machete de pagină personalizate pentru vizualizările de înregistrare. |
| `src/__tests__/` | Teste de integrare (configurare + test exemplu). |
| `public/` | Resurse statice (imagini, fonturi) servite împreună cu aplicația. |
| Fișier / Folder | Scop |
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Declară numele aplicației, versiunea și dependențele. Include un script `twenty` astfel încât să puteți rula `yarn twenty help` pentru a vedea toate comenzile. |
| `src/application-config.ts` | **Necesar.** Fișierul principal de configurare pentru aplicație. |
| `src/default-role.ts` | Rol implicit care controlează la ce pot avea acces funcțiile logice. |
| `src/constants/universal-identifiers.ts` | UUID-uri generate automat și metadatele aplicației (nume afișat, descriere). |
| `src/__tests__/` | Teste de integrare (configurare + test exemplu). |
| `public/` | Resurse statice (imagini, fonturi) servite împreună cu aplicația. |
## Gestionarea remote-urilor
## Server de dezvoltare local
Un „remote” este un server Twenty la care se conectează aplicația. În timpul configurării, generatorul de schelet creează automat unul pentru dvs. Puteți adăuga mai multe remote-uri sau comuta între ele oricând.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Acreditările dvs. sunt stocate în `~/.twenty/config.json`.
## Server local de dezvoltare (`yarn twenty server`)
CLI-ul poate gestiona un server Twenty local care rulează în Docker. Acesta este același server pornit automat când creați scheletul unei aplicații cu `create-twenty-app`, dar îl puteți gestiona și manual.
### Pornirea serverului
```bash filename="Terminal"
yarn twenty server start
```
Aceasta descarcă imaginea Docker `twentycrm/twenty-app-dev:latest` (dacă nu este deja prezentă), creează un container numit `twenty-app-dev` și îl pornește pe portul **2020**. CLI-ul așteaptă până când serverul trece verificarea de integritate înainte de a reveni.
Sunt create două volume Docker pentru a păstra datele între reporniri:
* `twenty-app-dev-data` — bază de date PostgreSQL
* `twenty-app-dev-storage` — stocare fișiere
Dacă portul 2020 este deja utilizat, puteți porni pe un alt port:
```bash filename="Terminal"
yarn twenty server start --port 3030
```
CLI-ul configurează automat `NODE_PORT` și `SERVER_URL` interne ale containerului pentru a se potrivi cu portul ales, astfel încât funcțiile logice, OAuth și toată rețeaua internă să funcționeze corect.
După pornire, serverul este înregistrat automat ca remote `local` în configurația CLI.
### Verificarea stării serverului
```bash filename="Terminal"
yarn twenty server status
```
Afișează dacă serverul rulează, URL-ul său și acreditările implicite de autentificare (`[email protected]` / `[email protected]`).
### Vizualizarea jurnalelor serverului
```bash filename="Terminal"
yarn twenty server logs
```
Transmite în flux jurnalele containerului. Folosiți `--lines` pentru a controla câte linii recente să fie afișate:
```bash filename="Terminal"
yarn twenty server logs --lines 100
```
### Oprirea serverului
```bash filename="Terminal"
yarn twenty server stop
```
Oprește containerul. Datele dvs. sunt păstrate în volumele Docker — următoarea comandă `start` reia de unde ați rămas.
### Resetarea serverului
```bash filename="Terminal"
yarn twenty server reset
```
Elimină containerul **și** șterge ambele volume Docker, ștergând toate datele. Următoarea comandă `start` creează o instanță nouă.
<Note>
Serverul necesită ca **Docker** să ruleze. Dacă vedeți eroarea "Docker not running", asigurați-vă că Docker Desktop (sau demonul Docker) este pornit.
</Note>
### Referință pentru comenzi
Generatorul de schelete a pornit deja un server Twenty local pentru dvs. Pentru a-l gestiona ulterior, folosiți `yarn twenty server`:
| Comandă | Descriere |
| -------------------------------------- | ------------------------------------------------------------- |
@@ -313,65 +211,11 @@ Elimină containerul **și** șterge ambele volume Docker, ștergând toate date
| `yarn twenty server logs --lines 100` | Afișează ultimele 100 de linii de jurnal |
| `yarn twenty server reset` | Șterge toate datele și pornește de la zero |
## CI cu GitHub Actions
Datele sunt păstrate între reporniri în două volume Docker (`twenty-app-dev-data` pentru PostgreSQL, `twenty-app-dev-storage` pentru fișiere). Folosiți `reset` pentru a șterge totul și a porni de la zero.
Scaffolderul generează un workflow GitHub Actions gata de utilizare în `.github/workflows/ci.yml`. Rulează automat testele de integrare la fiecare push pe `main` și la pull request-uri.
Workflow-ul:
1. Preia codul
2. Pornește un server Twenty temporar folosind acțiunea `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Instalează dependențele cu `yarn install --immutable`
4. Rulează `yarn test` cu `TWENTY_API_URL` și `TWENTY_API_KEY` injectate din rezultatele acțiunii
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Nu trebuie să configurați niciun secret — acțiunea `spawn-twenty-docker-image` pornește un server Twenty efemer direct în runner și oferă detaliile de conectare. Secretul `GITHUB_TOKEN` este furnizat automat de GitHub.
Pentru a fixa o versiune Twenty specifică în loc de `latest`, modificați variabila de mediu `TWENTY_VERSION` din partea de sus a workflow-ului.
<Note>
Serverul necesită ca **Docker** să ruleze. Dacă vedeți eroarea "Docker not running", asigurați-vă că Docker Desktop (sau demonul Docker) este pornit.
</Note>
## Configurare manuală (fără generator)
@@ -52,7 +52,11 @@ yarn twenty deploy
### Partajarea unei aplicații implementate
Aplicațiile tarball nu sunt listate în marketplace-ul public, astfel încât alte spații de lucru de pe același server nu le vor descoperi prin navigare. Pentru a partaja o aplicație implementată:
<Warning>
Sharing private (tarball) apps across workspaces is an **Enterprise** feature. The **Distribution** tab will show an upgrade prompt instead of the share controls until your workspace has a valid Enterprise key. See [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to activate it.
</Warning>
Aplicațiile tarball nu sunt listate în marketplace-ul public, astfel încât alte spații de lucru de pe același server nu le vor descoperi prin navigare. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. Mergi la **Setări > Aplicații > Înregistrări** și deschide aplicația ta
2. În fila **Distribuție**, fă clic pe **Copiază linkul de partajare**
@@ -60,10 +64,6 @@ Aplicațiile tarball nu sunt listate în marketplace-ul public, astfel încât a
Linkul de partajare folosește URL-ul de bază al serverului (fără niciun subdomeniu de spațiu de lucru), astfel încât funcționează pentru orice spațiu de lucru de pe server.
<Warning>
Partajarea aplicațiilor private este o funcționalitate Enterprise. Mergi la [Setări > Panou de administrare > Enterprise](/settings/admin-panel#enterprise) pentru a o activa.
</Warning>
### Gestionarea versiunilor
Pentru a lansa o actualizare:
@@ -81,7 +81,7 @@ import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
universalIdentifier: '39783023-bcac-41e3-b0d2-ff1944d8465d',
displayName: 'My Twenty App',
description: 'My first Twenty app',
icon: 'IconWorld',
@@ -716,6 +716,13 @@ yarn twenty exec --postInstall
Фронтенд-компоненты — это компоненты React, которые отображаются непосредственно внутри интерфейса Twenty. Они выполняются в изолированном Web Worker с использованием Remote DOM — ваш код изолирован (sandboxed), но рендерится нативно на странице, а не в iframe.
#### Где можно использовать фронт-компоненты
Фронт-компоненты могут отображаться в двух местах внутри Twenty:
* **Боковая панель** — фронт-компоненты с интерфейсом открываются в правой боковой панели. Это поведение по умолчанию, когда фронт-компонент запускается из меню команд.
* **Виджеты (дашборды и страницы записей)** — фронт-компоненты можно встраивать как виджеты в макеты страниц. При настройке дашборда или макета страницы записи пользователи могут добавить виджет фронт-компонента.
#### Простой пример
Самый быстрый способ увидеть фронтенд-компонент в действии — зарегистрировать его как **команду**. Добавление поля `command` с `isPinned: true` делает его кнопкой быстрого действия в правом верхнем углу страницы — макет страницы не требуется:
@@ -773,9 +780,13 @@ export default defineFrontComponent({
Помимо команд, вы можете встроить фронт-компонент непосредственно на страницу записи, добавив его как виджет в **макет страницы**. См. раздел [definePageLayout](#definepagelayout) для подробностей.
#### Headless-компоненты (`isHeadless: true`)
#### Headless и non-headless
Headless-компоненты не отображают видимый UI, но при этом выполняют логику React. Это полезно для **компонентов-эффектов** — компонентов, которые выполняют побочные эффекты при монтировании, например синхронизацию данных, запуск таймера, прослушивание событий или показ уведомления.
Фронт-компоненты поддерживают два режима отображения, управляемых опцией `isHeadless`:
**Non-headless (по умолчанию)** — компонент отображает видимый интерфейс. При запуске из меню команд он открывается в боковой панели. Это поведение по умолчанию, когда `isHeadless` имеет значение `false` или опущен.
**Headless (`isHeadless: true`)** — компонент монтируется невидимо в фоновом режиме. Он не открывает боковую панель. Компоненты headless предназначены для действий, которые выполняют логику и затем размонтируются — например, запуск асинхронной задачи, переход на страницу или показ модального окна подтверждения. Они естественно сочетаются с компонентами SDK Command, описанными ниже.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
@@ -802,6 +813,89 @@ export default defineFrontComponent({
Поскольку компонент возвращает `null`, Twenty пропускает рендеринг контейнера для него — в макете не появляется пустое место. Компонент по-прежнему имеет доступ ко всем хукам и API взаимодействия с хостом.
#### Компоненты SDK Command
Пакет `twenty-sdk` предоставляет четыре вспомогательных компонента Command, предназначенных для headless фронт-компонентов. Каждый компонент выполняет действие при монтировании, обрабатывает ошибки, показывая уведомление snackbar, и автоматически размонтирует фронт-компонент по завершении.
Импортируйте их из `twenty-sdk/command`:
* **`Command`** — запускает асинхронный колбэк через проп `execute`.
* **`CommandLink`** — переходит по пути внутри приложения. Пропы: `to`, `params`, `queryParams`, `options`.
* **`CommandModal`** — открывает модальное окно подтверждения. Если пользователь подтвердит, выполняет колбэк `execute`. Пропы: `title`, `subtitle`, `execute`, `confirmButtonText`, `confirmButtonAccent`.
* **`CommandOpenSidePanelPage`** — открывает конкретную страницу боковой панели. Пропы: `page`, `pageTitle`, `pageIcon`.
Полный пример headless фронт-компонента, использующего `Command` для запуска действия из меню команд:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
command: {
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
},
});
```
А также пример с использованием `CommandModal` для запроса подтверждения перед выполнением:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
const execute = async () => {
// perform the deletion
};
return (
<CommandModal
title="Delete draft?"
subtitle="This action cannot be undone."
execute={execute}
confirmButtonText="Delete"
confirmButtonAccent="danger"
/>
);
};
export default defineFrontComponent({
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
name: 'delete-draft',
description: 'Deletes a draft with confirmation',
component: DeleteDraft,
isHeadless: true,
command: {
universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
label: 'Delete draft',
icon: 'IconTrash',
},
});
```
#### Доступ к контексту времени выполнения
Внутри вашего компонента используйте хуки SDK для доступа к текущему пользователю, записи и экземпляру компонента:
@@ -858,6 +952,50 @@ export default defineFrontComponent({
| `unmountFrontComponent()` | Размонтировать компонент |
| `updateProgress(progress)` | Обновить индикатор прогресса |
Пример, который использует API хоста для показа snackbar и закрытия боковой панели после завершения действия:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
const recordId = useRecordId();
const handleArchive = async () => {
const client = new CoreApiClient();
await client.mutation({
updateTask: {
__args: { id: recordId, data: { status: 'ARCHIVED' } },
id: true,
},
});
await enqueueSnackbar({
message: 'Record archived',
variant: 'success',
});
await closeSidePanel();
};
return (
<div style={{ padding: '20px' }}>
<p>Archive this record?</p>
<button onClick={handleArchive}>Archive</button>
</div>
);
};
export default defineFrontComponent({
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
name: 'archive-record',
description: 'Archives the current record',
component: ArchiveRecord,
});
```
#### Параметры команды
Добавление поля `command` в `defineFrontComponent` регистрирует компонент в меню команд (Cmd+K). Если `isPinned` имеет значение `true`, команда также отображается как кнопка быстрого действия в правом верхнем углу страницы.
@@ -1712,3 +1850,86 @@ yarn twenty uninstall
# Skip the confirmation prompt
yarn twenty uninstall --yes
```
## Управление удалёнными серверами
**Remote** — это сервер Twenty, к которому подключается ваше приложение. Во время настройки скэффолдер автоматически создаст его для вас. Вы можете в любой момент добавлять новые удалённые серверы или переключаться между ними.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Ваши учётные данные хранятся в `~/.twenty/config.json`.
## CI с GitHub Actions
Скэффолдер генерирует готовый к использованию workflow GitHub Actions в `.github/workflows/ci.yml`. Он автоматически запускает ваши интеграционные тесты при каждом пуше в `main` и в pull request'ах.
Рабочий процесс:
1. Извлекает ваш код
2. Поднимает временный сервер Twenty с помощью экшена `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Устанавливает зависимости с помощью `yarn install --immutable`
4. Запускает `yarn test` с `TWENTY_API_URL` и `TWENTY_API_KEY`, переданными из выходных данных экшена
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Вам не нужно настраивать секреты — экшен `spawn-twenty-docker-image` запускает эфемерный сервер Twenty прямо в раннере и выводит данные для подключения. Секрет `GITHUB_TOKEN` предоставляется GitHub автоматически.
Чтобы закрепить конкретную версию Twenty вместо `latest`, измените переменную окружения `TWENTY_VERSION` в начале workflow.
@@ -7,7 +7,9 @@ description: Создайте своё первое приложение Twenty
Приложения сейчас проходят альфа-тестирование. Функция работает, но продолжает развиваться.
</Warning>
Приложения позволяют расширять Twenty с помощью пользовательских объектов, полей, логических функций, навыков ИИ и UI-компонентов — всё это управляется как код.
## Что такое приложения?
Приложения позволяют расширять Twenty с помощью пользовательских объектов, полей, логических функций, фронтенд-компонентов, навыков ИИ и многого другого — всё это управляется как код. Вместо настройки всего через интерфейс вы определяете модель данных и логику на TypeScript и развёртываете их в одном или нескольких рабочих пространствах.
## Требования
@@ -17,7 +19,9 @@ description: Создайте своё первое приложение Twenty
* **Yarn 4** — Поставляется вместе с Node.js через Corepack. Включите его, выполнив `corepack enable`
* **Docker** — [Скачать здесь](https://www.docker.com/products/docker-desktop/). Требуется для запуска локального экземпляра Twenty. Не требуется, если у вас уже запущен сервер Twenty.
## Шаг 1: Сгенерируйте каркас приложения
## Создайте своё первое приложение
### Сгенерируйте каркас приложения
Откройте терминал и выполните:
@@ -29,18 +33,7 @@ npx create-twenty-app@latest my-twenty-app
Будет создана новая папка `my-twenty-app` со всем необходимым.
<Note>
Генератор поддерживает следующие флаги:
* `--minimal` — сгенерировать только основные файлы, без примеров (по умолчанию)
* `--exhaustive` — сгенерировать все примеры сущностей
* `--name <name>` — задать имя приложения (пропускает запрос)
* `--display-name <displayName>` — задать отображаемое имя (пропускает запрос)
* `--description <description>` — задать описание (пропускает запрос)
* `--skip-local-instance` — пропустить запрос на настройку локального сервера
</Note>
## Шаг 2: Настройте локальный экземпляр Twenty
### Настройте локальный экземпляр Twenty
Скэффолдер спросит:
@@ -53,7 +46,7 @@ npx create-twenty-app@latest my-twenty-app
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Запустить локальный экземпляр?" />
</div>
## Шаг 3: Войдите в своё рабочее пространство
### Войдите в своё рабочее пространство
Затем откроется окно браузера со страницей входа в Twenty. Войдите, используя предварительно созданную демонстрационную учётную запись:
@@ -64,7 +57,7 @@ npx create-twenty-app@latest my-twenty-app
<img src="/images/docs/developers/extends/apps/login.png" alt="Экран входа в Twenty" />
</div>
## Шаг 4: Авторизуйте приложение
### Авторизуйте приложение
После входа вы увидите экран авторизации. Это позволит вашему приложению взаимодействовать с вашим рабочим пространством.
@@ -80,7 +73,7 @@ npx create-twenty-app@latest my-twenty-app
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="Каркас приложения успешно создан" />
</div>
## Шаг 5: Начните разработку
### Начните разработку
Перейдите в папку вашего нового приложения и запустите сервер разработки:
@@ -105,7 +98,7 @@ yarn twenty dev --verbose
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Вывод терминала в режиме разработки" />
</div>
## Шаг 6: Посмотрите своё приложение в Twenty
### Посмотрите своё приложение в Twenty
Откройте [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) в браузере. Перейдите в **Settings > Apps** и выберите вкладку **Developer**. Вы должны увидеть своё приложение в разделе **Your Apps**:
@@ -133,13 +126,28 @@ yarn twenty dev --verbose
Готово! Отредактируйте любой файл в `src/`, и изменения будут подхвачены автоматически.
Перейдите к разделу [Создание приложений](/l/ru/developers/extend/apps/building) за подробным руководством по созданию объектов, логических функций, фронтенд-компонентов, навыков и многого другого.
---
## Что вы можете создать
Приложения состоят из **сущностей** — каждая определена как файл TypeScript с одним `export default`:
| Сущность | Что делает |
| ----------------------------- | --------------------------------------------------------------------------------------------------------- |
| **Объекты и поля** | Определяйте пользовательские модели данных (например, Post Card, Invoice) с типизированными полями |
| **Логические функции** | Серверные функции на TypeScript, запускаемые HTTP-маршрутами, расписаниями cron или событиями базы данных |
| **Фронтенд-компоненты** | React-компоненты, которые отображаются внутри интерфейса Twenty (боковая панель, виджеты, командное меню) |
| **Навыки и агенты** | Возможности ИИ — многократно используемые инструкции и автономные помощники |
| **Представления и навигация** | Предварительно настроенные представления списков и элементы бокового меню для ваших объектов |
| **Макеты страниц** | Пользовательские страницы сведений о записи с вкладками и виджетами |
Перейдите к разделу [Создание приложений](/l/ru/developers/extend/apps/building), чтобы получить подробное руководство по каждому типу сущности.
---
## Структура проекта
Скэффолдер генерирует следующую структуру файлов (показано в режиме `--exhaustive`, который включает примеры для каждого типа сущностей):
Инструмент генерации каркаса создаёт следующую структуру файлов:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -148,160 +156,50 @@ my-twenty-app/
.gitignore
.nvmrc
.yarnrc.yml
.yarn/
install-state.gz
.oxlintrc.json
tsconfig.json
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
LLMS.md
README.md
.github/
└── workflows/
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
src/
├── application-config.ts # Required — main application configuration
├── __tests__/
├── setup-test.ts # Test setup (server health check, config)
│ └── app-install.integration-test.ts # Example integration test
── roles/
── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── create-hello-world-company.ts # Example logic function using CoreApiClient
│ ├── pre-install.ts # Runs before installation
│ └── post-install.ts # Runs after installation
├── front-components/
│ └── hello-world.tsx # Example front component
├── page-layouts/
│ └── example-record-page-layout.ts # Example page layout with front component
├── views/
│ └── example-view.ts # Example saved view definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
├── skills/
│ └── example-skill.ts # Example AI agent skill definition
└── agents/
└── example-agent.ts # Example AI agent definition
├── application-config.ts # Required — main application configuration
├── default-role.ts # Default role for logic functions
├── constants/
│ └── universal-identifiers.ts # Auto-generated UUIDs and app metadata
── __tests__/
── setup-test.ts # Test setup (server health check, config)
└── app-install.integration-test.ts # Integration test
```
По умолчанию (`--minimal`) создаются только основные файлы: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` и `logic-functions/post-install.ts`. Используйте `--exhaustive`, чтобы включить все показанные выше файлы-примеры.
### Начните с примера
Чтобы начать с более полного примера с пользовательскими объектами, полями, логическими функциями, фронтенд-компонентами и многим другим, используйте флаг `--example`:
```bash filename="Terminal"
npx create-twenty-app@latest my-twenty-app --example postcard
```
Примеры берутся из каталога [twenty-apps/examples](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples) на GitHub. Вы также можете сгенерировать каркас отдельных сущностей в существующем проекте с помощью `yarn twenty add` (см. [Создание приложений](/l/ru/developers/extend/apps/building#scaffolding-entities-with-yarn-twenty-add)).
### Ключевые файлы
| Файл / Папка | Назначение |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Содержит имя, версию и зависимости вашего приложения. Содержит скрипт `twenty`, чтобы вы могли выполнить `yarn twenty help` и увидеть все команды. |
| `src/application-config.ts` | **Обязательно.** Основной файл конфигурации для вашего приложения. |
| `src/roles/` | Определяет роли, которые контролируют доступ логических функций. |
| `src/logic-functions/` | Серверные функции, запускаемые маршрутами, расписаниями cron или событиями базы данных. |
| `src/front-components/` | Компоненты React, которые отображаются внутри интерфейса Twenty. |
| `src/objects/` | Пользовательские определения объектов для расширения вашей модели данных. |
| `src/fields/` | Пользовательские поля, добавляемые к существующим объектам. |
| `src/views/` | Конфигурации сохранённых представлений. |
| `src/navigation-menu-items/` | Пользовательские ссылки в боковой навигации. |
| `src/skills/` | Навыки, расширяющие возможности ИИ-агентов Twenty. |
| `src/agents/` | ИИ-агенты с пользовательскими промптами. |
| `src/page-layouts/` | Пользовательские макеты страниц для представлений записей. |
| `src/__tests__/` | Интеграционные тесты (настройка + пример теста). |
| `public/` | Статические ресурсы (изображения, шрифты), обслуживаемые вместе с вашим приложением. |
| Файл / Папка | Назначение |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Содержит имя, версию и зависимости вашего приложения. Содержит скрипт `twenty`, чтобы вы могли выполнить `yarn twenty help` и увидеть все команды. |
| `src/application-config.ts` | **Обязательно.** Основной файл конфигурации для вашего приложения. |
| `src/default-role.ts` | Роль по умолчанию, которая контролирует, к чему имеют доступ ваши логические функции. |
| `src/constants/universal-identifiers.ts` | Автоматически генерируемые UUID и метаданные приложения (отображаемое имя, описание). |
| `src/__tests__/` | Интеграционные тесты (настройка + пример теста). |
| `public/` | Статические ресурсы (изображения, шрифты), обслуживаемые вместе с вашим приложением. |
## Управление удалёнными серверами
## Локальный сервер разработки
Remote — это сервер Twenty, к которому подключается ваше приложение. Во время настройки скэффолдер автоматически создаст его для вас. Вы можете в любой момент добавлять новые remotes или переключаться между ними.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Ваши учётные данные хранятся в `~/.twenty/config.json`.
## Локальный сервер разработки (`yarn twenty server`)
CLI может управлять локальным сервером Twenty, запущенным в Docker. Это тот же сервер, который автоматически запускается при создании каркаса приложения с помощью `create-twenty-app`, но им можно управлять и вручную.
### Запуск сервера
```bash filename="Terminal"
yarn twenty server start
```
Эта команда скачивает Docker-образ `twentycrm/twenty-app-dev:latest` (если его ещё нет), создаёт контейнер с именем `twenty-app-dev` и запускает его на порту **2020**. CLI ждёт, пока сервер пройдёт проверку работоспособности, прежде чем вернуть управление.
Создаются два тома Docker для сохранения данных между перезапусками:
* `twenty-app-dev-data` — база данных PostgreSQL
* `twenty-app-dev-storage` — файловое хранилище
Если порт 2020 уже используется, вы можете запустить на другом порту:
```bash filename="Terminal"
yarn twenty server start --port 3030
```
CLI автоматически настраивает внутренние `NODE_PORT` и `SERVER_URL` контейнера в соответствии с выбранным портом, чтобы логические функции, OAuth и прочие внутренние сетевые взаимодействия работали корректно.
После запуска сервер автоматически регистрируется как remote `local` в конфигурации вашего CLI.
### Проверка состояния сервера
```bash filename="Terminal"
yarn twenty server status
```
Показывает, запущен ли сервер, его URL и учётные данные по умолчанию (`[email protected]` / `[email protected]`).
### Просмотр журналов сервера
```bash filename="Terminal"
yarn twenty server logs
```
Выводит журналы контейнера в потоковом режиме. Используйте `--lines`, чтобы задать, сколько последних строк показывать:
```bash filename="Terminal"
yarn twenty server logs --lines 100
```
### Остановка сервера
```bash filename="Terminal"
yarn twenty server stop
```
Останавливает контейнер. Ваши данные сохраняются в томах Docker — следующий `start` продолжит с того места, где вы остановились.
### Сброс сервера
```bash filename="Terminal"
yarn twenty server reset
```
Удаляет контейнер и оба тома Docker, полностью стирая все данные. Следующий `start` создаст новый чистый экземпляр.
<Note>
Для работы сервера необходимо, чтобы **Docker** был запущен. Если вы видите ошибку "Docker not running", убедитесь, что запущен Docker Desktop (или демон Docker).
</Note>
### Справочник команд
Генератор каркаса уже запустил для вас локальный сервер Twenty. Чтобы управлять им позже, используйте `yarn twenty server`:
| Команда | Описание |
| -------------------------------------- | -------------------------------------------------------------- |
@@ -313,65 +211,11 @@ yarn twenty server reset
| `yarn twenty server logs --lines 100` | Показать последние 100 строк журнала |
| `yarn twenty server reset` | Удалить все данные и начать с чистого листа |
## CI с GitHub Actions
Данные сохраняются между перезапусками в двух томах Docker (`twenty-app-dev-data` для PostgreSQL, `twenty-app-dev-storage` для файлов). Используйте `reset`, чтобы стереть всё и начать заново.
Скэффолдер генерирует готовый к использованию workflow GitHub Actions в `.github/workflows/ci.yml`. Он автоматически запускает ваши интеграционные тесты при каждом пуше в `main` и в pull request'ах.
Рабочий процесс:
1. Извлекает ваш код
2. Поднимает временный сервер Twenty с помощью экшена `twentyhq/twenty/.github/actions/spawn-twenty-docker-image`
3. Устанавливает зависимости с помощью `yarn install --immutable`
4. Запускает `yarn test` с `TWENTY_API_URL` и `TWENTY_API_KEY`, переданными из выходных данных экшена
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Вам не нужно настраивать секреты — экшен `spawn-twenty-docker-image` запускает эфемерный сервер Twenty прямо в раннере и выводит данные для подключения. Секрет `GITHUB_TOKEN` предоставляется GitHub автоматически.
Чтобы закрепить конкретную версию Twenty вместо `latest`, измените переменную окружения `TWENTY_VERSION` в начале workflow.
<Note>
Для работы сервера необходимо, чтобы **Docker** был запущен. Если вы видите ошибку "Docker not running", убедитесь, что запущен Docker Desktop (или демон Docker).
</Note>
## Ручная настройка (без генератора)
@@ -52,7 +52,11 @@ yarn twenty deploy
### Общий доступ к развернутому приложению
Приложения в формате tarball не отображаются в публичном маркетплейсе, поэтому другие рабочие пространства на том же сервере не найдут их при просмотре. Чтобы поделиться развернутым приложением:
<Warning>
Sharing private (tarball) apps across workspaces is an **Enterprise** feature. The **Distribution** tab will show an upgrade prompt instead of the share controls until your workspace has a valid Enterprise key. See [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to activate it.
</Warning>
Приложения в формате tarball не отображаются в публичном маркетплейсе, поэтому другие рабочие пространства на том же сервере не найдут их при просмотре. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. Перейдите в **Настройки > Приложения > Регистрации** и откройте ваше приложение
2. На вкладке **Распространение** нажмите **Копировать ссылку для общего доступа**
@@ -60,10 +64,6 @@ yarn twenty deploy
Ссылка общего доступа использует базовый URL сервера (без какого-либо поддомена рабочего пространства), поэтому она работает для любого рабочего пространства на сервере.
<Warning>
Возможность делиться частными приложениями — функция Enterprise. Перейдите в [Настройки > Панель администратора > Enterprise](/settings/admin-panel#enterprise), чтобы включить её.
</Warning>
### Управление версиями
Чтобы выпустить обновление:
@@ -81,7 +81,7 @@ import { defineApplication } from 'twenty-sdk';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
universalIdentifier: '39783023-bcac-41e3-b0d2-ff1944d8465d',
displayName: 'My Twenty App',
description: 'My first Twenty app',
icon: 'IconWorld',
@@ -717,6 +717,13 @@ yarn twenty exec --postInstall
Ön uç bileşenler, Twenty'nin UI'si içinde doğrudan görüntülenen React bileşenleridir. Remote DOM kullanan izole bir Web Worker içinde çalışırlar — kodunuz izole bir ortamda (sandbox) çalışır ancak bir iframe içinde değil, sayfada yerel olarak işlenir.
#### Ön bileşenlerin kullanılabileceği yerler
Ön bileşenler, Twenty içinde iki konumda işlenebilir:
* **Yan panel** — Headless olmayan ön bileşenler, sağ taraftaki yan panelde açılır. Bir ön bileşen komut menüsünden tetiklendiğinde varsayılan davranış budur.
* **Widget'lar (panolar ve kayıt sayfaları)** — Ön bileşenler, sayfa düzenlerine widget olarak gömülebilir. Bir pano veya kayıt sayfası düzeni yapılandırılırken kullanıcılar bir ön bileşen widget'ı ekleyebilir.
#### Basit örnek
Bir ön uç bileşenini çalışırken görmenin en hızlı yolu, onu bir komut olarak kaydetmektir. `isPinned: true` ile bir `command` alanı eklemek, sayfanın sağ üst köşesinde hızlı işlem düğmesi olarak görünmesini sağlar — herhangi bir sayfa düzenine gerek yoktur:
@@ -774,9 +781,13 @@ Bileşeni satır içi işlemek için üzerine tıklayın.
Komutların ötesinde, bir ön uç bileşenini bir **sayfa düzeninde** widget olarak ekleyerek doğrudan bir kayıt sayfasına gömebilirsiniz. Ayrıntılar için [definePageLayout](#definepagelayout) bölümüne bakın.
#### Headless bileşenler (`isHeadless: true`)
#### Headless ve headless olmayan
Headless bileşenler görünür bir kullanıcı arayüzü oluşturmaz ancak yine de React mantığını çalıştırır. Bu, **etki bileşenleri** için kullanışlıdır — bağlandıklarında veri senkronizasyonu yapmak, bir zamanlayıcı başlatmak, olayları dinlemek veya bir bildirimi tetiklemek gibi yan etkiler gerçekleştiren bileşenler.
Ön bileşenler, `isHeadless` seçeneğiyle kontrol edilen iki işleme kipiyle gelir:
**Headless olmayan (varsayılan)** — Bileşen görünür bir kullanıcı arayüzü (UI) oluşturur. Komut menüsünden tetiklendiğinde yan panelde açılır. `isHeadless` `false` olduğunda veya belirtilmediğinde bu varsayılan davranıştır.
**Headless (`isHeadless: true`)** — Bileşen arka planda görünmez şekilde bağlanır. Yan paneli açmaz. Headless bileşenler, mantığı çalıştırıp ardından kendilerini kaldıran eylemler için tasarlanmıştır — örneğin, bir async görevi çalıştırma, bir sayfaya gitme veya bir onay modalı gösterme. Aşağıda açıklanan SDK Command bileşenleriyle doğal olarak eşleşirler.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
@@ -803,6 +814,89 @@ export default defineFrontComponent({
Bileşen `null` döndürdüğü için, Twenty bunun için bir kapsayıcı oluşturmayı atlar — düzende boş alan görünmez. Bileşen yine de tüm hook'lara ve host iletişim API'sine erişime sahiptir.
#### SDK Command bileşenleri
`twenty-sdk` paketi, headless ön bileşenler için tasarlanmış dört Command yardımcı bileşeni sağlar. Her bileşen bağlandığında bir eylem yürütür, hataları bir snackbar bildirimi göstererek ele alır ve tamamlandığında ön bileşeni otomatik olarak kaldırır.
Bunları `twenty-sdk/command` içinden içe aktarın:
* **`Command`** — `execute` prop'u aracılığıyla async bir geri çağrıyı çalıştırır.
* **`CommandLink`** — Bir uygulama yoluna gider. Props: `to`, `params`, `queryParams`, `options`.
* **`CommandModal`** — Bir onay modalı açar. Kullanıcı onaylarsa `execute` geri çağrısını yürütür. Props: `title`, `subtitle`, `execute`, `confirmButtonText`, `confirmButtonAccent`.
* **`CommandOpenSidePanelPage`** — Belirli bir yan panel sayfasını açar. Props: `page`, `pageTitle`, `pageIcon`.
`Command` kullanarak komut menüsünden bir eylem çalıştıran headless bir ön bileşenin tam örneği:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
command: {
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
},
});
```
Ve yürütmeden önce onay istemek için `CommandModal` kullanan bir örnek:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
const execute = async () => {
// perform the deletion
};
return (
<CommandModal
title="Delete draft?"
subtitle="This action cannot be undone."
execute={execute}
confirmButtonText="Delete"
confirmButtonAccent="danger"
/>
);
};
export default defineFrontComponent({
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
name: 'delete-draft',
description: 'Deletes a draft with confirmation',
component: DeleteDraft,
isHeadless: true,
command: {
universalIdentifier: 'b8c9d0e1-f2a3-4567-bcde-678901234567',
label: 'Delete draft',
icon: 'IconTrash',
},
});
```
#### Çalışma zamanı bağlamına erişme
Bileşeninizin içinde, geçerli kullanıcıya, kayda ve bileşen örneğine erişmek için SDK hook'larını kullanın:
@@ -859,6 +953,50 @@ Kullanılabilir hook'lar:
| `unmountFrontComponent()` | Bileşeni kaldır (unmount) |
| `updateProgress(progress)` | Bir ilerleme göstergesini güncelle |
Bir eylem tamamlandıktan sonra bir snackbar göstermek ve yan paneli kapatmak için host API'sini kullanan bir örnek:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
const recordId = useRecordId();
const handleArchive = async () => {
const client = new CoreApiClient();
await client.mutation({
updateTask: {
__args: { id: recordId, data: { status: 'ARCHIVED' } },
id: true,
},
});
await enqueueSnackbar({
message: 'Record archived',
variant: 'success',
});
await closeSidePanel();
};
return (
<div style={{ padding: '20px' }}>
<p>Archive this record?</p>
<button onClick={handleArchive}>Archive</button>
</div>
);
};
export default defineFrontComponent({
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
name: 'archive-record',
description: 'Archives the current record',
component: ArchiveRecord,
});
```
#### Komut seçenekleri
`defineFrontComponent` içine bir `command` alanı eklemek, bileşeni komut menüsüne (Cmd+K) kaydeder. `isPinned` `true` ise, sayfanın sağ üst köşesinde bir hızlı işlem düğmesi olarak da görünür.
@@ -1713,3 +1851,86 @@ yarn twenty uninstall
# Skip the confirmation prompt
yarn twenty uninstall --yes
```
## Uzakları yönetme
Bir **uzak**, uygulamanızın bağlandığı Twenty sunucusudur. Kurulum sırasında iskelet oluşturucu sizin için otomatik olarak bir tane oluşturur. Dilediğiniz zaman daha fazla uzak ekleyebilir veya aralarında geçiş yapabilirsiniz.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Kimlik bilgileriniz `~/.twenty/config.json` içinde saklanır.
## GitHub Actions ile CI
İskelet oluşturucu, `.github/workflows/ci.yml` konumunda kullanıma hazır bir GitHub Actions iş akışı üretir. Entegrasyon testlerinizi `main` dalına yapılan her itmede ve çekme isteklerinde otomatik olarak çalıştırır.
İş akışı:
1. Kodunuzu çalışma alanına alır
2. `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` eylemini kullanarak geçici bir Twenty sunucusu başlatır
3. `yarn install --immutable` ile bağımlılıkları kurar
4. Eylem çıktılarından enjekte edilen `TWENTY_API_URL` ve `TWENTY_API_KEY` ile `yarn test` çalıştırır
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Herhangi bir gizli değişken yapılandırmanız gerekmez — `spawn-twenty-docker-image` eylemi, koşucu içinde doğrudan geçici bir Twenty sunucusu başlatır ve bağlantı ayrıntılarını çıktı olarak verir. `GITHUB_TOKEN` gizli değişkeni GitHub tarafından otomatik olarak sağlanır.
`latest` yerine belirli bir Twenty sürümünü sabitlemek için iş akışının başındaki `TWENTY_VERSION` ortam değişkenini değiştirin.
@@ -7,7 +7,9 @@ description: İlk Twenty uygulamanızı dakikalar içinde oluşturun.
Uygulamalar şu anda alfa aşamasında. Özellik işlevsel ancak hâlâ gelişmekte.
</Warning>
Uygulamalar, Twenty'yi özel nesneler, alanlar, mantık işlevleri, Yapay Zeka yetenekleri ve UI bileşenleriyle genişletmenizi sağlar — tümü kod olarak yönetilir.
## Uygulamalar nedir?
Uygulamalar, Twenty'yi özel nesneler, alanlar, mantıksal işlevler, ön uç bileşenleri, yapay zekâ yetenekleri ve daha fazlasıyla genişletmenizi sağlar — tümü kod olarak yönetilir. Her şeyi UI üzerinden yapılandırmak yerine, veri modelinizi ve mantığınızı TypeScript'te tanımlar ve bunu bir veya daha fazla çalışma alanına dağıtırsınız.
## Ön Gereksinimler
@@ -17,7 +19,9 @@ Başlamadan önce, makinenizde aşağıdakilerin kurulu olduğundan emin olun:
* **Yarn 4** — Corepack aracılığıyla Node.js ile birlikte gelir. `corepack enable` komutunu çalıştırarak etkinleştirin
* **Docker** — [Buradan indirin](https://www.docker.com/products/docker-desktop/). Yerel bir Twenty örneğini çalıştırmak için gereklidir. Zaten çalışan bir Twenty sunucunuz varsa gerekmez.
## Adım 1: Uygulamanızın iskeletini oluşturun
## İlk uygulamanızı oluşturun
### Uygulamanızın iskeletini oluşturun
Bir terminal açın ve şunu çalıştırın:
@@ -29,18 +33,7 @@ Uygulamanız için bir ad ve açıklama girmeniz istenecektir. Varsayılanları
Bu, `my-twenty-app` adlı, ihtiyacınız olan her şeyi içeren yeni bir klasör oluşturur.
<Note>
İskelet oluşturucu şu bayrakları destekler:
* `--minimal` — yalnızca temel dosyaların iskeletini oluşturur, örnek yok (varsayılan)
* `--exhaustive` — tüm örnek varlıkların iskeletini oluşturur
* `--name <name>` — uygulama adını ayarlar (istemi atlar)
* `--display-name <displayName>` — görünen adı ayarlar (istemi atlar)
* `--description <description>` — açıklamayı ayarlar (istemi atlar)
* `--skip-local-instance` — yerel sunucu kurulum istemini atlar
</Note>
## Adım 2: Yerel bir Twenty örneği kurun
### Yerel bir Twenty örneği kurun
İskelet oluşturucu şunu soracaktır:
@@ -53,7 +46,7 @@ Bu, `my-twenty-app` adlı, ihtiyacınız olan her şeyi içeren yeni bir klasör
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Yerel örnek başlatılsın mı?" />
</div>
## Adım 3: Çalışma alanınıza giriş yapın
### Çalışma alanınıza giriş yapın
Ardından, Twenty oturum açma sayfasıyla bir tarayıcı penceresi açılacaktır. Önceden eklenmiş demo hesabıyla oturum açın:
@@ -64,7 +57,7 @@ Ardından, Twenty oturum açma sayfasıyla bir tarayıcı penceresi açılacakt
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty oturum açma ekranı" />
</div>
## Adım 4: Uygulamayı yetkilendirin
### Uygulamayı yetkilendirin
Oturum açtıktan sonra bir yetkilendirme ekranı göreceksiniz. Bu, uygulamanızın çalışma alanınızla etkileşim kurmasını sağlar.
@@ -80,7 +73,7 @@ Yetkilendirildikten sonra terminaliniz her şeyin kurulduğunu onaylayacaktır.
<img src="/images/docs/developers/extends/apps/scaffolded.png" alt="Uygulama iskeleti başarıyla oluşturuldu" />
</div>
## Adım 5: Geliştirmeye başlayın
### Geliştirmeye başlayın
Yeni uygulama klasörünüze gidin ve geliştirme sunucusunu başlatın:
@@ -105,7 +98,7 @@ Geliştirme modu yalnızca geliştirme ortamında (`NODE_ENV=development`) çal
<img src="/images/docs/developers/extends/apps/dev.jpg" alt="Geliştirme modu terminal çıktısı" />
</div>
## Adım 6: Uygulamanızı Twenty'de görün
### Uygulamanızı Twenty'de görün
Tarayıcınızda [http://localhost:2020/settings/applications#developer](http://localhost:2020/settings/applications#developer) adresini açın. **Settings > Apps** bölümüne gidin ve **Developer** sekmesini seçin. **Your Apps** altında uygulamanızın listelendiğini görmelisiniz:
@@ -133,13 +126,28 @@ Uygulamanızın sağladığı her şeyi — nesneler, alanlar, mantık işlevler
Her şey hazır! `src/` içindeki herhangi bir dosyayı düzenleyin; değişiklikler otomatik olarak alınacaktır.
Nesneler, mantık işlevleri, ön bileşenler, beceriler ve daha fazlasını oluşturma hakkında ayrıntılı bir kılavuz için [Uygulama Oluşturma](/l/tr/developers/extend/apps/building) bölümüne göz atın.
---
## Oluşturabilecekleriniz
Uygulamalar **varlıklardan** oluşur — her biri tek bir `export default` içeren bir TypeScript dosyası olarak tanımlanır:
| Varlık | Ne yapar |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| **Nesneler ve Alanlar** | Tipli alanlarla özel veri modelleri (ör. Post Card, Invoice) tanımlayın |
| **Mantıksal işlevler** | HTTP rotaları, cron zamanlamaları veya veritabanı olayları tarafından tetiklenen sunucu tarafı TypeScript işlevleri |
| **Ön uç bileşenleri** | Twenty'nin arayüzünde görüntülenen React bileşenleri (yan panel, widget'lar, komut menüsü) |
| **Beceriler ve Aracılar** | Yapay zeka yetenekleri — yeniden kullanılabilir yönergeler ve otonom asistanlar |
| **Görünümler ve Gezinme** | Nesneleriniz için önceden yapılandırılmış liste görünümleri ve kenar çubuğu menü öğeleri |
| **Sayfa düzenleri** | Sekmeler ve widget'lar içeren özel kayıt ayrıntı sayfaları |
Her varlık türü hakkında ayrıntılı bir kılavuz için [Uygulama Oluşturma](/l/tr/developers/extend/apps/building) bölümüne göz atın.
---
## Proje yapısı
İskelet oluşturucu aşağıdaki dosya yapısını üretir (`--exhaustive` modunda gösterilmiştir; her varlık türü için örnekler içerir):
İskelet oluşturucu aşağıdaki dosya yapısını oluşturur:
```text filename="my-twenty-app/"
my-twenty-app/
@@ -148,160 +156,50 @@ my-twenty-app/
.gitignore
.nvmrc
.yarnrc.yml
.yarn/
install-state.gz
.oxlintrc.json
tsconfig.json
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
tsconfig.spec.json # TypeScript config for tests
vitest.config.ts # Vitest test runner configuration
LLMS.md
README.md
.github/
└── workflows/
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
└── ci.yml # GitHub Actions CI workflow
public/ # Public assets (images, fonts, etc.)
src/
├── application-config.ts # Required — main application configuration
├── __tests__/
├── setup-test.ts # Test setup (server health check, config)
│ └── app-install.integration-test.ts # Example integration test
── roles/
── default-role.ts # Default role for logic functions
├── objects/
│ └── example-object.ts # Example custom object definition
├── fields/
│ └── example-field.ts # Example standalone field definition
├── logic-functions/
│ ├── hello-world.ts # Example logic function
│ ├── create-hello-world-company.ts # Example logic function using CoreApiClient
│ ├── pre-install.ts # Runs before installation
│ └── post-install.ts # Runs after installation
├── front-components/
│ └── hello-world.tsx # Example front component
├── page-layouts/
│ └── example-record-page-layout.ts # Example page layout with front component
├── views/
│ └── example-view.ts # Example saved view definition
├── navigation-menu-items/
│ └── example-navigation-menu-item.ts # Example sidebar navigation link
├── skills/
│ └── example-skill.ts # Example AI agent skill definition
└── agents/
└── example-agent.ts # Example AI agent definition
├── application-config.ts # Required — main application configuration
├── default-role.ts # Default role for logic functions
├── constants/
│ └── universal-identifiers.ts # Auto-generated UUIDs and app metadata
── __tests__/
── setup-test.ts # Test setup (server health check, config)
└── app-install.integration-test.ts # Integration test
```
Varsayılan olarak (`--minimal`), yalnızca çekirdek dosyalar oluşturulur: `application-config.ts`, `roles/default-role.ts`, `logic-functions/pre-install.ts` ve `logic-functions/post-install.ts`. Yukarıda gösterilen tüm örnek dosyaları dahil etmek için `--exhaustive` kullanın.
### Bir örnekten başlayın
Özel nesneler, alanlar, mantık işlevleri, ön uç bileşenleri ve daha fazlasını içeren daha kapsamlı bir örnekten başlamak için `--example` bayrağını kullanın:
```bash filename="Terminal"
npx create-twenty-app@latest my-twenty-app --example postcard
```
Örnekler GitHub'daki [twenty-apps/examples](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/examples) dizininden alınır. Ayrıca `yarn twenty add` ile mevcut bir projeye tek tek varlıklar için iskelet oluşturabilirsiniz (bkz. [Uygulama Oluşturma](/l/tr/developers/extend/apps/building#scaffolding-entities-with-yarn-twenty-add)).
### Temel dosyalar
| Dosya / Klasör | Amaç |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Uygulamanızın adını, sürümünü ve bağımlılıklarını bildirir. Tüm komutları görmek için `yarn twenty help` çalıştırabilmeniz amacıyla bir `twenty` betiği içerir. |
| `src/application-config.ts` | **Gerekli.** Uygulamanızın ana yapılandırma dosyası. |
| `src/roles/` | Mantık işlevlerinizin neye erişebileceğini kontrol eden rolleri tanımlar. |
| `src/logic-functions/` | Rotalar, cron zamanlamaları veya veritabanı olayları tarafından tetiklenen sunucu tarafı işlevler. |
| `src/front-components/` | Twenty'nin UI'si içinde görüntülenen React bileşenleri. |
| `src/objects/` | Veri modelinizi genişletmek için özel nesne tanımları. |
| `src/fields/` | Mevcut nesnelere eklenen özel alanlar. |
| `src/views/` | Kaydedilmiş görünüm yapılandırmaları. |
| `src/navigation-menu-items/` | Kenar çubuğu gezintisinde özel bağlantılar. |
| `src/skills/` | Twenty'nin yapay zeka ajanlarının yeteneklerini genişleten beceriler. |
| `src/agents/` | Özel istemlere sahip yapay zekâ ajanları. |
| `src/page-layouts/` | Kayıt görünümleri için özel sayfa düzenleri. |
| `src/__tests__/` | Entegrasyon testleri (kurulum + örnek test). |
| `public/` | Uygulamanızla birlikte sunulan statik varlıklar (görüntüler, yazı tipleri). |
| Dosya / Klasör | Amaç |
| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `package.json` | Uygulamanızın adını, sürümünü ve bağımlılıklarını bildirir. Tüm komutları görmek için `yarn twenty help` çalıştırabilmeniz amacıyla bir `twenty` betiği içerir. |
| `src/application-config.ts` | **Gerekli.** Uygulamanızın ana yapılandırma dosyası. |
| `src/default-role.ts` | Mantık işlevlerinizin neye erişebileceğini denetleyen varsayılan rol. |
| `src/constants/universal-identifiers.ts` | Otomatik oluşturulan UUID'ler ve uygulama meta verileri (görünen ad, açıklama). |
| `src/__tests__/` | Entegrasyon testleri (kurulum + örnek test). |
| `public/` | Uygulamanızla birlikte sunulan statik varlıklar (görüntüler, yazı tipleri). |
## Uzakları yönetme
## Yerel geliştirme sunucusu
Bir **uzak**, uygulamanızın bağlandığı Twenty sunucusudur. Kurulum sırasında iskelet oluşturucu sizin için otomatik olarak bir tane oluşturur. Dilediğiniz zaman daha fazla uzak ekleyebilir veya aralarında geçiş yapabilirsiniz.
```bash filename="Terminal"
# Add a new remote (opens a browser for OAuth login)
yarn twenty remote add
# Connect to a local Twenty server (auto-detects port 2020 or 3000)
yarn twenty remote add --local
# Add a remote non-interactively (useful for CI)
yarn twenty remote add --api-url https://your-twenty-server.com --api-key $TWENTY_API_KEY --as my-remote
# List all configured remotes
yarn twenty remote list
# Switch the active remote
yarn twenty remote switch <name>
```
Kimlik bilgileriniz `~/.twenty/config.json` içinde saklanır.
## Yerel geliştirme sunucusu (`yarn twenty server`)
CLI, Docker'da çalışan yerel bir Twenty sunucusunu yönetebilir. Bu, `create-twenty-app` ile bir uygulamanın iskeletini oluşturduğunuzda otomatik olarak başlatılan sunucunun aynısıdır; ancak bunu el ile de yönetebilirsiniz.
### Sunucuyu Başlatma
```bash filename="Terminal"
yarn twenty server start
```
Bu, `twentycrm/twenty-app-dev:latest` Docker imajını (zaten mevcut değilse) çeker, `twenty-app-dev` adlı bir konteyner oluşturur ve **2020** portunda başlatır. CLI, dönmeden önce sunucunun sağlık kontrolünü geçmesini bekler.
Yeniden başlatmalar arasında verileri kalıcı kılmak için iki Docker birimi oluşturulur:
* `twenty-app-dev-data` — PostgreSQL veritabanı
* `twenty-app-dev-storage` — dosya depolama
2020 portu zaten kullanımda ise farklı bir portta başlatabilirsiniz:
```bash filename="Terminal"
yarn twenty server start --port 3030
```
CLI, seçilen porta uyacak şekilde konteynerin dahili `NODE_PORT` ve `SERVER_URL` ayarlarını otomatik olarak yapılandırır; böylece mantık işlevleri, OAuth ve diğer tüm dahili ağ işlemleri doğru şekilde çalışır.
Başlatıldığında, sunucu CLI yapılandırmanızda `local` uzak olarak otomatik olarak kaydedilir.
### Sunucu durumunu kontrol etme
```bash filename="Terminal"
yarn twenty server status
```
Sunucunun çalışıp çalışmadığını, URL'sini ve varsayılan oturum açma kimlik bilgilerini (`[email protected]` / `[email protected]`) gösterir.
### Sunucu günlüklerini görüntüleme
```bash filename="Terminal"
yarn twenty server logs
```
Konteyner günlüklerini akış olarak iletir. Kaç satırın gösterileceğini denetlemek için `--lines` kullanın:
```bash filename="Terminal"
yarn twenty server logs --lines 100
```
### Sunucuyu durdurma
```bash filename="Terminal"
yarn twenty server stop
```
Konteyneri durdurur. Verileriniz Docker birimlerinde korunur — bir sonraki `start`, kaldığınız yerden devam eder.
### Sunucuyu sıfırlama
```bash filename="Terminal"
yarn twenty server reset
```
Konteyneri kaldırır ve her iki Docker birimini de silerek tüm verileri temizler. Sonraki `start`, yeni bir örnek oluşturur.
<Note>
Sunucunun çalışması için **Docker**'ın çalışıyor olması gerekir. "Docker not running" hatası görürseniz Docker Desktop'ın (veya Docker daemon'ının) başlatıldığından emin olun.
</Note>
### Komut başvurusu
İskelet oluşturucu sizin için zaten yerel bir Twenty sunucusu başlattı. Daha sonra yönetmek için `yarn twenty server` komutunu kullanın:
| Komut | Açıklama |
| -------------------------------------- | ------------------------------------------------------ |
@@ -313,65 +211,11 @@ Konteyneri kaldırır ve her iki Docker birimini de silerek tüm verileri temizl
| `yarn twenty server logs --lines 100` | Son 100 günlük satırını gösterir |
| `yarn twenty server reset` | Tüm verileri siler ve sıfırdan başlatır |
## GitHub Actions ile CI
Veriler, yeniden başlatmalar arasında iki Docker biriminde kalıcıdır (PostgreSQL için `twenty-app-dev-data`, dosyalar için `twenty-app-dev-storage`). Her şeyi silip baştan başlamak için `reset` kullanın.
İskelet oluşturucu, `.github/workflows/ci.yml` konumunda kullanıma hazır bir GitHub Actions iş akışı üretir. Entegrasyon testlerinizi `main` dalına yapılan her itmede ve çekme isteklerinde otomatik olarak çalıştırır.
İş akışı:
1. Kodunuzu depodan çıkarır
2. `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` eylemini kullanarak geçici bir Twenty sunucusu başlatır
3. `yarn install --immutable` ile bağımlılıkları kurar
4. Eylem çıktılarından enjekte edilen `TWENTY_API_URL` ve `TWENTY_API_KEY` ile `yarn test` çalıştırır
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Herhangi bir gizli değişken yapılandırmanız gerekmez — `spawn-twenty-docker-image` eylemi, koşucu içinde doğrudan geçici bir Twenty sunucusu başlatır ve bağlantı ayrıntılarını çıktı olarak verir. `GITHUB_TOKEN` gizli değişkeni GitHub tarafından otomatik olarak sağlanır.
`latest` yerine belirli bir Twenty sürümünü sabitlemek için iş akışının başındaki `TWENTY_VERSION` ortam değişkenini değiştirin.
<Note>
Sunucunun çalışması için **Docker**'ın çalışıyor olması gerekir. "Docker not running" hatası görürseniz Docker Desktop'ın (veya Docker daemon'ının) başlatıldığından emin olun.
</Note>
## Manuel kurulum (iskelet oluşturucu olmadan)
@@ -52,7 +52,11 @@ yarn twenty deploy
### Dağıtılmış bir uygulamayı paylaşma
Tarball uygulamaları genel pazar yerinde listelenmez; bu nedenle aynı sunucudaki diğer çalışma alanları gezinerek onları keşfedemez. Dağıtılmış bir uygulamayı paylaşmak için:
<Warning>
Sharing private (tarball) apps across workspaces is an **Enterprise** feature. The **Distribution** tab will show an upgrade prompt instead of the share controls until your workspace has a valid Enterprise key. See [Settings > Admin Panel > Enterprise](/settings/admin-panel#enterprise) to activate it.
</Warning>
Tarball uygulamaları genel pazar yerinde listelenmez; bu nedenle aynı sunucudaki diğer çalışma alanları gezinerek onları keşfedemez. Once your workspace is on the Enterprise plan, you can share a deployed app like this:
1. **Ayarlar > Uygulamalar > Kayıtlar** bölümüne gidin ve uygulamanızı açın
2. **Dağıtım** sekmesinde, **Paylaşım bağlantısını kopyala**ya tıklayın
@@ -60,10 +64,6 @@ Tarball uygulamaları genel pazar yerinde listelenmez; bu nedenle aynı sunucuda
Paylaşım bağlantısı, sunucunun temel URLsini (herhangi bir çalışma alanı alt alan adı olmadan) kullanır; böylece sunucudaki herhangi bir çalışma alanı için çalışır.
<Warning>
Özel uygulamaları paylaşma bir Kurumsal özelliktir. [Ayarlar > Yönetim Paneli > Kurumsal](/settings/admin-panel#enterprise) bölümüne giderek etkinleştirin.
</Warning>
### Sürüm yönetimi
Bir güncelleme yayımlamak için:
+2
View File
@@ -21,6 +21,7 @@
"rules": {
"func-style": ["error", "declaration", { "allowArrowFunctions": true }],
"no-console": ["warn", { "allow": ["group", "groupCollapsed", "groupEnd"] }],
"no-script-url": "error",
"no-control-regex": "off",
"no-debugger": "error",
"no-duplicate-imports": "error",
@@ -58,6 +59,7 @@
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off",
"react/jsx-no-useless-fragment": "off",
"react/jsx-no-script-url": "error",
"react/jsx-props-no-spreading": ["error", { "explicitSpread": "ignore" }],
"react-hooks/rules-of-hooks": "error",
@@ -29,6 +29,7 @@ module.exports = {
'./src/modules/front-components/graphql/**/*.{ts,tsx}',
'./src/modules/page-layout/widgets/**/graphql/**/*.{ts,tsx}',
'./src/modules/activities/emails/graphql/mutations/**/*.{ts,tsx}',
'./src/modules/dashboards/graphql/**/*.{ts,tsx}',
'./src/modules/page-layout/graphql/**/*.{ts,tsx}',
+2 -1
View File
@@ -6,7 +6,8 @@ module.exports = {
'/graphql',
documents: [
'./src/modules/workflow/**/graphql/**/*.{ts,tsx}',
'./src/modules/activities/emails/graphql/**/*.{ts,tsx}',
'./src/modules/activities/emails/graphql/queries/**/*.{ts,tsx}',
'./src/modules/activities/emails/graphql/operation-signatures/**/*.{ts,tsx}',
'./src/modules/activities/calendar/graphql/**/*.{ts,tsx}',
'./src/modules/search/graphql/**/*.{ts,tsx}',
'./src/modules/command-menu/graphql/**/*.{ts,tsx}',
File diff suppressed because one or more lines are too long
@@ -1,9 +1,11 @@
import { useOpenSettingsMenu } from '@/navigation/hooks/useOpenSettings';
import { useNavigate } from 'react-router-dom';
import { type SettingsPath } from 'twenty-shared/types';
import { getSettingsPath } from 'twenty-shared/utils';
export const useNavigateSettings = () => {
const navigate = useNavigate();
const { openSettingsMenu } = useOpenSettingsMenu();
return <T extends SettingsPath>(
to: T,
@@ -14,6 +16,8 @@ export const useNavigateSettings = () => {
state?: any;
},
) => {
openSettingsMenu();
const path = getSettingsPath(to, params, queryParams);
return navigate(path, options);
};
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Dit sal dit permanent uit die waglyn verwyder. H
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Dit sal die geselekteerde werk herprobeer. Dit sal van vooraf weer uitgevoer word.} other {Dit sal die geselekteerde werke herprobeer. Hulle sal van vooraf weer uitgevoer word.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} sal ontkoppel word van die volgende rol:"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} tokens"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "'n Fout het voorgekom tydens die oplaai van die prent."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Goedgekeurde Domeine"
msgid "Apps"
msgstr "Apps"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "Basis-URL"
msgid "Base URL is required"
msgstr "Basis-URL word vereis"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "Kan nie skandeer nie? Kopieer die"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Kanselleer"
@@ -2753,6 +2774,11 @@ msgstr "Kanselleer planwisseling"
msgid "Cancel plan switching?"
msgstr "Kanselleer planwisseling?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Katalaans"
msgid "Category"
msgstr "Kategorie"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "CC"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "skep"
msgid "Create"
msgstr "Skep"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Skep & Ontwikkel"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Skep 'n werksvloei en kom terug hier om sy weergawes te besigtig"
msgid "Create a workspace"
msgstr "Skep 'n werksruimte"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Beskryf wat jy wil hê die KI moet doen..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "E-pos moet 'n geldige e-pos wees"
msgid "Email or domain is already in blocklist"
msgstr "E-pos of domein is reeds in bloklys"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "E-posdraad"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "Kon nie werkruimte-instruksies stoor nie"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Gratis proefkrediete uitgeput. Teken nou in om voort te gaan om AI-funks
msgid "French"
msgstr "Frans"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Laai vaardighede..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Laai draad"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Nuwe geselsie"
msgid "New conversation"
msgstr "Nuwe gesprek"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "Geen API sleutels beskikbaar nie"
msgid "No API keys match your search"
msgstr "Geen API sleutels voldoen aan jou soektog nie"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "Geen veranderlikes gevind nie"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "nou"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "Lees jou profiel"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Leesalleen — bestuur deur Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Ontvang 'n e-pos met skakel om wagwoord op te dateer"
msgid "Recent Events (oldest → newest)"
msgstr "Onlangse Gebeure (oudste → nuutste)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "Herskik opsies"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Reageer"
@@ -11743,6 +11815,11 @@ msgstr "Reageer"
msgid "Reply to all"
msgstr "Beantwoord almal"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "Stuur e-pos weer"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Stel terug"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Herstel na"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Stoor"
msgid "Save as new view"
msgstr "Stoor as nuwe aansig"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Skep die raamwerk vir 'n nuwe toepassing en gebruik dan die CLI om te ontwikkel, te publiseer en te versprei"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Soek vir 'n agent..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Kies watter modelle as aanbevole modelle in die werkruimte se modelkiese
msgid "Select your preferred language"
msgstr "Kies jou voorkeurtaal"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Onderwerp"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "Stelsel Prompt"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Stelselprompt ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14132,6 +14212,11 @@ msgstr ""
msgid "This week"
msgstr "Hierdie week"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14247,6 +14332,7 @@ msgstr "titel"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "Aan"
@@ -14548,7 +14634,6 @@ msgstr "Twee-faktor magtiging-setup suksesvol voltooi!"
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14571,6 +14656,11 @@ msgstr "Tik '/' vir opdragte, '@' vir vermeldings"
msgid "Type anything..."
msgstr "Tik enigiets..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14898,6 +14988,11 @@ msgstr "Opgradeer vir toegang"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15334,7 +15429,6 @@ msgstr "Bekyk logboeke"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Bekyk markplekbladsy"
@@ -15348,6 +15442,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Sien Vorige KI-kletse"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15942,6 +16041,11 @@ msgstr "Jy behoort reeds aan hierdie werksruimte"
msgid "You are not allowed to create records for this object"
msgstr "Jy mag nie rekords vir hierdie voorwerp skep nie"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16017,10 +16121,10 @@ msgstr "Jou rekening is geaktiveer."
msgid "Your app version is out of date. Please refresh the page."
msgstr "Jou app weergawe is verouderd. Verfris asseblief die bladsy."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Jou toepassings"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, zero {سيتم إزالة {jobCount} نهائيًا
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, zero {سيتم إعادة محاولة {jobCount} وظائف. سيتم تنفيذهم مجددًا من البداية.} one {سيتم إعادة محاولة الوظيفة المحددة. سيتم تنفيذها من البداية.} two {سيتم إعادة المحاولة للوظائف المحددة. سيتم تنفيذهم من البداية.} few {سيتم إعادة المحاولة للوظائف المحددة. سيتم تنفيذهم من البداية.} many {سيتم إعادة المحاولة للوظائف المحددة. سيتم تنفيذهم من البداية.} other {سيتم إعادة المحاولة للوظائف المحددة. سيتم تنفيذهم من البداية.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} سيتم إلغاء تعيينه من الدور
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} رموز"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "حدث خطأ أثناء تحميل الصورة."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "النطاقات المعتمدة"
msgid "Apps"
msgstr "التطبيقات"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "عنوان URL الأساسي"
msgid "Base URL is required"
msgstr "عنوان URL الأساسي مطلوب"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "هل لا يمكنك المسح؟ انسخ الـ"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "إلغاء"
@@ -2753,6 +2774,11 @@ msgstr "إلغاء تبديل الخطة"
msgid "Cancel plan switching?"
msgstr "إلغاء تبديل الخطة؟"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "الكاتالانية"
msgid "Category"
msgstr "الفئة"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "نسخة كربونية"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "إنشاء"
msgid "Create"
msgstr "إنشاء"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "الإنشاء والتطوير"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "أنشئ سير عمل وعُد إلى هنا لرؤية إصدارات
msgid "Create a workspace"
msgstr "إنشاء مساحة العمل"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "صف ما تريد أن يقوم به الذكاء الاصطناعي...
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "يجب أن يكون البريد الإلكتروني صالحًا"
msgid "Email or domain is already in blocklist"
msgstr "البريد الإلكتروني أو النطاق مدرج بالفعل في القائمة السوداء"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "سلسلة البريد الإلكتروني"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "تعذّر حفظ تعليمات مساحة العمل"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "نفدت أرصدة النسخة التجريبية المجانية. ا
msgid "French"
msgstr "الفرنسية"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "جارٍ تحميل المهارات..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "جارٍ تحميل السلسلة"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "دردشة جديدة"
msgid "New conversation"
msgstr "محادثة جديدة"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "لا توجد مفاتيح API متاحة"
msgid "No API keys match your search"
msgstr "لا توجد مفاتيح API مطابقة لبحثك"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "لم يتم العثور على متغيرات"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "الآن"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "قراءة ملفك الشخصي"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "للقراءة فقط — تُدار بواسطة Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "\\\\"
msgid "Recent Events (oldest → newest)"
msgstr "الأحداث الأخيرة (الأقدم ← الأحدث)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "إعادة ترتيب الخيارات"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "الرد"
@@ -11743,6 +11815,11 @@ msgstr "الرد"
msgid "Reply to all"
msgstr "الرد على الكل"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "إعادة إرسال البريد الإلكتروني"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "إعادة تعيين"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "\\\\"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "حفظ"
msgid "Save as new view"
msgstr "احفظ كعرض جديد"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "أنشئ قالبًا لتطبيق جديد، ثم استخدم CLI للتطوير والنشر والتوزيع"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "ابحث عن وكيل..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "حدد النماذج التي ستظهر كموصى بها في منت
msgid "Select your preferred language"
msgstr "\\\\"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "الموضوع"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "أمر النظام"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "موجّه النظام ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14132,6 +14212,11 @@ msgstr ""
msgid "This week"
msgstr "هذا الأسبوع"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14247,6 +14332,7 @@ msgstr "العنوان"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "إلى"
@@ -14548,7 +14634,6 @@ msgstr "تم إكمال إعداد المصادقة الثنائية بنجاح!
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14571,6 +14656,11 @@ msgstr "اكتب '/' للأوامر، و'@' للإشارات"
msgid "Type anything..."
msgstr "اكتب أي شيء..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14898,6 +14988,11 @@ msgstr "الترقية للوصول"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15334,7 +15429,6 @@ msgstr "عرض السجلات"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "عرض صفحة سوق التطبيقات"
@@ -15348,6 +15442,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "عرض الذكاءات الاصطناعية السابقة"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15940,6 +16039,11 @@ msgstr "أنت بالفعل تنتمي إلى هذا فضاء العمل"
msgid "You are not allowed to create records for this object"
msgstr "غير مسموح لك بإنشاء سجلات لهذا الكائن"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16015,10 +16119,10 @@ msgstr "تم تنشيط حسابك."
msgid "Your app version is out of date. Please refresh the page."
msgstr "نسخة التطبيق لديك قديمة. يُرجى تحديث الصفحة."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "تطبيقاتك"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Això eliminarà permanentment la cua. Aquesta a
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Això tornarà a intentar la feina seleccionada. Es tornarà a executar des del principi.} other {Això tornarà a intentar les feines seleccionades. Es tornaran a executar des del principi.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} serà desassignat del següent rol:"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} tokens"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "S'ha produït un error en carregar la imatge."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Dominis Aprovats"
msgid "Apps"
msgstr "Aplicacions"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "URL base"
msgid "Base URL is required"
msgstr "L'URL base és necessari"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "No pots escanejar? Copia la"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Cancel·la"
@@ -2753,6 +2774,11 @@ msgstr "Cancel·lar el canvi de pla"
msgid "Cancel plan switching?"
msgstr "Cancel·lar el canvi de pla?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Català"
msgid "Category"
msgstr "Categoria"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "CC"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "crea"
msgid "Create"
msgstr "Crea"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Crea i desenvolupa"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Crea un flux de treball i torna aquí per veure les seves versions"
msgid "Create a workspace"
msgstr "Crear un espai de treball"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Descriviu què voleu que faci la IA..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "El correu electrònic ha de ser vàlid"
msgid "Email or domain is already in blocklist"
msgstr "El correu electrònic o domini ja està en la llista de bloqueig"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "Fil de correu electrònic"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "No s'han pogut desar les instruccions de l'espai de treball"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Crèdits de la prova gratuïta esgotats. Subscriu-te ara per continuar u
msgid "French"
msgstr "Francès"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Carregant habilitats..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Carregant el fil"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Nou xat"
msgid "New conversation"
msgstr "Nova conversa"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "No hi ha claus d'API disponibles"
msgid "No API keys match your search"
msgstr "Cap clau d'API concorda amb la teva cerca"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "No s'han trobat variables"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "ara"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "Llegir el teu perfil"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Només de lectura — gestionat per Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Rep un correu que conté l'enllaç per actualitzar la contrasenya"
msgid "Recent Events (oldest → newest)"
msgstr "Esdeveniments recents (més antic → més nou)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr ""
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Respon"
@@ -11743,6 +11815,11 @@ msgstr "Respon"
msgid "Reply to all"
msgstr "Respon a tots"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "Reenviar correu electrònic"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Restableix"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Reinicia a"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Desa"
msgid "Save as new view"
msgstr "Desa com a nova vista"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Genera l'esquelet d'una aplicació nova, després utilitza la CLI per desenvolupar, publicar i distribuir"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Cerca un agent..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Seleccioneu quins models apareixen com a recomanats al selector de model
msgid "Select your preferred language"
msgstr "Tria la teva llengua preferida"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Assumpte"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "Indicador del Sistema"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Prompt del sistema ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14132,6 +14212,11 @@ msgstr ""
msgid "This week"
msgstr "Aquesta setmana"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14247,6 +14332,7 @@ msgstr "títol"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "A"
@@ -14548,7 +14634,6 @@ msgstr "Configuració de l'autenticació de dos factors completada amb èxit!"
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14571,6 +14656,11 @@ msgstr "Escriu '/' per a ordres, '@' per a mencions"
msgid "Type anything..."
msgstr "Teclegeu qualsevol cosa..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14898,6 +14988,11 @@ msgstr "Actualitza per accedir"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15334,7 +15429,6 @@ msgstr "Veure registres"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Veure la pàgina del Marketplace"
@@ -15348,6 +15442,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Veure els xats d'IA anteriors"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15942,6 +16041,11 @@ msgstr "Ja formes part d'aquest espai de treball"
msgid "You are not allowed to create records for this object"
msgstr "No tens permís per crear registres en aquest objecte"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16017,10 +16121,10 @@ msgstr "El teu compte s'ha activat."
msgid "Your app version is out of date. Please refresh the page."
msgstr "La teva versió de l'aplicació està desactualitzada. Si us plau, actualitza la pàgina."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Les teves aplicacions"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Tato akce ji trvale odstraní z fronty. Tuto akc
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Tato akce znovu spustí vybranou úlohu. Bude spuštěna znovu od začátku.} few {Tato akce znovu spustí vybrané úlohy. Budou spuštěny znovu od začátku.} many {Tato akce znovu spustí vybrané úlohy. Budou spuštěny znovu od začátku.} other {Tato akce znovu spustí vybrané úlohy. Budou spuštěny znovu od začátku.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} bude odebrán z následující role:"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} tokenů"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "Při nahrávání obrázku došlo k chybě."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Schválené domény"
msgid "Apps"
msgstr "Aplikace"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "Základní URL"
msgid "Base URL is required"
msgstr "Základní adresa URL je vyžadována"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "Nemůžete skenovat? Zkopírujte"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Storno"
@@ -2753,6 +2774,11 @@ msgstr "Zrušit změnu plánu"
msgid "Cancel plan switching?"
msgstr "Zrušit změnu plánu?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Katalánština"
msgid "Category"
msgstr "Kategorie"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "CC"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "vytvořit"
msgid "Create"
msgstr "Vytvořit"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Vytvořit a vyvíjet"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Vytvořte workflow a vraťte se zde pro zobrazení jeho verzí"
msgid "Create a workspace"
msgstr "Vytvořte pracovní prostor"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Popište, co chcete, aby AI dělalo..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "E-mail musí být platný"
msgid "Email or domain is already in blocklist"
msgstr "E-mail nebo doména již je v seznamu blokovaných"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "E-mailové vlákno"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "Nepodařilo se uložit pokyny pracovního prostoru"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Kredity ze zkušební verze byly vyčerpány. Předplaťte si nyní, aby
msgid "French"
msgstr "Francouzština"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Načítání dovedností..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Načítání vlákna"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Nový chat"
msgid "New conversation"
msgstr "Nová konverzace"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "Žádné API klíče nejsou k dispozici"
msgid "No API keys match your search"
msgstr "Žádné API klíče neodpovídají vašemu vyhledávání"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "Žádné proměnné nenalezeny"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "nyní"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "Čtení vašeho profilu"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Jen pro čtení — spravováno Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Obdržíte e-mail s odkazem na aktualizaci hesla"
msgid "Recent Events (oldest → newest)"
msgstr "Nedávné události (od nejstarších → k nejnovějším)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "Změnit pořadí možností"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Odpovědět"
@@ -11743,6 +11815,11 @@ msgstr "Odpovědět"
msgid "Reply to all"
msgstr "Odpovědět všem"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "Znovu odeslat e-mail"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Obnovit"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Obnovit na"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Uložit"
msgid "Save as new view"
msgstr "Uložit jako nové zobrazení"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Vytvořte kostru nové aplikace a poté pomocí CLI vyvíjejte, publikujte a distribuujte"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Hledat agenta..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Vyberte, které modely se budou zobrazovat jako doporučené ve výběru
msgid "Select your preferred language"
msgstr "Vyberte preferovaný jazyk"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Předmět"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "Systémová výzva"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Systémový prompt ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14132,6 +14212,11 @@ msgstr ""
msgid "This week"
msgstr "Tento týden"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14247,6 +14332,7 @@ msgstr "název"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "Komu"
@@ -14548,7 +14634,6 @@ msgstr "Nastavení dvoufaktorového ověřování bylo úspěšně dokončeno!"
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14571,6 +14656,11 @@ msgstr "Zadejte '/' pro příkazy, '@' pro zmínky"
msgid "Type anything..."
msgstr "Napište cokoli..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14898,6 +14988,11 @@ msgstr "Přejděte na vyšší verzi pro přístup"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15334,7 +15429,6 @@ msgstr "Zobrazit protokoly"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Zobrazit stránku na Marketplace"
@@ -15348,6 +15442,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Zobrazit předchozí AI diskuse"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15942,6 +16041,11 @@ msgstr "Již patříte do tohoto workspace"
msgid "You are not allowed to create records for this object"
msgstr "Nemáte povoleno vytvářet záznamy pro tento objekt"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16017,10 +16121,10 @@ msgstr "Váš účet byl aktivován."
msgid "Your app version is out of date. Please refresh the page."
msgstr "Verze vaší aplikace je zastaralá. Aktualizujte, prosím, stránku."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Vaše aplikace"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Dette vil permanent fjerne det fra køen. Denne
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Dette vil forsøge det valgte job igen. Det vil blive udført fra begyndelsen.} other {Dette vil forsøge de valgte jobs igen. De vil blive udført fra begyndelsen.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} vil blive fjernet fra følgende rolle:"
msgid "••••••••"
msgstr ""
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} tokens"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "Der opstod en fejl under upload af billedet."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Godkendte domæner"
msgid "Apps"
msgstr "Apps"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "Basis-URL"
msgid "Base URL is required"
msgstr "Basis-URL er påkrævet"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "Kan ikke scanne? Kopier"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Annuller"
@@ -2753,6 +2774,11 @@ msgstr "Annuller planskift"
msgid "Cancel plan switching?"
msgstr "Annuller planskift?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Catalansk"
msgid "Category"
msgstr ""
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr ""
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "opret"
msgid "Create"
msgstr "Opret"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Opret & udvikl"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Opret en arbejdsproces og vend tilbage hertil for at se dens versioner"
msgid "Create a workspace"
msgstr "Opret et arbejdsområde"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Beskriv, hvad du vil have AI'en til at gøre..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "E-mail skal være gyldig"
msgid "Email or domain is already in blocklist"
msgstr "E-mail eller domæne er allerede på blokeringslisten"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "E-mail-tråd"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "Kunne ikke gemme instruktioner for arbejdsområdet"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Kreditter i den gratis prøveperiode er opbrugt. Abonner nu for at forts
msgid "French"
msgstr "Fransk"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Indlæser færdigheder..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Indlæser tråd"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Ny chat"
msgid "New conversation"
msgstr "Ny samtale"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "Ingen API nøgler tilgængelige"
msgid "No API keys match your search"
msgstr "Ingen API nøgler matcher din søgning"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "Ingen variabler fundet"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "nu"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "Læs din profil"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Skrivebeskyttet — administreret af Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Modtag en e-mail med link til opdatering af kodeord"
msgid "Recent Events (oldest → newest)"
msgstr "Seneste hændelser (ældste → nyeste)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "Omarranger valgmuligheder"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Svar"
@@ -11743,6 +11815,11 @@ msgstr "Svar"
msgid "Reply to all"
msgstr "Svar til alle"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "Send e-mail igen"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Nulstil"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Nulstil til"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Gem"
msgid "Save as new view"
msgstr "Gem som ny visning"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Generér et skelet til en ny app, og brug derefter CLI til at udvikle, udgive og distribuere"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Søg efter en agent..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Vælg hvilke modeller der vises som anbefalede i arbejdsområdets modelv
msgid "Select your preferred language"
msgstr "Vælg dit foretrukne sprog"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Emne"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "Systemprompt"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Systemprompt ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14134,6 +14214,11 @@ msgstr ""
msgid "This week"
msgstr "Denne uge"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14249,6 +14334,7 @@ msgstr "titel"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr ""
@@ -14550,7 +14636,6 @@ msgstr "Opsætning af to-faktor godkendelse blev gennemført med succes!"
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14573,6 +14658,11 @@ msgstr "Skriv '/' for kommandoer, '@' for omtaler"
msgid "Type anything..."
msgstr "Skriv noget..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14900,6 +14990,11 @@ msgstr "Opgrader for at få adgang"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15336,7 +15431,6 @@ msgstr "Vis logge"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Se side på markedspladsen"
@@ -15350,6 +15444,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Se tidligere AI-chats"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15944,6 +16043,11 @@ msgstr "Du er allerede medlem af dette arbejdsområde"
msgid "You are not allowed to create records for this object"
msgstr "Du har ikke tilladelse til at oprette poster i dette objekt"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16019,10 +16123,10 @@ msgstr "Din konto er blevet aktiveret."
msgid "Your app version is out of date. Please refresh the page."
msgstr "Din app-version er forældet. Opdater venligst siden."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Dine apps"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Dies wird es dauerhaft von der Warteschlange ent
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Dies wird den ausgewählten Auftrag neu ausführen. Er wird von Anfang an neu ausgeführt.} other {Dies wird die ausgewählten Aufträge neu ausführen. Sie werden von Anfang an neu ausgeführt.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} wird von folgender Rolle abgezogen:"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} Token"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "Beim Hochladen des Bildes ist ein Fehler aufgetreten."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Genehmigte Domänen"
msgid "Apps"
msgstr "Apps"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "Basis-URL"
msgid "Base URL is required"
msgstr "Basis-URL ist erforderlich"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "Kann nicht gescannt werden? Kopieren Sie das"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Abbrechen"
@@ -2753,6 +2774,11 @@ msgstr "Tarifwechsel abbrechen"
msgid "Cancel plan switching?"
msgstr "Tarifwechsel abbrechen?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Katalanisch"
msgid "Category"
msgstr "Kategorie"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "CC"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "erstellen"
msgid "Create"
msgstr "Erstellen"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Erstellen & Entwickeln"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Erstellen Sie einen Workflow und kehren Sie hierher zurück, um die Vers
msgid "Create a workspace"
msgstr "Arbeitsbereich erstellen"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Beschreiben Sie, was die KI tun soll..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "E-Mail muss gültig sein"
msgid "Email or domain is already in blocklist"
msgstr "E-Mail oder Domain ist bereits in der Blockliste"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "E-Mail-Thread"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr "Fehler beim Speichern der Rollenberechtigungen: {errorMessage}"
msgid "Failed to save workspace instructions"
msgstr "Fehler beim Speichern der Arbeitsbereichsanweisungen"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Kostenloses Testguthaben aufgebraucht. Abonnieren Sie jetzt, um KI-Funkt
msgid "French"
msgstr "Französisch"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Skills werden geladen..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Thread wird geladen"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Neuer Chat"
msgid "New conversation"
msgstr "Neue Unterhaltung"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "Keine API-Schlüssel verfügbar"
msgid "No API keys match your search"
msgstr "Keine API-Schlüssel passen zu Ihrer Suche"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "Keine Variablen gefunden"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "jetzt"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "Ihr Profil lesen"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Schreibgeschützt — verwaltet von Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Erhalten Sie eine E-Mail mit einem Link zur Passwortaktualisierung"
msgid "Recent Events (oldest → newest)"
msgstr "Aktuelle Ereignisse (älteste → neueste)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "Optionen neu anordnen"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Antworten"
@@ -11743,6 +11815,11 @@ msgstr "Antworten"
msgid "Reply to all"
msgstr "Allen antworten"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "E-Mail erneut senden"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Zurücksetzen"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Zurücksetzen auf"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Speichern"
msgid "Save as new view"
msgstr "Als neue Ansicht speichern"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Ein neues App-Gerüst erstellen und anschließend die CLI zum Entwickeln, Veröffentlichen und Verteilen verwenden"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Einen Agenten suchen..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Wählen Sie aus, welche Modelle im Modellauswahlfeld des Arbeitsbereichs
msgid "Select your preferred language"
msgstr "Bevorzugte Sprache auswählen"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Betreff"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "Systemaufforderung"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Systemprompt ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14132,6 +14212,11 @@ msgstr ""
msgid "This week"
msgstr "Diese Woche"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14247,6 +14332,7 @@ msgstr "titel"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "An"
@@ -14548,7 +14634,6 @@ msgstr "Einrichtung der Zwei-Faktor-Authentifizierung erfolgreich abgeschlossen!
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14571,6 +14656,11 @@ msgstr "Geben Sie '/' für Befehle, '@' für Erwähnungen ein"
msgid "Type anything..."
msgstr "Geben Sie irgendetwas ein..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14898,6 +14988,11 @@ msgstr "Upgrade, um Zugriff zu erhalten"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15334,7 +15429,6 @@ msgstr "Protokolle anzeigen"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Marktplatz-Seite anzeigen"
@@ -15348,6 +15442,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Vorherige KI-Chats anzeigen"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15942,6 +16041,11 @@ msgstr "Sie gehören bereits zu diesem Arbeitsplatz"
msgid "You are not allowed to create records for this object"
msgstr "Sie dürfen keine Datensätze für dieses Objekt erstellen"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16017,10 +16121,10 @@ msgstr "Ihr Konto wurde aktiviert."
msgid "Your app version is out of date. Please refresh the page."
msgstr "Ihre App-Version ist veraltet. Bitte aktualisieren Sie die Seite."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Ihre Apps"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Αυτό θα την αφαιρέσει ορισ
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Αυτό θα επαναλάβει την επιλεγμένη εργασία. Θα εκτελεστεί από την αρχή.} other {Αυτό θα επαναλάβει τις επιλεγμένες εργασίες. Θα εκτελεστούν από την αρχή.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "Ο χρήστης {workspaceMemberName} θα αποδεσμευτεί α
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} διακριτικά"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "Παρουσιάστηκε σφάλμα κατά τη μεταφόρτω
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Εγκεκριμένοι Τομείς"
msgid "Apps"
msgstr "Εφαρμογές"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "Βασικό URL"
msgid "Base URL is required"
msgstr "Απαιτείται το βασικό URL"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "Δεν μπορείτε να σαρώσετε; Αντιγράψτε το
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Ακύρωση"
@@ -2753,6 +2774,11 @@ msgstr "Ακύρωση αλλαγής προγράμματος"
msgid "Cancel plan switching?"
msgstr "Ακύρωση αλλαγής προγράμματος;"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Καταλανικά"
msgid "Category"
msgstr "Κατηγορία"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "Κοινοποίηση"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "δημιουργία"
msgid "Create"
msgstr "Δημιουργία"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Δημιουργία & Ανάπτυξη"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Δημιουργήστε ένα workflow και επιστρέψτε ε
msgid "Create a workspace"
msgstr "Δημιουργία Χώρου Εργασίας"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Περιγράψτε τι θέλετε να κάνει το AI..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "Το email πρέπει να είναι έγκυρο"
msgid "Email or domain is already in blocklist"
msgstr "Το email ή ο τομέας βρίσκεται ήδη στη λίστα απόκλεισης"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "Νήμα email"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "Αποτυχία αποθήκευσης των οδηγιών του χώρου εργασίας"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Οι πιστώσεις της δωρεάν δοκιμής εξαντλ
msgid "French"
msgstr "Γαλλικά"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Φόρτωση δεξιοτήτων..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Φόρτωση νήματος"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Νέα συνομιλία"
msgid "New conversation"
msgstr "Νέα συνομιλία"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "Δεν υπάρχουν διαθέσιμα κλειδιά API"
msgid "No API keys match your search"
msgstr "Κανένα κλειδί API δεν ταιριάζει με την αναζήτησή σας"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "Δεν βρέθηκαν μεταβλητές"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "τώρα"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "Ανάγνωση του προφίλ σας"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Μόνο για ανάγνωση — διαχειρίζεται από την Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Λάβετε ένα email που περιέχει τον σύνδεσμ
msgid "Recent Events (oldest → newest)"
msgstr "Πρόσφατα Γεγονότα (παλιότερα → νεότερα)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "Αναδιάταξη επιλογών"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Απάντηση"
@@ -11743,6 +11815,11 @@ msgstr "Απάντηση"
msgid "Reply to all"
msgstr "Απάντηση σε όλους"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "Επαναποστολή email"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Επαναφορά"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Επαναφορά σε"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Αποθήκευση"
msgid "Save as new view"
msgstr "Αποθήκευση ως νέα προβολή"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Δημιουργήστε τον σκελετό μιας νέας εφαρμογής και στη συνέχεια χρησιμοποιήστε το CLI για να την αναπτύξετε, να τη δημοσιεύσετε και να τη διανείμετε"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Αναζήτηση πράκτορα..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Επιλέξτε ποια μοντέλα θα εμφανίζονται
msgid "Select your preferred language"
msgstr "Επιλέξτε την προτιμώμενη γλώσσα σας"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13403,6 +13486,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Θέμα"
@@ -13643,11 +13728,6 @@ msgstr ""
msgid "System Prompt"
msgstr "Σύστημα Προτροπής"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Προτροπή συστήματος ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14136,6 +14216,11 @@ msgstr ""
msgid "This week"
msgstr "Αυτή την εβδομάδα"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14251,6 +14336,7 @@ msgstr "τίτλος"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "Προς"
@@ -14552,7 +14638,6 @@ msgstr "Η εγκατάσταση δύο παραγοντικής ταυτοπο
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14575,6 +14660,11 @@ msgstr "Πληκτρολογήστε '/' για εντολές, '@' για αν
msgid "Type anything..."
msgstr "Πληκτρολογήστε οτιδήποτε..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14902,6 +14992,11 @@ msgstr "Αναβαθμίστε για πρόσβαση"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15338,7 +15433,6 @@ msgstr "Προβολή αρχείων καταγραφής"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Προβολή σελίδας marketplace"
@@ -15352,6 +15446,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Εμφάνιση Προηγούμενων Συνομιλιών AI"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15946,6 +16045,11 @@ msgstr "Ανήκετε ήδη σε αυτό το workspace"
msgid "You are not allowed to create records for this object"
msgstr "Δεν επιτρέπεται να δημιουργείτε εγγραφές για αυτό το αντικείμενο"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16021,10 +16125,10 @@ msgstr "Ο λογαριασμός σας έχει ενεργοποιηθεί."
msgid "Your app version is out of date. Please refresh the page."
msgstr "Η έκδοση της εφαρμογής σας είναι παρωχημένη. Παρακαλώ ανανεώστε τη σελίδα."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Οι εφαρμογές σας"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -311,6 +311,11 @@ msgstr "{jobCount, plural, one {This will permanently remove it from the queue.
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr "{messagesLength} emails"
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -446,11 +451,13 @@ msgstr "{workspaceMemberName} will be unassigned from the following role:"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} tokens"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr "~ {0} tokens"
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1697,6 +1704,7 @@ msgstr "An error occurred while uploading the picture."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1979,6 +1987,11 @@ msgstr "Approved Domains"
msgid "Apps"
msgstr "Apps"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr "Apps made by other developers published on npm"
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2403,6 +2416,12 @@ msgstr "Base URL"
msgid "Base URL is required"
msgstr "Base URL is required"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr "Bcc"
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2706,9 +2725,11 @@ msgstr "Can't scan? Copy the"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Cancel"
@@ -2748,6 +2769,11 @@ msgstr "Cancel plan switching"
msgid "Cancel plan switching?"
msgstr "Cancel plan switching?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr "Cancel reply"
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2816,11 +2842,22 @@ msgstr "Catalan"
msgid "Category"
msgstr "Category"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr "Cc"
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "CC"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr "Cc/Bcc"
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3771,11 +3808,6 @@ msgstr "create"
msgid "Create"
msgstr "Create"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Create & Develop"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3816,6 +3848,11 @@ msgstr "Create a workflow and return here to view its versions"
msgid "Create a workspace"
msgstr "Create a workspace"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr "Create an application"
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4789,6 +4826,7 @@ msgstr "Describe what you want the AI to do..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5334,16 +5372,16 @@ msgstr "Email must be a valid email"
msgid "Email or domain is already in blocklist"
msgstr "Email or domain is already in blocklist"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr "Email sent successfully"
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr "Email support"
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "Email Thread"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6428,6 +6466,12 @@ msgstr "Failed to save role permissions: {errorMessage}"
msgid "Failed to save workspace instructions"
msgstr "Failed to save workspace instructions"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr "Failed to send email"
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6919,6 +6963,11 @@ msgstr "Free trial credits exhausted. Subscribe now to continue using AI feature
msgid "French"
msgstr "French"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr "From"
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8566,7 +8615,7 @@ msgid "Loading skills..."
msgstr "Loading skills..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Loading thread"
@@ -9218,10 +9267,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9387,6 +9436,11 @@ msgstr "New chat"
msgid "New conversation"
msgstr "New conversation"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr "New Email"
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9585,6 +9639,11 @@ msgstr "No API keys available"
msgid "No API keys match your search"
msgstr "No API keys match your search"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr "No application found"
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10013,6 +10072,7 @@ msgid "No variables found"
msgstr "No variables found"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr "No variables to set for this application"
@@ -10128,6 +10188,11 @@ msgstr "now"
msgid "Npm package"
msgstr "Npm package"
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr "NPM packages"
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11352,10 +11417,11 @@ msgstr "Read the system prompts to understand how the AI works (~{0} tokens)"
msgid "Read your profile"
msgstr "Read your profile"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Read-only — managed by Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr "Read-only"
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11377,6 +11443,11 @@ msgstr "Receive an email containing password update link"
msgid "Recent Events (oldest → newest)"
msgstr "Recent Events (oldest → newest)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr "Recipients"
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11728,7 +11799,8 @@ msgid "Reorder options"
msgstr "Reorder options"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Reply"
@@ -11738,6 +11810,11 @@ msgstr "Reply"
msgid "Reply to all"
msgstr "Reply to all"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr "Reply..."
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11763,6 +11840,7 @@ msgstr "Resend email"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Reset"
@@ -11783,6 +11861,8 @@ msgid "Reset to"
msgstr "Reset to"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12081,11 +12161,6 @@ msgstr "Save"
msgid "Save as new view"
msgstr "Save as new view"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Scaffold a new app, then use the CLI to develop, publish, and distribute"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12227,6 +12302,7 @@ msgid "Search an agent..."
msgstr "Search an agent..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12681,6 +12757,13 @@ msgstr "Select which models appear as recommended in the workspace model picker"
msgid "Select your preferred language"
msgstr "Select your preferred language"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr "Send"
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13396,6 +13479,8 @@ msgstr "subheading"
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Subject"
@@ -13636,11 +13721,6 @@ msgstr "System objects"
msgid "System Prompt"
msgstr "System Prompt"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "System Prompt ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14129,6 +14209,11 @@ msgstr "This view uses {usageLabel} on object \"{0}\" which is not accessible."
msgid "This week"
msgstr "This week"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr "This will cancel all modifications done on the widget. This action cannot be undone."
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14244,6 +14329,7 @@ msgstr "title"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "To"
@@ -14545,7 +14631,6 @@ msgstr "Two-factor authentication setup completed successfully!"
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14568,6 +14653,11 @@ msgstr "Type '/' for commands, '@' for mentions"
msgid "Type anything..."
msgstr "Type anything..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr "Type something or press \"/\" to see commands"
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14895,6 +14985,11 @@ msgstr "Upgrade to access"
msgid "Upgrade to Enterprise to access audit logs."
msgstr "Upgrade to Enterprise to access audit logs."
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr "Upgrade to Enterprise to share private applications."
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15331,7 +15426,6 @@ msgstr "View Logs"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "View marketplace page"
@@ -15345,6 +15439,11 @@ msgstr "View not shared"
msgid "View Previous AI Chats"
msgstr "View Previous AI Chats"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr "View private application page"
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15939,6 +16038,11 @@ msgstr "You already belong to this workspace"
msgid "You are not allowed to create records for this object"
msgstr "You are not allowed to create records for this object"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr "You can either create a private app or share it to others"
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16014,10 +16118,10 @@ msgstr "Your account has been activated."
msgid "Your app version is out of date. Please refresh the page."
msgstr "Your app version is out of date. Please refresh the page."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Your Apps"
msgid "Your apps"
msgstr "Your apps"
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Esto lo eliminará permanentemente de la cola. E
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Esto reintentará el trabajo seleccionado. Será reejecutado desde el principio.} other {Esto reintentará los trabajos seleccionados. Serán reejecutados desde el principio.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} dejará de estar asignado al siguiente rol:"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} tokens"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "Se produjo un error al subir la imagen."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Dominios Aprobados"
msgid "Apps"
msgstr "Aplicaciones"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "URL base"
msgid "Base URL is required"
msgstr "La URL base es obligatoria"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "¿No puedes escanear? Copia el"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Cancelar"
@@ -2753,6 +2774,11 @@ msgstr "Cancelar cambio de plan"
msgid "Cancel plan switching?"
msgstr "¿Cancelar cambio de plan?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Catalán"
msgid "Category"
msgstr "Categoría"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "CC"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "crear"
msgid "Create"
msgstr "Crear"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Crear y Desarrollar"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Cree un workflow y vuelva aquí para ver sus versiones"
msgid "Create a workspace"
msgstr "Crear Espacio de Trabajo"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Describa lo que quiere que la IA haga..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "El correo electrónico debe ser válido"
msgid "Email or domain is already in blocklist"
msgstr "El correo electrónico o el dominio ya están en la lista de bloqueo"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "Hilo de correo electrónico"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr "Error al guardar los permisos de rol: {errorMessage}"
msgid "Failed to save workspace instructions"
msgstr "Error al guardar las instrucciones del espacio de trabajo"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Se han agotado los créditos de la prueba gratuita. Suscríbete ahora pa
msgid "French"
msgstr "Francés"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Cargando habilidades..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Cargando hilo"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Nuevo chat"
msgid "New conversation"
msgstr "Nueva conversación"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "No hay claves API disponibles"
msgid "No API keys match your search"
msgstr "No hay claves API que coincidan con tu búsqueda"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "No se encontraron variables"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "ahora"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "Leer tu perfil"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "De solo lectura — gestionado por Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Recibir un correo electrónico con un enlace para actualizar la contrase
msgid "Recent Events (oldest → newest)"
msgstr "Eventos Recientes (del más antiguo → al más nuevo)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "Reordenar opciones"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Responder"
@@ -11743,6 +11815,11 @@ msgstr "Responder"
msgid "Reply to all"
msgstr "Responder a todos"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "Reenviar correo electrónico"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Restablecer"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Restablecer a"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Guardar"
msgid "Save as new view"
msgstr "Guardar como nueva vista"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Crea la estructura inicial de una nueva aplicación y luego usa la CLI para desarrollar, publicar y distribuir"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Buscar un agente..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Selecciona qué modelos aparecen como recomendados en el selector de mod
msgid "Select your preferred language"
msgstr "Selecciona tu idioma preferido"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr "sub encabezado"
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Asunto"
@@ -13641,11 +13726,6 @@ msgstr "Objetos del sistema"
msgid "System Prompt"
msgstr "Aviso del sistema"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Prompt del sistema ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14134,6 +14214,11 @@ msgstr ""
msgid "This week"
msgstr "Esta semana"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14249,6 +14334,7 @@ msgstr "título"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "Para"
@@ -14550,7 +14636,6 @@ msgstr "¡La configuración de la autenticación de dos factores se completó co
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14573,6 +14658,11 @@ msgstr "Escribe \"/\" para comandos, \"@\" para menciones"
msgid "Type anything..."
msgstr "Escribe cualquier cosa..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14900,6 +14990,11 @@ msgstr "Actualiza para acceder"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15336,7 +15431,6 @@ msgstr "Ver registros"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Ver página del Marketplace"
@@ -15350,6 +15444,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Ver chats previos de IA"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15944,6 +16043,11 @@ msgstr "Ya perteneces a este espacio de trabajo"
msgid "You are not allowed to create records for this object"
msgstr "No tiene permiso para crear registros en este objeto"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16019,10 +16123,10 @@ msgstr "Tu cuenta ha sido activada."
msgid "Your app version is out of date. Please refresh the page."
msgstr "La versión de su aplicación está desactualizada. Por favor, actualice la página."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Tus aplicaciones"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Tämä poistaa sen pysyvästi jonosta. Tämä to
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Tämä yrittää valittua työtä uudelleen. Se suoritetaan alusta alkaen uudelleen.} other {Tämä yrittää valittuja töitä uudelleen. Ne suoritetaan alusta alkaen uudelleen.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} poistetaan seuraavasta roolista:"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} tokenia"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "Kuvaa ladattaessa tapahtui virhe."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Hyväksytyt verkkotunnukset"
msgid "Apps"
msgstr "Sovellukset"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "Perus-URL"
msgid "Base URL is required"
msgstr "Perus-URL on pakollinen"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "Et voi skannata? Kopioi"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Peruuta"
@@ -2753,6 +2774,11 @@ msgstr "Peruuta suunnitelman vaihtaminen"
msgid "Cancel plan switching?"
msgstr "Peruuta suunnitelman vaihtaminen?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Katalaani"
msgid "Category"
msgstr "Luokka"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "Kopio"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "luo"
msgid "Create"
msgstr "Luo"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Luo ja kehitä"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Luo työnkulku ja palaa tänne nähdäksesi sen versiot"
msgid "Create a workspace"
msgstr "Luo työtila"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Kuvaile mitä haluat, että tekoäly tekee..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "Sähköpostin on oltava kelvollinen sähköpostiosoite"
msgid "Email or domain is already in blocklist"
msgstr "Sähköposti tai verkkotunnus on jo estolistalla"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "Sähköpostiketju"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "Työtilan ohjeiden tallentaminen epäonnistui"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Kokeilujakson krediitit on käytetty. Tilaa nyt jatkaaksesi AI-ominaisuu
msgid "French"
msgstr "Ranska"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Ladataan taitoja..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Ladataan ketjua"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Uusi keskustelu"
msgid "New conversation"
msgstr "Uusi keskustelu"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "Ei käytettävissä olevia API-avaimia"
msgid "No API keys match your search"
msgstr "Yksikään API-avain ei vastaa hakua"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "Muuttujia ei löydy"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "nyt"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "Lue profiilisi"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Vain luku — Twenty hallinnoi"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Vastaanota sähköposti salasanan päivityslinkillä"
msgid "Recent Events (oldest → newest)"
msgstr "Viimeisimmät tapahtumat (vanhin → uusin)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "Järjestä vaihtoehdot uudelleen"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Vastaa"
@@ -11743,6 +11815,11 @@ msgstr "Vastaa"
msgid "Reply to all"
msgstr "Vastaa kaikille"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "Lähetä sähköposti uudelleen"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Nollaa"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Palauta"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Tallenna"
msgid "Save as new view"
msgstr "Tallenna uutena näkymänä"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Luo uuden sovelluksen perusrakenne ja käytä sitten CLI:tä kehittämiseen, julkaisuun ja jakeluun"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Etsi agenttia..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Valitse, mitkä mallit näkyvät suositeltuina työtilan mallivalitsimes
msgid "Select your preferred language"
msgstr "Valitse suosimasi kieli"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Aihe"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "Järjestelmäkehotus"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Järjestelmäkehote ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14132,6 +14212,11 @@ msgstr ""
msgid "This week"
msgstr "Tämä viikko"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14247,6 +14332,7 @@ msgstr "otsikko"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "Vastaanottaja"
@@ -14548,7 +14634,6 @@ msgstr "Kaksivaiheisen todennuksen asennus on valmis!"
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14571,6 +14656,11 @@ msgstr "Kirjoita '/' komentoja varten, '@' mainintoja varten"
msgid "Type anything..."
msgstr "Kirjoita jotain..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14898,6 +14988,11 @@ msgstr "Päivitä saadaksesi käyttöoikeuden"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15334,7 +15429,6 @@ msgstr "Näytä lokit"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Avaa markkinapaikan sivu"
@@ -15348,6 +15442,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Näytä edelliset AI Keskustelut"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15942,6 +16041,11 @@ msgstr "Kuulut jo tähän työtilaan"
msgid "You are not allowed to create records for this object"
msgstr "Et voi luoda tietueita tälle objektille"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16017,10 +16121,10 @@ msgstr "Tilisi on aktivoitu."
msgid "Your app version is out of date. Please refresh the page."
msgstr "Sovelluksesi versio on vanhentunut. Ole hyvä, päivitä sivu."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Omat sovellukset"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {Cela le retirera définitivement de la file d'at
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {Ceci va réessayer la tâche sélectionnée. Elle sera ré-exécutée depuis le début.} other {Ceci va réessayer les tâches sélectionnées. Elles seront ré-exécutées depuis le début.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} sera retiré du rôle suivant :"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} jetons"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "Une erreur s'est produite lors du téléversement de l'image."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "Domaines approuvés"
msgid "Apps"
msgstr "Applications"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "URL de base"
msgid "Base URL is required"
msgstr "L'URL de base est requise"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "Impossible de scanner ? Copiez le"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "Annuler"
@@ -2753,6 +2774,11 @@ msgstr "Annuler le changement de plan"
msgid "Cancel plan switching?"
msgstr "Annuler le changement de plan ?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "Catalan"
msgid "Category"
msgstr "Catégorie"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "Cc"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "créer"
msgid "Create"
msgstr "Créer"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "Créer et développer"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "Créez un workflow et revenez ici pour voir ses versions"
msgid "Create a workspace"
msgstr "Créer un espace de travail"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "Décrivez ce que vous voulez que l'IA fasse..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "L'adresse e-mail doit être valide"
msgid "Email or domain is already in blocklist"
msgstr "Le courriel ou le domaine est déjà dans la liste de blocage"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "Fil de discussion e-mail"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "Impossible d'enregistrer les instructions de l'espace de travail"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "Crédits d'essai gratuits épuisés. Abonnez-vous maintenant pour contin
msgid "French"
msgstr "Français"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "Chargement des compétences..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "Chargement du fil de discussion"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "Nouveau chat"
msgid "New conversation"
msgstr "Nouvelle conversation"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "Aucune clé API disponible"
msgid "No API keys match your search"
msgstr "Aucune clé API ne correspond à votre recherche"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "Aucune variable trouvée"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "maintenant"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr ""
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "Lecture seule — géré par Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "Recevoir un email contenant un lien de mise à jour du mot de passe"
msgid "Recent Events (oldest → newest)"
msgstr "Événements récents (du plus ancien au plus récent)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "Réordonner les options"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "Répondre"
@@ -11743,6 +11815,11 @@ msgstr "Répondre"
msgid "Reply to all"
msgstr "Répondre à tous"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "Renvoyer l'email"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "Réinitialiser"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "Réinitialiser à"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "Enregistrer"
msgid "Save as new view"
msgstr "Enregistrer comme nouvelle vue"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "Générez le squelette d'une nouvelle application, puis utilisez la CLI pour développer, publier et distribuer"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "Rechercher un agent..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "Sélectionnez les modèles qui apparaissent comme recommandés dans le s
msgid "Select your preferred language"
msgstr "Sélectionnez votre langue préférée"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "Objet"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "Invite système"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "Invite système ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14134,6 +14214,11 @@ msgstr ""
msgid "This week"
msgstr "Cette semaine"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14249,6 +14334,7 @@ msgstr "titre"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "À"
@@ -14550,7 +14636,6 @@ msgstr "Configuration de l'authentification à deux facteurs terminée avec succ
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14573,6 +14658,11 @@ msgstr "Tapez '/' pour les commandes, '@' pour les mentions"
msgid "Type anything..."
msgstr "Tapez n'importe quoi..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14900,6 +14990,11 @@ msgstr "Passez à un forfait supérieur pour y accéder"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15336,7 +15431,6 @@ msgstr "Afficher les journaux"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "Voir la page de la marketplace"
@@ -15350,6 +15444,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "Voir les Discussions AI Précédentes"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15944,6 +16043,11 @@ msgstr "Vous appartenez déjà à cet espace de travail"
msgid "You are not allowed to create records for this object"
msgstr "Vous n'êtes pas autorisé à créer des enregistrements pour cet objet"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16019,10 +16123,10 @@ msgstr "Votre compte a été activé."
msgid "Your app version is out of date. Please refresh the page."
msgstr "Votre version de l'application est obsolète. Veuillez rafraîchir la page."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "Vos applications"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+138 -34
View File
@@ -316,6 +316,11 @@ msgstr "{jobCount, plural, one {זה יסיר אותה מהתור לצמיתות
msgid "{jobCount, plural, one {This will retry the selected job. It will be re-executed from the beginning.} other {This will retry the selected jobs. They will be re-executed from the beginning.}}"
msgstr "{jobCount, plural, one {זה ינסה להפעיל מחדש את העבודה הנבחרת. היא תבוצע שוב מההתחלה.} two {זה ינסה להפעיל מחדש את העבודות הנבחרות. הן תבוצענה שוב מההתחלה.} many {זה ינסה להפעיל מחדש את העבודות הנבחרות. הן תבוצענה שוב מההתחלה.} other {זה ינסה להפעיל מחדש את העבודות הנבחרות. הן תבוצענה שוב מההתחלה.}}"
#. js-lingui-id: Y32cMj
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadIntermediaryMessages.tsx
msgid "{messagesLength} emails"
msgstr ""
#. js-lingui-id: Koe99p
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationItemTableRow.tsx
#: src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -451,11 +456,13 @@ msgstr "{workspaceMemberName} יוסר מהתפקיד הבא:"
msgid "••••••••"
msgstr "••••••••"
#. js-lingui-id: tD9raa
#. js-lingui-id: SMgdEJ
#. placeholder {0}: formatNumber(preview.estimatedTokenCount, { abbreviate: true, decimals: 1, })
#. placeholder {0}: formatNumber( section.estimatedTokenCount, { abbreviate: true, decimals: 1, }, )
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~{0} tokens"
msgstr "~{0} אסימונים"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "~ {0} tokens"
msgstr ""
#. js-lingui-id: Cx0xl3
#: src/modules/workflow/workflow-steps/workflow-actions/delay-actions/components/WorkflowEditActionDelay.tsx
@@ -1702,6 +1709,7 @@ msgstr "אירעה שגיאה בעת העלאת התמונה."
#: src/modules/views/hooks/internal/usePerformViewAPIPersist.ts
#: src/modules/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts
#: src/modules/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets.ts
#: src/modules/page-layout/hooks/useResetPageLayoutWidgetToDefault.ts
#: src/modules/object-metadata/hooks/useUpdateOneObjectMetadataItem.ts
#: src/modules/object-metadata/hooks/useUpdateOneFieldMetadataItem.ts
#: src/modules/object-metadata/hooks/useDeleteOneObjectMetadataItem.ts
@@ -1984,6 +1992,11 @@ msgstr "דומיינים מאושרים"
msgid "Apps"
msgstr "אפליקציות"
#. js-lingui-id: dEnE1D
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Apps made by other developers published on npm"
msgstr ""
#. js-lingui-id: 8HV3WN
#: src/pages/settings/profile/appearance/components/LocalePicker.tsx
msgid "Arabic"
@@ -2408,6 +2421,12 @@ msgstr "כתובת URL בסיסית"
msgid "Base URL is required"
msgstr "נדרשת כתובת URL בסיסית"
#. js-lingui-id: /xLNEx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Bcc"
msgstr ""
#. js-lingui-id: PFohi3
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "BCC"
@@ -2711,9 +2730,11 @@ msgstr "לא ניתן לסרוק? העתק את"
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx
#: src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/settings/components/SaveAndCancelButtons/CancelButton.tsx
#: src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Cancel"
msgstr "בטל"
@@ -2753,6 +2774,11 @@ msgstr "ביטול החלפת תכנית"
msgid "Cancel plan switching?"
msgstr "האם לבטל את החלפת התכנית?"
#. js-lingui-id: AnRu/j
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Cancel reply"
msgstr ""
#. js-lingui-id: N6gPiD
#: src/pages/settings/enterprise/SettingsEnterprise.tsx
#: src/modules/settings/billing/components/SettingsBillingContent.tsx
@@ -2821,11 +2847,22 @@ msgstr "קטלאנית"
msgid "Category"
msgstr "קטגוריה"
#. js-lingui-id: RpYfjZ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc"
msgstr ""
#. js-lingui-id: XdZeJk
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
msgid "CC"
msgstr "CC"
#. js-lingui-id: Dgsw8A
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Cc/Bcc"
msgstr ""
#. js-lingui-id: tHntRt
#: src/modules/page-layout/widgets/standalone-rich-text/components/DashboardEditorSideMenu.tsx
#: src/modules/blocknote-editor/components/CustomSideMenu.tsx
@@ -3776,11 +3813,6 @@ msgstr "צור"
msgid "Create"
msgstr "צור"
#. js-lingui-id: 5XhrY3
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create & Develop"
msgstr "יצירה ופיתוח"
#. js-lingui-id: 8aATyU
#: src/modules/ai/components/suggested-prompts/default-suggested-prompts.ts
msgid "Create a dashboard"
@@ -3821,6 +3853,11 @@ msgstr "צור זרימת עבודה וחזור לכאן כדי לצפות בג
msgid "Create a workspace"
msgstr "צור מרחב עבודה"
#. js-lingui-id: /WlFSf
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Create an application"
msgstr ""
#. js-lingui-id: 8ZjIgO
#: src/modules/settings/roles/role-permissions/permission-flags/hooks/useSettingsRolePermissionFlagConfig.ts
msgid "Create and configure AI agents"
@@ -4794,6 +4831,7 @@ msgstr "תאר מה אתה רוצה שהבינה המלאכותית תעשה..."
#. js-lingui-id: Nu4oKW
#: src/pages/settings/data-model/SettingsObjectFieldEdit.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/ai/SettingsToolDetail.tsx
@@ -5339,16 +5377,16 @@ msgstr "יש להזין כתובת דוא\"ל תקינה"
msgid "Email or domain is already in blocklist"
msgstr "דוא\"ל או תחום כבר נמצאים ברשימת החסימה"
#. js-lingui-id: Xl929X
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Email sent successfully"
msgstr ""
#. js-lingui-id: jvneza
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Email support"
msgstr ""
#. js-lingui-id: +VjrH/
#: src/modules/side-panel/hooks/useOpenEmailThreadInSidePanel.ts
msgid "Email Thread"
msgstr "שרשור דוא\"ל"
#. js-lingui-id: LimKOG
#: src/pages/settings/security/SettingsSecurityApprovedAccessDomain.tsx
msgid "Email verification"
@@ -6433,6 +6471,12 @@ msgstr ""
msgid "Failed to save workspace instructions"
msgstr "אירע כשל בשמירת הנחיות סביבת העבודה"
#. js-lingui-id: Lo/GQ5
#: src/modules/activities/emails/hooks/useSendEmail.ts
#: src/modules/activities/emails/hooks/useSendEmail.ts
msgid "Failed to send email"
msgstr ""
#. js-lingui-id: aj02T8
#: src/modules/settings/admin-panel/health-status/maintenance-mode/components/SettingsAdminMaintenanceMode.tsx
msgid "Failed to set maintenance mode."
@@ -6924,6 +6968,11 @@ msgstr "קרדיטי הניסיון בחינם אזלו. הירשם כעת כד
msgid "French"
msgstr "צרפתית"
#. js-lingui-id: ejVYRQ
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "From"
msgstr ""
#. js-lingui-id: qR8gT9
#: src/modules/workflow/workflow-trigger/utils/cron-to-human/descriptors/getDayOfWeekDescription.ts
msgid "from {startDay} to {endDay}"
@@ -8571,7 +8620,7 @@ msgid "Loading skills..."
msgstr "טוען מיומנויות..."
#. js-lingui-id: 7YK6ap
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadWidget.tsx
msgid "Loading thread"
msgstr "טוען שרשור"
@@ -9223,10 +9272,10 @@ msgstr "mySkill"
#: src/pages/settings/developers/api-keys/SettingsDevelopersApiKeyDetail.tsx
#: src/pages/settings/data-model/SettingsObjectFieldTable.tsx
#: src/pages/settings/data-model/constants/SettingsObjectTableMetadata.ts
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationGeneralTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationNameDescriptionTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTable.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
@@ -9392,6 +9441,11 @@ msgstr "צ'אט חדש"
msgid "New conversation"
msgstr "שיחה חדשה"
#. js-lingui-id: 3RwJHq
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
msgid "New Email"
msgstr ""
#. js-lingui-id: wqoYqp
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
#: src/pages/settings/emailing-domains/SettingsNewEmailingDomain.tsx
@@ -9590,6 +9644,11 @@ msgstr "אין מפתחות API זמינים"
msgid "No API keys match your search"
msgstr "לא נמצאו מפתחות API תואמים לחיפוש שלך"
#. js-lingui-id: /VRg8Z
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "No application found"
msgstr ""
#. js-lingui-id: rxBnh8
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
msgid "No applications available"
@@ -10018,6 +10077,7 @@ msgid "No variables found"
msgstr "לא נמצאו משתנים"
#. js-lingui-id: OCektF
#: src/pages/settings/applications/SettingsApplicationDetails.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationDetailEnvironmentVariablesTable.tsx
msgid "No variables to set for this application"
msgstr ""
@@ -10133,6 +10193,11 @@ msgstr "עכשיו"
msgid "Npm package"
msgstr ""
#. js-lingui-id: p7abaY
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "NPM packages"
msgstr ""
#. js-lingui-id: VVexZo
#: src/modules/advanced-text-editor/extensions/slash-command/DefaultSlashCommands.ts
msgid "number"
@@ -11357,10 +11422,11 @@ msgstr ""
msgid "Read your profile"
msgstr "קריאת הפרופיל שלך"
#. js-lingui-id: tCXcL7
#. js-lingui-id: 6pSHJ5
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only — managed by Twenty"
msgstr "קריאה בלבד — מנוהל על ידי Twenty"
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "Read-only"
msgstr ""
#. js-lingui-id: W+ApAD
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
@@ -11382,6 +11448,11 @@ msgstr "\\"
msgid "Recent Events (oldest → newest)"
msgstr "אירועים אחרונים (ישן → חדש)"
#. js-lingui-id: yPrbsy
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Recipients"
msgstr ""
#. js-lingui-id: b2+5uV
#: src/modules/settings/admin-panel/ai/components/SettingsAdminAI.tsx
msgid "Recommended Models"
@@ -11733,7 +11804,8 @@ msgid "Reorder options"
msgstr "סדר אופציות מחדש"
#. js-lingui-id: ImOQa9
#: src/modules/side-panel/pages/message-thread/components/SidePanelMessageThreadPage.tsx
#: src/modules/side-panel/hooks/useOpenComposeEmailInSidePanel.ts
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailThreadBottomBar.tsx
msgid "Reply"
msgstr "תגובה"
@@ -11743,6 +11815,11 @@ msgstr "תגובה"
msgid "Reply to all"
msgstr "השב לכולם"
#. js-lingui-id: fiPYZo
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
msgid "Reply..."
msgstr ""
#. js-lingui-id: tbmZmI
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
msgid "Report and issue"
@@ -11768,6 +11845,7 @@ msgstr "שלח שוב את הדוא\"ל"
#. js-lingui-id: OfhWJH
#: src/pages/settings/admin-panel/SettingsAdminConfigVariableDetails.tsx
#: src/modules/views/components/ViewBarDetails.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "Reset"
msgstr "איפוס"
@@ -11788,6 +11866,8 @@ msgid "Reset to"
msgstr "\\"
#. js-lingui-id: L+rMC9
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
#: src/modules/settings/data-model/fields/forms/address/components/SettingsDataModelFieldAddressForm.tsx
#: src/modules/command-menu-item/server-items/edit/components/SidePanelCommandMenuItemEditPage.tsx
msgid "Reset to default"
@@ -12086,11 +12166,6 @@ msgstr "שמור"
msgid "Save as new view"
msgstr "שמור כתצוגה חדשה"
#. js-lingui-id: veLq3R
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Scaffold a new app, then use the CLI to develop, publish, and distribute"
msgstr "צור שלד לאפליקציה חדשה, ולאחר מכן השתמש ב-CLI כדי לפתח, לפרסם ולהפיץ"
#. js-lingui-id: gmB6oO
#: src/modules/workflow/workflow-trigger/components/CronExpressionHelper.tsx
msgid "Schedule"
@@ -12232,6 +12307,7 @@ msgid "Search an agent..."
msgstr "חפש סוכן..."
#. js-lingui-id: fGTI3o
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationsAvailableTab.tsx
#: src/pages/settings/applications/components/SettingsApplicationsTable.tsx
msgid "Search an application"
@@ -12686,6 +12762,13 @@ msgstr "בחרו אילו מודלים יופיעו כמומלצים בבורר
msgid "Select your preferred language"
msgstr "\\"
#. js-lingui-id: JlFcis
#: src/modules/side-panel/pages/compose-email/components/SidePanelComposeEmailPage.tsx
#: src/modules/page-layout/widgets/email-thread/components/EmailThreadComposer.tsx
#: src/modules/activities/emails/components/EmailComposer.tsx
msgid "Send"
msgstr ""
#. js-lingui-id: mjK8F3
#: src/pages/settings/members/SettingsWorkspaceMembers.tsx
msgid "Send an invite email to your team"
@@ -13401,6 +13484,8 @@ msgstr ""
#. js-lingui-id: UJmAAK
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Subject"
msgstr "נושא"
@@ -13641,11 +13726,6 @@ msgstr ""
msgid "System Prompt"
msgstr "הנחיית מערכת"
#. js-lingui-id: BXGTWI
#: src/pages/settings/ai/SettingsAIPrompts.tsx
msgid "System Prompt ({totalTokenCount})"
msgstr "הנחיית מערכת ({totalTokenCount})"
#. js-lingui-id: k+7QWO
#: src/modules/settings/data-model/object-details/components/SettingsObjectRelationsTable.tsx
msgid "System relations"
@@ -14132,6 +14212,11 @@ msgstr ""
msgid "This week"
msgstr "השבוע"
#. js-lingui-id: VbVocX
#: src/modules/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings.tsx
msgid "This will cancel all modifications done on the widget. This action cannot be undone."
msgstr ""
#. js-lingui-id: h4VeOo
#: src/modules/settings/billing/hooks/useBillingWording.ts
msgid "This will cancel the scheduled interval change and keep your current billing interval ({currentIntervalLabel})."
@@ -14247,6 +14332,7 @@ msgstr "כותרת"
#. js-lingui-id: /jQctM
#: src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionEmailBase.tsx
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "To"
msgstr "אל"
@@ -14548,7 +14634,6 @@ msgstr "הגדרת האימות הדו-שלבי הושלמה בהצלחה!"
#. js-lingui-id: +zy2Nq
#: src/pages/settings/data-model/SettingsObjectIndexTable.tsx
#: src/pages/settings/applications/components/SettingsApplicationDataTableRow.tsx
#: src/pages/settings/ai/constants/SettingsSkillTableMetadata.ts
#: src/pages/settings/ai/constants/SettingsAiAgentTableMetadata.ts
#: src/pages/settings/ai/components/SettingsToolParameterTable.tsx
@@ -14571,6 +14656,11 @@ msgstr "הקלד/י '/' עבור פקודות, '@' עבור אזכורים"
msgid "Type anything..."
msgstr "הקלד כל דבר..."
#. js-lingui-id: LaEX5I
#: src/modules/activities/emails/components/EmailComposerFields.tsx
msgid "Type something or press \"/\" to see commands"
msgstr ""
#. js-lingui-id: UhqKcC
#: src/modules/navigation-menu-item/edit/side-panel/components/SidePanelNewSidebarItemRecordSubPage.tsx
msgid "Type to search records"
@@ -14898,6 +14988,11 @@ msgstr "שדרגו כדי לגשת"
msgid "Upgrade to Enterprise to access audit logs."
msgstr ""
#. js-lingui-id: D+7y/3
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "Upgrade to Enterprise to share private applications."
msgstr ""
#. js-lingui-id: +Gi3x1
#: src/pages/settings/applications/SettingsAvailableApplicationDetails.tsx
#: src/pages/settings/applications/components/SettingsApplicationVersionContainer.tsx
@@ -15334,7 +15429,6 @@ msgstr "צפה ביומנים"
#. js-lingui-id: 7PrSCy
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View marketplace page"
msgstr "צפייה בדף המרקטפלייס"
@@ -15348,6 +15442,11 @@ msgstr ""
msgid "View Previous AI Chats"
msgstr "הצג שיחות AI קודמות"
#. js-lingui-id: NnJpTN
#: src/pages/settings/applications/tabs/SettingsApplicationRegistrationDistributionTab.tsx
msgid "View private application page"
msgstr ""
#. js-lingui-id: hAAsm/
#: src/modules/workflow/workflow-steps/workflow-actions/ai-agent-action/components/WorkflowEditActionAiAgent.tsx
msgid "View role"
@@ -15942,6 +16041,11 @@ msgstr "אתה כבר משתייך לסביבת העבודה הזו"
msgid "You are not allowed to create records for this object"
msgstr "אין לך הרשאה ליצור רשומות באובייקט זה"
#. js-lingui-id: iibZbD
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "You can either create a private app or share it to others"
msgstr ""
#. js-lingui-id: CNAoaw
#: src/modules/workflow/workflow-steps/workflow-actions/logic-function-action/components/WorkflowEditActionLogicFunction.tsx
msgid "You can see the function logic in your application settings."
@@ -16017,10 +16121,10 @@ msgstr "החשבון שלך הופעל."
msgid "Your app version is out of date. Please refresh the page."
msgstr "גרסת האפליקציה שלך אינה מעודכנת. אנא רענן את הדף."
#. js-lingui-id: oNUh7z
#. js-lingui-id: 9pWhO+
#: src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx
msgid "Your Apps"
msgstr "האפליקציות שלך"
msgid "Your apps"
msgstr ""
#. js-lingui-id: +5YqGH
#: src/modules/onboarding/constants/OnboardingSyncEmailsOptions.ts

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