@braze/sanity-plugin-ai-translation 0.2.3 → 0.2.5

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 CHANGED
@@ -5,12 +5,11 @@
5
5
  ## Features
6
6
 
7
7
  - 🤖 **AI-Powered Translation** - Uses Sanity Agent Actions to translate documents between languages
8
- - 🔄 **Smart Translation Strategies** - Automatically detects translation freshness (fresh/stale/drifted) and applies appropriate strategy
8
+ - 📦 **Content Releases** - Translations are created in Content Releases for staged publishing
9
9
  - 🔗 **Reference Translation** - Optionally translate referenced documents recursively with configurable depth
10
10
  - 🎯 **Custom Translation Prompts** - Configure global and locale-specific translation instructions
11
11
  - 📚 **Translation Glossary** - Define term-specific translations to ensure consistency
12
12
  - 🛡️ **Protected Phrases** - Specify terms that should never be translated (e.g., brand names, product names)
13
- - 💬 **Feedback System** - AI-powered feedback analysis that automatically improves translation settings
14
13
  - ⚙️ **Flexible Configuration** - Control concurrent translation jobs, reference depth, and translation behavior
15
14
  - 🔍 **Debug Mode** - Comprehensive logging for troubleshooting translation issues
16
15
 
@@ -90,7 +89,7 @@ export default defineConfig({
90
89
 
91
90
  ### OpenAI Integration (Optional)
92
91
 
93
- The plugin supports optional OpenAI integration for enhanced translation capabilities, including review of Sanity translations and direct GPT-5 translation with no character limits.
92
+ The plugin supports optional OpenAI integration for enhanced translation capabilities, including direct OpenAI translation with no character limits.
94
93
 
95
94
  #### Setup
96
95
 
@@ -103,7 +102,7 @@ aiTranslationPlugin({
103
102
  reasoningEffort: 'medium', // Optional: 'minimal' | 'low' | 'medium' | 'high'
104
103
  verbosity: 'medium', // Optional: 'low' | 'medium' | 'high'
105
104
  enabled: true, // Optional, defaults to false
106
- defaultMode: 'sanity-with-review', // Optional, defaults to 'sanity-only'
105
+ defaultMode: 'openai-only', // Optional, defaults to 'sanity-only'
107
106
  }
108
107
  })
109
108
  ```
@@ -117,7 +116,7 @@ OPENAI_API_KEY=sk-...your-key-here...
117
116
 
118
117
  #### Translation Modes
119
118
 
120
- When OpenAI is enabled, users can select from three translation modes:
119
+ When OpenAI is enabled, users can select from two translation modes:
121
120
 
122
121
  1. **Sanity Agent Only** (Default)
123
122
  - Uses Sanity's built-in translation agent
@@ -125,21 +124,15 @@ When OpenAI is enabled, users can select from three translation modes:
125
124
  - No additional API costs
126
125
  - 2000 character style guide limit
127
126
 
128
- 2. **GPT-5 Only** (Beta)
129
- - Direct translation via GPT-5
127
+ 2. **OpenAI Only** (Beta)
128
+ - Direct translation via OpenAI
130
129
  - 1 million token context window
131
130
  - Full style guide capacity
132
131
  - Incurs OpenAI API costs
133
132
 
134
- 3. **Sanity + GPT-5 Review** (Highest Quality)
135
- - Sanity translation reviewed and refined by GPT-5
136
- - Best quality results
137
- - Approximately 2x processing time
138
- - Incurs OpenAI API costs
139
-
140
- #### GPT-5 Features
133
+ #### OpenAI Features
141
134
 
142
- GPT-5 (released August 2025) provides:
135
+ OpenAI models provide:
143
136
  - **1M token context window** - Handle very large documents and style guides
144
137
  - **Advanced reasoning** - Configurable reasoning effort for quality vs. speed tradeoff
145
138
  - **Verbosity control** - Adjust response length to optimize token usage
@@ -148,7 +141,7 @@ GPT-5 (released August 2025) provides:
148
141
  #### Cost Considerations
149
142
 
150
143
  OpenAI modes incur API costs based on token usage:
151
- - **GPT-5**: ~$0.002 per 1k input tokens, ~$0.010 per 1k output tokens, ~$0.005 per 1k reasoning tokens
144
+ - **OpenAI**: ~$0.002 per 1k input tokens, ~$0.010 per 1k output tokens, ~$0.005 per 1k reasoning tokens
152
145
  - **Typical article** (2000 words): ~$0.05-0.15 per translation
153
146
  - The plugin shows real-time cost estimates and usage summaries
154
147
 
@@ -158,8 +151,8 @@ OpenAI modes incur API costs based on token usage:
158
151
  |--------|------|---------|-------------|
159
152
  | `apiKey` | `string` | - | OpenAI API key (required if OpenAI enabled) |
160
153
  | `model` | `'gpt-5' \| 'gpt-4o' \| 'gpt-4-turbo' \| 'gpt-4'` | `'gpt-5'` | Model to use for translation/review |
161
- | `reasoningEffort` | `'minimal' \| 'low' \| 'medium' \| 'high'` | `'medium'` | GPT-5 reasoning effort (affects speed and quality) |
162
- | `verbosity` | `'low' \| 'medium' \| 'high'` | `'medium'` | GPT-5 response verbosity |
154
+ | `reasoningEffort` | `'minimal' \| 'low' \| 'medium' \| 'high'` | `'medium'` | OpenAI reasoning effort (affects speed and quality) |
155
+ | `verbosity` | `'low' \| 'medium' \| 'high'` | `'medium'` | OpenAI response verbosity |
163
156
  | `enabled` | `boolean` | `false` | Enable OpenAI features |
164
157
  | `defaultMode` | `TranslationMode` | `'sanity-only'` | Default translation mode when dialog opens |
165
158
 
@@ -205,19 +198,6 @@ Once configured, a "Translate" action will appear on all documents of types list
205
198
  - **Max reference depth** - How deep to traverse references (if enabled)
206
199
  5. Click "Translate" to start
207
200
 
208
- ### Translation States
209
-
210
- The plugin tracks three translation states:
211
-
212
- - **Fresh** ✅ - Translation is up-to-date with source
213
- - **Stale** ⚠️ - Source document revision changed (trivial changes)
214
- - **Drifted** 🔴 - Source document content changed significantly
215
-
216
- Based on state:
217
- - **Fresh** translations are skipped (unless "Overwrite fresh" is enabled)
218
- - **Stale** translations can use diff-based translation (if "Translate only diffs" is enabled)
219
- - **Drifted** translations are fully re-translated
220
-
221
201
  ### Translation Settings
222
202
 
223
203
  Create a `translationSettings` document to customize translation behavior:
@@ -263,34 +243,16 @@ Create `translationGlossaryTerm` documents for specific term mappings:
263
243
  }
264
244
  ```
265
245
 
266
- ### Give Translation Feedback
267
-
268
- The plugin includes an AI-powered feedback system that learns from corrections:
269
-
270
- 1. Open a translated document
271
- 2. Click "Give Translation Feedback" action
272
- 3. Provide feedback and/or enable "Include edits" to analyze changes
273
- 4. Review AI-generated suggestions:
274
- - Global prompt updates
275
- - Locale-specific prompt updates
276
- - Protected phrases to add
277
- - Glossary terms to add
278
- 5. Approve suggestions to apply
279
-
280
- The AI analyzes your feedback and automatically updates translation settings to improve future translations.
281
-
282
246
  ## Translation Workflow
283
247
 
284
248
  ### How It Works
285
249
 
286
- 1. **Fetch Metadata** - Retrieves translation history and existing translations
287
- 2. **Determine Strategy** - Checks freshness state (fresh/stale/drifted)
288
- 3. **Prepare Translation**:
289
- - For **drifted** or **fresh (overwrite)**: Full document translation
290
- - For **stale (translate diffs)**: Diff-based translation of changed fields only
291
- 4. **Translate** - Uses Sanity Agent Actions with configured prompts
250
+ 1. **Select Release** - Choose to create a new Content Release or add to an existing one
251
+ 2. **Prepare Translation** - Assemble translation prompts and prepare source document
252
+ 3. **Translate** - Uses Sanity Agent Actions (or OpenAI) with configured prompts
253
+ 4. **Create Versions** - Translations are created as versioned documents in the release
292
254
  5. **Localize References** - Optionally translates referenced documents
293
- 6. **Update Metadata** - Stores translation history with snapshots
255
+ 6. **Update Metadata** - Stores translation history
294
256
 
295
257
  ### Reference Translation
296
258
 
package/dist/index.d.ts CHANGED
@@ -38,6 +38,30 @@ export declare const aiTranslationPlugin: Plugin_2<PluginConfig>;
38
38
  */
39
39
  export declare type AnyFieldTransform = FieldTransform<any, any>;
40
40
 
41
+ /**
42
+ * Common enum field names that are typically excluded from translation
43
+ * @internal
44
+ */
45
+ export declare const COMMON_ENUM_FIELDS: readonly [
46
+ "status",
47
+ "state",
48
+ "type",
49
+ "category",
50
+ "priority",
51
+ "visibility",
52
+ "role",
53
+ "permission",
54
+ "level",
55
+ "mode",
56
+ "format",
57
+ "variant",
58
+ "size",
59
+ "theme",
60
+ "kind",
61
+ "phase",
62
+ "stage",
63
+ ];
64
+
41
65
  /**
42
66
  * Criteria for matching fields that should be transformed.
43
67
  * @public
@@ -169,6 +193,36 @@ export declare interface FieldTransform<
169
193
  ) => TOriginal;
170
194
  }
171
195
 
196
+ /**
197
+ * Result of filtering excluded fields from a document
198
+ * @internal
199
+ */
200
+ export declare interface FilteredDocument<T = any> {
201
+ /** Document with excluded fields removed */
202
+ filteredDocument: T;
203
+ /** Excluded field values that were removed */
204
+ excludedValues: Record<string, any>;
205
+ }
206
+
207
+ /**
208
+ * Recursively filters out excluded fields from a document
209
+ * @param document - The document to filter
210
+ * @param excludeFields - Array of field patterns to exclude. Supports:
211
+ * - Field names: 'status' (matches any field named 'status' anywhere)
212
+ * - Exact paths: 'meta.category' (matches only 'category' under 'meta')
213
+ * - Array paths: 'body[0].imageType' (matches 'imageType' in first array item)
214
+ * - Wildcard arrays: 'body[*].imageType' (matches 'imageType' in any array item)
215
+ * - Hierarchical: '**.status' (explicitly matches 'status' anywhere - same as just 'status')
216
+ * @param currentPath - Current path in the document (used internally)
217
+ * @returns Filtered document and excluded values
218
+ * @internal
219
+ */
220
+ export declare function filterExcludedFields<T extends Record<string, any>>(
221
+ document: T,
222
+ excludeFields?: string[],
223
+ currentPath?: string,
224
+ ): FilteredDocument<T>;
225
+
172
226
  /**
173
227
  * Helper type to infer the original type from a FieldTransform.
174
228
  * Useful for type checking and creating wrapper functions.
@@ -233,14 +287,105 @@ export declare interface PluginConfig {
233
287
  maxReferenceDepth?: number;
234
288
  openai?: {
235
289
  apiKey: string;
236
- model?: "gpt-5.1" | "gpt-5" | "gpt-4o" | "gpt-4-turbo" | "gpt-4";
290
+ model?:
291
+ | "gpt-5.1"
292
+ | "gpt-5"
293
+ | "gpt-5-mini"
294
+ | "gpt-5-nano"
295
+ | "gpt-5-pro"
296
+ | "gpt-4o"
297
+ | "gpt-4-turbo"
298
+ | "gpt-4";
237
299
  reasoningEffort?: "low" | "medium" | "high";
238
300
  enabled?: boolean;
239
301
  defaultMode?: TranslationMode;
240
302
  };
241
303
  fieldTransforms?: AnyFieldTransform[];
304
+ /**
305
+ * Fields to exclude from translation. These fields will be preserved as-is in the translated document.
306
+ * Supports field names (e.g., 'status') and nested field paths (e.g., 'meta.category').
307
+ * Useful for enum fields, IDs, technical values, and other non-translatable content.
308
+ *
309
+ * @example
310
+ * ```typescript
311
+ * excludeFields: ['status', 'category', 'type', 'meta.priority', 'config.mode']
312
+ * ```
313
+ */
314
+ excludeFields?: string[];
242
315
  }
