Kosten abschätzen

Schätze den Umfang eines Übersetzungslaufs ab, bevor du Geld ausgibst: zähle die Keys mit einem Dry Run, rechne sie in Requests und Tokens um und bepreise sie mit den Raten deines Providers.

Maschinell übersetzte Seite

Diese Seite wurde automatisch übersetzt und kann daher Fehler oder seltsame Formulierungen enthalten. Die englische Version ist die maßgebliche Quelle. Das englische Original lesen.

Bevor du ein KI-Werkzeug auf eine echte Locale-Datei loslässt, willst du eine Größenordnung dafür, was es kosten wird. Diese Seite gibt dir eine Methode statt einer Preisliste: verbatra verfolgt keine Provider-Raten, und Raten ändern sich. Der dauerhafte Teil ist deshalb zu wissen, welche Einheiten dir berechnet werden und wie du sie zählst. Jede Zahl unten ist eine Annahme, die du durch deine eigene ersetzt.

Die Kurzfassung für ein typisches Projekt: ein paar hundert Keys in ein paar Locales auf einem günstigen Modell kosten Cent, nicht Dollar, und der Lauf danach kostet fast nichts, weil verbatra nur sendet, was sich geändert hat.

Schritt 1: den Umfang mit einem Dry Run bestimmen

Ein Dry Run ist die vom Werkzeug unterstützte Antwort auf "wie viel Arbeit ist das". Er berechnet genau, welche Keys gesendet würden, ohne einen Provider zu konstruieren, einen API-Schlüssel zu lesen, eine Netzwerkanfrage zu stellen oder irgendetwas zu schreiben:

verbatra translate --dry-run
verbatra translate (dry run)
  de: 400 translated, 0 unchanged
  es: 400 translated, 0 unchanged
  fr: 400 translated, 0 unchanged
3 succeeded, 0 partial, 0 failed (dry run: nothing written)

Bei einem Dry Run ist die Zahl hinter translated die Anzahl der Keys, die an den Provider gesendet würden: die in der Zieldatei fehlenden Keys plus die Keys, deren Quelltext sich seit der Lock-Baseline geändert hat, abzüglich derjenigen, die wegen ungültigem ICU übersprungen werden. Diese Zahl ist die Eingabe für alles Weitere.

Behandle sie als Obergrenze, aus zwei Gründen. Ein Dry Run liest den Cache nie; Keys, die ein echter Lauf aus dem Übersetzungsspeicher bedienen würde, werden hier also mitgezählt. Und ein Dry Run dedupliziert nicht: Bei einem echten Lauf werden Keys mit identischem Quelltext gruppiert, und nur einer davon wird stellvertretend gesendet. Eine Datei mit wiederholten Strings wird also für weniger Keys abgerechnet, als der Dry Run zeigt.

Ein Dry Run allein meldet Zahlen, keine Tokens und kein Geld. --estimate nimmt dir diese Umrechnung ab; Schritt 5 weiter unten zeigt das. Die Schritte dazwischen sind genau die Rechnung, die dabei ausgeführt wird, und sie bleiben die Methode, auf die du zurückgreifst, wenn für ein Modell keine Rate hinterlegt ist. Die vollständige Flag-Liste steht unter verbatra translate.

Schritt 2: die Requests zählen

verbatra sendet nicht einen Request pro Key. Es teilt die Arbeit jedes Locales in sequenzielle Sub-Batches von höchstens maxBatchSize Keys auf (Standard 50), und jeder Sub-Batch ist ein Provider-Request:

Requests pro Locale = ceil(zu übersetzende Keys / maxBatchSize)

Für den festen Overhead zählt die Batch-Größe mehr als die Key-Anzahl, weil ein Teil jedes Requests konstant ist (siehe nächster Schritt). Zwei Korrekturen:

  • Eine unvollständige Antwort löst begrenzte zusätzliche Requests aus: höchstens eine Reparaturrunde, wenn Keys fehlend zurückkamen, und einen Wiederholungsversuch in Hälften, wenn die Ausgabe abgeschnitten wurde. Im Normalbetrieb sind das null zusätzliche Requests.
  • Jeder dieser Requests kann mehr als ein HTTP-Versuch sein. Keiner von verbatras Provider-Clients setzt eine Retry-Option, es gilt also der Standard des jeweiligen SDK: zwei zusätzliche Versuche bei Anthropic, OpenAI und openai-compatible, zwei bei Geminis eigener Schleife auf 429 und 5xx, und fünf bei DeepL. Ein Versuch, der das Modell erreicht hat, wird abgerechnet, egal ob seine Antwort ankam.
  • generatePlurals fügt eigene gebatchte Requests für die Pluralformen hinzu, die es ergänzt, gezählt nach derselben Regel. Sie sind von den Übersetzungs-Batches getrennt; ein Projekt, dessen Keys alle synchron sind, dessen Pluralsatz aber nicht, stellt also trotzdem Requests.

