Aller au contenu
Aller au contenu

Référence / Configuration

Page traduite automatiquement

Cette page a été traduite automatiquement, elle peut donc contenir des erreurs ou se lire un peu bizarrement. La version anglaise fait foi. Lire l'original en anglais.

Fichier de configuration

Chaque clé de configuration avec son type, son défaut et la version qui l'a ajoutée, plus l'emplacement du fichier et l'échec d'une mauvaise configuration.

verbatra lit un objet de configuration sans secret et le valide avant tout travail. Aucune clé d'API n'est jamais lue depuis ce fichier (Fournisseurs), donc la configuration peut être commitée sans risque.

Une configuration minimale

verbatra.config.ts
import { defineConfig } from "@verbatra/cli";

export default defineConfig({
  // Locales and files: required
  sourceLocale: "en",
  targetLocales: ["de", "fr"],
  format: "i18next-json",
  files: {
    // {locale} is the only token
    pattern: "locales/{locale}.json",
  },

  // Provider: required; the API key comes from the environment, never from here
  provider: {
    id: "gemini",
    options: {
      // example model id; use your provider's current one
      model: "gemini-2.5-flash",
      maxOutputTokens: 4096,
    },
  },

  // Optional groups, each off or at its default until you add it:
  // tone: "informal",
  // glossary: "glossary.json",
  // network: { policy: "local-only" },
  // sensitiveData: { mode: "warn" },
  // maxTokens: 200000,
  // budgetBehavior: "stop",
});

Voir locales et fichiers, provider, glossary, network, contenu sensible, budget, rates et extract.

defineConfig ne fait que typer son argument : options.model propose les identifiants de modèle du fournisseur, mais à l'exécution toute chaîne non vide est acceptée.

Chaque clé

Les clés inconnues sont rejetées à chaque niveau sauf $schema et les maps dont tu nommes les clés, comme maxLength, rates.table, localeMap et un glossary en ligne, donc une clé d'API ne peut pas se trouver dans la configuration.

