@easyling/sanity-connector 1.3.0 → 2.0.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.
Files changed (68) hide show
  1. package/README.md +570 -68
  2. package/dist/index.js +2 -1
  3. package/dist/index.js.map +1 -0
  4. package/package.json +38 -54
  5. package/LICENSE +0 -21
  6. package/dist/.tsbuildinfo +0 -1
  7. package/dist-types/actions/bulkTranslate.d.ts +0 -6
  8. package/dist-types/actions/manageDNTFields.d.ts +0 -11
  9. package/dist-types/actions/translateDocument.d.ts +0 -6
  10. package/dist-types/components/RadioWithDefault.d.ts +0 -16
  11. package/dist-types/components/auth/AuthNavbar.d.ts +0 -17
  12. package/dist-types/components/auth/AuthStatus.d.ts +0 -26
  13. package/dist-types/components/auth/AuthStatusWrapper.d.ts +0 -14
  14. package/dist-types/components/auth/MigrationPrompt.d.ts +0 -19
  15. package/dist-types/components/auth/MigrationPromptWrapper.d.ts +0 -13
  16. package/dist-types/components/auth/OAuthCallback.d.ts +0 -19
  17. package/dist-types/components/auth/index.d.ts +0 -14
  18. package/dist-types/components/config/LocaleConfigTool.d.ts +0 -16
  19. package/dist-types/components/config/LocaleConfigToolWrapper.d.ts +0 -12
  20. package/dist-types/components/config/OAuthConfig.d.ts +0 -25
  21. package/dist-types/components/config/OAuthConfigWrapper.d.ts +0 -12
  22. package/dist-types/components/config/PasswordInput.d.ts +0 -13
  23. package/dist-types/components/config/index.d.ts +0 -8
  24. package/dist-types/components/config/localeConfigToolDefinition.d.ts +0 -12
  25. package/dist-types/components/config/oauthConfigToolDefinition.d.ts +0 -12
  26. package/dist-types/components/dialogs/ConfirmationDialog.d.ts +0 -20
  27. package/dist-types/components/dialogs/ErrorDialog.d.ts +0 -20
  28. package/dist-types/components/dialogs/LocaleSelectionDialog.d.ts +0 -40
  29. package/dist-types/components/dialogs/SuccessDialog.d.ts +0 -18
  30. package/dist-types/components/dialogs/index.d.ts +0 -11
  31. package/dist-types/components/dnt/DNTFieldBadge.d.ts +0 -15
  32. package/dist-types/components/dnt/DNTFieldComponent.d.ts +0 -16
  33. package/dist-types/components/dnt/DNTFieldInput.d.ts +0 -13
  34. package/dist-types/components/dnt/DebugDNTBadge.d.ts +0 -19
  35. package/dist-types/components/dnt/index.d.ts +0 -7
  36. package/dist-types/config/index.d.ts +0 -5
  37. package/dist-types/config/pluginConfig.d.ts +0 -162
  38. package/dist-types/index.d.ts +0 -11
  39. package/dist-types/plugin.d.ts +0 -12
  40. package/dist-types/services/authStateManager.d.ts +0 -93
  41. package/dist-types/services/contentExtractor.d.ts +0 -161
  42. package/dist-types/services/dialogService.d.ts +0 -95
  43. package/dist-types/services/dntServiceManager.d.ts +0 -43
  44. package/dist-types/services/dntStorageAdapter.d.ts +0 -72
  45. package/dist-types/services/documentCreationService.d.ts +0 -196
  46. package/dist-types/services/localeService.d.ts +0 -159
  47. package/dist-types/services/localeStorageAdapter.d.ts +0 -41
  48. package/dist-types/services/oauthConfigStorage.d.ts +0 -45
  49. package/dist-types/services/oauthService.d.ts +0 -47
  50. package/dist-types/services/oauthServiceManager.d.ts +0 -195
  51. package/dist-types/services/tokenStorage.d.ts +0 -53
  52. package/dist-types/services/translationService.d.ts +0 -385
  53. package/dist-types/services/unifiedConfigStorage.d.ts +0 -133
  54. package/dist-types/test-utils.d.ts +0 -8
  55. package/dist-types/types/dialog.d.ts +0 -106
  56. package/dist-types/types/dnt.d.ts +0 -83
  57. package/dist-types/types/index.d.ts +0 -11
  58. package/dist-types/types/locale.d.ts +0 -115
  59. package/dist-types/types/oauth.d.ts +0 -89
  60. package/dist-types/types/pluginConfig.d.ts +0 -46
  61. package/dist-types/types/translation.d.ts +0 -121
  62. package/dist-types/utils/dntDefaults.d.ts +0 -101
  63. package/dist-types/utils/htmlFormatter.d.ts +0 -65
  64. package/dist-types/utils/index.d.ts +0 -16
  65. package/dist-types/utils/logger.d.ts +0 -104
  66. package/dist-types/utils/oauthErrorFeedback.d.ts +0 -75
  67. package/dist-types/utils/oauthLogger.d.ts +0 -175
  68. package/dist-types/utils/validator.d.ts +0 -66
