@nocobase/plugin-localization 2.1.0-beta.9 → 2.2.0-alpha.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.
Files changed (37) hide show
  1. package/client-v2.d.ts +2 -0
  2. package/client-v2.js +1 -0
  3. package/dist/ai/ai-employees/lina.d.ts +10 -0
  4. package/dist/ai/ai-employees/lina.js +60 -0
  5. package/dist/client/300.1f79b801d226f40d.js +10 -0
  6. package/dist/client/i18n-missing-handler.d.ts +1 -17
  7. package/dist/client/index.js +1 -1
  8. package/dist/client-v2/796.0ec484505de4b04a.js +10 -0
  9. package/dist/client-v2/common/constants.d.ts +13 -0
  10. package/dist/client-v2/common/i18n-missing-handler.d.ts +23 -0
  11. package/dist/{client/Localization.d.ts → client-v2/i18n-missing-handler.d.ts} +1 -2
  12. package/dist/client-v2/index.d.ts +9 -0
  13. package/dist/client-v2/index.js +10 -0
  14. package/dist/client-v2/locale.d.ts +11 -0
  15. package/dist/client-v2/pages/LocalizationPage.d.ts +11 -0
  16. package/dist/client-v2/plugin.d.ts +13 -0
  17. package/dist/externalVersion.js +18 -13
  18. package/dist/locale/en-US.json +38 -1
  19. package/dist/locale/zh-CN.json +38 -1
  20. package/dist/server/actions/aiTranslate.d.ts +14 -0
  21. package/dist/server/actions/aiTranslate.js +151 -0
  22. package/dist/server/actions/localization.js +30 -15
  23. package/dist/server/actions/localizationTexts.js +8 -9
  24. package/dist/server/collections/localization-texts.js +1 -0
  25. package/dist/server/collections/localization-translations.js +1 -0
  26. package/dist/server/migrations/20260511230000-delete-official-plugin-package-resource-modules.d.ts +14 -0
  27. package/dist/server/migrations/20260511230000-delete-official-plugin-package-resource-modules.js +64 -0
  28. package/dist/server/plugin.d.ts +5 -2
  29. package/dist/server/plugin.js +76 -14
  30. package/dist/server/tasks/localization-ai-translate.d.ts +48 -0
  31. package/dist/server/tasks/localization-ai-translate.js +606 -0
  32. package/dist/server/translation-scope.d.ts +31 -0
  33. package/dist/server/translation-scope.js +107 -0
  34. package/package.json +7 -2
  35. package/dist/client/177bd849c95cf6cc.js +0 -10
  36. package/dist/server/source-manager.d.ts +0 -35
  37. package/dist/server/source-manager.js +0 -77