CléTypeDéfautDepuisRôle
$schemachaîneaucun0.9.0Pointe un éditeur vers le JSON Schema ; ignoré à l'exécution.
sourceLocalecode de localerequis0.1.0La locale dans laquelle tes chaînes source sont écrites.
targetLocalestableau de codes de localerequis0.1.0Au moins une ; jamais sourceLocale, jamais deux égales sans tenir compte de la casse.
formatid de formatrequis0.1.0Le format de tes fichiers de locale, ou un id custom: pour un adaptateur extérieur.
files.patternchaînerequis0.1.0Le chemin de chaque fichier de locale, avec un jeton {locale}.
files.localeStyle"literal", "posix", "android""literal"0.7.0Comment {locale} est écrit dans le chemin.
provider.idid de fournisseurrequis0.1.0Le fournisseur de traduction, ou none pour aucune traduction automatique.
provider.optionsobjetrequis, sauf pour none0.1.0Les options propres au fournisseur.
glossaryobjet ou chemin de fichieraucun0.1.0Traductions fixes, traductions interdites et termes à ne pas traduire.
tone"formal", "informal", "neutral"aucun0.1.0Le registre des traductions, appliqué selon le fournisseur.
prunebooléenfalse0.3.0Supprime les clés orphelines des fichiers cibles et du fichier de verrouillage ; translate --prune prime.
generatePluralsbooléenfalse0.3.0Synthétise les formes plurielles CLDR dont une langue cible a besoin.
fuzzyCache.enabledbooléenrequis dans le bloc0.11.0Réutilise la traduction d'une source peu modifiée.
fuzzyCache.thresholdnombre, de 0.5 à 10.90.11.0À quel point ancienne et nouvelle source doivent se ressembler.
humanEdits"protect", "suggest", "overwrite""protect"0.12.0Ce que fait une exécution d'une clé obsolète écrite par une personne.
pinnedKeystableau de chaînesaucun0.12.0Des motifs de clés (* en joker) qu'aucune écriture automatique ne touche.
network.policy"any", "local-only", "allowlist""any"0.12.0Les hôtes auxquels un fournisseur peut se connecter.
network.allowedHoststableau de chaînesaucun ; requis pour "allowlist"0.12.0Hôtes autorisés en plus : noms, jokers *.suffix, IP ou plages CIDR.
sensitiveData.mode"off", "warn", "block", "redact"obligatoire dans le bloc ; "off" sans le bloc0.12.0Ce qu'une exécution fait du contenu sensible avant l'envoi.
sensitiveData.detectorstableau d'ID de détecteurssecret, email, iban, credit-card0.12.0Détecteurs actifs ; phone, ip, private-host sont optionnels.
sensitiveData.patternstableau de chaînesaucun0.12.0Expressions régulières pour tes propres termes, comme des noms de code.
sensitiveData.allowtableau de chaînesaucun0.12.0Correspondances jamais signalées ; * est un joker et la casse est ignorée.
maxBatchSizeentier positif500.3.0Le maximum d'entrées par requête fournisseur.
maxLengthtable de clé vers entier positifaucun0.11.0Longueurs maximales par clé, en groupes de graphèmes.
maxTokensentier positifaucun0.5.0Un budget de tokens pour toute l'exécution.
budgetBehavior"warn", "stop""warn"0.5.0Si atteindre maxTokens avertit ou arrête les envois.
rates.asOfdate YYYY-MM-DDrequis dans le bloc0.11.0La date à laquelle tu as lu les tarifs.
rates.currencytrois lettres majusculesrequis dans le bloc0.11.0La devise de chaque tarif, comme USD.
rates.tabletable de clé de tarif vers tarifrequis dans le bloc0.11.0Les tarifs par clé de tarif.
extract.framework"i18next"requis dans le bloc0.11.0Les appels que l'analyse du code source recherche.
extract.rootstableau de chaînesrequis dans le bloc0.11.0Les répertoires à analyser, au moins un.
extract.excludetableau de chaînesaucun0.11.0Des noms de répertoire supplémentaires à ignorer.
extract.literals.ignoretableau de chaînesaucun0.11.0Des textes exacts que doctor --literals retient.
extract.unused.ignoretableau de chaînesaucun0.11.0Des clés ou motifs * que diff --unused ne signale jamais.

Locales et fichiers

  • files.pattern doit contenir {locale}, son seul jeton, et se résout par rapport à la racine du projet : locales/{locale}.json devient locales/de.json. C'est un chemin littéral, jamais un glob, donc une configuration adresse un fichier par locale (Dispositions avec espaces de noms) ; apple-xcstrings résout chaque locale vers le même catalogue (Xcode String Catalogs).

  • files.localeStyle décide en quoi le jeton se développe :

    • literal écrit l'étiquette telle qu'elle est configurée, comme le veulent la plupart des dispositions.
    • posix remplace - par _ pour gettext et la disposition Java messages_{locale}.properties (pt-BR devient pt_BR) ; une variante comme de-1996 n'a pas d'écriture posix. gettext-po écrit les écritures à la manière de gettext (section suivante).
    • android se développe en un répertoire de ressources, écrit sous la forme res/{locale}/strings.xml : values pour la source, puis values-de, values-pt-rBR, values-b+zh+Hans.

    Un style refuse une locale qu'il ne sait pas écrire.

Noms de locale gettext

Avec format: "gettext-po" et localeStyle: "posix", les fichiers portent des noms gettext (language_REGION@modifier) tandis que la configuration garde des codes BCP 47 :

Code dans la configurationNom de fichier
pt-BRpt_BR
es-419es_419
sr-Latnsr@latin
sr-Latn-RSsr_RS@latin
uz-Cyrluz@cyrillic
ks-Deva-INks_IN@devanagari
zh-Hant-TWzh_TW
sr-Cyrl-RSsr_RS