package/README.md CHANGED
@@ -1,122 +1,624 @@
1
- # Sanity Translation Plugin
1
+ # @easyling/sanity-connector
2
2
 
3
- A Sanity Studio plugin that enables seamless document translation workflows. It extracts content as HTML, manages translation requests to external services, and handles the re-import of translated content while preserving Portable Text structures.
3
+ Sanity Studio v3 plugin for document translation with Easyling. Provides UI-based translation functionality with support for single document translation, bulk operations, and granular control over translatable content.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Single Document Translation**: Translate individual documents directly from the document form.
8
- - **Bulk Translation**: Batch process multiple documents via a dedicated tool.
9
- - **Smart Content Extraction**: Converts Sanity Portable Text to HTML for translation and back again.
10
- - **Translation Invariance**: granular control over what gets translated via "Do Not Translate" (DNT) flags.
11
- - **Inline Badges**: Toggle translation status for individual fields directly in the editor.
12
- - **Field Management**: dedicated action to manage DNT status across the whole document.
13
- - **Authentication Support**: Secure OAuth integration with translation services, with a legacy mode for local testing.
14
- - **Auto-Configuration**: Intelligent defaults for new installations to get you started quickly.
15
- - **Progress Tracking**: Real-time feedback for long-running bulk operations.
7
+ - **Single Document Translation**: Translate individual documents directly from the document form
8
+ - **Bulk Translation Tool**: Batch process multiple documents via a dedicated tool
9
+ - **Smart Content Extraction**: Converts Sanity Portable Text to HTML for translation and back again
10
+ - **Translation Collision Handling**: Intelligent detection and resolution when re-translating to the same locale
11
+ - **Do Not Translate (DNT) Control**: Granular field-level control over what gets translated
12
+ - Inline badges for toggling translation status
13
+ - Dedicated field management action
14
+ - Smart defaults based on field types and names
15
+ - **OAuth Integration**: Secure authentication with translation services
16
+ - **Real-time Progress Tracking**: Visual feedback for long-running operations
17
+ - **Debug Mode**: Detailed field information for troubleshooting
16
18
 
17
19
  ## Installation
18
20
 
19
- Install the plugin in your Sanity Studio project:
20
-
21
21
  ```bash
22
- npm install sanity-translation-plugin
22
+ npm install @easyling/sanity-connector
23
23
  ```
24
24
 
25
- Add the plugin to your `sanity.config.ts` file:
25
+ ### Peer Dependencies
26
+
27
+ The plugin requires the following peer dependencies:
28
+
29
+ - `sanity` ^3.0.0
30
+ - `react` ^18.0.0
31
+ - `react-dom` ^18.0.0
32
+
33
+ These are typically already installed in your Sanity Studio project.
34
+
35
+ ## Setup
36
+
37
+ ### Basic Configuration
38
+
39
+ Add the plugin to your `sanity.config.ts` or `sanity.config.js`:
26
40
 