243
316
 
317
+ /**
318
+ * Predefined exclusion lists for common use cases
319
+ * @internal
320
+ */
321
+ export declare const PREDEFINED_EXCLUSIONS: {
322
+ /** Common enum and status fields */
323
+ readonly enums: readonly [
324
+ "status",
325
+ "state",
326
+ "type",
327
+ "category",
328
+ "priority",
329
+ "visibility",
330
+ "role",
331
+ "permission",
332
+ "level",
333
+ "mode",
334
+ "format",
335
+ "variant",
336
+ "size",
337
+ "theme",
338
+ "kind",
339
+ "phase",
340
+ "stage",
341
+ ];
342
+ /** All metadata and system fields (starting with _) */
343
+ readonly metadata: readonly [
344
+ "_id",
345
+ "_type",
346
+ "_rev",
347
+ "_createdAt",
348
+ "_updatedAt",
349
+ ];
350
+ /** Common technical and configuration fields */
351
+ readonly technical: readonly [
352
+ "slug",
353
+ "handle",
354
+ "key",
355
+ "code",
356
+ "id",
357
+ "uuid",
358
+ "token",
359
+ "hash",
360
+ "checksum",
361
+ "version",
362
+ "config",
363
+ "settings",
364
+ ];
365
+ /** SEO and URL-related fields that often shouldn't be translated */
366
+ readonly seo: readonly [
367
+ "slug",
368
+ "handle",
369
+ "permalink",
370
+ "canonical",
371
+ "redirect",
372
+ "robots",
373
+ "sitemap",
374
+ ];
375
+ };
376
+
377
+ /**
378
+ * Restores previously excluded fields to a translated document
379
+ * @param translatedDocument - The translated document
380
+ * @param excludedValues - The excluded field values to restore
381
+ * @returns Document with excluded fields restored
382
+ * @internal
383
+ */
384
+ export declare function restoreExcludedFields<T extends Record<string, any>>(
385
+ translatedDocument: T,
386
+ excludedValues: Record<string, any>,
387
+ ): T;
388
+
244
389
  /**
245
390
  * Transform for handling Portable Text (rich text) content using XML-like serialization.
246
391
  * This leverages the existing serialization utilities to convert complex rich text
@@ -314,10 +459,7 @@ export declare const translationHistorySchema: {
314
459
  WidenValidation &
315
460
  WidenInitialValue;
316
461
 
317
- declare type TranslationMode =
318
- | "sanity-only"
319
- | "openai-only"
320
- | "sanity-with-review";
462
+ declare type TranslationMode = "sanity-only" | "openai-only";
321
463
 
322
464
  /**
323
465
  * Represents a VTT caption cue with timing and text content.