@@ -0,0 +1,606 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var localization_ai_translate_exports = {};
28
+ __export(localization_ai_translate_exports, {
29
+ LOCALIZATION_AI_TRANSLATE_TASK_TYPE: () => LOCALIZATION_AI_TRANSLATE_TASK_TYPE,
30
+ LocalizationAITranslateTask: () => LocalizationAITranslateTask,
31
+ pickBuiltInResourceReference: () => pickBuiltInResourceReference
32
+ });
33
+ module.exports = __toCommonJS(localization_ai_translate_exports);
34
+ var import_plugin_async_task_manager = require("@nocobase/plugin-async-task-manager");
35
+ var import_messages = require("@langchain/core/messages");
36
+ var import_translation_scope = require("../translation-scope");
37
+ const LOCALIZATION_AI_TRANSLATE_TASK_TYPE = "localization:ai-translate";
38
+ const DEFAULT_TRANSLATION_WORKER_COUNT = 10;
39
+ const MIN_TRANSLATION_WORKER_COUNT = 1;
40
+ const MAX_TRANSLATION_WORKER_COUNT = 20;
41
+ const TRANSLATION_CHUNK_SIZE = 200;
42
+ const elapsed = (start) => Date.now() - start;
43
+ const truncateForLog = (value, maxLength = 500) => value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
44
+ const LEGACY_SYMBOL_TRANSLATIONS = /* @__PURE__ */ new Set(["<", "=", ">"]);
45
+ const isString = (value) => typeof value === "string" && value.length > 0;
46
+ const getTranslationWorkerCount = () => {
47
+ const value = Number.parseInt(process.env.AI_LOCALIZATION_CONCURRENCY || "", 10);
48
+ if (Number.isInteger(value) && value >= MIN_TRANSLATION_WORKER_COUNT && value <= MAX_TRANSLATION_WORKER_COUNT) {
49
+ return value;
50
+ }
51
+ return DEFAULT_TRANSLATION_WORKER_COUNT;
52
+ };
53
+ const pickBuiltInResourceReference = (row, references, locales) => {
54
+ var _a;
55
+ for (const locale of [locales.primary, locales.fallback].filter(isString)) {
56
+ const translation = (_a = references.get(locale)) == null ? void 0 : _a.get(String(row.id));
57
+ if (translation) {
58
+ return { locale, translation };
59
+ }
60
+ }
61
+ return {};
62
+ };
63
+ class LocalizationAITranslationError extends Error {
64
+ constructor(message, details) {
65
+ super(message);
66
+ this.details = details;
67
+ this.name = "LocalizationAITranslationError";
68
+ }
69
+ }
70
+ class LocalizationAITranslateTask extends import_plugin_async_task_manager.TaskType {
71
+ static type = LOCALIZATION_AI_TRANSLATE_TASK_TYPE;
72
+ async execute() {
73
+ var _a, _b;
74
+ const params = this.record.params;
75
+ const locale = params.locale || "en-US";
76
+ const employeeUsername = params.employeeUsername || "lina";
77
+ const aiPlugin = this.app.pm.get("ai");
78
+ if (!(aiPlugin == null ? void 0 : aiPlugin.aiConversationsManager) || !(aiPlugin == null ? void 0 : aiPlugin.aiEmployeesManager)) {
79
+ throw new Error("AI plugin is not available");
80
+ }
81
+ const employee = await aiPlugin.aiEmployeesManager.getEmployee(employeeUsername);
82
+ if (!employee) {
83
+ throw new Error(`AI employee "${employeeUsername}" not found`);
84
+ }
85
+ const resolvedModel = await aiPlugin.aiEmployeesManager.resolveModel(employee, params.model);
86
+ const { provider, model, service } = await aiPlugin.aiManager.getLLMService(resolvedModel);
87
+ const defaultReferenceLocale = await this.getSystemDefaultLocale();
88
+ const builtInMatchResources = await this.app.localeManager.getBuiltInResources("en-US");
89
+ const referenceLocales = this.resolveReferenceLocales(params.referenceLocales, defaultReferenceLocale);
90
+ const findTextsOptions = await (0, import_translation_scope.buildFindTextsOptions)({
91
+ app: this.app,
92
+ mode: params.mode,
93
+ locale,
94
+ scope: params.scope || "all",
95
+ textIds: params.textIds,
96
+ fields: ["id", "text", "module"],
97
+ sort: ["id"]
98
+ });
99
+ const workerCount = getTranslationWorkerCount();
100
+ const chunkSize = TRANSLATION_CHUNK_SIZE;
101
+ const countStart = Date.now();
102
+ const total = await this.countTexts(findTextsOptions);
103
+ (_a = this.logger) == null ? void 0 : _a.debug("Localization AI translation task started", {
104
+ taskId: this.record.id,
105
+ mode: params.mode,
106
+ locale,
107
+ total,
108
+ countElapsedMs: elapsed(countStart),
109
+ workerCount,
110
+ chunkSize,
111
+ defaultReferenceLocale,
112
+ referenceLocales,
113
+ scope: params.scope || "all",
114
+ provider: service == null ? void 0 : service.provider,
115
+ llmService: service == null ? void 0 : service.name,
116
+ model
117
+ });
118
+ let translated = 0;
119
+ let chunkIndex = 0;
120
+ this.reportProgress({ total, current: 0 });
121
+ const repository = this.app.db.getRepository("localizationTexts");
122
+ const chunk = params.mode === "selected" ? repository.chunk.bind(repository) : repository.chunkWithCursor.bind(repository);
123
+ await chunk({
124
+ ...findTextsOptions,
125
+ chunkSize,
126
+ callback: async (rows) => {
127
+ var _a2, _b2, _c;
128
+ chunkIndex += 1;
129
+ const chunkStart = Date.now();
130
+ const textRows = rows.map((row) => (0, import_translation_scope.normalizeTextRecord)(row)).filter(Boolean);
131
+ const rowsWithScope = textRows.map((row) => ({
132
+ row,
133
+ isBuiltIn: (0, import_translation_scope.isBuiltInText)(row, builtInMatchResources)
134
+ }));
135
+ (_a2 = this.logger) == null ? void 0 : _a2.debug("Localization AI translation chunk loaded", {
136
+ taskId: this.record.id,
137
+ chunkIndex,
138
+ rows: textRows.length,
139
+ workerCount,
140
+ translated,
141
+ total
142
+ });
143
+ for (let start = 0; start < rowsWithScope.length; start += workerCount) {
144
+ if (this.isCanceled) {
145
+ throw new import_plugin_async_task_manager.CancelError();
146
+ }
147
+ const batchStart = Date.now();
148
+ const batch = rowsWithScope.slice(start, start + workerCount);
149
+ const items = await this.buildTranslationItems(batch, referenceLocales, chunkIndex);
150
+ await Promise.all(
151
+ items.map(
152
+ (item, index) => this.translateItem({
153
+ workerIndex: index + 1,
154
+ item,
155
+ total,
156
+ getTranslated: () => translated,
157
+ incrementTranslated: () => {
158
+ translated += 1;
159
+ return translated;
160
+ },
161
+ locale,
162
+ employeeUsername,
163
+ employee,
164
+ provider,
165
+ service,
166
+ model
167
+ })
168
+ )
169
+ );
170
+ (_b2 = this.logger) == null ? void 0 : _b2.debug("Localization AI translation batch completed", {
171
+ taskId: this.record.id,
172
+ chunkIndex,
173
+ batchSize: items.length,
174
+ referenceTranslations: items.filter((item) => item.referenceTranslation).length,
175
+ elapsedMs: elapsed(batchStart),
176
+ translated,
177
+ total
178
+ });
179
+ }
180
+ (_c = this.logger) == null ? void 0 : _c.debug("Localization AI translation chunk completed", {
181
+ taskId: this.record.id,
182
+ chunkIndex,
183
+ rows: textRows.length,
184
+ elapsedMs: elapsed(chunkStart),
185
+ translated,
186
+ total
187
+ });
188
+ }
189
+ });
190
+ (_b = this.logger) == null ? void 0 : _b.debug("Localization AI translation task completed", {
191
+ taskId: this.record.id,
192
+ translated,
193
+ total
194
+ });
195
+ return {
196
+ translated,
197
+ total
198
+ };
199
+ }
200
+ async countTexts(options) {
201
+ return await this.app.db.getRepository("localizationTexts").count(options);
202
+ }
203
+ async getLocaleReferences(textIds, locale) {
204
+ const references = /* @__PURE__ */ new Map();
205
+ if (!textIds.length) {
206
+ return references;
207
+ }
208
+ const rows = await this.app.db.getRepository("localizationTranslations").find({
209
+ fields: ["textId", "translation"],
210
+ filter: {
211
+ textId: {
212
+ $in: textIds
213
+ },
214
+ locale
215
+ }
216
+ });
217
+ for (const row of rows) {
218
+ const record = typeof row.toJSON === "function" ? row.toJSON() : row;
219
+ if ((record == null ? void 0 : record.textId) != null && record.translation) {
220
+ references.set(String(record.textId), record.translation);
221
+ }
222
+ }
223
+ return references;
224
+ }
225
+ async getReferenceMaps(textIds, locales) {
226
+ const result = /* @__PURE__ */ new Map();
227
+ await Promise.all(
228
+ Array.from(new Set(locales)).map(async (locale) => {
229
+ result.set(locale, await this.getLocaleReferences(textIds, locale));
230
+ })
231
+ );
232
+ return result;
233
+ }
234
+ async getBuiltInReferenceMaps(rows, locales) {
235
+ const result = /* @__PURE__ */ new Map();
236
+ if (!rows.length) {
237
+ return result;
238
+ }
239
+ await Promise.all(
240
+ Array.from(new Set(locales)).map(async (locale) => {
241
+ var _a;
242
+ const resources = await this.app.localeManager.getCacheResources(locale);
243
+ const references = /* @__PURE__ */ new Map();
244
+ for (const row of rows) {
245
+ const moduleName = (0, import_translation_scope.getModuleName)(row);
246
+ if (!moduleName) {
247
+ continue;
248
+ }
249
+ const modules = Array.from(/* @__PURE__ */ new Set([(0, import_translation_scope.normalizeModuleName)(moduleName), moduleName]));
250
+ for (const module2 of modules) {
251
+ const translation = (_a = resources == null ? void 0 : resources[module2]) == null ? void 0 : _a[row.text];
252
+ if (translation) {
253
+ references.set(String(row.id), translation);
254
+ break;
255
+ }
256
+ }
257
+ }
258
+ result.set(locale, references);
259
+ })
260
+ );
261
+ return result;
262
+ }
263
+ pickDbReference(row, references, locales) {
264
+ var _a;
265
+ for (const locale of [locales.primary, locales.fallback].filter(isString)) {
266
+ const translation = (_a = references.get(locale)) == null ? void 0 : _a.get(String(row.id));
267
+ if (translation) {
268
+ return { locale, translation };
269
+ }
270
+ }
271
+ return {};
272
+ }
273
+ async getSystemDefaultLocale() {
274
+ var _a;
275
+ const systemSetting = await ((_a = this.app.db.getRepository("systemSettings")) == null ? void 0 : _a.findOne());
276
+ const enabledLanguages = (systemSetting == null ? void 0 : systemSetting.get("enabledLanguages")) || [];
277
+ return (enabledLanguages == null ? void 0 : enabledLanguages[0]) || process.env.APP_LANG || "en-US";
278
+ }
279
+ resolveReferenceLocales(referenceLocales, defaultReferenceLocale) {
280
+ var _a, _b, _c, _d;
281
+ return {
282
+ builtIn: {
283
+ primary: ((_a = referenceLocales == null ? void 0 : referenceLocales.builtIn) == null ? void 0 : _a.primary) || "zh-CN",
284
+ fallback: ((_b = referenceLocales == null ? void 0 : referenceLocales.builtIn) == null ? void 0 : _b.fallback) || "ja-JP"
285
+ },
286
+ custom: {
287
+ primary: ((_c = referenceLocales == null ? void 0 : referenceLocales.custom) == null ? void 0 : _c.primary) || defaultReferenceLocale,
288
+ fallback: ((_d = referenceLocales == null ? void 0 : referenceLocales.custom) == null ? void 0 : _d.fallback) || "zh-CN"
289
+ }
290
+ };
291
+ }
292
+ async buildTranslationItems(batch, referenceLocales, chunkIndex) {
293
+ const builtInRows = batch.filter((item) => item.isBuiltIn).map((item) => item.row);
294
+ const customTextIds = batch.filter((item) => !item.isBuiltIn).map((item) => item.row.id);
295
+ const builtInReferences = await this.getBuiltInReferenceMaps(
296
+ builtInRows,
297
+ [referenceLocales.builtIn.primary, referenceLocales.builtIn.fallback].filter(isString)
298
+ );
299
+ const customReferences = await this.getReferenceMaps(
300
+ customTextIds,
301
+ [referenceLocales.custom.primary, referenceLocales.custom.fallback].filter(isString)
302
+ );
303
+ return batch.map(({ row, isBuiltIn }) => {
304
+ const references = isBuiltIn ? referenceLocales.builtIn : referenceLocales.custom;
305
+ const reference = isBuiltIn ? pickBuiltInResourceReference(row, builtInReferences, references) : this.pickDbReference(row, customReferences, references);
306
+ return {
307
+ row,
308
+ chunkIndex,
309
+ referenceTranslation: reference.translation,
310
+ referenceLocale: reference.locale,
311
+ isBuiltIn
312
+ };
313
+ });
314
+ }
315
+ async translateItem(options) {
316
+ var _a, _b, _c, _d, _e, _f, _g, _h;
317
+ const {
318
+ workerIndex,
319
+ item,
320
+ total,
321
+ getTranslated,
322
+ incrementTranslated,
323
+ locale,
324
+ employeeUsername,
325
+ employee,
326
+ provider,
327
+ service,
328
+ model
329
+ } = options;
330
+ if (this.isCanceled) {
331
+ throw new import_plugin_async_task_manager.CancelError();
332
+ }
333
+ const { row, chunkIndex, referenceTranslation, referenceLocale, isBuiltIn } = item;
334
+ try {
335
+ const textStart = Date.now();
336
+ (_c = (_a = this.logger) == null ? void 0 : _a.trace) == null ? void 0 : _c.call(_a, "Localization AI translation text started", {
337
+ taskId: this.record.id,
338
+ workerIndex,
339
+ chunkIndex,
340
+ textId: row.id,
341
+ textLength: ((_b = row.text) == null ? void 0 : _b.length) ?? 0,
342
+ hasReferenceTranslation: Boolean(referenceTranslation),
343
+ referenceLocale,
344
+ isBuiltIn,
345
+ translated: getTranslated(),
346
+ total
347
+ });
348
+ const isLegacySymbolTranslation = LEGACY_SYMBOL_TRANSLATIONS.has(row.text);
349
+ if (isLegacySymbolTranslation) {
350
+ (_e = (_d = this.logger) == null ? void 0 : _d.trace) == null ? void 0 : _e.call(_d, "Localization AI translation legacy symbol skipped", {
351
+ taskId: this.record.id,
352
+ workerIndex,
353
+ chunkIndex,
354
+ textId: row.id,
355
+ text: row.text
356
+ });
357
+ }
358
+ const translation = isLegacySymbolTranslation ? row.text : await this.translateText({
359
+ text: row.text,
360
+ module: row.module,
361
+ referenceTranslation,
362
+ referenceLocale,
363
+ isBuiltIn,
364
+ locale,
365
+ employeeUsername,
366
+ employee,
367
+ provider,
368
+ service,
369
+ model
370
+ });
371
+ const aiElapsedMs = elapsed(textStart);
372
+ const writeStart = Date.now();
373
+ await this.app.db.getRepository("localizationTranslations").updateOrCreate({
374
+ filterKeys: ["textId", "locale"],
375
+ values: {
376
+ textId: row.id,
377
+ locale,
378
+ translation
379
+ }
380
+ });
381
+ const writeElapsedMs = elapsed(writeStart);
382
+ const translated = incrementTranslated();
383
+ this.reportProgress({ total, current: translated });
384
+ (_g = this.logger) == null ? void 0 : _g.debug("Localization AI translation text completed", {
385
+ taskId: this.record.id,
386
+ workerIndex,
387
+ chunkIndex,
388
+ textId: row.id,
389
+ textLength: ((_f = row.text) == null ? void 0 : _f.length) ?? 0,
390
+ translationLength: translation.length,
391
+ aiElapsedMs,
392
+ writeElapsedMs,
393
+ totalElapsedMs: elapsed(textStart),
394
+ translated,
395
+ total
396
+ });
397
+ } catch (error) {
398
+ const message = error instanceof Error ? error.message : String(error);
399
+ const details = {
400
+ id: row.id,
401
+ text: row.text,
402
+ error: message
403
+ };
404
+ (_h = this.logger) == null ? void 0 : _h.error(`Failed to translate localization text ${row.id}: ${message}`, { error });
405
+ if (error instanceof import_plugin_async_task_manager.CancelError) {
406
+ throw error;
407
+ }
408
+ throw new LocalizationAITranslationError(`Failed to translate localization text ${row.id}: ${message}`, details);
409
+ }
410
+ }
411
+ async translateText(options) {
412
+ var _a, _b, _c, _d, _e, _f;
413
+ const {
414
+ text,
415
+ module: module2,
416
+ referenceTranslation,
417
+ referenceLocale,
418
+ isBuiltIn,
419
+ locale,
420
+ employeeUsername,
421
+ provider,
422
+ service,
423
+ model,
424
+ employee
425
+ } = options;
426
+ const setupStart = Date.now();
427
+ const sourceText = text;
428
+ const targetLang = this.getLanguageName(locale);
429
+ const context = this.buildProviderContext({
430
+ systemPrompt: this.getEmployeeSystemPrompt(employee),
431
+ sourceText,
432
+ targetLang,
433
+ referenceTranslation
434
+ });
435
+ const invokeStart = Date.now();
436
+ (_b = (_a = this.logger) == null ? void 0 : _a.trace) == null ? void 0 : _b.call(_a, "Localization AI translation invoke started", {
437
+ taskId: this.record.id,
438
+ textLength: (text == null ? void 0 : text.length) ?? 0,
439
+ sourceTextLength: (sourceText == null ? void 0 : sourceText.length) ?? 0,
440
+ locale,
441
+ targetLang,
442
+ module: module2,
443
+ employeeUsername,
444
+ provider: service == null ? void 0 : service.provider,
445
+ llmService: service == null ? void 0 : service.name,
446
+ model,
447
+ hasReferenceTranslation: Boolean(referenceTranslation),
448
+ referenceLocale,
449
+ isBuiltIn
450
+ });
451
+ const result = await provider.invoke(context);
452
+ const invokeElapsedMs = elapsed(invokeStart);
453
+ (_d = (_c = this.logger) == null ? void 0 : _c.trace) == null ? void 0 : _d.call(_c, "Localization AI translation invoke completed", {
454
+ taskId: this.record.id,
455
+ textLength: (text == null ? void 0 : text.length) ?? 0,
456
+ sourceTextLength: (sourceText == null ? void 0 : sourceText.length) ?? 0,
457
+ locale,
458
+ targetLang,
459
+ module: module2,
460
+ employeeUsername,
461
+ provider: service == null ? void 0 : service.provider,
462
+ llmService: service == null ? void 0 : service.name,
463
+ model,
464
+ hasReferenceTranslation: Boolean(referenceTranslation),
465
+ referenceLocale,
466
+ isBuiltIn,
467
+ setupElapsedMs: elapsed(setupStart) - invokeElapsedMs,
468
+ invokeElapsedMs,
469
+ totalElapsedMs: elapsed(setupStart)
470
+ });
471
+ const translation = this.extractTextContent(result == null ? void 0 : result.content).trim();
472
+ if (!translation) {
473
+ throw new Error("LLM service returned empty translation");
474
+ }
475
+ (_f = (_e = this.logger) == null ? void 0 : _e.trace) == null ? void 0 : _f.call(_e, "Localization AI translation result extracted", {
476
+ taskId: this.record.id,
477
+ textLength: (text == null ? void 0 : text.length) ?? 0,
478
+ sourceTextLength: (sourceText == null ? void 0 : sourceText.length) ?? 0,
479
+ translationLength: translation.length,
480
+ locale,
481
+ targetLang,
482
+ module: module2,
483
+ employeeUsername,
484
+ provider: service == null ? void 0 : service.provider,
485
+ llmService: service == null ? void 0 : service.name,
486
+ model,
487
+ hasReferenceTranslation: Boolean(referenceTranslation),
488
+ referenceLocale,
489
+ isBuiltIn,
490
+ sourceText: truncateForLog(sourceText),
491
+ referenceTranslation: referenceTranslation ? truncateForLog(referenceTranslation) : void 0,
492
+ translation: truncateForLog(translation)
493
+ });
494
+ return translation;
495
+ }
496
+ getEmployeeSystemPrompt(employee) {
497
+ var _a, _b;
498
+ 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) || "";
499
+ }
500
+ buildProviderContext(options) {
501
+ const { systemPrompt, sourceText, targetLang, referenceTranslation } = options;
502
+ const prompt = (systemPrompt || "").trim();
503
+ const reference = referenceTranslation ? `Refer to the following translation:
504
+ ${sourceText} is translated as ${referenceTranslation}
505
+
506
+ ` : "";
507
+ const task = `Translate the following text into ${targetLang}. Output only the translated result without any additional explanation:
508
+ ${sourceText}
509
+ `;
510
+ const content = [prompt, `${reference}${task}`].filter(Boolean).join("\n\n");
511
+ return {
512
+ messages: [new import_messages.HumanMessage(content)]
513
+ };
514
+ }
515
+ getLanguageName(locale) {
516
+ const normalized = locale.replace("_", "-");
517
+ const map = {
518
+ "en-US": "English",
519
+ "zh-CN": "Chinese",
520
+ "zh-TW": "Traditional Chinese",
521
+ "ja-JP": "Japanese",
522
+ "ko-KR": "Korean",
523
+ "fr-FR": "French",
524
+ "de-DE": "German",
525
+ "es-ES": "Spanish",
526
+ "it-IT": "Italian",
527
+ "pt-PT": "Portuguese",
528
+ "pt-BR": "Portuguese",
529
+ "ru-RU": "Russian",
530
+ "th-TH": "Thai",
531
+ "vi-VN": "Vietnamese",
532
+ "id-ID": "Indonesian",
533
+ "ms-MY": "Malay",
534
+ "ar-SA": "Arabic",
535
+ "hi-IN": "Hindi",
536
+ "tr-TR": "Turkish",
537
+ "nl-NL": "Dutch",
538
+ "pl-PL": "Polish",
539
+ "sv-SE": "Swedish",
540
+ "da-DK": "Danish",
541
+ "fi-FI": "Finnish",
542
+ "uk-UA": "Ukrainian"
543
+ };
544
+ if (map[normalized]) {
545
+ return map[normalized];
546
+ }
547
+ const language = normalized.split("-")[0];
548
+ const languageMap = {
549
+ en: "English",
550
+ zh: "Chinese",
551
+ ja: "Japanese",
552
+ ko: "Korean",
553
+ fr: "French",
554
+ de: "German",
555
+ es: "Spanish",
556
+ it: "Italian",
557
+ pt: "Portuguese",
558
+ ru: "Russian",
559
+ th: "Thai",
560
+ vi: "Vietnamese",
561
+ id: "Indonesian",
562
+ ms: "Malay",
563
+ ar: "Arabic",
564
+ hi: "Hindi",
565
+ tr: "Turkish",
566
+ nl: "Dutch",
567
+ pl: "Polish",
568
+ sv: "Swedish",
569
+ da: "Danish",
570
+ fi: "Finnish",
571
+ uk: "Ukrainian"
572
+ };
573
+ return languageMap[language] || language;
574
+ }
575
+ extractTextContent(content) {
576
+ if (typeof content === "string") {
577
+ return content;
578
+ }
579
+ if (Array.isArray(content)) {
580
+ return content.map((item) => {
581
+ if (typeof item === "string") {
582
+ return item;
583
+ }
584
+ if (item && typeof item === "object") {
585
+ if ("type" in item && item.type === "text") {
586
+ return typeof item.text === "string" ? item.text : "";
587
+ }
588
+ if ("content" in item) {
589
+ return this.extractTextContent(item.content);
590
+ }
591
+ }
592
+ return "";
593
+ }).join("").trim();
594
+ }
595
+ if (content && typeof content === "object" && "content" in content) {
596
+ return this.extractTextContent(content.content);
597
+ }
598
+ return "";
599
+ }
600
+ }
601
+ // Annotate the CommonJS export names for ESM import in node:
602
+ 0 && (module.exports = {
603
+ LOCALIZATION_AI_TRANSLATE_TASK_TYPE,
604
+ LocalizationAITranslateTask,
605
+ pickBuiltInResourceReference
606
+ });
@@ -0,0 +1,31 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ export type TranslationScope = 'all' | 'builtIn' | 'custom';
10
+ export type LocalizationTextRecord = {
11
+ id: string | number;
12
+ text: string;
13
+ module?: string;
14
+ translation?: string;
15
+ translationId?: string | number;
16
+ };
17
+ type BuildFindTextsOptions = {
18
+ app: any;
19
+ mode: string;
20
+ locale: string;
21
+ scope: TranslationScope;
22
+ textIds?: Array<string | number>;
23
+ fields?: string[];
24
+ sort?: string[];
25
+ };
26
+ export declare const normalizeTextRecord: (row: any) => LocalizationTextRecord | undefined;
27
+ export declare const getModuleName: (row: LocalizationTextRecord) => string;
28
+ export declare const normalizeModuleName: (module: string) => string;
29
+ export declare const isBuiltInText: (row: LocalizationTextRecord, resources: Record<string, Record<string, string>>) => boolean;
30
+ export declare const buildFindTextsOptions: (options: BuildFindTextsOptions) => Promise<any>;
31
+ export {};