---
order: 2
section: guides
title: Configuration
description: >-
  Toutes les options de scribe.config.ts : paramètres du projet, types de
  contenu, marqueurs de champs et routage des langues.
noindex: false
canonicalPath: /fr/docs/configuration
---
Tout est centralisé dans un seul fichier, `scribe.config.ts`, qui exporte `defineConfig({...})`. Le moteur d'exécution (`createScribe`) et la CLI (qui détecte `scribe.config.ts` dans le répertoire de travail) exploitent ce même fichier.  

## Options du projet

```ts
export default defineConfig({
  rootDir: ".",
  contentDir: "content",             // default
  store: ".scribe/store.sqlite",     // default
  assetsDir: "public",               // optional
  locales: ["en", "fr", "de"],
  defaultLocale: "en",               // default
  localeRouting: { strategy: "path-prefix", prefixDefaultLocale: false },
  localeFallbacks: true,             // default
  localePresets: { active: ["fr"] },
  translate: { /* see the translation page */ },
  types: [ /* defineContentType(...) */ ],
});
```

| Option | Par défaut | Description |
| --- | --- | --- |
| `rootDir` | (requis) | Racine du projet. Privilégiez un chemin relatif (généralement `"."`) : la CLI le résout par rapport au dossier du fichier de configuration, et `createScribe` par rapport à `process.cwd()`. Évitez de le construire avec `import.meta.url` : les bundlers intègrent ce chemin lors de la compilation, ce qui provoque des erreurs sur les hébergements serverless comme Vercel. |
| `contentDir` | `"content"` | Répertoire contenant un dossier par type de contenu. |
| `store` | `".scribe/store.sqlite"` | Base de données de traduction SQLite. **Versionnez-la (commit) ; n'ajoutez pas `.scribe/` à votre fichier gitignore.** |
| `assetsDir` | (aucun) | Racine des fichiers statiques (par exemple `"public"`). Si elle est définie, `scribe validate` signale les chemins d'images inexistants dans le frontmatter ou le contenu. |
| `locales` | (requis) | Toutes les langues prises en charge, y compris celle par défaut. |
| `defaultLocale` | `"en"` | Langue source canonique. Doit figurer dans `locales`. |
| `localeRouting` | path-prefix, sans préfixe par défaut | Comment les marqueurs de langue s'affichent dans les URL générées. `path-prefix` ajoute la langue en préfixe (en omettant la langue par défaut sauf si `prefixDefaultLocale` est sur true). `search-param` ajoute `?param=locale` pour les autres langues. |
| `localeFallbacks` | `true` | Déduit les chaînes de repli à partir des balises de langue : une variante régionale sans traduction reçoit la traduction la plus proche dans la langue de base (par exemple, `pt-BR` se rabat sur `pt`) avant d'utiliser la langue par défaut. Réglez sur `false` pour désactiver ce comportement. Voir [Chaînes de repli des langues](#locale-fallback-chains). |
| `localePresets` | (aucun) | Groupes de langues nommés pour la commande `scribe translate --preset name`. |
| `translate` | (aucun) | Paramètres de traduction par défaut pour l'ensemble du projet ([traduction](/docs/translation)). |
| `types` | (requis) | Définitions des types de contenu. |

Les configurations sont validées en amont : une valeur `defaultLocale` inconnue, des identifiants de type en double ou un modèle `path` mal formulé déclenchent immédiatement une erreur accompagnée d'un message explicite.

## Options des types de contenu

```ts
defineContentType({
  id: "blog",
  schema: blogSchema,
  path: "/blog/{slug}",
  contentDir: "blog",          // default: the id
  slugStrategy: "localized",   // default: "fixed"
  indexFallback: "en",         // default: "en" if path is set, else "none"
  orderBy: "-publishedAt",     // default: "slug"
  label: "Blog",               // default: capitalized id (studio UI only)
  crossValidate: (data, ctx) => [],
  translate: { /* per-type overrides */ },
})
```

