@verbatra/sdk 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -15
- package/dist/config-schema.json +306 -0
- package/dist/index.cjs +725 -290
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +390 -75
- package/dist/index.d.ts +390 -75
- package/dist/index.js +724 -292
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/
|
|
2
|
+
<img src="https://raw.githubusercontent.com/verbatra/verbatra/main/.github/assets/verbatra-mark.png" alt="verbatra logo, a glowing V mark on a dark square" width="96" height="96" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">@verbatra/sdk</h1>
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
<a href="https://www.npmjs.com/package/@verbatra/sdk"><img src="https://img.shields.io/npm/v/@verbatra/sdk?label=%40verbatra%2Fsdk" alt="@verbatra/sdk npm version" /></a>
|
|
13
|
-
<a href="https://github.com/
|
|
14
|
-
<a href="https://codecov.io/gh/
|
|
15
|
-
<a href="https://github.com/
|
|
13
|
+
<a href="https://github.com/verbatra/verbatra/actions/workflows/ci.yml"><img src="https://github.com/verbatra/verbatra/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI" /></a>
|
|
14
|
+
<a href="https://codecov.io/gh/verbatra/verbatra"><img src="https://codecov.io/gh/verbatra/verbatra/graph/badge.svg" alt="Coverage" /></a>
|
|
15
|
+
<a href="https://github.com/verbatra/verbatra/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License: MIT" /></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
## Description
|
|
19
19
|
|
|
20
|
-
`@verbatra/sdk` is the engine behind verbatra: load and validate a config, run the one-shot translate flow over every target locale, watch the source and re-translate on each change, check or diff your locales without writing, or export and import
|
|
20
|
+
`@verbatra/sdk` is the engine behind verbatra: load and validate a config, run the one-shot translate flow over every target locale, watch the source and re-translate on each change, check or diff your locales without writing, validate the whole project setup before you spend anything, or export and import a translator handoff for manual translation. The [`@verbatra/cli`](https://github.com/verbatra/verbatra/tree/main/packages/cli) command is a thin wrapper over this package.
|
|
21
21
|
|
|
22
22
|
## Requirements
|
|
23
23
|
|
|
@@ -89,13 +89,13 @@ Discovers and validates the configuration. With no arguments it searches upward
|
|
|
89
89
|
|
|
90
90
|
### `translate(input): Promise<RunSummary>`
|
|
91
91
|
|
|
92
|
-
Runs the one-shot read, diff, translate, write flow over every target locale. `input` is a `TranslateInput`: `{ config, cwd?, dryRun?, prune?, generatePlurals?, cache?, concurrency?, lockAcquireTimeoutMs?, onProgress?, onLockWait? }`. With `dryRun: true` it reads, diffs, and reports without calling the provider or writing anything. `prune` and `generatePlurals` each override the matching config option for this run.
|
|
92
|
+
Runs the one-shot read, diff, translate, write flow over every target locale. `input` is a `TranslateInput`: `{ config, cwd?, locales?, dryRun?, prune?, generatePlurals?, cache?, concurrency?, lockAcquireTimeoutMs?, onProgress?, onLockWait? }`. With `dryRun: true` it reads, diffs, and reports without calling the provider or writing anything. `locales` narrows the run to a subset of the configured target locales, exactly as it does on `check` and `diff`, and a locale that is not configured raises `UNKNOWN_LOCALE` before anything is read or spent. `prune` and `generatePlurals` each override the matching config option for this run.
|
|
93
93
|
|
|
94
94
|
`cache` (on by default, and ignored on a dry run) toggles the local content-addressed translation-memory cache in `verbatra.cache.json`: a key whose source content is unchanged, including under a renamed key or shared with another key, is served from the cache instead of being re-sent to the provider. A cached value is re-checked against that key's own current source first, and one that fails the gate falls through to the provider rather than being written. `concurrency` (defaults to 1, strictly serial) is how many target locales may run at once; it must be an integer of at least 1, and on a live run a value above 1 is refused when the config sets `maxTokens`, because concurrent locales would overshoot the budget nondeterministically. `lockAcquireTimeoutMs` overrides how long a locale's write lock keeps retrying before it fails. `onProgress` receives a structured event once per locale before and after it runs, once per provider sub-batch, and once when the locale loop ends; `onLockWait` fires while a locale's write lock is blocked on another process holding it. The SDK writes to no stream, so these callbacks are the only progress signal.
|
|
95
95
|
|
|
96
96
|
Resolves to a `RunSummary`: `dryRun`, `locales`, `succeeded`, `partial`, `failed`, plus `usage` when any provider call reported tokens and `budget` when `maxTokens` is configured. A locale's `status` is `"succeeded"` when nothing was withheld (a no-op with no candidate keys included), `"partial"` when it accepted at least one key and withheld at least one, and `"failed"` when it withheld keys and accepted none, or threw. Each `LocaleSummary` carries `locale`, `status`, `translated`, `unchanged`, `orphaned`, `pruned`, `invalidIcuSource`, `cacheHits`, `integrityMismatches`, `providerFailures`, `budgetWithheld`, `generated`, `notices`, `needsReview`, `unfilled`, `malformedRows`, `duplicateKeys`, an optional `usage`, and an optional `error` on a locale that threw. `cacheHits` are keys served from the translation-memory cache rather than the provider. `integrityMismatches` is a translation that came back and was withheld by verbatra's integrity gate, whose rejection reasons are the exported `IntegrityGateReason` union. `providerFailures` is a key withheld because nothing was translated for it (the provider call failed, or the response was still missing that key), with any secret-free failure code and message reported in `notices`. `budgetWithheld` is a candidate never sent because a `maxTokens` budget in `"stop"` mode had already tripped. `needsReview` flags accepted keys the review heuristics want a human to look at, and never withholds anything. `unfilled`, `malformedRows`, and `duplicateKeys` are populated only by `importWorkbook`, which returns this same shape. Every withheld key keeps its prior lock hash and is retried next run.
|
|
97
97
|
|
|
98
|
-
Whole-run failures throw an `SdkError`: an unknown format, provider construction (including a missing API key), an unreadable or invalid source file, a corrupt lock file, an invalid `concurrency`, or the concurrency-and-budget conflict above. A per-locale failure never throws; it is isolated on that locale's summary. On a non-dry run the flow also writes `.verbatra-local/run-status.json` (best-effort, read back through `runStatus`).
|
|
98
|
+
Whole-run failures throw an `SdkError`: an unknown format, a `locales` entry that is not a configured target, provider construction (including a missing API key), an unreadable or invalid source file, a corrupt lock file, an invalid `concurrency`, or the concurrency-and-budget conflict above. A per-locale failure never throws; it is isolated on that locale's summary. On a non-dry run the flow also writes `.verbatra-local/run-status.json` (best-effort, read back through `runStatus`).
|
|
99
99
|
|
|
100
100
|
```ts
|
|
101
101
|
const preview = await translate({ config, dryRun: true });
|
|
@@ -103,9 +103,9 @@ const preview = await translate({ config, dryRun: true });
|
|
|
103
103
|
|
|
104
104
|
### `watch(input): Promise<WatchController>`
|
|
105
105
|
|
|
106
|
-
Watches the source file and re-runs the translate flow on each debounced change. `input` is `{ config, cwd?, debounceMs?, onRun, cache?, concurrency?, lockAcquireTimeoutMs?, onLockWait?, onProgress? }`; `debounceMs` defaults to 300, and the last five are passed straight through to every run. One run starts immediately at startup, before any change arrives. Runs are serialized, so changes during a run collapse into a single follow-up.
|
|
106
|
+
Watches the source file and re-runs the translate flow on each debounced change. `input` is `{ config, cwd?, locales?, debounceMs?, onRun, cache?, concurrency?, lockAcquireTimeoutMs?, onLockWait?, onProgress? }`; `debounceMs` defaults to 300, `locales` narrows every run of the session to a subset of the configured target locales and is validated once at startup rather than per cycle, and the last five are passed straight through to every run. One run starts immediately at startup, before any change arrives. Runs are serialized, so changes during a run collapse into a single follow-up.
|
|
107
107
|
|
|
108
|
-
`onRun` receives a `WatchRunResult` per run: `{ status: "succeeded", summary }` or `{ status: "failed", error }` with a secret-free `{ code, message }`, so a failing run is reported and watching continues. `watch` itself throws only at startup: `CONCURRENCY_INVALID` or `CONCURRENCY_BUDGET_CONFLICT` for a `concurrency` no cycle could honor (resolved once, before the watcher exists, rather than failing every cycle), and `SOURCE_UNREADABLE` when the source locale file is absent. Resolves to a `WatchController` whose `stop()` closes the watcher and awaits the in-flight run.
|
|
108
|
+
`onRun` receives a `WatchRunResult` per run: `{ status: "succeeded", summary }` or `{ status: "failed", error }` with a secret-free `{ code, message }`, so a failing run is reported and watching continues. `watch` itself throws only at startup: `UNKNOWN_LOCALE` for a `locales` entry that is not a configured target, `CONCURRENCY_INVALID` or `CONCURRENCY_BUDGET_CONFLICT` for a `concurrency` no cycle could honor (resolved once, before the watcher exists, rather than failing every cycle), and `SOURCE_UNREADABLE` when the source locale file is absent. Resolves to a `WatchController` whose `stop()` closes the watcher and awaits the in-flight run.
|
|
109
109
|
|
|
110
110
|
```ts
|
|
111
111
|
import { loadConfig, watch } from "@verbatra/sdk";
|
|
@@ -146,13 +146,33 @@ const config = await loadConfig();
|
|
|
146
146
|
const summary = await diff({ config });
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
+
### `doctor(input?): Promise<DoctorResult>`
|
|
150
|
+
|
|
151
|
+
Validates the project setup and spends nothing: no provider is constructed, no network request is made, no file is written, and no API key value is ever read. `input` is `{ cwd?, configPath? }`, and it is optional as a whole because `doctor` loads the config itself, so a project with no config at all still gets a report rather than a thrown error. Five checks run, one per `DoctorCheckId`: `"config"` (a config was found and validates), `"format-adapter"` (the configured `format` resolves to an adapter), `"provider"` (the configured `provider.id` resolves to a factory), `"api-key"` (the environment variable that provider reads its key from is set), and `"source-file"` (the source locale file exists at its resolved path). Every check runs even when an earlier one failed, so one call reports every independent problem; when the config itself cannot be loaded, the four checks that depend on it report `"skipped"` instead of a verdict they could not reach. Resolves to a `DoctorResult` whose `ok` is true only when no check failed, and whose `checks` carry an `id`, a stable `title`, a `status` of `"pass"`, `"fail"`, or `"skipped"`, and a `detail` naming the variable or path behind the verdict but never a key value. Throws `CONFIG_NOT_FOUND` only for an explicit `configPath` that does not exist; a config that is merely absent from the search is a failed check instead.
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import { doctor } from "@verbatra/sdk";
|
|
155
|
+
|
|
156
|
+
const report = await doctor();
|
|
157
|
+
|
|
158
|
+
for (const entry of report.checks) {
|
|
159
|
+
console.log(`${entry.status}: ${entry.title} - ${entry.detail}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
process.exitCode = report.ok ? 0 : 1;
|
|
163
|
+
```
|
|
164
|
+
|
|
149
165
|
### `exportWorkbook(input): Promise<ExportWorkbookResult>`
|
|
150
166
|
|
|
151
|
-
Exports the strings that need translating into a
|
|
167
|
+
Exports the strings that need translating into a handoff for a human translator. `input` is `{ config, cwd?, out?, locales?, includeUnchanged?, format? }`. By default it writes the missing and changed strings for every target locale; `locales` narrows which target locales are exported, and `includeUnchanged: true` also exports already up-to-date strings. No provider is called and no lock file is written.
|
|
168
|
+
|
|
169
|
+
`format` is an `ExchangeFormat`, one of the exported `EXCHANGE_FORMATS` and defaulting to `DEFAULT_EXCHANGE_FORMAT` (`"xlsx"`). With `"xlsx"` it writes one styled workbook with a sheet per locale to `DEFAULT_WORKBOOK_PATH` (`verbatra-translations.xlsx`). With `"csv"` or `"tsv"` it writes one plain `<locale>.csv` or `<locale>.tsv` per exported locale into a directory, `DEFAULT_DELIMITED_PATH` (`verbatra-translations`) by default, creating it if it is missing, and it also leaves a hidden manifest there naming the locales it wrote, which is what lets a later import reject a file left over from a wider export. `out` overrides the default: a file path for `"xlsx"`, a directory for the delimited formats. Resolves to an `ExportWorkbookResult` with the absolute `path` written (the shared directory when one file per locale was written) and a per-locale row count.
|
|
152
170
|
|
|
153
171
|
### `importWorkbook(input): Promise<RunSummary>`
|
|
154
172
|
|
|
155
|
-
Imports a filled
|
|
173
|
+
Imports a filled handoff back into the locale files, gating every row through the same integrity gate as `translate` on top of a fresh source-drift check. `input` is `{ config, workbook, cwd?, dryRun?, format? }`. With `dryRun: true` it validates and reports without writing locale files or updating the lock.
|
|
174
|
+
|
|
175
|
+
`format` takes the same `ExchangeFormat` values as `exportWorkbook` and must match how the handoff was written. For `"xlsx"`, `workbook` is the workbook file and the locale comes from the sheet name. For `"csv"` and `"tsv"` the locale comes from the file name instead, and `workbook` is tried as a single `<locale>.csv` file first, so one locale can be imported on its own; if no file exists there it is read as the directory the per-locale files were written into. A file in that directory that the most recent export's manifest does not list is refused as a leftover rather than applied, and reported as that locale's failure with `HANDOFF_FILE_STALE`; a directory with no readable manifest is read as it always was, with every file present imported. Resolves to a `RunSummary`, the same shape `translate` returns: a row the translator left blank whose key still needs a translation is reported in that locale's `unfilled` (nothing is written and the prior lock baseline is kept), an unreadable row in `malformedRows`, a repeated key in `duplicateKeys` (the first occurrence wins), and a configured target locale whose sheet or delimited file is missing from the handoff is reported as that locale's failed summary rather than silently dropped. `unfilled`, `malformedRows`, and `duplicateKeys` do not feed a locale's `status`, so a partly filled sheet still imports the rows it has. A key is cleared by filling its Translation cell with the `[[CLEAR]]` sentinel; an ordinary blank never clears a value.
|
|
156
176
|
|
|
157
177
|
```ts
|
|
158
178
|
import { exportWorkbook, importWorkbook, loadConfig } from "@verbatra/sdk";
|
|
@@ -170,7 +190,7 @@ See [Manual translation](https://verbatra.kreitz-webdev.de/docs/manual-translati
|
|
|
170
190
|
|
|
171
191
|
### More entry points
|
|
172
192
|
|
|
173
|
-
Beyond the flows above, the SDK exports the building blocks Verbatra Studio and other tooling sit on
|
|
193
|
+
Beyond the flows above, the SDK exports the building blocks Verbatra Studio and other tooling sit on. Most are a one-call read or a locked single-key write:
|
|
174
194
|
|
|
175
195
|
- `keyIntegrity` reports, per changed key, whether its placeholders still match the source (with the missing and extra tokens on a mismatch) and whether the current target value is still valid ICU.
|
|
176
196
|
- `lockState` reports the lock file's existence, version, and per-locale drift; `loadLockFile` reads the lock file itself.
|
|
@@ -179,6 +199,15 @@ Beyond the flows above, the SDK exports the building blocks Verbatra Studio and
|
|
|
179
199
|
- `editEntry` saves a manually edited translation for one key, and `retranslateEntry` re-runs the provider for one key; both run the candidate through the same integrity gate as a full run (a rejection names an `IntegrityGateReason` and writes nothing) and hold the same per-locale write lock.
|
|
180
200
|
- `readLocaleFileSnapshot` and `diffLocaleSnapshots` snapshot one locale file as per-key content hashes and compare two snapshots, the primitives behind live-refresh watching.
|
|
181
201
|
- `loadConfigWithMeta` is `loadConfig` plus config-source and glossary provenance.
|
|
202
|
+
- `readGlossaryFile` reads a file-backed glossary fresh from disk, under the same validation `loadConfig` applies, for a long-running tool that has to show the glossary as it is now rather than as it was when the config was loaded. `updateGlossaryTerm` adds, replaces, or removes exactly one term (`translation: null` removes it) and returns the glossary as it now stands, keeping the file's existing key order and indentation. Both take the `GlossaryProvenance` from `loadConfigWithMeta` rather than a path, so the file they touch is always the one the config names. A write runs under a project-wide glossary lock and replaces the file atomically. Only a file-backed glossary can be read or changed this way: a glossary written inline in the config module is refused with `GLOSSARY_NOT_FILE_BACKED` rather than rewritten, and a failed write is `GLOSSARY_UNWRITABLE`.
|
|
203
|
+
|
|
204
|
+
The rest are the values a tool needs to agree with verbatra rather than restate it:
|
|
205
|
+
|
|
206
|
+
- `createLocalePathResolver` builds the two-way locale-to-path mapping from the `sourceLocale`, `targetLocales`, and `files` slice of a config: `pathFor(locale)` gives a locale's absolute file path and `localeFor(path)` gives the configured locale owning a path, which is how a file watcher decides whether a change concerns verbatra at all.
|
|
207
|
+
- `EXCHANGE_FORMATS`, `DEFAULT_EXCHANGE_FORMAT`, `DEFAULT_WORKBOOK_PATH`, and `DEFAULT_DELIMITED_PATH` are the handoff formats and their default output paths, so a `--format` argument can be validated and offered without restating the list. `EXCHANGE_FORMATS` is derived from the `ExchangeFormat` type itself, so it can never drift behind a format the SDK accepts.
|
|
208
|
+
- `CACHE_FILE_NAME` and `LOCK_FILE_NAME` are the names of the two files a run maintains in the project (`verbatra.cache.json` and `verbatra.lock.json`), for tooling that has to find, gitignore, or clear them.
|
|
209
|
+
- `verbatraConfigSchema` is the zod schema `loadConfig` validates against, for validating a config object you assembled yourself. The same schema is published as a JSON Schema document at `@verbatra/sdk/config-schema.json`, generated at build time, so an editor can complete and validate a `.verbatrarc.json` or YAML config; the config accepts an optional top-level `$schema` key to point at it, which is ignored at runtime. `scaffoldingMetadata` carries the facts a project generator needs to write a first config (each provider's key environment variable, a starting model, the token-limit option name it takes, and the supported formats), which is what `verbatra init` renders from. Neither holds an API key value.
|
|
210
|
+
- `SdkFs` is the file-system port every file the SDK touches goes through, so supplying your own as the `deps.fs` option redirects all of it and an entire run can be held in memory: the run-status file, the lock file, the config glossary, the workbook and delimited I/O, and the locale files themselves, which the format adapters read and write through a port built from this one. Reads are size-bounded by contract and writes are expected to be atomic. The single exception is a caller-supplied `deps.adapterRegistry`: those adapters were constructed by you, so `deps.fs` cannot reach them and passing both means you own that wiring.
|
|
182
211
|
|
|
183
212
|
## Errors and results
|
|
184
213
|
|
|
@@ -189,9 +218,9 @@ Per-locale failures do not throw: they are recorded on the `RunSummary` so one f
|
|
|
189
218
|
## Documentation
|
|
190
219
|
|
|
191
220
|
- [Documentation site](https://verbatra.kreitz-webdev.de)
|
|
192
|
-
- [Project README](https://github.com/
|
|
193
|
-
- [`@verbatra/cli`](https://github.com/
|
|
221
|
+
- [Project README](https://github.com/verbatra/verbatra)
|
|
222
|
+
- [`@verbatra/cli`](https://github.com/verbatra/verbatra/tree/main/packages/cli) for the command-line tool
|
|
194
223
|
|
|
195
224
|
## License
|
|
196
225
|
|
|
197
|
-
[MIT](https://github.com/
|
|
226
|
+
[MIT](https://github.com/verbatra/verbatra/blob/main/LICENSE) (c) Mario Kreitz
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"$schema": {
|
|
6
|
+
"type": "string"
|
|
7
|
+
},
|
|
8
|
+
"sourceLocale": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"minLength": 1
|
|
11
|
+
},
|
|
12
|
+
"targetLocales": {
|
|
13
|
+
"minItems": 1,
|
|
14
|
+
"type": "array",
|
|
15
|
+
"items": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"minLength": 1
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"format": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"enum": [
|
|
23
|
+
"i18next-json",
|
|
24
|
+
"vue-i18n-json",
|
|
25
|
+
"next-intl-json",
|
|
26
|
+
"ngx-translate-json",
|
|
27
|
+
"xliff",
|
|
28
|
+
"yaml",
|
|
29
|
+
"arb",
|
|
30
|
+
"properties"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"files": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"properties": {
|
|
36
|
+
"pattern": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"minLength": 1,
|
|
39
|
+
"pattern": "\\{locale\\}"
|
|
40
|
+
},
|
|
41
|
+
"localeStyle": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"enum": [
|
|
44
|
+
"literal",
|
|
45
|
+
"posix",
|
|
46
|
+
"android"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"required": [
|
|
51
|
+
"pattern"
|
|
52
|
+
],
|
|
53
|
+
"additionalProperties": false
|
|
54
|
+
},
|
|
55
|
+
"provider": {
|
|
56
|
+
"oneOf": [
|
|
57
|
+
{
|
|
58
|
+
"type": "object",
|
|
59
|
+
"properties": {
|
|
60
|
+
"id": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"const": "anthropic"
|
|
63
|
+
},
|
|
64
|
+
"options": {
|
|
65
|
+
"type": "object",
|
|
66
|
+
"properties": {
|
|
67
|
+
"model": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"minLength": 1
|
|
70
|
+
},
|
|
71
|
+
"maxTokens": {
|
|
72
|
+
"type": "integer",
|
|
73
|
+
"exclusiveMinimum": 0,
|
|
74
|
+
"maximum": 9007199254740991
|
|
75
|
+
},
|
|
76
|
+
"requestTimeoutMs": {
|
|
77
|
+
"type": "integer",
|
|
78
|
+
"exclusiveMinimum": 0,
|
|
79
|
+
"maximum": 9007199254740991
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"required": [
|
|
83
|
+
"model",
|
|
84
|
+
"maxTokens"
|
|
85
|
+
],
|
|
86
|
+
"additionalProperties": false
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"required": [
|
|
90
|
+
"id",
|
|
91
|
+
"options"
|
|
92
|
+
],
|
|
93
|
+
"additionalProperties": false
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"type": "object",
|
|
97
|
+
"properties": {
|
|
98
|
+
"id": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"const": "openai"
|
|
101
|
+
},
|
|
102
|
+
"options": {
|
|
103
|
+
"type": "object",
|
|
104
|
+
"properties": {
|
|
105
|
+
"model": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"minLength": 1
|
|
108
|
+
},
|
|
109
|
+
"maxOutputTokens": {
|
|
110
|
+
"type": "integer",
|
|
111
|
+
"exclusiveMinimum": 0,
|
|
112
|
+
"maximum": 9007199254740991
|
|
113
|
+
},
|
|
114
|
+
"requestTimeoutMs": {
|
|
115
|
+
"type": "integer",
|
|
116
|
+
"exclusiveMinimum": 0,
|
|
117
|
+
"maximum": 9007199254740991
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"required": [
|
|
121
|
+
"model",
|
|
122
|
+
"maxOutputTokens"
|
|
123
|
+
],
|
|
124
|
+
"additionalProperties": false
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"required": [
|
|
128
|
+
"id",
|
|
129
|
+
"options"
|
|
130
|
+
],
|
|
131
|
+
"additionalProperties": false
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"type": "object",
|
|
135
|
+
"properties": {
|
|
136
|
+
"id": {
|
|
137
|
+
"type": "string",
|
|
138
|
+
"const": "gemini"
|
|
139
|
+
},
|
|
140
|
+
"options": {
|
|
141
|
+
"type": "object",
|
|
142
|
+
"properties": {
|
|
143
|
+
"model": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"minLength": 1
|
|
146
|
+
},
|
|
147
|
+
"maxOutputTokens": {
|
|
148
|
+
"type": "integer",
|
|
149
|
+
"exclusiveMinimum": 0,
|
|
150
|
+
"maximum": 9007199254740991
|
|
151
|
+
},
|
|
152
|
+
"requestTimeoutMs": {
|
|
153
|
+
"type": "integer",
|
|
154
|
+
"exclusiveMinimum": 0,
|
|
155
|
+
"maximum": 9007199254740991
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"required": [
|
|
159
|
+
"model",
|
|
160
|
+
"maxOutputTokens"
|
|
161
|
+
],
|
|
162
|
+
"additionalProperties": false
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"required": [
|
|
166
|
+
"id",
|
|
167
|
+
"options"
|
|
168
|
+
],
|
|
169
|
+
"additionalProperties": false
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"type": "object",
|
|
173
|
+
"properties": {
|
|
174
|
+
"id": {
|
|
175
|
+
"type": "string",
|
|
176
|
+
"const": "deepl"
|
|
177
|
+
},
|
|
178
|
+
"options": {
|
|
179
|
+
"type": "object",
|
|
180
|
+
"properties": {
|
|
181
|
+
"glossaryId": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"minLength": 1
|
|
184
|
+
},
|
|
185
|
+
"requestTimeoutMs": {
|
|
186
|
+
"type": "integer",
|
|
187
|
+
"exclusiveMinimum": 0,
|
|
188
|
+
"maximum": 9007199254740991
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"additionalProperties": false
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
"required": [
|
|
195
|
+
"id",
|
|
196
|
+
"options"
|
|
197
|
+
],
|
|
198
|
+
"additionalProperties": false
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"type": "object",
|
|
202
|
+
"properties": {
|
|
203
|
+
"id": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"const": "openai-compatible"
|
|
206
|
+
},
|
|
207
|
+
"options": {
|
|
208
|
+
"type": "object",
|
|
209
|
+
"properties": {
|
|
210
|
+
"baseUrl": {
|
|
211
|
+
"type": "string",
|
|
212
|
+
"pattern": "^https?:\\/\\/"
|
|
213
|
+
},
|
|
214
|
+
"model": {
|
|
215
|
+
"type": "string",
|
|
216
|
+
"minLength": 1
|
|
217
|
+
},
|
|
218
|
+
"maxOutputTokens": {
|
|
219
|
+
"type": "integer",
|
|
220
|
+
"exclusiveMinimum": 0,
|
|
221
|
+
"maximum": 9007199254740991
|
|
222
|
+
},
|
|
223
|
+
"apiKeyEnvVar": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"minLength": 1
|
|
226
|
+
},
|
|
227
|
+
"requestTimeoutMs": {
|
|
228
|
+
"type": "integer",
|
|
229
|
+
"exclusiveMinimum": 0,
|
|
230
|
+
"maximum": 9007199254740991
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"required": [
|
|
234
|
+
"baseUrl",
|
|
235
|
+
"model",
|
|
236
|
+
"maxOutputTokens"
|
|
237
|
+
],
|
|
238
|
+
"additionalProperties": false
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
"required": [
|
|
242
|
+
"id",
|
|
243
|
+
"options"
|
|
244
|
+
],
|
|
245
|
+
"additionalProperties": false
|
|
246
|
+
}
|
|
247
|
+
]
|
|
248
|
+
},
|
|
249
|
+
"glossary": {
|
|
250
|
+
"anyOf": [
|
|
251
|
+
{
|
|
252
|
+
"type": "object",
|
|
253
|
+
"propertyNames": {
|
|
254
|
+
"type": "string"
|
|
255
|
+
},
|
|
256
|
+
"additionalProperties": {
|
|
257
|
+
"type": "string"
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"type": "string",
|
|
262
|
+
"minLength": 1
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
"tone": {
|
|
267
|
+
"type": "string",
|
|
268
|
+
"enum": [
|
|
269
|
+
"formal",
|
|
270
|
+
"informal",
|
|
271
|
+
"neutral"
|
|
272
|
+
]
|
|
273
|
+
},
|
|
274
|
+
"prune": {
|
|
275
|
+
"type": "boolean"
|
|
276
|
+
},
|
|
277
|
+
"generatePlurals": {
|
|
278
|
+
"type": "boolean"
|
|
279
|
+
},
|
|
280
|
+
"maxBatchSize": {
|
|
281
|
+
"type": "integer",
|
|
282
|
+
"exclusiveMinimum": 0,
|
|
283
|
+
"maximum": 9007199254740991
|
|
284
|
+
},
|
|
285
|
+
"maxTokens": {
|
|
286
|
+
"type": "integer",
|
|
287
|
+
"exclusiveMinimum": 0,
|
|
288
|
+
"maximum": 9007199254740991
|
|
289
|
+
},
|
|
290
|
+
"budgetBehavior": {
|
|
291
|
+
"type": "string",
|
|
292
|
+
"enum": [
|
|
293
|
+
"warn",
|
|
294
|
+
"stop"
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
"required": [
|
|
299
|
+
"sourceLocale",
|
|
300
|
+
"targetLocales",
|
|
301
|
+
"format",
|
|
302
|
+
"files",
|
|
303
|
+
"provider"
|
|
304
|
+
],
|
|
305
|
+
"additionalProperties": false
|
|
306
|
+
}
|