jowork 0.1.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.
@@ -0,0 +1,4031 @@
1
+ // ../../packages/core/src/types/engine.ts
2
+ var ENGINE_CLAUDE_CODE = "claude-code";
3
+ var ENGINE_OPENCLAW = "openclaw";
4
+ var ENGINE_NEMOCLAW = "nemoclaw";
5
+ var ENGINE_CLOUD = "jowork-cloud";
6
+
7
+ // ../../packages/core/src/db/schema.ts
8
+ import { sqliteTable, text, integer, primaryKey } from "drizzle-orm/sqlite-core";
9
+ var sessions = sqliteTable("sessions", {
10
+ id: text("id").primaryKey(),
11
+ title: text("title").notNull(),
12
+ engineId: text("engine_id").notNull(),
13
+ mode: text("mode").notNull().default("personal"),
14
+ messageCount: integer("message_count").default(0),
15
+ createdAt: integer("created_at").notNull(),
16
+ updatedAt: integer("updated_at").notNull()
17
+ });
18
+ var messages = sqliteTable("messages", {
19
+ id: text("id").primaryKey(),
20
+ sessionId: text("session_id").notNull().references(() => sessions.id),
21
+ role: text("role").notNull(),
22
+ content: text("content").notNull(),
23
+ toolName: text("tool_name"),
24
+ tokens: integer("tokens"),
25
+ cost: integer("cost"),
26
+ createdAt: integer("created_at").notNull()
27
+ });
28
+ var engineSessionMappings = sqliteTable("engine_session_mappings", {
29
+ sessionId: text("session_id").notNull().references(() => sessions.id),
30
+ engineId: text("engine_id").notNull(),
31
+ engineSessionId: text("engine_session_id").notNull(),
32
+ createdAt: integer("created_at").notNull()
33
+ }, (t2) => [primaryKey({ columns: [t2.sessionId, t2.engineId] })]);
34
+ var settings = sqliteTable("settings", {
35
+ key: text("key").primaryKey(),
36
+ value: text("value").notNull(),
37
+ updatedAt: integer("updated_at").notNull()
38
+ });
39
+ var connectorConfigs = sqliteTable("connector_configs", {
40
+ id: text("id").primaryKey(),
41
+ type: text("type").notNull(),
42
+ name: text("name").notNull(),
43
+ status: text("status").notNull().default("disconnected"),
44
+ config: text("config").notNull().default("{}"),
45
+ lastSyncAt: integer("last_sync_at"),
46
+ createdAt: integer("created_at").notNull(),
47
+ updatedAt: integer("updated_at").notNull()
48
+ });
49
+ var objects = sqliteTable("objects", {
50
+ id: text("id").primaryKey(),
51
+ source: text("source").notNull(),
52
+ sourceType: text("source_type").notNull(),
53
+ uri: text("uri").notNull().unique(),
54
+ title: text("title"),
55
+ summary: text("summary"),
56
+ tags: text("tags"),
57
+ docMap: text("doc_map"),
58
+ contentHash: text("content_hash"),
59
+ lastSyncedAt: integer("last_synced_at"),
60
+ createdAt: integer("created_at")
61
+ });
62
+ var objectBodies = sqliteTable("object_bodies", {
63
+ objectId: text("object_id").primaryKey().references(() => objects.id),
64
+ content: text("content").notNull(),
65
+ contentType: text("content_type"),
66
+ fetchedAt: integer("fetched_at")
67
+ });
68
+ var syncCursors = sqliteTable("sync_cursors", {
69
+ connectorId: text("connector_id").primaryKey(),
70
+ cursor: text("cursor"),
71
+ lastSyncedAt: integer("last_synced_at")
72
+ });
73
+ var objectChunks = sqliteTable("object_chunks", {
74
+ id: text("id").primaryKey(),
75
+ objectId: text("object_id").notNull().references(() => objects.id),
76
+ idx: integer("idx").notNull(),
77
+ heading: text("heading"),
78
+ content: text("content").notNull(),
79
+ tokens: integer("tokens")
80
+ });
81
+ var memories = sqliteTable("memories", {
82
+ id: text("id").primaryKey(),
83
+ title: text("title").notNull(),
84
+ content: text("content").notNull(),
85
+ tags: text("tags"),
86
+ scope: text("scope").notNull(),
87
+ pinned: integer("pinned").default(0),
88
+ source: text("source"),
89
+ accessCount: integer("access_count").notNull().default(0),
90
+ lastUsedAt: integer("last_used_at"),
91
+ createdAt: integer("created_at").notNull(),
92
+ updatedAt: integer("updated_at").notNull()
93
+ });
94
+ var contextDocs = sqliteTable("context_docs", {
95
+ id: text("id").primaryKey(),
96
+ title: text("title").notNull(),
97
+ content: text("content").notNull(),
98
+ scope: text("scope").notNull(),
99
+ category: text("category"),
100
+ priority: integer("priority").default(0),
101
+ createdAt: integer("created_at").notNull(),
102
+ updatedAt: integer("updated_at").notNull()
103
+ });
104
+ var scheduledTasks = sqliteTable("scheduled_tasks", {
105
+ id: text("id").primaryKey(),
106
+ name: text("name").notNull(),
107
+ cronExpression: text("cron_expression").notNull(),
108
+ timezone: text("timezone").default("Asia/Shanghai"),
109
+ type: text("type").notNull(),
110
+ // 'scan' | 'skill' | 'notify'
111
+ config: text("config"),
112
+ // JSON
113
+ enabled: integer("enabled").default(1),
114
+ lastRunAt: integer("last_run_at"),
115
+ nextRunAt: integer("next_run_at"),
116
+ cloudSync: integer("cloud_sync").default(0),
117
+ createdAt: integer("created_at").notNull()
118
+ });
119
+ var taskExecutions = sqliteTable("task_executions", {
120
+ id: text("id").primaryKey(),
121
+ taskId: text("task_id").notNull().references(() => scheduledTasks.id),
122
+ status: text("status").notNull(),
123
+ // 'success' | 'failure' | 'skipped'
124
+ result: text("result"),
125
+ error: text("error"),
126
+ durationMs: integer("duration_ms"),
127
+ executedAt: integer("executed_at").notNull()
128
+ });
129
+
130
+ // ../../packages/core/src/db/migrate.ts
131
+ async function runMigrations(_dbPath) {
132
+ }
133
+
134
+ // ../../node_modules/.pnpm/i18next@25.8.18_typescript@5.9.3/node_modules/i18next/dist/esm/i18next.js
135
+ var isString = (obj) => typeof obj === "string";
136
+ var defer = () => {
137
+ let res;
138
+ let rej;
139
+ const promise = new Promise((resolve, reject) => {
140
+ res = resolve;
141
+ rej = reject;
142
+ });
143
+ promise.resolve = res;
144
+ promise.reject = rej;
145
+ return promise;
146
+ };
147
+ var makeString = (object) => {
148
+ if (object == null) return "";
149
+ return "" + object;
150
+ };
151
+ var copy = (a, s, t2) => {
152
+ a.forEach((m) => {
153
+ if (s[m]) t2[m] = s[m];
154
+ });
155
+ };
156
+ var lastOfPathSeparatorRegExp = /###/g;
157
+ var cleanKey = (key) => key && key.indexOf("###") > -1 ? key.replace(lastOfPathSeparatorRegExp, ".") : key;
158
+ var canNotTraverseDeeper = (object) => !object || isString(object);
159
+ var getLastOfPath = (object, path, Empty) => {
160
+ const stack = !isString(path) ? path : path.split(".");
161
+ let stackIndex = 0;
162
+ while (stackIndex < stack.length - 1) {
163
+ if (canNotTraverseDeeper(object)) return {};
164
+ const key = cleanKey(stack[stackIndex]);
165
+ if (!object[key] && Empty) object[key] = new Empty();
166
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
167
+ object = object[key];
168
+ } else {
169
+ object = {};
170
+ }
171
+ ++stackIndex;
172
+ }
173
+ if (canNotTraverseDeeper(object)) return {};
174
+ return {
175
+ obj: object,
176
+ k: cleanKey(stack[stackIndex])
177
+ };
178
+ };
179
+ var setPath = (object, path, newValue) => {
180
+ const {
181
+ obj,
182
+ k
183
+ } = getLastOfPath(object, path, Object);
184
+ if (obj !== void 0 || path.length === 1) {
185
+ obj[k] = newValue;
186
+ return;
187
+ }
188
+ let e = path[path.length - 1];
189
+ let p = path.slice(0, path.length - 1);
190
+ let last = getLastOfPath(object, p, Object);
191
+ while (last.obj === void 0 && p.length) {
192
+ e = `${p[p.length - 1]}.${e}`;
193
+ p = p.slice(0, p.length - 1);
194
+ last = getLastOfPath(object, p, Object);
195
+ if (last?.obj && typeof last.obj[`${last.k}.${e}`] !== "undefined") {
196
+ last.obj = void 0;
197
+ }
198
+ }
199
+ last.obj[`${last.k}.${e}`] = newValue;
200
+ };
201
+ var pushPath = (object, path, newValue, concat) => {
202
+ const {
203
+ obj,
204
+ k
205
+ } = getLastOfPath(object, path, Object);
206
+ obj[k] = obj[k] || [];
207
+ obj[k].push(newValue);
208
+ };
209
+ var getPath = (object, path) => {
210
+ const {
211
+ obj,
212
+ k
213
+ } = getLastOfPath(object, path);
214
+ if (!obj) return void 0;
215
+ if (!Object.prototype.hasOwnProperty.call(obj, k)) return void 0;
216
+ return obj[k];
217
+ };
218
+ var getPathWithDefaults = (data, defaultData, key) => {
219
+ const value = getPath(data, key);
220
+ if (value !== void 0) {
221
+ return value;
222
+ }
223
+ return getPath(defaultData, key);
224
+ };
225
+ var deepExtend = (target, source, overwrite) => {
226
+ for (const prop in source) {
227
+ if (prop !== "__proto__" && prop !== "constructor") {
228
+ if (prop in target) {
229
+ if (isString(target[prop]) || target[prop] instanceof String || isString(source[prop]) || source[prop] instanceof String) {
230
+ if (overwrite) target[prop] = source[prop];
231
+ } else {
232
+ deepExtend(target[prop], source[prop], overwrite);
233
+ }
234
+ } else {
235
+ target[prop] = source[prop];
236
+ }
237
+ }
238
+ }
239
+ return target;
240
+ };
241
+ var regexEscape = (str) => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
242
+ var _entityMap = {
243
+ "&": "&amp;",
244
+ "<": "&lt;",
245
+ ">": "&gt;",
246
+ '"': "&quot;",
247
+ "'": "&#39;",
248
+ "/": "&#x2F;"
249
+ };
250
+ var escape = (data) => {
251
+ if (isString(data)) {
252
+ return data.replace(/[&<>"'\/]/g, (s) => _entityMap[s]);
253
+ }
254
+ return data;
255
+ };
256
+ var RegExpCache = class {
257
+ constructor(capacity) {
258
+ this.capacity = capacity;
259
+ this.regExpMap = /* @__PURE__ */ new Map();
260
+ this.regExpQueue = [];
261
+ }
262
+ getRegExp(pattern) {
263
+ const regExpFromCache = this.regExpMap.get(pattern);
264
+ if (regExpFromCache !== void 0) {
265
+ return regExpFromCache;
266
+ }
267
+ const regExpNew = new RegExp(pattern);
268
+ if (this.regExpQueue.length === this.capacity) {
269
+ this.regExpMap.delete(this.regExpQueue.shift());
270
+ }
271
+ this.regExpMap.set(pattern, regExpNew);
272
+ this.regExpQueue.push(pattern);
273
+ return regExpNew;
274
+ }
275
+ };
276
+ var chars = [" ", ",", "?", "!", ";"];
277
+ var looksLikeObjectPathRegExpCache = new RegExpCache(20);
278
+ var looksLikeObjectPath = (key, nsSeparator, keySeparator) => {
279
+ nsSeparator = nsSeparator || "";
280
+ keySeparator = keySeparator || "";
281
+ const possibleChars = chars.filter((c) => nsSeparator.indexOf(c) < 0 && keySeparator.indexOf(c) < 0);
282
+ if (possibleChars.length === 0) return true;
283
+ const r = looksLikeObjectPathRegExpCache.getRegExp(`(${possibleChars.map((c) => c === "?" ? "\\?" : c).join("|")})`);
284
+ let matched = !r.test(key);
285
+ if (!matched) {
286
+ const ki = key.indexOf(keySeparator);
287
+ if (ki > 0 && !r.test(key.substring(0, ki))) {
288
+ matched = true;
289
+ }
290
+ }
291
+ return matched;
292
+ };
293
+ var deepFind = (obj, path, keySeparator = ".") => {
294
+ if (!obj) return void 0;
295
+ if (obj[path]) {
296
+ if (!Object.prototype.hasOwnProperty.call(obj, path)) return void 0;
297
+ return obj[path];
298
+ }
299
+ const tokens = path.split(keySeparator);
300
+ let current = obj;
301
+ for (let i = 0; i < tokens.length; ) {
302
+ if (!current || typeof current !== "object") {
303
+ return void 0;
304
+ }
305
+ let next;
306
+ let nextPath = "";
307
+ for (let j = i; j < tokens.length; ++j) {
308
+ if (j !== i) {
309
+ nextPath += keySeparator;
310
+ }
311
+ nextPath += tokens[j];
312
+ next = current[nextPath];
313
+ if (next !== void 0) {
314
+ if (["string", "number", "boolean"].indexOf(typeof next) > -1 && j < tokens.length - 1) {
315
+ continue;
316
+ }
317
+ i += j - i + 1;
318
+ break;
319
+ }
320
+ }
321
+ current = next;
322
+ }
323
+ return current;
324
+ };
325
+ var getCleanedCode = (code) => code?.replace(/_/g, "-");
326
+ var consoleLogger = {
327
+ type: "logger",
328
+ log(args) {
329
+ this.output("log", args);
330
+ },
331
+ warn(args) {
332
+ this.output("warn", args);
333
+ },
334
+ error(args) {
335
+ this.output("error", args);
336
+ },
337
+ output(type, args) {
338
+ console?.[type]?.apply?.(console, args);
339
+ }
340
+ };
341
+ var Logger = class _Logger {
342
+ constructor(concreteLogger, options = {}) {
343
+ this.init(concreteLogger, options);
344
+ }
345
+ init(concreteLogger, options = {}) {
346
+ this.prefix = options.prefix || "i18next:";
347
+ this.logger = concreteLogger || consoleLogger;
348
+ this.options = options;
349
+ this.debug = options.debug;
350
+ }
351
+ log(...args) {
352
+ return this.forward(args, "log", "", true);
353
+ }
354
+ warn(...args) {
355
+ return this.forward(args, "warn", "", true);
356
+ }
357
+ error(...args) {
358
+ return this.forward(args, "error", "");
359
+ }
360
+ deprecate(...args) {
361
+ return this.forward(args, "warn", "WARNING DEPRECATED: ", true);
362
+ }
363
+ forward(args, lvl, prefix, debugOnly) {
364
+ if (debugOnly && !this.debug) return null;
365
+ if (isString(args[0])) args[0] = `${prefix}${this.prefix} ${args[0]}`;
366
+ return this.logger[lvl](args);
367
+ }
368
+ create(moduleName) {
369
+ return new _Logger(this.logger, {
370
+ ...{
371
+ prefix: `${this.prefix}:${moduleName}:`
372
+ },
373
+ ...this.options
374
+ });
375
+ }
376
+ clone(options) {
377
+ options = options || this.options;
378
+ options.prefix = options.prefix || this.prefix;
379
+ return new _Logger(this.logger, options);
380
+ }
381
+ };
382
+ var baseLogger = new Logger();
383
+ var EventEmitter = class {
384
+ constructor() {
385
+ this.observers = {};
386
+ }
387
+ on(events, listener) {
388
+ events.split(" ").forEach((event) => {
389
+ if (!this.observers[event]) this.observers[event] = /* @__PURE__ */ new Map();
390
+ const numListeners = this.observers[event].get(listener) || 0;
391
+ this.observers[event].set(listener, numListeners + 1);
392
+ });
393
+ return this;
394
+ }
395
+ off(event, listener) {
396
+ if (!this.observers[event]) return;
397
+ if (!listener) {
398
+ delete this.observers[event];
399
+ return;
400
+ }
401
+ this.observers[event].delete(listener);
402
+ }
403
+ emit(event, ...args) {
404
+ if (this.observers[event]) {
405
+ const cloned = Array.from(this.observers[event].entries());
406
+ cloned.forEach(([observer, numTimesAdded]) => {
407
+ for (let i = 0; i < numTimesAdded; i++) {
408
+ observer(...args);
409
+ }
410
+ });
411
+ }
412
+ if (this.observers["*"]) {
413
+ const cloned = Array.from(this.observers["*"].entries());
414
+ cloned.forEach(([observer, numTimesAdded]) => {
415
+ for (let i = 0; i < numTimesAdded; i++) {
416
+ observer.apply(observer, [event, ...args]);
417
+ }
418
+ });
419
+ }
420
+ }
421
+ };
422
+ var ResourceStore = class extends EventEmitter {
423
+ constructor(data, options = {
424
+ ns: ["translation"],
425
+ defaultNS: "translation"
426
+ }) {
427
+ super();
428
+ this.data = data || {};
429
+ this.options = options;
430
+ if (this.options.keySeparator === void 0) {
431
+ this.options.keySeparator = ".";
432
+ }
433
+ if (this.options.ignoreJSONStructure === void 0) {
434
+ this.options.ignoreJSONStructure = true;
435
+ }
436
+ }
437
+ addNamespaces(ns) {
438
+ if (this.options.ns.indexOf(ns) < 0) {
439
+ this.options.ns.push(ns);
440
+ }
441
+ }
442
+ removeNamespaces(ns) {
443
+ const index = this.options.ns.indexOf(ns);
444
+ if (index > -1) {
445
+ this.options.ns.splice(index, 1);
446
+ }
447
+ }
448
+ getResource(lng, ns, key, options = {}) {
449
+ const keySeparator = options.keySeparator !== void 0 ? options.keySeparator : this.options.keySeparator;
450
+ const ignoreJSONStructure = options.ignoreJSONStructure !== void 0 ? options.ignoreJSONStructure : this.options.ignoreJSONStructure;
451
+ let path;
452
+ if (lng.indexOf(".") > -1) {
453
+ path = lng.split(".");
454
+ } else {
455
+ path = [lng, ns];
456
+ if (key) {
457
+ if (Array.isArray(key)) {
458
+ path.push(...key);
459
+ } else if (isString(key) && keySeparator) {
460
+ path.push(...key.split(keySeparator));
461
+ } else {
462
+ path.push(key);
463
+ }
464
+ }
465
+ }
466
+ const result = getPath(this.data, path);
467
+ if (!result && !ns && !key && lng.indexOf(".") > -1) {
468
+ lng = path[0];
469
+ ns = path[1];
470
+ key = path.slice(2).join(".");
471
+ }
472
+ if (result || !ignoreJSONStructure || !isString(key)) return result;
473
+ return deepFind(this.data?.[lng]?.[ns], key, keySeparator);
474
+ }
475
+ addResource(lng, ns, key, value, options = {
476
+ silent: false
477
+ }) {
478
+ const keySeparator = options.keySeparator !== void 0 ? options.keySeparator : this.options.keySeparator;
479
+ let path = [lng, ns];
480
+ if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key);
481
+ if (lng.indexOf(".") > -1) {
482
+ path = lng.split(".");
483
+ value = ns;
484
+ ns = path[1];
485
+ }
486
+ this.addNamespaces(ns);
487
+ setPath(this.data, path, value);
488
+ if (!options.silent) this.emit("added", lng, ns, key, value);
489
+ }
490
+ addResources(lng, ns, resources, options = {
491
+ silent: false
492
+ }) {
493
+ for (const m in resources) {
494
+ if (isString(resources[m]) || Array.isArray(resources[m])) this.addResource(lng, ns, m, resources[m], {
495
+ silent: true
496
+ });
497
+ }
498
+ if (!options.silent) this.emit("added", lng, ns, resources);
499
+ }
500
+ addResourceBundle(lng, ns, resources, deep, overwrite, options = {
501
+ silent: false,
502
+ skipCopy: false
503
+ }) {
504
+ let path = [lng, ns];
505
+ if (lng.indexOf(".") > -1) {
506
+ path = lng.split(".");
507
+ deep = resources;
508
+ resources = ns;
509
+ ns = path[1];
510
+ }
511
+ this.addNamespaces(ns);
512
+ let pack = getPath(this.data, path) || {};
513
+ if (!options.skipCopy) resources = JSON.parse(JSON.stringify(resources));
514
+ if (deep) {
515
+ deepExtend(pack, resources, overwrite);
516
+ } else {
517
+ pack = {
518
+ ...pack,
519
+ ...resources
520
+ };
521
+ }
522
+ setPath(this.data, path, pack);
523
+ if (!options.silent) this.emit("added", lng, ns, resources);
524
+ }
525
+ removeResourceBundle(lng, ns) {
526
+ if (this.hasResourceBundle(lng, ns)) {
527
+ delete this.data[lng][ns];
528
+ }
529
+ this.removeNamespaces(ns);
530
+ this.emit("removed", lng, ns);
531
+ }
532
+ hasResourceBundle(lng, ns) {
533
+ return this.getResource(lng, ns) !== void 0;
534
+ }
535
+ getResourceBundle(lng, ns) {
536
+ if (!ns) ns = this.options.defaultNS;
537
+ return this.getResource(lng, ns);
538
+ }
539
+ getDataByLanguage(lng) {
540
+ return this.data[lng];
541
+ }
542
+ hasLanguageSomeTranslations(lng) {
543
+ const data = this.getDataByLanguage(lng);
544
+ const n = data && Object.keys(data) || [];
545
+ return !!n.find((v) => data[v] && Object.keys(data[v]).length > 0);
546
+ }
547
+ toJSON() {
548
+ return this.data;
549
+ }
550
+ };
551
+ var postProcessor = {
552
+ processors: {},
553
+ addPostProcessor(module) {
554
+ this.processors[module.name] = module;
555
+ },
556
+ handle(processors, value, key, options, translator) {
557
+ processors.forEach((processor) => {
558
+ value = this.processors[processor]?.process(value, key, options, translator) ?? value;
559
+ });
560
+ return value;
561
+ }
562
+ };
563
+ var PATH_KEY = /* @__PURE__ */ Symbol("i18next/PATH_KEY");
564
+ function createProxy() {
565
+ const state = [];
566
+ const handler = /* @__PURE__ */ Object.create(null);
567
+ let proxy;
568
+ handler.get = (target, key) => {
569
+ proxy?.revoke?.();
570
+ if (key === PATH_KEY) return state;
571
+ state.push(key);
572
+ proxy = Proxy.revocable(target, handler);
573
+ return proxy.proxy;
574
+ };
575
+ return Proxy.revocable(/* @__PURE__ */ Object.create(null), handler).proxy;
576
+ }
577
+ function keysFromSelector(selector, opts) {
578
+ const {
579
+ [PATH_KEY]: path
580
+ } = selector(createProxy());
581
+ const keySeparator = opts?.keySeparator ?? ".";
582
+ const nsSeparator = opts?.nsSeparator ?? ":";
583
+ if (path.length > 1 && nsSeparator) {
584
+ const ns = opts?.ns;
585
+ const namespaces = ns ? Array.isArray(ns) ? ns : [ns] : [];
586
+ if (namespaces.includes(path[0])) {
587
+ return `${path[0]}${nsSeparator}${path.slice(1).join(keySeparator)}`;
588
+ }
589
+ }
590
+ return path.join(keySeparator);
591
+ }
592
+ var checkedLoadedFor = {};
593
+ var shouldHandleAsObject = (res) => !isString(res) && typeof res !== "boolean" && typeof res !== "number";
594
+ var Translator = class _Translator extends EventEmitter {
595
+ constructor(services, options = {}) {
596
+ super();
597
+ copy(["resourceStore", "languageUtils", "pluralResolver", "interpolator", "backendConnector", "i18nFormat", "utils"], services, this);
598
+ this.options = options;
599
+ if (this.options.keySeparator === void 0) {
600
+ this.options.keySeparator = ".";
601
+ }
602
+ this.logger = baseLogger.create("translator");
603
+ }
604
+ changeLanguage(lng) {
605
+ if (lng) this.language = lng;
606
+ }
607
+ exists(key, o = {
608
+ interpolation: {}
609
+ }) {
610
+ const opt = {
611
+ ...o
612
+ };
613
+ if (key == null) return false;
614
+ const resolved = this.resolve(key, opt);
615
+ if (resolved?.res === void 0) return false;
616
+ const isObject = shouldHandleAsObject(resolved.res);
617
+ if (opt.returnObjects === false && isObject) {
618
+ return false;
619
+ }
620
+ return true;
621
+ }
622
+ extractFromKey(key, opt) {
623
+ let nsSeparator = opt.nsSeparator !== void 0 ? opt.nsSeparator : this.options.nsSeparator;
624
+ if (nsSeparator === void 0) nsSeparator = ":";
625
+ const keySeparator = opt.keySeparator !== void 0 ? opt.keySeparator : this.options.keySeparator;
626
+ let namespaces = opt.ns || this.options.defaultNS || [];
627
+ const wouldCheckForNsInKey = nsSeparator && key.indexOf(nsSeparator) > -1;
628
+ const seemsNaturalLanguage = !this.options.userDefinedKeySeparator && !opt.keySeparator && !this.options.userDefinedNsSeparator && !opt.nsSeparator && !looksLikeObjectPath(key, nsSeparator, keySeparator);
629
+ if (wouldCheckForNsInKey && !seemsNaturalLanguage) {
630
+ const m = key.match(this.interpolator.nestingRegexp);
631
+ if (m && m.length > 0) {
632
+ return {
633
+ key,
634
+ namespaces: isString(namespaces) ? [namespaces] : namespaces
635
+ };
636
+ }
637
+ const parts = key.split(nsSeparator);
638
+ if (nsSeparator !== keySeparator || nsSeparator === keySeparator && this.options.ns.indexOf(parts[0]) > -1) namespaces = parts.shift();
639
+ key = parts.join(keySeparator);
640
+ }
641
+ return {
642
+ key,
643
+ namespaces: isString(namespaces) ? [namespaces] : namespaces
644
+ };
645
+ }
646
+ translate(keys, o, lastKey) {
647
+ let opt = typeof o === "object" ? {
648
+ ...o
649
+ } : o;
650
+ if (typeof opt !== "object" && this.options.overloadTranslationOptionHandler) {
651
+ opt = this.options.overloadTranslationOptionHandler(arguments);
652
+ }
653
+ if (typeof opt === "object") opt = {
654
+ ...opt
655
+ };
656
+ if (!opt) opt = {};
657
+ if (keys == null) return "";
658
+ if (typeof keys === "function") keys = keysFromSelector(keys, {
659
+ ...this.options,
660
+ ...opt
661
+ });
662
+ if (!Array.isArray(keys)) keys = [String(keys)];
663
+ keys = keys.map((k) => typeof k === "function" ? keysFromSelector(k, {
664
+ ...this.options,
665
+ ...opt
666
+ }) : String(k));
667
+ const returnDetails = opt.returnDetails !== void 0 ? opt.returnDetails : this.options.returnDetails;
668
+ const keySeparator = opt.keySeparator !== void 0 ? opt.keySeparator : this.options.keySeparator;
669
+ const {
670
+ key,
671
+ namespaces
672
+ } = this.extractFromKey(keys[keys.length - 1], opt);
673
+ const namespace = namespaces[namespaces.length - 1];
674
+ let nsSeparator = opt.nsSeparator !== void 0 ? opt.nsSeparator : this.options.nsSeparator;
675
+ if (nsSeparator === void 0) nsSeparator = ":";
676
+ const lng = opt.lng || this.language;
677
+ const appendNamespaceToCIMode = opt.appendNamespaceToCIMode || this.options.appendNamespaceToCIMode;
678
+ if (lng?.toLowerCase() === "cimode") {
679
+ if (appendNamespaceToCIMode) {
680
+ if (returnDetails) {
681
+ return {
682
+ res: `${namespace}${nsSeparator}${key}`,
683
+ usedKey: key,
684
+ exactUsedKey: key,
685
+ usedLng: lng,
686
+ usedNS: namespace,
687
+ usedParams: this.getUsedParamsDetails(opt)
688
+ };
689
+ }
690
+ return `${namespace}${nsSeparator}${key}`;
691
+ }
692
+ if (returnDetails) {
693
+ return {
694
+ res: key,
695
+ usedKey: key,
696
+ exactUsedKey: key,
697
+ usedLng: lng,
698
+ usedNS: namespace,
699
+ usedParams: this.getUsedParamsDetails(opt)
700
+ };
701
+ }
702
+ return key;
703
+ }
704
+ const resolved = this.resolve(keys, opt);
705
+ let res = resolved?.res;
706
+ const resUsedKey = resolved?.usedKey || key;
707
+ const resExactUsedKey = resolved?.exactUsedKey || key;
708
+ const noObject = ["[object Number]", "[object Function]", "[object RegExp]"];
709
+ const joinArrays = opt.joinArrays !== void 0 ? opt.joinArrays : this.options.joinArrays;
710
+ const handleAsObjectInI18nFormat = !this.i18nFormat || this.i18nFormat.handleAsObject;
711
+ const needsPluralHandling = opt.count !== void 0 && !isString(opt.count);
712
+ const hasDefaultValue = _Translator.hasDefaultValue(opt);
713
+ const defaultValueSuffix = needsPluralHandling ? this.pluralResolver.getSuffix(lng, opt.count, opt) : "";
714
+ const defaultValueSuffixOrdinalFallback = opt.ordinal && needsPluralHandling ? this.pluralResolver.getSuffix(lng, opt.count, {
715
+ ordinal: false
716
+ }) : "";
717
+ const needsZeroSuffixLookup = needsPluralHandling && !opt.ordinal && opt.count === 0;
718
+ const defaultValue = needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] || opt[`defaultValue${defaultValueSuffix}`] || opt[`defaultValue${defaultValueSuffixOrdinalFallback}`] || opt.defaultValue;
719
+ let resForObjHndl = res;
720
+ if (handleAsObjectInI18nFormat && !res && hasDefaultValue) {
721
+ resForObjHndl = defaultValue;
722
+ }
723
+ const handleAsObject = shouldHandleAsObject(resForObjHndl);
724
+ const resType = Object.prototype.toString.apply(resForObjHndl);
725
+ if (handleAsObjectInI18nFormat && resForObjHndl && handleAsObject && noObject.indexOf(resType) < 0 && !(isString(joinArrays) && Array.isArray(resForObjHndl))) {
726
+ if (!opt.returnObjects && !this.options.returnObjects) {
727
+ if (!this.options.returnedObjectHandler) {
728
+ this.logger.warn("accessing an object - but returnObjects options is not enabled!");
729
+ }
730
+ const r = this.options.returnedObjectHandler ? this.options.returnedObjectHandler(resUsedKey, resForObjHndl, {
731
+ ...opt,
732
+ ns: namespaces
733
+ }) : `key '${key} (${this.language})' returned an object instead of string.`;
734
+ if (returnDetails) {
735
+ resolved.res = r;
736
+ resolved.usedParams = this.getUsedParamsDetails(opt);
737
+ return resolved;
738
+ }
739
+ return r;
740
+ }
741
+ if (keySeparator) {
742
+ const resTypeIsArray = Array.isArray(resForObjHndl);
743
+ const copy2 = resTypeIsArray ? [] : {};
744
+ const newKeyToUse = resTypeIsArray ? resExactUsedKey : resUsedKey;
745
+ for (const m in resForObjHndl) {
746
+ if (Object.prototype.hasOwnProperty.call(resForObjHndl, m)) {
747
+ const deepKey = `${newKeyToUse}${keySeparator}${m}`;
748
+ if (hasDefaultValue && !res) {
749
+ copy2[m] = this.translate(deepKey, {
750
+ ...opt,
751
+ defaultValue: shouldHandleAsObject(defaultValue) ? defaultValue[m] : void 0,
752
+ ...{
753
+ joinArrays: false,
754
+ ns: namespaces
755
+ }
756
+ });
757
+ } else {
758
+ copy2[m] = this.translate(deepKey, {
759
+ ...opt,
760
+ ...{
761
+ joinArrays: false,
762
+ ns: namespaces
763
+ }
764
+ });
765
+ }
766
+ if (copy2[m] === deepKey) copy2[m] = resForObjHndl[m];
767
+ }
768
+ }
769
+ res = copy2;
770
+ }
771
+ } else if (handleAsObjectInI18nFormat && isString(joinArrays) && Array.isArray(res)) {
772
+ res = res.join(joinArrays);
773
+ if (res) res = this.extendTranslation(res, keys, opt, lastKey);
774
+ } else {
775
+ let usedDefault = false;
776
+ let usedKey = false;
777
+ if (!this.isValidLookup(res) && hasDefaultValue) {
778
+ usedDefault = true;
779
+ res = defaultValue;
780
+ }
781
+ if (!this.isValidLookup(res)) {
782
+ usedKey = true;
783
+ res = key;
784
+ }
785
+ const missingKeyNoValueFallbackToKey = opt.missingKeyNoValueFallbackToKey || this.options.missingKeyNoValueFallbackToKey;
786
+ const resForMissing = missingKeyNoValueFallbackToKey && usedKey ? void 0 : res;
787
+ const updateMissing = hasDefaultValue && defaultValue !== res && this.options.updateMissing;
788
+ if (usedKey || usedDefault || updateMissing) {
789
+ this.logger.log(updateMissing ? "updateKey" : "missingKey", lng, namespace, key, updateMissing ? defaultValue : res);
790
+ if (keySeparator) {
791
+ const fk = this.resolve(key, {
792
+ ...opt,
793
+ keySeparator: false
794
+ });
795
+ if (fk && fk.res) this.logger.warn("Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.");
796
+ }
797
+ let lngs = [];
798
+ const fallbackLngs = this.languageUtils.getFallbackCodes(this.options.fallbackLng, opt.lng || this.language);
799
+ if (this.options.saveMissingTo === "fallback" && fallbackLngs && fallbackLngs[0]) {
800
+ for (let i = 0; i < fallbackLngs.length; i++) {
801
+ lngs.push(fallbackLngs[i]);
802
+ }
803
+ } else if (this.options.saveMissingTo === "all") {
804
+ lngs = this.languageUtils.toResolveHierarchy(opt.lng || this.language);
805
+ } else {
806
+ lngs.push(opt.lng || this.language);
807
+ }
808
+ const send = (l, k, specificDefaultValue) => {
809
+ const defaultForMissing = hasDefaultValue && specificDefaultValue !== res ? specificDefaultValue : resForMissing;
810
+ if (this.options.missingKeyHandler) {
811
+ this.options.missingKeyHandler(l, namespace, k, defaultForMissing, updateMissing, opt);
812
+ } else if (this.backendConnector?.saveMissing) {
813
+ this.backendConnector.saveMissing(l, namespace, k, defaultForMissing, updateMissing, opt);
814
+ }
815
+ this.emit("missingKey", l, namespace, k, res);
816
+ };
817
+ if (this.options.saveMissing) {
818
+ if (this.options.saveMissingPlurals && needsPluralHandling) {
819
+ lngs.forEach((language) => {
820
+ const suffixes = this.pluralResolver.getSuffixes(language, opt);
821
+ if (needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] && suffixes.indexOf(`${this.options.pluralSeparator}zero`) < 0) {
822
+ suffixes.push(`${this.options.pluralSeparator}zero`);
823
+ }
824
+ suffixes.forEach((suffix) => {
825
+ send([language], key + suffix, opt[`defaultValue${suffix}`] || defaultValue);
826
+ });
827
+ });
828
+ } else {
829
+ send(lngs, key, defaultValue);
830
+ }
831
+ }
832
+ }
833
+ res = this.extendTranslation(res, keys, opt, resolved, lastKey);
834
+ if (usedKey && res === key && this.options.appendNamespaceToMissingKey) {
835
+ res = `${namespace}${nsSeparator}${key}`;
836
+ }
837
+ if ((usedKey || usedDefault) && this.options.parseMissingKeyHandler) {
838
+ res = this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey ? `${namespace}${nsSeparator}${key}` : key, usedDefault ? res : void 0, opt);
839
+ }
840
+ }
841
+ if (returnDetails) {
842
+ resolved.res = res;
843
+ resolved.usedParams = this.getUsedParamsDetails(opt);
844
+ return resolved;
845
+ }
846
+ return res;
847
+ }
848
+ extendTranslation(res, key, opt, resolved, lastKey) {
849
+ if (this.i18nFormat?.parse) {
850
+ res = this.i18nFormat.parse(res, {
851
+ ...this.options.interpolation.defaultVariables,
852
+ ...opt
853
+ }, opt.lng || this.language || resolved.usedLng, resolved.usedNS, resolved.usedKey, {
854
+ resolved
855
+ });
856
+ } else if (!opt.skipInterpolation) {
857
+ if (opt.interpolation) this.interpolator.init({
858
+ ...opt,
859
+ ...{
860
+ interpolation: {
861
+ ...this.options.interpolation,
862
+ ...opt.interpolation
863
+ }
864
+ }
865
+ });
866
+ const skipOnVariables = isString(res) && (opt?.interpolation?.skipOnVariables !== void 0 ? opt.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables);
867
+ let nestBef;
868
+ if (skipOnVariables) {
869
+ const nb = res.match(this.interpolator.nestingRegexp);
870
+ nestBef = nb && nb.length;
871
+ }
872
+ let data = opt.replace && !isString(opt.replace) ? opt.replace : opt;
873
+ if (this.options.interpolation.defaultVariables) data = {
874
+ ...this.options.interpolation.defaultVariables,
875
+ ...data
876
+ };
877
+ res = this.interpolator.interpolate(res, data, opt.lng || this.language || resolved.usedLng, opt);
878
+ if (skipOnVariables) {
879
+ const na = res.match(this.interpolator.nestingRegexp);
880
+ const nestAft = na && na.length;
881
+ if (nestBef < nestAft) opt.nest = false;
882
+ }
883
+ if (!opt.lng && resolved && resolved.res) opt.lng = this.language || resolved.usedLng;
884
+ if (opt.nest !== false) res = this.interpolator.nest(res, (...args) => {
885
+ if (lastKey?.[0] === args[0] && !opt.context) {
886
+ this.logger.warn(`It seems you are nesting recursively key: ${args[0]} in key: ${key[0]}`);
887
+ return null;
888
+ }
889
+ return this.translate(...args, key);
890
+ }, opt);
891
+ if (opt.interpolation) this.interpolator.reset();
892
+ }
893
+ const postProcess = opt.postProcess || this.options.postProcess;
894
+ const postProcessorNames = isString(postProcess) ? [postProcess] : postProcess;
895
+ if (res != null && postProcessorNames?.length && opt.applyPostProcessor !== false) {
896
+ res = postProcessor.handle(postProcessorNames, res, key, this.options && this.options.postProcessPassResolved ? {
897
+ i18nResolved: {
898
+ ...resolved,
899
+ usedParams: this.getUsedParamsDetails(opt)
900
+ },
901
+ ...opt
902
+ } : opt, this);
903
+ }
904
+ return res;
905
+ }
906
+ resolve(keys, opt = {}) {
907
+ let found;
908
+ let usedKey;
909
+ let exactUsedKey;
910
+ let usedLng;
911
+ let usedNS;
912
+ if (isString(keys)) keys = [keys];
913
+ if (Array.isArray(keys)) keys = keys.map((k) => typeof k === "function" ? keysFromSelector(k, {
914
+ ...this.options,
915
+ ...opt
916
+ }) : k);
917
+ keys.forEach((k) => {
918
+ if (this.isValidLookup(found)) return;
919
+ const extracted = this.extractFromKey(k, opt);
920
+ const key = extracted.key;
921
+ usedKey = key;
922
+ let namespaces = extracted.namespaces;
923
+ if (this.options.fallbackNS) namespaces = namespaces.concat(this.options.fallbackNS);
924
+ const needsPluralHandling = opt.count !== void 0 && !isString(opt.count);
925
+ const needsZeroSuffixLookup = needsPluralHandling && !opt.ordinal && opt.count === 0;
926
+ const needsContextHandling = opt.context !== void 0 && (isString(opt.context) || typeof opt.context === "number") && opt.context !== "";
927
+ const codes = opt.lngs ? opt.lngs : this.languageUtils.toResolveHierarchy(opt.lng || this.language, opt.fallbackLng);
928
+ namespaces.forEach((ns) => {
929
+ if (this.isValidLookup(found)) return;
930
+ usedNS = ns;
931
+ if (!checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils?.hasLoadedNamespace && !this.utils?.hasLoadedNamespace(usedNS)) {
932
+ checkedLoadedFor[`${codes[0]}-${ns}`] = true;
933
+ this.logger.warn(`key "${usedKey}" for languages "${codes.join(", ")}" won't get resolved as namespace "${usedNS}" was not yet loaded`, "This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");
934
+ }
935
+ codes.forEach((code) => {
936
+ if (this.isValidLookup(found)) return;
937
+ usedLng = code;
938
+ const finalKeys = [key];
939
+ if (this.i18nFormat?.addLookupKeys) {
940
+ this.i18nFormat.addLookupKeys(finalKeys, key, code, ns, opt);
941
+ } else {
942
+ let pluralSuffix;
943
+ if (needsPluralHandling) pluralSuffix = this.pluralResolver.getSuffix(code, opt.count, opt);
944
+ const zeroSuffix = `${this.options.pluralSeparator}zero`;
945
+ const ordinalPrefix = `${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;
946
+ if (needsPluralHandling) {
947
+ if (opt.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) {
948
+ finalKeys.push(key + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
949
+ }
950
+ finalKeys.push(key + pluralSuffix);
951
+ if (needsZeroSuffixLookup) {
952
+ finalKeys.push(key + zeroSuffix);
953
+ }
954
+ }
955
+ if (needsContextHandling) {
956
+ const contextKey = `${key}${this.options.contextSeparator || "_"}${opt.context}`;
957
+ finalKeys.push(contextKey);
958
+ if (needsPluralHandling) {
959
+ if (opt.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) {
960
+ finalKeys.push(contextKey + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
961
+ }
962
+ finalKeys.push(contextKey + pluralSuffix);
963
+ if (needsZeroSuffixLookup) {
964
+ finalKeys.push(contextKey + zeroSuffix);
965
+ }
966
+ }
967
+ }
968
+ }
969
+ let possibleKey;
970
+ while (possibleKey = finalKeys.pop()) {
971
+ if (!this.isValidLookup(found)) {
972
+ exactUsedKey = possibleKey;
973
+ found = this.getResource(code, ns, possibleKey, opt);
974
+ }
975
+ }
976
+ });
977
+ });
978
+ });
979
+ return {
980
+ res: found,
981
+ usedKey,
982
+ exactUsedKey,
983
+ usedLng,
984
+ usedNS
985
+ };
986
+ }
987
+ isValidLookup(res) {
988
+ return res !== void 0 && !(!this.options.returnNull && res === null) && !(!this.options.returnEmptyString && res === "");
989
+ }
990
+ getResource(code, ns, key, options = {}) {
991
+ if (this.i18nFormat?.getResource) return this.i18nFormat.getResource(code, ns, key, options);
992
+ return this.resourceStore.getResource(code, ns, key, options);
993
+ }
994
+ getUsedParamsDetails(options = {}) {
995
+ const optionsKeys = ["defaultValue", "ordinal", "context", "replace", "lng", "lngs", "fallbackLng", "ns", "keySeparator", "nsSeparator", "returnObjects", "returnDetails", "joinArrays", "postProcess", "interpolation"];
996
+ const useOptionsReplaceForData = options.replace && !isString(options.replace);
997
+ let data = useOptionsReplaceForData ? options.replace : options;
998
+ if (useOptionsReplaceForData && typeof options.count !== "undefined") {
999
+ data.count = options.count;
1000
+ }
1001
+ if (this.options.interpolation.defaultVariables) {
1002
+ data = {
1003
+ ...this.options.interpolation.defaultVariables,
1004
+ ...data
1005
+ };
1006
+ }
1007
+ if (!useOptionsReplaceForData) {
1008
+ data = {
1009
+ ...data
1010
+ };
1011
+ for (const key of optionsKeys) {
1012
+ delete data[key];
1013
+ }
1014
+ }
1015
+ return data;
1016
+ }
1017
+ static hasDefaultValue(options) {
1018
+ const prefix = "defaultValue";
1019
+ for (const option in options) {
1020
+ if (Object.prototype.hasOwnProperty.call(options, option) && prefix === option.substring(0, prefix.length) && void 0 !== options[option]) {
1021
+ return true;
1022
+ }
1023
+ }
1024
+ return false;
1025
+ }
1026
+ };
1027
+ var LanguageUtil = class {
1028
+ constructor(options) {
1029
+ this.options = options;
1030
+ this.supportedLngs = this.options.supportedLngs || false;
1031
+ this.logger = baseLogger.create("languageUtils");
1032
+ }
1033
+ getScriptPartFromCode(code) {
1034
+ code = getCleanedCode(code);
1035
+ if (!code || code.indexOf("-") < 0) return null;
1036
+ const p = code.split("-");
1037
+ if (p.length === 2) return null;
1038
+ p.pop();
1039
+ if (p[p.length - 1].toLowerCase() === "x") return null;
1040
+ return this.formatLanguageCode(p.join("-"));
1041
+ }
1042
+ getLanguagePartFromCode(code) {
1043
+ code = getCleanedCode(code);
1044
+ if (!code || code.indexOf("-") < 0) return code;
1045
+ const p = code.split("-");
1046
+ return this.formatLanguageCode(p[0]);
1047
+ }
1048
+ formatLanguageCode(code) {
1049
+ if (isString(code) && code.indexOf("-") > -1) {
1050
+ let formattedCode;
1051
+ try {
1052
+ formattedCode = Intl.getCanonicalLocales(code)[0];
1053
+ } catch (e) {
1054
+ }
1055
+ if (formattedCode && this.options.lowerCaseLng) {
1056
+ formattedCode = formattedCode.toLowerCase();
1057
+ }
1058
+ if (formattedCode) return formattedCode;
1059
+ if (this.options.lowerCaseLng) {
1060
+ return code.toLowerCase();
1061
+ }
1062
+ return code;
1063
+ }
1064
+ return this.options.cleanCode || this.options.lowerCaseLng ? code.toLowerCase() : code;
1065
+ }
1066
+ isSupportedCode(code) {
1067
+ if (this.options.load === "languageOnly" || this.options.nonExplicitSupportedLngs) {
1068
+ code = this.getLanguagePartFromCode(code);
1069
+ }
1070
+ return !this.supportedLngs || !this.supportedLngs.length || this.supportedLngs.indexOf(code) > -1;
1071
+ }
1072
+ getBestMatchFromCodes(codes) {
1073
+ if (!codes) return null;
1074
+ let found;
1075
+ codes.forEach((code) => {
1076
+ if (found) return;
1077
+ const cleanedLng = this.formatLanguageCode(code);
1078
+ if (!this.options.supportedLngs || this.isSupportedCode(cleanedLng)) found = cleanedLng;
1079
+ });
1080
+ if (!found && this.options.supportedLngs) {
1081
+ codes.forEach((code) => {
1082
+ if (found) return;
1083
+ const lngScOnly = this.getScriptPartFromCode(code);
1084
+ if (this.isSupportedCode(lngScOnly)) return found = lngScOnly;
1085
+ const lngOnly = this.getLanguagePartFromCode(code);
1086
+ if (this.isSupportedCode(lngOnly)) return found = lngOnly;
1087
+ found = this.options.supportedLngs.find((supportedLng) => {
1088
+ if (supportedLng === lngOnly) return supportedLng;
1089
+ if (supportedLng.indexOf("-") < 0 && lngOnly.indexOf("-") < 0) return;
1090
+ if (supportedLng.indexOf("-") > 0 && lngOnly.indexOf("-") < 0 && supportedLng.substring(0, supportedLng.indexOf("-")) === lngOnly) return supportedLng;
1091
+ if (supportedLng.indexOf(lngOnly) === 0 && lngOnly.length > 1) return supportedLng;
1092
+ });
1093
+ });
1094
+ }
1095
+ if (!found) found = this.getFallbackCodes(this.options.fallbackLng)[0];
1096
+ return found;
1097
+ }
1098
+ getFallbackCodes(fallbacks, code) {
1099
+ if (!fallbacks) return [];
1100
+ if (typeof fallbacks === "function") fallbacks = fallbacks(code);
1101
+ if (isString(fallbacks)) fallbacks = [fallbacks];
1102
+ if (Array.isArray(fallbacks)) return fallbacks;
1103
+ if (!code) return fallbacks.default || [];
1104
+ let found = fallbacks[code];
1105
+ if (!found) found = fallbacks[this.getScriptPartFromCode(code)];
1106
+ if (!found) found = fallbacks[this.formatLanguageCode(code)];
1107
+ if (!found) found = fallbacks[this.getLanguagePartFromCode(code)];
1108
+ if (!found) found = fallbacks.default;
1109
+ return found || [];
1110
+ }
1111
+ toResolveHierarchy(code, fallbackCode) {
1112
+ const fallbackCodes = this.getFallbackCodes((fallbackCode === false ? [] : fallbackCode) || this.options.fallbackLng || [], code);
1113
+ const codes = [];
1114
+ const addCode = (c) => {
1115
+ if (!c) return;
1116
+ if (this.isSupportedCode(c)) {
1117
+ codes.push(c);
1118
+ } else {
1119
+ this.logger.warn(`rejecting language code not found in supportedLngs: ${c}`);
1120
+ }
1121
+ };
1122
+ if (isString(code) && (code.indexOf("-") > -1 || code.indexOf("_") > -1)) {
1123
+ if (this.options.load !== "languageOnly") addCode(this.formatLanguageCode(code));
1124
+ if (this.options.load !== "languageOnly" && this.options.load !== "currentOnly") addCode(this.getScriptPartFromCode(code));
1125
+ if (this.options.load !== "currentOnly") addCode(this.getLanguagePartFromCode(code));
1126
+ } else if (isString(code)) {
1127
+ addCode(this.formatLanguageCode(code));
1128
+ }
1129
+ fallbackCodes.forEach((fc) => {
1130
+ if (codes.indexOf(fc) < 0) addCode(this.formatLanguageCode(fc));
1131
+ });
1132
+ return codes;
1133
+ }
1134
+ };
1135
+ var suffixesOrder = {
1136
+ zero: 0,
1137
+ one: 1,
1138
+ two: 2,
1139
+ few: 3,
1140
+ many: 4,
1141
+ other: 5
1142
+ };
1143
+ var dummyRule = {
1144
+ select: (count) => count === 1 ? "one" : "other",
1145
+ resolvedOptions: () => ({
1146
+ pluralCategories: ["one", "other"]
1147
+ })
1148
+ };
1149
+ var PluralResolver = class {
1150
+ constructor(languageUtils, options = {}) {
1151
+ this.languageUtils = languageUtils;
1152
+ this.options = options;
1153
+ this.logger = baseLogger.create("pluralResolver");
1154
+ this.pluralRulesCache = {};
1155
+ }
1156
+ clearCache() {
1157
+ this.pluralRulesCache = {};
1158
+ }
1159
+ getRule(code, options = {}) {
1160
+ const cleanedCode = getCleanedCode(code === "dev" ? "en" : code);
1161
+ const type = options.ordinal ? "ordinal" : "cardinal";
1162
+ const cacheKey = JSON.stringify({
1163
+ cleanedCode,
1164
+ type
1165
+ });
1166
+ if (cacheKey in this.pluralRulesCache) {
1167
+ return this.pluralRulesCache[cacheKey];
1168
+ }
1169
+ let rule;
1170
+ try {
1171
+ rule = new Intl.PluralRules(cleanedCode, {
1172
+ type
1173
+ });
1174
+ } catch (err) {
1175
+ if (typeof Intl === "undefined") {
1176
+ this.logger.error("No Intl support, please use an Intl polyfill!");
1177
+ return dummyRule;
1178
+ }
1179
+ if (!code.match(/-|_/)) return dummyRule;
1180
+ const lngPart = this.languageUtils.getLanguagePartFromCode(code);
1181
+ rule = this.getRule(lngPart, options);
1182
+ }
1183
+ this.pluralRulesCache[cacheKey] = rule;
1184
+ return rule;
1185
+ }
1186
+ needsPlural(code, options = {}) {
1187
+ let rule = this.getRule(code, options);
1188
+ if (!rule) rule = this.getRule("dev", options);
1189
+ return rule?.resolvedOptions().pluralCategories.length > 1;
1190
+ }
1191
+ getPluralFormsOfKey(code, key, options = {}) {
1192
+ return this.getSuffixes(code, options).map((suffix) => `${key}${suffix}`);
1193
+ }
1194
+ getSuffixes(code, options = {}) {
1195
+ let rule = this.getRule(code, options);
1196
+ if (!rule) rule = this.getRule("dev", options);
1197
+ if (!rule) return [];
1198
+ return rule.resolvedOptions().pluralCategories.sort((pluralCategory1, pluralCategory2) => suffixesOrder[pluralCategory1] - suffixesOrder[pluralCategory2]).map((pluralCategory) => `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ""}${pluralCategory}`);
1199
+ }
1200
+ getSuffix(code, count, options = {}) {
1201
+ const rule = this.getRule(code, options);
1202
+ if (rule) {
1203
+ return `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ""}${rule.select(count)}`;
1204
+ }
1205
+ this.logger.warn(`no plural rule found for: ${code}`);
1206
+ return this.getSuffix("dev", count, options);
1207
+ }
1208
+ };
1209
+ var deepFindWithDefaults = (data, defaultData, key, keySeparator = ".", ignoreJSONStructure = true) => {
1210
+ let path = getPathWithDefaults(data, defaultData, key);
1211
+ if (!path && ignoreJSONStructure && isString(key)) {
1212
+ path = deepFind(data, key, keySeparator);
1213
+ if (path === void 0) path = deepFind(defaultData, key, keySeparator);
1214
+ }
1215
+ return path;
1216
+ };
1217
+ var regexSafe = (val) => val.replace(/\$/g, "$$$$");
1218
+ var Interpolator = class {
1219
+ constructor(options = {}) {
1220
+ this.logger = baseLogger.create("interpolator");
1221
+ this.options = options;
1222
+ this.format = options?.interpolation?.format || ((value) => value);
1223
+ this.init(options);
1224
+ }
1225
+ init(options = {}) {
1226
+ if (!options.interpolation) options.interpolation = {
1227
+ escapeValue: true
1228
+ };
1229
+ const {
1230
+ escape: escape$1,
1231
+ escapeValue,
1232
+ useRawValueToEscape,
1233
+ prefix,
1234
+ prefixEscaped,
1235
+ suffix,
1236
+ suffixEscaped,
1237
+ formatSeparator,
1238
+ unescapeSuffix,
1239
+ unescapePrefix,
1240
+ nestingPrefix,
1241
+ nestingPrefixEscaped,
1242
+ nestingSuffix,
1243
+ nestingSuffixEscaped,
1244
+ nestingOptionsSeparator,
1245
+ maxReplaces,
1246
+ alwaysFormat
1247
+ } = options.interpolation;
1248
+ this.escape = escape$1 !== void 0 ? escape$1 : escape;
1249
+ this.escapeValue = escapeValue !== void 0 ? escapeValue : true;
1250
+ this.useRawValueToEscape = useRawValueToEscape !== void 0 ? useRawValueToEscape : false;
1251
+ this.prefix = prefix ? regexEscape(prefix) : prefixEscaped || "{{";
1252
+ this.suffix = suffix ? regexEscape(suffix) : suffixEscaped || "}}";
1253
+ this.formatSeparator = formatSeparator || ",";
1254
+ this.unescapePrefix = unescapeSuffix ? "" : unescapePrefix || "-";
1255
+ this.unescapeSuffix = this.unescapePrefix ? "" : unescapeSuffix || "";
1256
+ this.nestingPrefix = nestingPrefix ? regexEscape(nestingPrefix) : nestingPrefixEscaped || regexEscape("$t(");
1257
+ this.nestingSuffix = nestingSuffix ? regexEscape(nestingSuffix) : nestingSuffixEscaped || regexEscape(")");
1258
+ this.nestingOptionsSeparator = nestingOptionsSeparator || ",";
1259
+ this.maxReplaces = maxReplaces || 1e3;
1260
+ this.alwaysFormat = alwaysFormat !== void 0 ? alwaysFormat : false;
1261
+ this.resetRegExp();
1262
+ }
1263
+ reset() {
1264
+ if (this.options) this.init(this.options);
1265
+ }
1266
+ resetRegExp() {
1267
+ const getOrResetRegExp = (existingRegExp, pattern) => {
1268
+ if (existingRegExp?.source === pattern) {
1269
+ existingRegExp.lastIndex = 0;
1270
+ return existingRegExp;
1271
+ }
1272
+ return new RegExp(pattern, "g");
1273
+ };
1274
+ this.regexp = getOrResetRegExp(this.regexp, `${this.prefix}(.+?)${this.suffix}`);
1275
+ this.regexpUnescape = getOrResetRegExp(this.regexpUnescape, `${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`);
1276
+ this.nestingRegexp = getOrResetRegExp(this.nestingRegexp, `${this.nestingPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${this.nestingSuffix}`);
1277
+ }
1278
+ interpolate(str, data, lng, options) {
1279
+ let match;
1280
+ let value;
1281
+ let replaces;
1282
+ const defaultData = this.options && this.options.interpolation && this.options.interpolation.defaultVariables || {};
1283
+ const handleFormat = (key) => {
1284
+ if (key.indexOf(this.formatSeparator) < 0) {
1285
+ const path = deepFindWithDefaults(data, defaultData, key, this.options.keySeparator, this.options.ignoreJSONStructure);
1286
+ return this.alwaysFormat ? this.format(path, void 0, lng, {
1287
+ ...options,
1288
+ ...data,
1289
+ interpolationkey: key
1290
+ }) : path;
1291
+ }
1292
+ const p = key.split(this.formatSeparator);
1293
+ const k = p.shift().trim();
1294
+ const f = p.join(this.formatSeparator).trim();
1295
+ return this.format(deepFindWithDefaults(data, defaultData, k, this.options.keySeparator, this.options.ignoreJSONStructure), f, lng, {
1296
+ ...options,
1297
+ ...data,
1298
+ interpolationkey: k
1299
+ });
1300
+ };
1301
+ this.resetRegExp();
1302
+ const missingInterpolationHandler = options?.missingInterpolationHandler || this.options.missingInterpolationHandler;
1303
+ const skipOnVariables = options?.interpolation?.skipOnVariables !== void 0 ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables;
1304
+ const todos = [{
1305
+ regex: this.regexpUnescape,
1306
+ safeValue: (val) => regexSafe(val)
1307
+ }, {
1308
+ regex: this.regexp,
1309
+ safeValue: (val) => this.escapeValue ? regexSafe(this.escape(val)) : regexSafe(val)
1310
+ }];
1311
+ todos.forEach((todo) => {
1312
+ replaces = 0;
1313
+ while (match = todo.regex.exec(str)) {
1314
+ const matchedVar = match[1].trim();
1315
+ value = handleFormat(matchedVar);
1316
+ if (value === void 0) {
1317
+ if (typeof missingInterpolationHandler === "function") {
1318
+ const temp = missingInterpolationHandler(str, match, options);
1319
+ value = isString(temp) ? temp : "";
1320
+ } else if (options && Object.prototype.hasOwnProperty.call(options, matchedVar)) {
1321
+ value = "";
1322
+ } else if (skipOnVariables) {
1323
+ value = match[0];
1324
+ continue;
1325
+ } else {
1326
+ this.logger.warn(`missed to pass in variable ${matchedVar} for interpolating ${str}`);
1327
+ value = "";
1328
+ }
1329
+ } else if (!isString(value) && !this.useRawValueToEscape) {
1330
+ value = makeString(value);
1331
+ }
1332
+ const safeValue = todo.safeValue(value);
1333
+ str = str.replace(match[0], safeValue);
1334
+ if (skipOnVariables) {
1335
+ todo.regex.lastIndex += value.length;
1336
+ todo.regex.lastIndex -= match[0].length;
1337
+ } else {
1338
+ todo.regex.lastIndex = 0;
1339
+ }
1340
+ replaces++;
1341
+ if (replaces >= this.maxReplaces) {
1342
+ break;
1343
+ }
1344
+ }
1345
+ });
1346
+ return str;
1347
+ }
1348
+ nest(str, fc, options = {}) {
1349
+ let match;
1350
+ let value;
1351
+ let clonedOptions;
1352
+ const handleHasOptions = (key, inheritedOptions) => {
1353
+ const sep = this.nestingOptionsSeparator;
1354
+ if (key.indexOf(sep) < 0) return key;
1355
+ const c = key.split(new RegExp(`${regexEscape(sep)}[ ]*{`));
1356
+ let optionsString = `{${c[1]}`;
1357
+ key = c[0];
1358
+ optionsString = this.interpolate(optionsString, clonedOptions);
1359
+ const matchedSingleQuotes = optionsString.match(/'/g);
1360
+ const matchedDoubleQuotes = optionsString.match(/"/g);
1361
+ if ((matchedSingleQuotes?.length ?? 0) % 2 === 0 && !matchedDoubleQuotes || (matchedDoubleQuotes?.length ?? 0) % 2 !== 0) {
1362
+ optionsString = optionsString.replace(/'/g, '"');
1363
+ }
1364
+ try {
1365
+ clonedOptions = JSON.parse(optionsString);
1366
+ if (inheritedOptions) clonedOptions = {
1367
+ ...inheritedOptions,
1368
+ ...clonedOptions
1369
+ };
1370
+ } catch (e) {
1371
+ this.logger.warn(`failed parsing options string in nesting for key ${key}`, e);
1372
+ return `${key}${sep}${optionsString}`;
1373
+ }
1374
+ if (clonedOptions.defaultValue && clonedOptions.defaultValue.indexOf(this.prefix) > -1) delete clonedOptions.defaultValue;
1375
+ return key;
1376
+ };
1377
+ while (match = this.nestingRegexp.exec(str)) {
1378
+ let formatters = [];
1379
+ clonedOptions = {
1380
+ ...options
1381
+ };
1382
+ clonedOptions = clonedOptions.replace && !isString(clonedOptions.replace) ? clonedOptions.replace : clonedOptions;
1383
+ clonedOptions.applyPostProcessor = false;
1384
+ delete clonedOptions.defaultValue;
1385
+ const keyEndIndex = /{.*}/.test(match[1]) ? match[1].lastIndexOf("}") + 1 : match[1].indexOf(this.formatSeparator);
1386
+ if (keyEndIndex !== -1) {
1387
+ formatters = match[1].slice(keyEndIndex).split(this.formatSeparator).map((elem) => elem.trim()).filter(Boolean);
1388
+ match[1] = match[1].slice(0, keyEndIndex);
1389
+ }
1390
+ value = fc(handleHasOptions.call(this, match[1].trim(), clonedOptions), clonedOptions);
1391
+ if (value && match[0] === str && !isString(value)) return value;
1392
+ if (!isString(value)) value = makeString(value);
1393
+ if (!value) {
1394
+ this.logger.warn(`missed to resolve ${match[1]} for nesting ${str}`);
1395
+ value = "";
1396
+ }
1397
+ if (formatters.length) {
1398
+ value = formatters.reduce((v, f) => this.format(v, f, options.lng, {
1399
+ ...options,
1400
+ interpolationkey: match[1].trim()
1401
+ }), value.trim());
1402
+ }
1403
+ str = str.replace(match[0], value);
1404
+ this.regexp.lastIndex = 0;
1405
+ }
1406
+ return str;
1407
+ }
1408
+ };
1409
+ var parseFormatStr = (formatStr) => {
1410
+ let formatName = formatStr.toLowerCase().trim();
1411
+ const formatOptions = {};
1412
+ if (formatStr.indexOf("(") > -1) {
1413
+ const p = formatStr.split("(");
1414
+ formatName = p[0].toLowerCase().trim();
1415
+ const optStr = p[1].substring(0, p[1].length - 1);
1416
+ if (formatName === "currency" && optStr.indexOf(":") < 0) {
1417
+ if (!formatOptions.currency) formatOptions.currency = optStr.trim();
1418
+ } else if (formatName === "relativetime" && optStr.indexOf(":") < 0) {
1419
+ if (!formatOptions.range) formatOptions.range = optStr.trim();
1420
+ } else {
1421
+ const opts = optStr.split(";");
1422
+ opts.forEach((opt) => {
1423
+ if (opt) {
1424
+ const [key, ...rest] = opt.split(":");
1425
+ const val = rest.join(":").trim().replace(/^'+|'+$/g, "");
1426
+ const trimmedKey = key.trim();
1427
+ if (!formatOptions[trimmedKey]) formatOptions[trimmedKey] = val;
1428
+ if (val === "false") formatOptions[trimmedKey] = false;
1429
+ if (val === "true") formatOptions[trimmedKey] = true;
1430
+ if (!isNaN(val)) formatOptions[trimmedKey] = parseInt(val, 10);
1431
+ }
1432
+ });
1433
+ }
1434
+ }
1435
+ return {
1436
+ formatName,
1437
+ formatOptions
1438
+ };
1439
+ };
1440
+ var createCachedFormatter = (fn) => {
1441
+ const cache = {};
1442
+ return (v, l, o) => {
1443
+ let optForCache = o;
1444
+ if (o && o.interpolationkey && o.formatParams && o.formatParams[o.interpolationkey] && o[o.interpolationkey]) {
1445
+ optForCache = {
1446
+ ...optForCache,
1447
+ [o.interpolationkey]: void 0
1448
+ };
1449
+ }
1450
+ const key = l + JSON.stringify(optForCache);
1451
+ let frm = cache[key];
1452
+ if (!frm) {
1453
+ frm = fn(getCleanedCode(l), o);
1454
+ cache[key] = frm;
1455
+ }
1456
+ return frm(v);
1457
+ };
1458
+ };
1459
+ var createNonCachedFormatter = (fn) => (v, l, o) => fn(getCleanedCode(l), o)(v);
1460
+ var Formatter = class {
1461
+ constructor(options = {}) {
1462
+ this.logger = baseLogger.create("formatter");
1463
+ this.options = options;
1464
+ this.init(options);
1465
+ }
1466
+ init(services, options = {
1467
+ interpolation: {}
1468
+ }) {
1469
+ this.formatSeparator = options.interpolation.formatSeparator || ",";
1470
+ const cf = options.cacheInBuiltFormats ? createCachedFormatter : createNonCachedFormatter;
1471
+ this.formats = {
1472
+ number: cf((lng, opt) => {
1473
+ const formatter = new Intl.NumberFormat(lng, {
1474
+ ...opt
1475
+ });
1476
+ return (val) => formatter.format(val);
1477
+ }),
1478
+ currency: cf((lng, opt) => {
1479
+ const formatter = new Intl.NumberFormat(lng, {
1480
+ ...opt,
1481
+ style: "currency"
1482
+ });
1483
+ return (val) => formatter.format(val);
1484
+ }),
1485
+ datetime: cf((lng, opt) => {
1486
+ const formatter = new Intl.DateTimeFormat(lng, {
1487
+ ...opt
1488
+ });
1489
+ return (val) => formatter.format(val);
1490
+ }),
1491
+ relativetime: cf((lng, opt) => {
1492
+ const formatter = new Intl.RelativeTimeFormat(lng, {
1493
+ ...opt
1494
+ });
1495
+ return (val) => formatter.format(val, opt.range || "day");
1496
+ }),
1497
+ list: cf((lng, opt) => {
1498
+ const formatter = new Intl.ListFormat(lng, {
1499
+ ...opt
1500
+ });
1501
+ return (val) => formatter.format(val);
1502
+ })
1503
+ };
1504
+ }
1505
+ add(name, fc) {
1506
+ this.formats[name.toLowerCase().trim()] = fc;
1507
+ }
1508
+ addCached(name, fc) {
1509
+ this.formats[name.toLowerCase().trim()] = createCachedFormatter(fc);
1510
+ }
1511
+ format(value, format, lng, options = {}) {
1512
+ const formats = format.split(this.formatSeparator);
1513
+ if (formats.length > 1 && formats[0].indexOf("(") > 1 && formats[0].indexOf(")") < 0 && formats.find((f) => f.indexOf(")") > -1)) {
1514
+ const lastIndex = formats.findIndex((f) => f.indexOf(")") > -1);
1515
+ formats[0] = [formats[0], ...formats.splice(1, lastIndex)].join(this.formatSeparator);
1516
+ }
1517
+ const result = formats.reduce((mem, f) => {
1518
+ const {
1519
+ formatName,
1520
+ formatOptions
1521
+ } = parseFormatStr(f);
1522
+ if (this.formats[formatName]) {
1523
+ let formatted = mem;
1524
+ try {
1525
+ const valOptions = options?.formatParams?.[options.interpolationkey] || {};
1526
+ const l = valOptions.locale || valOptions.lng || options.locale || options.lng || lng;
1527
+ formatted = this.formats[formatName](mem, l, {
1528
+ ...formatOptions,
1529
+ ...options,
1530
+ ...valOptions
1531
+ });
1532
+ } catch (error) {
1533
+ this.logger.warn(error);
1534
+ }
1535
+ return formatted;
1536
+ } else {
1537
+ this.logger.warn(`there was no format function for ${formatName}`);
1538
+ }
1539
+ return mem;
1540
+ }, value);
1541
+ return result;
1542
+ }
1543
+ };
1544
+ var removePending = (q, name) => {
1545
+ if (q.pending[name] !== void 0) {
1546
+ delete q.pending[name];
1547
+ q.pendingCount--;
1548
+ }
1549
+ };
1550
+ var Connector = class extends EventEmitter {
1551
+ constructor(backend, store, services, options = {}) {
1552
+ super();
1553
+ this.backend = backend;
1554
+ this.store = store;
1555
+ this.services = services;
1556
+ this.languageUtils = services.languageUtils;
1557
+ this.options = options;
1558
+ this.logger = baseLogger.create("backendConnector");
1559
+ this.waitingReads = [];
1560
+ this.maxParallelReads = options.maxParallelReads || 10;
1561
+ this.readingCalls = 0;
1562
+ this.maxRetries = options.maxRetries >= 0 ? options.maxRetries : 5;
1563
+ this.retryTimeout = options.retryTimeout >= 1 ? options.retryTimeout : 350;
1564
+ this.state = {};
1565
+ this.queue = [];
1566
+ this.backend?.init?.(services, options.backend, options);
1567
+ }
1568
+ queueLoad(languages, namespaces, options, callback) {
1569
+ const toLoad = {};
1570
+ const pending = {};
1571
+ const toLoadLanguages = {};
1572
+ const toLoadNamespaces = {};
1573
+ languages.forEach((lng) => {
1574
+ let hasAllNamespaces = true;
1575
+ namespaces.forEach((ns) => {
1576
+ const name = `${lng}|${ns}`;
1577
+ if (!options.reload && this.store.hasResourceBundle(lng, ns)) {
1578
+ this.state[name] = 2;
1579
+ } else if (this.state[name] < 0) ;
1580
+ else if (this.state[name] === 1) {
1581
+ if (pending[name] === void 0) pending[name] = true;
1582
+ } else {
1583
+ this.state[name] = 1;
1584
+ hasAllNamespaces = false;
1585
+ if (pending[name] === void 0) pending[name] = true;
1586
+ if (toLoad[name] === void 0) toLoad[name] = true;
1587
+ if (toLoadNamespaces[ns] === void 0) toLoadNamespaces[ns] = true;
1588
+ }
1589
+ });
1590
+ if (!hasAllNamespaces) toLoadLanguages[lng] = true;
1591
+ });
1592
+ if (Object.keys(toLoad).length || Object.keys(pending).length) {
1593
+ this.queue.push({
1594
+ pending,
1595
+ pendingCount: Object.keys(pending).length,
1596
+ loaded: {},
1597
+ errors: [],
1598
+ callback
1599
+ });
1600
+ }
1601
+ return {
1602
+ toLoad: Object.keys(toLoad),
1603
+ pending: Object.keys(pending),
1604
+ toLoadLanguages: Object.keys(toLoadLanguages),
1605
+ toLoadNamespaces: Object.keys(toLoadNamespaces)
1606
+ };
1607
+ }
1608
+ loaded(name, err, data) {
1609
+ const s = name.split("|");
1610
+ const lng = s[0];
1611
+ const ns = s[1];
1612
+ if (err) this.emit("failedLoading", lng, ns, err);
1613
+ if (!err && data) {
1614
+ this.store.addResourceBundle(lng, ns, data, void 0, void 0, {
1615
+ skipCopy: true
1616
+ });
1617
+ }
1618
+ this.state[name] = err ? -1 : 2;
1619
+ if (err && data) this.state[name] = 0;
1620
+ const loaded = {};
1621
+ this.queue.forEach((q) => {
1622
+ pushPath(q.loaded, [lng], ns);
1623
+ removePending(q, name);
1624
+ if (err) q.errors.push(err);
1625
+ if (q.pendingCount === 0 && !q.done) {
1626
+ Object.keys(q.loaded).forEach((l) => {
1627
+ if (!loaded[l]) loaded[l] = {};
1628
+ const loadedKeys = q.loaded[l];
1629
+ if (loadedKeys.length) {
1630
+ loadedKeys.forEach((n) => {
1631
+ if (loaded[l][n] === void 0) loaded[l][n] = true;
1632
+ });
1633
+ }
1634
+ });
1635
+ q.done = true;
1636
+ if (q.errors.length) {
1637
+ q.callback(q.errors);
1638
+ } else {
1639
+ q.callback();
1640
+ }
1641
+ }
1642
+ });
1643
+ this.emit("loaded", loaded);
1644
+ this.queue = this.queue.filter((q) => !q.done);
1645
+ }
1646
+ read(lng, ns, fcName, tried = 0, wait = this.retryTimeout, callback) {
1647
+ if (!lng.length) return callback(null, {});
1648
+ if (this.readingCalls >= this.maxParallelReads) {
1649
+ this.waitingReads.push({
1650
+ lng,
1651
+ ns,
1652
+ fcName,
1653
+ tried,
1654
+ wait,
1655
+ callback
1656
+ });
1657
+ return;
1658
+ }
1659
+ this.readingCalls++;
1660
+ const resolver = (err, data) => {
1661
+ this.readingCalls--;
1662
+ if (this.waitingReads.length > 0) {
1663
+ const next = this.waitingReads.shift();
1664
+ this.read(next.lng, next.ns, next.fcName, next.tried, next.wait, next.callback);
1665
+ }
1666
+ if (err && data && tried < this.maxRetries) {
1667
+ setTimeout(() => {
1668
+ this.read.call(this, lng, ns, fcName, tried + 1, wait * 2, callback);
1669
+ }, wait);
1670
+ return;
1671
+ }
1672
+ callback(err, data);
1673
+ };
1674
+ const fc = this.backend[fcName].bind(this.backend);
1675
+ if (fc.length === 2) {
1676
+ try {
1677
+ const r = fc(lng, ns);
1678
+ if (r && typeof r.then === "function") {
1679
+ r.then((data) => resolver(null, data)).catch(resolver);
1680
+ } else {
1681
+ resolver(null, r);
1682
+ }
1683
+ } catch (err) {
1684
+ resolver(err);
1685
+ }
1686
+ return;
1687
+ }
1688
+ return fc(lng, ns, resolver);
1689
+ }
1690
+ prepareLoading(languages, namespaces, options = {}, callback) {
1691
+ if (!this.backend) {
1692
+ this.logger.warn("No backend was added via i18next.use. Will not load resources.");
1693
+ return callback && callback();
1694
+ }
1695
+ if (isString(languages)) languages = this.languageUtils.toResolveHierarchy(languages);
1696
+ if (isString(namespaces)) namespaces = [namespaces];
1697
+ const toLoad = this.queueLoad(languages, namespaces, options, callback);
1698
+ if (!toLoad.toLoad.length) {
1699
+ if (!toLoad.pending.length) callback();
1700
+ return null;
1701
+ }
1702
+ toLoad.toLoad.forEach((name) => {
1703
+ this.loadOne(name);
1704
+ });
1705
+ }
1706
+ load(languages, namespaces, callback) {
1707
+ this.prepareLoading(languages, namespaces, {}, callback);
1708
+ }
1709
+ reload(languages, namespaces, callback) {
1710
+ this.prepareLoading(languages, namespaces, {
1711
+ reload: true
1712
+ }, callback);
1713
+ }
1714
+ loadOne(name, prefix = "") {
1715
+ const s = name.split("|");
1716
+ const lng = s[0];
1717
+ const ns = s[1];
1718
+ this.read(lng, ns, "read", void 0, void 0, (err, data) => {
1719
+ if (err) this.logger.warn(`${prefix}loading namespace ${ns} for language ${lng} failed`, err);
1720
+ if (!err && data) this.logger.log(`${prefix}loaded namespace ${ns} for language ${lng}`, data);
1721
+ this.loaded(name, err, data);
1722
+ });
1723
+ }
1724
+ saveMissing(languages, namespace, key, fallbackValue, isUpdate, options = {}, clb = () => {
1725
+ }) {
1726
+ if (this.services?.utils?.hasLoadedNamespace && !this.services?.utils?.hasLoadedNamespace(namespace)) {
1727
+ this.logger.warn(`did not save key "${key}" as the namespace "${namespace}" was not yet loaded`, "This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");
1728
+ return;
1729
+ }
1730
+ if (key === void 0 || key === null || key === "") return;
1731
+ if (this.backend?.create) {
1732
+ const opts = {
1733
+ ...options,
1734
+ isUpdate
1735
+ };
1736
+ const fc = this.backend.create.bind(this.backend);
1737
+ if (fc.length < 6) {
1738
+ try {
1739
+ let r;
1740
+ if (fc.length === 5) {
1741
+ r = fc(languages, namespace, key, fallbackValue, opts);
1742
+ } else {
1743
+ r = fc(languages, namespace, key, fallbackValue);
1744
+ }
1745
+ if (r && typeof r.then === "function") {
1746
+ r.then((data) => clb(null, data)).catch(clb);
1747
+ } else {
1748
+ clb(null, r);
1749
+ }
1750
+ } catch (err) {
1751
+ clb(err);
1752
+ }
1753
+ } else {
1754
+ fc(languages, namespace, key, fallbackValue, clb, opts);
1755
+ }
1756
+ }
1757
+ if (!languages || !languages[0]) return;
1758
+ this.store.addResource(languages[0], namespace, key, fallbackValue);
1759
+ }
1760
+ };
1761
+ var get = () => ({
1762
+ debug: false,
1763
+ initAsync: true,
1764
+ ns: ["translation"],
1765
+ defaultNS: ["translation"],
1766
+ fallbackLng: ["dev"],
1767
+ fallbackNS: false,
1768
+ supportedLngs: false,
1769
+ nonExplicitSupportedLngs: false,
1770
+ load: "all",
1771
+ preload: false,
1772
+ simplifyPluralSuffix: true,
1773
+ keySeparator: ".",
1774
+ nsSeparator: ":",
1775
+ pluralSeparator: "_",
1776
+ contextSeparator: "_",
1777
+ partialBundledLanguages: false,
1778
+ saveMissing: false,
1779
+ updateMissing: false,
1780
+ saveMissingTo: "fallback",
1781
+ saveMissingPlurals: true,
1782
+ missingKeyHandler: false,
1783
+ missingInterpolationHandler: false,
1784
+ postProcess: false,
1785
+ postProcessPassResolved: false,
1786
+ returnNull: false,
1787
+ returnEmptyString: true,
1788
+ returnObjects: false,
1789
+ joinArrays: false,
1790
+ returnedObjectHandler: false,
1791
+ parseMissingKeyHandler: false,
1792
+ appendNamespaceToMissingKey: false,
1793
+ appendNamespaceToCIMode: false,
1794
+ overloadTranslationOptionHandler: (args) => {
1795
+ let ret = {};
1796
+ if (typeof args[1] === "object") ret = args[1];
1797
+ if (isString(args[1])) ret.defaultValue = args[1];
1798
+ if (isString(args[2])) ret.tDescription = args[2];
1799
+ if (typeof args[2] === "object" || typeof args[3] === "object") {
1800
+ const options = args[3] || args[2];
1801
+ Object.keys(options).forEach((key) => {
1802
+ ret[key] = options[key];
1803
+ });
1804
+ }
1805
+ return ret;
1806
+ },
1807
+ interpolation: {
1808
+ escapeValue: true,
1809
+ format: (value) => value,
1810
+ prefix: "{{",
1811
+ suffix: "}}",
1812
+ formatSeparator: ",",
1813
+ unescapePrefix: "-",
1814
+ nestingPrefix: "$t(",
1815
+ nestingSuffix: ")",
1816
+ nestingOptionsSeparator: ",",
1817
+ maxReplaces: 1e3,
1818
+ skipOnVariables: true
1819
+ },
1820
+ cacheInBuiltFormats: true
1821
+ });
1822
+ var transformOptions = (options) => {
1823
+ if (isString(options.ns)) options.ns = [options.ns];
1824
+ if (isString(options.fallbackLng)) options.fallbackLng = [options.fallbackLng];
1825
+ if (isString(options.fallbackNS)) options.fallbackNS = [options.fallbackNS];
1826
+ if (options.supportedLngs?.indexOf?.("cimode") < 0) {
1827
+ options.supportedLngs = options.supportedLngs.concat(["cimode"]);
1828
+ }
1829
+ if (typeof options.initImmediate === "boolean") options.initAsync = options.initImmediate;
1830
+ return options;
1831
+ };
1832
+ var noop = () => {
1833
+ };
1834
+ var bindMemberFunctions = (inst) => {
1835
+ const mems = Object.getOwnPropertyNames(Object.getPrototypeOf(inst));
1836
+ mems.forEach((mem) => {
1837
+ if (typeof inst[mem] === "function") {
1838
+ inst[mem] = inst[mem].bind(inst);
1839
+ }
1840
+ });
1841
+ };
1842
+ var SUPPORT_NOTICE_KEY = "__i18next_supportNoticeShown";
1843
+ var getSupportNoticeShown = () => typeof globalThis !== "undefined" && !!globalThis[SUPPORT_NOTICE_KEY];
1844
+ var setSupportNoticeShown = () => {
1845
+ if (typeof globalThis !== "undefined") globalThis[SUPPORT_NOTICE_KEY] = true;
1846
+ };
1847
+ var usesLocize = (inst) => {
1848
+ if (inst?.modules?.backend?.name?.indexOf("Locize") > 0) return true;
1849
+ if (inst?.modules?.backend?.constructor?.name?.indexOf("Locize") > 0) return true;
1850
+ if (inst?.options?.backend?.backends) {
1851
+ if (inst.options.backend.backends.some((b) => b?.name?.indexOf("Locize") > 0 || b?.constructor?.name?.indexOf("Locize") > 0)) return true;
1852
+ }
1853
+ if (inst?.options?.backend?.projectId) return true;
1854
+ if (inst?.options?.backend?.backendOptions) {
1855
+ if (inst.options.backend.backendOptions.some((b) => b?.projectId)) return true;
1856
+ }
1857
+ return false;
1858
+ };
1859
+ var I18n = class _I18n extends EventEmitter {
1860
+ constructor(options = {}, callback) {
1861
+ super();
1862
+ this.options = transformOptions(options);
1863
+ this.services = {};
1864
+ this.logger = baseLogger;
1865
+ this.modules = {
1866
+ external: []
1867
+ };
1868
+ bindMemberFunctions(this);
1869
+ if (callback && !this.isInitialized && !options.isClone) {
1870
+ if (!this.options.initAsync) {
1871
+ this.init(options, callback);
1872
+ return this;
1873
+ }
1874
+ setTimeout(() => {
1875
+ this.init(options, callback);
1876
+ }, 0);
1877
+ }
1878
+ }
1879
+ init(options = {}, callback) {
1880
+ this.isInitializing = true;
1881
+ if (typeof options === "function") {
1882
+ callback = options;
1883
+ options = {};
1884
+ }
1885
+ if (options.defaultNS == null && options.ns) {
1886
+ if (isString(options.ns)) {
1887
+ options.defaultNS = options.ns;
1888
+ } else if (options.ns.indexOf("translation") < 0) {
1889
+ options.defaultNS = options.ns[0];
1890
+ }
1891
+ }
1892
+ const defOpts = get();
1893
+ this.options = {
1894
+ ...defOpts,
1895
+ ...this.options,
1896
+ ...transformOptions(options)
1897
+ };
1898
+ this.options.interpolation = {
1899
+ ...defOpts.interpolation,
1900
+ ...this.options.interpolation
1901
+ };
1902
+ if (options.keySeparator !== void 0) {
1903
+ this.options.userDefinedKeySeparator = options.keySeparator;
1904
+ }
1905
+ if (options.nsSeparator !== void 0) {
1906
+ this.options.userDefinedNsSeparator = options.nsSeparator;
1907
+ }
1908
+ if (typeof this.options.overloadTranslationOptionHandler !== "function") {
1909
+ this.options.overloadTranslationOptionHandler = defOpts.overloadTranslationOptionHandler;
1910
+ }
1911
+ if (this.options.showSupportNotice !== false && !usesLocize(this) && !getSupportNoticeShown()) {
1912
+ if (typeof console !== "undefined" && typeof console.info !== "undefined") console.info("\u{1F310} i18next is made possible by our own product, Locize \u2014 consider powering your project with managed localization (AI, CDN, integrations): https://locize.com \u{1F499}");
1913
+ setSupportNoticeShown();
1914
+ }
1915
+ const createClassOnDemand = (ClassOrObject) => {
1916
+ if (!ClassOrObject) return null;
1917
+ if (typeof ClassOrObject === "function") return new ClassOrObject();
1918
+ return ClassOrObject;
1919
+ };
1920
+ if (!this.options.isClone) {
1921
+ if (this.modules.logger) {
1922
+ baseLogger.init(createClassOnDemand(this.modules.logger), this.options);
1923
+ } else {
1924
+ baseLogger.init(null, this.options);
1925
+ }
1926
+ let formatter;
1927
+ if (this.modules.formatter) {
1928
+ formatter = this.modules.formatter;
1929
+ } else {
1930
+ formatter = Formatter;
1931
+ }
1932
+ const lu = new LanguageUtil(this.options);
1933
+ this.store = new ResourceStore(this.options.resources, this.options);
1934
+ const s = this.services;
1935
+ s.logger = baseLogger;
1936
+ s.resourceStore = this.store;
1937
+ s.languageUtils = lu;
1938
+ s.pluralResolver = new PluralResolver(lu, {
1939
+ prepend: this.options.pluralSeparator,
1940
+ simplifyPluralSuffix: this.options.simplifyPluralSuffix
1941
+ });
1942
+ const usingLegacyFormatFunction = this.options.interpolation.format && this.options.interpolation.format !== defOpts.interpolation.format;
1943
+ if (usingLegacyFormatFunction) {
1944
+ this.logger.deprecate(`init: you are still using the legacy format function, please use the new approach: https://www.i18next.com/translation-function/formatting`);
1945
+ }
1946
+ if (formatter && (!this.options.interpolation.format || this.options.interpolation.format === defOpts.interpolation.format)) {
1947
+ s.formatter = createClassOnDemand(formatter);
1948
+ if (s.formatter.init) s.formatter.init(s, this.options);
1949
+ this.options.interpolation.format = s.formatter.format.bind(s.formatter);
1950
+ }
1951
+ s.interpolator = new Interpolator(this.options);
1952
+ s.utils = {
1953
+ hasLoadedNamespace: this.hasLoadedNamespace.bind(this)
1954
+ };
1955
+ s.backendConnector = new Connector(createClassOnDemand(this.modules.backend), s.resourceStore, s, this.options);
1956
+ s.backendConnector.on("*", (event, ...args) => {
1957
+ this.emit(event, ...args);
1958
+ });
1959
+ if (this.modules.languageDetector) {
1960
+ s.languageDetector = createClassOnDemand(this.modules.languageDetector);
1961
+ if (s.languageDetector.init) s.languageDetector.init(s, this.options.detection, this.options);
1962
+ }
1963
+ if (this.modules.i18nFormat) {
1964
+ s.i18nFormat = createClassOnDemand(this.modules.i18nFormat);
1965
+ if (s.i18nFormat.init) s.i18nFormat.init(this);
1966
+ }
1967
+ this.translator = new Translator(this.services, this.options);
1968
+ this.translator.on("*", (event, ...args) => {
1969
+ this.emit(event, ...args);
1970
+ });
1971
+ this.modules.external.forEach((m) => {
1972
+ if (m.init) m.init(this);
1973
+ });
1974
+ }
1975
+ this.format = this.options.interpolation.format;
1976
+ if (!callback) callback = noop;
1977
+ if (this.options.fallbackLng && !this.services.languageDetector && !this.options.lng) {
1978
+ const codes = this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);
1979
+ if (codes.length > 0 && codes[0] !== "dev") this.options.lng = codes[0];
1980
+ }
1981
+ if (!this.services.languageDetector && !this.options.lng) {
1982
+ this.logger.warn("init: no languageDetector is used and no lng is defined");
1983
+ }
1984
+ const storeApi = ["getResource", "hasResourceBundle", "getResourceBundle", "getDataByLanguage"];
1985
+ storeApi.forEach((fcName) => {
1986
+ this[fcName] = (...args) => this.store[fcName](...args);
1987
+ });
1988
+ const storeApiChained = ["addResource", "addResources", "addResourceBundle", "removeResourceBundle"];
1989
+ storeApiChained.forEach((fcName) => {
1990
+ this[fcName] = (...args) => {
1991
+ this.store[fcName](...args);
1992
+ return this;
1993
+ };
1994
+ });
1995
+ const deferred = defer();
1996
+ const load = () => {
1997
+ const finish = (err, t2) => {
1998
+ this.isInitializing = false;
1999
+ if (this.isInitialized && !this.initializedStoreOnce) this.logger.warn("init: i18next is already initialized. You should call init just once!");
2000
+ this.isInitialized = true;
2001
+ if (!this.options.isClone) this.logger.log("initialized", this.options);
2002
+ this.emit("initialized", this.options);
2003
+ deferred.resolve(t2);
2004
+ callback(err, t2);
2005
+ };
2006
+ if (this.languages && !this.isInitialized) return finish(null, this.t.bind(this));
2007
+ this.changeLanguage(this.options.lng, finish);
2008
+ };
2009
+ if (this.options.resources || !this.options.initAsync) {
2010
+ load();
2011
+ } else {
2012
+ setTimeout(load, 0);
2013
+ }
2014
+ return deferred;
2015
+ }
2016
+ loadResources(language, callback = noop) {
2017
+ let usedCallback = callback;
2018
+ const usedLng = isString(language) ? language : this.language;
2019
+ if (typeof language === "function") usedCallback = language;
2020
+ if (!this.options.resources || this.options.partialBundledLanguages) {
2021
+ if (usedLng?.toLowerCase() === "cimode" && (!this.options.preload || this.options.preload.length === 0)) return usedCallback();
2022
+ const toLoad = [];
2023
+ const append = (lng) => {
2024
+ if (!lng) return;
2025
+ if (lng === "cimode") return;
2026
+ const lngs = this.services.languageUtils.toResolveHierarchy(lng);
2027
+ lngs.forEach((l) => {
2028
+ if (l === "cimode") return;
2029
+ if (toLoad.indexOf(l) < 0) toLoad.push(l);
2030
+ });
2031
+ };
2032
+ if (!usedLng) {
2033
+ const fallbacks = this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);
2034
+ fallbacks.forEach((l) => append(l));
2035
+ } else {
2036
+ append(usedLng);
2037
+ }
2038
+ this.options.preload?.forEach?.((l) => append(l));
2039
+ this.services.backendConnector.load(toLoad, this.options.ns, (e) => {
2040
+ if (!e && !this.resolvedLanguage && this.language) this.setResolvedLanguage(this.language);
2041
+ usedCallback(e);
2042
+ });
2043
+ } else {
2044
+ usedCallback(null);
2045
+ }
2046
+ }
2047
+ reloadResources(lngs, ns, callback) {
2048
+ const deferred = defer();
2049
+ if (typeof lngs === "function") {
2050
+ callback = lngs;
2051
+ lngs = void 0;
2052
+ }
2053
+ if (typeof ns === "function") {
2054
+ callback = ns;
2055
+ ns = void 0;
2056
+ }
2057
+ if (!lngs) lngs = this.languages;
2058
+ if (!ns) ns = this.options.ns;
2059
+ if (!callback) callback = noop;
2060
+ this.services.backendConnector.reload(lngs, ns, (err) => {
2061
+ deferred.resolve();
2062
+ callback(err);
2063
+ });
2064
+ return deferred;
2065
+ }
2066
+ use(module) {
2067
+ if (!module) throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");
2068
+ if (!module.type) throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()");
2069
+ if (module.type === "backend") {
2070
+ this.modules.backend = module;
2071
+ }
2072
+ if (module.type === "logger" || module.log && module.warn && module.error) {
2073
+ this.modules.logger = module;
2074
+ }
2075
+ if (module.type === "languageDetector") {
2076
+ this.modules.languageDetector = module;
2077
+ }
2078
+ if (module.type === "i18nFormat") {
2079
+ this.modules.i18nFormat = module;
2080
+ }
2081
+ if (module.type === "postProcessor") {
2082
+ postProcessor.addPostProcessor(module);
2083
+ }
2084
+ if (module.type === "formatter") {
2085
+ this.modules.formatter = module;
2086
+ }
2087
+ if (module.type === "3rdParty") {
2088
+ this.modules.external.push(module);
2089
+ }
2090
+ return this;
2091
+ }
2092
+ setResolvedLanguage(l) {
2093
+ if (!l || !this.languages) return;
2094
+ if (["cimode", "dev"].indexOf(l) > -1) return;
2095
+ for (let li = 0; li < this.languages.length; li++) {
2096
+ const lngInLngs = this.languages[li];
2097
+ if (["cimode", "dev"].indexOf(lngInLngs) > -1) continue;
2098
+ if (this.store.hasLanguageSomeTranslations(lngInLngs)) {
2099
+ this.resolvedLanguage = lngInLngs;
2100
+ break;
2101
+ }
2102
+ }
2103
+ if (!this.resolvedLanguage && this.languages.indexOf(l) < 0 && this.store.hasLanguageSomeTranslations(l)) {
2104
+ this.resolvedLanguage = l;
2105
+ this.languages.unshift(l);
2106
+ }
2107
+ }
2108
+ changeLanguage(lng, callback) {
2109
+ this.isLanguageChangingTo = lng;
2110
+ const deferred = defer();
2111
+ this.emit("languageChanging", lng);
2112
+ const setLngProps = (l) => {
2113
+ this.language = l;
2114
+ this.languages = this.services.languageUtils.toResolveHierarchy(l);
2115
+ this.resolvedLanguage = void 0;
2116
+ this.setResolvedLanguage(l);
2117
+ };
2118
+ const done = (err, l) => {
2119
+ if (l) {
2120
+ if (this.isLanguageChangingTo === lng) {
2121
+ setLngProps(l);
2122
+ this.translator.changeLanguage(l);
2123
+ this.isLanguageChangingTo = void 0;
2124
+ this.emit("languageChanged", l);
2125
+ this.logger.log("languageChanged", l);
2126
+ }
2127
+ } else {
2128
+ this.isLanguageChangingTo = void 0;
2129
+ }
2130
+ deferred.resolve((...args) => this.t(...args));
2131
+ if (callback) callback(err, (...args) => this.t(...args));
2132
+ };
2133
+ const setLng = (lngs) => {
2134
+ if (!lng && !lngs && this.services.languageDetector) lngs = [];
2135
+ const fl = isString(lngs) ? lngs : lngs && lngs[0];
2136
+ const l = this.store.hasLanguageSomeTranslations(fl) ? fl : this.services.languageUtils.getBestMatchFromCodes(isString(lngs) ? [lngs] : lngs);
2137
+ if (l) {
2138
+ if (!this.language) {
2139
+ setLngProps(l);
2140
+ }
2141
+ if (!this.translator.language) this.translator.changeLanguage(l);
2142
+ this.services.languageDetector?.cacheUserLanguage?.(l);
2143
+ }
2144
+ this.loadResources(l, (err) => {
2145
+ done(err, l);
2146
+ });
2147
+ };
2148
+ if (!lng && this.services.languageDetector && !this.services.languageDetector.async) {
2149
+ setLng(this.services.languageDetector.detect());
2150
+ } else if (!lng && this.services.languageDetector && this.services.languageDetector.async) {
2151
+ if (this.services.languageDetector.detect.length === 0) {
2152
+ this.services.languageDetector.detect().then(setLng);
2153
+ } else {
2154
+ this.services.languageDetector.detect(setLng);
2155
+ }
2156
+ } else {
2157
+ setLng(lng);
2158
+ }
2159
+ return deferred;
2160
+ }
2161
+ getFixedT(lng, ns, keyPrefix) {
2162
+ const fixedT = (key, opts, ...rest) => {
2163
+ let o;
2164
+ if (typeof opts !== "object") {
2165
+ o = this.options.overloadTranslationOptionHandler([key, opts].concat(rest));
2166
+ } else {
2167
+ o = {
2168
+ ...opts
2169
+ };
2170
+ }
2171
+ o.lng = o.lng || fixedT.lng;
2172
+ o.lngs = o.lngs || fixedT.lngs;
2173
+ o.ns = o.ns || fixedT.ns;
2174
+ if (o.keyPrefix !== "") o.keyPrefix = o.keyPrefix || keyPrefix || fixedT.keyPrefix;
2175
+ const keySeparator = this.options.keySeparator || ".";
2176
+ let resultKey;
2177
+ if (o.keyPrefix && Array.isArray(key)) {
2178
+ resultKey = key.map((k) => {
2179
+ if (typeof k === "function") k = keysFromSelector(k, {
2180
+ ...this.options,
2181
+ ...opts
2182
+ });
2183
+ return `${o.keyPrefix}${keySeparator}${k}`;
2184
+ });
2185
+ } else {
2186
+ if (typeof key === "function") key = keysFromSelector(key, {
2187
+ ...this.options,
2188
+ ...opts
2189
+ });
2190
+ resultKey = o.keyPrefix ? `${o.keyPrefix}${keySeparator}${key}` : key;
2191
+ }
2192
+ return this.t(resultKey, o);
2193
+ };
2194
+ if (isString(lng)) {
2195
+ fixedT.lng = lng;
2196
+ } else {
2197
+ fixedT.lngs = lng;
2198
+ }
2199
+ fixedT.ns = ns;
2200
+ fixedT.keyPrefix = keyPrefix;
2201
+ return fixedT;
2202
+ }
2203
+ t(...args) {
2204
+ return this.translator?.translate(...args);
2205
+ }
2206
+ exists(...args) {
2207
+ return this.translator?.exists(...args);
2208
+ }
2209
+ setDefaultNamespace(ns) {
2210
+ this.options.defaultNS = ns;
2211
+ }
2212
+ hasLoadedNamespace(ns, options = {}) {
2213
+ if (!this.isInitialized) {
2214
+ this.logger.warn("hasLoadedNamespace: i18next was not initialized", this.languages);
2215
+ return false;
2216
+ }
2217
+ if (!this.languages || !this.languages.length) {
2218
+ this.logger.warn("hasLoadedNamespace: i18n.languages were undefined or empty", this.languages);
2219
+ return false;
2220
+ }
2221
+ const lng = options.lng || this.resolvedLanguage || this.languages[0];
2222
+ const fallbackLng = this.options ? this.options.fallbackLng : false;
2223
+ const lastLng = this.languages[this.languages.length - 1];
2224
+ if (lng.toLowerCase() === "cimode") return true;
2225
+ const loadNotPending = (l, n) => {
2226
+ const loadState = this.services.backendConnector.state[`${l}|${n}`];
2227
+ return loadState === -1 || loadState === 0 || loadState === 2;
2228
+ };
2229
+ if (options.precheck) {
2230
+ const preResult = options.precheck(this, loadNotPending);
2231
+ if (preResult !== void 0) return preResult;
2232
+ }
2233
+ if (this.hasResourceBundle(lng, ns)) return true;
2234
+ if (!this.services.backendConnector.backend || this.options.resources && !this.options.partialBundledLanguages) return true;
2235
+ if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
2236
+ return false;
2237
+ }
2238
+ loadNamespaces(ns, callback) {
2239
+ const deferred = defer();
2240
+ if (!this.options.ns) {
2241
+ if (callback) callback();
2242
+ return Promise.resolve();
2243
+ }
2244
+ if (isString(ns)) ns = [ns];
2245
+ ns.forEach((n) => {
2246
+ if (this.options.ns.indexOf(n) < 0) this.options.ns.push(n);
2247
+ });
2248
+ this.loadResources((err) => {
2249
+ deferred.resolve();
2250
+ if (callback) callback(err);
2251
+ });
2252
+ return deferred;
2253
+ }
2254
+ loadLanguages(lngs, callback) {
2255
+ const deferred = defer();
2256
+ if (isString(lngs)) lngs = [lngs];
2257
+ const preloaded = this.options.preload || [];
2258
+ const newLngs = lngs.filter((lng) => preloaded.indexOf(lng) < 0 && this.services.languageUtils.isSupportedCode(lng));
2259
+ if (!newLngs.length) {
2260
+ if (callback) callback();
2261
+ return Promise.resolve();
2262
+ }
2263
+ this.options.preload = preloaded.concat(newLngs);
2264
+ this.loadResources((err) => {
2265
+ deferred.resolve();
2266
+ if (callback) callback(err);
2267
+ });
2268
+ return deferred;
2269
+ }
2270
+ dir(lng) {
2271
+ if (!lng) lng = this.resolvedLanguage || (this.languages?.length > 0 ? this.languages[0] : this.language);
2272
+ if (!lng) return "rtl";
2273
+ try {
2274
+ const l = new Intl.Locale(lng);
2275
+ if (l && l.getTextInfo) {
2276
+ const ti = l.getTextInfo();
2277
+ if (ti && ti.direction) return ti.direction;
2278
+ }
2279
+ } catch (e) {
2280
+ }
2281
+ const rtlLngs = ["ar", "shu", "sqr", "ssh", "xaa", "yhd", "yud", "aao", "abh", "abv", "acm", "acq", "acw", "acx", "acy", "adf", "ads", "aeb", "aec", "afb", "ajp", "apc", "apd", "arb", "arq", "ars", "ary", "arz", "auz", "avl", "ayh", "ayl", "ayn", "ayp", "bbz", "pga", "he", "iw", "ps", "pbt", "pbu", "pst", "prp", "prd", "ug", "ur", "ydd", "yds", "yih", "ji", "yi", "hbo", "men", "xmn", "fa", "jpr", "peo", "pes", "prs", "dv", "sam", "ckb"];
2282
+ const languageUtils = this.services?.languageUtils || new LanguageUtil(get());
2283
+ if (lng.toLowerCase().indexOf("-latn") > 1) return "ltr";
2284
+ return rtlLngs.indexOf(languageUtils.getLanguagePartFromCode(lng)) > -1 || lng.toLowerCase().indexOf("-arab") > 1 ? "rtl" : "ltr";
2285
+ }
2286
+ static createInstance(options = {}, callback) {
2287
+ const instance2 = new _I18n(options, callback);
2288
+ instance2.createInstance = _I18n.createInstance;
2289
+ return instance2;
2290
+ }
2291
+ cloneInstance(options = {}, callback = noop) {
2292
+ const forkResourceStore = options.forkResourceStore;
2293
+ if (forkResourceStore) delete options.forkResourceStore;
2294
+ const mergedOptions = {
2295
+ ...this.options,
2296
+ ...options,
2297
+ ...{
2298
+ isClone: true
2299
+ }
2300
+ };
2301
+ const clone = new _I18n(mergedOptions);
2302
+ if (options.debug !== void 0 || options.prefix !== void 0) {
2303
+ clone.logger = clone.logger.clone(options);
2304
+ }
2305
+ const membersToCopy = ["store", "services", "language"];
2306
+ membersToCopy.forEach((m) => {
2307
+ clone[m] = this[m];
2308
+ });
2309
+ clone.services = {
2310
+ ...this.services
2311
+ };
2312
+ clone.services.utils = {
2313
+ hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone)
2314
+ };
2315
+ if (forkResourceStore) {
2316
+ const clonedData = Object.keys(this.store.data).reduce((prev, l) => {
2317
+ prev[l] = {
2318
+ ...this.store.data[l]
2319
+ };
2320
+ prev[l] = Object.keys(prev[l]).reduce((acc, n) => {
2321
+ acc[n] = {
2322
+ ...prev[l][n]
2323
+ };
2324
+ return acc;
2325
+ }, prev[l]);
2326
+ return prev;
2327
+ }, {});
2328
+ clone.store = new ResourceStore(clonedData, mergedOptions);
2329
+ clone.services.resourceStore = clone.store;
2330
+ }
2331
+ if (options.interpolation) {
2332
+ const defOpts = get();
2333
+ const mergedInterpolation = {
2334
+ ...defOpts.interpolation,
2335
+ ...this.options.interpolation,
2336
+ ...options.interpolation
2337
+ };
2338
+ const mergedForInterpolator = {
2339
+ ...mergedOptions,
2340
+ interpolation: mergedInterpolation
2341
+ };
2342
+ clone.services.interpolator = new Interpolator(mergedForInterpolator);
2343
+ }
2344
+ clone.translator = new Translator(clone.services, mergedOptions);
2345
+ clone.translator.on("*", (event, ...args) => {
2346
+ clone.emit(event, ...args);
2347
+ });
2348
+ clone.init(mergedOptions, callback);
2349
+ clone.translator.options = mergedOptions;
2350
+ clone.translator.backendConnector.services.utils = {
2351
+ hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone)
2352
+ };
2353
+ return clone;
2354
+ }
2355
+ toJSON() {
2356
+ return {
2357
+ options: this.options,
2358
+ store: this.store,
2359
+ language: this.language,
2360
+ languages: this.languages,
2361
+ resolvedLanguage: this.resolvedLanguage
2362
+ };
2363
+ }
2364
+ };
2365
+ var instance = I18n.createInstance();
2366
+ var createInstance = instance.createInstance;
2367
+ var dir = instance.dir;
2368
+ var init = instance.init;
2369
+ var loadResources = instance.loadResources;
2370
+ var reloadResources = instance.reloadResources;
2371
+ var use = instance.use;
2372
+ var changeLanguage = instance.changeLanguage;
2373
+ var getFixedT = instance.getFixedT;
2374
+ var t = instance.t;
2375
+ var exists = instance.exists;
2376
+ var setDefaultNamespace = instance.setDefaultNamespace;
2377
+ var hasLoadedNamespace = instance.hasLoadedNamespace;
2378
+ var loadNamespaces = instance.loadNamespaces;
2379
+ var loadLanguages = instance.loadLanguages;
2380
+
2381
+ // ../../packages/core/src/i18n/locales/zh/common.json
2382
+ var common_default = {
2383
+ app: { name: "JoWork" },
2384
+ save: "\u4FDD\u5B58",
2385
+ cancel: "\u53D6\u6D88",
2386
+ create: "\u521B\u5EFA",
2387
+ update: "\u66F4\u65B0",
2388
+ delete: "\u5220\u9664",
2389
+ edit: "\u7F16\u8F91",
2390
+ close: "\u5173\u95ED",
2391
+ confirm: "\u786E\u8BA4",
2392
+ loading: "\u52A0\u8F7D\u4E2D...",
2393
+ saving: "\u4FDD\u5B58\u4E2D...",
2394
+ search: "\u641C\u7D22",
2395
+ filter: "\u7B5B\u9009",
2396
+ noResults: "\u65E0\u7ED3\u679C",
2397
+ retry: "\u91CD\u8BD5",
2398
+ back: "\u8FD4\u56DE",
2399
+ next: "\u4E0B\u4E00\u6B65",
2400
+ done: "\u5B8C\u6210",
2401
+ enable: "\u542F\u7528",
2402
+ disable: "\u7981\u7528",
2403
+ personal: "\u4E2A\u4EBA",
2404
+ teamLabel: "\u56E2\u961F",
2405
+ online: "\u5728\u7EBF",
2406
+ offline: "\u79BB\u7EBF",
2407
+ syncing: "\u540C\u6B65\u4E2D",
2408
+ syncComplete: "\u540C\u6B65\u5B8C\u6210",
2409
+ version: "\u7248\u672C",
2410
+ skipToMainContent: "\u8DF3\u8F6C\u5230\u4E3B\u8981\u5185\u5BB9",
2411
+ contextConnectors: "\u8FDE\u63A5\u5668",
2412
+ contextNoConnectors: "\u6682\u65E0\u6D3B\u8DC3\u8FDE\u63A5\u5668",
2413
+ contextInactive: "\u672A\u6FC0\u6D3B",
2414
+ contextPinnedMemories: "\u7F6E\u9876\u8BB0\u5FC6",
2415
+ contextNoMemories: "\u6682\u65E0\u7F6E\u9876\u8BB0\u5FC6",
2416
+ contextRecent: "\u6700\u8FD1",
2417
+ teamMode: "\u56E2\u961F: {{name}}",
2418
+ somethingWentWrong: "\u51FA\u4E86\u70B9\u95EE\u9898",
2419
+ unexpectedError: "\u53D1\u751F\u4E86\u610F\u5916\u9519\u8BEF\u3002",
2420
+ tryAgain: "\u91CD\u8BD5",
2421
+ featureError: "{{name}} \u51FA\u9519",
2422
+ dismissNotification: "\u5173\u95ED\u901A\u77E5",
2423
+ menuFile: "\u6587\u4EF6",
2424
+ menuView: "\u89C6\u56FE",
2425
+ trayShow: "\u663E\u793A JoWork",
2426
+ trayQuickChat: "\u5FEB\u6377\u63D0\u95EE",
2427
+ trayQuit: "\u9000\u51FA",
2428
+ goHome: "\u8FD4\u56DE\u9996\u9875",
2429
+ searchPlaceholder: "\u8F93\u5165\u5173\u952E\u8BCD\u641C\u7D22...",
2430
+ searching: "\u641C\u7D22\u4E2D...",
2431
+ noResultsFound: "\u672A\u627E\u5230\u7ED3\u679C",
2432
+ pages: "\u9875\u9762",
2433
+ conversations: "\u5BF9\u8BDD",
2434
+ messages: "\u6D88\u606F",
2435
+ confirmDelete: "\u786E\u8BA4\u5220\u9664",
2436
+ deleteWarning: "\u6B64\u64CD\u4F5C\u4E0D\u53EF\u64A4\u9500\u3002",
2437
+ savedSuccessfully: "\u4FDD\u5B58\u6210\u529F",
2438
+ deletedSuccessfully: "\u5220\u9664\u6210\u529F",
2439
+ operationFailed: "\u64CD\u4F5C\u5931\u8D25",
2440
+ connectedSuccessfully: "\u8FDE\u63A5\u6210\u529F",
2441
+ disconnectedSuccessfully: "\u5DF2\u65AD\u5F00\u8FDE\u63A5",
2442
+ installedSuccessfully: "\u5B89\u88C5\u6210\u529F",
2443
+ installFailed: "\u5B89\u88C5\u5931\u8D25",
2444
+ copyFailed: "\u590D\u5236\u5931\u8D25",
2445
+ settingsSaved: "\u8BBE\u7F6E\u5DF2\u4FDD\u5B58",
2446
+ v2: "v2",
2447
+ localFirst: "\u672C\u5730\u4F18\u5148",
2448
+ detected: "\u5DF2\u68C0\u6D4B\u5230",
2449
+ notDetected: "\u672A\u68C0\u6D4B\u5230",
2450
+ copy: "\u590D\u5236",
2451
+ copied: "\u5DF2\u590D\u5236\uFF01",
2452
+ error: "\u53D1\u751F\u4E86\u9519\u8BEF"
2453
+ };
2454
+
2455
+ // ../../packages/core/src/i18n/locales/zh/sidebar.json
2456
+ var sidebar_default = {
2457
+ conversation: "AI \u52A9\u624B",
2458
+ dashboard: "\u4EEA\u8868\u76D8",
2459
+ connectors: "\u8FDE\u63A5\u5668",
2460
+ memories: "\u8BB0\u5FC6",
2461
+ skills: "\u6280\u80FD",
2462
+ workstyle: "\u5DE5\u4F5C\u98CE\u683C",
2463
+ scheduler: "\u5B9A\u65F6\u4EFB\u52A1",
2464
+ notifications: "\u901A\u77E5",
2465
+ terminal: "\u7EC8\u7AEF",
2466
+ settings: "\u8BBE\u7F6E",
2467
+ billing: "\u8BA1\u8D39",
2468
+ personal: "\u4E2A\u4EBA\u7248",
2469
+ team: "\u56E2\u961F\u7248",
2470
+ search: "\u641C\u7D22",
2471
+ hideSidebar: "\u9690\u85CF\u4FA7\u8FB9\u680F",
2472
+ showSidebar: "\u663E\u793A\u4FA7\u8FB9\u680F",
2473
+ hidePanel: "\u9690\u85CF\u9762\u677F",
2474
+ showPanel: "\u663E\u793A\u9762\u677F",
2475
+ hideContext: "\u9690\u85CF\u4E0A\u4E0B\u6587",
2476
+ showContext: "\u663E\u793A\u4E0A\u4E0B\u6587",
2477
+ collapse: "\u6536\u8D77",
2478
+ expand: "\u5C55\u5F00",
2479
+ expandNav: "\u5C55\u5F00\u5BFC\u822A",
2480
+ collapseNav: "\u6536\u8D77\u5BFC\u822A",
2481
+ credits: "\u989D\u5EA6",
2482
+ newConversation: "\u53D1\u8D77\u65B0\u5BF9\u8BDD",
2483
+ searchPlaceholder: "\u641C\u7D22 (\u2318K)"
2484
+ };
2485
+
2486
+ // ../../packages/core/src/i18n/locales/zh/chat.json
2487
+ var chat_default = {
2488
+ title: "JoWork AI \u52A9\u624B",
2489
+ placeholder: "\u8F93\u5165\u6D88\u606F... (Enter \u53D1\u9001)",
2490
+ send: "\u53D1\u9001",
2491
+ stop: "\u505C\u6B62",
2492
+ emptyTitle: "\u5F00\u59CB\u65B0\u5BF9\u8BDD",
2493
+ emptyDescription: "\u4E0E AI \u52A9\u624B\u5BF9\u8BDD\uFF0C\u5B83\u53EF\u4EE5\u5E2E\u4F60\u7F16\u7801\u3001\u5206\u6790\u6570\u636E\u7B49\u3002",
2494
+ noConversations: "\u8FD8\u6CA1\u6709\u5BF9\u8BDD",
2495
+ detectingEngines: "\u6B63\u5728\u68C0\u6D4B\u5F15\u64CE...",
2496
+ thinking: "\u601D\u8003\u4E2D...",
2497
+ toolCall: "\u5DE5\u5177\u8C03\u7528",
2498
+ toolResult: "\u5DE5\u5177\u7ED3\u679C",
2499
+ toolsUsed: "\u4F7F\u7528\u4E86 {{count}} \u4E2A\u5DE5\u5177",
2500
+ conversations: "\u5BF9\u8BDD",
2501
+ newConversation: "\u65B0\u5BF9\u8BDD",
2502
+ deleteConversation: "\u5220\u9664\u5BF9\u8BDD",
2503
+ renameConversation: "\u91CD\u547D\u540D\u5BF9\u8BDD",
2504
+ searchConversations: "\u641C\u7D22\u5BF9\u8BDD...",
2505
+ export: "\u5BFC\u51FA",
2506
+ exportConversation: "\u5BFC\u51FA\u5BF9\u8BDD",
2507
+ exportMarkdown: "Markdown (.md)",
2508
+ exportJson: "JSON (.json)",
2509
+ loadOlder: "\u52A0\u8F7D\u66F4\u65E9\u6D88\u606F",
2510
+ loadingOlder: "\u52A0\u8F7D\u4E2D...",
2511
+ noMatchingConversations: "\u6CA1\u6709\u5339\u914D\u7684\u5BF9\u8BDD",
2512
+ dropFilesHere: "\u62D6\u653E\u6587\u4EF6\u5230\u6B64\u5904...",
2513
+ inputAriaLabel: "\u804A\u5929\u6D88\u606F\u8F93\u5165",
2514
+ stopAriaLabel: "\u505C\u6B62 AI \u56DE\u590D",
2515
+ sendAriaLabel: "\u53D1\u9001\u6D88\u606F",
2516
+ actionConfirmation: "\u64CD\u4F5C\u786E\u8BA4",
2517
+ riskLow: "\u4F4E\u98CE\u9669",
2518
+ riskMedium: "\u4E2D\u7B49\u98CE\u9669",
2519
+ riskHigh: "\u9AD8\u98CE\u9669",
2520
+ alwaysAllow: "\u59CB\u7EC8\u5141\u8BB8\u6B64\u64CD\u4F5C",
2521
+ deny: "\u62D2\u7EDD",
2522
+ allow: "\u5141\u8BB8",
2523
+ notInstalled: "\u672A\u5B89\u88C5",
2524
+ engineClaudeCode: "Claude Code",
2525
+ engineOpenClaw: "OpenClaw",
2526
+ engineCodex: "Codex",
2527
+ engineNemoClaw: "NemoClaw",
2528
+ engineJoworkCloud: "JoWork \u4E91\u7AEF",
2529
+ launcherPlaceholder: "\u5411 JoWork \u63D0\u95EE...",
2530
+ recent: "\u6700\u8FD1",
2531
+ launcherHint: "\u6309 Enter \u63D0\u95EE\uFF0CEsc \u5173\u95ED",
2532
+ skillsLabel: "\u53EF\u7528\u6280\u80FD",
2533
+ engineCrashed: "AI \u5F15\u64CE\u5D29\u6E83\uFF0C\u6B63\u5728\u91CD\u542F... (\u7B2C {{retries}} \u6B21)",
2534
+ engineCrashFatal: "AI \u5F15\u64CE\u5728 {{max}} \u6B21\u91CD\u542F\u540E\u4ECD\u7136\u5931\u8D25\uFF0C\u8BF7\u5728\u8BBE\u7F6E\u4E2D\u5207\u6362\u5F15\u64CE\u3002",
2535
+ engineRestartReady: "AI \u5F15\u64CE\u5DF2\u91CD\u65B0\u542F\u52A8\u3002",
2536
+ launcherTitle: "JoWork \u5FEB\u6377\u63D0\u95EE",
2537
+ launcherClose: "\u5173\u95ED",
2538
+ launcherOpenMain: "\u6253\u5F00\u4E3B\u7A97\u53E3",
2539
+ launcherModes: "\u6A21\u5F0F",
2540
+ launcherAskAI: "AI \u95EE\u7B54",
2541
+ launcherRunCommand: "\u6267\u884C\u547D\u4EE4",
2542
+ launcherJumpToPage: "\u8DF3\u8F6C\u9875\u9762",
2543
+ timeJustNow: "\u521A\u521A",
2544
+ timeMinutesAgo: "{{count}}\u5206\u949F\u524D",
2545
+ engineError: "\u5F15\u64CE\u9519\u8BEF",
2546
+ retryMessage: "\u91CD\u8BD5",
2547
+ scrollToBottom: "\u8DF3\u5230\u6700\u65B0",
2548
+ exportSuccess: "\u5BF9\u8BDD\u5DF2\u5BFC\u51FA",
2549
+ exportFailed: "\u5BFC\u51FA\u5931\u8D25",
2550
+ deleteSuccess: "\u5BF9\u8BDD\u5DF2\u5220\u9664",
2551
+ deleteConfirmTitle: "\u5220\u9664\u5BF9\u8BDD\uFF1F",
2552
+ deleteConfirmMessage: "\u6B64\u64CD\u4F5C\u4E0D\u53EF\u64A4\u9500\u3002",
2553
+ expand: "\u5C55\u5F00",
2554
+ collapse: "\u6536\u8D77",
2555
+ toolConfirmation: "\u5DE5\u5177\u786E\u8BA4",
2556
+ renameSession: "\u91CD\u547D\u540D",
2557
+ saveAsSkill: "\u4FDD\u5B58\u4E3A\u6280\u80FD",
2558
+ generatingSkill: "\u751F\u6210\u4E2D\u2026",
2559
+ skillGenerateFailed: "\u6280\u80FD\u751F\u6210\u5931\u8D25",
2560
+ deleteConfirm: "\u5220\u9664\uFF1F",
2561
+ paramsCount: "{{count}} \u4E2A\u53C2\u6570",
2562
+ starterPrompt1: "\u5E2E\u6211\u89C4\u5212\u4ECA\u5929\uFF0C\u6211\u5E94\u8BE5\u5148\u505A\u4EC0\u4E48\uFF1F",
2563
+ starterPrompt2: "\u6211\u6709\u4E2A\u7C97\u7565\u7684\u60F3\u6CD5\uFF0C\u5E2E\u6211\u68B3\u7406\u6E05\u695A\uFF0C\u53D8\u6210\u53EF\u6267\u884C\u7684\u65B9\u6848\u3002",
2564
+ starterPrompt3: "\u4EC0\u4E48\u5728\u963B\u788D\u6211\u7684\u8FDB\u5C55\uFF1F\u5E2E\u6211\u627E\u51FA\u771F\u6B63\u7684\u74F6\u9888\u3002",
2565
+ quotaExhaustedTitle: "\u4ECA\u65E5\u514D\u8D39\u5BF9\u8BDD\u5DF2\u7528\u5B8C",
2566
+ quotaExhaustedDesc: "\u660E\u5929 00:00 UTC \u91CD\u7F6E\uFF0C\u6216\u5347\u7EA7 Pro \u7EE7\u7EED\u4F7F\u7528",
2567
+ upgradePro: "\u5347\u7EA7 Pro",
2568
+ waitUntilTomorrow: "\u7B49\u5230\u660E\u5929",
2569
+ switchEngine: "\u5207\u6362\u5F15\u64CE",
2570
+ showSidebar: "\u663E\u793A\u9762\u677F",
2571
+ hideSidebar: "\u9690\u85CF\u9762\u677F"
2572
+ };
2573
+
2574
+ // ../../packages/core/src/i18n/locales/zh/connectors.json
2575
+ var connectors_default = {
2576
+ title: "\u8FDE\u63A5\u5668",
2577
+ description: "\u8FDE\u63A5\u4F60\u7684\u5DE5\u5177\u548C\u6570\u636E\u6E90\u5230 JoWork\u3002",
2578
+ connected: "\u5DF2\u8FDE\u63A5",
2579
+ connectedCount: "{{count}} \u4E2A\u5DF2\u8FDE\u63A5",
2580
+ all: "\u5168\u90E8",
2581
+ available: "\u53EF\u7528\u6570\u636E\u6E90",
2582
+ noConnected: "\u5C1A\u672A\u8FDE\u63A5\u4EFB\u4F55\u6570\u636E\u6E90\uFF0C\u4ECE\u4E0B\u65B9\u9009\u62E9\u4E00\u4E2A\u5F00\u59CB\u914D\u7F6E\u3002",
2583
+ credentialStored: "\u51ED\u636E\u5DF2\u4FDD\u5B58",
2584
+ needsAuth: "\u9700\u8981\u6388\u6743",
2585
+ core: "\u6838\u5FC3\u8FDE\u63A5\u5668",
2586
+ more: "\u66F4\u591A\u8FDE\u63A5\u5668",
2587
+ configure: "\u914D\u7F6E",
2588
+ connect: "\u8FDE\u63A5",
2589
+ disconnect: "\u65AD\u5F00",
2590
+ loading: "\u52A0\u8F7D\u8FDE\u63A5\u5668...",
2591
+ loadingDescription: "\u6B63\u5728\u68C0\u67E5\u6570\u636E\u6E90\u72B6\u6001...",
2592
+ tokenPlaceholder: "Access Token \u6216 API Key",
2593
+ health: "\u5065\u5EB7\u72B6\u6001",
2594
+ healthy: "\u6B63\u5E38",
2595
+ unhealthy: "\u5F02\u5E38",
2596
+ lastSync: "\u4E0A\u6B21\u540C\u6B65",
2597
+ authorize: "\u6388\u6743",
2598
+ revoke: "\u64A4\u9500\u6388\u6743",
2599
+ tierBeta: "\u6D4B\u8BD5\u7248",
2600
+ tierPlanned: "\u8BA1\u5212\u4E2D",
2601
+ authorizeTitle: "\u6388\u6743 {{name}}",
2602
+ authorizeDescription: "\u5C06\u6253\u5F00\u6D4F\u89C8\u5668\u7A97\u53E3\uFF0C\u6388\u6743 JoWork \u8BBF\u95EE\u4F60\u7684 {{name}} \u6570\u636E\u3002",
2603
+ noHealthData: "\u6682\u65E0\u5065\u5EB7\u6570\u636E\u3002",
2604
+ status: "\u72B6\u6001",
2605
+ syncedData: "\u5DF2\u540C\u6B65\u6570\u636E",
2606
+ noSyncedData: "\u6682\u65E0\u540C\u6B65\u6570\u636E\u3002",
2607
+ syncLog: "\u540C\u6B65\u65E5\u5FD7",
2608
+ noSyncActivity: "\u6682\u65E0\u540C\u6B65\u6D3B\u52A8\u3002",
2609
+ disconnectConfirmTitle: "\u65AD\u5F00 {{name}}\uFF1F",
2610
+ disconnectConfirmMessage: "\u5C06\u79FB\u9664\u8FDE\u63A5\u5E76\u64A4\u9500\u8BBF\u95EE\u6743\u9650\u3002",
2611
+ authorization: "\u6388\u6743",
2612
+ comingSoon: "\u5373\u5C06\u63A8\u51FA",
2613
+ saveAndConnect: "\u4FDD\u5B58\u5E76\u8FDE\u63A5",
2614
+ signIn: "\u767B\u5F55",
2615
+ authorizing: "\u767B\u5F55\u4E2D\u2026",
2616
+ connecting: "\u8FDE\u63A5\u4E2D\u2026",
2617
+ cat_code: "\u4EE3\u7801",
2618
+ cat_design: "\u8BBE\u8BA1",
2619
+ cat_communication: "\u901A\u8BAF",
2620
+ cat_docs: "\u6587\u6863",
2621
+ cat_local: "\u672C\u5730",
2622
+ cat_analytics: "\u641C\u7D22",
2623
+ c_github_name: "GitHub",
2624
+ c_github_desc: "\u4EE3\u7801\u4ED3\u5E93\u3001Issues\u3001Pull Requests",
2625
+ c_gitlab_name: "GitLab",
2626
+ c_gitlab_desc: "\u9879\u76EE\u3001\u5408\u5E76\u8BF7\u6C42\u3001Issues",
2627
+ c_figma_name: "Figma",
2628
+ c_figma_desc: "\u8BBE\u8BA1\u6587\u4EF6\u548C\u7EC4\u4EF6",
2629
+ "c_local-folder_name": "\u672C\u5730\u9879\u76EE",
2630
+ "c_local-folder_desc": "\u8BA9 Claude \u8BBF\u95EE\u672C\u5730\u6587\u4EF6\u5939",
2631
+ c_feishu_name: "\u98DE\u4E66 \xB7 \u7EC4\u7EC7\u6570\u636E",
2632
+ c_feishu_desc: "\u7FA4\u6D88\u606F\u3001\u7EC4\u7EC7\u6587\u6863\u3001\u65E5\u5386\uFF08\u9700\u8981 Bot App \u51ED\u8BC1\uFF09",
2633
+ c_notion_name: "Notion",
2634
+ c_notion_desc: "\u9875\u9762\u3001\u6570\u636E\u5E93\u3001\u5DE5\u4F5C\u533A\u77E5\u8BC6",
2635
+ c_slack_name: "Slack",
2636
+ c_slack_desc: "\u9891\u9053\u3001\u6D88\u606F\u3001\u56E2\u961F\u6C9F\u901A",
2637
+ "c_brave-search_name": "\u7F51\u9875\u641C\u7D22",
2638
+ "c_brave-search_desc": "\u901A\u8FC7 Brave Search API \u8FDB\u884C\u5B9E\u65F6\u7F51\u9875\u641C\u7D22",
2639
+ c_posthog_name: "PostHog",
2640
+ c_posthog_desc: "\u4EA7\u54C1\u5206\u6790\u3001\u529F\u80FD\u5F00\u5173\u3001\u4F1A\u8BDD\u5F55\u5236",
2641
+ c_linear_name: "Linear",
2642
+ c_linear_desc: "Issue \u7BA1\u7406\u3001\u9879\u76EE\u3001\u8FED\u4EE3\u3001\u8DEF\u7EBF\u56FE",
2643
+ "c_feishu-personal_name": "\u98DE\u4E66 \xB7 \u4E2A\u4EBA\u6570\u636E",
2644
+ "c_feishu-personal_desc": "\u4E2A\u4EBA\u6587\u6863\u3001\u79C1\u804A\u6D88\u606F\u3001\u65E5\u5386\u3001\u90AE\u4EF6\uFF08\u767B\u5F55 JoWork Cloud \u540E\u4E00\u952E\u6388\u6743\uFF09",
2645
+ feishuPersonalRequiresLogin: "\u8BF7\u5148\u767B\u5F55 JoWork Cloud \u4EE5\u8FDE\u63A5\u98DE\u4E66\u4E2A\u4EBA\u6570\u636E",
2646
+ type_local: "\u672C\u673A\u6570\u636E",
2647
+ type_local_desc: "\u8BA9 AI \u76F4\u63A5\u8BBF\u95EE\u672C\u5730\u6587\u4EF6\u548C\u6587\u4EF6\u5939",
2648
+ type_sync: "\u7EBF\u4E0A\u6570\u636E",
2649
+ type_sync_desc: "\u5B9A\u65F6\u589E\u91CF\u540C\u6B65\u5230\u672C\u5730\uFF0C\u652F\u6301\u5FEB\u901F\u641C\u7D22",
2650
+ type_mcp: "MCP \u5DE5\u5177",
2651
+ type_mcp_desc: "\u6309\u9700\u8BF7\u6C42\uFF0C\u7528\u65F6\u83B7\u53D6\u6570\u636E",
2652
+ addFolder: "\u6DFB\u52A0\u6587\u4EF6\u5939",
2653
+ folderName: "\u663E\u793A\u540D\u79F0",
2654
+ folderPath: "\u6587\u4EF6\u5939\u8DEF\u5F84",
2655
+ removeInstance: "\u79FB\u9664",
2656
+ removeInstanceConfirm: "\u79FB\u9664\u6B64\u6587\u4EF6\u5939\uFF1F"
2657
+ };
2658
+
2659
+ // ../../packages/core/src/i18n/locales/zh/settings.json
2660
+ var settings_default = {
2661
+ title: "\u8BBE\u7F6E",
2662
+ general: "\u901A\u7528",
2663
+ appearance: "\u5916\u89C2",
2664
+ engines: "AI \u5F15\u64CE",
2665
+ about: "\u5173\u4E8E",
2666
+ themeLight: "\u6D45\u8272",
2667
+ themeDark: "\u6DF1\u8272",
2668
+ themeSystem: "\u8DDF\u968F\u7CFB\u7EDF",
2669
+ language: "\u8BED\u8A00",
2670
+ update: "\u66F4\u65B0",
2671
+ checkUpdate: "\u68C0\u67E5\u66F4\u65B0",
2672
+ updateAvailable: "\u6709\u65B0\u7248\u672C\u53EF\u7528",
2673
+ updateDownloaded: "\u66F4\u65B0\u5DF2\u4E0B\u8F7D\uFF0C\u91CD\u542F\u540E\u5B89\u88C5",
2674
+ restartToUpdate: "\u7ACB\u5373\u91CD\u542F\u66F4\u65B0",
2675
+ upToDate: "\u5DF2\u662F\u6700\u65B0\u7248\u672C",
2676
+ checking: "\u68C0\u67E5\u4E2D...",
2677
+ keyboardShortcuts: "\u952E\u76D8\u5FEB\u6377\u952E",
2678
+ shortcutHint: "\u5728 Windows/Linux \u4E0A\uFF0C\u8BF7\u7528 Ctrl \u66FF\u4EE3 Cmd\u3002",
2679
+ shortcutNewConversation: "\u65B0\u5EFA\u5BF9\u8BDD",
2680
+ shortcutGlobalSearch: "\u5168\u5C40\u641C\u7D22",
2681
+ shortcutQuickLauncher: "\u5FEB\u6377\u542F\u52A8\u5668",
2682
+ shortcutExport: "\u5BFC\u51FA\u5BF9\u8BDD",
2683
+ shortcutSettings: "\u8BBE\u7F6E",
2684
+ shortcutSend: "\u53D1\u9001\u6D88\u606F",
2685
+ shortcutStop: "\u505C\u6B62 / \u5173\u95ED",
2686
+ shortcutTerminal: "\u6253\u5F00\u7EC8\u7AEF",
2687
+ shortcutCloseWindow: "\u5173\u95ED\u7A97\u53E3",
2688
+ workstyleTitle: "\u5DE5\u4F5C\u98CE\u683C",
2689
+ workstyleDescription: "\u5B9A\u4E49 AI \u5982\u4F55\u914D\u5408\u4F60\u5DE5\u4F5C\u3002\u6B64\u5185\u5BB9\u4F1A\u6CE8\u5165\u6BCF\u6B21\u5BF9\u8BDD\u3002",
2690
+ workstylePlaceholder: "\u7528 Markdown \u7F16\u5199\u4F60\u7684\u5DE5\u4F5C\u98CE\u683C\u6307\u5357...",
2691
+ workstyleHint: "\u652F\u6301 Markdown\u3002\u6B64\u6587\u6863\u4F1A\u4F5C\u4E3A\u4E0A\u4E0B\u6587\u6CE8\u5165\u6BCF\u6B21 AI \u5BF9\u8BDD\u3002",
2692
+ saved: "\u5DF2\u4FDD\u5B58\uFF01",
2693
+ workstyleTemplate: "# \u6211\u7684\u5DE5\u4F5C\u98CE\u683C\n\n## \u89D2\u8272\n[\u4F60\u7684\u804C\u4F4D\u548C\u804C\u8D23]\n\n## \u6C9F\u901A\u504F\u597D\n- \u56DE\u590D\u98CE\u683C: [\u7B80\u6D01/\u8BE6\u7EC6]\n- \u8BED\u8A00: [\u4E2D\u6587/\u82F1\u6587/\u53CC\u8BED]\n\n## \u5DE5\u4F5C\u4E60\u60EF\n[\u4F60\u7684\u65E5\u5E38\u5DE5\u4F5C\u6D41\u7A0B]\n\n## \u91CD\u8981\u89C4\u5219\n[AI \u5FC5\u987B\u9075\u5B88\u7684\u89C4\u5219]\n",
2694
+ terminalTitle: "\u7EC8\u7AEF",
2695
+ terminalTab: "\u7EC8\u7AEF {{n}}",
2696
+ stylePrompt: "\u98CE\u683C\u63D0\u793A\u8BCD",
2697
+ quickAccess: "\u5FEB\u6377\u5165\u53E3"
2698
+ };
2699
+
2700
+ // ../../packages/core/src/i18n/locales/zh/billing.json
2701
+ var billing_default = {
2702
+ title: "\u8BA1\u8D39",
2703
+ credits: "\u79EF\u5206",
2704
+ remaining: "\u5269\u4F59",
2705
+ used: "\u672C\u5468\u671F\u5DF2\u7528",
2706
+ wallet: "\u94B1\u5305\u4F59\u989D",
2707
+ buyCredits: "\u8D2D\u4E70\u79EF\u5206",
2708
+ plans: "\u65B9\u6848",
2709
+ currentPlan: "\u5F53\u524D\u65B9\u6848",
2710
+ upgrade: "\u5347\u7EA7",
2711
+ manageSubscription: "\u7BA1\u7406\u8BA2\u9605",
2712
+ signInRequired: "\u767B\u5F55\u540E\u53EF\u4F7F\u7528\u8BA1\u8D39\u548C\u4E91\u79EF\u5206\u529F\u80FD\u3002",
2713
+ buyAmount: "\u8D2D\u4E70 {{amount}} \u79EF\u5206",
2714
+ free: "\u514D\u8D39",
2715
+ pro: "\u4E13\u4E1A\u7248",
2716
+ teamPlan: "\u56E2\u961F\u7248",
2717
+ perMonth: "/\u6708",
2718
+ usageChart: "\u7528\u91CF\u7EDF\u8BA1",
2719
+ dailyUsage: "\u6BCF\u65E5\u7528\u91CF\uFF087\u5929\uFF09",
2720
+ creditsLeft: "\u5269\u4F59 {{count}}",
2721
+ walletBalance: "+{{count}} \u94B1\u5305",
2722
+ creditsPerMonth: "{{count}} \u79EF\u5206/\u6708",
2723
+ downgrade: "\u964D\u7EA7",
2724
+ dailyLimit: "\u9650\u989D\uFF1A{{limit}}/\u5929",
2725
+ usageHistory: "\u7528\u91CF\u5386\u53F2",
2726
+ creditOverview: "\u989D\u5EA6\u6982\u89C8"
2727
+ };
2728
+
2729
+ // ../../packages/core/src/i18n/locales/zh/team.json
2730
+ var team_default = {
2731
+ title: "\u56E2\u961F",
2732
+ members: "\u6210\u5458",
2733
+ invite: "\u9080\u8BF7\u6210\u5458",
2734
+ createTeam: "\u521B\u5EFA\u56E2\u961F",
2735
+ settings: "\u56E2\u961F\u8BBE\u7F6E",
2736
+ signInRequired: "\u767B\u5F55\u540E\u53EF\u521B\u5EFA\u6216\u52A0\u5165\u56E2\u961F\u5DE5\u4F5C\u533A\u3002",
2737
+ yourTeams: "\u4F60\u7684\u56E2\u961F",
2738
+ switch: "\u5207\u6362",
2739
+ owner: "\u6240\u6709\u8005",
2740
+ admin: "\u7BA1\u7406\u5458",
2741
+ member: "\u6210\u5458",
2742
+ teamName: "\u56E2\u961F\u540D\u79F0",
2743
+ memberCount: "{{count}} \u4F4D\u6210\u5458",
2744
+ creating: "\u521B\u5EFA\u4E2D...",
2745
+ inviteLink: "\u9080\u8BF7\u94FE\u63A5",
2746
+ copyLink: "\u590D\u5236\u94FE\u63A5",
2747
+ linkCopied: "\u5DF2\u590D\u5236",
2748
+ removeMember: "\u79FB\u9664\u6210\u5458",
2749
+ changeRole: "\u66F4\u6539\u89D2\u8272",
2750
+ leaveTeam: "\u79BB\u5F00\u56E2\u961F",
2751
+ inviteTitle: "\u9080\u8BF7\u56E2\u961F\u6210\u5458",
2752
+ inviteDescription: "\u751F\u6210\u9080\u8BF7\u94FE\u63A5\u5E76\u5206\u4EAB\u7ED9\u4F60\u7684\u56E2\u961F\u6210\u5458\u3002",
2753
+ generating: "\u751F\u6210\u4E2D...",
2754
+ generateInviteLink: "\u751F\u6210\u9080\u8BF7\u94FE\u63A5",
2755
+ inviteUrl: "\u9080\u8BF7\u94FE\u63A5",
2756
+ inviteExpiry: "\u6B64\u94FE\u63A5 7 \u5929\u540E\u8FC7\u671F\u3002\u4EFB\u4F55\u4EBA\u90FD\u53EF\u4EE5\u901A\u8FC7\u6B64\u94FE\u63A5\u52A0\u5165\u56E2\u961F\u3002",
2757
+ teamId: "\u56E2\u961F ID",
2758
+ remove: "\u79FB\u9664",
2759
+ createTeamDescription: "\u4E3A\u4F60\u7684\u7EC4\u7EC7\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684\u534F\u4F5C\u7A7A\u95F4\u3002",
2760
+ removeConfirmTitle: "\u79FB\u9664\u6210\u5458\uFF1F",
2761
+ removeConfirmMessage: "\u8BE5\u6210\u5458\u5C06\u5931\u53BB\u56E2\u961F\u8D44\u6E90\u7684\u8BBF\u95EE\u6743\u9650\u3002",
2762
+ noTeams: "\u4F60\u8FD8\u6CA1\u6709\u52A0\u5165\u4EFB\u4F55\u56E2\u961F\u3002",
2763
+ inviteError: "\u751F\u6210\u9080\u8BF7\u94FE\u63A5\u5931\u8D25"
2764
+ };
2765
+
2766
+ // ../../packages/core/src/i18n/locales/zh/memory.json
2767
+ var memory_default = {
2768
+ title: "\u8BB0\u5FC6",
2769
+ description: "AI \u8DE8\u5BF9\u8BDD\u8BB0\u4F4F\u7684\u5173\u4E8E\u4F60\u7684\u4FE1\u606F\u3002",
2770
+ new: "\u65B0\u5EFA",
2771
+ editMemory: "\u7F16\u8F91\u8BB0\u5FC6",
2772
+ newMemory: "\u65B0\u5EFA\u8BB0\u5FC6",
2773
+ titlePlaceholder: "\u8BB0\u5FC6\u6807\u9898",
2774
+ contentPlaceholder: "\u8BB0\u5FC6\u5185\u5BB9...",
2775
+ tagsPlaceholder: "\u6807\u7B7E\uFF08\u9017\u53F7\u5206\u9694\uFF09",
2776
+ pinned: "\u5DF2\u7F6E\u9876",
2777
+ allMemories: "\u6240\u6709\u8BB0\u5FC6",
2778
+ noMemories: "\u8FD8\u6CA1\u6709\u8BB0\u5FC6\u3002",
2779
+ noMemoriesHint: "\u624B\u52A8\u521B\u5EFA\u6216\u8BA9 AI \u4ECE\u5BF9\u8BDD\u4E2D\u5B66\u4E60\u3002",
2780
+ pin: "\u7F6E\u9876",
2781
+ unpin: "\u53D6\u6D88\u7F6E\u9876",
2782
+ searchMemories: "\u641C\u7D22\u8BB0\u5FC6...",
2783
+ sourceAuto: "\u81EA\u52A8",
2784
+ sourceManual: "\u624B\u52A8",
2785
+ scope: "\u8303\u56F4",
2786
+ scopePersonal: "\u4E2A\u4EBA",
2787
+ scopeTeam: "\u56E2\u961F",
2788
+ deleteConfirmTitle: "\u5220\u9664\u8BB0\u5FC6\uFF1F",
2789
+ deleteConfirmMessage: "\u6B64\u8BB0\u5FC6\u5C06\u88AB\u6C38\u4E45\u5220\u9664\u3002"
2790
+ };
2791
+
2792
+ // ../../packages/core/src/i18n/locales/zh/skills.json
2793
+ var skills_default = {
2794
+ title: "\u6280\u80FD",
2795
+ description: "\u6765\u81EA\u591A\u4E2A\u6765\u6E90\u7684\u53EF\u590D\u7528\u63D0\u793A\u8BCD\u548C\u5DE5\u4F5C\u6D41\u3002",
2796
+ filterPlaceholder: "\u7B5B\u9009\u6280\u80FD...",
2797
+ noSkills: "\u672A\u627E\u5230\u6280\u80FD\u3002",
2798
+ noSkillsHint: "\u6DFB\u52A0 .md \u6587\u4EF6\u5230 ~/.claude/commands/ \u6216 ~/.claude/skills/",
2799
+ sourceClaudeCode: "Claude Code",
2800
+ sourceJowork: "JoWork",
2801
+ sourceOpenclaw: "OpenClaw",
2802
+ sourceCommunity: "\u793E\u533A",
2803
+ loading: "\u52A0\u8F7D\u6280\u80FD...",
2804
+ run: "\u8FD0\u884C",
2805
+ details: "\u8BE6\u60C5",
2806
+ marketplace: "\u6280\u80FD\u5E02\u573A",
2807
+ createSkill: "\u521B\u5EFA",
2808
+ variableCount: "{{count}} \u4E2A\u53D8\u91CF",
2809
+ variableCount_one: "{{count}} \u4E2A\u53D8\u91CF",
2810
+ runSkill: "\u8FD0\u884C\u6280\u80FD",
2811
+ running: "\u8FD0\u884C\u4E2D...",
2812
+ selectPlaceholder: "\u9009\u62E9...",
2813
+ createCustomSkill: "\u521B\u5EFA\u81EA\u5B9A\u4E49\u6280\u80FD",
2814
+ skillName: "\u540D\u79F0",
2815
+ skillTrigger: "\u89E6\u53D1\u5668",
2816
+ skillDescription: "\u63CF\u8FF0",
2817
+ promptTemplate: "\u63D0\u793A\u8BCD\u6A21\u677F",
2818
+ promptPlaceholder: "\u4F7F\u7528 {{variable_name}} \u63D2\u5165\u52A8\u6001\u503C...",
2819
+ variables: "\u53D8\u91CF",
2820
+ addVariable: "+ \u6DFB\u52A0\u53D8\u91CF",
2821
+ varLabel: "\u6807\u7B7E",
2822
+ varTypeText: "\u6587\u672C",
2823
+ varTypeMultiline: "\u591A\u884C",
2824
+ varTypeSelect: "\u9009\u62E9",
2825
+ varRequired: "\u5FC5\u586B",
2826
+ saveSkill: "\u4FDD\u5B58\u6280\u80FD",
2827
+ skillMarketplace: "\u6280\u80FD\u5E02\u573A",
2828
+ browseSkills: "\u6D4F\u89C8\u548C\u5B89\u88C5\u793E\u533A\u6280\u80FD",
2829
+ searchSkills: "\u641C\u7D22\u6280\u80FD...",
2830
+ installCount: "{{count}} \u6B21\u5B89\u88C5",
2831
+ install: "\u5B89\u88C5",
2832
+ installed: "\u5DF2\u5B89\u88C5",
2833
+ noSkillsMatch: "\u6CA1\u6709\u5339\u914D\u7684\u6280\u80FD\u3002",
2834
+ skillLibrary: "\u6280\u80FD\u5E93",
2835
+ customSkillLabel: "\u81EA\u5B9A\u4E49\u6280\u80FD",
2836
+ fromConversation: "\u4ECE\u5BF9\u8BDD\u521B\u5EFA",
2837
+ reviewAndSaveSkill: "\u5BA1\u67E5\u5E76\u4FDD\u5B58\u6280\u80FD",
2838
+ skillType: "\u7C7B\u578B",
2839
+ typeSimple: "\u7B80\u5355",
2840
+ typeWorkflow: "\u5DE5\u4F5C\u6D41",
2841
+ workflowSteps: "\u6B65\u9AA4",
2842
+ addStep: "\u6DFB\u52A0\u6B65\u9AA4",
2843
+ noStepsYet: "\u6682\u65E0\u6B65\u9AA4\uFF0C\u6DFB\u52A0\u6B65\u9AA4\u6765\u5B9A\u4E49\u5DE5\u4F5C\u6D41\u3002",
2844
+ step: "\u6B65\u9AA4",
2845
+ stepPromptPlaceholder: "\u6B65\u9AA4\u63D0\u793A\u8BCD\u2026",
2846
+ outputVar: "\u8F93\u51FA\u53D8\u91CF\uFF08\u53EF\u9009\uFF09",
2847
+ stepCondition: "\u6267\u884C\u6761\u4EF6\uFF08\u53EF\u9009\uFF09",
2848
+ namePlaceholder: "\u6211\u7684\u6280\u80FD",
2849
+ triggerPlaceholder: "/\u6211\u7684\u6280\u80FD",
2850
+ varNamePlaceholder: "\u53D8\u91CF\u540D"
2851
+ };
2852
+
2853
+ // ../../packages/core/src/i18n/locales/zh/scheduler.json
2854
+ var scheduler_default = {
2855
+ title: "\u5B9A\u65F6\u4EFB\u52A1",
2856
+ description: "\u81EA\u52A8\u5316\u6570\u636E\u626B\u63CF\u3001\u6280\u80FD\u6267\u884C\u548C\u901A\u77E5\u7B49\u5468\u671F\u6027\u4EFB\u52A1\u3002",
2857
+ newTask: "\u65B0\u5EFA\u4EFB\u52A1",
2858
+ editTask: "\u7F16\u8F91\u4EFB\u52A1",
2859
+ namePlaceholder: "\u4EFB\u52A1\u540D\u79F0",
2860
+ cronPlaceholder: "Cron \u8868\u8FBE\u5F0F (\u5982 0 10 * * *)",
2861
+ cloudExecution: "\u79BB\u7EBF\u65F6\u542F\u7528\u4E91\u7AEF\u6267\u884C",
2862
+ noTasks: "\u8FD8\u6CA1\u6709\u5B9A\u65F6\u4EFB\u52A1\u3002",
2863
+ noTasksHint: "\u521B\u5EFA\u4E00\u4E2A\u6765\u81EA\u52A8\u5316\u4F60\u7684\u5DE5\u4F5C\u6D41\u3002",
2864
+ enabled: "\u5DF2\u542F\u7528",
2865
+ disabled: "\u5DF2\u7981\u7528",
2866
+ lastRun: "\u4E0A\u6B21\u6267\u884C",
2867
+ nextRun: "\u4E0B\u6B21\u6267\u884C",
2868
+ history: "\u6267\u884C\u5386\u53F2",
2869
+ typeScan: "\u626B\u63CF",
2870
+ typeSkill: "\u6280\u80FD",
2871
+ typeNotify: "\u901A\u77E5",
2872
+ cloud: "\u4E91\u7AEF",
2873
+ lastRunShort: "\u4E0A\u6B21:",
2874
+ nextRunShort: "\u4E0B\u6B21:",
2875
+ executionHistory: "\u6267\u884C\u5386\u53F2",
2876
+ noExecutions: "\u6682\u65E0\u6267\u884C\u8BB0\u5F55\u3002",
2877
+ timezonePlaceholder: "\u65F6\u533A (\u5982 Asia/Shanghai)",
2878
+ presets: "\u9884\u8BBE",
2879
+ hidePresets: "\u6536\u8D77",
2880
+ customSchedule: "\u81EA\u5B9A\u4E49\u8C03\u5EA6",
2881
+ everyMinute: "\u6BCF\u5206\u949F",
2882
+ presetEveryHour: "\u6BCF\u5C0F\u65F6",
2883
+ presetEvery2Hours: "\u6BCF 2 \u5C0F\u65F6",
2884
+ presetMorning9: "\u6BCF\u5929\u65E9\u4E0A 9 \u70B9",
2885
+ presetMorning10: "\u6BCF\u5929\u65E9\u4E0A 10 \u70B9",
2886
+ presetEvening6: "\u6BCF\u5929\u665A\u4E0A 6 \u70B9",
2887
+ presetTwiceDaily: "\u6BCF\u5929\u4E24\u6B21 (9am, 6pm)",
2888
+ presetWeekdays9: "\u5DE5\u4F5C\u65E5 9 \u70B9",
2889
+ presetMonday9: "\u6BCF\u5468\u4E00 9 \u70B9",
2890
+ presetEvery15Min: "\u6BCF 15 \u5206\u949F",
2891
+ presetEvery30Min: "\u6BCF 30 \u5206\u949F",
2892
+ descEveryHour: "\u6BCF\u5C0F\u65F6\u6574\u70B9",
2893
+ descEvery2Hours: "\u6BCF 2 \u5C0F\u65F6\u6574\u70B9",
2894
+ descMorning9: "\u6BCF\u5929 09:00",
2895
+ descMorning10: "\u6BCF\u5929 10:00",
2896
+ descEvening6: "\u6BCF\u5929 18:00",
2897
+ descTwiceDaily: "09:00 \u548C 18:00",
2898
+ descWeekdays9: "\u5468\u4E00\u81F3\u5468\u4E94 09:00",
2899
+ descMonday9: "\u6BCF\u5468\u4E00 09:00",
2900
+ descEvery15Min: "\u6BCF\u5C0F\u65F6 :00, :15, :30, :45",
2901
+ descEvery30Min: "\u6BCF\u5C0F\u65F6 :00 \u548C :30",
2902
+ cronMin: "\u5206",
2903
+ cronHour: "\u65F6",
2904
+ cronDay: "\u65E5",
2905
+ cronMonth: "\u6708",
2906
+ cronDow: "\u5468",
2907
+ daySun: "\u65E5",
2908
+ dayMon: "\u4E00",
2909
+ dayTue: "\u4E8C",
2910
+ dayWed: "\u4E09",
2911
+ dayThu: "\u56DB",
2912
+ dayFri: "\u4E94",
2913
+ daySat: "\u516D",
2914
+ invalidCron: "\u65E0\u6548\u7684 Cron \u8868\u8FBE\u5F0F\uFF08\u9700\u8981 5 \u4E2A\u5B57\u6BB5\uFF1A\u5206 \u65F6 \u65E5 \u6708 \u5468\uFF09",
2915
+ nlPlaceholder: "\u81EA\u7136\u8BED\u8A00\u63CF\u8FF0 (\u5982\u300C\u6BCF\u5929\u65E9\u4E0A10\u70B9\u300D\u300C\u6BCF30\u5206\u949F\u300D)",
2916
+ nlNoMatch: "\u65E0\u6CD5\u8BC6\u522B\uFF0C\u8BF7\u4F7F\u7528\u4E0B\u65B9 Cron \u8868\u8FBE\u5F0F\u6216\u9884\u8BBE",
2917
+ applyNl: "\u5E94\u7528",
2918
+ deleteConfirmTitle: "\u5220\u9664\u4EFB\u52A1\uFF1F",
2919
+ deleteConfirmMessage: "\u6B64\u5B9A\u65F6\u4EFB\u52A1\u5C06\u88AB\u6C38\u4E45\u5220\u9664\u3002",
2920
+ taskType: "\u4EFB\u52A1\u7C7B\u578B",
2921
+ statusSuccess: "\u6210\u529F",
2922
+ statusFailure: "\u5931\u8D25",
2923
+ statusSkipped: "\u5DF2\u8DF3\u8FC7"
2924
+ };
2925
+
2926
+ // ../../packages/core/src/i18n/locales/zh/onboarding.json
2927
+ var onboarding_default = {
2928
+ welcome: "\u6B22\u8FCE\u4F7F\u7528 JoWork",
2929
+ welcomeTitle: "\u8BA9 JoWork \u5148\u8BA4\u8BC6\u4F60\u7684\u5DE5\u4F5C\u65B9\u5F0F\u3002",
2930
+ welcomeDescription: "\u4F60\u7684 AI \u5DE5\u4F5C\u52A9\u624B\uFF0C\u672C\u5730\u4F18\u5148\u3001\u9690\u79C1\u5B89\u5168\u3002",
2931
+ loginTitle: "\u4E91\u7AEF & \u56E2\u961F\u529F\u80FD",
2932
+ loginDescription: "\u767B\u5F55\u4EE5\u89E3\u9501\u4E91\u7AEF AI\u3001\u56E2\u961F\u534F\u4F5C\u548C\u8DE8\u8BBE\u5907\u540C\u6B65\u3002",
2933
+ step1Title: "\u9009\u62E9 AI \u5F15\u64CE",
2934
+ step1Description: "JoWork \u652F\u6301\u591A\u79CD AI \u5F15\u64CE\u3002\u9009\u62E9\u4E00\u4E2A\u5F00\u59CB\u4F7F\u7528\u3002",
2935
+ step2Title: "\u8FDE\u63A5\u6570\u636E\u6E90",
2936
+ step2Description: "\u8FDE\u63A5\u4F60\u5E38\u7528\u7684\u5DE5\u5177\uFF0C\u8BA9 AI \u66F4\u597D\u5730\u5E2E\u52A9\u4F60\u3002",
2937
+ profileTitle: "\u4ECB\u7ECD\u4F60\u81EA\u5DF1",
2938
+ profileDescription: "\u5E2E\u52A9 AI \u4E86\u89E3\u5982\u4F55\u66F4\u597D\u5730\u534F\u52A9\u4F60\u3002",
2939
+ step3Title: "\u7ACB\u5373\u4F53\u9A8C\uFF01",
2940
+ step3Description: "\u4E00\u5207\u5C31\u7EEA\uFF01\u5F00\u59CB\u548C AI \u52A9\u624B\u534F\u4F5C\u5427\u3002",
2941
+ skip: "\u8DF3\u8FC7",
2942
+ getStarted: "\u5F00\u59CB\u4F7F\u7528",
2943
+ yourRole: "\u4F60\u7684\u89D2\u8272",
2944
+ communicationStyle: "\u6C9F\u901A\u98CE\u683C",
2945
+ concise: "\u7B80\u6D01",
2946
+ detailed: "\u8BE6\u7EC6",
2947
+ rulesLabel: "AI \u5FC5\u987B\u9075\u5B88\u7684\u89C4\u5219\uFF08\u53EF\u9009\uFF09",
2948
+ rulesPlaceholder: "\u4F8B\u5982\uFF1A\u56DE\u7B54\u7528\u4E2D\u6587\uFF0C\u4EE3\u7801\u6CE8\u91CA\u7528\u82F1\u6587",
2949
+ roleEngineer: "\u5DE5\u7A0B\u5E08",
2950
+ rolePm: "\u4EA7\u54C1\u7ECF\u7406",
2951
+ roleDesigner: "\u8BBE\u8BA1\u5E08",
2952
+ roleOps: "\u8FD0\u8425",
2953
+ roleFounder: "\u521B\u59CB\u4EBA",
2954
+ roleOther: "\u5176\u4ED6",
2955
+ responseGenerated: "\u56DE\u7B54\u5DF2\u751F\u6210\u3002",
2956
+ engineUnavailable: "\u5F15\u64CE\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u5B8C\u6210\u8BBE\u7F6E\u540E\u518D\u8BD5\u3002",
2957
+ cloudFallback: "\u672C\u5730\u5F15\u64CE\u4E0D\u53EF\u7528\uFF0C\u5DF2\u5207\u6362\u5230\u4E91\u7AEF\u5F15\u64CE\u3002",
2958
+ loginForCloud: "\u672C\u5730\u5F15\u64CE\u4E0D\u53EF\u7528\u3002\u767B\u5F55\u5373\u53EF\u4F7F\u7528\u4E91\u7AEF AI \u5F15\u64CE\u3002",
2959
+ defaultQ1: "\u5E2E\u6211\u5199\u4E00\u6BB5 README.md",
2960
+ defaultQ2: "\u89E3\u91CA\u4E00\u4E0B\u4EC0\u4E48\u662F MCP Server",
2961
+ defaultQ3: "\u5E2E\u6211\u89C4\u5212\u4E00\u4E2A\u65B0\u9879\u76EE\u7684\u67B6\u6784",
2962
+ qGithub: "\u5E2E\u6211\u770B\u770B\u8FD9\u5468\u6709\u54EA\u4E9B PR \u9700\u8981 review",
2963
+ qFeishu: "\u603B\u7ED3\u4E00\u4E0B\u98DE\u4E66\u7FA4\u4ECA\u5929\u7684\u91CD\u70B9",
2964
+ qLocalFolder: "\u8FD9\u4E2A\u9879\u76EE\u6700\u8FD1\u6700\u503C\u5F97\u5173\u6CE8\u7684\u6587\u4EF6\u662F\u4EC0\u4E48\uFF1F",
2965
+ qFigma: "\u770B\u770B Figma \u91CC\u6700\u65B0\u7684\u8BBE\u8BA1\u66F4\u65B0",
2966
+ qGitlab: "\u603B\u7ED3\u4E00\u4E0B GitLab \u4E0A\u6700\u8FD1\u7684 merge requests",
2967
+ connectorLocalProject: "\u672C\u5730\u9879\u76EE",
2968
+ eyebrowWelcome: "\u6B22\u8FCE",
2969
+ eyebrowAccount: "\u8D26\u53F7",
2970
+ eyebrowEngine: "\u5F15\u64CE",
2971
+ eyebrowConnectors: "\u8FDE\u63A5\u5668",
2972
+ eyebrowProfile: "\u4E2A\u4EBA\u8D44\u6599",
2973
+ eyebrowAhaMoment: "\u521D\u4F53\u9A8C",
2974
+ infoLanguage: "\u8BED\u8A00",
2975
+ infoPromise: "\u627F\u8BFA",
2976
+ promiseContent: "\u672C\u5730\u4F18\u5148\u3001\u53EF\u63A5\u4E91\u7AEF\u3001\u53EF\u63A5\u771F\u5B9E\u5DE5\u4F5C\u6570\u636E\u3002\u9996\u542F\u53EA\u505A\u5FC5\u8981\u8BBE\u7F6E\uFF0C\u4E0D\u628A\u4F60\u56F0\u5728\u4E00\u5806 marketing \u6587\u6848\u91CC\u3002",
2977
+ featureLocalData: "\u672C\u5730\u6570\u636E\u8FDE\u63A5",
2978
+ featureMcpRole: "\u672C\u5730\u6570\u636E\u8FDE\u63A5\u5668",
2979
+ featureMcpQuote: "JoWork \u901A\u8FC7 MCP \u534F\u8BAE\u6DF1\u5EA6\u8FDE\u63A5\u4F60\u7684\u672C\u5730\u4EE3\u7801\u5E93\u3001\u6587\u4EF6\u548C\u6570\u636E\u5E93\uFF0C\u8BA9 AI \u771F\u6B63\u61C2\u4F60\u7684\u5DE5\u4F5C\u6D41\u3002",
2980
+ featureMultiEngine: "\u591A\u5F15\u64CE\u8C03\u5EA6",
2981
+ featureEngineRole: "\u591A\u6A21\u578B\u8C03\u5EA6\u5F15\u64CE",
2982
+ featureEngineQuote: "\u652F\u6301 Claude\u3001GPT\u3001DeepSeek \u53CA\u672C\u5730 Ollama \u6A21\u578B\uFF0C\u6839\u636E\u4EFB\u52A1\u590D\u6742\u5EA6\u81EA\u52A8\u9009\u62E9\u6700\u4F73\u5F15\u64CE\u3002",
2983
+ badgeLocalFirst: "Local-first",
2984
+ badgeSecure: "\u5B89\u5168",
2985
+ badgeIntelligent: "\u667A\u80FD",
2986
+ badgeFast: "\u5FEB\u901F",
2987
+ infoWhySignIn: "\u4E3A\u4EC0\u4E48\u8981\u767B\u5F55",
2988
+ whySignInContent: "\u767B\u5F55\u540E\u53EF\u4EE5\u4F7F\u7528\u4E91\u5F15\u64CE\u3001\u540C\u6B65\u56E2\u961F\u6570\u636E\u3001\u8D2D\u4E70\u79EF\u5206\uFF0C\u5E76\u5728\u672C\u5730\u5F15\u64CE\u672A\u5B89\u88C5\u65F6\u81EA\u52A8\u56DE\u9000\u5230\u4E91\u7AEF\u6267\u884C\u3002",
2989
+ infoPrivacy: "\u9690\u79C1",
2990
+ privacyContent: "\u51ED\u636E\u9ED8\u8BA4\u4ECD\u4EE5\u672C\u5730\u4F18\u5148\u4FDD\u5B58",
2991
+ googleSignIn: "Google \u767B\u5F55",
2992
+ googleSignInDesc: "\u9002\u5408\u76F4\u63A5\u8FDB\u5165\u5B8C\u6574\u4EA7\u54C1\u4F53\u9A8C\uFF0C\u5305\u542B\u4E91\u80FD\u529B\u3001\u56E2\u961F\u529F\u80FD\u548C\u8DE8\u8BBE\u5907\u4F1A\u8BDD\u3002",
2993
+ skipForNow: "\u6682\u65F6\u8DF3\u8FC7",
2994
+ skipForNowDesc: "\u5982\u679C\u4F60\u53EA\u60F3\u5148\u7528\u672C\u5730\u6A21\u5F0F\uFF0C\u4E5F\u53EF\u4EE5\u7EE7\u7EED\u3002\u540E\u9762\u4ECD\u7136\u53EF\u4EE5\u5728\u8BBE\u7F6E\u6216\u8BA1\u8D39\u9875\u767B\u5F55\u3002",
2995
+ infoDetection: "\u68C0\u6D4B",
2996
+ detectionContent: "\u8FD9\u91CC\u4F1A\u68C0\u6D4B\u672C\u673A\u53EF\u7528\u5F15\u64CE\u3002\u540E\u7EED\u5982\u679C\u672C\u5730\u5F15\u64CE\u4E0D\u53EF\u7528\u4F46\u4F60\u5DF2\u767B\u5F55\uFF0C\u7CFB\u7EDF\u4F1A\u4F18\u5148\u56DE\u9000\u5230\u4E91\u5F15\u64CE\u3002",
2997
+ infoRecommended: "\u63A8\u8350",
2998
+ recommendedContent: "Claude Code \u9002\u5408\u9AD8\u8D28\u91CF\u7F16\u7801\u534F\u4F5C\uFF1BCloud \u9002\u5408\u5FEB\u901F\u5F00\u59CB\uFF1B\u540E\u7EED\u53EF\u5728\u8BBE\u7F6E\u9875\u968F\u65F6\u5207\u6362\u3002",
2999
+ installLater: "\u7A0D\u540E\u5B89\u88C5",
3000
+ notDetected: "\u672A\u68C0\u6D4B\u5230",
3001
+ infoCoreSet: "\u6838\u5FC3\u5957\u4EF6",
3002
+ coreSetContent: "\u9996\u53D1\u6838\u5FC3\u8FDE\u63A5\u5668\u662F GitHub\u3001GitLab\u3001Figma\u3001Feishu \u548C\u672C\u5730\u9879\u76EE\u6587\u4EF6\u5939\u3002\u8FD9\u91CC\u4F18\u5148\u8FDE\u63A5\u4F60\u6700\u5E38\u7528\u7684\u4E00\u4E24\u4E2A\u3002",
3003
+ infoTip: "\u63D0\u793A",
3004
+ tipContent: "\u4E0D\u5FC5\u4E00\u6B21\u8FDE\u5B8C\u3002\u771F\u6B63\u91CD\u8981\u7684\u662F\u8BA9\u540E\u9762\u7684\u9996\u4E2A\u5BF9\u8BDD\u80FD\u62FF\u5230\u81F3\u5C11\u4E00\u4E2A\u771F\u5B9E\u4E0A\u4E0B\u6587\u6E90\u3002",
3005
+ connected: "\u5DF2\u8FDE\u63A5",
3006
+ infoHowUsed: "\u5982\u4F55\u4F7F\u7528",
3007
+ howUsedContent: "\u8FD9\u4E9B\u504F\u597D\u4F1A\u5199\u5165\u672C\u5730 profile \u548C workstyle\uFF0C\u5F71\u54CD\u9ED8\u8BA4\u56DE\u7B54\u98CE\u683C\u3001\u7C92\u5EA6\u548C\u6267\u884C\u7EA6\u675F\u3002",
3008
+ infoGoal: "\u76EE\u6807",
3009
+ goalContent: "\u7528\u4E00\u4E2A\u771F\u5B9E\u95EE\u9898\u8DD1\u51FA\u7B2C\u4E00\u6761\u56DE\u7B54\u3002\u8FD9\u4E2A\u6B65\u9AA4\u7684\u76EE\u7684\u4E0D\u662F\u6F14\u793A UI\uFF0C\u800C\u662F\u786E\u8BA4\u4E0A\u4E0B\u6587\u3001\u5F15\u64CE\u548C\u56DE\u7B54\u94FE\u8DEF\u90FD\u80FD\u5B9E\u9645\u5DE5\u4F5C\u3002",
3010
+ infoEngineFallback: "\u5F15\u64CE\u56DE\u9000",
3011
+ askQuestion: "\u63D0\u95EE",
3012
+ onboardingBadge: "\u5F15\u5BFC\u8BBE\u7F6E",
3013
+ setupTitle: "\u50CF\u771F\u6B63\u7684\u5DE5\u4F5C\u7A7A\u95F4\u4E00\u6837\u8BBE\u7F6E JoWork\u3002",
3014
+ stepLabel: "\u7B2C {{step}} \u6B65",
3015
+ progress: "\u8FDB\u5EA6",
3016
+ stepProgress: "\u7B2C {{current}} \u6B65 / \u5171 {{total}} \u6B65",
3017
+ onboardingDescription: "\u4E00\u6B21\u914D\u7F6E\u8D26\u6237\u3001\u5F15\u64CE\u3001\u8FDE\u63A5\u5668\u548C\u5DE5\u4F5C\u504F\u597D\u3002"
3018
+ };
3019
+
3020
+ // ../../packages/core/src/i18n/locales/zh/auth.json
3021
+ var auth_default = {
3022
+ signIn: "\u4F7F\u7528 Google \u767B\u5F55",
3023
+ signOut: "\u9000\u51FA\u767B\u5F55"
3024
+ };
3025
+
3026
+ // ../../packages/core/src/i18n/locales/zh/notifications.json
3027
+ var notifications_default = {
3028
+ title: "\u901A\u77E5",
3029
+ inbox: "\u6536\u4EF6\u7BB1",
3030
+ rules: "\u89C4\u5219",
3031
+ markAllRead: "\u5168\u90E8\u6807\u4E3A\u5DF2\u8BFB",
3032
+ clearAll: "\u6E05\u7A7A\u5168\u90E8",
3033
+ confirmClearAll: "\u6E05\u7A7A\u6240\u6709\u901A\u77E5\uFF1F",
3034
+ noNotifications: "\u6682\u65E0\u901A\u77E5\u3002",
3035
+ noNotificationsHint: "\u542F\u7528\u901A\u77E5\u89C4\u5219\uFF0C\u5F00\u59CB\u63A5\u6536\u8FDE\u63A5\u5668\u7684\u66F4\u65B0\u63A8\u9001\u3002",
3036
+ rulesDescription: "\u914D\u7F6E\u4F55\u65F6\u4EE5\u53CA\u5982\u4F55\u63A5\u6536\u8FDE\u63A5\u5668\u7684\u901A\u77E5\u3002",
3037
+ newRule: "+ \u65B0\u5EFA\u89C4\u5219",
3038
+ noRules: "\u5C1A\u672A\u914D\u7F6E\u901A\u77E5\u89C4\u5219\u3002",
3039
+ noRulesHint: "\u521B\u5EFA\u89C4\u5219\u4EE5\u63A5\u6536\u8FDE\u63A5\u5668\u4E8B\u4EF6\u901A\u77E5\u3002",
3040
+ editRule: "\u7F16\u8F91\u89C4\u5219",
3041
+ newRuleTitle: "\u65B0\u5EFA\u901A\u77E5\u89C4\u5219",
3042
+ connectorId: "\u8FDE\u63A5\u5668 ID",
3043
+ connectorIdPlaceholder: "\u5982 github, gitlab, feishu",
3044
+ condition: "\u6761\u4EF6",
3045
+ condMentionMe: "\u63D0\u53CA\u6211",
3046
+ condP0Issue: "P0 \u95EE\u9898\u521B\u5EFA",
3047
+ condPrReview: "PR \u5BA1\u67E5\u8BF7\u6C42",
3048
+ condCustom: "\u81EA\u5B9A\u4E49\u7B5B\u9009",
3049
+ customFilterExpression: "\u81EA\u5B9A\u4E49\u7B5B\u9009\u8868\u8FBE\u5F0F",
3050
+ customFilterPlaceholder: '\u5982 title contains "urgent"',
3051
+ deliveryChannels: "\u901A\u77E5\u6E20\u9053",
3052
+ channelSystem: "\u7CFB\u7EDF\u901A\u77E5",
3053
+ channelApp: "\u5E94\u7528\u5185\u901A\u77E5",
3054
+ channelFeishu: "\u98DE\u4E66\u6D88\u606F",
3055
+ silentHours: "\u514D\u6253\u6270\u65F6\u6BB5",
3056
+ silentTo: "\u81F3",
3057
+ aiSummary: "\u6295\u9012\u524D AI \u6458\u8981",
3058
+ createRule: "\u521B\u5EFA\u89C4\u5219",
3059
+ channels: "\u901A\u77E5\u6E20\u9053",
3060
+ silent: "\u514D\u6253\u6270"
3061
+ };
3062
+
3063
+ // ../../packages/core/src/i18n/locales/en/common.json
3064
+ var common_default2 = {
3065
+ app: { name: "JoWork" },
3066
+ save: "Save",
3067
+ cancel: "Cancel",
3068
+ create: "Create",
3069
+ update: "Update",
3070
+ delete: "Delete",
3071
+ edit: "Edit",
3072
+ close: "Close",
3073
+ confirm: "Confirm",
3074
+ loading: "Loading...",
3075
+ saving: "Saving...",
3076
+ search: "Search",
3077
+ filter: "Filter",
3078
+ noResults: "No results",
3079
+ retry: "Retry",
3080
+ back: "Back",
3081
+ next: "Next",
3082
+ done: "Done",
3083
+ enable: "Enable",
3084
+ disable: "Disable",
3085
+ personal: "Personal",
3086
+ teamLabel: "Team",
3087
+ online: "Online",
3088
+ offline: "Offline",
3089
+ syncing: "Syncing",
3090
+ syncComplete: "Sync complete",
3091
+ version: "Version",
3092
+ skipToMainContent: "Skip to main content",
3093
+ contextConnectors: "Connectors",
3094
+ contextNoConnectors: "No active connectors",
3095
+ contextInactive: "inactive",
3096
+ contextPinnedMemories: "Pinned Memories",
3097
+ contextNoMemories: "No pinned memories",
3098
+ contextRecent: "Recent",
3099
+ teamMode: "Team: {{name}}",
3100
+ somethingWentWrong: "Something went wrong",
3101
+ unexpectedError: "An unexpected error occurred.",
3102
+ tryAgain: "Try Again",
3103
+ featureError: "{{name}} error",
3104
+ dismissNotification: "Dismiss notification",
3105
+ menuFile: "File",
3106
+ menuView: "View",
3107
+ trayShow: "Show JoWork",
3108
+ trayQuickChat: "Quick Chat",
3109
+ trayQuit: "Quit",
3110
+ goHome: "Go Home",
3111
+ searchPlaceholder: "Type to search...",
3112
+ searching: "Searching...",
3113
+ noResultsFound: "No results found",
3114
+ pages: "Pages",
3115
+ conversations: "Conversations",
3116
+ messages: "Messages",
3117
+ confirmDelete: "Confirm Delete",
3118
+ deleteWarning: "This action cannot be undone.",
3119
+ savedSuccessfully: "Saved successfully",
3120
+ deletedSuccessfully: "Deleted successfully",
3121
+ operationFailed: "Operation failed",
3122
+ connectedSuccessfully: "Connected successfully",
3123
+ disconnectedSuccessfully: "Disconnected successfully",
3124
+ installedSuccessfully: "Installed successfully",
3125
+ installFailed: "Install failed",
3126
+ copyFailed: "Copy failed",
3127
+ settingsSaved: "Settings saved",
3128
+ v2: "v2",
3129
+ localFirst: "Local First",
3130
+ detected: "Detected",
3131
+ notDetected: "Not detected",
3132
+ copy: "Copy",
3133
+ copied: "Copied!",
3134
+ error: "An error occurred"
3135
+ };
3136
+
3137
+ // ../../packages/core/src/i18n/locales/en/sidebar.json
3138
+ var sidebar_default2 = {
3139
+ conversation: "AI Assistant",
3140
+ dashboard: "Dashboard",
3141
+ connectors: "Connectors",
3142
+ memories: "Memories",
3143
+ skills: "Skills",
3144
+ workstyle: "Work Style",
3145
+ scheduler: "Scheduler",
3146
+ notifications: "Notifications",
3147
+ terminal: "Terminal",
3148
+ settings: "Settings",
3149
+ billing: "Billing",
3150
+ personal: "Personal",
3151
+ team: "Team",
3152
+ search: "Search",
3153
+ hideSidebar: "Hide sidebar",
3154
+ showSidebar: "Show sidebar",
3155
+ hidePanel: "Hide panel",
3156
+ showPanel: "Show panel",
3157
+ hideContext: "Hide context",
3158
+ showContext: "Show context",
3159
+ collapse: "Collapse",
3160
+ expand: "Expand",
3161
+ expandNav: "Expand navigation",
3162
+ collapseNav: "Collapse navigation",
3163
+ credits: "Credits",
3164
+ newConversation: "New conversation",
3165
+ searchPlaceholder: "Search (\u2318K)"
3166
+ };
3167
+
3168
+ // ../../packages/core/src/i18n/locales/en/chat.json
3169
+ var chat_default2 = {
3170
+ title: "JoWork AI Assistant",
3171
+ placeholder: "Type a message... (Enter to send)",
3172
+ send: "Send",
3173
+ stop: "Stop",
3174
+ emptyTitle: "Start a conversation",
3175
+ emptyDescription: "Start a conversation with your AI assistant. It can help you with code, analysis, and more.",
3176
+ noConversations: "No conversations yet",
3177
+ detectingEngines: "Detecting engines...",
3178
+ thinking: "Thinking...",
3179
+ toolCall: "Tool call",
3180
+ toolResult: "Tool result",
3181
+ toolsUsed_one: "{{count}} tool used",
3182
+ toolsUsed_other: "{{count}} tools used",
3183
+ conversations: "Conversations",
3184
+ newConversation: "New conversation",
3185
+ deleteConversation: "Delete conversation",
3186
+ renameConversation: "Rename conversation",
3187
+ searchConversations: "Search conversations...",
3188
+ export: "Export",
3189
+ exportConversation: "Export conversation",
3190
+ exportMarkdown: "Markdown (.md)",
3191
+ exportJson: "JSON (.json)",
3192
+ loadOlder: "Load older messages",
3193
+ loadingOlder: "Loading older messages...",
3194
+ noMatchingConversations: "No matching conversations",
3195
+ dropFilesHere: "Drop files here...",
3196
+ inputAriaLabel: "Chat message input",
3197
+ stopAriaLabel: "Stop AI response",
3198
+ sendAriaLabel: "Send message",
3199
+ actionConfirmation: "Action Confirmation",
3200
+ riskLow: "Low risk",
3201
+ riskMedium: "Medium risk",
3202
+ riskHigh: "High risk",
3203
+ alwaysAllow: "Always allow this action",
3204
+ deny: "Deny",
3205
+ allow: "Allow",
3206
+ notInstalled: "not installed",
3207
+ engineClaudeCode: "Claude Code",
3208
+ engineOpenClaw: "OpenClaw",
3209
+ engineCodex: "Codex",
3210
+ engineNemoClaw: "NemoClaw",
3211
+ engineJoworkCloud: "JoWork Cloud",
3212
+ launcherPlaceholder: "Ask JoWork anything...",
3213
+ recent: "Recent",
3214
+ launcherHint: "Press Enter to ask, Esc to close",
3215
+ skillsLabel: "Available Skills",
3216
+ engineCrashed: "AI engine crashed, restarting... (attempt {{retries}})",
3217
+ engineCrashFatal: "AI engine failed after {{max}} restart attempts. Try switching engines in Settings.",
3218
+ engineRestartReady: "AI engine restarted successfully.",
3219
+ launcherTitle: "JoWork Quick Ask",
3220
+ launcherClose: "close",
3221
+ launcherOpenMain: "open main",
3222
+ launcherModes: "Modes",
3223
+ launcherAskAI: "Ask AI",
3224
+ launcherRunCommand: "Run command",
3225
+ launcherJumpToPage: "Jump to page",
3226
+ timeJustNow: "Just now",
3227
+ timeMinutesAgo: "{{count}}m ago",
3228
+ engineError: "Engine error",
3229
+ retryMessage: "Retry",
3230
+ scrollToBottom: "Jump to latest",
3231
+ exportSuccess: "Conversation exported",
3232
+ exportFailed: "Export failed",
3233
+ deleteSuccess: "Conversation deleted",
3234
+ deleteConfirmTitle: "Delete conversation?",
3235
+ deleteConfirmMessage: "This action cannot be undone.",
3236
+ expand: "Expand",
3237
+ collapse: "Collapse",
3238
+ toolConfirmation: "Tool confirmation",
3239
+ renameSession: "Rename",
3240
+ saveAsSkill: "Save as Skill",
3241
+ generatingSkill: "Generating\u2026",
3242
+ skillGenerateFailed: "Failed to generate skill",
3243
+ deleteConfirm: "Delete?",
3244
+ paramsCount: "{{count}} params",
3245
+ starterPrompt1: "Help me plan today \u2014 what should I focus on first?",
3246
+ starterPrompt2: "I have a rough idea. Help me think it through and make it actionable.",
3247
+ starterPrompt3: "What's blocking my progress? Help me find the real bottleneck.",
3248
+ quotaExhaustedTitle: "Free conversations used up today",
3249
+ quotaExhaustedDesc: "Resets at 00:00 UTC tomorrow, or upgrade Pro to continue",
3250
+ upgradePro: "Upgrade Pro",
3251
+ waitUntilTomorrow: "Wait until tomorrow",
3252
+ switchEngine: "Switch engine",
3253
+ showSidebar: "Show panel",
3254
+ hideSidebar: "Hide panel"
3255
+ };
3256
+
3257
+ // ../../packages/core/src/i18n/locales/en/connectors.json
3258
+ var connectors_default2 = {
3259
+ title: "Connectors",
3260
+ description: "Connect your tools and data sources to JoWork.",
3261
+ connected: "Connected",
3262
+ connectedCount: "{{count}} connected",
3263
+ all: "All",
3264
+ available: "Available Data Sources",
3265
+ noConnected: "No data sources connected yet. Configure one below to get started.",
3266
+ credentialStored: "Credential stored",
3267
+ needsAuth: "Needs authorization",
3268
+ core: "Core Connectors",
3269
+ more: "More Connectors",
3270
+ configure: "Configure",
3271
+ connect: "Connect",
3272
+ disconnect: "Disconnect",
3273
+ loading: "Loading connectors...",
3274
+ loadingDescription: "Checking data source status...",
3275
+ tokenPlaceholder: "Access token or API key",
3276
+ health: "Health status",
3277
+ healthy: "Healthy",
3278
+ unhealthy: "Unhealthy",
3279
+ lastSync: "Last sync",
3280
+ authorize: "Authorize",
3281
+ revoke: "Revoke",
3282
+ tierBeta: "Beta",
3283
+ tierPlanned: "Planned",
3284
+ authorizeTitle: "Authorize {{name}}",
3285
+ authorizeDescription: "A browser window will open for you to authorize JoWork to access your {{name}} data.",
3286
+ noHealthData: "No health data available.",
3287
+ status: "Status",
3288
+ syncedData: "Synced Data",
3289
+ noSyncedData: "No data synced yet.",
3290
+ syncLog: "Sync Log",
3291
+ noSyncActivity: "No sync activity.",
3292
+ disconnectConfirmTitle: "Disconnect {{name}}?",
3293
+ disconnectConfirmMessage: "This will remove the connection and revoke access.",
3294
+ authorization: "Authorization",
3295
+ comingSoon: "Coming Soon",
3296
+ saveAndConnect: "Save & Connect",
3297
+ signIn: "Sign in",
3298
+ authorizing: "Signing in\u2026",
3299
+ connecting: "Connecting\u2026",
3300
+ cat_code: "Code",
3301
+ cat_design: "Design",
3302
+ cat_communication: "Communication",
3303
+ cat_docs: "Documents",
3304
+ cat_local: "Local",
3305
+ cat_analytics: "Analytics",
3306
+ c_github_name: "GitHub",
3307
+ c_github_desc: "Repositories, issues, pull requests",
3308
+ c_gitlab_name: "GitLab",
3309
+ c_gitlab_desc: "Projects, merge requests, issues",
3310
+ c_figma_name: "Figma",
3311
+ c_figma_desc: "Design files and components",
3312
+ "c_local-folder_name": "Local Project",
3313
+ "c_local-folder_desc": "Give Claude access to a local folder",
3314
+ c_feishu_name: "Feishu / Lark \xB7 Org",
3315
+ c_feishu_desc: "Group messages, org docs, calendar (requires Bot App credentials)",
3316
+ c_notion_name: "Notion",
3317
+ c_notion_desc: "Pages, databases, workspace knowledge",
3318
+ c_slack_name: "Slack",
3319
+ c_slack_desc: "Channels, messages, team communication",
3320
+ "c_brave-search_name": "Web Search",
3321
+ "c_brave-search_desc": "Real-time web search via Brave Search API",
3322
+ c_posthog_name: "PostHog",
3323
+ c_posthog_desc: "Product analytics, feature flags, session recordings",
3324
+ c_linear_name: "Linear",
3325
+ c_linear_desc: "Issues, projects, cycles, roadmaps",
3326
+ "c_feishu-personal_name": "Feishu / Lark \xB7 Personal",
3327
+ "c_feishu-personal_desc": "Personal docs, DMs, calendar, email (sign in to JoWork Cloud first)",
3328
+ feishuPersonalRequiresLogin: "Sign in to JoWork Cloud to connect your Feishu personal data",
3329
+ type_local: "Local Data",
3330
+ type_local_desc: "Give the AI direct access to local files and folders",
3331
+ type_sync: "Online Data",
3332
+ type_sync_desc: "Periodically syncs to local for fast search",
3333
+ type_mcp: "MCP Tools",
3334
+ type_mcp_desc: "Fetches data on demand when needed",
3335
+ addFolder: "Add Folder",
3336
+ folderName: "Display Name",
3337
+ folderPath: "Folder Path",
3338
+ removeInstance: "Remove",
3339
+ removeInstanceConfirm: "Remove this folder?"
3340
+ };
3341
+
3342
+ // ../../packages/core/src/i18n/locales/en/settings.json
3343
+ var settings_default2 = {
3344
+ title: "Settings",
3345
+ general: "General",
3346
+ appearance: "Appearance",
3347
+ engines: "AI Engines",
3348
+ about: "About",
3349
+ themeLight: "Light",
3350
+ themeDark: "Dark",
3351
+ themeSystem: "System",
3352
+ language: "Language",
3353
+ update: "Update",
3354
+ checkUpdate: "Check for updates",
3355
+ updateAvailable: "New version available",
3356
+ updateDownloaded: "Update downloaded, restart to install",
3357
+ restartToUpdate: "Restart to update",
3358
+ upToDate: "Up to date",
3359
+ checking: "Checking...",
3360
+ keyboardShortcuts: "Keyboard Shortcuts",
3361
+ shortcutHint: "On Windows/Linux, replace Cmd with Ctrl.",
3362
+ shortcutNewConversation: "New conversation",
3363
+ shortcutGlobalSearch: "Global search",
3364
+ shortcutQuickLauncher: "Quick launcher",
3365
+ shortcutExport: "Export conversation",
3366
+ shortcutSettings: "Settings",
3367
+ shortcutSend: "Send message",
3368
+ shortcutStop: "Stop / close",
3369
+ shortcutTerminal: "Open terminal",
3370
+ shortcutCloseWindow: "Close window",
3371
+ workstyleTitle: "Work Style",
3372
+ workstyleDescription: "Define how the AI should work with you. This is injected into every conversation.",
3373
+ workstylePlaceholder: "Write your work style guide in Markdown...",
3374
+ workstyleHint: "Supports Markdown. This document is included in every AI conversation as context.",
3375
+ saved: "Saved!",
3376
+ workstyleTemplate: "# My Work Style\n\n## Role\n[Your title and responsibilities]\n\n## Communication Preferences\n- Reply style: [concise/detailed]\n- Language: [Chinese/English/bilingual]\n\n## Work Habits\n[Your daily workflow]\n\n## Important Rules\n[Rules the AI must follow]\n",
3377
+ terminalTitle: "Terminal",
3378
+ terminalTab: "Terminal {{n}}",
3379
+ stylePrompt: "Style prompt",
3380
+ quickAccess: "Quick Access"
3381
+ };
3382
+
3383
+ // ../../packages/core/src/i18n/locales/en/billing.json
3384
+ var billing_default2 = {
3385
+ title: "Billing",
3386
+ credits: "Credits",
3387
+ remaining: "Remaining",
3388
+ used: "Used this period",
3389
+ wallet: "Wallet Balance",
3390
+ buyCredits: "Buy Credits",
3391
+ plans: "Plans",
3392
+ currentPlan: "Current Plan",
3393
+ upgrade: "Upgrade",
3394
+ manageSubscription: "Manage Subscription",
3395
+ signInRequired: "Sign in to access billing and cloud credits.",
3396
+ buyAmount: "Buy {{amount}} credits",
3397
+ free: "Free",
3398
+ pro: "Pro",
3399
+ teamPlan: "Team",
3400
+ perMonth: "/mo",
3401
+ usageChart: "Usage",
3402
+ dailyUsage: "Daily Usage (7 days)",
3403
+ creditsLeft: "{{count}} left",
3404
+ walletBalance: "+{{count}} wallet",
3405
+ creditsPerMonth: "{{count}} credits/month",
3406
+ downgrade: "Downgrade",
3407
+ dailyLimit: "Limit: {{limit}}/day",
3408
+ usageHistory: "Usage History",
3409
+ creditOverview: "Credit overview"
3410
+ };
3411
+
3412
+ // ../../packages/core/src/i18n/locales/en/team.json
3413
+ var team_default2 = {
3414
+ title: "Team",
3415
+ members: "Members",
3416
+ invite: "Invite Members",
3417
+ createTeam: "Create a Team",
3418
+ settings: "Team Settings",
3419
+ signInRequired: "Sign in to create or join a team workspace.",
3420
+ yourTeams: "Your Teams",
3421
+ switch: "Switch",
3422
+ owner: "Owner",
3423
+ admin: "Admin",
3424
+ member: "Member",
3425
+ teamName: "Team name",
3426
+ memberCount: "{{count}} members",
3427
+ creating: "Creating...",
3428
+ inviteLink: "Invite link",
3429
+ copyLink: "Copy link",
3430
+ linkCopied: "Copied",
3431
+ removeMember: "Remove member",
3432
+ changeRole: "Change role",
3433
+ leaveTeam: "Leave team",
3434
+ inviteTitle: "Invite Team Members",
3435
+ inviteDescription: "Generate an invite link to share with your team members.",
3436
+ generating: "Generating...",
3437
+ generateInviteLink: "Generate Invite Link",
3438
+ inviteUrl: "Invite URL",
3439
+ inviteExpiry: "This link expires in 7 days. Anyone with this link can join the team.",
3440
+ teamId: "Team ID",
3441
+ remove: "Remove",
3442
+ createTeamDescription: "Create a new workspace for your organization.",
3443
+ removeConfirmTitle: "Remove member?",
3444
+ removeConfirmMessage: "They will lose access to team resources.",
3445
+ noTeams: "You haven't joined any teams yet.",
3446
+ inviteError: "Failed to generate invite link"
3447
+ };
3448
+
3449
+ // ../../packages/core/src/i18n/locales/en/memory.json
3450
+ var memory_default2 = {
3451
+ title: "Memories",
3452
+ description: "Things the AI remembers about you across conversations.",
3453
+ new: "New",
3454
+ editMemory: "Edit Memory",
3455
+ newMemory: "New Memory",
3456
+ titlePlaceholder: "Memory title",
3457
+ contentPlaceholder: "Memory content...",
3458
+ tagsPlaceholder: "Tags (comma-separated)",
3459
+ pinned: "Pinned",
3460
+ allMemories: "All Memories",
3461
+ noMemories: "No memories yet.",
3462
+ noMemoriesHint: "Create one manually or let AI learn from conversations.",
3463
+ pin: "Pin",
3464
+ unpin: "Unpin",
3465
+ searchMemories: "Search memories...",
3466
+ sourceAuto: "Auto",
3467
+ sourceManual: "Manual",
3468
+ scope: "Scope",
3469
+ scopePersonal: "Personal",
3470
+ scopeTeam: "Team",
3471
+ deleteConfirmTitle: "Delete memory?",
3472
+ deleteConfirmMessage: "This memory will be permanently removed."
3473
+ };
3474
+
3475
+ // ../../packages/core/src/i18n/locales/en/skills.json
3476
+ var skills_default2 = {
3477
+ title: "Skills",
3478
+ description: "Reusable prompts and workflows from multiple sources.",
3479
+ filterPlaceholder: "Filter skills...",
3480
+ noSkills: "No skills found.",
3481
+ noSkillsHint: "Add .md files to ~/.claude/commands/ or ~/.claude/skills/",
3482
+ sourceClaudeCode: "Claude Code",
3483
+ sourceJowork: "JoWork",
3484
+ sourceOpenclaw: "OpenClaw",
3485
+ sourceCommunity: "Community",
3486
+ loading: "Loading skills...",
3487
+ run: "Run",
3488
+ details: "Details",
3489
+ marketplace: "Marketplace",
3490
+ createSkill: "Create",
3491
+ variableCount: "{{count}} vars",
3492
+ variableCount_one: "{{count}} var",
3493
+ runSkill: "Run Skill",
3494
+ running: "Running...",
3495
+ selectPlaceholder: "Select...",
3496
+ createCustomSkill: "Create Custom Skill",
3497
+ skillName: "Name",
3498
+ skillTrigger: "Trigger",
3499
+ skillDescription: "Description",
3500
+ promptTemplate: "Prompt Template",
3501
+ promptPlaceholder: "Use {{variable_name}} for dynamic values...",
3502
+ variables: "Variables",
3503
+ addVariable: "+ Add Variable",
3504
+ varLabel: "Label",
3505
+ varTypeText: "Text",
3506
+ varTypeMultiline: "Multiline",
3507
+ varTypeSelect: "Select",
3508
+ varRequired: "Req",
3509
+ saveSkill: "Save Skill",
3510
+ skillMarketplace: "Skill Marketplace",
3511
+ browseSkills: "Browse and install community skills",
3512
+ searchSkills: "Search skills...",
3513
+ installCount: "{{count}} installs",
3514
+ install: "Install",
3515
+ installed: "Installed",
3516
+ noSkillsMatch: "No skills match your search.",
3517
+ skillLibrary: "Skill library",
3518
+ customSkillLabel: "Custom skill",
3519
+ fromConversation: "From Conversation",
3520
+ reviewAndSaveSkill: "Review & Save Skill",
3521
+ skillType: "Type",
3522
+ typeSimple: "Simple",
3523
+ typeWorkflow: "Workflow",
3524
+ workflowSteps: "Steps",
3525
+ addStep: "Add Step",
3526
+ noStepsYet: "No steps yet. Add a step to define the workflow.",
3527
+ step: "Step",
3528
+ stepPromptPlaceholder: "Step prompt\u2026",
3529
+ outputVar: "Output variable (optional)",
3530
+ stepCondition: "Condition to run (optional)",
3531
+ namePlaceholder: "My Skill",
3532
+ triggerPlaceholder: "/my-skill",
3533
+ varNamePlaceholder: "var_name"
3534
+ };
3535
+
3536
+ // ../../packages/core/src/i18n/locales/en/scheduler.json
3537
+ var scheduler_default2 = {
3538
+ title: "Scheduled Tasks",
3539
+ description: "Automate recurring tasks like data scans, skill execution, and notifications.",
3540
+ newTask: "New Task",
3541
+ editTask: "Edit Task",
3542
+ namePlaceholder: "Task name",
3543
+ cronPlaceholder: "Cron expression (e.g. 0 10 * * *)",
3544
+ cloudExecution: "Enable cloud execution when offline",
3545
+ noTasks: "No scheduled tasks yet.",
3546
+ noTasksHint: "Create one to automate your workflow.",
3547
+ enabled: "Enabled",
3548
+ disabled: "Disabled",
3549
+ lastRun: "Last run",
3550
+ nextRun: "Next run",
3551
+ history: "Run history",
3552
+ typeScan: "Scan",
3553
+ typeSkill: "Skill",
3554
+ typeNotify: "Notify",
3555
+ cloud: "Cloud",
3556
+ lastRunShort: "Last:",
3557
+ nextRunShort: "Next:",
3558
+ executionHistory: "Execution History",
3559
+ noExecutions: "No executions yet.",
3560
+ timezonePlaceholder: "Timezone (e.g. Asia/Shanghai)",
3561
+ presets: "Presets",
3562
+ hidePresets: "Hide",
3563
+ customSchedule: "Custom schedule",
3564
+ everyMinute: "Every minute",
3565
+ presetEveryHour: "Every hour",
3566
+ presetEvery2Hours: "Every 2 hours",
3567
+ presetMorning9: "Every morning (9am)",
3568
+ presetMorning10: "Every morning (10am)",
3569
+ presetEvening6: "Every evening (6pm)",
3570
+ presetTwiceDaily: "Twice daily (9am, 6pm)",
3571
+ presetWeekdays9: "Weekdays at 9am",
3572
+ presetMonday9: "Every Monday 9am",
3573
+ presetEvery15Min: "Every 15 minutes",
3574
+ presetEvery30Min: "Every 30 minutes",
3575
+ descEveryHour: "At minute 0 of every hour",
3576
+ descEvery2Hours: "At minute 0, every 2 hours",
3577
+ descMorning9: "Every day at 09:00",
3578
+ descMorning10: "Every day at 10:00",
3579
+ descEvening6: "Every day at 18:00",
3580
+ descTwiceDaily: "At 09:00 and 18:00",
3581
+ descWeekdays9: "Mon-Fri at 09:00",
3582
+ descMonday9: "Every Monday at 09:00",
3583
+ descEvery15Min: "At :00, :15, :30, :45",
3584
+ descEvery30Min: "At :00 and :30",
3585
+ cronMin: "min",
3586
+ cronHour: "hour",
3587
+ cronDay: "day",
3588
+ cronMonth: "month",
3589
+ cronDow: "dow",
3590
+ daySun: "Sun",
3591
+ dayMon: "Mon",
3592
+ dayTue: "Tue",
3593
+ dayWed: "Wed",
3594
+ dayThu: "Thu",
3595
+ dayFri: "Fri",
3596
+ daySat: "Sat",
3597
+ invalidCron: "Invalid cron expression (requires 5 fields: min hour day month dow)",
3598
+ nlPlaceholder: 'Natural language (e.g. "every morning at 10", "every 30 minutes")',
3599
+ nlNoMatch: "Unrecognized. Use the cron field or presets below.",
3600
+ applyNl: "Apply",
3601
+ deleteConfirmTitle: "Delete task?",
3602
+ deleteConfirmMessage: "This scheduled task will be permanently removed.",
3603
+ taskType: "Task type",
3604
+ statusSuccess: "Success",
3605
+ statusFailure: "Failed",
3606
+ statusSkipped: "Skipped"
3607
+ };
3608
+
3609
+ // ../../packages/core/src/i18n/locales/en/onboarding.json
3610
+ var onboarding_default2 = {
3611
+ welcome: "Welcome to JoWork",
3612
+ welcomeTitle: "Let JoWork learn your workflow.",
3613
+ welcomeDescription: "Your AI work assistant. Local-first, privacy-safe.",
3614
+ loginTitle: "Cloud & Team Features",
3615
+ loginDescription: "Sign in to unlock cloud AI, team collaboration, and cross-device sync.",
3616
+ step1Title: "Choose an AI Engine",
3617
+ step1Description: "JoWork supports multiple AI engines. Choose one to get started.",
3618
+ step2Title: "Connect Data Sources",
3619
+ step2Description: "Connect your tools so the AI can better assist you.",
3620
+ profileTitle: "Tell JoWork About You",
3621
+ profileDescription: "Help AI understand how to assist you better.",
3622
+ step3Title: "Try It Now!",
3623
+ step3Description: "All set! Start collaborating with your AI assistant.",
3624
+ skip: "Skip",
3625
+ getStarted: "Get Started",
3626
+ yourRole: "Your Role",
3627
+ communicationStyle: "Communication Style",
3628
+ concise: "Concise",
3629
+ detailed: "Detailed",
3630
+ rulesLabel: "Rules for AI (optional)",
3631
+ rulesPlaceholder: "e.g., Always respond in English",
3632
+ roleEngineer: "Engineer",
3633
+ rolePm: "Product Manager",
3634
+ roleDesigner: "Designer",
3635
+ roleOps: "Operations",
3636
+ roleFounder: "Founder",
3637
+ roleOther: "Other",
3638
+ responseGenerated: "Response generated.",
3639
+ engineUnavailable: "Engine unavailable right now. Try again after setup.",
3640
+ cloudFallback: "Local engine unavailable. Switched to cloud engine.",
3641
+ loginForCloud: "Local engine unavailable. Sign in to use the cloud AI engine.",
3642
+ defaultQ1: "Help me write a README.md",
3643
+ defaultQ2: "Explain what an MCP Server is",
3644
+ defaultQ3: "Help me plan a new project architecture",
3645
+ qGithub: "Show me PRs that need review this week",
3646
+ qFeishu: "Summarize today's highlights from Feishu group",
3647
+ qLocalFolder: "What files in this project are most worth my attention?",
3648
+ qFigma: "Show me the latest design updates in Figma",
3649
+ qGitlab: "Summarize recent merge requests on GitLab",
3650
+ connectorLocalProject: "Local Project",
3651
+ eyebrowWelcome: "Welcome",
3652
+ eyebrowAccount: "Account",
3653
+ eyebrowEngine: "Engine",
3654
+ eyebrowConnectors: "Connectors",
3655
+ eyebrowProfile: "Profile",
3656
+ eyebrowAhaMoment: "Aha moment",
3657
+ infoLanguage: "Language",
3658
+ infoPromise: "Promise",
3659
+ promiseContent: "Local-first, cloud-optional, with real work data. Setup does only what's necessary \u2014 no marketing fluff.",
3660
+ featureLocalData: "Local data access",
3661
+ featureMcpRole: "Local Data Connector",
3662
+ featureMcpQuote: "Connect seamlessly with local files, repos and DBs via MCP protocol.",
3663
+ featureMultiEngine: "Multi-engine dispatch",
3664
+ featureEngineRole: "Multi-Engine Dispatch",
3665
+ featureEngineQuote: "Native support for Claude, GPT, DeepSeek and Ollama. Auto-switches based on task complexity.",
3666
+ badgeLocalFirst: "Local-first",
3667
+ badgeSecure: "Secure",
3668
+ badgeIntelligent: "Intelligent",
3669
+ badgeFast: "Fast",
3670
+ infoWhySignIn: "Why sign in",
3671
+ whySignInContent: "After signing in, you can use cloud engines, sync team data, purchase credits, and auto-fallback to cloud when local engine isn't installed.",
3672
+ infoPrivacy: "Privacy",
3673
+ privacyContent: "Credentials are stored locally by default.",
3674
+ googleSignIn: "Google sign-in",
3675
+ googleSignInDesc: "Best for the full product experience including cloud capabilities, team features, and cross-device sessions.",
3676
+ skipForNow: "Skip for now",
3677
+ skipForNowDesc: "If you just want to try local mode first, you can continue. You can always sign in later from Settings or Billing.",
3678
+ infoDetection: "Detection",
3679
+ detectionContent: "We detect available engines on your machine. If a local engine is unavailable but you're signed in, the system will fallback to cloud.",
3680
+ infoRecommended: "Recommended",
3681
+ recommendedContent: "Claude Code is ideal for high-quality coding. Cloud is great for quick start. You can switch anytime in Settings.",
3682
+ installLater: "Install later",
3683
+ notDetected: "Not detected",
3684
+ infoCoreSet: "Core set",
3685
+ coreSetContent: "The core connectors are GitHub, GitLab, Figma, Feishu, and Local Folder. Connect the one or two you use most here.",
3686
+ infoTip: "Tip",
3687
+ tipContent: "No need to connect everything at once. What matters most is having at least one real context source for your first conversation.",
3688
+ connected: "Connected",
3689
+ infoHowUsed: "How it is used",
3690
+ howUsedContent: "These preferences are saved to your local profile and workstyle. They affect the default response style, granularity, and execution constraints.",
3691
+ infoGoal: "Goal",
3692
+ goalContent: "Run a real question to get your first answer. This step confirms that context, engine, and response pipeline actually work.",
3693
+ infoEngineFallback: "Engine fallback",
3694
+ askQuestion: "Ask",
3695
+ onboardingBadge: "Onboarding",
3696
+ setupTitle: "Set up JoWork like a real workspace.",
3697
+ stepLabel: "Step {{step}}",
3698
+ progress: "Progress",
3699
+ stepProgress: "Step {{current}} / {{total}}",
3700
+ onboardingDescription: "Configure your account, engine, connectors and work preferences in one go."
3701
+ };
3702
+
3703
+ // ../../packages/core/src/i18n/locales/en/auth.json
3704
+ var auth_default2 = {
3705
+ signIn: "Sign in with Google",
3706
+ signOut: "Sign out"
3707
+ };
3708
+
3709
+ // ../../packages/core/src/i18n/locales/en/notifications.json
3710
+ var notifications_default2 = {
3711
+ title: "Notifications",
3712
+ inbox: "Inbox",
3713
+ rules: "Rules",
3714
+ markAllRead: "Mark all read",
3715
+ clearAll: "Clear all",
3716
+ confirmClearAll: "Clear all notifications?",
3717
+ noNotifications: "No notifications.",
3718
+ noNotificationsHint: "Enable notification rules to start receiving updates from your connectors.",
3719
+ rulesDescription: "Configure when and how you receive notifications from connectors.",
3720
+ newRule: "+ New Rule",
3721
+ noRules: "No notification rules configured.",
3722
+ noRulesHint: "Create a rule to get notified about connector events.",
3723
+ editRule: "Edit Rule",
3724
+ newRuleTitle: "New Notification Rule",
3725
+ connectorId: "Connector ID",
3726
+ connectorIdPlaceholder: "e.g. github, gitlab, feishu",
3727
+ condition: "Condition",
3728
+ condMentionMe: "Mention me",
3729
+ condP0Issue: "P0 issue created",
3730
+ condPrReview: "PR review requested",
3731
+ condCustom: "Custom filter",
3732
+ customFilterExpression: "Custom Filter Expression",
3733
+ customFilterPlaceholder: 'e.g. title contains "urgent"',
3734
+ deliveryChannels: "Delivery Channels",
3735
+ channelSystem: "System notification",
3736
+ channelApp: "In-app notification",
3737
+ channelFeishu: "Feishu message",
3738
+ silentHours: "Silent hours",
3739
+ silentTo: "to",
3740
+ aiSummary: "AI-powered summary before delivery",
3741
+ createRule: "Create Rule",
3742
+ channels: "Channels",
3743
+ silent: "Silent"
3744
+ };
3745
+
3746
+ // ../../packages/core/src/i18n/index.ts
3747
+ var i18nNamespaces = [
3748
+ "common",
3749
+ "sidebar",
3750
+ "chat",
3751
+ "connectors",
3752
+ "settings",
3753
+ "billing",
3754
+ "team",
3755
+ "memory",
3756
+ "skills",
3757
+ "scheduler",
3758
+ "onboarding",
3759
+ "auth",
3760
+ "notifications"
3761
+ ];
3762
+ var SUPPORTED_LANGS = ["zh", "en"];
3763
+ function detectLanguage() {
3764
+ if (typeof navigator !== "undefined" && navigator.language) {
3765
+ const tag = navigator.language.toLowerCase();
3766
+ if (SUPPORTED_LANGS.includes(tag)) return tag;
3767
+ const prefix = tag.split("-")[0];
3768
+ if (SUPPORTED_LANGS.includes(prefix)) return prefix;
3769
+ }
3770
+ if (typeof process !== "undefined" && process.env?.LANG) {
3771
+ const lang = process.env.LANG.toLowerCase();
3772
+ if (lang.startsWith("zh")) return "zh";
3773
+ if (lang.startsWith("en")) return "en";
3774
+ }
3775
+ return "zh";
3776
+ }
3777
+ var i18n = instance.createInstance();
3778
+ i18n.init({
3779
+ lng: detectLanguage(),
3780
+ fallbackLng: "zh",
3781
+ supportedLngs: [...SUPPORTED_LANGS],
3782
+ ns: [...i18nNamespaces],
3783
+ defaultNS: "common",
3784
+ interpolation: { escapeValue: false },
3785
+ showSupportNotice: false,
3786
+ resources: {
3787
+ zh: {
3788
+ common: common_default,
3789
+ sidebar: sidebar_default,
3790
+ chat: chat_default,
3791
+ connectors: connectors_default,
3792
+ settings: settings_default,
3793
+ billing: billing_default,
3794
+ team: team_default,
3795
+ memory: memory_default,
3796
+ skills: skills_default,
3797
+ scheduler: scheduler_default,
3798
+ onboarding: onboarding_default,
3799
+ auth: auth_default,
3800
+ notifications: notifications_default
3801
+ },
3802
+ en: {
3803
+ common: common_default2,
3804
+ sidebar: sidebar_default2,
3805
+ chat: chat_default2,
3806
+ connectors: connectors_default2,
3807
+ settings: settings_default2,
3808
+ billing: billing_default2,
3809
+ team: team_default2,
3810
+ memory: memory_default2,
3811
+ skills: skills_default2,
3812
+ scheduler: scheduler_default2,
3813
+ onboarding: onboarding_default2,
3814
+ auth: auth_default2,
3815
+ notifications: notifications_default2
3816
+ }
3817
+ }
3818
+ });
3819
+
3820
+ // ../../node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/index.js
3821
+ import { webcrypto as crypto } from "crypto";
3822
+ var POOL_SIZE_MULTIPLIER = 128;
3823
+ var pool;
3824
+ var poolOffset;
3825
+ function fillPool(bytes) {
3826
+ if (!pool || pool.length < bytes) {
3827
+ pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
3828
+ crypto.getRandomValues(pool);
3829
+ poolOffset = 0;
3830
+ } else if (poolOffset + bytes > pool.length) {
3831
+ crypto.getRandomValues(pool);
3832
+ poolOffset = 0;
3833
+ }
3834
+ poolOffset += bytes;
3835
+ }
3836
+ function random(bytes) {
3837
+ fillPool(bytes |= 0);
3838
+ return pool.subarray(poolOffset - bytes, poolOffset);
3839
+ }
3840
+ function customRandom(alphabet2, defaultSize, getRandom) {
3841
+ let mask = (2 << 31 - Math.clz32(alphabet2.length - 1 | 1)) - 1;
3842
+ let step = Math.ceil(1.6 * mask * defaultSize / alphabet2.length);
3843
+ return (size = defaultSize) => {
3844
+ if (!size) return "";
3845
+ let id = "";
3846
+ while (true) {
3847
+ let bytes = getRandom(step);
3848
+ let i = step;
3849
+ while (i--) {
3850
+ id += alphabet2[bytes[i] & mask] || "";
3851
+ if (id.length >= size) return id;
3852
+ }
3853
+ }
3854
+ };
3855
+ }
3856
+ function customAlphabet(alphabet2, size = 21) {
3857
+ return customRandom(alphabet2, size, random);
3858
+ }
3859
+
3860
+ // ../../packages/core/src/utils/id.ts
3861
+ var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-";
3862
+ var generate = customAlphabet(alphabet, 12);
3863
+ var createId = (prefix) => prefix ? `${prefix}_${generate()}` : generate();
3864
+
3865
+ // ../../packages/core/src/utils/logger.ts
3866
+ import pino from "pino";
3867
+ var logger = pino({ name: "jowork" });
3868
+
3869
+ // ../../packages/core/src/utils/tokens.ts
3870
+ function estimateTokens(text2) {
3871
+ const cjkChars = (text2.match(/[\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]/g) || []).length;
3872
+ const otherChars = text2.length - cjkChars;
3873
+ return Math.ceil(cjkChars / 2 + otherChars / 4);
3874
+ }
3875
+
3876
+ // ../../packages/core/src/utils/compaction.ts
3877
+ function shouldCompact(messages2, opts = {}) {
3878
+ const contextWindow = opts.contextWindow ?? 1e5;
3879
+ const reserveTokens = opts.reserveTokens ?? 16e3;
3880
+ const totalTokens = messages2.reduce((sum, m) => sum + estimateTokens(m.content), 0);
3881
+ return totalTokens > contextWindow - reserveTokens;
3882
+ }
3883
+ function findCutPoint(messages2, keepRecentTokens) {
3884
+ let recentTokens = 0;
3885
+ for (let i = messages2.length - 1; i >= 0; i--) {
3886
+ recentTokens += estimateTokens(messages2[i].content);
3887
+ if (recentTokens >= keepRecentTokens) {
3888
+ for (let j = i; j >= 0; j--) {
3889
+ if (messages2[j].role === "user" || messages2[j].role === "assistant") return j;
3890
+ }
3891
+ return i;
3892
+ }
3893
+ }
3894
+ return 0;
3895
+ }
3896
+ function compactMessages(messages2, opts = {}) {
3897
+ const keepRecentTokens = opts.keepRecentTokens ?? 2e4;
3898
+ const cutPoint = findCutPoint(messages2, keepRecentTokens);
3899
+ if (cutPoint <= 0) {
3900
+ return { summary: "", keptMessages: messages2, compactedCount: 0, tokensSaved: 0 };
3901
+ }
3902
+ const toCompact = messages2.slice(0, cutPoint);
3903
+ const toKeep = messages2.slice(cutPoint);
3904
+ const summary = buildExtractiveSummary(toCompact);
3905
+ const tokensSaved = toCompact.reduce((sum, m) => sum + estimateTokens(m.content), 0) - estimateTokens(summary);
3906
+ return { summary, keptMessages: toKeep, compactedCount: toCompact.length, tokensSaved: Math.max(0, tokensSaved) };
3907
+ }
3908
+ function buildExtractiveSummary(messages2) {
3909
+ const userMessages = messages2.filter((m) => m.role === "user");
3910
+ const assistantMessages = messages2.filter((m) => m.role === "assistant");
3911
+ const toolMessages = messages2.filter((m) => m.role === "tool" || m.toolName);
3912
+ const sections = ["## \u5BF9\u8BDD\u5386\u53F2\u6458\u8981\n"];
3913
+ if (userMessages.length > 0) {
3914
+ sections.push("### \u7528\u6237\u76EE\u6807");
3915
+ sections.push(userMessages.slice(0, 3).map(
3916
+ (m) => `- ${m.content.slice(0, 200).replace(/\n/g, " ")}${m.content.length > 200 ? "\u2026" : ""}`
3917
+ ).join("\n"));
3918
+ sections.push("");
3919
+ }
3920
+ const decisionPatterns = /决定|选择|方案|采用|使用|confirmed|decided|chose|approach|strategy/i;
3921
+ const decisions = assistantMessages.filter((m) => decisionPatterns.test(m.content)).slice(0, 5).map((m) => `- ${m.content.slice(0, 200).replace(/\n/g, " ")}${m.content.length > 200 ? "\u2026" : ""}`);
3922
+ if (decisions.length > 0) {
3923
+ sections.push("### \u5173\u952E\u51B3\u7B56");
3924
+ sections.push(decisions.join("\n"));
3925
+ sections.push("");
3926
+ }
3927
+ if (toolMessages.length > 0) {
3928
+ const toolNames = [...new Set(toolMessages.map((m) => m.toolName).filter(Boolean))];
3929
+ if (toolNames.length > 0) sections.push(`### \u5DF2\u4F7F\u7528\u7684\u5DE5\u5177
3930
+ - ${toolNames.join("\u3001")}
3931
+ `);
3932
+ }
3933
+ const lastExchanges = messages2.slice(-4);
3934
+ if (lastExchanges.length > 0) {
3935
+ sections.push("### \u6700\u8FD1\u8FDB\u5C55");
3936
+ for (const msg of lastExchanges) {
3937
+ const prefix = msg.role === "user" ? "\u7528\u6237" : msg.role === "assistant" ? "AI" : msg.role;
3938
+ sections.push(`- [${prefix}] ${msg.content.slice(0, 150).replace(/\n/g, " ")}${msg.content.length > 150 ? "\u2026" : ""}`);
3939
+ }
3940
+ sections.push("");
3941
+ }
3942
+ return sections.join("\n");
3943
+ }
3944
+ function mergeSummaries(existing, newSummary) {
3945
+ if (!existing) return newSummary;
3946
+ return `${newSummary}
3947
+
3948
+ ### \u66F4\u65E9\u7684\u5386\u53F2
3949
+
3950
+ ${existing.replace(/^## 对话历史摘要\n/, "").trim()}`;
3951
+ }
3952
+
3953
+ // ../../packages/core/src/utils/fts.ts
3954
+ var CJK_RANGES = "\\u4e00-\\u9fff\\u3400-\\u4dbf\\uf900-\\ufaff\\u3000-\\u303f\\uff00-\\uffef";
3955
+ var CJK_RE = new RegExp(`[${CJK_RANGES}]`);
3956
+ var CJK_THEN_LATIN = new RegExp(`([${CJK_RANGES}])([a-zA-Z0-9])`, "g");
3957
+ var LATIN_THEN_CJK = new RegExp(`([a-zA-Z0-9])([${CJK_RANGES}])`, "g");
3958
+ function ftsNormalize(text2) {
3959
+ return text2.replace(CJK_THEN_LATIN, "$1 $2").replace(LATIN_THEN_CJK, "$1 $2");
3960
+ }
3961
+ function buildFtsQuery(input) {
3962
+ const parts = input.split(/[\s,.:;!?()[\]{}<>'"、。,!?()【】《》""''·\-/\\|]+/).filter(Boolean);
3963
+ const latinTokens = [];
3964
+ let hasCjk = false;
3965
+ for (const part of parts) {
3966
+ if (CJK_RE.test(part)) {
3967
+ hasCjk = true;
3968
+ const latinParts = part.split(new RegExp(`[${CJK_RANGES}]+`)).filter((p) => p.length >= 2);
3969
+ latinTokens.push(...latinParts);
3970
+ } else if (part.length >= 2) {
3971
+ latinTokens.push(part.replace(/['"(){}*:^~\-+[\]]/g, ""));
3972
+ }
3973
+ }
3974
+ if (hasCjk && latinTokens.length === 0) return null;
3975
+ if (latinTokens.length === 0) return null;
3976
+ return latinTokens.join(" OR ");
3977
+ }
3978
+ function detectSourceFromQuery(query) {
3979
+ const lower = query.toLowerCase();
3980
+ if (/飞书|feishu|lark/.test(lower)) return "feishu";
3981
+ if (/\bgithub\b/.test(lower)) return "github";
3982
+ if (/\bgitlab\b/.test(lower)) return "gitlab";
3983
+ if (/\bnotion\b/.test(lower)) return "notion";
3984
+ if (/\bslack\b/.test(lower)) return "slack";
3985
+ return null;
3986
+ }
3987
+ var SOURCE_ALIASES = {
3988
+ feishu: "feishu \u98DE\u4E66 lark",
3989
+ github: "github",
3990
+ gitlab: "gitlab",
3991
+ notion: "notion",
3992
+ slack: "slack",
3993
+ local: "local \u672C\u5730"
3994
+ };
3995
+ function ftsEnrichSource(source) {
3996
+ return SOURCE_ALIASES[source] ?? source;
3997
+ }
3998
+
3999
+ export {
4000
+ ENGINE_CLAUDE_CODE,
4001
+ ENGINE_OPENCLAW,
4002
+ ENGINE_NEMOCLAW,
4003
+ ENGINE_CLOUD,
4004
+ sessions,
4005
+ messages,
4006
+ engineSessionMappings,
4007
+ settings,
4008
+ connectorConfigs,
4009
+ objects,
4010
+ objectBodies,
4011
+ syncCursors,
4012
+ objectChunks,
4013
+ memories,
4014
+ contextDocs,
4015
+ scheduledTasks,
4016
+ taskExecutions,
4017
+ runMigrations,
4018
+ i18nNamespaces,
4019
+ i18n,
4020
+ createId,
4021
+ logger,
4022
+ estimateTokens,
4023
+ shouldCompact,
4024
+ compactMessages,
4025
+ mergeSummaries,
4026
+ CJK_RE,
4027
+ ftsNormalize,
4028
+ buildFtsQuery,
4029
+ detectSourceFromQuery,
4030
+ ftsEnrichSource
4031
+ };