Aller au contenu
Sonenta

Guide · Cycle de vie

Comment votre contenu arrive en production

Sonenta se place entre une clé dans votre code et la valeur que votre app récupère au runtime. Cette page parcourt tout le chemin : comment le contenu est créé, comment nommer les clés, les statuts qu'une valeur traverse, et comment confirmer qu'une langue est en ligne. Lisez-la une fois et évitez les tâtonnements.

Créer du contenu

Tout se fait depuis le CLI ou via MCP. Le dashboard est une option, pas la seule, et l'ancienne idée « la création se fait uniquement au dashboard » est obsolète.

Avec une clé API, via MCP (sans humain)

Une clé API mcp:* permet à votre agent de créer des namespaces (create_namespace) et des clés (create_key, ou create_keys_bulk jusqu'à 500 d'un coup, idempotent), et d'écrire des valeurs en masse depuis vos fichiers source avec sonenta push. Le CLI fait de même avec la même clé : sonenta namespaces create / list, et sonenta push auto-crée les namespaces manquants au passage (--no-create-namespaces pour désactiver ; CLI 0.46.0). Aucune connexion requise.

Ce qui exige une session compte

Créer un projet (sonenta projects create) ou une clé API (sonenta api-keys create) exige une session compte. Lancez sonenta login une fois : un flow device navigateur qu'un humain org-admin approuve une seule fois ; ensuite le token est stocké et s'auto-rafraîchit, donc votre agent enchaîne ces commandes sans nouvelle intervention. projects create accepte --slug, --description, --source-language (défaut en) et --org ; api-keys create exige --name et accepte --scopes (défaut mcp:*), --env, --projects et d'autres. Le secret de la clé API n'est affiché qu'une seule fois. Disponible depuis le CLI 0.32.0.

terminal
1# one-time: a human org-admin approves this once2sonenta login 4# then your agent can run, unattended:5sonenta projects create "My app" --source-language en6sonenta api-keys create --name "ci" --scopes mcp:*7#   the API-key secret is printed once, then never again

Pourquoi la création n'est pas un outil MCP

Créer des projets et des clés API sont des opérations org-admin, au niveau du compte. Elles vivent dans le CLI (session compte) et ne sont pas dans la surface MCP, par design : elles exigent un token de compte, pas une clé API, donc un agent porteur d'une simple clé API ne peut pas s'auto-générer projets ou clés. Cette frontière est voulue. En résumé : clés et namespaces = self-service agent via MCP ; projets et clés API = CLI après un sonenta login humain unique, puis en autonomie.

Comment nommer les clés

Une clé, ce sont deux champs distincts : un namespace (un slug, ex. common) et un name en dot-notation (ex. hero.title). Au runtime le SDK l'adresse sous la forme namespace:name. Les points regroupent les clés à l'intérieur d'un namespace ; ils ne sont pas le namespace.

key
1// namespace and name are SEPARATE fields2namespace "common" + name "title"        -> common:title3namespace "common" + name "hero.title"   -> common:hero.title4// the trap: the slug repeated inside the name5namespace "common" + name "common.title" -> common:common.title6//                                          ^ doubled namespace

Côté fichiers (sonenta push / pull), l'arborescence est locales/<lang>/<namespace>.json, clés à plat en dot-notation. Le nom de fichier porte déjà le namespace : ne re-préfixez pas chaque clé avec ce même slug, sinon vous le doublez.

Attrapé automatiquement

Ce n'est pas qu'un conseil de style. validate_translations signale un namespace doublé comme une entrée structural_issues[] ({namespace, key, issue, detail} avec issue: 'self_namespaced_key', plus counts.structural_issues). Le detail indique : "key '{key}' is prefixed by its own namespace '{ns}': this creates a redundant {ns}: {…} layer in the bundle, which makes the SDK silently fall back to the source locale. Remove the '{ns}.' prefix (store it as '{stripped}')." Le write-path le rejette aussi d'emblée : create_keys_bulk rejette l'item (self_namespaced_key), l'import i18next rejette l'unité (redundant_namespace_layer), et sonenta ci échoue dès que structural_issues n'est pas vide.

Les statuts qu'une valeur traverse

Une valeur traverse ces statuts. La publication commence à translated : tout ce qui est en dessous reste hors du CDN.

Un draft pur ne peut pas être approuvé en une étape (approve_translation renvoie not_approvable) : il doit d'abord atteindre translated. Le périmètre d'export par défaut (XLIFF, CSV) est de même translated,reviewed,approved et exclut le draft sauf demande.

Ce qui part au CDN

La publication (publish_cdn) construit un bundle par langue et namespace. Seuls les statuts publiables y entrent, et seulement les valeurs non vides.

Inclus

translated, reviewed, approved (tout à partir du seuil translated).

Exclus

draft, missing, rejected. Une valeur vide est ignorée aussi, même si son statut qualifierait.

Le garde-fou du bundle vide

C'est pourquoi un namespace 100% draft ne peut pas expédier du vide en silence. Si aucune clé d'un bundle n'est publiable, publish_cdn saute ce bundle (skipped: true, rien n'est écrasé) et renvoie une entrée warnings[] ({language_code, namespace, key_count, included_count, excluded_count, skipped, reason}). Le reason indique : "namespace '{ns}' / '{lang}': 0 of {N} keys are publishable: all are below 'translated' status (e.g. draft). The bundle is EMPTY: nothing will be served. Publish was SKIPPED for this bundle; set allow_empty=true to force an empty bundle." Passez allow_empty: true pour publier quand même le bundle vide (toujours signalé). En clair : vous ne pouvez pas vider par accident un namespace en ligne en publiant une pile de clés draft.

Confirmer qu'une langue est en ligne

Avant de publier : valider

Lancez validate_translations avant de publier pour attraper les problèmes de qualité tant qu'ils sont faciles à corriger. Sans payload, il audite les valeurs stockées (passez un payload pour inspecter une soumission) et renvoie quality_issues[] (plus counts.quality_issues) ; chaque entrée est {key, type, detail}, où type vaut same_as_source, wrong_language, ou looks_like_raw_key. Le detail indique, par exemple : "value is identical to the source, likely not translated" ; "value is written in {Script} script but '{lang}' expects {Expected}" ; "value reads like '{lang}', not the target '{target}' (stopword heuristic)" ; ou "value '{v}' looks like a key path/identifier, not text". C'est indicatif : il signale, il ne réécrit jamais vos valeurs.

Une fois publiée, il y a deux questions distinctes, avec deux vérifications :

Est-elle publiée ?

Utilisez distribution_info (lecture seule via MCP, zéro crédit) : il renvoie la base CDN et le gabarit d'URL de bundle, la version de production, quelles paires langue/namespace sont publiées, et les gaps. C'est exactement ce que les SDK clients peuvent récupérer maintenant.

Se résout-elle ?

Lancez sonenta pull --language <code> : il télécharge les traductions résolues de cette langue, preuve concrète que les valeurs se récupèrent.

Notez que sonenta status diffe votre copie locale contre le projet distant, pas le CDN : ce n'est donc pas une vérif de publication. Les SDK abonnés reçoivent aussi un événement translations_published et se rafraîchissent en place. Deux aides de préflight à connaître : sonenta doctor vérifie que le MCP est câblé, joignable et de scope mcp:*, et sonenta ci évalue l'impact i18n d'une pull request.

Suite