27
41
  ```typescript
28
42
  import { defineConfig } from 'sanity'
29
- import translationPlugin from 'sanity-translation-plugin'
43
+ import translationPlugin from '@easyling/sanity-connector'
30
44
 
31
45
  export default defineConfig({
32
- // ... your other config
46
+ // ... other config
33
47
  plugins: [
34
- // ... other plugins
35
48
  translationPlugin()
36
49
  ]
37
50
  })
38
51
  ```
39
52
 
40
- ## Configuration
53
+ That's it! The plugin will automatically:
54
+ - Register document actions (Translate, Manage DNT Fields)
55
+ - Add the Bulk Translate tool to your Studio
56
+ - Create configuration document types
57
+ - Initialize services on Studio load
58
+
59
+ ### Initial Configuration
60
+
61
+ After installing the plugin, you'll need to configure:
62
+
63
+ 1. **OAuth Credentials** (required for translation)
64
+ 2. **Target Locales** (languages to translate to)
65
+ 3. **Translation API Endpoint** (optional, defaults to Easyling)
66
+
67
+ Configuration is stored in your Sanity dataset as an `EL_PluginConfiguration` document. You can configure through:
68
+
69
+ - The Studio UI (recommended)
70
+ - Direct document editing
71
+ - The UnifiedConfigStorage API
72
+
73
+ ## Configuration Options
74
+
75
+ ### OAuth Configuration
76
+
77
+ Configure authentication with your translation service:
78
+
79
+ 1. Navigate to your Studio
80
+ 2. Create or edit the `EL_PluginConfiguration` document
81
+ 3. Fill in the OAuth section:
82
+ - **Project ID**: Your translation project identifier
83
+ - **Access Token**: Long-lived access token (hidden for security)
84
+
85
+ ```typescript
86
+ // Example: Programmatic configuration
87
+ import { UnifiedConfigStorage } from '@easyling/sanity-connector'
88
+ import { createClient } from 'sanity'
89
+
90
+ const client = createClient({
91
+ projectId: 'your-project-id',
92
+ dataset: 'production',
93
+ apiVersion: '2024-01-01',
94
+ token: 'your-token'
95
+ })
96
+
97
+ const configStorage = new UnifiedConfigStorage(client)
98
+
99
+ await configStorage.update({
100
+ projectId: 'your-easyling-project-id',
101
+ accessToken: 'your-access-token'
102
+ })
103
+ ```
104
+
105
+ ### Locale Configuration
106
+
107
+ Define which languages you want to translate to:
108
+
109
+ ```typescript
110
+ await configStorage.update({
111
+ locales: [
112
+ {
113
+ code: 'en',
114
+ title: 'English',
115
+ enabled: true,
116
+ isDefault: true
117
+ },
118
+ {
119
+ code: 'ja',
120
+ title: 'Japanese',
121
+ enabled: true,
122
+ isDefault: false
123
+ },
124
+ {
125
+ code: 'de',
126
+ title: 'German',
127
+ enabled: true,
128
+ isDefault: false
129
+ }
130
+ ]
131
+ })
132
+ ```
133
+
134
+ **Locale Fields:**
135
+ - `code`: Language code (e.g., 'en', 'ja-JP')
136
+ - `title`: Display name for the language
137
+ - `enabled`: Whether this locale is active for translation
138
+ - `isDefault`: Whether this is the source language (only one should be true)
139
+
140
+ ### Translation API Configuration
141
+
142
+ Customize the translation service endpoint and format:
143
+
144
+ ```typescript
145
+ await configStorage.update({
146
+ translationApiEndpoint: 'https://api.easyling.com/translate',
147
+ requestContentType: 'application/x-protobuf', // or 'application/json'
148
+ responseAcceptHeader: 'application/x-protobuf' // or 'application/json'
149
+ })
150
+ ```
41
151
 
42
- ### Authentication & Connection
152
+ **Default values:**
153
+ - Endpoint: Easyling translation API
154
+ - Content Type: `application/x-protobuf`
155
+ - Accept Header: `application/x-protobuf`
43
156
 