Une écriture que la langue et la région impliquent déjà est omise, donc zh-TW et zh-Hant-TW ensemble échouent avec LOCALE_PATH_COLLISION ; une écriture sans modificateur gettext, comme zh-Hant seul, échoue avec LOCALE_LAYOUT_INVALID. verbatra init relit ces noms. Les autres formats gardent l'écriture ICU (sr_Latn).

Codes de locale

Chaque code de locale doit être une étiquette qu'accepte Intl.getCanonicalLocales, avec une sous-étiquette de langue de deux ou trois lettres, sinon le chargement échoue avec CONFIG_INVALID : pt_BR (écris pt-BR avec localeStyle: "posix") et german sont rejetés. Un code valide non canonique, comme zh-hant-tw ou l'obsolète iw, fonctionne tel qu'il est écrit.

provider

provider.id sélectionne l'un des fournisseurs ou none, dont options peut être omis et doit sinon valoir {} (Travailler sans traduction automatique). Les autres fournisseurs acceptent options.localeMap et options.requestTimeoutMs (Fournisseurs) ; depuis 0.12.0, une clé mal placée sous provider, comme localeMap, échoue avec CONFIG_INVALID.

glossary

Des termes traduits d'une façon fixe, en ligne ou comme chemin vers un fichier JSON de la même forme (jamais fusionnées). La version 1 associe chaque terme source à une traduction pour toutes les locales :

verbatra.config.ts
export default defineConfig({
  // ...
  glossary: {
    "Sign in": "Anmelden",
  },
  // or: glossary: "glossary.json",
});

Un chemin relatif se résout par rapport au répertoire du fichier de configuration ; le fichier doit être en UTF-8, ne pas dépasser 1 MiB, et il est lu une fois au chargement. Un fichier absent, un JSON invalide ou une forme invalide échoue avec CONFIG_INVALID, en nommant le chemin et, pour la version 2, le champ. Mets un terme __proto__ dans un fichier ; un littéral JavaScript le transforme en prototype.

Glossaire par locale (version 2)

La version 2 ajoute des traductions par locale, des traductions interdites et des termes à garder tels qu'ils sont écrits :

glossary.json
{
  "version": 2,
  "terms": [
    {
      "source": "Dashboard",
      "targets": { "de": "Übersicht", "fr": "Tableau de bord" },
      "forbidden": { "de": ["Instrumententafel"] },
      "note": "The start page after sign-in",
      "partOfSpeech": "noun"
    },
    { "source": "Sign in", "target": "Anmelden", "caseSensitive": true }
  ],
  "doNotTranslate": ["verbatra", { "term": "Acme", "caseSensitive": false }]
}
ChampSignification
versionToujours 2 ; tout autre nombre échoue.
terms[].sourceLe terme source ; chaque terme apparaît une seule fois.
terms[].targetLa traduction pour chaque locale sans entrée propre dans targets.
terms[].targetsLes traductions par locale. Une locale prend sa propre entrée, puis celle de sa langue de base (de couvre de-AT), puis target, en comparant les codes canoniques sans tenir compte de la casse.
terms[].forbiddenLes traductions qu'une locale ne doit jamais utiliser ; une locale régionale respecte aussi la liste de sa langue de base.
terms[].caseSensitiveComparer le terme, les traductions et les traductions interdites en tenant compte de la casse. false par défaut.
terms[].note, terms[].partOfSpeechUn contexte en texte libre, envoyé comme données à un fournisseur LLM.
doNotTranslateLes termes recopiés sans traduction. Une simple chaîne garde sa casse ; { "term", "caseSensitive": false } peut la changer.

