@procore/ai-translations 0.5.0 → 0.6.1

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.
@@ -22,10 +22,16 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
22
22
  // src/index.ts
23
23
  var index_exports = {};
24
24
  __export(index_exports, {
25
+ ACTION: () => ACTION,
25
26
  AITranslateText: () => AITranslateText,
26
27
  AITranslationProvider: () => AITranslationProvider,
27
28
  AI_TRANSLATION_FEATURE_FLAG_KEY: () => AI_TRANSLATION_FEATURE_FLAG_KEY,
29
+ BUTTON_TYPE: () => BUTTON_TYPE,
30
+ buildAnalyticEvent: () => buildAnalyticEvent,
31
+ buildEventKey: () => buildEventKey,
32
+ buildObject: () => buildObject,
28
33
  getAITranslationLDId: () => getAITranslationLDId,
34
+ useAIAnalytics: () => useAIAnalytics,
29
35
  useAITranslation: () => useAITranslation,
30
36
  useConfig: () => useConfig
31
37
  });
@@ -81,6 +87,9 @@ var Config = class _Config {
81
87
  setToolName(name) {
82
88
  this.toolName = name;
83
89
  }
90
+ isBackendTranslationStrategy() {
91
+ return this.ToolConfig.strategy === "backend_translations";
92
+ }
84
93
  getToolName() {
85
94
  return this.toolName;
86
95
  }
@@ -416,6 +425,19 @@ var _Storage = class _Storage {
416
425
  }
417
426
  }
418
427
  // ------------------------------------
428
+ // 🗑️ Clear Translation by ID
429
+ // ------------------------------------
430
+ static async deleteById(id) {
431
+ try {
432
+ const db = await _Storage.getDB();
433
+ await db.delete(_Storage.STORE_NAME, id);
434
+ return true;
435
+ } catch (error) {
436
+ console.error("[Storage] Failed to delete by id:", error);
437
+ return false;
438
+ }
439
+ }
440
+ // ------------------------------------
419
441
  // 🗑️ Clear All Translations
420
442
  // ------------------------------------
