@braze/sanity-plugin-ai-translation 0.3.0 → 0.3.2
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 +24 -3
- package/dist/index.d.ts +88 -19
- package/dist/index.js +70 -65
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +39 -1
- package/dist/server.js +12 -1
- package/dist/server.js.map +1 -1
- package/package.json +35 -35
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ Your Studio must already support internationalized documents.
|
|
|
64
64
|
|
|
65
65
|
Required:
|
|
66
66
|
|
|
67
|
-
- **Sanity Studio
|
|
67
|
+
- **Sanity Studio v6.12 or newer** with `@sanity/ui` v4, React 19.2+, and Node.js 22.12+ (the plugin invokes Sanity Functions through Studio's client, which needs `@sanity/client` 8.3+; Studio 6.12 is the first release that bundles it)
|
|
68
68
|
- `@sanity/document-internationalization` configured
|
|
69
69
|
- `sanity-plugin-internationalized-array` installed and configured (used for glossary term translations)
|
|
70
70
|
- `@sanity/client` **7.1.0+** (required for Agent Actions)
|
|
@@ -159,6 +159,7 @@ export default defineConfig({
|
|
|
159
159
|
|
|
160
160
|
- `schemaId` is usually `'_.schemas.default'` for most projects.
|
|
161
161
|
- `languageFieldName` must match the field your documents use (often `language`).
|
|
162
|
+
- `glossaryDataset` (optional) reads glossary terms from another dataset in the same project. See [`translationGlossaryTerm`](#translationglossaryterm).
|
|
162
163
|
|
|
163
164
|
### 3) Add translation history metadata
|
|
164
165
|
|
|
@@ -247,9 +248,16 @@ aiTranslationPlugin({
|
|
|
247
248
|
The plugin exposes a server-only entry at `@braze/sanity-plugin-ai-translation/server` for running the OpenAI call outside the browser (for example in a Sanity function). It does not load React or Studio, it is not part of the Studio bundle, and it does not read the API key from the environment, so the caller passes it in.
|
|
248
249
|
|
|
249
250
|
```typescript
|
|
250
|
-
import {
|
|
251
|
+
import {
|
|
252
|
+
isOpenAIModel,
|
|
253
|
+
OPENAI_MODELS,
|
|
254
|
+
requestOpenAICompletion,
|
|
255
|
+
} from "@braze/sanity-plugin-ai-translation/server";
|
|
251
256
|
|
|
252
257
|
// payload: { model, messages, reasoningEffort?, temperature? } assembled in Studio
|
|
258
|
+
if (!isOpenAIModel(payload.model)) {
|
|
259
|
+
throw new Error(`model must be one of ${OPENAI_MODELS.join(", ")}`);
|
|
260
|
+
}
|
|
253
261
|
const { content, tokensUsed } = await requestOpenAICompletion(payload, {
|
|
254
262
|
apiKey: process.env.OPENAI_API_KEY!,
|
|
255
263
|
});
|
|
@@ -261,7 +269,7 @@ The first argument is the client-supplied request and is validated at runtime. T
|
|
|
261
269
|
- Only `role` and `content` are sent for each message. Any other fields in the payload are dropped.
|
|
262
270
|
- Logs never include prompt or document text, even with plugin logging turned on. They include only the model, message roles, and content lengths.
|
|
263
271
|
|
|
264
|
-
Serialization, prompt assembly, structure validation, and the Content Release write stay in Studio. The entry does not allowlist models. Do that in the caller before invoking it.
|
|
272
|
+
Serialization, prompt assembly, structure validation, and the Content Release write stay in Studio. The entry does not allowlist models on its own. Do that in the caller before invoking it, with `isOpenAIModel` (or `OPENAI_MODELS`): it is the same list the `openai.model` plugin option accepts, so Studio and the function never disagree about which models are allowed.
|
|
265
273
|
|
|
266
274
|
---
|
|
267
275
|
|
|
@@ -382,6 +390,19 @@ Conceptual example:
|
|
|
382
390
|
|
|
383
391
|
Glossary terms are used to build locale-specific translation instructions.
|
|
384
392
|
|
|
393
|
+
By default, glossary terms are read from the dataset of the document being translated. To share one glossary across datasets, set `glossaryDataset` to another dataset in the same project:
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
aiTranslationPlugin({
|
|
397
|
+
// ...
|
|
398
|
+
glossaryDataset: "production",
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
- Terms are read with the editor's existing Studio session, so editors need read access to that dataset.
|
|
403
|
+
- Only glossary terms come from `glossaryDataset`. `translationSettings` (global prompt, locale prompts, protected phrases) is still read from the document's dataset.
|
|
404
|
+
- Nothing is written to either dataset's glossary.
|
|
405
|
+
|
|
385
406
|
---
|
|
386
407
|
|
|
387
408
|
## Advanced configuration
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import { ArrayDefinition } from "sanity";
|
|
2
|
-
import { FieldDefinitionBase } from "sanity";
|
|
3
1
|
import { Plugin as Plugin_2 } from "sanity";
|
|
4
2
|
import type { SanityDocument } from "sanity";
|
|
5
|
-
import { WidenInitialValue } from "sanity";
|
|
6
|
-
import { WidenValidation } from "sanity";
|
|
7
3
|
|
|
8
4
|
/**
|
|
9
5
|
* AI translation plugin for Sanity Studio
|
|
@@ -269,6 +265,26 @@ export declare type InferOriginalType<T> =
|
|
|
269
265
|
export declare type InferTranslatableType<T> =
|
|
270
266
|
T extends FieldTransform<unknown, infer R> ? R : never;
|
|
271
267
|
|
|
268
|
+
/**
|
|
269
|
+
* OpenAI models the plugin supports.
|
|
270
|
+
*
|
|
271
|
+
* This is the single source of truth: Studio's `PluginConfig['openai']['model']` is derived from
|
|
272
|
+
* it, and the translation function allowlists against it before calling `requestOpenAICompletion`,
|
|
273
|
+
* so the two can never drift apart.
|
|
274
|
+
*
|
|
275
|
+
* @public
|
|
276
|
+
*/
|
|
277
|
+
declare const OPENAI_MODELS: readonly [
|
|
278
|
+
"gpt-5.1",
|
|
279
|
+
"gpt-5",
|
|
280
|
+
"gpt-5-mini",
|
|
281
|
+
"gpt-5-nano",
|
|
282
|
+
"gpt-5-pro",
|
|
283
|
+
"gpt-4o",
|
|
284
|
+
"gpt-4-turbo",
|
|
285
|
+
"gpt-4",
|
|
286
|
+
];
|
|
287
|
+
|
|
272
288
|
/**
|
|
273
289
|
* Event emitted when an OpenAI API call is made
|
|
274
290
|
* @public
|
|
@@ -288,6 +304,13 @@ declare interface OpenAIApiCallEvent extends TelemetryEventBase {
|
|
|
288
304
|
};
|
|
289
305
|
}
|
|
290
306
|
|
|
307
|
+
/**
|
|
308
|
+
* An OpenAI model id from {@link OPENAI_MODELS}
|
|
309
|
+
*
|
|
310
|
+
* @public
|
|
311
|
+
*/
|
|
312
|
+
export declare type OpenAIModel = (typeof OPENAI_MODELS)[number];
|
|
313
|
+
|
|
291
314
|
/**
|
|
292
315
|
*
|
|
293
316
|
* Configuration for the Sanity AI Translation plugin.
|
|
@@ -310,22 +333,18 @@ export declare interface PluginConfig {
|
|
|
310
333
|
* Requires `@sanity/client` 8.1 or newer as Studio's client.
|
|
311
334
|
*/
|
|
312
335
|
openai?: {
|
|
313
|
-
/** Blueprint stack that contains the translation function, e.g. `ST-
|
|
336
|
+
/** Blueprint stack that contains the translation function, e.g. `ST-xxxxxxxxxx`. Required for OpenAI mode. */
|
|
314
337
|
stackId: string;
|
|
315
338
|
/**
|
|
316
339
|
* Name of the translation function, as declared in the blueprint.
|
|
317
340
|
* @defaultValue 'ai-translation'
|
|
318
341
|
*/
|
|
319
342
|
functionName?: string;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
| "gpt-5-pro"
|
|
326
|
-
| "gpt-4o"
|
|
327
|
-
| "gpt-4-turbo"
|
|
328
|
-
| "gpt-4";
|
|
343
|
+
/**
|
|
344
|
+
* OpenAI model id. Must be one of `OPENAI_MODELS` from the server entry.
|
|
345
|
+
* @defaultValue 'gpt-5'
|
|
346
|
+
*/
|
|
347
|
+
model?: OpenAIModel;
|
|
329
348
|
reasoningEffort?: "low" | "medium" | "high";
|
|
330
349
|
enabled?: boolean;
|
|
331
350
|
defaultMode?: TranslationMode;
|
|
@@ -362,6 +381,17 @@ export declare interface PluginConfig {
|
|
|
362
381
|
* ```
|
|
363
382
|
*/
|
|
364
383
|
unsetFields?: UnsetFieldEntry[];
|
|
384
|
+
/**
|
|
385
|
+
* Dataset (in the same project) to read `translationGlossaryTerm` documents from.
|
|
386
|
+
* Defaults to the dataset of the document being translated.
|
|
387
|
+
* Translation settings and locale prompts are always read from the document's dataset.
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* ```typescript
|
|
391
|
+
* glossaryDataset: 'production'
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
394
|
+
glossaryDataset?: string;
|
|
365
395
|
/**
|
|
366
396
|
* Optional telemetry configuration for monitoring translation operations.
|
|
367
397
|
* Provides callbacks for lightweight events and detailed error bundles.
|
|
@@ -684,12 +714,51 @@ declare type TranslationErrorType =
|
|
|
684
714
|
* @public
|
|
685
715
|
*/
|
|
686
716
|
export declare const translationHistorySchema: {
|
|
687
|
-
type: "array";
|
|
688
717
|
name: "translationHistory";
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
718
|
+
type: "array";
|
|
719
|
+
of: {
|
|
720
|
+
name: string;
|
|
721
|
+
type: "object";
|
|
722
|
+
fields: (
|
|
723
|
+
| {
|
|
724
|
+
name: "language";
|
|
725
|
+
title: string;
|
|
726
|
+
description: string;
|
|
727
|
+
type: "string";
|
|
728
|
+
}
|
|
729
|
+
| {
|
|
730
|
+
name: "sourceId";
|
|
731
|
+
title: string;
|
|
732
|
+
description: string;
|
|
733
|
+
type: "string";
|
|
734
|
+
}
|
|
735
|
+
| {
|
|
736
|
+
name: "sourceRev";
|
|
737
|
+
title: string;
|
|
738
|
+
description: string;
|
|
739
|
+
type: "string";
|
|
740
|
+
}
|
|
741
|
+
| {
|
|
742
|
+
name: "sourceLanguage";
|
|
743
|
+
title: string;
|
|
744
|
+
description: string;
|
|
745
|
+
type: "string";
|
|
746
|
+
}
|
|
747
|
+
| {
|
|
748
|
+
name: "sourceSnapshot";
|
|
749
|
+
title: string;
|
|
750
|
+
description: string;
|
|
751
|
+
type: "text";
|
|
752
|
+
}
|
|
753
|
+
| {
|
|
754
|
+
name: "targetId";
|
|
755
|
+
title: string;
|
|
756
|
+
description: string;
|
|
757
|
+
type: "string";
|
|
758
|
+
}
|
|
759
|
+
)[];
|
|
760
|
+
}[];
|
|
761
|
+
};
|
|
693
762
|
|
|
694
763
|
/**
|
|
695
764
|
* Event emitted when an individual translation job completes successfully
|