Chaque terme a besoin d'un target, d'une entrée dans targets ou d'une liste forbidden ; il ne peut pas interdire sa propre traduction, nommer deux fois une locale ni figurer dans doNotTranslate. Aucun texte ne peut être vide ; un terme compte au plus 200 caractères, une traduction ou une forme interdite 2000, une note 500 et une partOfSpeech 50. L'empreinte de cache d'une locale ne couvre que ses propres termes. Un fichier version 1 garde son empreinte ; updateGlossaryTerm ne le réécrit en version 2 que pour une modification que la version 1 ne sait pas exprimer.

Studio ne modifie que la forme fichier, un terme à la fois. Les fournisseurs qui appliquent le glossaire sont indiqués dans Fournisseurs ; chaque sortie est vérifiée ensuite.

generatePlurals

Quand il vaut true, verbatra synthétise les formes plurielles CLDR dont une cible a besoin mais que la source n'a pas, comme few et many pour le polonais, et les clés ordinales (<key>_ordinal_<category>) selon les règles ordinales CLDR. Seul i18next-json avec un fournisseur LLM le prend en charge ; tout le reste, et une locale sans règles CLDR, reçoit l'avertissement de pluriel (les ordinaux supposent other). Il n'y a pas d'option CLI ; translate() du SDK accepte une surcharge par exécution.

fuzzyCache

fuzzyCache: { enabled: true } laisse une source modifiée réutiliser la traduction de sa forme antérieure quand les deux se ressemblent au moins à hauteur de threshold, toujours signalée avec FUZZY_CACHE_REUSE (Réutilisation approximative) ; --no-cache le contourne.

humanEdits et pinnedKeys

humanEdits couvre une clé obsolète dont la valeur a été écrite par une personne (provenance human, import ou external) ; une clé qui correspond à pinnedKeys (comme ["legal.*", "brand.name"]) n'est jamais écrite par une machine, quoi que dise humanEdits. * correspond à toute suite de caractères, points compris, et la comparaison est sensible à la casse. Ce que fait chaque mode est décrit dans Garder les traductions humaines.

network

Voir Restreindre l'accès réseau.

verbatra.config.ts
network: { policy: "local-only", allowedHosts: ["gpu.lan"] }

maxBatchSize

Les entrées manquantes et modifiées partent en sous-lots séquentiels d'au plus cette taille. Aucune option CLI ne le remplace.

maxLength

Des limites de longueur par clé, pour les chaînes soumises à une contrainte de mise en page :

verbatra.config.ts
maxLength: {
  "nav.dashboard": 18,
  "cta.submit": 12,
}
  • Ici ou dans verbatra.limits.json. nouveau Les clés sont comparées littéralement, jamais comme des globs ; une clé fixée dans aucun des deux n'est jamais mesurée. setKeyLengthLimit n'accepte que des clés de la source, donc Studio ne peut pas limiter une forme plurielle générée ; une entrée écrite à la main pour sa propre clé s'applique. Le fichier versionné à côté du fichier de verrou accepte { "version": 1, "maxLength": { ... } }, la config l'emporte par clé et setKeyLengthLimit l'écrit.
  • Groupes de graphèmes. La longueur compte les caractères perçus, espaces compris : un emoji, une lettre accentuée ou un caractère CJK compte pour un. La limite est inclusive.
  • Quand. Chaque valeur que translate produit pour la clé, réutilisations du cache comprises ; une clé à jour n'est mesurée que quand sa source change, ou par export --include-unchanged.
  • Consultatif. Un dépassement est quand même écrit et verrouillé, et signalé pour relecture comme MAX_LENGTH_EXCEEDED.

maxTokens et budgetBehavior

maxTokens est un budget pour toute l'exécution : tokens d'entrée plus de sortie sur chaque appel fournisseur (traduction et génération de pluriels) et chaque locale cible. translate --max-tokens peut le resserrer pour une exécution, jamais le relâcher, et toujours comme un "stop" ferme.