421
443
  static async clearAll() {
@@ -502,7 +524,9 @@ var _TranslationRegistry = class _TranslationRegistry {
502
524
  async removeTextsFromEnqueued(texts, targetLanguage, strategy) {
503
525
  for (const text of texts) {
504
526
  const id = await Storage.generateId(text, targetLanguage, this.tool);
505
- _TranslationRegistry.enqueuedItems.delete(`${id}:${strategy}`);
527
+ _TranslationRegistry.enqueuedItems.delete(
528
+ this.generateEnqueuedKey(id, strategy)
529
+ );
506
530
  }
507
531
  }
508
532
  static removeFromEnqueued(key) {
@@ -511,10 +535,19 @@ var _TranslationRegistry = class _TranslationRegistry {
511
535
  generateEnqueuedKey(id, strategy) {
512
536
  return `${id}:${strategy}`;
513
537
  }
514
- async get(text, targetLanguage, tool) {
538
+ async get(text, targetLanguage, tool, config2) {
515
539
  const key = await Hash.generateFromMultiple([text, targetLanguage, tool]);
516
- if (_TranslationRegistry.memoryCache.has(key)) {
517
- return _TranslationRegistry.memoryCache.get(key);
540
+ const cached = _TranslationRegistry.memoryCache.get(key);
541
+ if (cached) {
542
+ if (cached.translationStrategy === "frontend_translations" && config2.isBackendTranslationStrategy()) {
543
+ _TranslationRegistry.memoryCache.delete(key);
544
+ if (cached.translatedText) {
545
+ _TranslationRegistry.originalTextIndex.delete(cached.translatedText);
546
+ }
547
+ await Storage.deleteById(key);
548
+ return void 0;
549
+ }
550
+ return cached;
518
551
  }
519
552
  const translation = await Storage.getTranslation(
520
553
  text,
@@ -522,6 +555,10 @@ var _TranslationRegistry = class _TranslationRegistry {
522
555
  tool
523
556
  );
524
557
  if (translation !== void 0) {
558
+ if (translation.translation_strategy === "frontend_translations" && config2.isBackendTranslationStrategy()) {
559
+ await Storage.deleteById(translation.id);
560
+ return void 0;
561
+ }
525
562
  return this.toTranslationRegistryEntry(translation);
526
563
  }
527
564
  return void 0;
@@ -794,19 +831,21 @@ var TranslationManager = class {
794
831
  this.translationProgress.total = queueManager.queueSize(
795
832
  this.currentTranslatorStrategy
796
833
  );
797
- for (const batch of queueManager.generateBatches(
798
- this.translator.getConfig()
799
- )) {
800
- batch.forEach((entry) => this.mfeToBeNotified.add(entry.tool));
801
- const result = await this.translator.processTranslations(
802
- batch.map(
803
- (entry) => this.convertTranslationQueueEntryToTranslationRequest(entry)
804
- )
805
- );
806
- this.setTranslationProgress(batch.length);
807
- await this.updateDatabaseWithTranslations(result);
808
- await this.notifyTranslationCompleted();
809
- }
834
+ do {
835
+ for (const batch of queueManager.generateBatches(
836
+ this.translator.getConfig()
837
+ )) {
838
+ batch.forEach((entry) => this.mfeToBeNotified.add(entry.tool));
839
+ const result = await this.translator.processTranslations(
840
+ batch.map(
841
+ (entry) => this.convertTranslationQueueEntryToTranslationRequest(entry)
842
+ )
843
+ );
844
+ this.setTranslationProgress(batch.length);
845
+ await this.updateDatabaseWithTranslations(result);
846
+ await this.notifyTranslationCompleted();
847
+ }
848
+ } while (queueManager.queueSize(this.currentTranslatorStrategy) > 0);
810
849
  this.resetTranslationProgress();
811
850
  this.publishTranslationProgress();
812
851
  if (this.currentTranslatorStrategy === "frontend_translations") {
@@ -960,8 +999,16 @@ var Client = class {
960
999
  method: "POST",
961
1000
  body: JSON.stringify(requests)
962
1001
  });
1002
+ const responseBody = Array.isArray(data) ? data.map((group) => ({
1003
+ ...group,
1004
+ translations: Array.isArray(group.translations) ? group.translations.map((t) => ({
1005
+ ...t,
1006
+ isTranslated: t.isTranslated ?? (!!t.translation && t.translation !== ""),
1007
+ retryable: t.retryable ?? true
1008
+ })) : []
1009
+ })) : data;
963
1010
  return {
964
- responseBody: data,
1011
+ responseBody,
965
1012
  success: true
966
1013
  };
967
1014
  } catch (error) {
@@ -1039,11 +1086,54 @@ var getModelDownloadEventHandler = () => {
1039
1086
  }
1040
1087
  return _modelDownloadEventHandler;
1041
1088
  };
1089
+ var SUPPORTED_LANGUAGES = /* @__PURE__ */ new Set([
1090
+ "ar",
1091
+ "bn",
1092
+ "bg",
1093
+ "zh",
1094
+ "hr",
1095
+ "cs",
1096
+ "da",
1097
+ "nl",
1098
+ "en",
1099
+ "fi",
1100
+ "fr",
1101
+ "de",
1102
+ "el",
1103
+ "he",
1104
+ "hi",
1105
+ "hu",
1106
+ "id",
1107
+ "it",
1108
+ "ja",
1109
+ "kn",
1110
+ "ko",
1111
+ "lt",
1112
+ "mr",
1113
+ "no",
1114
+ "pl",
1115
+ "pt",
1116
+ "ro",
1117
+ "ru",
1118
+ "sk",
1119
+ "sl",
1120
+ "es",
1121
+ "sv",
1122
+ "ta",
1123
+ "te",
1124
+ "th",
1125
+ "tr",
1126
+ "uk",
1127
+ "vi"
1128
+ ]);
1042
1129
  var _ChromeTranslator = class _ChromeTranslator {
1043
1130
  constructor(translator) {
1044
1131
  __publicField(this, "translator");
1045
1132
  this.translator = translator;
1046
1133
  }
1134
+ static isSupportedLanguage(lang) {
1135
+ return SUPPORTED_LANGUAGES.has(lang) || SUPPORTED_LANGUAGES.has(lang.split("-")[0] ?? "");
1136
+ }
1047
1137
  static ensureRegistry() {
1048
1138
  if (!globalThis.chromeTranslatorRegistry) {
1049
1139
  globalThis.chromeTranslatorRegistry = /* @__PURE__ */ new Map();
@@ -1065,30 +1155,31 @@ var _ChromeTranslator = class _ChromeTranslator {
1065
1155
  );
1066
1156
  }
1067
1157
  static async createTranslator(source, target) {
1158
+ const key = this.generateKey(source, target);
1068
1159
  let resolveReady;
1069
- this.translatorReadyPromise = new Promise((resolve) => {
1160
+ const readyPromise = new Promise((resolve) => {
1070
1161
  resolveReady = resolve;
1071
1162
  });
1163
+ this.translatorReadyPromises.set(key, readyPromise);
1072
1164
  let isDownloading = false;
1073
1165
  const translator = await Translator.create({
1074
1166
  sourceLanguage: source,
1075
1167
  targetLanguage: target,
1076
1168
  monitor(m) {
1077
- m.addEventListener(
1078
- "downloadprogress",
1079
- (e) => {
1080
- isDownloading = true;
1081
- const progress = e.total > 0 ? Math.round(e.loaded / e.total * 100) : 0;
1082
- getModelDownloadEventHandler().publishModelDownloadProgressEvent(
1083
- e.loaded,
1084
- e.total,
1085
- progress
1086
- );
1087
- if (e.loaded === e.total) {
1088
- resolveReady();
1089
- }
1169
+ m.addEventListener("downloadprogress", (e) => {
1170
+ isDownloading = true;
1171
+ const loaded = e.loaded ?? 0;
1172
+ const total = e.total ?? 0;
1173
+ const progress = total > 0 ? Math.round(loaded / total * 100) : 0;
1174
+ getModelDownloadEventHandler().publishModelDownloadProgressEvent(
1175
+ loaded,
1176
+ total,
1177
+ progress
1178
+ );
1179
+ if (total > 0 && loaded >= total) {
1180
+ resolveReady();
1090
1181
  }
1091
- );
1182
+ });
1092
1183
  }
1093
1184
  });
1094
1185
  if (!isDownloading) {
@@ -1096,8 +1187,8 @@ var _ChromeTranslator = class _ChromeTranslator {
1096
1187
  }
1097
1188
  return translator;
1098
1189
  }
1099
- static waitForReady() {
1100
- return this.translatorReadyPromise;
1190
+ static waitForReady(key) {
1191
+ return this.translatorReadyPromises.get(key) ?? Promise.resolve();
1101
1192
  }
1102
1193
  static async translate(text, targetLanguage) {
1103
1194
  var _a;
@@ -1106,8 +1197,17 @@ var _ChromeTranslator = class _ChromeTranslator {
1106
1197
  const detector = await ChromeLanguageDetector.getInstance();
1107
1198
  const sourceLanguage = await detector.detectLanguage(text);
1108
1199
  const key = this.generateKey(sourceLanguage, targetLanguage);
1109
- let instance = globalThis.chromeTranslatorRegistry.get(key);
1110
- if (!instance) {
1200
+ if (!this.isSupportedLanguage(sourceLanguage) || !this.isSupportedLanguage(targetLanguage)) {
1201
+ return {
1202
+ translation: text,
1203
+ sourceLanguage,
1204
+ success: false,
1205
+ retryable: false,
1206
+ errorMessage: `Unsupported language pair: ${sourceLanguage} \u2192 ${targetLanguage}`
1207
+ };
1208
+ }
1209
+ const existingInstance = globalThis.chromeTranslatorRegistry.get(key);
1210
+ if (!existingInstance) {
1111
1211
  const translatorCapabilities = await Translator.availability({
1112
1212
  sourceLanguage,
1113
1213
  targetLanguage
@@ -1125,10 +1225,16 @@ var _ChromeTranslator = class _ChromeTranslator {
1125
1225
  sourceLanguage,
1126
1226
  targetLanguage
1127
1227
  );
1128
- instance = new _ChromeTranslator(chromeTranslator);
1129
- globalThis.chromeTranslatorRegistry.set(key, instance);
1228
+ if (!globalThis.chromeTranslatorRegistry.has(key)) {
1229
+ globalThis.chromeTranslatorRegistry.set(
1230
+ key,
1231
+ new _ChromeTranslator(chromeTranslator)
1232
+ );
1233
+ }
1130
1234
  }
1131
- await this.waitForReady();
1235
+ const instance = globalThis.chromeTranslatorRegistry.get(key);
1236
+ await this.waitForReady(key);
1237
+ this.translatorReadyPromises.delete(key);
1132
1238
  const translation = await ((_a = instance.translator) == null ? void 0 : _a.translate(text));
1133
1239
  if (!translation) {
1134
1240
  return {
@@ -1136,7 +1242,7 @@ var _ChromeTranslator = class _ChromeTranslator {
1136
1242
  sourceLanguage,
1137
1243
  success: false,
1138
1244
  errorMessage: "Translation failed",
1139
- retryable: true
1245
+ retryable: false
1140
1246
  };
1141
1247
  }
1142
1248
  return {
@@ -1146,11 +1252,12 @@ var _ChromeTranslator = class _ChromeTranslator {
1146
1252
  retryable: true
1147
1253
  };
1148
1254
  } catch (error) {
1255
+ const message = error instanceof Error ? error.message : "Unknown error";
1149
1256
  return {
1150
1257
  translation: text,
1151
1258
  sourceLanguage: targetLanguage,
1152
1259
  success: false,
1153
- errorMessage: error instanceof Error ? error.message : "Unknown error",
1260
+ errorMessage: message,
1154
1261
  retryable: true
1155
1262
  };
1156
1263
  }
@@ -1159,7 +1266,7 @@ var _ChromeTranslator = class _ChromeTranslator {
1159
1266
  return `${sourceLanguage.toUpperCase()}-${targetLanguage.toUpperCase()}`;
1160
1267
  }
1161
1268
  };
1162
- __publicField(_ChromeTranslator, "translatorReadyPromise", Promise.resolve());
1269
+ __publicField(_ChromeTranslator, "translatorReadyPromises", /* @__PURE__ */ new Map());
1163
1270
  var ChromeTranslator = _ChromeTranslator;
1164
1271
 
1165
1272
  // src/translators/frontend_translators/chrome/client.ts
@@ -1309,7 +1416,8 @@ var aitFunction = async (text, translationRegistry, config2, tool) => {
1309
1416
  const existingByOriginal = await translationRegistry.get(
1310
1417
  text,
1311
1418
  targetLanguage,
1312
- tool
1419
+ tool,
1420
+ config2
1313
1421
  );
1314
1422
  if (existingByOriginal && existingByOriginal.isTranslated && existingByOriginal.translatedText && existingByOriginal.translatedText.trim() !== "") {
1315
1423
  return existingByOriginal.translatedText;
@@ -1370,7 +1478,12 @@ function AITranslationInnerProvider(props) {
1370
1478
  companyId,
1371
1479
  userId,
1372
1480
  projectId,
1373
- enableAIT = true
1481
+ enableAIT = true,
1482
+ companyLocale,
1483
+ projectLocale,
1484
+ onTrackAnalyticsEvent,
1485
+ page,
1486
+ scope
1374
1487
  } = props;
1375
1488
  const [translationProgress, setTranslationProgress] = (0, import_react.useState)(null);
1376
1489
  const [modelDownloadProgress, setModelDownloadProgress] = (0, import_react.useState)(null);
@@ -1426,15 +1539,15 @@ function AITranslationInnerProvider(props) {
1426
1539
  return () => unsubscribe();
1427
1540
  }, []);
1428
1541
  (0, import_react.useEffect)(() => {
1429
- if (isFetched && remoteConfig && remoteConfig[tool]) {
1430
- setConfig((prevConfig) => {
1431
- const clonedConfig = prevConfig.clone();
1432
- clonedConfig.setTargetLanguage(locale);
1433
- clonedConfig.setToolConfig(remoteConfig[tool]);
1434
- translator.current.updateConfig(clonedConfig);
1435
- return clonedConfig;
1436
- });
1437
- }
1542
+ if (!isFetched || !remoteConfig) return;
1543
+ const toolConfig = remoteConfig[tool] ?? remoteConfig;
1544
+ setConfig((prevConfig) => {
1545
+ const clonedConfig = prevConfig.clone();
1546
+ clonedConfig.setTargetLanguage(locale);
1547
+ clonedConfig.setToolConfig(toolConfig);
1548
+ translator.current.updateConfig(clonedConfig);
1549
+ return clonedConfig;
1550
+ });
1438
1551
  }, [tool, remoteConfig, isFetched, locale]);
1439
1552
  config2.setTargetLanguage(locale);
1440
1553
  config2.setToolName(tool);
@@ -1447,10 +1560,15 @@ function AITranslationInnerProvider(props) {
1447
1560
  const contextValue = {
1448
1561
  ait,
1449
1562
  locale,
1563
+ companyLocale,
1564
+ projectLocale,
1450
1565
  renderVersion: renderVersionManager.getVersion(),
1451
1566
  translationProgress,
1452
1567
  modelDownloadProgress,
1453
- tool
1568
+ tool,
1569
+ onTrackAnalyticsEvent,
1570
+ page,
1571
+ scope
1454
1572
  };
1455
1573
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AITranslationContext.Provider, { value: contextValue, children });
1456
1574
  }
@@ -1470,15 +1588,143 @@ function useAITranslation() {
1470
1588
  return ctx;
1471
1589
  }
1472
1590
 
1591
+ // src/hooks/useAIAnalytics.ts
1592
+ var import_react3 = require("react");
1593
+
1594
+ // src/analytics/events.ts
1595
+ var BUTTON_TYPE = {
1596
+ TRANSLATE: "translate",
1597
+ HIGHLIGHT: "highlight"
1598
+ };
1599
+ var ACTION = {
1600
+ CLICKED: "clicked"
1601
+ };
1602
+ function buildObject(pageContext, buttonType) {
1603
+ return `${pageContext}_${buttonType}_button`;
1604
+ }
1605
+ function buildEventKey(parts) {
1606
+ const { scope, tool, object, action } = parts;
1607
+ return `ux.web.feature.${scope}.${tool}.${object}.${action}`;
1608
+ }
1609
+ function buildAnalyticEvent(params) {
1610
+ const {
1611
+ scope,
1612
+ tool,
1613
+ pageContext,
1614
+ buttonType,
1615
+ baseProperties,
1616
+ action,
1617
+ additionalProperties
1618
+ } = params;
1619
+ const resolvedAction = action ?? ACTION.CLICKED;
1620
+ const object = buildObject(pageContext, buttonType);
1621
+ const key = buildEventKey({
1622
+ scope,
1623
+ tool,
1624
+ object,
1625
+ action: resolvedAction
1626
+ });
1627
+ const properties = {
1628
+ ...baseProperties,
1629
+ ...additionalProperties
1630
+ };
1631
+ return { key, properties };
1632
+ }
1633
+
1634
+ // src/hooks/useAIAnalytics.ts
1635
+ function useAIAnalytics() {
1636
+ const ctx = (0, import_react3.useContext)(AITranslationContext);
1637
+ if (!ctx) {
1638
+ throw new Error(
1639
+ "useAIAnalytics must be used inside an AITranslationProvider"
1640
+ );
1641
+ }
1642
+ const {
1643
+ locale,
1644
+ companyLocale,
1645
+ projectLocale,
1646
+ tool,
1647
+ page,
1648
+ scope,
1649
+ onTrackAnalyticsEvent
1650
+ } = ctx;
1651
+ const isTrackingEnabled = Boolean(onTrackAnalyticsEvent);
1652
+ const buildBaseProperties = (0, import_react3.useCallback)(() => {
1653
+ const props = {
1654
+ user_locale: locale,
1655
+ tool,
1656
+ page: page ?? ""
1657
+ };
1658
+ if (companyLocale) props.company_locale = companyLocale;
1659
+ if (projectLocale) props.project_locale = projectLocale;
1660
+ return props;
1661
+ }, [locale, tool, page, companyLocale, projectLocale]);
1662
+ const trackTranslateButtonClicked = (0, import_react3.useCallback)(
1663
+ (additionalProperties) => {
1664
+ if (!onTrackAnalyticsEvent || !page || !scope) return;
1665
+ onTrackAnalyticsEvent(
1666
+ buildAnalyticEvent({
1667
+ scope,
1668
+ tool,
1669
+ pageContext: page,
1670
+ buttonType: BUTTON_TYPE.TRANSLATE,
1671
+ baseProperties: buildBaseProperties(),
1672
+ additionalProperties
1673
+ })
1674
+ );
1675
+ },
1676
+ [onTrackAnalyticsEvent, tool, page, scope, buildBaseProperties]
1677
+ );
1678
+ const trackHighlightButtonClicked = (0, import_react3.useCallback)(
1679
+ (additionalProperties) => {
1680
+ if (!onTrackAnalyticsEvent || !page || !scope) return;
1681
+ onTrackAnalyticsEvent(
1682
+ buildAnalyticEvent({
1683
+ scope,
1684
+ tool,
1685
+ pageContext: page,
1686
+ buttonType: BUTTON_TYPE.HIGHLIGHT,
1687
+ baseProperties: buildBaseProperties(),
1688
+ additionalProperties
1689
+ })
1690
+ );
1691
+ },
1692
+ [onTrackAnalyticsEvent, tool, page, scope, buildBaseProperties]
1693
+ );
1694
+ const trackCustomEvent = (0, import_react3.useCallback)(
1695
+ (buttonType, action, additionalProperties) => {
1696
+ if (!onTrackAnalyticsEvent || !page || !scope) return;
1697
+ onTrackAnalyticsEvent(
1698
+ buildAnalyticEvent({
1699
+ scope,
1700
+ tool,
1701
+ pageContext: page,
1702
+ buttonType,
1703
+ baseProperties: buildBaseProperties(),
1704
+ action,
1705
+ additionalProperties
1706
+ })
1707
+ );
1708
+ },
1709
+ [onTrackAnalyticsEvent, tool, page, scope, buildBaseProperties]
1710
+ );
1711
+ return {
1712
+ trackTranslateButtonClicked,
1713
+ trackHighlightButtonClicked,
1714
+ trackCustomEvent,
1715
+ isTrackingEnabled
1716
+ };
1717
+ }
1718
+
1473
1719
  // src/components/AITranslateText.tsx
1474
- var import_react4 = require("react");
1720
+ var import_react5 = require("react");
1475
1721
 
1476
1722
  // src/components/TranslatedIcon.tsx
1477
- var import_react3 = require("react");
1723
+ var import_react4 = require("react");
1478
1724
  var import_jsx_runtime2 = require("react/jsx-runtime");
1479
1725
  var TranslatedIcon = ({
1480
- width = 14,
1481
- height = 14,
1726
+ width = 24,
1727
+ height = 24,
1482
1728
  className,
1483
1729
  color = "#000000"
1484
1730
  }) => {
@@ -1491,11 +1737,12 @@ var TranslatedIcon = ({
1491
1737
  className,
1492
1738
  xmlns: "http://www.w3.org/2000/svg",
1493
1739
  "aria-hidden": "true",
1740
+ style: { marginRight: "10px", flexShrink: 0 },
1494
1741
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1495
1742
  "path",
1496
1743
  {
1497
1744
  fill: color,
1498
- d: "M12.87,15.07l-2.54,-2.51 0.03,-0.03c1.74,-1.94 2.98,-4.17 3.71,-6.53L17,6L17,4h-7L10,2L8,2v2L1,4v1.99h11.17C11.5,7.92 10.44,9.75 9,11.35 8.07,10.32 7.3,9.19 6.69,8h-2c0.73,1.63 1.73,3.17 2.98,4.56l-5.09,5.02L4,19l5,-5 3.11,3.11 0.76,-2.04zM18.5,10h-2L12,22h2l1.12,-3h4.75L21,22h2l-4.5,-12zM15.88,17l1.62,-4.33L19.12,17h-3.24z"
1745
+ d: "M11.99 2C6.47 2 2 6.48 2 12C2 17.52 6.47 22 11.99 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 11.99 2ZM18.92 8H15.97C15.65 6.75 15.19 5.55 14.59 4.44C16.43 5.07 17.96 6.35 18.92 8ZM12 4.04C12.83 5.24 13.48 6.57 13.91 8H10.09C10.52 6.57 11.17 5.24 12 4.04ZM4.26 14C4.1 13.36 4 12.69 4 12C4 11.31 4.1 10.64 4.26 10H7.64C7.56 10.66 7.5 11.32 7.5 12C7.5 12.68 7.56 13.34 7.64 14H4.26ZM5.08 16H8.03C8.35 17.25 8.81 18.45 9.41 19.56C7.57 18.93 6.04 17.66 5.08 16ZM8.03 8H5.08C6.04 6.34 7.57 5.07 9.41 4.44C8.81 5.55 8.35 6.75 8.03 8ZM12 19.96C11.17 18.76 10.52 17.43 10.09 16H13.91C13.48 17.43 12.83 18.76 12 19.96ZM14.34 14H9.66C9.57 13.34 9.5 12.68 9.5 12C9.5 11.32 9.57 10.65 9.66 10H14.34C14.43 10.65 14.5 11.32 14.5 12C14.5 12.68 14.43 13.34 14.34 14ZM14.59 19.56C15.19 18.45 15.65 17.25 15.97 16H18.92C17.96 17.65 16.43 18.93 14.59 19.56ZM16.36 14C16.44 13.34 16.5 12.68 16.5 12C16.5 11.32 16.44 10.66 16.36 10H19.74C19.9 10.64 20 11.31 20 12C20 12.69 19.9 13.36 19.74 14H16.36Z"
1499
1746
  }
1500
1747
  )
1501
1748
  }
@@ -1510,11 +1757,11 @@ var AITranslateText = ({
1510
1757
  showHighlight = false,
1511
1758
  translatedIconProps
1512
1759
  }) => {
1513
- const context = (0, import_react4.useContext)(AITranslationContext);
1514
- const [displayText, setDisplayText] = (0, import_react4.useState)(text ?? "");
1515
- const [showHighlightState, setShowHighlightState] = (0, import_react4.useState)(showHighlight);
1516
- const eventHandlerRef = (0, import_react4.useRef)(null);
1517
- (0, import_react4.useEffect)(() => {
1760
+ const context = (0, import_react5.useContext)(AITranslationContext);
1761
+ const [displayText, setDisplayText] = (0, import_react5.useState)(text ?? "");
1762
+ const [showHighlightState, setShowHighlightState] = (0, import_react5.useState)(showHighlight);
1763
+ const eventHandlerRef = (0, import_react5.useRef)(null);
1764
+ (0, import_react5.useEffect)(() => {
1518
1765
  if (!context) return;
1519
1766
  if (!eventHandlerRef.current) {
1520
1767
  eventHandlerRef.current = new EventHandler(context.tool);
@@ -1533,14 +1780,14 @@ var AITranslateText = ({
1533
1780
  );
1534
1781
  return () => unsubscribe();
1535
1782
  }, [context, text, showHighlight]);
1536
- const reset = (0, import_react4.useCallback)(
1783
+ const reset = (0, import_react5.useCallback)(
1537
1784
  (displayValue = text) => {
1538
1785
  setDisplayText(displayValue);
1539
1786
  setShowHighlightState(false);
1540
1787
  },
1541
1788
  [text]
1542
1789
  );
1543
- (0, import_react4.useEffect)(() => {
1790
+ (0, import_react5.useEffect)(() => {
1544
1791
  if (text == null || text === "") {
1545
1792
  reset(text ?? "");
1546
1793
  return;
@@ -1567,8 +1814,8 @@ var AITranslateText = ({
1567
1814
  };
1568
1815
  }, [text, shouldTranslate, context, showHighlight, reset]);
1569
1816
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1570
- displayText,
1571
- showHighlightState && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TranslatedIcon, { ...translatedIconProps })
1817
+ showHighlightState && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TranslatedIcon, { ...translatedIconProps }),
1818
+ displayText
1572
1819
  ] });
1573
1820
  };
1574
1821
 
@@ -1592,10 +1839,16 @@ var getAITranslationLDId = (domain) => {
1592
1839
  };
1593
1840
  // Annotate the CommonJS export names for ESM import in node:
1594
1841
  0 && (module.exports = {
1842
+ ACTION,
1595
1843
  AITranslateText,
1596
1844
  AITranslationProvider,
1597
1845
  AI_TRANSLATION_FEATURE_FLAG_KEY,
1846
+ BUTTON_TYPE,
1847
+ buildAnalyticEvent,
1848
+ buildEventKey,
1849
+ buildObject,
1598
1850
  getAITranslationLDId,
1851
+ useAIAnalytics,
1599
1852
  useAITranslation,
1600
1853
  useConfig
1601
1854
  });