@procore/ai-translations 0.4.0 → 0.6.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/dist/legacy/index.d.mts +3 -2
- package/dist/legacy/index.d.ts +3 -2
- package/dist/legacy/index.js +238 -95
- package/dist/legacy/index.mjs +238 -95
- package/dist/modern/index.d.mts +3 -2
- package/dist/modern/index.d.ts +3 -2
- package/dist/modern/index.js +237 -93
- package/dist/modern/index.mjs +237 -93
- package/package.json +1 -1
package/dist/legacy/index.d.mts
CHANGED
|
@@ -17,6 +17,7 @@ interface TranslationProgress {
|
|
|
17
17
|
total: number;
|
|
18
18
|
}
|
|
19
19
|
interface TranslationQueueEntry {
|
|
20
|
+
id: string;
|
|
20
21
|
originalText: string;
|
|
21
22
|
isTranslated: boolean;
|
|
22
23
|
targetLanguage: string;
|
|
@@ -170,8 +171,8 @@ declare const AI_TRANSLATION_FEATURE_FLAG_KEY = "ai-translation";
|
|
|
170
171
|
declare const getAITranslationLDId: (domain: string) => "67e17b925ace3c08088c4bd2" | "570f2f6e348a2806d7006b6f" | "570e9423348a2806d7004354" | "570f37b4eee8b907140070c5";
|
|
171
172
|
|
|
172
173
|
declare global {
|
|
173
|
-
var __AI_TRANSLATION_FRONTEND_QUEUE__:
|
|
174
|
-
var __AI_TRANSLATION_BACKEND_QUEUE__:
|
|
174
|
+
var __AI_TRANSLATION_FRONTEND_QUEUE__: Map<string, TranslationQueueEntry> | undefined;
|
|
175
|
+
var __AI_TRANSLATION_BACKEND_QUEUE__: Map<string, TranslationQueueEntry> | undefined;
|
|
175
176
|
var _FRONTEND_AI_TRANSLATION_IN_PROGRESS_: boolean;
|
|
176
177
|
var _BACKEND_AI_TRANSLATION_IN_PROGRESS_: boolean;
|
|
177
178
|
}
|
package/dist/legacy/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ interface TranslationProgress {
|
|
|
17
17
|
total: number;
|
|
18
18
|
}
|
|
19
19
|
interface TranslationQueueEntry {
|
|
20
|
+
id: string;
|
|
20
21
|
originalText: string;
|
|
21
22
|
isTranslated: boolean;
|
|
22
23
|
targetLanguage: string;
|
|
@@ -170,8 +171,8 @@ declare const AI_TRANSLATION_FEATURE_FLAG_KEY = "ai-translation";
|
|
|
170
171
|
declare const getAITranslationLDId: (domain: string) => "67e17b925ace3c08088c4bd2" | "570f2f6e348a2806d7006b6f" | "570e9423348a2806d7004354" | "570f37b4eee8b907140070c5";
|
|
171
172
|
|
|
172
173
|
declare global {
|
|
173
|
-
var __AI_TRANSLATION_FRONTEND_QUEUE__:
|
|
174
|
-
var __AI_TRANSLATION_BACKEND_QUEUE__:
|
|
174
|
+
var __AI_TRANSLATION_FRONTEND_QUEUE__: Map<string, TranslationQueueEntry> | undefined;
|
|
175
|
+
var __AI_TRANSLATION_BACKEND_QUEUE__: Map<string, TranslationQueueEntry> | undefined;
|
|
175
176
|
var _FRONTEND_AI_TRANSLATION_IN_PROGRESS_: boolean;
|
|
176
177
|
var _BACKEND_AI_TRANSLATION_IN_PROGRESS_: boolean;
|
|
177
178
|
}
|
package/dist/legacy/index.js
CHANGED
|
@@ -81,6 +81,9 @@ var Config = class _Config {
|
|
|
81
81
|
setToolName(name) {
|
|
82
82
|
this.toolName = name;
|
|
83
83
|
}
|
|
84
|
+
isBackendTranslationStrategy() {
|
|
85
|
+
return this.ToolConfig.strategy === "backend_translations";
|
|
86
|
+
}
|
|
84
87
|
getToolName() {
|
|
85
88
|
return this.toolName;
|
|
86
89
|
}
|
|
@@ -268,10 +271,10 @@ var Hash = class {
|
|
|
268
271
|
var QueueManager = class {
|
|
269
272
|
constructor() {
|
|
270
273
|
if (!globalThis.__AI_TRANSLATION_FRONTEND_QUEUE__) {
|
|
271
|
-
globalThis.__AI_TRANSLATION_FRONTEND_QUEUE__ = /* @__PURE__ */ new
|
|
274
|
+
globalThis.__AI_TRANSLATION_FRONTEND_QUEUE__ = /* @__PURE__ */ new Map();
|
|
272
275
|
}
|
|
273
276
|
if (!globalThis.__AI_TRANSLATION_BACKEND_QUEUE__) {
|
|
274
|
-
globalThis.__AI_TRANSLATION_BACKEND_QUEUE__ = /* @__PURE__ */ new
|
|
277
|
+
globalThis.__AI_TRANSLATION_BACKEND_QUEUE__ = /* @__PURE__ */ new Map();
|
|
275
278
|
}
|
|
276
279
|
}
|
|
277
280
|
getQueue(strategy) {
|
|
@@ -284,42 +287,20 @@ var QueueManager = class {
|
|
|
284
287
|
return void 0;
|
|
285
288
|
}
|
|
286
289
|
add(entry) {
|
|
287
|
-
|
|
288
|
-
(
|
|
289
|
-
|
|
290
|
-
*generateBatches(strategy, config2) {
|
|
291
|
-
const queue = this.getQueue(strategy);
|
|
292
|
-
if (!queue) {
|
|
293
|
-
throw new Error("Invalid translation strategy");
|
|
294
|
-
}
|
|
295
|
-
if (queue.size === 0) {
|
|
296
|
-
console.warn("No translations to process");
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
const batch = config2.getToolConfig().translationBatchSize;
|
|
300
|
-
let batches = [];
|
|
301
|
-
for (const entry of queue.values()) {
|
|
302
|
-
batches.push(entry);
|
|
303
|
-
if (batches.length >= batch) {
|
|
304
|
-
yield batches;
|
|
305
|
-
batches = [];
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
if (batches.length > 0) {
|
|
309
|
-
queue.clear();
|
|
310
|
-
yield batches;
|
|
311
|
-
}
|
|
290
|
+
const queue = this.getQueue(entry.translationStrategy);
|
|
291
|
+
if (!queue || queue.has(entry.id)) return;
|
|
292
|
+
queue.set(entry.id, entry);
|
|
312
293
|
}
|
|
313
|
-
*
|
|
294
|
+
*generateBatches(config2) {
|
|
314
295
|
const queue = this.getQueue(config2.getToolConfig().strategy);
|
|
315
296
|
if (!queue) throw new Error("Invalid translation strategy");
|
|
316
297
|
const batchSize = config2.getToolConfig().translationBatchSize;
|
|
317
298
|
while (queue.size > 0) {
|
|
318
299
|
const batch = [];
|
|
319
300
|
while (batch.length < batchSize && queue.size > 0) {
|
|
320
|
-
const
|
|
321
|
-
queue.delete(
|
|
322
|
-
batch.push(
|
|
301
|
+
const [key, entry] = queue.entries().next().value;
|
|
302
|
+
queue.delete(key);
|
|
303
|
+
batch.push(entry);
|
|
323
304
|
}
|
|
324
305
|
yield batch;
|
|
325
306
|
}
|
|
@@ -438,6 +419,19 @@ var _Storage = class _Storage {
|
|
|
438
419
|
}
|
|
439
420
|
}
|
|
440
421
|
// ------------------------------------
|
|
422
|
+
// 🗑️ Clear Translation by ID
|
|
423
|
+
// ------------------------------------
|
|
424
|
+
static async deleteById(id) {
|
|
425
|
+
try {
|
|
426
|
+
const db = await _Storage.getDB();
|
|
427
|
+
await db.delete(_Storage.STORE_NAME, id);
|
|
428
|
+
return true;
|
|
429
|
+
} catch (error) {
|
|
430
|
+
console.error("[Storage] Failed to delete by id:", error);
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// ------------------------------------
|
|
441
435
|
// 🗑️ Clear All Translations
|
|
442
436
|
// ------------------------------------
|
|
443
437
|
static async clearAll() {
|
|
@@ -512,10 +506,42 @@ var _TranslationRegistry = class _TranslationRegistry {
|
|
|
512
506
|
isNonRetryable(key) {
|
|
513
507
|
return _TranslationRegistry.nonRetryableTexts.has(key);
|
|
514
508
|
}
|
|
515
|
-
|
|
509
|
+
enqueue(enqueuedKey) {
|
|
510
|
+
_TranslationRegistry.enqueuedItems.add(enqueuedKey);
|
|
511
|
+
}
|
|
512
|
+
isEnqueued(enqueuedKey) {
|
|
513
|
+
return _TranslationRegistry.enqueuedItems.has(enqueuedKey);
|
|
514
|
+
}
|
|
515
|
+
clearEnqueued() {
|
|
516
|
+
_TranslationRegistry.enqueuedItems.clear();
|
|
517
|
+
}
|
|
518
|
+
async removeTextsFromEnqueued(texts, targetLanguage, strategy) {
|
|
519
|
+
for (const text of texts) {
|
|
520
|
+
const id = await Storage.generateId(text, targetLanguage, this.tool);
|
|
521
|
+
_TranslationRegistry.enqueuedItems.delete(
|
|
522
|
+
this.generateEnqueuedKey(id, strategy)
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
static removeFromEnqueued(key) {
|
|
527
|
+
_TranslationRegistry.enqueuedItems.delete(key);
|
|
528
|
+
}
|
|
529
|
+
generateEnqueuedKey(id, strategy) {
|
|
530
|
+
return `${id}:${strategy}`;
|
|
531
|
+
}
|
|
532
|
+
async get(text, targetLanguage, tool, config2) {
|
|
516
533
|
const key = await Hash.generateFromMultiple([text, targetLanguage, tool]);
|
|
517
|
-
|
|
518
|
-
|
|
534
|
+
const cached = _TranslationRegistry.memoryCache.get(key);
|
|
535
|
+
if (cached) {
|
|
536
|
+
if (cached.translationStrategy === "frontend_translations" && config2.isBackendTranslationStrategy()) {
|
|
537
|
+
_TranslationRegistry.memoryCache.delete(key);
|
|
538
|
+
if (cached.translatedText) {
|
|
539
|
+
_TranslationRegistry.originalTextIndex.delete(cached.translatedText);
|
|
540
|
+
}
|
|
541
|
+
await Storage.deleteById(key);
|
|
542
|
+
return void 0;
|
|
543
|
+
}
|
|
544
|
+
return cached;
|
|
519
545
|
}
|
|
520
546
|
const translation = await Storage.getTranslation(
|
|
521
547
|
text,
|
|
@@ -523,6 +549,10 @@ var _TranslationRegistry = class _TranslationRegistry {
|
|
|
523
549
|
tool
|
|
524
550
|
);
|
|
525
551
|
if (translation !== void 0) {
|
|
552
|
+
if (translation.translation_strategy === "frontend_translations" && config2.isBackendTranslationStrategy()) {
|
|
553
|
+
await Storage.deleteById(translation.id);
|
|
554
|
+
return void 0;
|
|
555
|
+
}
|
|
526
556
|
return this.toTranslationRegistryEntry(translation);
|
|
527
557
|
}
|
|
528
558
|
return void 0;
|
|
@@ -537,6 +567,7 @@ var _TranslationRegistry = class _TranslationRegistry {
|
|
|
537
567
|
async clear() {
|
|
538
568
|
_TranslationRegistry.memoryCache.clear();
|
|
539
569
|
_TranslationRegistry.originalTextIndex.clear();
|
|
570
|
+
_TranslationRegistry.enqueuedItems.clear();
|
|
540
571
|
await Storage.clearAll();
|
|
541
572
|
return;
|
|
542
573
|
}
|
|
@@ -544,6 +575,7 @@ var _TranslationRegistry = class _TranslationRegistry {
|
|
|
544
575
|
await Storage.deleteByToolAndStrategy(tool, strategy);
|
|
545
576
|
_TranslationRegistry.memoryCache.clear();
|
|
546
577
|
_TranslationRegistry.originalTextIndex.clear();
|
|
578
|
+
_TranslationRegistry.enqueuedItems.clear();
|
|
547
579
|
return;
|
|
548
580
|
}
|
|
549
581
|
toTranslationRegistryEntry(translation) {
|
|
@@ -565,10 +597,16 @@ var _TranslationRegistry = class _TranslationRegistry {
|
|
|
565
597
|
translation.id
|
|
566
598
|
);
|
|
567
599
|
const newTranslation = this.toTranslationRegistryEntry(translation);
|
|
600
|
+
const enqueuedKey = this.generateEnqueuedKey(
|
|
601
|
+
translation.id,
|
|
602
|
+
translation.translation_strategy
|
|
603
|
+
);
|
|
568
604
|
if (currentTranslation && !this.shouldUpdateTranslation(currentTranslation, newTranslation)) {
|
|
605
|
+
_TranslationRegistry.removeFromEnqueued(enqueuedKey);
|
|
569
606
|
continue;
|
|
570
607
|
}
|
|
571
608
|
this.setTranslationToRegistry(newTranslation);
|
|
609
|
+
_TranslationRegistry.removeFromEnqueued(enqueuedKey);
|
|
572
610
|
}
|
|
573
611
|
return;
|
|
574
612
|
}
|
|
@@ -611,6 +649,7 @@ var _TranslationRegistry = class _TranslationRegistry {
|
|
|
611
649
|
__publicField(_TranslationRegistry, "memoryCache", /* @__PURE__ */ new Map());
|
|
612
650
|
__publicField(_TranslationRegistry, "originalTextIndex", /* @__PURE__ */ new Map());
|
|
613
651
|
__publicField(_TranslationRegistry, "nonRetryableTexts", /* @__PURE__ */ new Set());
|
|
652
|
+
__publicField(_TranslationRegistry, "enqueuedItems", /* @__PURE__ */ new Set());
|
|
614
653
|
var TranslationRegistry = _TranslationRegistry;
|
|
615
654
|
|
|
616
655
|
// src/utils/eventHandler.ts
|
|
@@ -631,12 +670,13 @@ var EventHandler = class {
|
|
|
631
670
|
this.aiTranslationEvents = new import_web_sdk_events.SystemEvents(this.sourceEventIdentifier);
|
|
632
671
|
this.toolName = toolName;
|
|
633
672
|
}
|
|
634
|
-
publishTranslationCompleteEvent(sourceTranslatedTexts, nonRetryableTexts) {
|
|
673
|
+
publishTranslationCompleteEvent(sourceTranslatedTexts, nonRetryableTexts, retryableFailedTexts = []) {
|
|
635
674
|
this.aiTranslationEvents.publish(
|
|
636
675
|
this.withEventName(TRANSLATION_COMPLETE_EVENT_NAME),
|
|
637
676
|
{
|
|
638
677
|
sourceTranslatedTexts,
|
|
639
|
-
nonRetryableTexts
|
|
678
|
+
nonRetryableTexts,
|
|
679
|
+
retryableFailedTexts
|
|
640
680
|
}
|
|
641
681
|
);
|
|
642
682
|
}
|
|
@@ -644,12 +684,19 @@ var EventHandler = class {
|
|
|
644
684
|
return this.aiTranslationEvents.subscribe(
|
|
645
685
|
this.withEventName(TRANSLATION_COMPLETE_EVENT_NAME),
|
|
646
686
|
(detail) => {
|
|
647
|
-
var _a, _b;
|
|
687
|
+
var _a, _b, _c;
|
|
648
688
|
const sourceTranslatedTexts = Array.isArray(
|
|
649
689
|
(_a = detail.data) == null ? void 0 : _a.sourceTranslatedTexts
|
|
650
690
|
) ? detail.data.sourceTranslatedTexts : [];
|
|
651
691
|
const nonRetryableTexts = Array.isArray((_b = detail.data) == null ? void 0 : _b.nonRetryableTexts) ? detail.data.nonRetryableTexts : [];
|
|
652
|
-
|
|
692
|
+
const retryableFailedTexts = Array.isArray(
|
|
693
|
+
(_c = detail.data) == null ? void 0 : _c.retryableFailedTexts
|
|
694
|
+
) ? detail.data.retryableFailedTexts : [];
|
|
695
|
+
callback(
|
|
696
|
+
sourceTranslatedTexts,
|
|
697
|
+
nonRetryableTexts,
|
|
698
|
+
retryableFailedTexts
|
|
699
|
+
);
|
|
653
700
|
}
|
|
654
701
|
);
|
|
655
702
|
}
|
|
@@ -750,6 +797,7 @@ var TranslationManager = class {
|
|
|
750
797
|
__publicField(this, "currentTranslatorStrategy");
|
|
751
798
|
__publicField(this, "sourceTexts", /* @__PURE__ */ new Map());
|
|
752
799
|
__publicField(this, "nonRetryableTexts", /* @__PURE__ */ new Set());
|
|
800
|
+
__publicField(this, "retryableFailedTexts", /* @__PURE__ */ new Map());
|
|
753
801
|
__publicField(this, "progressEventHandler");
|
|
754
802
|
__publicField(this, "translationProgress", {
|
|
755
803
|
progress: 0,
|
|
@@ -777,19 +825,21 @@ var TranslationManager = class {
|
|
|
777
825
|
this.translationProgress.total = queueManager.queueSize(
|
|
778
826
|
this.currentTranslatorStrategy
|
|
779
827
|
);
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
828
|
+
do {
|
|
829
|
+
for (const batch of queueManager.generateBatches(
|
|
830
|
+
this.translator.getConfig()
|
|
831
|
+
)) {
|
|
832
|
+
batch.forEach((entry) => this.mfeToBeNotified.add(entry.tool));
|
|
833
|
+
const result = await this.translator.processTranslations(
|
|
834
|
+
batch.map(
|
|
835
|
+
(entry) => this.convertTranslationQueueEntryToTranslationRequest(entry)
|
|
836
|
+
)
|
|
837
|
+
);
|
|
838
|
+
this.setTranslationProgress(batch.length);
|
|
839
|
+
await this.updateDatabaseWithTranslations(result);
|
|
840
|
+
await this.notifyTranslationCompleted();
|
|
841
|
+
}
|
|
842
|
+
} while (queueManager.queueSize(this.currentTranslatorStrategy) > 0);
|
|
793
843
|
this.resetTranslationProgress();
|
|
794
844
|
this.publishTranslationProgress();
|
|
795
845
|
if (this.currentTranslatorStrategy === "frontend_translations") {
|
|
@@ -808,6 +858,7 @@ var TranslationManager = class {
|
|
|
808
858
|
continue;
|
|
809
859
|
}
|
|
810
860
|
if (!translation.isTranslated) {
|
|
861
|
+
this.addRetryableFailedText(response.tool, translation.sourceText);
|
|
811
862
|
continue;
|
|
812
863
|
}
|
|
813
864
|
this.addSourceTextToMap(response.tool, translation.sourceText);
|
|
@@ -827,12 +878,14 @@ var TranslationManager = class {
|
|
|
827
878
|
const eventhandler = new EventHandler(mfe);
|
|
828
879
|
eventhandler.publishTranslationCompleteEvent(
|
|
829
880
|
Array.from(this.sourceTexts.get(mfe) ?? /* @__PURE__ */ new Set()),
|
|
830
|
-
Array.from(this.nonRetryableTexts)
|
|
881
|
+
Array.from(this.nonRetryableTexts),
|
|
882
|
+
Array.from(this.retryableFailedTexts.get(mfe) ?? /* @__PURE__ */ new Set())
|
|
831
883
|
);
|
|
832
884
|
}
|
|
833
885
|
this.mfeToBeNotified.clear();
|
|
834
886
|
this.sourceTexts.clear();
|
|
835
887
|
this.nonRetryableTexts.clear();
|
|
888
|
+
this.retryableFailedTexts.clear();
|
|
836
889
|
}
|
|
837
890
|
setTranslationProgress(batchSize) {
|
|
838
891
|
this.translationProgress.current += batchSize;
|
|
@@ -869,6 +922,11 @@ var TranslationManager = class {
|
|
|
869
922
|
existing.add(sourceText);
|
|
870
923
|
this.sourceTexts.set(tool, existing);
|
|
871
924
|
}
|
|
925
|
+
addRetryableFailedText(tool, sourceText) {
|
|
926
|
+
const existing = this.retryableFailedTexts.get(tool) ?? /* @__PURE__ */ new Set();
|
|
927
|
+
existing.add(sourceText);
|
|
928
|
+
this.retryableFailedTexts.set(tool, existing);
|
|
929
|
+
}
|
|
872
930
|
publishTranslationProgress() {
|
|
873
931
|
this.progressEventHandler.publishTranslationProgressEvent(
|
|
874
932
|
this.translationProgress.progress,
|
|
@@ -935,8 +993,16 @@ var Client = class {
|
|
|
935
993
|
method: "POST",
|
|
936
994
|
body: JSON.stringify(requests)
|
|
937
995
|
});
|
|
996
|
+
const responseBody = Array.isArray(data) ? data.map((group) => ({
|
|
997
|
+
...group,
|
|
998
|
+
translations: Array.isArray(group.translations) ? group.translations.map((t) => ({
|
|
999
|
+
...t,
|
|
1000
|
+
isTranslated: t.isTranslated ?? (!!t.translation && t.translation !== ""),
|
|
1001
|
+
retryable: t.retryable ?? true
|
|
1002
|
+
})) : []
|
|
1003
|
+
})) : data;
|
|
938
1004
|
return {
|
|
939
|
-
responseBody
|
|
1005
|
+
responseBody,
|
|
940
1006
|
success: true
|
|
941
1007
|
};
|
|
942
1008
|
} catch (error) {
|
|
@@ -1014,11 +1080,54 @@ var getModelDownloadEventHandler = () => {
|
|
|
1014
1080
|
}
|
|
1015
1081
|
return _modelDownloadEventHandler;
|
|
1016
1082
|
};
|
|
1083
|
+
var SUPPORTED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
1084
|
+
"ar",
|
|
1085
|
+
"bn",
|
|
1086
|
+
"bg",
|
|
1087
|
+
"zh",
|
|
1088
|
+
"hr",
|
|
1089
|
+
"cs",
|
|
1090
|
+
"da",
|
|
1091
|
+
"nl",
|
|
1092
|
+
"en",
|
|
1093
|
+
"fi",
|
|
1094
|
+
"fr",
|
|
1095
|
+
"de",
|
|
1096
|
+
"el",
|
|
1097
|
+
"he",
|
|
1098
|
+
"hi",
|
|
1099
|
+
"hu",
|
|
1100
|
+
"id",
|
|
1101
|
+
"it",
|
|
1102
|
+
"ja",
|
|
1103
|
+
"kn",
|
|
1104
|
+
"ko",
|
|
1105
|
+
"lt",
|
|
1106
|
+
"mr",
|
|
1107
|
+
"no",
|
|
1108
|
+
"pl",
|
|
1109
|
+
"pt",
|
|
1110
|
+
"ro",
|
|
1111
|
+
"ru",
|
|
1112
|
+
"sk",
|
|
1113
|
+
"sl",
|
|
1114
|
+
"es",
|
|
1115
|
+
"sv",
|
|
1116
|
+
"ta",
|
|
1117
|
+
"te",
|
|
1118
|
+
"th",
|
|
1119
|
+
"tr",
|
|
1120
|
+
"uk",
|
|
1121
|
+
"vi"
|
|
1122
|
+
]);
|
|
1017
1123
|
var _ChromeTranslator = class _ChromeTranslator {
|
|
1018
1124
|
constructor(translator) {
|
|
1019
1125
|
__publicField(this, "translator");
|
|
1020
1126
|
this.translator = translator;
|
|
1021
1127
|
}
|
|
1128
|
+
static isSupportedLanguage(lang) {
|
|
1129
|
+
return SUPPORTED_LANGUAGES.has(lang) || SUPPORTED_LANGUAGES.has(lang.split("-")[0] ?? "");
|
|
1130
|
+
}
|
|
1022
1131
|
static ensureRegistry() {
|
|
1023
1132
|
if (!globalThis.chromeTranslatorRegistry) {
|
|
1024
1133
|
globalThis.chromeTranslatorRegistry = /* @__PURE__ */ new Map();
|
|
@@ -1040,30 +1149,31 @@ var _ChromeTranslator = class _ChromeTranslator {
|
|
|
1040
1149
|
);
|
|
1041
1150
|
}
|
|
1042
1151
|
static async createTranslator(source, target) {
|
|
1152
|
+
const key = this.generateKey(source, target);
|
|
1043
1153
|
let resolveReady;
|
|
1044
|
-
|
|
1154
|
+
const readyPromise = new Promise((resolve) => {
|
|
1045
1155
|
resolveReady = resolve;
|
|
1046
1156
|
});
|
|
1157
|
+
this.translatorReadyPromises.set(key, readyPromise);
|
|
1047
1158
|
let isDownloading = false;
|
|
1048
1159
|
const translator = await Translator.create({
|
|
1049
1160
|
sourceLanguage: source,
|
|
1050
1161
|
targetLanguage: target,
|
|
1051
1162
|
monitor(m) {
|
|
1052
|
-
m.addEventListener(
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
}
|
|
1163
|
+
m.addEventListener("downloadprogress", (e) => {
|
|
1164
|
+
isDownloading = true;
|
|
1165
|
+
const loaded = e.loaded ?? 0;
|
|
1166
|
+
const total = e.total ?? 0;
|
|
1167
|
+
const progress = total > 0 ? Math.round(loaded / total * 100) : 0;
|
|
1168
|
+
getModelDownloadEventHandler().publishModelDownloadProgressEvent(
|
|
1169
|
+
loaded,
|
|
1170
|
+
total,
|
|
1171
|
+
progress
|
|
1172
|
+
);
|
|
1173
|
+
if (total > 0 && loaded >= total) {
|
|
1174
|
+
resolveReady();
|
|
1065
1175
|
}
|
|
1066
|
-
);
|
|
1176
|
+
});
|
|
1067
1177
|
}
|
|
1068
1178
|
});
|
|
1069
1179
|
if (!isDownloading) {
|
|
@@ -1071,8 +1181,8 @@ var _ChromeTranslator = class _ChromeTranslator {
|
|
|
1071
1181
|
}
|
|
1072
1182
|
return translator;
|
|
1073
1183
|
}
|
|
1074
|
-
static waitForReady() {
|
|
1075
|
-
return this.
|
|
1184
|
+
static waitForReady(key) {
|
|
1185
|
+
return this.translatorReadyPromises.get(key) ?? Promise.resolve();
|
|
1076
1186
|
}
|
|
1077
1187
|
static async translate(text, targetLanguage) {
|
|
1078
1188
|
var _a;
|
|
@@ -1081,8 +1191,17 @@ var _ChromeTranslator = class _ChromeTranslator {
|
|
|
1081
1191
|
const detector = await ChromeLanguageDetector.getInstance();
|
|
1082
1192
|
const sourceLanguage = await detector.detectLanguage(text);
|
|
1083
1193
|
const key = this.generateKey(sourceLanguage, targetLanguage);
|
|
1084
|
-
|
|
1085
|
-
|
|
1194
|
+
if (!this.isSupportedLanguage(sourceLanguage) || !this.isSupportedLanguage(targetLanguage)) {
|
|
1195
|
+
return {
|
|
1196
|
+
translation: text,
|
|
1197
|
+
sourceLanguage,
|
|
1198
|
+
success: false,
|
|
1199
|
+
retryable: false,
|
|
1200
|
+
errorMessage: `Unsupported language pair: ${sourceLanguage} \u2192 ${targetLanguage}`
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
const existingInstance = globalThis.chromeTranslatorRegistry.get(key);
|
|
1204
|
+
if (!existingInstance) {
|
|
1086
1205
|
const translatorCapabilities = await Translator.availability({
|
|
1087
1206
|
sourceLanguage,
|
|
1088
1207
|
targetLanguage
|
|
@@ -1100,10 +1219,16 @@ var _ChromeTranslator = class _ChromeTranslator {
|
|
|
1100
1219
|
sourceLanguage,
|
|
1101
1220
|
targetLanguage
|
|
1102
1221
|
);
|
|
1103
|
-
|
|
1104
|
-
|
|
1222
|
+
if (!globalThis.chromeTranslatorRegistry.has(key)) {
|
|
1223
|
+
globalThis.chromeTranslatorRegistry.set(
|
|
1224
|
+
key,
|
|
1225
|
+
new _ChromeTranslator(chromeTranslator)
|
|
1226
|
+
);
|
|
1227
|
+
}
|
|
1105
1228
|
}
|
|
1106
|
-
|
|
1229
|
+
const instance = globalThis.chromeTranslatorRegistry.get(key);
|
|
1230
|
+
await this.waitForReady(key);
|
|
1231
|
+
this.translatorReadyPromises.delete(key);
|
|
1107
1232
|
const translation = await ((_a = instance.translator) == null ? void 0 : _a.translate(text));
|
|
1108
1233
|
if (!translation) {
|
|
1109
1234
|
return {
|
|
@@ -1111,7 +1236,7 @@ var _ChromeTranslator = class _ChromeTranslator {
|
|
|
1111
1236
|
sourceLanguage,
|
|
1112
1237
|
success: false,
|
|
1113
1238
|
errorMessage: "Translation failed",
|
|
1114
|
-
retryable:
|
|
1239
|
+
retryable: false
|
|
1115
1240
|
};
|
|
1116
1241
|
}
|
|
1117
1242
|
return {
|
|
@@ -1121,11 +1246,12 @@ var _ChromeTranslator = class _ChromeTranslator {
|
|
|
1121
1246
|
retryable: true
|
|
1122
1247
|
};
|
|
1123
1248
|
} catch (error) {
|
|
1249
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1124
1250
|
return {
|
|
1125
1251
|
translation: text,
|
|
1126
1252
|
sourceLanguage: targetLanguage,
|
|
1127
1253
|
success: false,
|
|
1128
|
-
errorMessage:
|
|
1254
|
+
errorMessage: message,
|
|
1129
1255
|
retryable: true
|
|
1130
1256
|
};
|
|
1131
1257
|
}
|
|
@@ -1134,7 +1260,7 @@ var _ChromeTranslator = class _ChromeTranslator {
|
|
|
1134
1260
|
return `${sourceLanguage.toUpperCase()}-${targetLanguage.toUpperCase()}`;
|
|
1135
1261
|
}
|
|
1136
1262
|
};
|
|
1137
|
-
__publicField(_ChromeTranslator, "
|
|
1263
|
+
__publicField(_ChromeTranslator, "translatorReadyPromises", /* @__PURE__ */ new Map());
|
|
1138
1264
|
var ChromeTranslator = _ChromeTranslator;
|
|
1139
1265
|
|
|
1140
1266
|
// src/translators/frontend_translators/chrome/client.ts
|
|
@@ -1284,13 +1410,22 @@ var aitFunction = async (text, translationRegistry, config2, tool) => {
|
|
|
1284
1410
|
const existingByOriginal = await translationRegistry.get(
|
|
1285
1411
|
text,
|
|
1286
1412
|
targetLanguage,
|
|
1287
|
-
tool
|
|
1413
|
+
tool,
|
|
1414
|
+
config2
|
|
1288
1415
|
);
|
|
1289
1416
|
if (existingByOriginal && existingByOriginal.isTranslated && existingByOriginal.translatedText && existingByOriginal.translatedText.trim() !== "") {
|
|
1290
1417
|
return existingByOriginal.translatedText;
|
|
1291
1418
|
}
|
|
1292
1419
|
if (!existingByOriginal) {
|
|
1420
|
+
const id = await Storage.generateId(text, targetLanguage, tool);
|
|
1421
|
+
const strategy = config2.getToolConfig().strategy;
|
|
1422
|
+
const enqueuedKey = translationRegistry.generateEnqueuedKey(id, strategy);
|
|
1423
|
+
if (translationRegistry.isEnqueued(enqueuedKey)) {
|
|
1424
|
+
return text;
|
|
1425
|
+
}
|
|
1426
|
+
translationRegistry.enqueue(enqueuedKey);
|
|
1293
1427
|
queueManager.add({
|
|
1428
|
+
id,
|
|
1294
1429
|
originalText: text,
|
|
1295
1430
|
targetLanguage,
|
|
1296
1431
|
tool,
|
|
@@ -1354,12 +1489,17 @@ function AITranslationInnerProvider(props) {
|
|
|
1354
1489
|
});
|
|
1355
1490
|
(0, import_react.useEffect)(() => {
|
|
1356
1491
|
const unsubscribe = eventHandler.current.subscribeToTranslationCompleteEvent(
|
|
1357
|
-
async (sourceTranslatedTexts, nonRetryableTexts) => {
|
|
1492
|
+
async (sourceTranslatedTexts, nonRetryableTexts, retryableFailedTexts) => {
|
|
1358
1493
|
try {
|
|
1359
1494
|
await translationRegistry.current.populateRegistryFromDatabase();
|
|
1360
1495
|
translationRegistry.current.populateNonRetryableTexts(
|
|
1361
1496
|
nonRetryableTexts
|
|
1362
1497
|
);
|
|
1498
|
+
translationRegistry.current.removeTextsFromEnqueued(
|
|
1499
|
+
retryableFailedTexts,
|
|
1500
|
+
locale,
|
|
1501
|
+
config2.getToolConfig().strategy
|
|
1502
|
+
);
|
|
1363
1503
|
eventHandler.current.publishRerenderEvent(sourceTranslatedTexts);
|
|
1364
1504
|
} catch (error) {
|
|
1365
1505
|
console.error(
|
|
@@ -1370,7 +1510,7 @@ function AITranslationInnerProvider(props) {
|
|
|
1370
1510
|
}
|
|
1371
1511
|
);
|
|
1372
1512
|
return () => unsubscribe();
|
|
1373
|
-
}, []);
|
|
1513
|
+
}, [locale, config2]);
|
|
1374
1514
|
(0, import_react.useEffect)(() => {
|
|
1375
1515
|
const unsubscribe = eventHandler.current.subscribeToTranslationProgressEvent(
|
|
1376
1516
|
(progress, current, total) => {
|
|
@@ -1388,15 +1528,15 @@ function AITranslationInnerProvider(props) {
|
|
|
1388
1528
|
return () => unsubscribe();
|
|
1389
1529
|
}, []);
|
|
1390
1530
|
(0, import_react.useEffect)(() => {
|
|
1391
|
-
if (isFetched
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
}
|
|
1531
|
+
if (!isFetched || !remoteConfig) return;
|
|
1532
|
+
const toolConfig = remoteConfig[tool] ?? remoteConfig;
|
|
1533
|
+
setConfig((prevConfig) => {
|
|
1534
|
+
const clonedConfig = prevConfig.clone();
|
|
1535
|
+
clonedConfig.setTargetLanguage(locale);
|
|
1536
|
+
clonedConfig.setToolConfig(toolConfig);
|
|
1537
|
+
translator.current.updateConfig(clonedConfig);
|
|
1538
|
+
return clonedConfig;
|
|
1539
|
+
});
|
|
1400
1540
|
}, [tool, remoteConfig, isFetched, locale]);
|
|
1401
1541
|
config2.setTargetLanguage(locale);
|
|
1402
1542
|
config2.setToolName(tool);
|
|
@@ -1453,6 +1593,7 @@ var TranslatedIcon = ({
|
|
|
1453
1593
|
className,
|
|
1454
1594
|
xmlns: "http://www.w3.org/2000/svg",
|
|
1455
1595
|
"aria-hidden": "true",
|
|
1596
|
+
style: { marginRight: "10px", flexShrink: 0 },
|
|
1456
1597
|
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1457
1598
|
"path",
|
|
1458
1599
|
{
|
|
@@ -1487,12 +1628,14 @@ var AITranslateText = ({
|
|
|
1487
1628
|
return;
|
|
1488
1629
|
}
|
|
1489
1630
|
if (sourceTexts.includes(text)) {
|
|
1490
|
-
|
|
1631
|
+
const translatedText = await context.ait(text);
|
|
1632
|
+
setDisplayText(translatedText);
|
|
1633
|
+
setShowHighlightState(showHighlight && translatedText !== text);
|
|
1491
1634
|
}
|
|
1492
1635
|
}
|
|
1493
1636
|
);
|
|
1494
1637
|
return () => unsubscribe();
|
|
1495
|
-
}, [context, text]);
|
|
1638
|
+
}, [context, text, showHighlight]);
|
|
1496
1639
|
const reset = (0, import_react4.useCallback)(
|
|
1497
1640
|
(displayValue = text) => {
|
|
1498
1641
|
setDisplayText(displayValue);
|
|
@@ -1515,7 +1658,7 @@ var AITranslateText = ({
|
|
|
1515
1658
|
const translatedText = await context.ait(text);
|
|
1516
1659
|
if (cancelled) return;
|
|
1517
1660
|
setDisplayText(translatedText);
|
|
1518
|
-
setShowHighlightState(showHighlight);
|
|
1661
|
+
setShowHighlightState(showHighlight && translatedText !== text);
|
|
1519
1662
|
} catch {
|
|
1520
1663
|
if (cancelled) return;
|
|
1521
1664
|
reset();
|
|
@@ -1527,8 +1670,8 @@ var AITranslateText = ({
|
|
|
1527
1670
|
};
|
|
1528
1671
|
}, [text, shouldTranslate, context, showHighlight, reset]);
|
|
1529
1672
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1530
|
-
|
|
1531
|
-
|
|
1673
|
+
showHighlightState && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TranslatedIcon, { ...translatedIconProps }),
|
|
1674
|
+
displayText
|
|
1532
1675
|
] });
|
|
1533
1676
|
};
|
|
1534
1677
|
|