budgetBehavior décide de ce qui se passe alors :

  • "warn", la valeur par défaut, compte la dépense et signale le dépassement, mais continue.
  • "stop" en fait un plafond pour chaque fournisseur. Avant chaque requête, l'exécution projette son coût comme l'estimation préalable et refuse une requête qui dépasserait maxTokens. Les clés de cette requête et chaque clé pas encore tentée (le reste de la locale et chaque locale suivante, dont la comparaison et le rapport d'orphelines tournent quand même) sont retenues, gardent leur hash de verrouillage précédent et sont retentées à l'exécution suivante.

Sous "stop" :

  • Après chaque requête, le total est réconcilié avec l'usage remonté par le fournisseur : une exécution peut donc finir légèrement au-dessus de maxTokens (le budget du résumé d'exécution). Les fournisseurs de traduction automatique ne remontent aucun token et sont budgétés à partir de la projection.
  • Une requête échouée ou tronquée est entièrement comptée.
  • La projection ajoute une allocation fixe pour le prompt LLM, aussi pour les fournisseurs de traduction automatique, et couvre un lot entier, donc un maxTokens inférieur à la projection d'un lot le refuse à chaque exécution ; l'avis dit de baisser maxBatchSize ou d'augmenter maxTokens.
  • Une locale dont des clés ont été retenues est partial, ou failed si aucune clé n'est arrivée, et les deux sortent avec 1. Sous "warn", le code de sortie ne change jamais.

Le budget borne une exécution de translate, jamais la retraduction d'une seule entrée ; watch en démarre un neuf par exécution. Un budget exclut --concurrency supérieur à 1 sur une exécution réelle ; un dry run est exempté. budgetBehavior sans maxTokens n'a aucun effet.

Deux maxTokens différents

Le maxTokens de premier niveau est ce budget de toute l'exécution ; le provider.options.maxTokens d'Anthropic, sans lien avec lui, plafonne une réponse (Fournisseurs).

rates

Lu uniquement par translate --estimate, qui transforme les tarifs en argent ; une exécution réelle l'ignore.

verbatra.config.ts
rates: {
  asOf: "2026-01-15",
  currency: "USD",
  table: {
    // placeholders: copy the current rates from each provider's pricing page
    "gemini/gemini-2.5-flash": { inputPerMillionTokens: 1, outputPerMillionTokens: 2 },
    deepl: { perMillionCharacters: 1 },
  },
}

Une clé de table est provider/model, ou l'id seul pour un fournisseur sans modèle (deepl, google-translate). Une entrée est facturée aux tokens (inputPerMillionTokens, outputPerMillionTokens) ou aux caractères (perMillionCharacters), jamais les deux, et un tarif négatif, un tarif au-delà de 1 000 000 000 par million ou la mauvaise unité est refusé. openai-compatible et libretranslate n'envoient aucune facture, donc leur quantité est indiquée sans tarif.

extract

Lu uniquement par extract, doctor --literals et diff --unused.

verbatra.config.ts
extract: {
  framework: "i18next",
  roots: ["src", "app"],
  exclude: ["generated"],
  literals: { ignore: ["Acme Inc."] },
  unused: { ignore: ["emails.*"] },
}
  • framework doit en nommer un doté d'un extracteur (formes d'appel) ; tout autre est refusé.
  • roots se résolvent par rapport à la racine du projet ; exclude ajoute des noms de répertoire (pas des chemins), reconnus n'importe où sous une racine, à l'ensemble toujours ignoré.
  • literals.ignore correspond au texte complet d'un littéral, espaces regroupés et références décodées (Littéraux non traduits).
  • unused.ignore est comparé à la clé décodée (diff --unused).

Ordre de découverte

verbatra cherche vers le haut depuis le répertoire de travail et prend la première correspondance, en s'arrêtant au répertoire le plus proche qui contient .git, sinon à ton répertoire personnel (ou au répertoire de travail quand le personnel n'est pas au-dessus), donc il ne prend jamais une configuration située au-dessus de ton dépôt :

  1. package.json (une propriété "verbatra")
  2. .verbatrarc
  3. .verbatrarc.json
  4. .verbatrarc.yaml
  5. .verbatrarc.yml
  6. .verbatrarc.js
  7. .verbatrarc.cjs
  8. .verbatrarc.ts
  9. verbatra.config.js
  10. verbatra.config.cjs
  11. verbatra.config.ts

