@zwa73/utils 1.0.224 → 1.0.226

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{types/QuickExport.d.ts → QuickExport.d.ts} +1 -1
  2. package/dist/{cjs/QuickExport.js → QuickExport.js} +2 -2
  3. package/dist/UtilClass/index.d.ts +3 -0
  4. package/dist/{cjs/UtilClass → UtilClass}/index.js +7 -6
  5. package/dist/{cjs/UtilCodecs.js → UtilCodecs.js} +1 -5
  6. package/dist/{cjs/UtilFileTools.js → UtilFileTools.js} +2 -2
  7. package/dist/{types/UtilFunctions.d.ts → UtilFunctions.d.ts} +1 -19
  8. package/dist/{cjs/UtilFunctions.js → UtilFunctions.js} +2 -26
  9. package/dist/{types/UtilInterfaces.d.ts → UtilInterfaces.d.ts} +1 -1
  10. package/package.json +2 -8
  11. package/dist/mjs/QuickExport.mjs +0 -35
  12. package/dist/mjs/UtilClass/Hbs.mjs +0 -51
  13. package/dist/mjs/UtilClass/index.mjs +0 -3
  14. package/dist/mjs/UtilCodecs.mjs +0 -109
  15. package/dist/mjs/UtilDecorators.mjs +0 -2
  16. package/dist/mjs/UtilFP.mjs +0 -2
  17. package/dist/mjs/UtilFileTools.mjs +0 -407
  18. package/dist/mjs/UtilFunctions.mjs +0 -138
  19. package/dist/mjs/UtilHttp.mjs +0 -475
  20. package/dist/mjs/UtilI18n.mjs +0 -206
  21. package/dist/mjs/UtilInterfaces.mjs +0 -2
  22. package/dist/mjs/UtilLogger.mjs +0 -361
  23. package/dist/mjs/UtilSymbol.mjs +0 -2
  24. package/dist/mjs/index.mjs +0 -17
  25. package/dist/types/UtilClass/index.d.ts +0 -3
  26. package/index.d.ts +0 -1
  27. package/index.js +0 -1
  28. /package/dist/{types/UtilClass → UtilClass}/Hbs.d.ts +0 -0
  29. /package/dist/{cjs/UtilClass → UtilClass}/Hbs.js +0 -0
  30. /package/dist/{types/UtilCodecs.d.ts → UtilCodecs.d.ts} +0 -0
  31. /package/dist/{types/UtilDecorators.d.ts → UtilDecorators.d.ts} +0 -0
  32. /package/dist/{cjs/UtilDecorators.js → UtilDecorators.js} +0 -0
  33. /package/dist/{types/UtilFP.d.ts → UtilFP.d.ts} +0 -0
  34. /package/dist/{cjs/UtilFP.js → UtilFP.js} +0 -0
  35. /package/dist/{types/UtilFileTools.d.ts → UtilFileTools.d.ts} +0 -0
  36. /package/dist/{types/UtilHttp.d.ts → UtilHttp.d.ts} +0 -0
  37. /package/dist/{cjs/UtilHttp.js → UtilHttp.js} +0 -0
  38. /package/dist/{types/UtilI18n.d.ts → UtilI18n.d.ts} +0 -0
  39. /package/dist/{cjs/UtilI18n.js → UtilI18n.js} +0 -0
  40. /package/dist/{cjs/UtilInterfaces.js → UtilInterfaces.js} +0 -0
  41. /package/dist/{types/UtilLogger.d.ts → UtilLogger.d.ts} +0 -0
  42. /package/dist/{cjs/UtilLogger.js → UtilLogger.js} +0 -0
  43. /package/dist/{types/UtilSymbol.d.ts → UtilSymbol.d.ts} +0 -0
  44. /package/dist/{cjs/UtilSymbol.js → UtilSymbol.js} +0 -0
  45. /package/dist/{types/index.d.ts → index.d.ts} +0 -0
  46. /package/dist/{cjs/index.js → index.js} +0 -0
