@shuo-li/i18n 1.1.0 → 1.2.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.
- package/dist/{cacheEvents-DAFvp5or.d.cts → cacheEvents-BwXBBuex.d.cts} +17 -6
- package/dist/{cacheEvents-DAFvp5or.d.ts → cacheEvents-BwXBBuex.d.ts} +17 -6
- package/dist/{chunk-LZQP6OHB.js → chunk-FFIQQFC4.js} +81 -90
- package/dist/chunk-JOUVTRSA.cjs +61 -0
- package/dist/chunk-NEXKR7GY.js +61 -0
- package/dist/{chunk-T7476FJ4.cjs → chunk-UMU62XLB.cjs} +105 -114
- package/dist/index.cjs +41 -22
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +39 -20
- package/dist/mp/index.cjs +31 -9
- package/dist/mp/index.d.cts +2 -2
- package/dist/mp/index.d.ts +2 -2
- package/dist/mp/index.js +29 -7
- package/dist/native/index.cjs +26 -4
- package/dist/native/index.d.cts +2 -2
- package/dist/native/index.d.ts +2 -2
- package/dist/native/index.js +24 -2
- package/dist/workers/preload-worker.cjs +90 -5
- package/dist/workers/preload-worker.js +89 -4
- package/package.json +1 -1
|
@@ -39,20 +39,22 @@ interface I18nInitOptions {
|
|
|
39
39
|
sse?: SSEConfig;
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
interface I18nValue {
|
|
43
|
+
termCode?: string;
|
|
44
|
+
langValue?: string;
|
|
45
|
+
}
|
|
42
46
|
interface PullLangBlock {
|
|
43
47
|
langCode: string;
|
|
44
48
|
modules: Array<{
|
|
45
49
|
moduleCode: string;
|
|
46
50
|
version: number;
|
|
47
|
-
|
|
48
|
-
resources: Record<string, unknown>;
|
|
51
|
+
i18nValues: I18nValue[];
|
|
49
52
|
}>;
|
|
50
53
|
}
|
|
51
54
|
interface SSEMessage {
|
|
52
55
|
type: string;
|
|
53
56
|
langCode: string;
|
|
54
57
|
moduleCode: string;
|
|
55
|
-
/** SSE 消息携带的数据版本号,与本地 version 对比决定是否拉取 */
|
|
56
58
|
version: number;
|
|
57
59
|
storeName: string;
|
|
58
60
|
}
|
|
@@ -71,7 +73,6 @@ interface ResourceRecord {
|
|
|
71
73
|
key: string;
|
|
72
74
|
moduleCode: string;
|
|
73
75
|
langCode: string;
|
|
74
|
-
/** 当前已存储数据的版本号(对应旧的 toSynTime) */
|
|
75
76
|
version: number;
|
|
76
77
|
resources: Record<string, unknown>;
|
|
77
78
|
}
|
|
@@ -81,6 +82,8 @@ interface WorkerTask {
|
|
|
81
82
|
moduleCode?: string;
|
|
82
83
|
/** 全量拉取时为 0;SSE 增量拉取时为本地已有版本号 */
|
|
83
84
|
version?: number;
|
|
85
|
+
/** 唯一标识,用于主线程回传 parsedData 时关联任务(Web 模式下必须) */
|
|
86
|
+
taskId?: number;
|
|
84
87
|
trigger?: 'init-full' | 'sse';
|
|
85
88
|
/** 经 buildParams 映射后的实际请求参数;未提供时 Worker 使用内部字段名 */
|
|
86
89
|
params?: Record<string, unknown>;
|
|
@@ -90,6 +93,14 @@ interface WorkerRawDataMessage {
|
|
|
90
93
|
task: WorkerTask;
|
|
91
94
|
raw: unknown;
|
|
92
95
|
}
|
|
96
|
+
/** Worker 写入一个模块后通知主线程(Web 模式,Worker 写 IDB) */
|
|
97
|
+
interface WorkerModuleLoadedMessage {
|
|
98
|
+
type: 'moduleLoaded';
|
|
99
|
+
storeName: string;
|
|
100
|
+
moduleCode: string;
|
|
101
|
+
langCode: string;
|
|
102
|
+
version: number;
|
|
103
|
+
}
|
|
93
104
|
interface WorkerModuleErrorMessage {
|
|
94
105
|
type: 'moduleError';
|
|
95
106
|
storeName: string;
|
|
@@ -103,7 +114,7 @@ interface WorkerErrorMessage {
|
|
|
103
114
|
type: 'error';
|
|
104
115
|
message?: string;
|
|
105
116
|
}
|
|
106
|
-
type WorkerOutMessage = WorkerRawDataMessage | WorkerModuleErrorMessage | WorkerDoneMessage | WorkerErrorMessage;
|
|
117
|
+
type WorkerOutMessage = WorkerRawDataMessage | WorkerModuleLoadedMessage | WorkerModuleErrorMessage | WorkerDoneMessage | WorkerErrorMessage;
|
|
107
118
|
interface WorkerLike {
|
|
108
119
|
postMessage(data: unknown): void;
|
|
109
120
|
onMessage(handler: (data: WorkerOutMessage) => void): void;
|
|
@@ -119,4 +130,4 @@ declare function getAllRecordsByModule(moduleCode: string): Promise<ResourceReco
|
|
|
119
130
|
declare const I18N_RESOURCES_UPDATED_EVENT = "golucky:i18n-resources-updated";
|
|
120
131
|
declare function emitI18nResourcesUpdated(): void;
|
|
121
132
|
|
|
122
|
-
export { I18N_RESOURCES_UPDATED_EVENT as I, type PullLangBlock as P, type ResourceRecord as R, type SSEMessage as S, type WorkerLike as W, getResource as a, type I18nInitOptions as b, closeSSE as c, type StandardPullParams as d, ensureModules as e, type StoreConfig as f, getAllRecordsByModule as g, emitI18nResourcesUpdated as h, initI18n as i };
|
|
133
|
+
export { I18N_RESOURCES_UPDATED_EVENT as I, type PullLangBlock as P, type ResourceRecord as R, type SSEMessage as S, type WorkerLike as W, getResource as a, type I18nInitOptions as b, closeSSE as c, type StandardPullParams as d, ensureModules as e, type StoreConfig as f, getAllRecordsByModule as g, emitI18nResourcesUpdated as h, initI18n as i, type I18nValue as j };
|
|
@@ -39,20 +39,22 @@ interface I18nInitOptions {
|
|
|
39
39
|
sse?: SSEConfig;
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
interface I18nValue {
|
|
43
|
+
termCode?: string;
|
|
44
|
+
langValue?: string;
|
|
45
|
+
}
|
|
42
46
|
interface PullLangBlock {
|
|
43
47
|
langCode: string;
|
|
44
48
|
modules: Array<{
|
|
45
49
|
moduleCode: string;
|
|
46
50
|
version: number;
|
|
47
|
-
|
|
48
|
-
resources: Record<string, unknown>;
|
|
51
|
+
i18nValues: I18nValue[];
|
|
49
52
|
}>;
|
|
50
53
|
}
|
|
51
54
|
interface SSEMessage {
|
|
52
55
|
type: string;
|
|
53
56
|
langCode: string;
|
|
54
57
|
moduleCode: string;
|
|
55
|
-
/** SSE 消息携带的数据版本号,与本地 version 对比决定是否拉取 */
|
|
56
58
|
version: number;
|
|
57
59
|
storeName: string;
|
|
58
60
|
}
|
|
@@ -71,7 +73,6 @@ interface ResourceRecord {
|
|
|
71
73
|
key: string;
|
|
72
74
|
moduleCode: string;
|
|
73
75
|
langCode: string;
|
|
74
|
-
/** 当前已存储数据的版本号(对应旧的 toSynTime) */
|
|
75
76
|
version: number;
|
|
76
77
|
resources: Record<string, unknown>;
|
|
77
78
|
}
|
|
@@ -81,6 +82,8 @@ interface WorkerTask {
|
|
|
81
82
|
moduleCode?: string;
|
|
82
83
|
/** 全量拉取时为 0;SSE 增量拉取时为本地已有版本号 */
|
|
83
84
|
version?: number;
|
|
85
|
+
/** 唯一标识,用于主线程回传 parsedData 时关联任务(Web 模式下必须) */
|
|
86
|
+
taskId?: number;
|
|
84
87
|
trigger?: 'init-full' | 'sse';
|
|
85
88
|
/** 经 buildParams 映射后的实际请求参数;未提供时 Worker 使用内部字段名 */
|
|
86
89
|
params?: Record<string, unknown>;
|
|
@@ -90,6 +93,14 @@ interface WorkerRawDataMessage {
|
|
|
90
93
|
task: WorkerTask;
|
|
91
94
|
raw: unknown;
|
|
92
95
|
}
|
|
96
|
+
/** Worker 写入一个模块后通知主线程(Web 模式,Worker 写 IDB) */
|
|
97
|
+
interface WorkerModuleLoadedMessage {
|
|
98
|
+
type: 'moduleLoaded';
|
|
99
|
+
storeName: string;
|
|
100
|
+
moduleCode: string;
|
|
101
|
+
langCode: string;
|
|
102
|
+
version: number;
|
|
103
|
+
}
|
|
93
104
|
interface WorkerModuleErrorMessage {
|
|
94
105
|
type: 'moduleError';
|
|
95
106
|
storeName: string;
|
|
@@ -103,7 +114,7 @@ interface WorkerErrorMessage {
|
|
|
103
114
|
type: 'error';
|
|
104
115
|
message?: string;
|
|
105
116
|
}
|
|
106
|
-
type WorkerOutMessage = WorkerRawDataMessage | WorkerModuleErrorMessage | WorkerDoneMessage | WorkerErrorMessage;
|
|
117
|
+
type WorkerOutMessage = WorkerRawDataMessage | WorkerModuleLoadedMessage | WorkerModuleErrorMessage | WorkerDoneMessage | WorkerErrorMessage;
|
|
107
118
|
interface WorkerLike {
|
|
108
119
|
postMessage(data: unknown): void;
|
|
109
120
|
onMessage(handler: (data: WorkerOutMessage) => void): void;
|
|
@@ -119,4 +130,4 @@ declare function getAllRecordsByModule(moduleCode: string): Promise<ResourceReco
|
|
|
119
130
|
declare const I18N_RESOURCES_UPDATED_EVENT = "golucky:i18n-resources-updated";
|
|
120
131
|
declare function emitI18nResourcesUpdated(): void;
|
|
121
132
|
|
|
122
|
-
export { I18N_RESOURCES_UPDATED_EVENT as I, type PullLangBlock as P, type ResourceRecord as R, type SSEMessage as S, type WorkerLike as W, getResource as a, type I18nInitOptions as b, closeSSE as c, type StandardPullParams as d, ensureModules as e, type StoreConfig as f, getAllRecordsByModule as g, emitI18nResourcesUpdated as h, initI18n as i };
|
|
133
|
+
export { I18N_RESOURCES_UPDATED_EVENT as I, type PullLangBlock as P, type ResourceRecord as R, type SSEMessage as S, type WorkerLike as W, getResource as a, type I18nInitOptions as b, closeSSE as c, type StandardPullParams as d, ensureModules as e, type StoreConfig as f, getAllRecordsByModule as g, emitI18nResourcesUpdated as h, initI18n as i, type I18nValue as j };
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildKey,
|
|
3
|
+
deepMerge,
|
|
4
|
+
flatToNested,
|
|
5
|
+
parseI18nValues,
|
|
6
|
+
toDefaultParams,
|
|
7
|
+
toQueryString
|
|
8
|
+
} from "./chunk-NEXKR7GY.js";
|
|
9
|
+
|
|
1
10
|
// src/core/cacheEvents.ts
|
|
2
11
|
var I18N_RESOURCES_UPDATED_EVENT = "golucky:i18n-resources-updated";
|
|
3
12
|
function emitI18nResourcesUpdated() {
|
|
@@ -5,52 +14,6 @@ function emitI18nResourcesUpdated() {
|
|
|
5
14
|
window.dispatchEvent(new CustomEvent(I18N_RESOURCES_UPDATED_EVENT));
|
|
6
15
|
}
|
|
7
16
|
|
|
8
|
-
// src/core/utils.ts
|
|
9
|
-
function buildKey(moduleCode, langCode, store) {
|
|
10
|
-
return store.cacheGroupKey ? `${moduleCode}_${langCode}_${store.cacheGroupKey}` : `${moduleCode}_${langCode}`;
|
|
11
|
-
}
|
|
12
|
-
function flatToNested(flat) {
|
|
13
|
-
const result = {};
|
|
14
|
-
for (const [key, value] of Object.entries(flat)) {
|
|
15
|
-
const parts = key.split(".");
|
|
16
|
-
let cur = result;
|
|
17
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
18
|
-
const part = parts[i];
|
|
19
|
-
if (typeof cur[part] !== "object" || cur[part] === null) {
|
|
20
|
-
cur[part] = {};
|
|
21
|
-
}
|
|
22
|
-
cur = cur[part];
|
|
23
|
-
}
|
|
24
|
-
cur[parts[parts.length - 1]] = value;
|
|
25
|
-
}
|
|
26
|
-
return result;
|
|
27
|
-
}
|
|
28
|
-
function deepMerge(target, source) {
|
|
29
|
-
const result = { ...target };
|
|
30
|
-
for (const [key, sv] of Object.entries(source)) {
|
|
31
|
-
const tv = result[key];
|
|
32
|
-
if (sv !== null && typeof sv === "object" && !Array.isArray(sv) && tv !== null && typeof tv === "object" && !Array.isArray(tv)) {
|
|
33
|
-
result[key] = deepMerge(tv, sv);
|
|
34
|
-
} else {
|
|
35
|
-
result[key] = sv;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return result;
|
|
39
|
-
}
|
|
40
|
-
function toDefaultParams(p) {
|
|
41
|
-
const result = {};
|
|
42
|
-
if (p?.storeName) result["storeName"] = p.storeName;
|
|
43
|
-
if (p?.langCode) result["langCode"] = p.langCode;
|
|
44
|
-
if (p?.moduleCode) result["moduleCode"] = p.moduleCode;
|
|
45
|
-
if (p?.version != null) result["version"] = String(p.version);
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
function toQueryString(params) {
|
|
49
|
-
return new URLSearchParams(
|
|
50
|
-
Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
|
|
51
|
-
).toString();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
17
|
// src/core/manager.ts
|
|
55
18
|
import i18n from "i18next";
|
|
56
19
|
|
|
@@ -182,12 +145,31 @@ var WorkerManager = class {
|
|
|
182
145
|
}
|
|
183
146
|
const worker = createWorker();
|
|
184
147
|
this.worker = worker;
|
|
148
|
+
const workerWritesDB = typeof callbacks.transformRaw === "function";
|
|
185
149
|
worker.onMessage((msg) => {
|
|
186
150
|
if (msg.type === "rawData") {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
151
|
+
if (workerWritesDB && callbacks.transformRaw) {
|
|
152
|
+
let blocks;
|
|
153
|
+
try {
|
|
154
|
+
blocks = callbacks.transformRaw(msg.task, msg.raw);
|
|
155
|
+
} catch (err) {
|
|
156
|
+
console.error("[i18n] transform failed", msg.task, err);
|
|
157
|
+
blocks = [];
|
|
158
|
+
}
|
|
159
|
+
worker.postMessage({ type: "parsedData", taskId: msg.task.taskId, blocks });
|
|
160
|
+
} else if (callbacks.onRawData) {
|
|
161
|
+
const p = callbacks.onRawData(msg.task, msg.raw).catch(() => {
|
|
162
|
+
});
|
|
163
|
+
this.pendingCallbacks.add(p);
|
|
164
|
+
p.finally(() => this.pendingCallbacks.delete(p));
|
|
165
|
+
}
|
|
166
|
+
} else if (msg.type === "moduleLoaded") {
|
|
167
|
+
if (callbacks.onModuleLoaded) {
|
|
168
|
+
const p = callbacks.onModuleLoaded(msg).catch(() => {
|
|
169
|
+
});
|
|
170
|
+
this.pendingCallbacks.add(p);
|
|
171
|
+
p.finally(() => this.pendingCallbacks.delete(p));
|
|
172
|
+
}
|
|
191
173
|
} else if (msg.type === "moduleError") {
|
|
192
174
|
callbacks.onModuleError?.(msg);
|
|
193
175
|
} else if (msg.type === "done" || msg.type === "error") {
|
|
@@ -227,6 +209,7 @@ var resolvedLanguages = [];
|
|
|
227
209
|
var unloginPullStarted = false;
|
|
228
210
|
var managerOptions = null;
|
|
229
211
|
var initOptions = null;
|
|
212
|
+
var taskIdCounter = 0;
|
|
230
213
|
var loadedModules = /* @__PURE__ */ new Set();
|
|
231
214
|
var loadingModules = /* @__PURE__ */ new Set();
|
|
232
215
|
var sseClient = new SSEClient();
|
|
@@ -363,24 +346,15 @@ async function _initI18n(options) {
|
|
|
363
346
|
startSSE(options);
|
|
364
347
|
}
|
|
365
348
|
}
|
|
366
|
-
var CACHE_VERSION_KEY = "__meta__:cache_version";
|
|
367
349
|
async function checkCacheVersion(storage, options) {
|
|
368
350
|
if (options.version == null) return;
|
|
369
|
-
const baseStoreName = resolvedStores[0].name;
|
|
370
351
|
const current = String(options.version);
|
|
371
|
-
const
|
|
372
|
-
const stored = record?.resources?.["value"];
|
|
352
|
+
const stored = await storage.getMeta("cache_version").catch(() => null);
|
|
373
353
|
if (stored === current) return;
|
|
374
354
|
for (const store of options.stores) {
|
|
375
355
|
await storage.clearStore(store.name);
|
|
376
356
|
}
|
|
377
|
-
await storage.
|
|
378
|
-
key: CACHE_VERSION_KEY,
|
|
379
|
-
moduleCode: "__meta__",
|
|
380
|
-
langCode: "__meta__",
|
|
381
|
-
version: 0,
|
|
382
|
-
resources: { value: current }
|
|
383
|
-
});
|
|
357
|
+
await storage.setMeta("cache_version", current);
|
|
384
358
|
}
|
|
385
359
|
async function doUnloginPull(storage, options) {
|
|
386
360
|
const { apiContext } = options;
|
|
@@ -398,9 +372,10 @@ async function doUnloginPull(storage, options) {
|
|
|
398
372
|
for (const mod of block.modules ?? []) {
|
|
399
373
|
const key = buildKey(mod.moduleCode, block.langCode, baseStore);
|
|
400
374
|
const existing = await storage.getRecord(baseStore.name, key);
|
|
375
|
+
const flat = parseI18nValues(mod.i18nValues);
|
|
401
376
|
const resources = deepMerge(
|
|
402
377
|
existing?.resources ?? {},
|
|
403
|
-
|
|
378
|
+
flatToNested(flat)
|
|
404
379
|
);
|
|
405
380
|
await storage.putRecord(baseStore.name, {
|
|
406
381
|
key,
|
|
@@ -420,16 +395,13 @@ async function startWorkerFull(options) {
|
|
|
420
395
|
const pull = apiContext.pull;
|
|
421
396
|
const tasks = [];
|
|
422
397
|
for (const store of resolvedStores) {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
}
|
|
398
|
+
const internal = { storeName: store.name };
|
|
399
|
+
tasks.push({
|
|
400
|
+
storeName: store.name,
|
|
401
|
+
taskId: ++taskIdCounter,
|
|
402
|
+
trigger: "init-full",
|
|
403
|
+
params: pull.buildParams ? pull.buildParams(internal) : void 0
|
|
404
|
+
});
|
|
433
405
|
}
|
|
434
406
|
await runWorker(options, tasks, pull);
|
|
435
407
|
}
|
|
@@ -437,16 +409,35 @@ function runWorker(options, tasks, pull) {
|
|
|
437
409
|
return new Promise((resolve, reject) => {
|
|
438
410
|
const { apiContext } = options;
|
|
439
411
|
const storage = managerOptions.storage;
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
412
|
+
const workerWritesDB = managerOptions.workerWritesDB ?? false;
|
|
413
|
+
const payload = {
|
|
414
|
+
baseURL: apiContext.baseURL,
|
|
415
|
+
headers: apiContext.getHeaders(),
|
|
416
|
+
pullPath: pull.path,
|
|
417
|
+
pullMethod: pull.method ?? "GET",
|
|
418
|
+
tasks,
|
|
419
|
+
...workerWritesDB ? { storeConfigs: resolvedStores } : {}
|
|
420
|
+
};
|
|
421
|
+
if (workerWritesDB) {
|
|
422
|
+
workerManager.start(managerOptions.createWorker, payload, {
|
|
423
|
+
transformRaw: (task, raw) => {
|
|
424
|
+
try {
|
|
425
|
+
return pull.transform ? pull.transform(raw) : raw;
|
|
426
|
+
} catch (err) {
|
|
427
|
+
console.error("[i18n] pull transform \u5931\u8D25", task, err);
|
|
428
|
+
return [];
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
onModuleLoaded: async (info) => {
|
|
432
|
+
await onModuleLoaded(info);
|
|
433
|
+
},
|
|
434
|
+
onModuleError: () => {
|
|
435
|
+
},
|
|
436
|
+
onDone: resolve,
|
|
437
|
+
onError: () => reject(new Error("[i18n] Worker fatal error"))
|
|
438
|
+
});
|
|
439
|
+
} else {
|
|
440
|
+
workerManager.start(managerOptions.createWorker, payload, {
|
|
450
441
|
onRawData: async (task, raw) => {
|
|
451
442
|
let blocks;
|
|
452
443
|
try {
|
|
@@ -463,7 +454,8 @@ function runWorker(options, tasks, pull) {
|
|
|
463
454
|
const key = buildKey(mod.moduleCode, block.langCode, store);
|
|
464
455
|
const existing = await storage.getRecord(store.name, key);
|
|
465
456
|
if (existing && mod.version <= existing.version) continue;
|
|
466
|
-
const
|
|
457
|
+
const flat = parseI18nValues(mod.i18nValues);
|
|
458
|
+
const resources = storeIndex === 0 ? deepMerge(existing?.resources ?? {}, flatToNested(flat)) : { ...existing?.resources ?? {}, ...flat };
|
|
467
459
|
await storage.putRecord(store.name, {
|
|
468
460
|
key,
|
|
469
461
|
moduleCode: mod.moduleCode,
|
|
@@ -473,19 +465,19 @@ function runWorker(options, tasks, pull) {
|
|
|
473
465
|
});
|
|
474
466
|
await onModuleLoaded({
|
|
475
467
|
storeName: task.storeName,
|
|
476
|
-
langCode: block.langCode,
|
|
477
468
|
moduleCode: mod.moduleCode,
|
|
469
|
+
langCode: block.langCode,
|
|
478
470
|
version: mod.version
|
|
479
471
|
});
|
|
480
472
|
}
|
|
481
473
|
}
|
|
482
474
|
},
|
|
483
|
-
onModuleError: (
|
|
475
|
+
onModuleError: () => {
|
|
484
476
|
},
|
|
485
477
|
onDone: resolve,
|
|
486
478
|
onError: () => reject(new Error("[i18n] Worker fatal error"))
|
|
487
|
-
}
|
|
488
|
-
|
|
479
|
+
});
|
|
480
|
+
}
|
|
489
481
|
});
|
|
490
482
|
}
|
|
491
483
|
async function onModuleLoaded(data) {
|
|
@@ -609,7 +601,8 @@ async function pullAndStore(task, fromVersion, options) {
|
|
|
609
601
|
const key = buildKey(mod.moduleCode, block.langCode, store);
|
|
610
602
|
const existing = await storage.getRecord(store.name, key);
|
|
611
603
|
if (mod.version <= (existing?.version ?? 0)) continue;
|
|
612
|
-
const
|
|
604
|
+
const flat = parseI18nValues(mod.i18nValues);
|
|
605
|
+
const resources = storeIndex === 0 ? deepMerge(existing?.resources ?? {}, flatToNested(flat)) : { ...existing?.resources ?? {}, ...flat };
|
|
613
606
|
const version = Math.max(mod.version, task.targetVersion);
|
|
614
607
|
await storage.putRecord(store.name, {
|
|
615
608
|
key,
|
|
@@ -665,7 +658,5 @@ async function getStoredVersion(store, moduleCode, langCode) {
|
|
|
665
658
|
export {
|
|
666
659
|
I18N_RESOURCES_UPDATED_EVENT,
|
|
667
660
|
emitI18nResourcesUpdated,
|
|
668
|
-
flatToNested,
|
|
669
|
-
deepMerge,
|
|
670
661
|
createI18nManager
|
|
671
662
|
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/core/utils.ts
|
|
2
|
+
function buildKey(moduleCode, langCode, store) {
|
|
3
|
+
return store.cacheGroupKey ? `${moduleCode}_${langCode}_${store.cacheGroupKey}` : `${moduleCode}_${langCode}`;
|
|
4
|
+
}
|
|
5
|
+
function parseI18nValues(values) {
|
|
6
|
+
const result = {};
|
|
7
|
+
for (const v of values) {
|
|
8
|
+
if (v.termCode) result[v.termCode] = _nullishCoalesce(v.langValue, () => ( ""));
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
function flatToNested(flat) {
|
|
13
|
+
const result = {};
|
|
14
|
+
for (const [key, value] of Object.entries(flat)) {
|
|
15
|
+
const parts = key.split(".");
|
|
16
|
+
let cur = result;
|
|
17
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
18
|
+
const part = parts[i];
|
|
19
|
+
if (typeof cur[part] !== "object" || cur[part] === null) {
|
|
20
|
+
cur[part] = {};
|
|
21
|
+
}
|
|
22
|
+
cur = cur[part];
|
|
23
|
+
}
|
|
24
|
+
cur[parts[parts.length - 1]] = value;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
function deepMerge(target, source) {
|
|
29
|
+
const result = { ...target };
|
|
30
|
+
for (const [key, sv] of Object.entries(source)) {
|
|
31
|
+
const tv = result[key];
|
|
32
|
+
if (sv !== null && typeof sv === "object" && !Array.isArray(sv) && tv !== null && typeof tv === "object" && !Array.isArray(tv)) {
|
|
33
|
+
result[key] = deepMerge(tv, sv);
|
|
34
|
+
} else {
|
|
35
|
+
result[key] = sv;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
function toDefaultParams(p) {
|
|
41
|
+
const result = {};
|
|
42
|
+
if (_optionalChain([p, 'optionalAccess', _ => _.storeName])) result["storeName"] = p.storeName;
|
|
43
|
+
if (_optionalChain([p, 'optionalAccess', _2 => _2.langCode])) result["langCode"] = p.langCode;
|
|
44
|
+
if (_optionalChain([p, 'optionalAccess', _3 => _3.moduleCode])) result["moduleCode"] = p.moduleCode;
|
|
45
|
+
if (_optionalChain([p, 'optionalAccess', _4 => _4.version]) != null) result["version"] = String(p.version);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function toQueryString(params) {
|
|
49
|
+
return new URLSearchParams(
|
|
50
|
+
Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
|
|
51
|
+
).toString();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
exports.buildKey = buildKey; exports.parseI18nValues = parseI18nValues; exports.flatToNested = flatToNested; exports.deepMerge = deepMerge; exports.toDefaultParams = toDefaultParams; exports.toQueryString = toQueryString;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/core/utils.ts
|
|
2
|
+
function buildKey(moduleCode, langCode, store) {
|
|
3
|
+
return store.cacheGroupKey ? `${moduleCode}_${langCode}_${store.cacheGroupKey}` : `${moduleCode}_${langCode}`;
|
|
4
|
+
}
|
|
5
|
+
function parseI18nValues(values) {
|
|
6
|
+
const result = {};
|
|
7
|
+
for (const v of values) {
|
|
8
|
+
if (v.termCode) result[v.termCode] = v.langValue ?? "";
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
function flatToNested(flat) {
|
|
13
|
+
const result = {};
|
|
14
|
+
for (const [key, value] of Object.entries(flat)) {
|
|
15
|
+
const parts = key.split(".");
|
|
16
|
+
let cur = result;
|
|
17
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
18
|
+
const part = parts[i];
|
|
19
|
+
if (typeof cur[part] !== "object" || cur[part] === null) {
|
|
20
|
+
cur[part] = {};
|
|
21
|
+
}
|
|
22
|
+
cur = cur[part];
|
|
23
|
+
}
|
|
24
|
+
cur[parts[parts.length - 1]] = value;
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
function deepMerge(target, source) {
|
|
29
|
+
const result = { ...target };
|
|
30
|
+
for (const [key, sv] of Object.entries(source)) {
|
|
31
|
+
const tv = result[key];
|
|
32
|
+
if (sv !== null && typeof sv === "object" && !Array.isArray(sv) && tv !== null && typeof tv === "object" && !Array.isArray(tv)) {
|
|
33
|
+
result[key] = deepMerge(tv, sv);
|
|
34
|
+
} else {
|
|
35
|
+
result[key] = sv;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
function toDefaultParams(p) {
|
|
41
|
+
const result = {};
|
|
42
|
+
if (p?.storeName) result["storeName"] = p.storeName;
|
|
43
|
+
if (p?.langCode) result["langCode"] = p.langCode;
|
|
44
|
+
if (p?.moduleCode) result["moduleCode"] = p.moduleCode;
|
|
45
|
+
if (p?.version != null) result["version"] = String(p.version);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function toQueryString(params) {
|
|
49
|
+
return new URLSearchParams(
|
|
50
|
+
Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
|
|
51
|
+
).toString();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export {
|
|
55
|
+
buildKey,
|
|
56
|
+
parseI18nValues,
|
|
57
|
+
flatToNested,
|
|
58
|
+
deepMerge,
|
|
59
|
+
toDefaultParams,
|
|
60
|
+
toQueryString
|
|
61
|
+
};
|