Schritt 3: die Tokens in einem Request zählen

Ein LLM-Request trägt vier Dinge. Eines skaliert mit deiner Key-Anzahl, und eines trägt dein Glossar vollständig mit:

TeilSkaliert mitUngefähre Größe
Systemregelnnichts: konstant pro Request~250 Tokens
Ausgabeschemanichts: konstant pro Request~100 Tokens
Items-PayloadKeys im Sub-Batch, dazu Glossar und TonfallKey + Wert + ~21 Zeichen JSON, pro Item
AntwortKeys im Sub-BatchKey + übersetzter Wert + ~21 Zeichen JSON, pro Item

Die Systemregeln sind eine Compile-Zeit-Konstante, in jedem Request identisch. Deshalb ist der Overhead pro Request bekannt und keine Schätzung. Die Items-Payload ist ein JSON-Objekt mit Quell- und Ziel-Locale, einem optionalen Tonfall und Glossar sowie einem Item pro Key mit key, value und optional description und meaning. Die Antwort wiederholt jeden Key neben seiner Übersetzung, die Ausgabegröße folgt der Eingabegröße also eng.

Das Glossar wird dabei gern übersehen. Es wird vollständig in jeden Request serialisiert, nicht einmal pro Lauf. Ein Glossar mit 200 Begriffen und rund 6.000 Zeichen legt also auf jeden einzelnen Request etwa 1.500 Tokens drauf. Bei kleinen Sub-Batches kann das schwerer wiegen als die Keys selbst, ein weiterer Grund, warum die Batch-Größe zählt.

Die Antwort ist der Teil, der sich nicht messen lässt, weil die Übersetzung noch nicht existiert. verbatra bemisst sie am Quellwert plus einem Zuschlag von 50 Prozent: Deutsch, Französisch und Russisch laufen regelmäßig ein Drittel bis die Hälfte länger als Englisch, und Antwort-Tokens sind auf jeder LLM-Preisliste die teure Hälfte. Eine Sprache, die über den Zuschlag hinauswächst, liefert mehr zurück, als die Schätzung vorhergesagt hat.

Zum Zählen gilt als Faustregel ~4 Zeichen pro Token für englische Prosa. Nicht-lateinische Schriften und stark interpunktierte Strings sind dichter, behandle das also als Größenordnung, nicht als Messung.

Schritt 4: mit den Raten deines Providers bepreisen

verbatra veröffentlicht bewusst keine Preise. Schlage die aktuelle Rate für dein Modell auf der Seite des Providers selbst nach; sie ist die einzige Autorität. Wenn du sie hast, kannst du sie verbatra übergeben, statt sie im Kopf zu behalten: siehe Schritt 5.

ProviderAbgerechnet nachPreise
GeminiEingabe- und Ausgabe-Tokens (kostenlose Stufe verfügbar)Gemini API pricing
AnthropicEingabe- und Ausgabe-TokensAnthropic pricing
OpenAIEingabe- und Ausgabe-TokensOpenAI API pricing
DeepLQuellzeichen, nicht TokensDeepL Pro pricing
Google Cloud TranslationQuellzeichen, nicht TokensCloud Translation pricing
openai-compatiblenichts: deine eigene Hardwarekeine API-Kosten

Schritt 5: verbatra die Rechnung machen lassen

Verfügbar ab 0.11.0

Dafür brauchst du verbatra 0.11.0 oder neuer. Frühere Releases haben es nicht: Prüf deine installierte Version mit verbatra --version und aktualisiere, falls sie älter ist.

--estimate führt jeden Schritt von oben für dich aus und beendet sich, ohne einen Provider aufzurufen:

