@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.
@@ -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 MAX_TRANSLATION_QUEUE_SIZE = TRANSLATION_BATCH_SIZE * 2;
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(params.mode, locale, params.textIds);
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
- queueLimit: MAX_TRANSLATION_QUEUE_SIZE,
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 workers = Array.from(
102
- { length: workerCount },
103
- (_, workerIndex) => this.runTranslationWorker({
104
- workerIndex: workerIndex + 1,
105
- queue,
106
- isDone: () => producerDone,
107
- getError: () => firstError,
108
- setError: (error) => {
109
- firstError = firstError ?? error;
110
- },
111
- total,
112
- getTranslated: () => translated,
113
- incrementTranslated: () => {
114
- translated += 1;
115
- return translated;
116
- },
117
- locale,
118
- employeeUsername,
119
- employee,
120
- provider,
121
- service,
122
- model
123
- })
124
- );
125
- try {
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
- callback: async (rows) => {
138
- var _a2;
139
- chunkIndex += 1;
140
- const chunkStart = Date.now();
141
- const textRows = rows.map((row) => this.normalizeTextRecord(row)).filter(Boolean);
142
- const textIds = textRows.map((row) => row.id);
143
- const englishReferences = await this.getLocaleReferences(textIds, "en-US");
144
- const defaultLocaleReferences = defaultReferenceLocale === "en-US" ? englishReferences : await this.getLocaleReferences(textIds, defaultReferenceLocale);
145
- const queueItems = textRows.map((row) => {
146
- const isBuiltIn = this.isBuiltInText(row, builtInMatchResources);
147
- return {
148
- row,
149
- chunkIndex,
150
- englishReference: englishReferences.get(String(row.id)),
151
- referenceTranslation: isBuiltIn ? this.getBuiltInReference(row, builtInReferenceResources) : defaultLocaleReferences.get(String(row.id)),
152
- referenceLocale: isBuiltIn ? "zh-CN" : defaultReferenceLocale,
153
- isBuiltIn
154
- };
155
- });
156
- queue.push(...queueItems);
157
- (_a2 = this.logger) == null ? void 0 : _a2.debug("Localization AI translation chunk enqueued", {
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
- rows: textRows.length,
161
- englishReferences: englishReferences.size,
162
- referenceLocale: defaultReferenceLocale,
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
- } finally {
173
- producerDone = true;
174
- }
175
- await Promise.all(workers);
176
- if (firstError) {
177
- throw firstError;
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(mode, locale, textIds) {
190
- return await this.app.db.getRepository("localizationTexts").count(this.buildFindTextsOptions(mode, locale, textIds));
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
- getModuleName(row) {
247
- var _a;
248
- return (_a = row.module) == null ? void 0 : _a.replace("resources.", "");
249
- }
250
- isBuiltInText(row, resources) {
251
- var _a;
252
- const moduleName = this.getModuleName(row);
253
- return Boolean(moduleName && ((_a = resources[moduleName]) == null ? void 0 : _a[row.text]) !== void 0);
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
- getBuiltInReference(row, resources) {
256
- var _a;
257
- const moduleName = this.getModuleName(row);
258
- return moduleName ? (_a = resources[moduleName]) == null ? void 0 : _a[row.text] : void 0;
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 runTranslationWorker(options) {
275
+ async translateItem(options) {
261
276
  var _a, _b, _c, _d, _e, _f, _g, _h;
262
277
  const {
263
278
  workerIndex,
264
- queue,
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
- while (!isDone() || queue.length > 0) {
279
- if (getError()) {
280
- return;
281
- }
282
- if (this.isCanceled) {
283
- throw new import_plugin_async_task_manager.CancelError();
284
- }
285
- const item = queue.shift();
286
- if (!item) {
287
- await sleep(50);
288
- continue;
289
- }
290
- const { row, chunkIndex, englishReference, referenceTranslation, referenceLocale, isBuiltIn } = item;
291
- try {
292
- const textStart = Date.now();
293
- (_c = (_a = this.logger) == null ? void 0 : _a.trace) == null ? void 0 : _c.call(_a, "Localization AI translation text started", {
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
- textLength: ((_b = row.text) == null ? void 0 : _b.length) ?? 0,
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
- const isLegacySymbolTranslation = LEGACY_SYMBOL_TRANSLATIONS.has(row.text);
308
- if (isLegacySymbolTranslation) {
309
- (_e = (_d = this.logger) == null ? void 0 : _d.trace) == null ? void 0 : _e.call(_d, "Localization AI translation legacy symbol skipped", {
310
- taskId: this.record.id,
311
- workerIndex,
312
- chunkIndex,
313
- textId: row.id,
314
- text: row.text
315
- });
316
- }
317
- const translation = isLegacySymbolTranslation ? row.text : await this.translateText({
318
- text: row.text,
319
- module: row.module,
320
- englishReference,
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: {
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
- 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
- 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
- setError(
370
- new LocalizationAITranslationError(`Failed to translate localization text ${row.id}: ${message}`, details)
371
- );
372
- return;
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 = englishReference || text;
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
- referenceSourceTerm: sourceText,
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, referenceSourceTerm, referenceTargetTerm } = options;
482
- const reference = referenceSourceTerm && referenceTargetTerm ? `Refer to the following translation:
483
- ${referenceSourceTerm} is translated as ${referenceTargetTerm}
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 content = `${reference}Translate the following text into ${targetLang}. Output only the translated result without any additional explanation:
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 = {