@shuo-li/i18n 1.0.9 → 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.
@@ -1,10 +1,47 @@
1
+ import {
2
+ buildKey,
3
+ deepMerge,
4
+ flatToNested,
5
+ parseI18nValues
6
+ } from "../chunk-NEXKR7GY.js";
7
+
1
8
  // src/workers/preload-worker.ts
9
+ var DB_NAME = "i18n_cache";
10
+ var pendingParsedData = /* @__PURE__ */ new Map();
11
+ var dbInstance = null;
12
+ function openDB() {
13
+ if (dbInstance) return Promise.resolve(dbInstance);
14
+ return new Promise((resolve, reject) => {
15
+ const req = indexedDB.open(DB_NAME);
16
+ req.onsuccess = () => {
17
+ dbInstance = req.result;
18
+ resolve(req.result);
19
+ };
20
+ req.onerror = () => reject(req.error);
21
+ });
22
+ }
23
+ function idbGet(db, storeName, key) {
24
+ return new Promise((resolve, reject) => {
25
+ const tx = db.transaction(`i18n_resources_${storeName}`, "readonly");
26
+ const req = tx.objectStore(`i18n_resources_${storeName}`).get(key);
27
+ req.onsuccess = () => resolve(req.result);
28
+ req.onerror = () => reject(req.error);
29
+ });
30
+ }
31
+ function idbPut(db, storeName, record) {
32
+ return new Promise((resolve, reject) => {
33
+ const tx = db.transaction(`i18n_resources_${storeName}`, "readwrite");
34
+ const req = tx.objectStore(`i18n_resources_${storeName}`).put(record);
35
+ req.onsuccess = () => resolve();
36
+ req.onerror = () => reject(req.error);
37
+ });
38
+ }
2
39
  function toQueryString(params) {
3
40
  return new URLSearchParams(
4
41
  Object.entries(params).filter(([, v]) => v != null).map(([k, v]) => [k, String(v)])
5
42
  ).toString();
6
43
  }
7
- async function processTask(task, payload) {
44
+ async function fetchRaw(task, payload) {
8
45
  const { baseURL, headers, pullPath, pullMethod } = payload;
9
46
  const params = task.params ?? {};
10
47
  if (!task.params) {
@@ -26,12 +63,60 @@ async function processTask(task, payload) {
26
63
  res = await fetch(qs ? `${url}?${qs}` : url, { headers });
27
64
  }
28
65
  if (!res.ok) throw new Error(`[i18n worker] fetch failed: ${res.status}`);
29
- const raw = await res.json();
66
+ return res.json();
67
+ }
68
+ async function writeBlocksToIDB(blocks, storeConfig, storeIndex) {
69
+ const db = await openDB();
70
+ for (const block of blocks) {
71
+ for (const mod of block.modules ?? []) {
72
+ const key = buildKey(mod.moduleCode, block.langCode, storeConfig);
73
+ const existing = await idbGet(db, storeConfig.name, key);
74
+ if (existing && mod.version <= (existing.version ?? 0)) continue;
75
+ const flat = parseI18nValues(mod.i18nValues);
76
+ const resources = storeIndex === 0 ? deepMerge(existing?.resources ?? {}, flatToNested(flat)) : { ...existing?.resources ?? {}, ...flat };
77
+ await idbPut(db, storeConfig.name, {
78
+ key,
79
+ moduleCode: mod.moduleCode,
80
+ langCode: block.langCode,
81
+ version: mod.version,
82
+ resources
83
+ });
84
+ self.postMessage({
85
+ type: "moduleLoaded",
86
+ storeName: storeConfig.name,
87
+ moduleCode: mod.moduleCode,
88
+ langCode: block.langCode,
89
+ version: mod.version
90
+ });
91
+ }
92
+ }
93
+ }
94
+ async function processTask(task, payload) {
95
+ const raw = await fetchRaw(task, payload);
30
96
  self.postMessage({ type: "rawData", task, raw });
97
+ const blocks = await new Promise((resolve) => {
98
+ pendingParsedData.set(task.taskId, resolve);
99
+ });
100
+ if (blocks.length === 0) return;
101
+ const storeConfigs = payload.storeConfigs ?? [];
102
+ const storeConfig = storeConfigs.find((s) => s.name === task.storeName);
103
+ if (!storeConfig) return;
104
+ const storeIndex = storeConfigs.indexOf(storeConfig);
105
+ await writeBlocksToIDB(blocks, storeConfig, storeIndex);
31
106
  }
32
107
  self.onmessage = async (event) => {
33
- if (event.data.type !== "start") return;
34
- const { payload } = event.data;
108
+ const data = event.data;
109
+ if (data.type === "parsedData") {
110
+ const { taskId, blocks } = data;
111
+ const resolve = pendingParsedData.get(taskId);
112
+ if (resolve) {
113
+ pendingParsedData.delete(taskId);
114
+ resolve(blocks);
115
+ }
116
+ return;
117
+ }
118
+ if (data.type !== "start") return;
119
+ const payload = data.payload;
35
120
  for (const task of payload.tasks) {
36
121
  try {
37
122
  await processTask(task, payload);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuo-li/i18n",
3
- "version": "1.0.9",
3
+ "version": "1.2.0",
4
4
  "description": "Cross-platform i18n library for Web, React Native and WeChat MiniProgram",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",