verbatra translate --estimate
verbatra translate (dry run)
  de: 400 translated, 0 unchanged
  es: 400 translated, 0 unchanged
  fr: 400 translated, 0 unchanged
  estimate: 1200 keys in 24 requests, ~33312 input + ~30720 output tokens
  estimated spend: no rate on file for gemini/gemini-2.5-flash; add rates.table["gemini/gemini-2.5-flash"] to your config to see a currency figure
  estimate excludes: cache hits, duplicate source strings, provider-side retries, translation length, tokenizer differences, repair requests
3 succeeded, 0 partial, 0 failed (dry run: nothing written)

Es impliziert --dry-run: Es wird kein Provider konstruiert, kein API-Schlüssel gelesen, keine Netzwerkanfrage gestellt und nichts geschrieben. Ein Machine-Translation-Provider wird in Quellzeichen statt in Tokens gezählt, und ein selbst gehosteter openai-compatible-Endpunkt wird als gänzlich ohne API-Kosten ausgewiesen.

Die Menge bekommst du geschenkt. Das Geld nicht: verbatra veröffentlicht weiterhin keine Preise, ein Geldbetrag erscheint also erst, wenn du die in Schritt 4 nachgeschlagenen Raten in deine Konfiguration einträgst, unter einem rates-Block, der festhält, wann du sie gelesen hast:

verbatra.config.ts
export default defineConfig({
  // ...
  rates: {
    asOf: "2026-01-15",
    currency: "USD",
    table: {
      "gemini/gemini-2.5-flash": { inputPerMillionTokens: 0.1, outputPerMillionTokens: 0.4 },
      deepl: { perMillionCharacters: 25 },
    },
  },
});

Der Key ist provider/model für einen Provider mit konfiguriertem Modell und die blanke Provider-ID für einen ohne (deepl, google-translate). Ein tokenbasiert abgerechnetes Modell nimmt inputPerMillionTokens und outputPerMillionTokens, ein zeichenbasiertes perMillionCharacters. Jede ausgegebene Zahl trägt das asOf-Datum; eine Ratentabelle, die du zuletzt vor einem Jahr angefasst hast, sagt das also bei jedem Lauf. Siehe die Konfigurationsreferenz.

Drei Dinge wird es nie tun: eine Rate erfinden, die es nicht hat, eine in der falschen Einheit geschriebene Rate anwenden oder 0.00 für ein Modell ausgeben, das es nicht bepreisen kann. Jeder dieser Fälle wird stattdessen als ausdrückliche Zeile gemeldet, und der Lauf endet trotzdem mit 0.

--json liefert dieselben Zahlen als strukturierte Felder unter result.estimate, pro Locale und als Summe, ein Skript kann also darauf prüfen, statt eine Zeile zu parsen.

Die Zahl begrenzt den Plan, nicht die Rechnung. Jeder Request, den ein echter Lauf machen würde, wird gezählt, auch die Batches der Pluralgenerierung; der Prompt wird gemessen, indem die tatsächlich zu sendende Payload serialisiert wird, statt ihre Form in einer Formel nachzubauen, ein Glossar oder ein Tonfall kann also nicht ungezählt bleiben; und die Antwort wird mit dem Zuschlag aus Schritt 3 bemessen. Gegenüber diesem Plan gibt ein echter Lauf meistens weniger aus, aus denselben zwei Gründen, aus denen die Dry-Run-Zahl eine Obergrenze ist: er zieht den Cache heran, und er fasst identische Quellstrings zusammen.

Er kann aber auch mehr ausgeben, und die Zeile estimate excludes benennt jeden Weg dorthin. Ein tokenbasiert abgerechneter Provider bekommt sechs Einträge: Cache-Treffer, doppelte Quellstrings, Retries auf Provider-Seite, Übersetzungslänge, Tokenizer-Unterschiede und Reparatur-Requests. Ein zeichenbasiert abgerechneter bekommt die ersten drei, weil es dort keine Tokens zu schätzen gibt, keine Reparaturrunde läuft und der Quelltext abgerechnet wird, nicht die Übersetzung.

Zwei davon entscheiden, ob du die Zahl als Deckel behandeln kannst. Die SDK-Retries aus Schritt 2 können aus einem gezählten Request drei HTTP-Versuche machen, bei DeepL sechs. Und eine Reparaturrunde schickt Systemregeln, Glossar und Tonfall erneut vollständig mit, einen fehlenden Key in einem Batch mit großem Glossar zu reparieren kostet also fast einen ganzen zusätzlichen Request. Plane mit dieser Zahl, versprich einer Finanzabteilung aber nicht, dass sie nicht überschritten werden kann.

