Docs / Anleitungen
Maschinell übersetzte Seite
Einen eigenen Format-Adapter schreiben
Liefere ein Format, das verbatra nicht mitbringt: benenne es mit einem custom:-Bezeichner, baue es auf einer Adapter-Fabrik auf und erfahre, wem du vertraust.
Das brauchst du, wenn deine Locale-Dateien in einem Format vorliegen, das verbatra nicht von Haus aus liest (siehe Formate). Du baust den Adapter in deinem eigenen Paket, benennst das Format mit einem custom:-Bezeichner und übergibst verbatra eine Registry, die ihn enthält. Nichts wird bei verbatra veröffentlicht, und kein Release ist nötig.
Du brauchst @verbatra/sdk im Projekt. Die Kommandozeile verbatra lädt absichtlich kein Plugin (siehe Worauf du dich einlässt), also läuft ein Projekt mit eigenem Format über das SDK.
Das Format benennen
Ein Format von außerhalb heißt custom:, gefolgt von einem kleingeschriebenen, mit Bindestrichen getrennten Namen, etwa custom:toml oder custom:my-format. Kein eingebauter Name enthält einen Doppelpunkt, also kann er nie einen verdecken. Trag ihn wie einen eingebauten Namen in die Konfiguration ein:
{
"sourceLocale": "en",
"targetLocales": ["de"],
"format": "custom:toml",
"files": { "pattern": "locales/{locale}.toml" },
"provider": { "id": "gemini", "options": { "model": "gemini-2.5-flash", "maxOutputTokens": 4096 } }
}Die Konfiguration prüft nur die Form des Bezeichners, weil der Adapter in deinem Paket liegt. Liefert niemand einen Adapter dafür, scheitert der Lauf mit UNKNOWN_. Studio und project.snapshot im MCP-Server melden den Bezeichner unverändert, sodass ein Agent ein eigenes Format von einem eingebauten unterscheiden kann.
Den Adapter bauen
Implementier den Adapter-Vertrag nicht von Hand. Zwei Fabriken liefern das begrenzte Lesen, das atomare Schreiben, die Erkennung per Dateiendung und strukturierte Fehler und lassen dir nur das Parsen deines Formats.
Wird jeder Eintrag über genau einen Key ohne Verschachtelung angesprochen, nimmst du createFlatFileAdapter:
import { createFlatFileAdapter, type FormatAdapter } from "@verbatra/sdk";
const TOKEN = /\{[a-z]+\}/g;
const tokensIn = (value: string): readonly string[] =>
[...value.matchAll(TOKEN)].map((match) => match[0]);
export const tomlAdapter: FormatAdapter = createFlatFileAdapter({
format: "custom:toml",
extensions: [".toml"],
parseEntries: (content, namespace) => parseToml(content, namespace),
serializeEntries: (entries) => serializeToml(entries),
extractPlaceholders: tokensIn,
});Liegen die Einträge auf Pfaden durch verschachtelte Objekte, nimmst du createTreeFileAdapter; es erwartet parse und serialize über einen Baum sowie ein deriveEntry für jedes Blatt.
Dann, je nachdem, was dein Format braucht:
- Ist deine Dateiendung eine allgemeine, gib der Fabrik ein
sniff, das eine Inhaltsprobe prüft. Ohne das beansprucht dein Adapter jede Datei mit dieser Endung, und die Erkennung meldet eine Mehrdeutigkeit. - Enthält eine Datei Quell- und Zieltext zugleich oder hält sie ihre Locale fest, lies das zusätzliche Argument
locale, dasparseEntriesundserializeEntriesbekommen. - Würde eine flache Token-Liste die Struktur deiner Platzhalter verlieren, ergänze
comparePlaceholders; hat dein Format Plural- oder Select-Zweige, ergänzecompareBranchArms. - Markiert dein Format Inhalte als nicht zu übersetzen, gib aus
parseEntries{ entries, excludedLeafPaths }zurück, statt sie wegzulassen. - Lies und schreib über den
fs-Port, den dir die Fabrik übergibt, standardmäßignodeAdapterFs, nie direkt übernode:fs. So bleiben das begrenzte Lesen und das atomare Schreiben erhalten, und du kannst den Adapter ohne Festplatte testen.
Registrieren und laufen lassen
Starte mit der eingebauten Registry, damit dein Format zu den anderen dazukommt, und übergib sie als Abhängigkeit adapterRegistry, die jeder SDK-Ablauf annimmt:
import { createDefaultRegistry, translate, loadConfig } from "@verbatra/sdk";
import { tomlAdapter } from "./toml-adapter.js";
const config = await loadConfig({ cwd: process.cwd() });
const adapterRegistry = createDefaultRegistry().register(tomlAdapter);
const summary = await translate({ config }, { adapterRegistry });register gibt die Registry zurück, Registrierungen lassen sich also verketten. Es lehnt ein Format, das die Registry schon hat, mit DUPLICATE_ ab und einen fehlerhaften Bezeichner wie custom:TOML mit INVALID_, sodass zwei Plugins mit demselben Namen schon beim Start scheitern.
Die richtigen Fehler werfen
Ein custom:-Adapter wird beim Registrieren umhüllt, sodass ein unerwarteter Fehler daraus als ADAPTER_ auftaucht, mit deinem Format und der Methode, statt verbatra die Schuld zu geben. Die Meldung wiederholt deine nie, weil sie die Datei zitieren könnte; deinen ursprünglichen Fehler liest du aus cause.
Zwei Arten von Fehlern gehen unverändert durch:
- Ein
AdapterError, den du selbst wirfst, behält seinen Code. WirfINVALID_für Inhalte, die dein Format nicht abbilden kann.STRUCTURE - Ein Fehler mit einem errno-Code wie
ENOENTbehält ihn, sodass eine fehlende Datei weiter als solche gemeldet wird. Die Prüfung sieht nur auf die Form des Fehlers, also gib deinen eigenen Validierungsfehlern keinen errno-Code.
Worauf du dich einlässt
Ein Format-Adapter ist voll vertrauenswürdiger Code, auf derselben Vertrauensstufe wie jedes Paket, das du installierst. verbatra sperrt ihn in keine Sandbox.
Ein Adapter kann process.env lesen, wo jeder Provider-Key liegt, jede Datei lesen und schreiben, auf die der Prozess Zugriff hat, und Netzwerkverbindungen öffnen. Der fs-Port ist eine Konvention, keine Grenze.
Der Adapter entscheidet außerdem, was als Platzhalter zählt. Meldet er keine, besteht die Platzhalter-Integritätsprüfung für sein Format immer, und eine Übersetzung mit zerstörter Interpolation geht unbemerkt durch, egal ob der Adapter fehlerhaft oder böswillig ist.
Zusichern kann verbatra, dass nie etwas implizit geladen wird: Es entdeckt kein Plugin, durchsucht kein Verzeichnis, installiert nichts und folgt keiner Namenskonvention. Ein Adapter läuft nur, weil dein Code ihn importiert und verbatra die Registry übergeben hat. Behandle ihn wie jede Abhängigkeit, die deine Secrets liest: lies ihn, pinne die Version und prüf jedes Update.
Siehe auch
- Adapter, Provider, Schwärzung: jede Fabrik-Option und jeder Export.
- Fehlercodes der Format-Adapter: was jede Ablehnung bedeutet.
- Formate: die Formate, die verbatra mitbringt.