44
- The plugin supports two modes of operation:
157
+ ### Document Creation Options
45
158
 
46
- 1. **OAuth Mode (Recommended for Production)**:
47
- - Uses secure token-based authentication.
48
- - Configurable via the **OAuth Configuration** tool within Sanity Studio.
49
- - Supports project-specific access control.
159
+ Control how translated documents are created:
50
160
 
51
- 2. **Legacy/Development Mode**:
52
- - Default behavior out of the box.
53
- - Points to `http://app.easyling.com` by default.
54
- - Useful for local development and testing without setting up full auth.
161
+ ```typescript
162
+ await configStorage.update({
163
+ defaultDocumentCreationMode: 'draft', // or 'published'
164
+ collisionResolutionMode: 'skip', // or 'replace', 'merge'
165
+ existingDocumentHandling: 'keep' // or 'archive', 'delete'
166
+ })
167
+ ```
55
168
 
56
- To configure the plugin for production use, navigate to the **Easyling Translation Plugin Configuration** document type in your Sanity Studio after installation, and create a new configuration. Enter your project code and access token (both are available in the Easyling platform), and publish your configuration.
169
+ **Creation Modes:**
170
+ - `draft`: Create translated documents as drafts (recommended)
171
+ - `published`: Create translated documents as published
57
172
 
58
- Next, navigate to the **Locales** tab of the configuration, and add the locales you wish to handle. These are the ones you will be able to translate your content into.
173
+ **Collision Resolution:**
174
+ - `skip`: Don't create if translation already exists
175
+ - `replace`: Overwrite existing translation
176
+ - `merge`: Merge with existing translation (preserves untranslated fields)
59
177
 
60
- At this point, you're ready to begin processing content, but if you want, you can add translation-invariant fields for your content types, by toggling the badges on the individual fields.
178
+ **Existing Document Handling:**
179
+ - `keep`: Keep existing document as-is
180
+ - `archive`: Move existing document to drafts
181
+ - `delete`: Delete existing document
61
182
 
62
- ### Defaults
183
+ ### DNT (Do Not Translate) Configuration
63
184
 
64
- The plugin comes with "Auto-Default" behavior. When you install it for the first time, it will automatically select sensible defaults (like "Draft" mode for new translated documents) so you can start using it immediately without manual configuration.
185
+ Configure which fields should not be translated by default:
186
+
187
+ ```typescript
188
+ await configStorage.setDNTField('article', 'author.name', true)
189
+ await configStorage.setDNTField('article', 'publishDate', true)
190
+ ```
191
+
192
+ The plugin automatically applies smart defaults for common non-translatable fields:
193
+ - Author names
194
+ - Dates and timestamps
195
+ - IDs and references
196
+ - Technical metadata
197
+
198
+ You can override these defaults on a per-field basis using the inline DNT badges or the Manage DNT Fields action.
199
+
200
+ ### Debug Mode
201
+
202
+ Enable debug mode to see detailed field information:
203
+
204
+ ```typescript
205
+ await configStorage.update({
206
+ debugMode: true
207
+ })
208
+ ```
209
+
210
+ When enabled, all fields will show debug badges with:
211
+ - Field path
212
+ - Field type
213
+ - DNT status (default and stored)
214
+ - Group/fieldset information
65
215
 
66
216
  ## Usage
67
217
 
68
218
  ### Single Document Translation
69
219
 
70
- 1. Open a document in Sanity Studio.
71
- 2. Click the **Translate** icon in the document toolbar.
72
- 3. Review the document details in the confirmation dialog.
73
- 4. Click **Translate**.
74
- 5. The plugin will process the translation and inform you when complete.
220
+ 1. Open any document in your Studio
221
+ 2. Click the **Translate** button in the document toolbar
222
+ 3. Select target languages
223
+ 4. Configure translation options (creation mode, collision handling)
224
+ 5. Click **Translate**
225
+
226
+ The plugin will:
227
+ - Extract translatable content from the document
228
+ - Send translation request to the configured API
229
+ - Create new documents for each target language
230
+ - Show progress and results
75
231
 