Die Schätzung deckt translate ab. Einen einzelnen Eintrag aus Studio oder aus einem Agenten-Tool neu zu übersetzen, ruft den Provider auf einem eigenen Weg auf, und keine Schätzung hier sieht diese Ausgabe.

Ein durchgerechnetes Beispiel

Ersetze jede Annahme in diesem Block durch deine eigenen Zahlen.

Annahmen

  • 400 zu übersetzende Keys pro Locale (die Dry-Run-Zahl oben), 3 Ziel-Locales
  • durchschnittlicher Quellwert 40 Zeichen, durchschnittlicher Key-Name 20 Zeichen
  • kein description, meaning, Glossar oder Tonfall
  • maxBatchSize auf dem Standardwert 50
  • Provider gemini, Modell gemini-2.5-flash
  • 4 Zeichen pro Token
  • übersetzte Werte bis zu 50 Prozent länger als die Quelle, das ist der Zuschlag, den verbatra ansetzt
  • illustrative Rate von $0.10 pro Million Eingabe-Tokens und $0.40 pro Million Ausgabe-Tokens: ein Platzhalter, der die Rechnung konkret macht, kein zitierter Preis. Schlage die echte nach.

Requests

ceil(400 / 50) = 8 Requests pro Locale, 24 Requests insgesamt.

Eingabe-Tokens pro Request

Systemregeln250
Ausgabeschema100
(50 Items x (20 + 40 + ~21 JSON) Zeichen + ~50 Envelope) / 41.038
Summe~1.388

Ausgabe-Tokens pro Request

(50 Items x (20 Zeichen Key + 40 Zeichen Wert + ~21 JSON) + ~20 Envelope + 50 x 20 Zuschlag) / 4 = ~1.280.

Summen über 3 Locales

  • Eingabe: 24 x 1.388 = ~33.312 Tokens
  • Ausgabe: 24 x 1.280 = ~30.720 Tokens
  • Kosten: (33.312 / 1.000.000 x $0.10) + (30.720 / 1.000.000 x $0.40) = $0.0033 + $0.0123 = etwa 1,6 Cent

Beachte, wo der feste Overhead landet: Systemregeln und Schema machen 24 x 350 = 8.400 der 33.312 Eingabe-Tokens aus, etwa ein Viertel. Ein höheres maxBatchSize verteilt diese Konstante auf mehr Keys; ein niedrigeres (etwa um unter einem Rate-Limit zu bleiben) kostet proportional mehr.

Die genaue Methode: an einem Locale kalibrieren

Jede Schätzung oben ist eine Rechnung auf Annahmen. Die genaue Zahl kommt daraus, ein Locale echt zu übersetzen und die Tokens zu lesen, die verbatra meldet.

translate nimmt --locales entgegen, grenze den Lauf also direkt auf der Kommandozeile auf ein einzelnes konfiguriertes Locale ein:

verbatra translate --locales de
verbatra translate
  de: 400 translated, 0 unchanged, 18400 tokens (10800 in, 7600 out)
  total: 18400 tokens (10800 in, 7600 out)
1 succeeded, 0 partial, 0 failed

Multipliziere diesen gemessenen Wert mit der Zahl deiner übrigen Locales. Die Token-Nutzung steht auch in der --json-Ausgabe als usage.inputTokens und usage.outputTokens, ein Skript kann die Hochrechnung also übernehmen. Das ist die Zahl, die du demjenigen vorlegst, der die Ausgabe freigibt.

Der Kalibrierungslauf ist ein echter Lauf: er gibt echtes Geld aus und schreibt echte Übersetzungen für dieses Locale. Genau das ist der Sinn, und die Arbeit ist nicht verloren, weil die übrigen Locales von derselben Quelle ausgehen und das kalibrierte Locale nun fertig ist.