| Option | Description |
| --- | --- |
| `id` | Identifiant unique. Devient l'accesseur typé (`scribe.blog`) et le `contentDir` par défaut. |
| `schema` | Schéma d'objet Zod pour le frontmatter, avec ses marqueurs de champs (voir ci-dessous). |
| `path` | Modèle d'URL contenant exactement un `{slug}` (par exemple `/blog/{slug}`). À omettre pour les types de contenu **strictement référentiels** (auteurs, catégories) qui ne possèdent pas leurs propres pages. |
| `contentDir` | Dossier situé dans le `contentDir` du projet et contenant les fichiers `.mdx` de ce type. |
| `slugStrategy` | `"fixed"` indique que toutes les langues utilisent le slug en anglais. `"localized"` indique que le traducteur génère un slug spécifique pour chaque langue (`/fr/blog/bonjour-le-monde`). |
| `indexFallback` | Ce que renvoie `resolve()` lorsqu'une langue ne possède aucune traduction : `"en"` fournit le document en anglais (avec `actualLocale: "en"`), et `"none"` ne renvoie rien. |
| `orderBy` | Tri par défaut pour `list()` : `"slug"`, `"publishedAt"`, `"-publishedAt"`, `"updatedAt"`, `"-updatedAt"`, ou un comparateur `(a, b) => number` sur des documents entièrement typés. |
| `crossValidate` | Validation supplémentaire exécutée par `scribe validate`, qui reçoit le frontmatter analysé et typé. Doit retourner `{ field, message, level }[]`. |
| `translate` | Instructions, règles ou modèle de traduction spécifiques à ce type ([traduction](/docs/translation)). |

## Marqueurs de champs

Chaque champ du schéma appartient à l'une des trois catégories suivantes. Les champs sans marqueur sont **structurels** par défaut.

```ts
import { field } from "scribe-cms";

const schema = z.object({
  // Envoyé au traducteur, stocké par langue :
  title: field.translatable(z.string().min(1)),

  // Uniquement en anglais ; copié du document EN vers chaque langue :
  heroImage: field.structural(z.string().optional()),

  // Référence(s) de slug en anglais vers un autre type de contenu :
  author: field.relation("author"),
  relatedPosts: field.relation("blog", { multiple: true, max: 4, optional: true }),
});
```

Les marqueurs traduisibles fonctionnent également sur les champs imbriqués dans des tableaux simples ou des objets (par exemple `sections.*.title`). Il suffit de ne pas envelopper le tableau conteneur avec `field.structural`, sinon l'intégralité de la sous-arborescence sera limitée à l'anglais.

### `field.relation(typeId, options?)`

| Option | Par défaut | Description |
| --- | --- | --- |
| `multiple` | `false` | Le champ est un tableau de slugs. |
| `optional` | `false` | Le champ peut être omis. La fonction `related()` renvoie alors `null` (pour un élément unique) ou ignore les éléments manquants (pour les éléments multiples). |
| `min` / `max` | (aucun) | Limites de la quantité d'éléments (uniquement si `multiple: true`). |

Les contraintes s'insèrent dans l'objet d'options, et **non** via des méthodes Zod chaînées. Un chaînage (comme `.max(8)` ou `.optional()`) clone le schéma et supprimerait les métadonnées de la relation.

Les relations stockent systématiquement les **slugs en anglais**. Elles sont vérifiées par `scribe validate` (une relation obligatoire pointant dans le vide bloque la compilation, tandis qu'une relation facultative orpheline génère un avertissement), et elles sont déréférencées à l'exécution avec `related()`. Consultez l'[API d'exécution](/docs/runtime-api).

## Chaînes de repli des langues

Par défaut, une langue régionale dépourvue de traduction pour un document se voit proposer sa langue de base avant la langue par défaut. Chaque langue teste successivement les préfixes plus courts de sa propre balise qui figurent également dans `locales`. Ainsi, `fr-CA` se rabat sur `fr`, et `zh-Hant-TW` essaie `zh-Hant`, puis `zh`. Réglez `localeFallbacks: false` pour désactiver cette fonction. La langue par défaut n'appartient jamais à une chaîne de repli. Elle demeure le recours ultime, régi par la propriété `indexFallback` du type de contenu.

Ces replis s'appliquent à `resolve()` (la langue servie est indiquée dans `actualLocale` et les redirections de slugs utilisent le slug de la langue de repli) ainsi qu'à `staticParams()` (les slugs pré-rendus correspondent à ce que sert `resolve()`). Ils ne s'appliquent volontairement **pas** à `get()`, `list()`, `translation()`, `alternates()` ni au sitemap : ceux-ci conservent une correspondance exacte.

## Types clients typés

Pour les alias de types côté application, déduisez tout depuis la configuration :

```ts
import type { ScribeClient, ScribeDocs } from "scribe-cms/runtime";
import config from "./scribe.config";

type MyScribe = ScribeClient<typeof config>;
type BlogDoc = ScribeDocs<typeof config>["blog"];
```