@@ -1,475 +0,0 @@
1
- import http from 'http';
2
- import https from 'https';
3
- import { URL } from 'url';
4
- import { SLogger } from "./UtilLogger.mjs";
5
- import { UtilFunc } from "./UtilFunctions.mjs";
6
- import qs from "querystring";
7
- import FormData from "form-data";
8
- import HttpProxyAgent from "http-proxy-agent";
9
- import HttpsProxyAgent from "https-proxy-agent";
10
- import { PromiseQueue } from "@zwa73/js-utils";
11
- import fs from "fs";
12
- import path from "pathe";
13
- const AcceptTypeList = ["json", "string"];
14
- const SendTypeList = ["json", "query", "formData", "none"];
15
- const SendNoneProc = {
16
- proc: (opt) => (req) => void req.end()
17
- };
18
- const AcceptStringProc = {
19
- init: '',
20
- reduce: (acc, dat) => acc + dat,
21
- parse: (result) => result
22
- };
23
- const AcceptNoneProc = {
24
- init: undefined,
25
- reduce: () => undefined,
26
- parse: () => undefined
27
- };
28
- /**http请求工具 */
29
- export class UtilHttp {
30
- _data;
31
- _send;
32
- _accept;
33
- constructor(_data, _send, _accept) {
34
- this._data = _data;
35
- this._send = _send;
36
- this._accept = _accept;
37
- }
38
- //#region 流式创建
39
- /**设为https请求 */
40
- static https() {
41
- return new UtilHttp({ protocol: 'https:' }, SendNoneProc, AcceptStringProc);
42
- }
43
- /**设为http请求 */
44
- static http() {
45
- return new UtilHttp({ protocol: 'http:' }, SendNoneProc, AcceptStringProc);
46
- }
47
- /**从url创建 */
48
- static url(urlStr) {
49
- const { protocol, hostname, port, pathname } = new URL(urlStr);
50
- if (!['http:', 'https:'].includes(protocol))
51
- UtilFunc.throwError(`url协议错误: ${urlStr}`);
52
- const req = new UtilHttp({ protocol: protocol }, SendNoneProc, AcceptStringProc);
53
- return req.option({
54
- hostname,
55
- path: pathname,
56
- port: port ? parseInt(port) : undefined,
57
- });
58
- }
59
- /**设为get方式的请求 */
60
- get() {
61
- this._data.method = 'GET';
62
- return this;
63
- }
64
- /**设为Post方式的请求 */
65
- post() {
66
- this._data.method = 'POST';
67
- return this;
68
- }
69
- /**补充参数
70
- * 不会检查必要参数完整性
71
- * 将会替换对应字段, 修改headers请用header函数
72
- */
73
- option(option) {
74
- this._data = { ...this._data, ...option };
75
- return this;
76
- }
77
- /**完成参数
78
- * 会检查必要参数完整性
79
- * 将会替换对应字段, 修改headers请用header函数
80
- */
81
- finalize(option) {
82
- this._data = { ...this._data, ...option };
83
- return this;
84
- }
85
- /**补充header */
86
- header(headers) {
87
- this._data.headers = {
88
- ...this._data.headers,
89
- ...headers,
90
- };
91
- return this;
92
- }
93
- /**设置agent */
94
- proxyAgent(url) {
95
- this._data.agent = UtilFunc.match(this._data['protocol'], {
96
- 'http:': () => HttpProxyAgent(url),
97
- 'https:': () => HttpsProxyAgent(url),
98
- });
99
- return this;
100
- }
101
- /**添加一段query */
102
- query(data) {
103
- this._data.path = UtilHttp.buildQuery(this._data.path ?? '', data);
104
- return this;
105
- }
106
- /**克隆 */
107
- clone() {
108
- return new UtilHttp({ ...this._data }, this._send, this._accept);
109
- }
110
- //#endregion
111
- //#region 快速预设
112
- /**收发皆为json的预设 */
113
- json() {
114
- return this.sendJson().acceptJson();
115
- }
116
- /**收发皆为json的post预设 */
117
- postJson() {
118
- return this.post().json();
119
- }
120
- /**无查询参数获取json的get预设 */
121
- getJson() {
122
- return this.get().sendNone().acceptJson();
123
- }
124
- /**有查询参数获取json的get预设 */
125
- queryJson() {
126
- return this.get().sendQuery().acceptJson();
127
- }
128
- /**收发皆为json的https-post预设 */
129
- static httpsPostJson() {
130
- return UtilHttp.https().postJson();
131
- }
132
- /**收发皆为json的http-post预设 */
133
- static httpPostJson() {
134
- return UtilHttp.http().postJson();
135
- }
136
- /**无查询参数获取json的https-get预设 */
137
- static httpsGetJson() {
138
- return UtilHttp.https().getJson();
139
- }
140
- /**有查询参数获取json的https-get预设 */
141
- static httpsQueryJson() {
142
- return UtilHttp.http().queryJson();
143
- }
144
- /**无查询参数获取json的http-get预设 */
145
- static httpGetJson() {
146
- return UtilHttp.http().getJson();
147
- }
148
- /**有查询参数获取json的http-get预设 */
149
- static httpQueryJson() {
150
- return UtilHttp.http().queryJson();
151
- }
152
- //#endregion
153
- //#region 接收数据类型
154
- /**预设的接收数据类型*/
155
- accept(t) {
156
- const map = {
157
- 'json': this.acceptJson(),
158
- 'string': this.acceptString(),
159
- 'none': this.acceptNone(),
160
- };
161
- return map[t];
162
- }
163
- acceptJson() {
164
- const proc = {
165
- init: '',
166
- reduce: (acc, curr) => acc + curr,
167
- parse: (result) => {
168
- if (result == undefined) {
169
- SLogger.warn(`json accept 接收反馈错误: 响应结果无效`);
170
- return undefined;
171
- }
172
- const { data, ...rest } = result;
173
- if (data.trim() == "") {
174
- SLogger.warn(`json accept 接收反馈错误: 原始字符串为空`, UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
175
- return { ...result, raw: "", data: null };
176
- }
177
- try {
178
- const obj = JSON.parse(data.trim());
179
- SLogger.http(`json accept 接受信息 data:`, UtilFunc.stringifyJToken(obj, { compress: true, space: 2 }), `result:`, UtilFunc.stringifyJToken(rest, { compress: true, space: 2 }));
180
- return { ...rest, data: obj };
181
- }
182
- catch (e) {
183
- SLogger.warn(`json accept 接收反馈错误:${e}`, UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
184
- return { ...result, raw: data, data: null };
185
- }
186
- }
187
- };
188
- this._accept = proc;
189
- return this;
190
- }
191
- acceptString() {
192
- this._accept = AcceptStringProc;
193
- return this;
194
- }
195
- acceptNone() {
196
- this._accept = AcceptNoneProc;
197
- return this;
198
- }
199
- /**自定的接收数据类型*/
200
- acceptRaw(proc) {
201
- this._accept = proc;
202
- return this;
203
- }
204
- //#endregion
205
- //#region 发送数据类型
206
- /**预设的发送数据类型 */
207
- send(t) {
208
- const map = {
209
- 'json': this.sendJson(),
210
- 'query': this.sendQuery(),
211
- 'formData': this.sendFormData(),
212
- 'form': this.sendForm(),
213
- 'file': this.sendFile(),
214
- 'none': this.sendNone(),
215
- };
216
- return map[t];
217
- }
218
- /**发送json
219
- * 请求参数为 (token:JToken)
220
- */
221
- sendJson() {
222
- const proc = {
223
- proc: (opt, token) => {
224
- const { method } = opt;
225
- const isPost = (method == "POST");
226
- const data = JSON.stringify(token);
227
- this._data.headers ??= {};
228
- this._data.headers['Content-Length'] = Buffer.byteLength(data);
229
- const procReq = (req) => {
230
- if (isPost)
231
- req.write(data);
232
- req.end();
233
- };
234
- return procReq;
235
- }
236
- };
237
- this._send = proc;
238
- this._data.headers ??= {};
239
- this._data.headers['Content-Type'] = 'application/json';
240
- return this;
241
- }
242
- /**利用 appendQuery 直接将数据附加在path上发送请求
243
- * 请求参数为 (form:QueryRequestData)
244
- */
245
- sendQuery() {
246
- const proc = {
247
- proc: (opt, form) => {
248
- opt.path = UtilHttp.buildQuery(opt.path ?? '', form);
249
- const procReq = (req) => void req.end();
250
- return procReq;
251
- }
252
- };
253
- this._send = proc;
254
- return this;
255
- }
256
- /**发送表单数据
257
- * 请求参数为 (formData: FormData)
258
- */
259
- sendFormData() {
260
- const proc = {
261
- proc: (opt, formData) => {
262
- opt.headers = formData.getHeaders();
263
- const procReq = (req) => {
264
- formData.pipe(req);
265
- };
266
- return procReq;
267
- },
268
- };
269
- this._send = proc;
270
- this._data.headers ??= {};
271
- this._data.headers['Content-Type'] = 'multipart/form-data';
272
- return this;
273
- }
274
- /**发送表单
275
- * 请求参数为 (form:QueryRequestData)
276
- */
277
- sendForm() {
278
- const proc = {
279
- proc: (opt, form) => {
280
- const { method } = opt;
281
- const isPost = (method == "POST");
282
- const data = qs.stringify(form);
283
- this._data.headers ??= {};
284
- this._data.headers['Content-Length'] = Buffer.byteLength(data);
285
- const procReq = (req) => {
286
- if (isPost)
287
- req.write(data);
288
- req.end();
289
- };
290
- return procReq;
291
- }
292
- };
293
- this._send = proc;
294
- this._data.headers ??= {};
295
- this._data.headers['Content-Type'] = 'application/x-www-form-urlencoded';
296
- return this;
297
- }
298
- /**发送文件
299
- * 请求参数为 (filepath:string, filename?: string)
300
- */
301
- sendFile() {
302
- const proc = {
303
- proc: (opt, filepath, filename) => {
304
- const formData = new FormData();
305
- filename = filename ?? path.basename(filepath);
306
- formData.append(filename, fs.createReadStream(filepath));
307
- opt.headers = formData.getHeaders();
308
- const procReq = (req) => {
309
- formData.pipe(req);
310
- };
311
- return procReq;
312
- },
313
- };
314
- this._send = proc;
315
- this._data.headers ??= {};
316
- this._data.headers['Content-Type'] = 'multipart/form-data';
317
- return this;
318
- }
319
- sendNone() {
320
- this._send = SendNoneProc;
321
- return this;
322
- }
323
- /**自定的发送数据类型 */
324
- sendRaw(proc) {
325
- this._send = proc;
326
- return this;
327
- }
328
- //#endregion
329
- /**发送请求
330
- * @param datas - 数据对象
331
- */
332
- async once(...datas) {
333
- const fullopt = this._data;
334
- const proc = await this._send.proc(fullopt, ...datas);
335
- const { reduce, init, parse } = this._accept;
336
- const res = await UtilHttp.request(fullopt, proc, reduce, init);
337
- return parse(res);
338
- }
339
- /**重复发送网络请求
340
- * @param verify - 有效性验证函数
341
- * @param retries - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
342
- * @param datas - 数据对象
343
- */
344
- async retry(opt, ...datas) {
345
- let { retries, verify } = opt;
346
- retries ??= {};
347
- retries.tryDelay = retries.tryDelay ?? 1000;
348
- const procFn = async () => this.once(...datas);
349
- return UtilFunc.retryPromise(procFn, verify, retries);
350
- }
351
- /**发送网络请求
352
- * @param option - 网络请求选项
353
- * @param proc - 请求处理函数 需调用req.end()
354
- * @param reduce - 数据处理函数
355
- * @param init - 初始数据
356
- */
357
- static async request(option, proc, reduce, init) {
358
- const { protocol, timeout, ...baseReqOpt } = option;
359
- const hasTimeLimit = (timeout ? timeout >= 10_000 : false);
360
- const flagName = `UtilCom.request ${protocol}${baseReqOpt.method} ${UtilFunc.genUUID()}`;
361
- const reduceQueue = new PromiseQueue();
362
- let dataPromise = null;
363
- return new Promise(async (resolve, rejecte) => {
364
- const resFunc = (res) => {
365
- try {
366
- //请求超时
367
- if (hasTimeLimit) {
368
- res.setTimeout(timeout, () => {
369
- SLogger.warn(`${flagName} 接收反馈超时: ${timeout} ms`);
370
- res.destroy();
371
- });
372
- }
373
- let mergedata = init;
374
- res.setEncoding(option.responseEncode ?? 'utf8');
375
- res.on('data', chunk => {
376
- dataPromise = reduceQueue
377
- .enqueue(async () => mergedata = await reduce(mergedata, chunk))
378
- .catch(e => {
379
- SLogger.error(`${flagName} reduce函数错误:${e}\nchunk:${chunk}\nmergedata:`, mergedata);
380
- resolve(undefined);
381
- });
382
- });
383
- res.on('error', e => {
384
- SLogger.warn(`${flagName} 接收反馈错误:${e}`);
385
- resolve(undefined);
386
- });
387
- res.on('end', async () => {
388
- await dataPromise;
389
- resolve({
390
- headers: res.headers,
391
- statusCode: res.statusCode,
392
- data: mergedata,
393
- });
394
- });
395
- }
396
- catch (err) {
397
- SLogger.warn(`${flagName} 未知错误:${err}`);
398
- resolve(undefined);
399
- return;
400
- }
401
- };
402
- //路由 http/https
403
- const req = protocol == "https:"
404
- ? https.request(baseReqOpt, resFunc)
405
- : http.request(baseReqOpt, resFunc);
406
- //请求超时
407
- if (hasTimeLimit) {
408
- req.setTimeout(timeout, () => {
409
- SLogger.warn(`${flagName} 发送请求超时: ${timeout} ms`);
410
- req.destroy();
411
- });
412
- }
413
- req.on('error', e => {
414
- SLogger.warn(`${flagName} 发送请求错误:${e}`);
415
- resolve(undefined);
416
- });
417
- try {
418
- await proc(req);
419
- }
420
- catch (e) {
421
- SLogger.error(`${flagName} proc函数错误:${e}`);
422
- resolve(undefined);
423
- }
424
- });
425
- }
426
- /**构建query */
427
- static buildQuery(base, data) {
428
- const queryString = qs.stringify(data);
429
- if (queryString) {
430
- // 检查当前路径是否已经包含问号
431
- const separator = base.includes('?') ? '&' : '?';
432
- base += separator + queryString;
433
- }
434
- return base;
435
- }
436
- }
437
- if (false)
438
- void ((async () => {
439
- const tool = UtilHttp
440
- .url('https://httpbin.org/post')
441
- .post()
442
- .finalize({ timeout: 10000 });
443
- //json
444
- const sj = await tool.clone()
445
- .sendJson()
446
- .acceptJson()
447
- .once({ test: 1 });
448
- console.log(sj);
449
- //form
450
- const sf = await tool.clone()
451
- .sendForm()
452
- .acceptJson()
453
- .once({ test: 1 });
454
- console.log(sf);
455
- //query
456
- const sq = await tool.clone()
457
- .sendQuery()
458
- .acceptJson()
459
- .once({ test: 1 });
460
- console.log(sq);
461
- const filepath = path.join(`${process.platform === 'win32' ? '' : '/'}${/file:\/{2,3}(.+)\/[^/]/.exec(import.meta.url)[1]}`, '..', 'input.wav');
462
- //formData
463
- //const form = new FormData();
464
- //form.append('name', 'input.wav');
465
- //form.append('file', fs.createReadStream(path.join(`${process.platform === 'win32' ? '' : '/'}${/file:\/{2,3}(.+)\/[^/]/.exec(import.meta.url)[1]}`,'..','input.wav')));
466
- //const sfd = await tool.clone()
467
- // .sendFormData()
468
- // .acceptJson()
469
- // .once(form);
470
- const sfile = await tool.clone()
471
- .sendFile()
472
- .acceptJson()
473
- .once(filepath);
474
- console.log(sfile);
475
- })());
@@ -1,206 +0,0 @@
1
- import { UtilFT } from "./UtilFileTools.mjs";
2
- import { UtilFunc } from "./UtilFunctions.mjs";
3
- import { SLogger } from "./UtilLogger.mjs";
4
- import path from 'pathe';
5
- /**语言:地区 表 */
6
- const I18nFlagTable = {
7
- "zh": ["CN", "TW"],
8
- "en": ["US"]
9
- };
10
- /**语言标签列表 */
11
- const LangFlagList = Object.entries(I18nFlagTable)
12
- .map(([k, v]) => `${k}-${v}`)
13
- .concat(Object.keys(I18nFlagTable));
14
- const parseLangFlag = (lf) => {
15
- const match = lf.match(/^([^-]+)(.+)/);
16
- return { 1: match[1], 2: match[2] != '' ? match[2] : undefined };
17
- };
18
- const MarkRegex = /%([^%]+)%$/;
19
- const BaseFile = 'base_lang.json';
20
- const TemplateFile = 'template.json';
21
- const LangDir = 'lang';
22
- /**运行时I18n工具
23
- * 需先调用 init初始化
24
- */
25
- export class SI18n {
26
- static _table;
27
- static _lang;
28
- static _dataDir;
29
- static _vaildLang;
30
- /**解析i18n索引 */
31
- static parseI18nKey(i18nKey) {
32
- const match = i18nKey.match(/([\s\S]+?)((?<!\\)%[^%]+(?<!\\)%$)?$/);
33
- const base = match[1];
34
- const mark = match[2] == '' || match[2] == undefined
35
- ? undefined
36
- : match[2].match(/^%([^%]+)%$/)[1];
37
- return { base, mark };
38
- }
39
- /**格式化文本与mark为i18n索引key */
40
- static formatI18nKey(str, mark) {
41
- return str + (mark == undefined ? '' : SI18n.mark(mark));
42
- }
43
- /**特殊标记
44
- * 若添加在文本末尾则不会作为原文文本显示, 仅供索引
45
- * @param mk - 特殊标记文本
46
- */
47
- static mark(mk) {
48
- return `%${mk}%`;
49
- }
50
- /**初始化函数,加载国际化数据,设置语言,并在进程退出前保存数据。
51
- * @param i18nDataDir - 国际化数据的路径。
52
- * @param lang - 要设置的语言。
53
- */
54
- static async init(i18nDataDir, lang = '*') {
55
- const date = new Date().toISOString();
56
- const mergePath = path.join(i18nDataDir, BaseFile);
57
- const table = await UtilFT.loadJSONFile(mergePath, { default: {
58
- base_lang: 'zh-CN',
59
- texts: [],
60
- } });
61
- const { texts, ...rest } = table;
62
- SI18n._table = {
63
- ...rest,
64
- text_table: texts.reduce((acc, cur) => ({ ...acc, [SI18n.formatI18nKey(cur.original, cur.mark)]: { ...cur, lang_table: {} } }), {}),
65
- };
66
- SI18n._vaildLang = ['template'];
67
- //覆盖入单语言文件
68
- const singleDir = path.join(i18nDataDir, LangDir);
69
- (await Promise.all((await UtilFT.fileSearchGlob(singleDir, `**/${parseLangFlag(lang)[1]}*.json`))
70
- .map(async (p) => await UtilFT.loadJSONFile(p))))
71
- .forEach(t => {
72
- SI18n._vaildLang?.push(t.target_lang);
73
- return Object.entries(t.translate_table)
74
- .forEach(([k, v]) => {
75
- if (v == null)
76
- return;
77
- const ttable = SI18n._table.text_table;
78
- ttable[k] ??= {
79
- original: k,
80
- scan_time: date,
81
- source: 'Runtime',
82
- lang_table: {}
83
- };
84
- const ltable = ttable[k].lang_table;
85
- ltable[t.target_lang] ??= v;
86
- });
87
- });
88
- if (lang != undefined && lang != '*' && !SI18n._vaildLang.includes(lang))
89
- SI18n._vaildLang.push(lang);
90
- SI18n._lang = lang == "*" ? undefined : lang;
91
- SI18n._dataDir = i18nDataDir;
92
- }
93
- static t(strings, ...values) {
94
- if (typeof strings == 'string') {
95
- const mark = values.length >= 1 ? SI18n.mark(values[0]) : '';
96
- return SI18n.getI18n(strings.replace(/%/g, '\\%') + mark, SI18n._lang)
97
- .replace(/\\%/g, '%');
98
- }
99
- let i18nKey = ``;
100
- const vakyeKeys = values.map((v, i) => `%${i}`);
101
- for (let i = 0; i < values.length; i++)
102
- i18nKey += strings[i].replace(/%/g, '\\%') + vakyeKeys[i];
103
- i18nKey += strings[strings.length - 1];
104
- //检查是否为mark
105
- if (MarkRegex.test(String(values[values.length - 1])) && strings[strings.length - 1] == '')
106
- i18nKey = i18nKey.replace(vakyeKeys[vakyeKeys.length - 1], '') + String(values[values.length - 1]);
107
- //console.log(1,i18nKey)
108
- let trans = SI18n.getI18n(i18nKey, SI18n._lang);
109
- //console.log(2,trans)
110
- vakyeKeys.forEach((k, i) => trans = trans.replace(new RegExp(`((?<!\\\\)${k})`), String(values[i])));
111
- //console.log(3,trans)
112
- return trans.replace(/\\%/g, '%');
113
- }
114
- /**根据提供的键和语言,返回对应的国际化字符串。
115
- * 如果没有找到对应的字符串,将会抛出错误。
116
- * @param key - 要查找的键。
117
- * @param lang - 要查找的语言。
118
- * @returns 对应的国际化字符串。
119
- */
120
- static getI18n(key, lang) {
121
- if (SI18n._table == undefined)
122
- return UtilFunc.throwError('SI18n 未初始化');
123
- let obj = SI18n._table.text_table[key];
124
- if (obj == undefined) {
125
- SLogger.warn(`SI18n 未在 ${SI18n._dataDir} 找到 ${key} 对应的数据, 已自动添加`);
126
- const p = SI18n.parseI18nKey(key);
127
- obj = SI18n.addOriginalText({
128
- original: p.base,
129
- scan_time: new Date().toISOString(),
130
- lang_table: {},
131
- mark: p.mark,
132
- source: 'Runtime'
133
- });
134
- }
135
- if (lang == undefined)
136
- return obj.original;
137
- if (obj.invalid === true)
138
- return obj.original;
139
- return SI18n.tryAndRollback(lang, obj);
140
- }
141
- /**尝试获取指定语言的翻译,如果没有找到,将回滚到其他可用的语言。
142
- * @param lang - 要查找的语言。
143
- * @param dat - 包含翻译的数据对象。
144
- * @returns 找到的翻译,如果没有找到,将返回原始字符串。
145
- */
146
- static tryAndRollback(lang, dat) {
147
- const langTable = {
148
- [SI18n._table.base_lang]: dat.original,
149
- ...dat.lang_table
150
- };
151
- if (langTable[lang] != undefined)
152
- return langTable[lang];
153
- const l1 = lang.match(/^([^-]+)/)[1];
154
- const rb = Object.entries(langTable).find(([k, v]) => k.includes(l1));
155
- if (rb)
156
- return rb[1];
157
- return dat.original;
158
- }
159
- /**覆盖性的添加一处原文 */
160
- static addOriginalText(dat) {
161
- const key = SI18n.formatI18nKey(dat.original, dat.mark);
162
- SI18n._table.text_table[key] = dat;
163
- return SI18n._table.text_table[key];
164
- }
165
- /**保存数据 */
166
- static async saveTable() {
167
- const { text_table, ...rest } = SI18n._table;
168
- const date = new Date().toISOString();
169
- //console.log(text_table)
170
- //保存原始文本数据
171
- const tb = {
172
- ...rest,
173
- texts: Object.values(text_table).map((d) => {
174
- const { lang_table, ...rest } = d;
175
- return rest;
176
- })
177
- };
178
- const mergePath = path.join(SI18n._dataDir, BaseFile);
179
- await UtilFT.writeJSONFile(mergePath, tb);
180
- //保存所有语言数据
181
- const tbMap = {};
182
- Object.values(text_table).forEach(d => {
183
- if (d.invalid === true)
184
- return;
185
- SI18n._vaildLang?.forEach((vl) => {
186
- const lf = vl;
187
- tbMap[lf] ??= {
188
- base_lang: rest.base_lang,
189
- modify_time: date,
190
- target_lang: lf,
191
- translate_table: {}
192
- };
193
- const v = d.lang_table[lf];
194
- tbMap[lf].translate_table[SI18n.formatI18nKey(d.original, d.mark)] = v ?? null;
195
- });
196
- });
197
- await Promise.all(Object.values(tbMap).map(async (t) => {
198
- if (t.target_lang == 'template') {
199
- const tmppath = path.join(SI18n._dataDir, TemplateFile);
200
- return await UtilFT.writeJSONFile(tmppath, t);
201
- }
202
- const singlePath = path.join(SI18n._dataDir, LangDir, t.target_lang);
203
- return await UtilFT.writeJSONFile(singlePath, t);
204
- }));
205
- }
206
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //#endregion