@procore/ai-translations 0.1.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/LICENSE +84 -0
- package/README.md +1 -0
- package/dist/legacy/index.d.mts +367 -0
- package/dist/legacy/index.d.ts +367 -0
- package/dist/legacy/index.js +57 -0
- package/dist/legacy/index.mjs +28 -0
- package/dist/modern/index.d.mts +367 -0
- package/dist/modern/index.d.ts +367 -0
- package/dist/modern/index.js +57 -0
- package/dist/modern/index.mjs +28 -0
- package/package.json +71 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
interface AITranslationContextValue {
|
|
2
|
+
ait: (text: string) => string;
|
|
3
|
+
isShowingTranslations: boolean;
|
|
4
|
+
toggleTranslations: () => void;
|
|
5
|
+
locale: string;
|
|
6
|
+
isTranslating: boolean;
|
|
7
|
+
renderVersion?: number;
|
|
8
|
+
initializeTranslators: (targetLanguages?: string[], sourceLanguages?: string[]) => Promise<void>;
|
|
9
|
+
isInitialized: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* useAITranslation Hook
|
|
14
|
+
*
|
|
15
|
+
* Custom React hook to access the AI translation context and manage translation state.
|
|
16
|
+
* This hook provides access to translation functions, state, and utilities for
|
|
17
|
+
* managing translations in your React components.
|
|
18
|
+
*
|
|
19
|
+
* Key Features:
|
|
20
|
+
* - Access to `ait()` function for registering translatable strings
|
|
21
|
+
* - Toggle translations on/off
|
|
22
|
+
* - Check translation state (isShowingTranslations, isTranslating)
|
|
23
|
+
* - Initialize translators (required for first use)
|
|
24
|
+
* - Automatic re-rendering when translations update
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* ```typescript
|
|
28
|
+
* function MyComponent() {
|
|
29
|
+
* const { ait, isShowingTranslations, toggleTranslations } = useAITranslation();
|
|
30
|
+
*
|
|
31
|
+
* return (
|
|
32
|
+
* <div>
|
|
33
|
+
* <h1>{ait("Welcome to our app")}</h1>
|
|
34
|
+
* <button onClick={toggleTranslations}>
|
|
35
|
+
* {isShowingTranslations ? 'Show Original' : 'Translate'}
|
|
36
|
+
* </button>
|
|
37
|
+
* </div>
|
|
38
|
+
* );
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* Initialization Example:
|
|
43
|
+
* ```typescript
|
|
44
|
+
* function TranslateButton() {
|
|
45
|
+
* const { initializeTranslators, isInitialized } = useAITranslation();
|
|
46
|
+
*
|
|
47
|
+
* const handleClick = async () => {
|
|
48
|
+
* if (!isInitialized) {
|
|
49
|
+
* await initializeTranslators(['es', 'fr'], ['en']);
|
|
50
|
+
* }
|
|
51
|
+
* };
|
|
52
|
+
*
|
|
53
|
+
* return <button onClick={handleClick}>Enable Translation</button>;
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @throws {Error} If used outside of AITranslationProvider
|
|
58
|
+
* @returns {AITranslationContextValue} The translation context value with reactive render version
|
|
59
|
+
*/
|
|
60
|
+
declare function useAITranslation(): AITranslationContextValue;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* DataTable Translation Hook
|
|
64
|
+
*
|
|
65
|
+
* @module useDataTableAITranslation
|
|
66
|
+
* @description
|
|
67
|
+
* Specialized React hook for translating table data (AG Grid) with Chrome AI.
|
|
68
|
+
* Handles the complexity of translating dynamic table content, managing pagination,
|
|
69
|
+
* data changes, and field-level exclusions while maintaining optimal performance.
|
|
70
|
+
*
|
|
71
|
+
* ## Problem Solved
|
|
72
|
+
*
|
|
73
|
+
* Tables present unique translation challenges:
|
|
74
|
+
* - Data loads asynchronously (pagination, sorting, filtering)
|
|
75
|
+
* - New content appears without component remounts
|
|
76
|
+
* - Some fields shouldn't be translated (dates, IDs, technical fields)
|
|
77
|
+
* - Translation must not break table rendering or performance
|
|
78
|
+
* - Memory leaks from event listeners must be prevented
|
|
79
|
+
*
|
|
80
|
+
* This hook solves all these challenges with an intelligent translation system
|
|
81
|
+
* that automatically detects, translates, and applies translations to table data.
|
|
82
|
+
*
|
|
83
|
+
* ## Key Features
|
|
84
|
+
*
|
|
85
|
+
* 1. **Automatic String Registration**: All table cell text is registered for translation
|
|
86
|
+
* 2. **Field Exclusion**: Skip translation for datetime, ID, or custom fields
|
|
87
|
+
* 3. **Pagination Support**: Automatically translates new pages as they load
|
|
88
|
+
* 4. **Data Source Integration**: Listens to data events (loaded, changed)
|
|
89
|
+
* 5. **Progress Reporting**: Access global translation progress directly from the hook
|
|
90
|
+
* 6. **Memory Safe**: Prevents leaks with proper cleanup on unmount
|
|
91
|
+
* 7. **AG Grid Integration**: Direct integration with AG Grid's API
|
|
92
|
+
* 8. **Batch Translation**: Parallel translation for optimal performance
|
|
93
|
+
* 9. **Microtask Batching**: Catches late-loading rows with RAF timing
|
|
94
|
+
*
|
|
95
|
+
* ## Architecture
|
|
96
|
+
*
|
|
97
|
+
* The hook operates in phases:
|
|
98
|
+
*
|
|
99
|
+
* ### Registration Phase (Always Active)
|
|
100
|
+
* - As table renders, `ait()` is called on each cell value
|
|
101
|
+
* - Strings are registered in the string registry
|
|
102
|
+
* - Original values are preserved in `_originalLabel` properties
|
|
103
|
+
*
|
|
104
|
+
* ### Translation Phase (When Toggled ON)
|
|
105
|
+
* 1. Detect source language for each registered string
|
|
106
|
+
* 2. Filter out strings already in target language
|
|
107
|
+
* 3. Translate all strings in parallel batches
|
|
108
|
+
* 4. Update string registry with translations
|
|
109
|
+
* 5. Force table refresh to display translated content
|
|
110
|
+
*
|
|
111
|
+
* ### Update Phase (During Pagination/Data Changes)
|
|
112
|
+
* - New data triggers registration of new strings
|
|
113
|
+
* - If translations are active, automatically translates new strings
|
|
114
|
+
* - Applies translations and refreshes only affected cells
|
|
115
|
+
*
|
|
116
|
+
* ## Usage
|
|
117
|
+
*
|
|
118
|
+
* ### Basic Usage
|
|
119
|
+
* ```tsx
|
|
120
|
+
* import { useTableTranslation } from './ai-translations-package';
|
|
121
|
+
*
|
|
122
|
+
* function MyTable() {
|
|
123
|
+
* const tableApi = useTableApi();
|
|
124
|
+
* const fields = useFields();
|
|
125
|
+
*
|
|
126
|
+
* const {
|
|
127
|
+
* isShowingTranslations,
|
|
128
|
+
* toggleTranslations,
|
|
129
|
+
* isTranslating,
|
|
130
|
+
* translationProgress
|
|
131
|
+
* } = useTableTranslation({
|
|
132
|
+
* tableApi,
|
|
133
|
+
* fieldsIndex: fields,
|
|
134
|
+
* });
|
|
135
|
+
*
|
|
136
|
+
* return (
|
|
137
|
+
* <>
|
|
138
|
+
* <Button onClick={toggleTranslations} loading={isTranslating}>
|
|
139
|
+
* {isShowingTranslations ? 'Show Original' : 'Translate'}
|
|
140
|
+
* </Button>
|
|
141
|
+
* {translationProgress && (
|
|
142
|
+
* <span>Progress: {translationProgress.progress}%</span>
|
|
143
|
+
* )}
|
|
144
|
+
* <Table api={tableApi} />
|
|
145
|
+
* </>
|
|
146
|
+
* );
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* ### With Field Exclusions
|
|
151
|
+
* ```tsx
|
|
152
|
+
* const { toggleTranslations } = useTableTranslation({
|
|
153
|
+
* tableApi,
|
|
154
|
+
* fieldsIndex: fields,
|
|
155
|
+
* excludeFields: ['created_at', 'updated_at', 'id', 'code'],
|
|
156
|
+
* shouldExcludeField: (field) => field.type === 'datetime' || field.technical
|
|
157
|
+
* });
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* ### With Progress Reporting
|
|
161
|
+
* ```tsx
|
|
162
|
+
* const {
|
|
163
|
+
* toggleTranslations,
|
|
164
|
+
* translationProgress
|
|
165
|
+
* } = useTableTranslation({
|
|
166
|
+
* tableApi,
|
|
167
|
+
* fieldsIndex: fields,
|
|
168
|
+
* });
|
|
169
|
+
*
|
|
170
|
+
* // Display global progress (no need to call useAITranslation separately!)
|
|
171
|
+
* {translationProgress && (
|
|
172
|
+
* <ProgressBar
|
|
173
|
+
* progress={translationProgress.progress}
|
|
174
|
+
* current={translationProgress.current}
|
|
175
|
+
* total={translationProgress.total}
|
|
176
|
+
* />
|
|
177
|
+
* )}
|
|
178
|
+
* ```
|
|
179
|
+
*
|
|
180
|
+
* ### With Data Source Integration
|
|
181
|
+
* ```tsx
|
|
182
|
+
* const dataSource = useDataSource();
|
|
183
|
+
*
|
|
184
|
+
* const { toggleTranslations } = useTableTranslation({
|
|
185
|
+
* tableApi,
|
|
186
|
+
* fieldsIndex: fields,
|
|
187
|
+
* dataSource, // Automatically handles pagination and view changes
|
|
188
|
+
* });
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* ### Manual Data Loading
|
|
192
|
+
* ```tsx
|
|
193
|
+
* const { applyTranslationsToNewData } = useTableTranslation({
|
|
194
|
+
* tableApi,
|
|
195
|
+
* fieldsIndex: fields,
|
|
196
|
+
* });
|
|
197
|
+
*
|
|
198
|
+
* // Call when new data loads
|
|
199
|
+
* const handleDataLoaded = async () => {
|
|
200
|
+
* await applyTranslationsToNewData();
|
|
201
|
+
* };
|
|
202
|
+
* ```
|
|
203
|
+
*
|
|
204
|
+
* ## Field Exclusion
|
|
205
|
+
*
|
|
206
|
+
* By default, these fields are excluded from translation:
|
|
207
|
+
* - `created_at`, `updated_at`, `deleted_at`
|
|
208
|
+
* - `workflow_completion_date`, `workflow_step_due_date`
|
|
209
|
+
* - `received_date`, `date_required`, `private_at`
|
|
210
|
+
*
|
|
211
|
+
* ## Performance Considerations
|
|
212
|
+
*
|
|
213
|
+
* - **Parallel Translation**: All strings translate simultaneously
|
|
214
|
+
* - **Smart Caching**: Translations are cached in the string registry
|
|
215
|
+
* - **Incremental Updates**: Only new strings are translated on pagination
|
|
216
|
+
* - **Microtask Batching**: Multiple refreshes batched with RAF timing
|
|
217
|
+
* - **Memory Safe**: Cleanup prevents leaks from event listeners
|
|
218
|
+
*
|
|
219
|
+
* ## Integration with AG Grid
|
|
220
|
+
*
|
|
221
|
+
* The hook integrates directly with AG Grid's API:
|
|
222
|
+
* - `getRowData()`: Reads current row data for translation
|
|
223
|
+
* - `refreshCells()`: Forces cell updates after translation
|
|
224
|
+
* - `modelUpdated` event: Catches pagination/sorting/filtering
|
|
225
|
+
*
|
|
226
|
+
* It modifies row data in-place by:
|
|
227
|
+
* 1. Storing original values in `_originalLabel` properties
|
|
228
|
+
* 2. Updating `label` properties with translated text
|
|
229
|
+
* 3. Updating both `field.values` and `row[fieldId]` arrays
|
|
230
|
+
*
|
|
231
|
+
* ## Requirements
|
|
232
|
+
*
|
|
233
|
+
* - AG Grid table with `innerTableApi` property
|
|
234
|
+
* - Fields index with `byId` Map structure
|
|
235
|
+
* - Chrome browser with AI translation support
|
|
236
|
+
* - User gesture required for first translation
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* // Complete example with all features
|
|
240
|
+
* const {
|
|
241
|
+
* isShowingTranslations,
|
|
242
|
+
* isTranslating,
|
|
243
|
+
* toggleTranslations,
|
|
244
|
+
* applyTranslationsToNewData,
|
|
245
|
+
* translationProgress
|
|
246
|
+
* } = useTableTranslation({
|
|
247
|
+
* tableApi,
|
|
248
|
+
* fieldsIndex: fields,
|
|
249
|
+
* excludeFields: ['created_at', 'id'],
|
|
250
|
+
* shouldExcludeField: (field) => field.type === 'datetime',
|
|
251
|
+
* dataSource: myDataSource,
|
|
252
|
+
* });
|
|
253
|
+
*
|
|
254
|
+
* // Display global translation progress directly from the hook
|
|
255
|
+
* {translationProgress && (
|
|
256
|
+
* <div>
|
|
257
|
+
* Progress: {translationProgress.progress}%
|
|
258
|
+
* ({translationProgress.current}/{translationProgress.total})
|
|
259
|
+
* </div>
|
|
260
|
+
* )}
|
|
261
|
+
*/
|
|
262
|
+
declare function useDataTableAITranslation(): void;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* AI Translation Provider
|
|
266
|
+
*
|
|
267
|
+
* @module AITranslationProvider
|
|
268
|
+
* @description
|
|
269
|
+
* Core provider component for Chrome AI-powered translations in React applications.
|
|
270
|
+
* Manages translation state, string registration, language detection, and translation execution.
|
|
271
|
+
*
|
|
272
|
+
* ## Architecture Overview
|
|
273
|
+
*
|
|
274
|
+
* This provider orchestrates several key components:
|
|
275
|
+
* - **String Registry**: Tracks all translatable strings and their states
|
|
276
|
+
* - **Chrome AI Client**: Interfaces with Chrome's built-in AI translation API
|
|
277
|
+
* - **Translation Service**: Handles translation requests with batching and caching
|
|
278
|
+
* - **Render Version Manager**: Forces component re-renders when translations update
|
|
279
|
+
*
|
|
280
|
+
* ## Key Features
|
|
281
|
+
*
|
|
282
|
+
* 1. **Automatic String Registration**: All strings passed through `ait()` are registered
|
|
283
|
+
* 2. **Language Detection**: Automatically detects source language using Chrome AI
|
|
284
|
+
* 3. **Batched Translation**: Efficiently translates multiple strings in parallel
|
|
285
|
+
* 4. **Toggle Mechanism**: Switch between original and translated content on-demand
|
|
286
|
+
* 5. **User Gesture Required**: Chrome AI initialization requires user interaction
|
|
287
|
+
* 6. **Pagination Support**: New content is automatically registered and translated
|
|
288
|
+
*
|
|
289
|
+
* ## Usage
|
|
290
|
+
*
|
|
291
|
+
* ```tsx
|
|
292
|
+
* import { AITranslationProvider } from './ai-translations-package';
|
|
293
|
+
*
|
|
294
|
+
* function App() {
|
|
295
|
+
* const handleProgress = (progress, current, total) => {
|
|
296
|
+
* console.log(`Translation progress: ${progress}% (${current}/${total})`);
|
|
297
|
+
* };
|
|
298
|
+
*
|
|
299
|
+
* return (
|
|
300
|
+
* <AITranslationProvider locale="es" onProgressChange={handleProgress}>
|
|
301
|
+
* <YourApp />
|
|
302
|
+
* </AITranslationProvider>
|
|
303
|
+
* );
|
|
304
|
+
* }
|
|
305
|
+
* ```
|
|
306
|
+
*
|
|
307
|
+
* ## Translation Workflow
|
|
308
|
+
*
|
|
309
|
+
* 1. **Registration Phase**: Strings are registered via `ait(text)` calls
|
|
310
|
+
* 2. **Initialization**: User clicks toggle (user gesture required for Chrome AI)
|
|
311
|
+
* 3. **Detection Phase**: Source languages are detected for all registered strings
|
|
312
|
+
* 4. **Translation Phase**: Strings are translated to target locale
|
|
313
|
+
* 5. **Display Phase**: Translations are displayed, original text on toggle off
|
|
314
|
+
*
|
|
315
|
+
* ## Context Value
|
|
316
|
+
*
|
|
317
|
+
* The provider exposes:
|
|
318
|
+
* - `ait`: Translation function - wrap strings with this
|
|
319
|
+
* - `isShowingTranslations`: Current display state
|
|
320
|
+
* - `toggleTranslations`: Toggle between original and translated content
|
|
321
|
+
* - `isTranslating`: Whether translations are in progress
|
|
322
|
+
* - `initializeTranslators`: Manual initialization for specific languages
|
|
323
|
+
* - `isInitialized`: Whether Chrome AI translators are ready
|
|
324
|
+
* - `locale`: Current target language
|
|
325
|
+
* - `translationProgress`: Global translation progress (progress %, current count, total count)
|
|
326
|
+
*
|
|
327
|
+
* ## Requirements
|
|
328
|
+
*
|
|
329
|
+
* - Chrome browser with AI translation API support
|
|
330
|
+
* - User gesture required for initial translator creation
|
|
331
|
+
* - Network connection for AI model downloads (first use)
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* // Using the ait function in a component
|
|
335
|
+
* const { ait } = useAITranslation();
|
|
336
|
+
* return <h1>{ait('Hello World')}</h1>;
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* // Displaying global translation progress
|
|
340
|
+
* const { translationProgress, toggleTranslations } = useAITranslation();
|
|
341
|
+
*
|
|
342
|
+
* return (
|
|
343
|
+
* <div>
|
|
344
|
+
* <button onClick={toggleTranslations}>Translate</button>
|
|
345
|
+
* {translationProgress && (
|
|
346
|
+
* <div>
|
|
347
|
+
* Translating: {translationProgress.current}/{translationProgress.total}
|
|
348
|
+
* ({translationProgress.progress}%)
|
|
349
|
+
* </div>
|
|
350
|
+
* )}
|
|
351
|
+
* </div>
|
|
352
|
+
* );
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* // Manual initialization with specific languages
|
|
356
|
+
* const { initializeTranslators, toggleTranslations } = useAITranslation();
|
|
357
|
+
*
|
|
358
|
+
* <button onClick={async () => {
|
|
359
|
+
* await initializeTranslators(['es', 'fr'], ['en', 'de']);
|
|
360
|
+
* await toggleTranslations();
|
|
361
|
+
* }}>
|
|
362
|
+
* Translate to Spanish/French
|
|
363
|
+
* </button>
|
|
364
|
+
*/
|
|
365
|
+
declare function AITranslationProvider(): void;
|
|
366
|
+
|
|
367
|
+
export { AITranslationProvider, useAITranslation, useDataTableAITranslation };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AITranslationProvider: () => AITranslationProvider,
|
|
24
|
+
useAITranslation: () => useAITranslation,
|
|
25
|
+
useDataTableAITranslation: () => useDataTableAITranslation
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/hooks/useAiTranslation.tsx
|
|
30
|
+
function useAITranslation() {
|
|
31
|
+
return {
|
|
32
|
+
ait: () => "",
|
|
33
|
+
isShowingTranslations: false,
|
|
34
|
+
toggleTranslations: () => {
|
|
35
|
+
},
|
|
36
|
+
locale: "",
|
|
37
|
+
isTranslating: false,
|
|
38
|
+
renderVersion: void 0,
|
|
39
|
+
initializeTranslators: async () => {
|
|
40
|
+
},
|
|
41
|
+
isInitialized: false
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/hooks/useDataTableAITranslation.tsx
|
|
46
|
+
function useDataTableAITranslation() {
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/Provider.tsx
|
|
50
|
+
function AITranslationProvider() {
|
|
51
|
+
}
|
|
52
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
53
|
+
0 && (module.exports = {
|
|
54
|
+
AITranslationProvider,
|
|
55
|
+
useAITranslation,
|
|
56
|
+
useDataTableAITranslation
|
|
57
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/hooks/useAiTranslation.tsx
|
|
2
|
+
function useAITranslation() {
|
|
3
|
+
return {
|
|
4
|
+
ait: () => "",
|
|
5
|
+
isShowingTranslations: false,
|
|
6
|
+
toggleTranslations: () => {
|
|
7
|
+
},
|
|
8
|
+
locale: "",
|
|
9
|
+
isTranslating: false,
|
|
10
|
+
renderVersion: void 0,
|
|
11
|
+
initializeTranslators: async () => {
|
|
12
|
+
},
|
|
13
|
+
isInitialized: false
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/hooks/useDataTableAITranslation.tsx
|
|
18
|
+
function useDataTableAITranslation() {
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/Provider.tsx
|
|
22
|
+
function AITranslationProvider() {
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
AITranslationProvider,
|
|
26
|
+
useAITranslation,
|
|
27
|
+
useDataTableAITranslation
|
|
28
|
+
};
|