--config <path> charge un seul fichier à la place, relatif au répertoire de travail ; la priorité côté SDK est décrite sous loadConfig.

Validation dans l'éditeur

@verbatra/sdk livre un JSON Schema généré à partir de son schéma zod, servi aussi à une URL stable pour toute installation, npx, un monorepo avec hoisting ou un agent distant :

https://verbatra.kreitz-webdev.de/schema/v1/config.json

Hors ligne, ou pour figer la version installée, utilise la copie du paquet, ./node_modules/@verbatra/sdk/dist/config-schema.json (tous les schémas).

.verbatrarc.json et .verbatrarc prennent une clé $schema pour VS Code :

.verbatrarc.json
{
  "$schema": "https://verbatra.kreitz-webdev.de/schema/v1/config.json",
  "sourceLocale": "en",
  "targetLocales": ["de", "fr"],
  "format": "i18next-json",
  "files": { "pattern": "locales/{locale}.json" },
  "provider": { "id": "gemini", "options": { "model": "gemini-2.5-flash", "maxOutputTokens": 4096 } }
}

Le .verbatrarc sans extension a aussi besoin d'une association de fichiers dans l'espace de travail :

.vscode/settings.json
{
  "json.schemas": [
    {
      "fileMatch": [".verbatrarc", ".verbatrarc.json"],
      "url": "https://verbatra.kreitz-webdev.de/schema/v1/config.json"
    }
  ]
}

Une configuration YAML prend un commentaire YAML Language Server :

.verbatrarc.yaml
# yaml-language-server: $schema=https://verbatra.kreitz-webdev.de/schema/v1/config.json
sourceLocale: en
targetLocales: [de, fr]
format: i18next-json
files:
  pattern: "locales/{locale}.json"
provider:
  id: gemini
  options:
    model: gemini-2.5-flash
    maxOutputTokens: 4096

package.json ne prend pas de schéma ; les formes exécutables sont typées par defineConfig.

Ce que le document ne peut pas vérifier

Seul le chargement de la configuration vérifie ces règles : les règles de targetLocales et des codes de locale, les clés de localeMap et les règles de baseUrl et apiKeyEnvVar d'openai-compatible, des adresses et plages valides dans network.allowedHosts, sensitiveData.patterns dans les règles de sécurité des motifs et les règles des termes d'un glossaire en ligne en version 2.

Le répertoire de travail et .env

Le répertoire de travail (là où tu lances verbatra, ou --cwd) lance la recherche de configuration et contient les fichiers d'environnement. Les chemins de locale, verbatra.lock.json, le cache, le fichier de provenance et .verbatra-local/ sont résolus par rapport à la racine du projet, le répertoire de la configuration trouvée, donc une exécution depuis un sous-répertoire utilise les mêmes fichiers. Avec --config, le répertoire de travail est la racine, et une configuration située ailleurs reçoit une note sur stderr, car le chemin de son glossaire est résolu par rapport à son propre répertoire. Un chemin que tu passes, comme --out ou check --file, est résolu par rapport au répertoire de travail.

Quand le chargement échoue

  • CONFIG_NOT_FOUND : aucune configuration à aucun des endroits cherchés, ou le chemin --config n'existe pas.
  • CONFIG_INVALID : une configuration a été trouvée mais n'est pas utilisable. Le message liste chaque problème avec son chemin de clé ; une clé inconnue ajoute l'indice que les clés d'API viennent de l'environnement. Un échec d'analyse nomme le fichier (avec la ligne et la colonne pour YAML) mais ne cite jamais son contenu, et chaque message passe par la rédaction des clés.

La CLI sort avec 2 dans les deux cas.

Modifier sur GitHub

Sur cette page