76
232
  ### Bulk Translation
77
233
 
78
- 1. Open the **Bulk Translate** tool from the Sanity Studio tools menu.
79
- 2. Select the document types you wish to translate.
80
- 3. Filter and select specific documents from the list.
81
- 4. Click the **Translate** button to process the batch.
82
- 5. A summary report will be displayed upon completion.
234
+ 1. Open the **Bulk Translate** tool from the Studio tools menu
235
+ 2. Select document type to translate
236
+ 3. Choose documents (or select all)
237
+ 4. Select target languages
238
+ 5. Configure translation options
239
+ 6. Click **Start Translation**
240
+
241
+ The tool provides:
242
+ - Real-time progress tracking
243
+ - Success/failure counts
244
+ - Detailed results for each document
245
+ - Rollback capability if needed
246
+
247
+ ### Managing DNT Fields
248
+
249
+ #### Inline Badges
250
+
251
+ For translatable fields (string, text, array), you'll see a DNT badge:
252
+ - **Green badge**: Field will be translated
253
+ - **Red badge**: Field will NOT be translated
254
+ - Click the badge to toggle the DNT status
255
+
256
+ #### Manage DNT Fields Action
257
+
258
+ 1. Open any document
259
+ 2. Click **Manage DNT Fields** in the document toolbar
260
+ 3. View all fields with their DNT status
261
+ 4. Toggle individual fields or apply bulk changes
262
+ 5. Save changes
263
+
264
+ The action shows:
265
+ - Field path and type
266
+ - Current DNT status
267
+ - Smart default recommendations
268
+ - Ability to reset to defaults
269
+
270
+ ## Migration from Previous Version
271
+
272
+ If you're upgrading from the single-package version (pre-monorepo), follow these steps:
273
+
274
+ ### 1. Update Package Name
275
+
276
+ The plugin package name remains the same, but the internal structure has changed:
277
+
278
+ ```bash
279
+ # Uninstall old version
280
+ npm uninstall @easyling/sanity-connector
281
+
282
+ # Install new version
283
+ npm install @easyling/sanity-connector
284
+ ```
285
+
286
+ ### 2. Update Imports
287
+
288
+ Most imports remain the same, but some have moved to the shared library:
289
+
290
+ **Before:**
291
+ ```typescript
292
+ import { UnifiedConfigStorage } from '@easyling/sanity-connector'
293
+ ```
294
+
295
+ **After:**
296
+ ```typescript
297
+ // Still works - re-exported from plugin
298
+ import { UnifiedConfigStorage } from '@easyling/sanity-connector'
299
+
300
+ // Or import directly from shared library
301
+ import { UnifiedConfigStorage } from '@easyling/sanity-connector-shared'
302
+ ```
303
+
304
+ ### 3. Configuration Migration
305
+
306
+ The plugin automatically migrates legacy configuration documents:
83
307
 
84
- ### Managing Translatable Fields
308
+ - **Legacy OAuth Config** (`EL_oauth-config`) → Merged into `EL_PluginConfiguration`
309
+ - **Legacy Locale Config** (`EL_locale-config`) → Merged into `EL_PluginConfiguration`
85
310
 
86
- Sometimes you need to keep specific fields (like product codes, technical IDs, or proper names) from being translated.
311
+ Migration happens automatically on first load. Legacy documents are hidden from the UI but preserved for rollback if needed.
87
312
 
88
- **Method 1: Inline Badges**
89
- In the document editor, you will see small badges below translatable fields:
90
- - **Green "Will Translate"**: The field will be included in the translation request.
91
- - **Red "Do Not Translate"**: The field will be skipped.
92
- Click the badge to toggle the status.
313
+ ### 4. Verify Configuration
93
314
 
