@nocobase/plugin-localization 2.1.0-beta.34 → 2.1.0-beta.35
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/ai/ai-employees/lina.js +11 -11
- package/dist/client/300.1f79b801d226f40d.js +10 -0
- package/dist/client/index.js +1 -1
- package/dist/client-v2/796.0ec484505de4b04a.js +10 -0
- package/dist/client-v2/index.js +1 -1
- package/dist/externalVersion.js +12 -11
- package/dist/locale/en-US.json +23 -0
- package/dist/locale/zh-CN.json +23 -0
- package/dist/server/actions/aiTranslate.js +45 -21
- package/dist/server/tasks/localization-ai-translate.d.ts +15 -7
- package/dist/server/tasks/localization-ai-translate.js +224 -255
- package/dist/server/translation-scope.d.ts +31 -0
- package/dist/server/translation-scope.js +107 -0
- package/package.json +2 -2
- package/dist/client/300.3a4b9b688d36da96.js +0 -10
- package/dist/client-v2/796.b9d793cda3c8b932.js +0 -10
|
@@ -32,16 +32,16 @@ __export(localization_ai_translate_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(localization_ai_translate_exports);
|
|
33
33
|
var import_plugin_async_task_manager = require("@nocobase/plugin-async-task-manager");
|
|
34
34
|
var import_messages = require("@langchain/core/messages");
|
|
35
|
+
var import_translation_scope = require("../translation-scope");
|
|
35
36
|
const LOCALIZATION_AI_TRANSLATE_TASK_TYPE = "localization:ai-translate";
|
|
36
|
-
const TRANSLATION_BATCH_SIZE = 10;
|
|
37
37
|
const DEFAULT_TRANSLATION_WORKER_COUNT = 10;
|
|
38
38
|
const MIN_TRANSLATION_WORKER_COUNT = 1;
|
|
39
39
|
const MAX_TRANSLATION_WORKER_COUNT = 20;
|
|
40
|
-
const
|
|
40
|
+
const TRANSLATION_CHUNK_SIZE = 200;
|
|
41
41
|
const elapsed = (start) => Date.now() - start;
|
|
42
|
-
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
43
42
|
const truncateForLog = (value, maxLength = 500) => value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
|
|
44
43
|
const LEGACY_SYMBOL_TRANSLATIONS = /* @__PURE__ */ new Set(["<", "=", ">"]);
|
|
44
|
+
const isString = (value) => typeof value === "string" && value.length > 0;
|
|
45
45
|
const getTranslationWorkerCount = () => {
|
|
46
46
|
const value = Number.parseInt(process.env.AI_LOCALIZATION_CONCURRENCY || "", 10);
|
|
47
47
|
if (Number.isInteger(value) && value >= MIN_TRANSLATION_WORKER_COUNT && value <= MAX_TRANSLATION_WORKER_COUNT) {
|
|
@@ -74,11 +74,21 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
74
74
|
const resolvedModel = await aiPlugin.aiEmployeesManager.resolveModel(employee, params.model);
|
|
75
75
|
const { provider, model, service } = await aiPlugin.aiManager.getLLMService(resolvedModel);
|
|
76
76
|
const defaultReferenceLocale = await this.getSystemDefaultLocale();
|
|
77
|
-
const builtInReferenceResources = await this.app.localeManager.getBuiltInResources("zh-CN");
|
|
78
77
|
const builtInMatchResources = await this.app.localeManager.getBuiltInResources("en-US");
|
|
78
|
+
const referenceLocales = this.resolveReferenceLocales(params.referenceLocales, defaultReferenceLocale);
|
|
79
|
+
const findTextsOptions = await (0, import_translation_scope.buildFindTextsOptions)({
|
|
80
|
+
app: this.app,
|
|
81
|
+
mode: params.mode,
|
|
82
|
+
locale,
|
|
83
|
+
scope: params.scope || "all",
|
|
84
|
+
textIds: params.textIds,
|
|
85
|
+
fields: ["id", "text", "module"],
|
|
86
|
+
sort: ["id"]
|
|
87
|
+
});
|
|
79
88
|
const workerCount = getTranslationWorkerCount();
|
|
89
|
+
const chunkSize = TRANSLATION_CHUNK_SIZE;
|
|
80
90
|
const countStart = Date.now();
|
|
81
|
-
const total = await this.countTexts(
|
|
91
|
+
const total = await this.countTexts(findTextsOptions);
|
|
82
92
|
(_a = this.logger) == null ? void 0 : _a.debug("Localization AI translation task started", {
|
|
83
93
|
taskId: this.record.id,
|
|
84
94
|
mode: params.mode,
|
|
@@ -86,96 +96,86 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
86
96
|
total,
|
|
87
97
|
countElapsedMs: elapsed(countStart),
|
|
88
98
|
workerCount,
|
|
89
|
-
|
|
99
|
+
chunkSize,
|
|
90
100
|
defaultReferenceLocale,
|
|
101
|
+
referenceLocales,
|
|
102
|
+
scope: params.scope || "all",
|
|
91
103
|
provider: service == null ? void 0 : service.provider,
|
|
92
104
|
llmService: service == null ? void 0 : service.name,
|
|
93
105
|
model
|
|
94
106
|
});
|
|
95
107
|
let translated = 0;
|
|
96
108
|
let chunkIndex = 0;
|
|
97
|
-
let producerDone = false;
|
|
98
|
-
let firstError;
|
|
99
|
-
const queue = [];
|
|
100
109
|
this.reportProgress({ total, current: 0 });
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
await this.app.db.getRepository("localizationTexts").chunkWithCursor({
|
|
127
|
-
...this.buildFindTextsOptions(params.mode, locale, params.textIds),
|
|
128
|
-
chunkSize: TRANSLATION_BATCH_SIZE,
|
|
129
|
-
beforeFind: async () => {
|
|
130
|
-
while (!firstError && queue.length >= MAX_TRANSLATION_QUEUE_SIZE) {
|
|
131
|
-
await sleep(100);
|
|
132
|
-
}
|
|
133
|
-
if (firstError) {
|
|
134
|
-
throw firstError;
|
|
110
|
+
const repository = this.app.db.getRepository("localizationTexts");
|
|
111
|
+
const chunk = params.mode === "selected" ? repository.chunk.bind(repository) : repository.chunkWithCursor.bind(repository);
|
|
112
|
+
await chunk({
|
|
113
|
+
...findTextsOptions,
|
|
114
|
+
chunkSize,
|
|
115
|
+
callback: async (rows) => {
|
|
116
|
+
var _a2, _b2, _c;
|
|
117
|
+
chunkIndex += 1;
|
|
118
|
+
const chunkStart = Date.now();
|
|
119
|
+
const textRows = rows.map((row) => (0, import_translation_scope.normalizeTextRecord)(row)).filter(Boolean);
|
|
120
|
+
const rowsWithScope = textRows.map((row) => ({
|
|
121
|
+
row,
|
|
122
|
+
isBuiltIn: (0, import_translation_scope.isBuiltInText)(row, builtInMatchResources)
|
|
123
|
+
}));
|
|
124
|
+
(_a2 = this.logger) == null ? void 0 : _a2.debug("Localization AI translation chunk loaded", {
|
|
125
|
+
taskId: this.record.id,
|
|
126
|
+
chunkIndex,
|
|
127
|
+
rows: textRows.length,
|
|
128
|
+
workerCount,
|
|
129
|
+
translated,
|
|
130
|
+
total
|
|
131
|
+
});
|
|
132
|
+
for (let start = 0; start < rowsWithScope.length; start += workerCount) {
|
|
133
|
+
if (this.isCanceled) {
|
|
134
|
+
throw new import_plugin_async_task_manager.CancelError();
|
|
135
135
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
136
|
+
const batchStart = Date.now();
|
|
137
|
+
const batch = rowsWithScope.slice(start, start + workerCount);
|
|
138
|
+
const items = await this.buildTranslationItems(batch, referenceLocales, chunkIndex);
|
|
139
|
+
await Promise.all(
|
|
140
|
+
items.map(
|
|
141
|
+
(item, index) => this.translateItem({
|
|
142
|
+
workerIndex: index + 1,
|
|
143
|
+
item,
|
|
144
|
+
total,
|
|
145
|
+
getTranslated: () => translated,
|
|
146
|
+
incrementTranslated: () => {
|
|
147
|
+
translated += 1;
|
|
148
|
+
return translated;
|
|
149
|
+
},
|
|
150
|
+
locale,
|
|
151
|
+
employeeUsername,
|
|
152
|
+
employee,
|
|
153
|
+
provider,
|
|
154
|
+
service,
|
|
155
|
+
model
|
|
156
|
+
})
|
|
157
|
+
)
|
|
158
|
+
);
|
|
159
|
+
(_b2 = this.logger) == null ? void 0 : _b2.debug("Localization AI translation batch completed", {
|
|
158
160
|
taskId: this.record.id,
|
|
159
161
|
chunkIndex,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
referenceTranslations: queueItems.filter((item) => item.referenceTranslation).length,
|
|
164
|
-
builtInReferences: queueItems.filter((item) => item.isBuiltIn && item.referenceTranslation).length,
|
|
165
|
-
queueSize: queue.length,
|
|
166
|
-
elapsedMs: elapsed(chunkStart),
|
|
162
|
+
batchSize: items.length,
|
|
163
|
+
referenceTranslations: items.filter((item) => item.referenceTranslation).length,
|
|
164
|
+
elapsedMs: elapsed(batchStart),
|
|
167
165
|
translated,
|
|
168
166
|
total
|
|
169
167
|
});
|
|
170
168
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
169
|
+
(_c = this.logger) == null ? void 0 : _c.debug("Localization AI translation chunk completed", {
|
|
170
|
+
taskId: this.record.id,
|
|
171
|
+
chunkIndex,
|
|
172
|
+
rows: textRows.length,
|
|
173
|
+
elapsedMs: elapsed(chunkStart),
|
|
174
|
+
translated,
|
|
175
|
+
total
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
179
|
(_b = this.logger) == null ? void 0 : _b.debug("Localization AI translation task completed", {
|
|
180
180
|
taskId: this.record.id,
|
|
181
181
|
translated,
|
|
@@ -186,34 +186,8 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
186
186
|
total
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
-
async countTexts(
|
|
190
|
-
return await this.app.db.getRepository("localizationTexts").count(
|
|
191
|
-
}
|
|
192
|
-
buildFindTextsOptions(mode, locale, textIds) {
|
|
193
|
-
const options = {
|
|
194
|
-
fields: ["id", "text", "module"],
|
|
195
|
-
sort: ["id"]
|
|
196
|
-
};
|
|
197
|
-
if (mode === "selected") {
|
|
198
|
-
options.filter = {
|
|
199
|
-
id: {
|
|
200
|
-
$in: textIds || []
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
if (mode === "incremental") {
|
|
205
|
-
options.include = [{ association: "translations", where: { locale }, required: false }];
|
|
206
|
-
options.where = {
|
|
207
|
-
"$translations.id$": null
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
return options;
|
|
211
|
-
}
|
|
212
|
-
normalizeTextRecord(row) {
|
|
213
|
-
if (!row) {
|
|
214
|
-
return void 0;
|
|
215
|
-
}
|
|
216
|
-
return typeof row.toJSON === "function" ? row.toJSON() : row;
|
|
189
|
+
async countTexts(options) {
|
|
190
|
+
return await this.app.db.getRepository("localizationTexts").count(options);
|
|
217
191
|
}
|
|
218
192
|
async getLocaleReferences(textIds, locale) {
|
|
219
193
|
const references = /* @__PURE__ */ new Map();
|
|
@@ -223,10 +197,10 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
223
197
|
const rows = await this.app.db.getRepository("localizationTranslations").find({
|
|
224
198
|
fields: ["textId", "translation"],
|
|
225
199
|
filter: {
|
|
226
|
-
locale,
|
|
227
200
|
textId: {
|
|
228
201
|
$in: textIds
|
|
229
|
-
}
|
|
202
|
+
},
|
|
203
|
+
locale
|
|
230
204
|
}
|
|
231
205
|
});
|
|
232
206
|
for (const row of rows) {
|
|
@@ -237,34 +211,72 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
237
211
|
}
|
|
238
212
|
return references;
|
|
239
213
|
}
|
|
214
|
+
async getReferenceMaps(textIds, locales) {
|
|
215
|
+
const result = /* @__PURE__ */ new Map();
|
|
216
|
+
await Promise.all(
|
|
217
|
+
locales.map(async (locale) => {
|
|
218
|
+
result.set(locale, await this.getLocaleReferences(textIds, locale));
|
|
219
|
+
})
|
|
220
|
+
);
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
pickDbReference(row, references, locales) {
|
|
224
|
+
var _a;
|
|
225
|
+
for (const locale of [locales.primary, locales.fallback].filter(isString)) {
|
|
226
|
+
const translation = (_a = references.get(locale)) == null ? void 0 : _a.get(String(row.id));
|
|
227
|
+
if (translation) {
|
|
228
|
+
return { locale, translation };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return {};
|
|
232
|
+
}
|
|
240
233
|
async getSystemDefaultLocale() {
|
|
241
234
|
var _a;
|
|
242
235
|
const systemSetting = await ((_a = this.app.db.getRepository("systemSettings")) == null ? void 0 : _a.findOne());
|
|
243
236
|
const enabledLanguages = (systemSetting == null ? void 0 : systemSetting.get("enabledLanguages")) || [];
|
|
244
237
|
return (enabledLanguages == null ? void 0 : enabledLanguages[0]) || process.env.APP_LANG || "en-US";
|
|
245
238
|
}
|
|
246
|
-
|
|
247
|
-
var _a;
|
|
248
|
-
return
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
239
|
+
resolveReferenceLocales(referenceLocales, defaultReferenceLocale) {
|
|
240
|
+
var _a, _b, _c, _d;
|
|
241
|
+
return {
|
|
242
|
+
builtIn: {
|
|
243
|
+
primary: ((_a = referenceLocales == null ? void 0 : referenceLocales.builtIn) == null ? void 0 : _a.primary) || "zh-CN",
|
|
244
|
+
fallback: ((_b = referenceLocales == null ? void 0 : referenceLocales.builtIn) == null ? void 0 : _b.fallback) || "ja-JP"
|
|
245
|
+
},
|
|
246
|
+
custom: {
|
|
247
|
+
primary: ((_c = referenceLocales == null ? void 0 : referenceLocales.custom) == null ? void 0 : _c.primary) || defaultReferenceLocale,
|
|
248
|
+
fallback: ((_d = referenceLocales == null ? void 0 : referenceLocales.custom) == null ? void 0 : _d.fallback) || "zh-CN"
|
|
249
|
+
}
|
|
250
|
+
};
|
|
254
251
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
|
|
252
|
+
async buildTranslationItems(batch, referenceLocales, chunkIndex) {
|
|
253
|
+
const builtInTextIds = batch.filter((item) => item.isBuiltIn).map((item) => item.row.id);
|
|
254
|
+
const customTextIds = batch.filter((item) => !item.isBuiltIn).map((item) => item.row.id);
|
|
255
|
+
const builtInReferences = await this.getReferenceMaps(
|
|
256
|
+
builtInTextIds,
|
|
257
|
+
[referenceLocales.builtIn.primary, referenceLocales.builtIn.fallback].filter(isString)
|
|
258
|
+
);
|
|
259
|
+
const customReferences = await this.getReferenceMaps(
|
|
260
|
+
customTextIds,
|
|
261
|
+
[referenceLocales.custom.primary, referenceLocales.custom.fallback].filter(isString)
|
|
262
|
+
);
|
|
263
|
+
return batch.map(({ row, isBuiltIn }) => {
|
|
264
|
+
const references = isBuiltIn ? referenceLocales.builtIn : referenceLocales.custom;
|
|
265
|
+
const reference = this.pickDbReference(row, isBuiltIn ? builtInReferences : customReferences, references);
|
|
266
|
+
return {
|
|
267
|
+
row,
|
|
268
|
+
chunkIndex,
|
|
269
|
+
referenceTranslation: reference.translation,
|
|
270
|
+
referenceLocale: reference.locale,
|
|
271
|
+
isBuiltIn
|
|
272
|
+
};
|
|
273
|
+
});
|
|
259
274
|
}
|
|
260
|
-
async
|
|
275
|
+
async translateItem(options) {
|
|
261
276
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
262
277
|
const {
|
|
263
278
|
workerIndex,
|
|
264
|
-
|
|
265
|
-
isDone,
|
|
266
|
-
getError,
|
|
267
|
-
setError,
|
|
279
|
+
item,
|
|
268
280
|
total,
|
|
269
281
|
getTranslated,
|
|
270
282
|
incrementTranslated,
|
|
@@ -275,102 +287,85 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
275
287
|
service,
|
|
276
288
|
model
|
|
277
289
|
} = options;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
290
|
+
if (this.isCanceled) {
|
|
291
|
+
throw new import_plugin_async_task_manager.CancelError();
|
|
292
|
+
}
|
|
293
|
+
const { row, chunkIndex, referenceTranslation, referenceLocale, isBuiltIn } = item;
|
|
294
|
+
try {
|
|
295
|
+
const textStart = Date.now();
|
|
296
|
+
(_c = (_a = this.logger) == null ? void 0 : _a.trace) == null ? void 0 : _c.call(_a, "Localization AI translation text started", {
|
|
297
|
+
taskId: this.record.id,
|
|
298
|
+
workerIndex,
|
|
299
|
+
chunkIndex,
|
|
300
|
+
textId: row.id,
|
|
301
|
+
textLength: ((_b = row.text) == null ? void 0 : _b.length) ?? 0,
|
|
302
|
+
hasReferenceTranslation: Boolean(referenceTranslation),
|
|
303
|
+
referenceLocale,
|
|
304
|
+
isBuiltIn,
|
|
305
|
+
translated: getTranslated(),
|
|
306
|
+
total
|
|
307
|
+
});
|
|
308
|
+
const isLegacySymbolTranslation = LEGACY_SYMBOL_TRANSLATIONS.has(row.text);
|
|
309
|
+
if (isLegacySymbolTranslation) {
|
|
310
|
+
(_e = (_d = this.logger) == null ? void 0 : _d.trace) == null ? void 0 : _e.call(_d, "Localization AI translation legacy symbol skipped", {
|
|
294
311
|
taskId: this.record.id,
|
|
295
312
|
workerIndex,
|
|
296
313
|
chunkIndex,
|
|
297
314
|
textId: row.id,
|
|
298
|
-
|
|
299
|
-
hasEnglishReference: Boolean(englishReference),
|
|
300
|
-
hasReferenceTranslation: Boolean(referenceTranslation),
|
|
301
|
-
referenceLocale,
|
|
302
|
-
isBuiltIn,
|
|
303
|
-
queueSize: queue.length,
|
|
304
|
-
translated: getTranslated(),
|
|
305
|
-
total
|
|
315
|
+
text: row.text
|
|
306
316
|
});
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
employee,
|
|
327
|
-
provider,
|
|
328
|
-
service,
|
|
329
|
-
model
|
|
330
|
-
});
|
|
331
|
-
const aiElapsedMs = elapsed(textStart);
|
|
332
|
-
const writeStart = Date.now();
|
|
333
|
-
await this.app.db.getRepository("localizationTranslations").updateOrCreate({
|
|
334
|
-
filterKeys: ["textId", "locale"],
|
|
335
|
-
values: {
|
|
336
|
-
textId: row.id,
|
|
337
|
-
locale,
|
|
338
|
-
translation
|
|
339
|
-
}
|
|
340
|
-
});
|
|
341
|
-
const writeElapsedMs = elapsed(writeStart);
|
|
342
|
-
const translated = incrementTranslated();
|
|
343
|
-
this.reportProgress({ total, current: translated });
|
|
344
|
-
(_g = this.logger) == null ? void 0 : _g.debug("Localization AI translation text completed", {
|
|
345
|
-
taskId: this.record.id,
|
|
346
|
-
workerIndex,
|
|
347
|
-
chunkIndex,
|
|
317
|
+
}
|
|
318
|
+
const translation = isLegacySymbolTranslation ? row.text : await this.translateText({
|
|
319
|
+
text: row.text,
|
|
320
|
+
module: row.module,
|
|
321
|
+
referenceTranslation,
|
|
322
|
+
referenceLocale,
|
|
323
|
+
isBuiltIn,
|
|
324
|
+
locale,
|
|
325
|
+
employeeUsername,
|
|
326
|
+
employee,
|
|
327
|
+
provider,
|
|
328
|
+
service,
|
|
329
|
+
model
|
|
330
|
+
});
|
|
331
|
+
const aiElapsedMs = elapsed(textStart);
|
|
332
|
+
const writeStart = Date.now();
|
|
333
|
+
await this.app.db.getRepository("localizationTranslations").updateOrCreate({
|
|
334
|
+
filterKeys: ["textId", "locale"],
|
|
335
|
+
values: {
|
|
348
336
|
textId: row.id,
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
aiElapsedMs,
|
|
352
|
-
writeElapsedMs,
|
|
353
|
-
totalElapsedMs: elapsed(textStart),
|
|
354
|
-
translated,
|
|
355
|
-
total,
|
|
356
|
-
queueSize: queue.length
|
|
357
|
-
});
|
|
358
|
-
} catch (error) {
|
|
359
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
360
|
-
const details = {
|
|
361
|
-
id: row.id,
|
|
362
|
-
text: row.text,
|
|
363
|
-
error: message
|
|
364
|
-
};
|
|
365
|
-
(_h = this.logger) == null ? void 0 : _h.error(`Failed to translate localization text ${row.id}: ${message}`, { error });
|
|
366
|
-
if (error instanceof import_plugin_async_task_manager.CancelError) {
|
|
367
|
-
throw error;
|
|
337
|
+
locale,
|
|
338
|
+
translation
|
|
368
339
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
340
|
+
});
|
|
341
|
+
const writeElapsedMs = elapsed(writeStart);
|
|
342
|
+
const translated = incrementTranslated();
|
|
343
|
+
this.reportProgress({ total, current: translated });
|
|
344
|
+
(_g = this.logger) == null ? void 0 : _g.debug("Localization AI translation text completed", {
|
|
345
|
+
taskId: this.record.id,
|
|
346
|
+
workerIndex,
|
|
347
|
+
chunkIndex,
|
|
348
|
+
textId: row.id,
|
|
349
|
+
textLength: ((_f = row.text) == null ? void 0 : _f.length) ?? 0,
|
|
350
|
+
translationLength: translation.length,
|
|
351
|
+
aiElapsedMs,
|
|
352
|
+
writeElapsedMs,
|
|
353
|
+
totalElapsedMs: elapsed(textStart),
|
|
354
|
+
translated,
|
|
355
|
+
total
|
|
356
|
+
});
|
|
357
|
+
} catch (error) {
|
|
358
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
359
|
+
const details = {
|
|
360
|
+
id: row.id,
|
|
361
|
+
text: row.text,
|
|
362
|
+
error: message
|
|
363
|
+
};
|
|
364
|
+
(_h = this.logger) == null ? void 0 : _h.error(`Failed to translate localization text ${row.id}: ${message}`, { error });
|
|
365
|
+
if (error instanceof import_plugin_async_task_manager.CancelError) {
|
|
366
|
+
throw error;
|
|
373
367
|
}
|
|
368
|
+
throw new LocalizationAITranslationError(`Failed to translate localization text ${row.id}: ${message}`, details);
|
|
374
369
|
}
|
|
375
370
|
}
|
|
376
371
|
async translateText(options) {
|
|
@@ -378,7 +373,6 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
378
373
|
const {
|
|
379
374
|
text,
|
|
380
375
|
module: module2,
|
|
381
|
-
englishReference,
|
|
382
376
|
referenceTranslation,
|
|
383
377
|
referenceLocale,
|
|
384
378
|
isBuiltIn,
|
|
@@ -390,14 +384,13 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
390
384
|
employee
|
|
391
385
|
} = options;
|
|
392
386
|
const setupStart = Date.now();
|
|
393
|
-
const sourceText =
|
|
394
|
-
const sourceLang = englishReference ? "English" : "auto";
|
|
387
|
+
const sourceText = text;
|
|
395
388
|
const targetLang = this.getLanguageName(locale);
|
|
396
389
|
const context = this.buildProviderContext({
|
|
390
|
+
systemPrompt: this.getEmployeeSystemPrompt(employee),
|
|
397
391
|
sourceText,
|
|
398
392
|
targetLang,
|
|
399
|
-
|
|
400
|
-
referenceTargetTerm: referenceTranslation
|
|
393
|
+
referenceTranslation
|
|
401
394
|
});
|
|
402
395
|
const invokeStart = Date.now();
|
|
403
396
|
(_b = (_a = this.logger) == null ? void 0 : _a.trace) == null ? void 0 : _b.call(_a, "Localization AI translation invoke started", {
|
|
@@ -405,44 +398,29 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
405
398
|
textLength: (text == null ? void 0 : text.length) ?? 0,
|
|
406
399
|
sourceTextLength: (sourceText == null ? void 0 : sourceText.length) ?? 0,
|
|
407
400
|
locale,
|
|
408
|
-
sourceLang,
|
|
409
401
|
targetLang,
|
|
410
402
|
module: module2,
|
|
411
403
|
employeeUsername,
|
|
412
404
|
provider: service == null ? void 0 : service.provider,
|
|
413
405
|
llmService: service == null ? void 0 : service.name,
|
|
414
406
|
model,
|
|
415
|
-
hasEnglishReference: Boolean(englishReference),
|
|
416
407
|
hasReferenceTranslation: Boolean(referenceTranslation),
|
|
417
408
|
referenceLocale,
|
|
418
409
|
isBuiltIn
|
|
419
410
|
});
|
|
420
|
-
const result = await provider.invoke(context
|
|
421
|
-
modelRequestParams: {
|
|
422
|
-
sourceText,
|
|
423
|
-
sourceLang,
|
|
424
|
-
targetLang,
|
|
425
|
-
terms: this.buildTranslationTerms({
|
|
426
|
-
sourceTerm: sourceText,
|
|
427
|
-
targetTerm: referenceTranslation,
|
|
428
|
-
targetLang
|
|
429
|
-
})
|
|
430
|
-
}
|
|
431
|
-
});
|
|
411
|
+
const result = await provider.invoke(context);
|
|
432
412
|
const invokeElapsedMs = elapsed(invokeStart);
|
|
433
413
|
(_d = (_c = this.logger) == null ? void 0 : _c.trace) == null ? void 0 : _d.call(_c, "Localization AI translation invoke completed", {
|
|
434
414
|
taskId: this.record.id,
|
|
435
415
|
textLength: (text == null ? void 0 : text.length) ?? 0,
|
|
436
416
|
sourceTextLength: (sourceText == null ? void 0 : sourceText.length) ?? 0,
|
|
437
417
|
locale,
|
|
438
|
-
sourceLang,
|
|
439
418
|
targetLang,
|
|
440
419
|
module: module2,
|
|
441
420
|
employeeUsername,
|
|
442
421
|
provider: service == null ? void 0 : service.provider,
|
|
443
422
|
llmService: service == null ? void 0 : service.name,
|
|
444
423
|
model,
|
|
445
|
-
hasEnglishReference: Boolean(englishReference),
|
|
446
424
|
hasReferenceTranslation: Boolean(referenceTranslation),
|
|
447
425
|
referenceLocale,
|
|
448
426
|
isBuiltIn,
|
|
@@ -460,14 +438,12 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
460
438
|
sourceTextLength: (sourceText == null ? void 0 : sourceText.length) ?? 0,
|
|
461
439
|
translationLength: translation.length,
|
|
462
440
|
locale,
|
|
463
|
-
sourceLang,
|
|
464
441
|
targetLang,
|
|
465
442
|
module: module2,
|
|
466
443
|
employeeUsername,
|
|
467
444
|
provider: service == null ? void 0 : service.provider,
|
|
468
445
|
llmService: service == null ? void 0 : service.name,
|
|
469
446
|
model,
|
|
470
|
-
hasEnglishReference: Boolean(englishReference),
|
|
471
447
|
hasReferenceTranslation: Boolean(referenceTranslation),
|
|
472
448
|
referenceLocale,
|
|
473
449
|
isBuiltIn,
|
|
@@ -477,32 +453,25 @@ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskT
|
|
|
477
453
|
});
|
|
478
454
|
return translation;
|
|
479
455
|
}
|
|
456
|
+
getEmployeeSystemPrompt(employee) {
|
|
457
|
+
var _a, _b;
|
|
458
|
+
return ((_a = employee == null ? void 0 : employee.get) == null ? void 0 : _a.call(employee, "about")) || ((_b = employee == null ? void 0 : employee.get) == null ? void 0 : _b.call(employee, "defaultPrompt")) || (employee == null ? void 0 : employee.about) || (employee == null ? void 0 : employee.defaultPrompt) || "";
|
|
459
|
+
}
|
|
480
460
|
buildProviderContext(options) {
|
|
481
|
-
const { sourceText, targetLang,
|
|
482
|
-
const
|
|
483
|
-
|
|
461
|
+
const { systemPrompt, sourceText, targetLang, referenceTranslation } = options;
|
|
462
|
+
const prompt = (systemPrompt || "").trim();
|
|
463
|
+
const reference = referenceTranslation ? `Refer to the following translation:
|
|
464
|
+
${sourceText} is translated as ${referenceTranslation}
|
|
484
465
|
|
|
485
466
|
` : "";
|
|
486
|
-
const
|
|
487
|
-
|
|
467
|
+
const task = `Translate the following text into ${targetLang}. Output only the translated result without any additional explanation:
|
|
488
468
|
${sourceText}
|
|
489
469
|
`;
|
|
470
|
+
const content = [prompt, `${reference}${task}`].filter(Boolean).join("\n\n");
|
|
490
471
|
return {
|
|
491
472
|
messages: [new import_messages.HumanMessage(content)]
|
|
492
473
|
};
|
|
493
474
|
}
|
|
494
|
-
buildTranslationTerms(options) {
|
|
495
|
-
const { sourceTerm, targetTerm, targetLang } = options;
|
|
496
|
-
if (!sourceTerm || !targetTerm || !["Chinese", "Traditional Chinese"].includes(targetLang)) {
|
|
497
|
-
return void 0;
|
|
498
|
-
}
|
|
499
|
-
return [
|
|
500
|
-
{
|
|
501
|
-
source: sourceTerm,
|
|
502
|
-
target: targetTerm
|
|
503
|
-
}
|
|
504
|
-
];
|
|
505
|
-
}
|
|
506
475
|
getLanguageName(locale) {
|
|
507
476
|
const normalized = locale.replace("_", "-");
|
|
508
477
|
const map = {
|