Um einen Lauf zu deckeln, statt ihn vorherzusagen, setze maxTokens mit budgetBehavior: "stop". Damit wird jeder Request projiziert, bevor er gesendet wird, und ein Request, der den Lauf über die Obergrenze brächte, wird zurückgehalten, ebenso jeder danach noch nicht versuchte Key; zurückgehaltene Keys werden im nächsten Lauf automatisch erneut versucht. Reserviert wird gegen dieselbe Projektion, die diese Seite beschreibt, einmal pro tatsächlich gesendetem Request; auch ein nach einer abgeschnittenen Antwort neu aufgeteilter Request wird also je Hälfte geprüft. Die Zählung wird nach jedem Request auf das abgeglichen, was der Provider meldet; ein Lauf kann deshalb um die Differenz des letzten zugelassenen Requests über der Obergrenze enden, und um nicht mehr. Zwei Dinge liegen außerhalb dessen, was eine Reservierung begrenzen kann, weil sie in einem bereits zugelassenen Request passieren: Die Provider-Schicht sendet einen eigenen Reparatur-Request, wenn Keys fehlen, ein zugelassener Batch kann also bis zu etwa das Doppelte seiner Projektion kosten, und die Zählung ist nur so gut wie das, was der Provider meldet. Beides landet beim Abgleich, und danach wird nichts weiter zugelassen. Die Obergrenze begrenzt einen Lauf: watch startet für jeden ausgelösten Lauf ein frisches Budget. Siehe die Konfigurationsreferenz.

DeepL wird anders abgerechnet

DeepL ist eine maschinelle Übersetzungs-API, kein nach Tokens abgerechnetes LLM, und folgt deshalb nicht der Formel oben:

  • Die abrechenbare Einheit sind Quellzeichen. Für das Beispielprojekt sind das 400 Keys x 40 Zeichen = 16.000 Zeichen pro Locale, 48.000 über alle drei.
  • verbatra sendet an DeepL nur den Quelltext. Es gibt keine Systemregeln, keine Key-Namen und keinen JSON-Envelope in der abgerechneten Payload, also auch keine Konstante pro Request, die sich amortisieren ließe.
  • DeepL hält Strings mit Platzhaltern oder ICU-Syntax zurück, statt sie zu riskieren. Die tatsächlich gesendeten Zeichen können also unter der Rohsumme liegen.
  • DeepL meldet keine Token-Nutzung, ein konfiguriertes maxTokens-Budget wird deshalb aus verbatras eigener Projektion gezählt. Es greift trotzdem; die Lauf-Zusammenfassung weist die Zahl als geschätzt statt als gemeldet aus.

Google Cloud Translation wird genauso abgerechnet

Verfügbar ab 0.10.0

Dafür brauchst du verbatra 0.10.0 oder neuer. Frühere Releases haben es nicht: Prüf deine installierte Version mit verbatra --version und aktualisiere, falls sie älter ist.

Google Cloud Translation ist ebenfalls eine maschinelle Übersetzungs-API und wird wie DeepL oben abgerechnet: Die Einheit sind Quellzeichen, keine Tokens (siehe Cloud Translation pricing). verbatra sendet nur den Quelltext, hält Strings mit Platzhaltern oder ICU-Syntax zurück, statt sie zu riskieren, und meldet keine Token-Nutzung, ein konfiguriertes maxTokens-Budget wird deshalb aus verbatras eigener Projektion gezählt, greift trotzdem und wird in der Lauf-Zusammenfassung als geschätzt statt als gemeldet ausgewiesen.

Warum der zweite Lauf fast kostenlos ist

Der mit Abstand größte Faktor dafür, was verbatra über die Zeit kostet, ist, dass Läufe inkrementell sind. Gesendet werden nur Keys, die fehlen oder deren Quelltext sich seit der Baseline in der Lock-Datei geändert hat. Ein unverändertes Projekt erneut laufen zu lassen, sendet nichts und kostet nichts.

Das durchgerechnete Beispiel oben sind also die Erstlauf-Kosten, die einmalige Rechnung dafür, ein Projekt von Grund auf zu übersetzen. Im Alltag zahlst du für die Handvoll Strings, die du seit dem letzten Lauf bearbeitet hast. Deshalb liegen die laufenden Kosten, ein Projekt übersetzt zu halten, weit unter der Anfangszahl. Der Cache senkt wiederkehrende Kosten weiter, indem er eine identische frühere Übersetzung wiederverwendet, statt sie zweimal zu bezahlen. Mit aktiviertem fuzzyCache geht er einen Schritt weiter und verwendet auch die Übersetzung eines nur leicht geänderten Quellstrings wieder, was der häufige Fall ist, sobald ein Projekt läuft.

Um das Ganze vorher zu null Kosten zu proben, nutze Geminis kostenlose Stufe oder richte den openai-compatible-Provider auf ein lokales Modell. Siehe Provider.

Edit on GitHub