@nocobase/plugin-localization 2.1.0-alpha.4 → 2.1.0-alpha.45

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/LICENSE +201 -661
  2. package/README.md +79 -10
  3. package/client-v2.d.ts +2 -0
  4. package/client-v2.js +1 -0
  5. package/dist/ai/ai-employees/lina.d.ts +10 -0
  6. package/dist/ai/ai-employees/lina.js +60 -0
  7. package/dist/client/300.1f79b801d226f40d.js +10 -0
  8. package/dist/client/i18n-missing-handler.d.ts +1 -17
  9. package/dist/client/index.js +1 -1
  10. package/dist/client-v2/796.0ec484505de4b04a.js +10 -0
  11. package/dist/client-v2/common/constants.d.ts +13 -0
  12. package/dist/client-v2/common/i18n-missing-handler.d.ts +23 -0
  13. package/dist/{client/Localization.d.ts → client-v2/i18n-missing-handler.d.ts} +1 -2
  14. package/dist/client-v2/index.d.ts +9 -0
  15. package/dist/client-v2/index.js +10 -0
  16. package/dist/client-v2/locale.d.ts +11 -0
  17. package/dist/client-v2/pages/LocalizationPage.d.ts +11 -0
  18. package/dist/client-v2/plugin.d.ts +13 -0
  19. package/dist/externalVersion.js +18 -13
  20. package/dist/locale/en-US.json +38 -1
  21. package/dist/locale/zh-CN.json +38 -1
  22. package/dist/server/actions/aiTranslate.d.ts +14 -0
  23. package/dist/server/actions/aiTranslate.js +151 -0
  24. package/dist/server/actions/localization.js +30 -15
  25. package/dist/server/actions/localizationTexts.js +8 -9
  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 +8 -3
  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