94
- **Method 2: Field Management Action**
95
- For a high-level view:
96
- 1. Click the document menu (three dots) in the top right.
97
- 2. Select **Manage Translation Fields**.
98
- 3. View and toggle the translation status for all fields in the document.
315
+ After migration, verify your configuration:
316
+
317
+ 1. Open the `EL_PluginConfiguration` document in your Studio
318
+ 2. Check that OAuth credentials are present
319
+ 3. Verify locale settings
320
+ 4. Test a translation to ensure everything works
321
+
322
+ ### 5. Update Custom Code (if applicable)
323
+
324
+ If you have custom code using the plugin's APIs:
325
+
326
+ **Service Imports:**
327
+ ```typescript
328
+ // Before
329
+ import { ContentExtractor } from '@easyling/sanity-connector/services'
330
+
331
+ // After - import from shared library
332
+ import { ContentExtractor } from '@easyling/sanity-connector-shared'
333
+ ```
334
+
335
+ **Type Imports:**
336
+ ```typescript
337
+ // Before
338
+ import type { TranslationRequest } from '@easyling/sanity-connector/types'
339
+
340
+ // After - still works, or use shared library
341
+ import type { TranslationRequest } from '@easyling/sanity-connector'
342
+ // or
343
+ import type { TranslationRequest } from '@easyling/sanity-connector-shared'
344
+ ```
345
+
346
+ ### Breaking Changes
347
+
348
+ The monorepo restructuring introduces minimal breaking changes:
349
+
350
+ 1. **Internal file structure**: If you were importing from internal paths (not recommended), update to use public exports
351
+ 2. **Service initialization**: Some services now require explicit client initialization
352
+ 3. **Configuration storage**: Legacy config documents are deprecated (but still supported)
353
+
354
+ ### Rollback
355
+
356
+ If you need to rollback to the previous version:
357
+
358
+ ```bash
359
+ npm install @easyling/sanity-connector@1.3.0
360
+ ```
361
+
362
+ Your configuration will remain intact as the document structure hasn't changed.
363
+
364
+ ## Advanced Usage
365
+
366
+ ### Custom Translation Workflow
367
+
368
+ You can build custom translation workflows using the exported services:
369
+
370
+ ```typescript
371
+ import {
372
+ ContentExtractor,
373
+ TranslationService,
374
+ DocumentCreationService,
375
+ UnifiedConfigStorage
376
+ } from '@easyling/sanity-connector-shared'
377
+ import { useClient } from 'sanity'
378
+
379
+ function MyCustomTranslationComponent() {
380
+ const client = useClient()
381
+
382
+ const handleCustomTranslation = async (document) => {
383
+ // Initialize services
384
+ const configStorage = new UnifiedConfigStorage(client)
385
+ const extractor = new ContentExtractor(client)
386
+ const translationService = new TranslationService(client)
387
+ const docCreationService = new DocumentCreationService(client)
388
+
389
+ // Load configuration
390
+ const config = await configStorage.load()
391
+ translationService.setEndpoint(config.translationApiEndpoint)
392
+ translationService.setAuthToken(config.accessToken, config.projectId)
393
+
394
+ // Extract content
395
+ const structured = await extractor.extractStructuredContent(
396
+ document,
397
+ configStorage
398
+ )
399
+
400
+ // Translate
401
+ const response = await translationService.translateDocument(
402
+ structured,
403
+ document._type,
404
+ 'en',
405
+ undefined,
406
+ ['ja', 'de']
407
+ )
408
+
409
+ // Create translated documents
410
+ for (const translatedDoc of response.translatedDocuments) {
411
+ await docCreationService.createDocumentFromTranslation(
412
+ document,
413
+ { ...response, translatedDocuments: [translatedDoc] },
414
+ {
415
+ targetLanguage: translatedDoc.locale,
416
+ creationMode: 'draft'
417
+ }
418
+ )
419
+ }
420
+ }
421
+
422
+ return <button onClick={() => handleCustomTranslation(doc)}>Translate</button>
423
+ }
424
+ ```
425
+
426
+ ### Custom DNT Logic
427
+
428
+ Implement custom DNT logic for your schema:
429
+
430
+ ```typescript
431
+ import { DNTServiceManager } from '@easyling/sanity-connector'
432
+ import { useClient } from 'sanity'
433
+
434
+ function MyComponent() {
435
+ const client = useClient()
436
+ const dntService = DNTServiceManager.getInstance(client)
437
+
438
+ const checkDNTStatus = async (documentType, fieldPath) => {
439
+ const isDNT = await dntService.getDNTFieldStatus(documentType, fieldPath)
440
+ console.log(`Field ${fieldPath} is ${isDNT ? 'NOT' : ''} translatable`)
441
+ }
442
+
443
+ const setDNTStatus = async (documentType, fieldPath, isDNT) => {
444
+ await dntService.setDNTField(documentType, fieldPath, isDNT)
445
+ }
446
+
447
+ return <div>Custom DNT UI</div>
448
+ }
449
+ ```
450
+
451
+ ### Accessing Configuration
452
+
453
+ Access plugin configuration in your custom components:
454
+
455
+ ```typescript
456
+ import { UnifiedConfigStorage } from '@easyling/sanity-connector'
457
+ import { useClient } from 'sanity'
458
+ import { useEffect, useState } from 'react'
459
+
460
+ function MyConfigComponent() {
461
+ const client = useClient()
462
+ const [config, setConfig] = useState(null)
463
+
464
+ useEffect(() => {
465
+ const loadConfig = async () => {
466
+ const configStorage = new UnifiedConfigStorage(client)
467
+ const cfg = await configStorage.load()
468
+ setConfig(cfg)
469
+ }
470
+ loadConfig()
471
+ }, [client])
472
+
473
+ return (
474
+ <div>
475
+ <h2>Current Configuration</h2>
476
+ <pre>{JSON.stringify(config, null, 2)}</pre>
477
+ </div>
478
+ )
479
+ }
480
+ ```
99
481
 
