@procore/ai-translations 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 +39 -5
- package/dist/legacy/index.d.mts +28 -3
- package/dist/legacy/index.d.ts +28 -3
- package/dist/legacy/index.js +346 -74
- package/dist/legacy/index.mjs +346 -74
- package/dist/modern/index.d.mts +28 -3
- package/dist/modern/index.d.ts +28 -3
- package/dist/modern/index.js +339 -73
- package/dist/modern/index.mjs +339 -73
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,14 +4,14 @@ React package for AI-powered UI string translation in frontend apps. It provides
|
|
|
4
4
|
|
|
5
5
|
- `AITranslationProvider` to initialize translation context
|
|
6
6
|
- `AITranslateText` to render translated text
|
|
7
|
-
- `useAITranslation` for direct access to translation and progress state
|
|
7
|
+
- `useAITranslation` for direct access to translation, consent, and progress state
|
|
8
8
|
|
|
9
9
|
Need deeper implementation details? See the internal guide: [`README.internal.md`](./README.internal.md).
|
|
10
10
|
|
|
11
11
|
This package supports two runtime strategies:
|
|
12
12
|
|
|
13
|
-
- `frontend_translations`: browser-based translation (Chrome-family AI APIs)
|
|
14
|
-
- `backend_translations`: server-side translation API
|
|
13
|
+
- `frontend_translations`: browser-based translation (Chrome-family AI APIs). Translation runs sequentially and is gated on user consent when an on-device model must be downloaded.
|
|
14
|
+
- `backend_translations`: server-side translation API. No on-device model downloads; model-consent popups are suppressed automatically.
|
|
15
15
|
|
|
16
16
|
For Procore-specific operational details, see `README.internal.md`.
|
|
17
17
|
|
|
@@ -190,8 +190,21 @@ Returns:
|
|
|
190
190
|
- `tool: string`
|
|
191
191
|
- `translationProgress: { progress: number; current: number; total: number } | null`
|
|
192
192
|
- `modelDownloadProgress: ModelDownloadProgress | null`
|
|
193
|
+
- `modelConsent: ModelConsentRequest | null` - non-null while the translation run is paused awaiting user consent to download a source→target model; `null` otherwise
|
|
194
|
+
- `confirmModelDownload: () => void` - call this (e.g. from a Download button's `onClick`) to provide the required user gesture, start the download, and resume translation; no-op when `modelConsent` is `null` or when the active strategy is `backend_translations`
|
|
193
195
|
- `renderVersion: number | undefined`
|
|
194
196
|
|
|
197
|
+
### `normalizeLanguage(language: string): string`
|
|
198
|
+
|
|
199
|
+
Utility that strips the region/script subtag from a BCP-47 language tag (e.g. `"en-US"` → `"en"`). Falls back to the original string when no subtag is present.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import { normalizeLanguage } from '@procore/ai-translations';
|
|
203
|
+
|
|
204
|
+
normalizeLanguage('en-US'); // 'en'
|
|
205
|
+
normalizeLanguage('fr'); // 'fr'
|
|
206
|
+
```
|
|
207
|
+
|
|
195
208
|
### Feature flag helpers
|
|
196
209
|
|
|
197
210
|
- `AI_TRANSLATION_FEATURE_FLAG_KEY`
|
|
@@ -210,14 +223,35 @@ queueText --> manager[TranslationManager]
|
|
|
210
223
|
manager --> strategy[TranslatorStrategy]
|
|
211
224
|
strategy --> frontendClient[ChromeFrontendClient]
|
|
212
225
|
strategy --> backendClient[BackendApiClient]
|
|
213
|
-
frontendClient -->
|
|
226
|
+
frontendClient --> modelGate{ModelDownloadGate}
|
|
227
|
+
modelGate -- model ready --> translate[Translate]
|
|
228
|
+
modelGate -- model missing --> consentEvent[MODEL_CONSENT_REQUIRED event]
|
|
229
|
+
consentEvent --> popup[ModelDownloadConsentPopup]
|
|
230
|
+
popup -- user clicks Download --> confirmModelDownload[confirmModelDownload]
|
|
231
|
+
confirmModelDownload --> downloadModel[downloadModel]
|
|
232
|
+
downloadModel --> markReady[gate.markReady]
|
|
233
|
+
markReady --> translate
|
|
234
|
+
translate --> persist[PersistToIndexedDB]
|
|
214
235
|
backendClient --> persist
|
|
215
236
|
persist --> publish[PublishTranslationEvents]
|
|
216
237
|
publish --> rerender[AITranslateTextRerender]
|
|
217
238
|
rerender --> translatedUi[DisplayTranslatedText]
|
|
218
239
|
```
|
|
219
240
|
|
|
220
|
-
At runtime, strings are registered through `ait()`, processed in batches, cached in memory and IndexedDB, and then rerendered via package events.
|
|
241
|
+
At runtime, strings are registered through `ait()`, processed sequentially (frontend strategy) or in configurable batches (backend strategy), cached in memory and IndexedDB, and then rerendered via package events.
|
|
242
|
+
|
|
243
|
+
### Frontend model-download consent flow
|
|
244
|
+
|
|
245
|
+
When the `frontend_translations` strategy encounters a source→target model that has not yet been downloaded, Chrome requires a user gesture to initiate the download. The package handles this automatically:
|
|
246
|
+
|
|
247
|
+
1. The translation run **pauses** and fires a `MODEL_CONSENT_REQUIRED` event carrying `{ sourceLanguage, targetLanguage }`.
|
|
248
|
+
2. `useAITranslation().modelConsent` becomes non-null — render `<ModelDownloadConsentPopup />` (from `@procore/ai-translation-utils`) to surface the consent UI to the user.
|
|
249
|
+
3. The user clicks the **Download** button, calling `confirmModelDownload()` which provides the required gesture, starts the download, and shows `<ModelDownloadProgressPopup />`.
|
|
250
|
+
4. When the download completes, `modelDownloadGate.markReady(source, target)` is called and the paused translation run **resumes automatically**.
|
|
251
|
+
5. Steps 1–4 repeat for each unique source→target model pair that is not yet cached. Already-downloaded models skip the consent step entirely.
|
|
252
|
+
6. After all texts are translated the run terminates. Translated text is displayed immediately as each translation completes, not only at the end.
|
|
253
|
+
|
|
254
|
+
> **Important**: your app must render `<ModelDownloadConsentPopup />` inside `AITranslationProvider` for the consent flow to work. Without it, `ensureModelReady` will never resolve and the translation run will hang indefinitely.
|
|
221
255
|
|
|
222
256
|
## Configuration
|
|
223
257
|
|
package/dist/legacy/index.d.mts
CHANGED
|
@@ -64,6 +64,20 @@ interface ModelDownloadProgress {
|
|
|
64
64
|
progress: number;
|
|
65
65
|
/** True once the model has finished downloading */
|
|
66
66
|
isComplete: boolean;
|
|
67
|
+
/** Source language of the model being downloaded (e.g. `"fr"`) */
|
|
68
|
+
sourceLanguage: string;
|
|
69
|
+
/** Target language of the model being downloaded (e.g. `"en"`) */
|
|
70
|
+
targetLanguage: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A pending request for the user to consent to downloading a specific
|
|
74
|
+
* source -> target language model before translation can continue.
|
|
75
|
+
*/
|
|
76
|
+
interface ModelConsentRequest {
|
|
77
|
+
/** Source language of the model that needs downloading (e.g. `"fr"`). */
|
|
78
|
+
sourceLanguage: string;
|
|
79
|
+
/** Target language of the model that needs downloading (e.g. `"en"`). */
|
|
80
|
+
targetLanguage: string;
|
|
67
81
|
}
|
|
68
82
|
interface AITranslationContextValue {
|
|
69
83
|
ait: (text: string) => Promise<string>;
|
|
@@ -77,6 +91,17 @@ interface AITranslationContextValue {
|
|
|
77
91
|
translationProgress: TranslationProgress | null;
|
|
78
92
|
/** Chrome AI model download progress; `null` until a download begins. */
|
|
79
93
|
modelDownloadProgress: ModelDownloadProgress | null;
|
|
94
|
+
/**
|
|
95
|
+
* Pending model the translation run is paused on, awaiting the user's consent
|
|
96
|
+
* to download; `null` when no consent is required.
|
|
97
|
+
*/
|
|
98
|
+
modelConsent: ModelConsentRequest | null;
|
|
99
|
+
/**
|
|
100
|
+
* Confirms the pending {@link modelConsent} download. Must be called from a
|
|
101
|
+
* user gesture (e.g. a click handler) since Chrome requires a gesture to
|
|
102
|
+
* start a model download.
|
|
103
|
+
*/
|
|
104
|
+
confirmModelDownload: () => void;
|
|
80
105
|
tool: string;
|
|
81
106
|
/** Called by `useAIAnalytics` with a fully assembled event. The MFE is responsible for sending it. */
|
|
82
107
|
onTrackAnalyticsEvent?: AIAnalyticsTracker;
|
|
@@ -171,7 +196,7 @@ type Action = (typeof ACTION)[keyof typeof ACTION];
|
|
|
171
196
|
* Builds the `object` segment: `{pageContext}_{buttonType}_button`
|
|
172
197
|
* e.g. `buildObject('view', 'translate')` → `'view_translate_button'`
|
|
173
198
|
*/
|
|
174
|
-
declare function buildObject(
|
|
199
|
+
declare function buildObject(buttonType: ButtonType): string;
|
|
175
200
|
/**
|
|
176
201
|
* Builds a fully-qualified event key:
|
|
177
202
|
* `ux.web.feature.{scope}.{tool}.{object}.{action}`
|
|
@@ -320,7 +345,7 @@ declare const CustomizableAITranslateText: React.FC<CustomizableAITranslateTextP
|
|
|
320
345
|
/**
|
|
321
346
|
* The key used to store/retrieve the feature flag in local storage.
|
|
322
347
|
*/
|
|
323
|
-
declare const AI_TRANSLATION_FEATURE_FLAG_KEY = "
|
|
348
|
+
declare const AI_TRANSLATION_FEATURE_FLAG_KEY = "ai-translation";
|
|
324
349
|
/**
|
|
325
350
|
* Retrieves the LD ID for the AI translation feature flag based on the domain.
|
|
326
351
|
* @param domain - The domain to determine the LD ID for
|
|
@@ -335,4 +360,4 @@ declare global {
|
|
|
335
360
|
var _BACKEND_AI_TRANSLATION_IN_PROGRESS_: boolean;
|
|
336
361
|
}
|
|
337
362
|
|
|
338
|
-
export { ACTION, type AIAnalyticsEventProperties, type AIAnalyticsTracker, AITranslateText, type AITranslateTextProps, AITranslationProvider, AI_TRANSLATION_FEATURE_FLAG_KEY, type Action, type AnalyticEvent, BUTTON_TYPE, type BuildAnalyticEventParams, type ButtonType, CustomizableAITranslateText, type CustomizableAITranslateTextProps, type EventKeyParts, type Scope, type TextSegmenter, type TranslatableSegment, type TranslatedIconProps, type UseAIAnalyticsReturn, type UseConfigOptions, buildAnalyticEvent, buildEventKey, buildObject, getAITranslationLDId, isSupportedBrowser, useAIAnalytics, useAITranslation, useConfig };
|
|
363
|
+
export { ACTION, type AIAnalyticsEventProperties, type AIAnalyticsTracker, AITranslateText, type AITranslateTextProps, AITranslationProvider, AI_TRANSLATION_FEATURE_FLAG_KEY, type Action, type AnalyticEvent, BUTTON_TYPE, type BuildAnalyticEventParams, type ButtonType, CustomizableAITranslateText, type CustomizableAITranslateTextProps, type EventKeyParts, type ModelConsentRequest, type ModelDownloadProgress, type Scope, type TextSegmenter, type TranslatableSegment, type TranslatedIconProps, type UseAIAnalyticsReturn, type UseConfigOptions, buildAnalyticEvent, buildEventKey, buildObject, getAITranslationLDId, isSupportedBrowser, useAIAnalytics, useAITranslation, useConfig };
|
package/dist/legacy/index.d.ts
CHANGED
|
@@ -64,6 +64,20 @@ interface ModelDownloadProgress {
|
|
|
64
64
|
progress: number;
|
|
65
65
|
/** True once the model has finished downloading */
|
|
66
66
|
isComplete: boolean;
|
|
67
|
+
/** Source language of the model being downloaded (e.g. `"fr"`) */
|
|
68
|
+
sourceLanguage: string;
|
|
69
|
+
/** Target language of the model being downloaded (e.g. `"en"`) */
|
|
70
|
+
targetLanguage: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A pending request for the user to consent to downloading a specific
|
|
74
|
+
* source -> target language model before translation can continue.
|
|
75
|
+
*/
|
|
76
|
+
interface ModelConsentRequest {
|
|
77
|
+
/** Source language of the model that needs downloading (e.g. `"fr"`). */
|
|
78
|
+
sourceLanguage: string;
|
|
79
|
+
/** Target language of the model that needs downloading (e.g. `"en"`). */
|
|
80
|
+
targetLanguage: string;
|
|
67
81
|
}
|
|
68
82
|
interface AITranslationContextValue {
|
|
69
83
|
ait: (text: string) => Promise<string>;
|
|
@@ -77,6 +91,17 @@ interface AITranslationContextValue {
|
|
|
77
91
|
translationProgress: TranslationProgress | null;
|
|
78
92
|
/** Chrome AI model download progress; `null` until a download begins. */
|
|
79
93
|
modelDownloadProgress: ModelDownloadProgress | null;
|
|
94
|
+
/**
|
|
95
|
+
* Pending model the translation run is paused on, awaiting the user's consent
|
|
96
|
+
* to download; `null` when no consent is required.
|
|
97
|
+
*/
|
|
98
|
+
modelConsent: ModelConsentRequest | null;
|
|
99
|
+
/**
|
|
100
|
+
* Confirms the pending {@link modelConsent} download. Must be called from a
|
|
101
|
+
* user gesture (e.g. a click handler) since Chrome requires a gesture to
|
|
102
|
+
* start a model download.
|
|
103
|
+
*/
|
|
104
|
+
confirmModelDownload: () => void;
|
|
80
105
|
tool: string;
|
|
81
106
|
/** Called by `useAIAnalytics` with a fully assembled event. The MFE is responsible for sending it. */
|
|
82
107
|
onTrackAnalyticsEvent?: AIAnalyticsTracker;
|
|
@@ -171,7 +196,7 @@ type Action = (typeof ACTION)[keyof typeof ACTION];
|
|
|
171
196
|
* Builds the `object` segment: `{pageContext}_{buttonType}_button`
|
|
172
197
|
* e.g. `buildObject('view', 'translate')` → `'view_translate_button'`
|
|
173
198
|
*/
|
|
174
|
-
declare function buildObject(
|
|
199
|
+
declare function buildObject(buttonType: ButtonType): string;
|
|
175
200
|
/**
|
|
176
201
|
* Builds a fully-qualified event key:
|
|
177
202
|
* `ux.web.feature.{scope}.{tool}.{object}.{action}`
|
|
@@ -320,7 +345,7 @@ declare const CustomizableAITranslateText: React.FC<CustomizableAITranslateTextP
|
|
|
320
345
|
/**
|
|
321
346
|
* The key used to store/retrieve the feature flag in local storage.
|
|
322
347
|
*/
|
|
323
|
-
declare const AI_TRANSLATION_FEATURE_FLAG_KEY = "
|
|
348
|
+
declare const AI_TRANSLATION_FEATURE_FLAG_KEY = "ai-translation";
|
|
324
349
|
/**
|
|
325
350
|
* Retrieves the LD ID for the AI translation feature flag based on the domain.
|
|
326
351
|
* @param domain - The domain to determine the LD ID for
|
|
@@ -335,4 +360,4 @@ declare global {
|
|
|
335
360
|
var _BACKEND_AI_TRANSLATION_IN_PROGRESS_: boolean;
|
|
336
361
|
}
|
|
337
362
|
|
|
338
|
-
export { ACTION, type AIAnalyticsEventProperties, type AIAnalyticsTracker, AITranslateText, type AITranslateTextProps, AITranslationProvider, AI_TRANSLATION_FEATURE_FLAG_KEY, type Action, type AnalyticEvent, BUTTON_TYPE, type BuildAnalyticEventParams, type ButtonType, CustomizableAITranslateText, type CustomizableAITranslateTextProps, type EventKeyParts, type Scope, type TextSegmenter, type TranslatableSegment, type TranslatedIconProps, type UseAIAnalyticsReturn, type UseConfigOptions, buildAnalyticEvent, buildEventKey, buildObject, getAITranslationLDId, isSupportedBrowser, useAIAnalytics, useAITranslation, useConfig };
|
|
363
|
+
export { ACTION, type AIAnalyticsEventProperties, type AIAnalyticsTracker, AITranslateText, type AITranslateTextProps, AITranslationProvider, AI_TRANSLATION_FEATURE_FLAG_KEY, type Action, type AnalyticEvent, BUTTON_TYPE, type BuildAnalyticEventParams, type ButtonType, CustomizableAITranslateText, type CustomizableAITranslateTextProps, type EventKeyParts, type ModelConsentRequest, type ModelDownloadProgress, type Scope, type TextSegmenter, type TranslatableSegment, type TranslatedIconProps, type UseAIAnalyticsReturn, type UseConfigOptions, buildAnalyticEvent, buildEventKey, buildObject, getAITranslationLDId, isSupportedBrowser, useAIAnalytics, useAITranslation, useConfig };
|