i18n - docs translations (#21789)

Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
github-actions[bot]
2026-06-18 15:21:04 +02:00
committed by GitHub
parent 22baf2c6c5
commit 2b3b2362db
704 changed files with 38268 additions and 9002 deletions
@@ -0,0 +1,50 @@
---
title: Extension des objets
description: Ajoutez des champs aux objets standard de Twenty (Person, Company, …) ou aux objets d'autres applications en utilisant defineField.
icon: wand-magic-sparkles
---
Utilisez `defineField()` pour ajouter un champ à un objet que vous ne possédez pas — un objet standard de Twenty comme Person ou Company, ou un objet fourni par une autre application installée. Contrairement aux champs en ligne déclarés à l'intérieur de [`defineObject`](/l/fr/developers/extend/apps/data/objects), les champs autonomes nécessitent un `objectUniversalIdentifier` pour préciser l'objet qu'ils étendent.
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
objectUniversalIdentifier: '701aecb9-eb1c-4d84-9d94-b954b231b64b', // Company object
name: 'loyaltyTier',
type: FieldType.SELECT,
label: 'Loyalty Tier',
icon: 'IconStar',
options: [
{ value: 'BRONZE', label: 'Bronze', position: 0, color: 'orange' },
{ value: 'SILVER', label: 'Silver', position: 1, color: 'gray' },
{ value: 'GOLD', label: 'Gold', position: 2, color: 'yellow' },
],
});
```
## Points clés
* `objectUniversalIdentifier` identifie l'objet cible. Pour les objets standard de Twenty, importez la constante depuis `twenty-sdk` :
```ts
import { STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS } from 'twenty-sdk/define';
// STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.company.universalIdentifier
// STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.person.universalIdentifier
// STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.opportunity.universalIdentifier
// …
```
* Lorsque vous définissez des champs **en ligne dans `defineObject()`**, vous n'avez **pas** besoin de `objectUniversalIdentifier` — il est hérité de l'objet parent.
* `defineField()` est la seule manière d'ajouter des champs à des objets que vous n'avez pas créés avec `defineObject()`.
* Lemplacement du fichier est à votre discrétion. La convention est `src/fields/\<name>.field.ts`, mais le SDK détecte les champs n'importe où dans `src/`.
* Pour ajouter un onglet à une mise en page standard (par exemple la page de détail de Task ou de Company), utilisez [`definePageLayoutTab`](/l/fr/developers/extend/apps/layout/page-layouts#definepagelayouttab) avec `STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS` depuis `twenty-sdk/define`.
## Ajouter une relation à un objet existant
Pour ajouter un champ de relation (par exemple pour lier votre objet personnalisé à un `Person` standard), utilisez `defineField()` avec `FieldType.RELATION`. Le modèle est le même que pour les relations en ligne, mais avec `objectUniversalIdentifier` défini explicitement. Voir [Relations](/l/fr/developers/extend/apps/data/relations) pour le modèle bidirectionnel.
@@ -0,0 +1,104 @@
---
title: Objets
description: Déclarez de nouveaux types denregistrements — des tables personnalisées avec leurs propres champs — à laide de defineObject.
icon: table
---
Les **objets** personnalisés sont de nouveaux types denregistrements que votre application ajoute à un espace de travail — carte postale, facture, abonnement, tout ce qui est spécifique à votre domaine. Chaque objet déclare son schéma (champs, relations, valeurs par défaut) et un identifiant universel stable qui survit aux synchronisations et aux déploiements.
```ts src/objects/post-card.object.ts
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
SENT = 'SENT',
DELIVERED = 'DELIVERED',
RETURNED = 'RETURNED',
}
export default defineObject({
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
nameSingular: 'postCard',
namePlural: 'postCards',
labelSingular: 'Post Card',
labelPlural: 'Post Cards',
description: 'A post card object',
icon: 'IconMail',
fields: [
{
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
name: 'content',
type: FieldType.TEXT,
label: 'Content',
description: "Postcard's content",
icon: 'IconAbc',
},
{
universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
name: 'recipientName',
type: FieldType.FULL_NAME,
label: 'Recipient name',
icon: 'IconUser',
},
{
universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
name: 'recipientAddress',
type: FieldType.ADDRESS,
label: 'Recipient address',
icon: 'IconHome',
},
{
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
name: 'status',
type: FieldType.SELECT,
label: 'Status',
icon: 'IconSend',
defaultValue: `'${PostCardStatus.DRAFT}'`,
options: [
{ value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' },
{ value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' },
{ value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' },
{ value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' },
],
},
{
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
name: 'deliveredAt',
type: FieldType.DATE_TIME,
label: 'Delivered at',
icon: 'IconCheck',
isNullable: true,
defaultValue: null,
},
],
});
```
## Points clés
* Le `universalIdentifier` doit être unique et stable entre les déploiements.
* Chaque champ nécessite un `name`, un `type`, un `label` et son propre `universalIdentifier` stable.
* Le tableau `fields` est facultatif — vous pouvez définir des objets sans champs personnalisés.
* Les champs en ligne définis ici nont **pas** besoin dun `objectUniversalIdentifier` — il est hérité de lobjet parent. Utilisez [`defineField()`](/l/fr/developers/extend/apps/data/extending-objects) pour ajouter des champs aux objets que vous ne possédez pas.
* Vous pouvez générer de nouveaux objets avec `yarn twenty dev:add object`, qui vous guide à travers le nommage, les champs et les relations. Voir [Architecture → Scaffolding entities](/l/fr/developers/extend/apps/getting-started/scaffolding).
<Note>
**Les champs de base sont ajoutés automatiquement.** Lorsque vous définissez un objet personnalisé, Twenty crée pour vous des champs standard comme `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` et `deletedAt`. Vous navez pas besoin de les déclarer dans votre tableau `fields` — uniquement vos champs personnalisés. Vous pouvez remplacer un champ par défaut en en déclarant un avec le même nom, mais cest rarement une bonne idée.
</Note>
## Valeurs par défaut
Les valeurs par défaut de type chaîne littérale doivent être entourées de guillemets simples **à lintérieur** de la chaîne — `defaultValue: "'Draft'"`, et non `defaultValue: "Draft"`. Cest pourquoi le champ `status` ci-dessus utilise `` `'${PostCardStatus.DRAFT}'` ``.
Les chaînes sans guillemets sont réservées aux valeurs par défaut calculées, évaluées lors de la création dun enregistrement :
* `'uuid'` — génère un UUID (pour les champs `UUID`)
* `'now'` — lhorodatage actuel (pour les champs `DATE_TIME`)
La même convention sapplique aux sous-champs de type chaîne des valeurs par défaut composites (par exemple `{ source: "'MANUAL'" }` sur un champ `ACTOR`) ainsi quaux valeurs `SELECT`/`MULTI_SELECT`. Une valeur par défaut littérale de type chaîne laissée sans guillemets génère un avertissement lors de la compilation de votre application.
## Et après
* **Connectez cet objet aux autres** — voir [Relations](/l/fr/developers/extend/apps/data/relations) pour le modèle de relation bidirectionnelle.
* **Ajoutez des champs aux objets dautres applications** — voir [Extending Objects](/l/fr/developers/extend/apps/data/extending-objects) pour `defineField()`.
* **Affichez cet objet dans linterface utilisateur** — voir [Views](/l/fr/developers/extend/apps/layout/views) et [Navigation Menu Items](/l/fr/developers/extend/apps/layout/navigation-menu-items) pour lajouter à la barre latérale.
@@ -0,0 +1,97 @@
---
title: Vue d'ensemble
description: Façonnez les données que votre application ajoute à un espace de travail — objets, champs et relations.
icon: database
---
La **couche de données** dune application Twenty correspond aux données que votre application *ajoute* à un espace de travail — les nouveaux types denregistrements quelle déclare, les colonnes quelle ajoute aux objets existants et la manière dont ces enregistrements sont reliés les uns aux autres.
```text
┌──────────────────────────────────────────────────┐
│ Object — a record type, e.g. PostCard │
│ ├─ Field (name, type, label) │
│ ├─ Field │
│ └─ Relation (link to another object) │
└──────────────────────────────────────────────────┘
├── lives in your app, OR
┌──────────────────────────────────────────────────┐
│ Standard / other apps' objects │
│ └─ Field added by your app via defineField │
└──────────────────────────────────────────────────┘
```
## Dans cette section
<CardGroup cols={2}>
<Card title="Objets" icon="table" href="/l/fr/developers/extend/apps/data/objects">
`defineObject` — déclarez de nouveaux types denregistrements avec leurs propres champs.
</Card>
<Card title="Extension des objets" icon="wand-magic-sparkles" href="/l/fr/developers/extend/apps/data/extending-objects">
`defineField` — ajoutez des champs aux objets standard ou à ceux dautres applications.
</Card>
<Card title="Relations" icon="diagram-project" href="/l/fr/developers/extend/apps/data/relations">
Connexions bidirectionnelles `MANY_TO_ONE` / `ONE_TO_MANY` entre objets.
</Card>
</CardGroup>
## Aperçu des entités
| Entité | Objectif | Défini avec |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| **Objet** | Un nouveau type denregistrement personnalisé (par ex. PostCard, Invoice) avec ses propres champs | `defineObject()` |
| **Champ** | Une colonne dun objet. Les champs autonomes peuvent étendre des objets que vous navez pas créés (par ex. ajouter `loyaltyTier` à Company) | `defineField()` |
| **Relation** | Un lien bidirectionnel entre deux objets — les deux côtés étant déclarés comme des champs | `defineField()` avec `FieldType.RELATION` |
| **Index** | Un index de base de données pour accélérer une requête récurrente sur lun de vos objets | `defineIndex()` |
Le SDK les détecte via une analyse AST au moment de la compilation, donc lorganisation des fichiers vous appartient — la convention est `src/objects/`, `src/fields/` et `src/indexes/`. Des UUID `universalIdentifier` stables relient tout dun déploiement à lautre.
## Index (optionnels)
Les applications peuvent fournir des index avec leurs objets pour que les requêtes récurrentes restent rapides. Le cas le plus courant est une colonne de statut ou de clé étrangère que vous lisez fréquemment.
```ts src/indexes/post-card-status.index.ts
import { defineIndex } from 'twenty-sdk/define';
import {
POST_CARD_UNIVERSAL_IDENTIFIER,
STATUS_FIELD_UNIVERSAL_IDENTIFIER,
} from '../objects/post-card.object';
export default defineIndex({
universalIdentifier: 'b6e9d2a1-5a4c-46ca-9d52-42c8f02d1ff0',
objectUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
fields: [
{
universalIdentifier: 'b6e9d2a1-5a4c-46ca-9d52-42c8f02d1ff1',
fieldUniversalIdentifier: STATUS_FIELD_UNIVERSAL_IDENTIFIER,
},
],
});
```
### Index uniques
`defineIndex` accepte `isUnique: true` pour lunicité sur une ou plusieurs colonnes. Cest la primitive recommandée — `defineField({ isUnique: true })` est obsolète et sera supprimé dans une future version.
```ts
defineIndex({
universalIdentifier: '…',
objectUniversalIdentifier: PERSON_UNIVERSAL_IDENTIFIER,
isUnique: true,
fields: [{ universalIdentifier: '…', fieldUniversalIdentifier: EMAIL_FIELD_UNIVERSAL_IDENTIFIER }],
});
```
### Autres contraintes
* Les clauses `WHERE` partielles restent sous le contrôle de ladministrateur — les applications ne peuvent pas les déclarer.
* Chaque objet est limité à 10 index personnalisés (les index propres au framework ne comptent pas).
Ordonnez le tableau `fields` dans lordre dans lequel Postgres doit lutiliser — colonne la plus à gauche en premier, comme dans un annuaire téléphonique. Les index ne sont pas gratuits : chaque écriture dans la table les met à jour. Ajoutez-en un uniquement lorsque vous avez une requête qui en a besoin.
<Note>
Vous cherchez **Application Config** ou **Roles & Permissions** ? Ces éléments décrivent lapplication elle-même plutôt que les données quelle ajoute — ils se trouvent sous [Config](/l/fr/developers/extend/apps/config/overview). Vous cherchez **Connections** (Linear, GitHub, Slack OAuth) ? Ceux-ci existent pour être appelés *depuis* des fonctions logiques et se trouvent sous [Logic](/l/fr/developers/extend/apps/logic/connections).
</Note>
@@ -0,0 +1,160 @@
---
title: Relations
description: Reliez des objets entre eux avec des relations MANY_TO_ONE / ONE_TO_MANY bidirectionnelles.
icon: diagram-project
---
Les relations relient deux objets entre eux. Dans Twenty, les relations sont toujours **bidirectionnelles** — chaque relation a deux côtés, et chaque côté est déclaré comme un champ qui référence l'autre.
| Type de relation | Description | Possède une clé étrangère ? |
| ---------------- | ------------------------------------------------------------------------------------ | --------------------------- |
| `MANY_TO_ONE` | De nombreux enregistrements de cet objet pointent vers un enregistrement de la cible | Oui (`joinColumnName`) |
| `ONE_TO_MANY` | Un enregistrement de cet objet possède de nombreux enregistrements de la cible | Non (le côté inverse) |
## Fonctionnement des relations
Chaque relation nécessite **deux champs** qui se référencent mutuellement :
1. Le côté **MANY_TO_ONE** — réside sur l'objet qui détient la clé étrangère.
2. Le côté **ONE_TO_MANY** — réside sur l'objet qui possède la collection.
Les deux champs utilisent `FieldType.RELATION` et se référencent mutuellement via `relationTargetFieldMetadataUniversalIdentifier`.
## Exemple : une carte postale a de nombreux destinataires
Un `PostCard` peut être envoyé à de nombreux enregistrements `PostCardRecipient`. Chaque destinataire appartient à exactement une carte postale.
**Étape 1: Définir le côté ONE_TO_MANY sur PostCard** (le côté "one") :
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
// Export so the other side can reference it
export const POST_CARD_RECIPIENTS_FIELD_ID = 'a1111111-1111-1111-1111-111111111111';
// Import from the other side
import { POST_CARD_FIELD_ID } from './post-card-on-post-card-recipient.field';
export default defineField({
universalIdentifier: POST_CARD_RECIPIENTS_FIELD_ID,
objectUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
type: FieldType.RELATION,
name: 'postCardRecipients',
label: 'Post Card Recipients',
icon: 'IconUsers',
relationTargetObjectMetadataUniversalIdentifier: POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER,
relationTargetFieldMetadataUniversalIdentifier: POST_CARD_FIELD_ID,
universalSettings: {
relationType: RelationType.ONE_TO_MANY,
},
});
```
**Étape 2: Définir le côté MANY_TO_ONE sur PostCardRecipient** (le côté "many" — détient la clé étrangère) :
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
// Export so the other side can reference it
export const POST_CARD_FIELD_ID = 'b2222222-2222-2222-2222-222222222222';
// Import from the other side
import { POST_CARD_RECIPIENTS_FIELD_ID } from './post-card-recipients-on-post-card.field';
export default defineField({
universalIdentifier: POST_CARD_FIELD_ID,
objectUniversalIdentifier: POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER,
type: FieldType.RELATION,
name: 'postCard',
label: 'Post Card',
icon: 'IconMail',
relationTargetObjectMetadataUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
relationTargetFieldMetadataUniversalIdentifier: POST_CARD_RECIPIENTS_FIELD_ID,
universalSettings: {
relationType: RelationType.MANY_TO_ONE,
onDelete: OnDeleteAction.CASCADE,
joinColumnName: 'postCardId',
},
});
```
<Note>
**Imports circulaires :** les deux champs de relation se référencent l'un l'autre via leur `universalIdentifier`. Pour éviter les problèmes d'import circulaire, exportez les ID de vos champs en tant que constantes nommées depuis chaque fichier, puis importez-les dans l'autre. Le système de build les résout au moment de la compilation.
</Note>
## Relation avec des objets standard
Pour créer une relation avec un objet Twenty intégré (Person, Company, etc.), utilisez `STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS` :
```ts src/fields/person-on-self-hosting-user.field.ts
import {
defineField,
FieldType,
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
export const SELF_HOSTING_USER_REVERSE_FIELD_ID = 'd4444444-4444-4444-4444-444444444444';
export default defineField({
universalIdentifier: PERSON_FIELD_ID,
objectUniversalIdentifier: SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER,
type: FieldType.RELATION,
name: 'person',
label: 'Person',
description: 'Person matching with the self hosting user',
isNullable: true,
relationTargetObjectMetadataUniversalIdentifier:
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS.person.universalIdentifier,
relationTargetFieldMetadataUniversalIdentifier: SELF_HOSTING_USER_REVERSE_FIELD_ID,
universalSettings: {
relationType: RelationType.MANY_TO_ONE,
onDelete: OnDeleteAction.SET_NULL,
joinColumnName: 'personId',
},
});
```
## Propriétés des champs de relation
| Propriété | Obligatoire | Description |
| ------------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `type` | Oui | Doit être `FieldType.RELATION` |
| `relationTargetObjectMetadataUniversalIdentifier` | Oui | Le `universalIdentifier` de l'objet cible |
| `relationTargetFieldMetadataUniversalIdentifier` | Oui | Le `universalIdentifier` du champ correspondant sur l'objet cible |
| `universalSettings.relationType` | Oui | `RelationType.MANY_TO_ONE` ou `RelationType.ONE_TO_MANY` |
| `universalSettings.onDelete` | MANY_TO_ONE uniquement | Ce qui se passe lorsque l'enregistrement référencé est supprimé : `CASCADE`, `SET_NULL`, `RESTRICT` ou `NO_ACTION` |
| `universalSettings.joinColumnName` | MANY_TO_ONE uniquement | Nom de la colonne de base de données pour la clé étrangère (p. ex., `postCardId`) |
## Champs de relation en ligne
Vous pouvez également déclarer une relation directement à l'intérieur de [`defineObject`](/l/fr/developers/extend/apps/data/objects). Lorsqu'il est en ligne, omettez `objectUniversalIdentifier` — il est hérité de l'objet parent :
```ts
export default defineObject({
universalIdentifier: '...',
nameSingular: 'postCardRecipient',
// ...
fields: [
{
universalIdentifier: POST_CARD_FIELD_ID,
type: FieldType.RELATION,
name: 'postCard',
label: 'Post Card',
relationTargetObjectMetadataUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
relationTargetFieldMetadataUniversalIdentifier: POST_CARD_RECIPIENTS_FIELD_ID,
universalSettings: {
relationType: RelationType.MANY_TO_ONE,
onDelete: OnDeleteAction.CASCADE,
joinColumnName: 'postCardId',
},
},
// … other fields
],
});
```