100
482
  ## Troubleshooting
101
483
 
102
- **Plugin not appearing in Studio**
103
- - Verify `npm install sanity-translation-plugin` completed successfully.
104
- - Ensure `translationPlugin()` is in the `plugins` array in `sanity.config.ts`.
105
- - Restart the Sanity Studio development server.
484
+ ### Translation Fails with Authentication Error
485
+
486
+ **Problem**: Translation requests fail with 401 or 403 errors
487
+
488
+ **Solution**:
489
+ 1. Verify OAuth credentials in `EL_PluginConfiguration`
490
+ 2. Check that Project ID and Access Token are correct
491
+ 3. Ensure access token hasn't expired
492
+ 4. Contact your translation service provider for new credentials
493
+
494
+ ### DNT Badges Not Showing
106
495
 
107
- **Translation action not visible**
108
- - The action only appears on documents that have translatable fields defined in their schema.
496
+ **Problem**: DNT badges don't appear on fields
109
497
 
110
- **Authentication Issues**
111
- - If using OAuth, check the **OAuth Configuration** tool to ensure your tokens are valid.
112
- - If using local testing, ensure your mock translation service is running on the expected port.
498
+ **Solution**:
499
+ 1. Check that the field type is translatable (string, text, array)
500
+ 2. Verify the field isn't blacklisted (locale, _id, _type, etc.)
501
+ 3. Enable debug mode to see all fields
502
+ 4. Check browser console for errors
503
+
504
+ ### Translated Documents Not Created
505
+
506
+ **Problem**: Translation succeeds but no documents are created
507
+
508
+ **Solution**:
509
+ 1. Check collision resolution mode - may be set to 'skip'
510
+ 2. Verify you have write permissions in the dataset
511
+ 3. Check browser console for document creation errors
512
+ 4. Ensure target locale codes match your schema
513
+
514
+ ### Bulk Translation Stalls
515
+
516
+ **Problem**: Bulk translation stops or hangs
517
+
518
+ **Solution**:
519
+ 1. Check network connection
520
+ 2. Verify translation API is responding
521
+ 3. Try translating a single document to isolate the issue
522
+ 4. Check browser console for errors
523
+ 5. Reduce batch size if translating many documents
524
+
525
+ ### Configuration Not Persisting
526
+
527
+ **Problem**: Configuration changes don't save
528
+
529
+ **Solution**:
530
+ 1. Verify you have write permissions in the dataset
531
+ 2. Check that `EL_PluginConfiguration` document exists
532
+ 3. Look for validation errors in the Studio
533
+ 4. Check browser console for save errors
534
+
535
+ ### Migration Issues
536
+
537
+ **Problem**: Legacy configuration not migrated
538
+
539
+ **Solution**:
540
+ 1. Check that legacy documents exist (`EL_oauth-config`, `EL_locale-config`)
541
+ 2. Manually create `EL_PluginConfiguration` document
542
+ 3. Copy values from legacy documents
543
+ 4. Contact support if automatic migration fails
544
+
545
+ ## API Reference
546
+
547
+ ### Exported Components
548
+
549
+ - `DNTFieldBadge`: Standalone DNT badge component
550
+ - `withDNTBadge`: HOC for adding DNT badge to custom fields
551
+ - `DNTFieldInput`: Complete field input with DNT badge
552
+
553
+ ### Exported Services
554
+
555
+ - `UnifiedConfigStorage`: Configuration management
556
+ - `DNTServiceManager`: DNT field management
557
+ - `DNTStorageAdapter`: DNT storage interface
558
+ - `LegacyDNTStorageAdapter`: Legacy DNT storage support
559
+
560
+ ### Exported Types
561
+
562
+ ```typescript
563
+ import type {
564
+ LocaleDefinition,
565
+ LocaleConfig,
566
+ TranslationRequestPayload,
567
+ TranslationResponse,
568
+ TranslatableField,
569
+ DNTFieldPreference,
570
+ DNTPreferences,
571
+ DNTTypeConfig,
572
+ DNTStorage,
573
+ UnifiedPluginConfig
574
+ } from '@easyling/sanity-connector'
575
+ ```
576
+
577
+ See the [shared library documentation](../shared/README.md) for complete API reference.
578
+
579
+ ## Development
580
+
581
+ ### Building
582
+
583
+ ```bash
584
+ npm run build # Production build
585
+ npm run dev # Development build with watch
586
+ npm run clean # Remove build artifacts
587
+ ```
588
+
589
+ ### Testing
590
+
591
+ ```bash
592
+ npm test # Run all tests
593
+ npm run test:watch # Run tests in watch mode
594
+ npm run test:coverage # Generate coverage report
595
+ ```
596
+
597
+ ### Code Quality
598
+
599
+ ```bash
600
+ npm run lint # Check for linting issues
601
+ npm run lint:fix # Auto-fix linting issues
602
+ npm run typecheck # Type check without emitting
603
+ ```
113
604
 
114
605
  ## Support
115
606
 
116
- Our support team can be reached at support@easyling.com.
607
+ For questions, issues, or feature requests:
117
608
 
118
- **Note:** In order to investigate compatibility or interoperability issues, we may need access to your Sanity data lake and Studio codebase. We are happy to work with you to establish secure access for debugging purposes.
609
+ - **Email**: support@easyling.com
610
+ - **Issues**: [GitHub Issues](https://github.com/easyling/el-sanity-connector/issues)
611
+ - **Documentation**: [Main README](../README.md) | [Shared Library](../shared/README.md)
119
612
 
120
613
  ## License
121
614
 
122
- MIT License - see [LICENSE](LICENSE) file for details.
615
+ MIT
616
+
617
+ ## Related Packages
618
+
619
+ - [@easyling/sanity-connector-shared](../shared/README.md) - Core translation logic
620
+ - [@easyling/sanity-function-auto-translate](../function/README.md) - Automatic translation on publish
621
+
622
+ ## Changelog
623
+
624
+ See [CHANGELOG.md](CHANGELOG.md) for version history and migration notes.