@@ -42,17 +42,29 @@ __export(plugin_exports, {
42
42
  module.exports = __toCommonJS(plugin_exports);
43
43
  var import_server = require("@nocobase/server");
44
44
  var import_localization = __toESM(require("./actions/localization"));
45
+ var import_aiTranslate = __toESM(require("./actions/aiTranslate"));
45
46
  var import_localizationTexts = __toESM(require("./actions/localizationTexts"));
46
47
  var import_resources = __toESM(require("./resources"));
47
48
  var import_utils = require("./utils");
48
49
  var import_constants = require("./constants");
49
- var import_source_manager = require("./source-manager");
50
50
  var import_utils2 = require("@nocobase/utils");
51
+ var import_localization_ai_translate = require("./tasks/localization-ai-translate");
51
52
  var import_package = __toESM(require("../../package.json"));
52
53
  class PluginLocalizationServer extends import_server.Plugin {
53
54
  resources;
54
- sourceManager = new import_source_manager.SourceManager();
55
+ aiTranslateTaskRegistered = false;
56
+ localeSourceTextHookKeys = /* @__PURE__ */ new Set();
57
+ normalizeResourceModule(module2) {
58
+ const prefix = "resources.";
59
+ const namespace = module2.startsWith(prefix) ? module2.slice(prefix.length) : module2;
60
+ const normalizedNamespace = namespace.startsWith(import_server.OFFICIAL_PLUGIN_PREFIX) ? namespace.replace(import_server.OFFICIAL_PLUGIN_PREFIX, "") : namespace;
61
+ return `${prefix}${normalizedNamespace}`;
62
+ }
55
63
  addNewTexts = async (texts, options) => {
64
+ texts = texts.map(({ text, module: module2 }) => ({
65
+ text,
66
+ module: this.normalizeResourceModule(module2)
67
+ }));
56
68
  texts = await this.resources.filterExists(texts, options == null ? void 0 : options.transaction);
57
69
  await this.db.getModel("localizationTexts").bulkCreate(
58
70
  texts.map(({ text, module: module2 }) => ({
@@ -88,23 +100,44 @@ class PluginLocalizationServer extends import_server.Plugin {
88
100
  });
89
101
  };
90
102
  afterAdd() {
91
- this.app.on("afterLoad", () => this.sourceManager.handleTextsSaved(this.db, this.addNewTexts));
103
+ this.app.on("afterLoad", () => this.handleLocaleSourceTextsSaved());
104
+ this.app.on("afterLoad", () => this.registerAITranslateTaskType());
92
105
  }
93
106
  beforeLoad() {
94
107
  }
108
+ registerAITranslateTaskType() {
109
+ if (this.aiTranslateTaskRegistered) {
110
+ return;
111
+ }
112
+ try {
113
+ const taskManager = this.app.container.get("AsyncTaskManager");
114
+ taskManager.registerTaskType(import_localization_ai_translate.LocalizationAITranslateTask);
115
+ this.aiTranslateTaskRegistered = true;
116
+ } catch (error) {
117
+ this.log.warn("AsyncTaskManager is not available, skip localization AI translate task registration.");
118
+ }
119
+ }
95
120
  async load() {
121
+ this.registerAITranslateTaskType();
96
122
  this.app.resourceManager.define({
97
123
  name: "localizationTexts",
98
124
  actions: import_localizationTexts.default
99
125
  });
100
126
  this.app.resourceManager.define({
101
127
  name: "localization",
102
- actions: import_localization.default
128
+ actions: {
129
+ ...import_localization.default,
130
+ ...import_aiTranslate.default
131
+ }
103
132
  });
104
133
  this.app.acl.registerSnippet({
105
134
  name: `pm.${this.name}.localization`,
106
135
  actions: ["localization:*", "localizationTexts:*", "localizationTranslations:*"]
107
136
  });
137
+ this.app.acl.registerSnippet({
138
+ name: "ui.localization",
139
+ actions: ["localizationTexts:missing"]
140
+ });
108
141
  this.app.localeManager.registerResourceStorer("plugin-localization", {
109
142
  getResources: (lang) => this.resources.getResources(lang),
110
143
  reset: () => this.resources.reset()
@@ -115,24 +148,22 @@ class PluginLocalizationServer extends import_server.Plugin {
115
148
  store: "memory"
116
149
  });
117
150
  this.resources = new import_resources.default(this.db, cache);
118
- this.sourceManager.registerSource("local", {
151
+ this.app.localeManager.registerSource("local", {
119
152
  title: (0, import_utils2.tval)("System & Plugins", { ns: import_package.default.name }),
120
153
  sync: async (ctx) => {
121
- const resources = await ctx.app.localeManager.getCacheResources(ctx.get("X-Locale") || "en-US");
154
+ const resources = await ctx.app.localeManager.getBuiltInResources(ctx.get("X-Locale") || "en-US");
122
155
  const result = {};
123
156
  Object.entries(resources).forEach(([module2, resource]) => {
124
- if (module2.startsWith(import_server.OFFICIAL_PLUGIN_PREFIX)) {
125
- const name = module2.replace(import_server.OFFICIAL_PLUGIN_PREFIX, "");
126
- if (resources[name]) {
127
- return;
128
- }
129
- }
130
- result[module2] = resource;
157
+ const name = module2.startsWith(import_server.OFFICIAL_PLUGIN_PREFIX) ? module2.replace(import_server.OFFICIAL_PLUGIN_PREFIX, "") : module2;
158
+ result[name] = {
159
+ ...result[name] || {},
160
+ ...resource
161
+ };
131
162
  });
132
163
  return result;
133
164
  }
134
165
  });
135
- this.sourceManager.registerSource("db", {
166
+ this.app.localeManager.registerSource("db", {
136
167
  title: (0, import_utils2.tval)("Collections & Fields", { ns: import_package.default.name }),
137
168
  namespace: import_constants.NAMESPACE_COLLECTIONS,
138
169
  sync: async (ctx) => {
@@ -181,6 +212,37 @@ class PluginLocalizationServer extends import_server.Plugin {
181
212
  await this.addNewTexts(texts, options);
182
213
  });
183
214
  }
215
+ handleLocaleSourceTextsSaved() {
216
+ for (const [sourceName, source] of this.app.localeManager.sources.getEntities()) {
217
+ if (!source.collections) {
218
+ continue;
219
+ }
220
+ for (const [index, collectionOptions] of source.collections.entries()) {
221
+ const hookKey = `${sourceName}:${index}:${collectionOptions.collection}`;
222
+ if (this.localeSourceTextHookKeys.has(hookKey)) {
223
+ continue;
224
+ }
225
+ this.localeSourceTextHookKeys.add(hookKey);
226
+ this.db.on(`${collectionOptions.collection}.afterSave`, async (instance, options) => {
227
+ let texts = [];
228
+ if (collectionOptions.getTexts) {
229
+ texts = await collectionOptions.getTexts(instance, options);
230
+ } else {
231
+ const fields = collectionOptions.fields || [];
232
+ const changedFields = fields.filter((field) => instance["_changed"].has(field));
233
+ if (!changedFields.length) {
234
+ return;
235
+ }
236
+ texts = changedFields.map((field) => instance.get(field)).filter(Boolean).map((text) => ({ text, module: `resources.${source.namespace}` }));
237
+ }
238
+ if (!(texts == null ? void 0 : texts.length)) {
239
+ return;
240
+ }
241
+ await this.addNewTexts(texts, options);
242
+ });
243
+ }
244
+ }
245
+ }
184
246
  async handleSyncMessage(message) {
185
247
  switch (message.type) {
186
248
  case "updateCacheTexts":
@@ -0,0 +1,48 @@
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
+ import { TaskType } from '@nocobase/plugin-async-task-manager';
10
+ import type { LocalizationTextRecord } from '../translation-scope';
11
+ export declare const LOCALIZATION_AI_TRANSLATE_TASK_TYPE = "localization:ai-translate";
12
+ export declare const pickBuiltInResourceReference: (row: LocalizationTextRecord, references: Map<string, Map<string, string>>, locales: ReferenceLocaleConfig) => {
13
+ locale: string;
14
+ translation: string;
15
+ } | {
16
+ locale?: undefined;
17
+ translation?: undefined;
18
+ };
19
+ type ReferenceLocaleConfig = {
20
+ primary?: string;
21
+ fallback?: string;
22
+ };
23
+ export type TranslationReferenceLocales = {
24
+ builtIn?: ReferenceLocaleConfig;
25
+ custom?: ReferenceLocaleConfig;
26
+ };
27
+ export declare class LocalizationAITranslateTask extends TaskType {
28
+ static type: string;
29
+ execute(): Promise<{
30
+ translated: number;
31
+ total: number;
32
+ }>;
33
+ private countTexts;
34
+ private getLocaleReferences;
35
+ private getReferenceMaps;
36
+ private getBuiltInReferenceMaps;
37
+ private pickDbReference;
38
+ private getSystemDefaultLocale;
39
+ private resolveReferenceLocales;
40
+ private buildTranslationItems;
41
+ private translateItem;
42
+ private translateText;
43
+ private getEmployeeSystemPrompt;
44
+ private buildProviderContext;
45
+ private getLanguageName;
46
+ private extractTextContent;
47
+ }
48
+ export {};