@adminforth/i18n 1.0.13 → 1.0.16-next.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/Changelog.md CHANGED
@@ -6,7 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
 
9
+ ## [1.0.14]
9
10
 
11
+ ### Fixed
12
+
13
+ - Add `ignoreInitial` for watch to prevent initial messages loading
14
+ - Add locking mechanism to prevent initial messages loading call in parallel (just in case)
10
15
 
11
16
  ## [1.0.13]
12
17
 
package/dist/index.js CHANGED
@@ -12,6 +12,8 @@ import iso6391 from 'iso-639-1';
12
12
  import path from 'path';
13
13
  import fs from 'fs-extra';
14
14
  import chokidar from 'chokidar';
15
+ import { AsyncQueue } from '@sapphire/async-queue';
16
+ const processFrontendMessagesQueue = new AsyncQueue();
15
17
  const SLAVIC_PLURAL_EXAMPLES = {
16
18
  uk: 'яблук | Яблуко | Яблука | Яблук', // zero | singular | 2-4 | 5+
17
19
  bg: 'ябълки | ябълка | ябълки | ябълки', // zero | singular | 2-4 | 5+
@@ -275,19 +277,23 @@ export default class I18N extends AdminForthPlugin {
275
277
  confirm: 'Are you sure you want to translate selected items?',
276
278
  state: 'selected',
277
279
  action: (_j) => __awaiter(this, [_j], void 0, function* ({ selectedIds, tr }) {
280
+ let translatedCount = 0;
278
281
  try {
279
- yield this.bulkTranslate({ selectedIds });
282
+ translatedCount = yield this.bulkTranslate({ selectedIds });
280
283
  }
281
284
  catch (e) {
282
285
  if (e instanceof AiTranslateError) {
286
+ process.env.HEAVY_DEBUG && console.error('🪲⛔ bulkTranslate error', e);
283
287
  return { ok: false, error: e.message };
284
288
  }
285
289
  }
286
- console.log('🪲bulkTranslate done', selectedIds);
290
+ process.env.HEAVY_DEBUG && console.log('🪲bulkTranslate done', selectedIds);
287
291
  this.updateUntranslatedMenuBadge();
288
292
  return {
289
293
  ok: true, error: undefined,
290
- successMessage: yield tr(`Translated {count} items`, 'backend', { count: selectedIds.length }),
294
+ successMessage: yield tr(`Translated {count} items`, 'backend', {
295
+ count: translatedCount,
296
+ }),
291
297
  };
292
298
  })
293
299
  });
@@ -349,7 +355,7 @@ export default class I18N extends AdminForthPlugin {
349
355
  let totalTranslated = 0;
350
356
  for (let i = 0; i < strings.length; i += maxKeysInOneReq) {
351
357
  const slicedStrings = strings.slice(i, i + maxKeysInOneReq);
352
- console.log('🪲🔪slicedStrings ', slicedStrings);
358
+ process.env.HEAVY_DEBUG && console.log('🪲🔪slicedStrings len', slicedStrings.length);
353
359
  totalTranslated += yield translateToLang(langIsoCode, slicedStrings, plurals);
354
360
  }
355
361
  return totalTranslated;
@@ -368,10 +374,10 @@ ${JSON.stringify(strings.reduce((acc, s) => {
368
374
  }, {}), null, 2)}
369
375
  \`\`\`
370
376
  `;
371
- process.env.HEAVY_DEBUG && console.log('llm prompt', prompt);
377
+ process.env.HEAVY_DEBUG && console.log('🧠 llm prompt', prompt);
372
378
  // call OpenAI
373
379
  const resp = yield this.options.completeAdapter.complete(prompt, [], 300);
374
- process.env.HEAVY_DEBUG && console.log('llm resp', resp);
380
+ process.env.HEAVY_DEBUG && console.log('🧠 llm resp', resp);
375
381
  if (resp.error) {
376
382
  throw new AiTranslateError(resp.error);
377
383
  }
@@ -386,7 +392,7 @@ ${JSON.stringify(strings.reduce((acc, s) => {
386
392
  }
387
393
  catch (e) {
388
394
  console.error('error in parsing OpenAI', resp);
389
- return;
395
+ throw new AiTranslateError('Error in parsing OpenAI response');
390
396
  }
391
397
  res = JSON.parse(res);
392
398
  for (const [enStr, translatedStr] of Object.entries(res)) {
@@ -433,6 +439,7 @@ ${JSON.stringify(strings.reduce((acc, s) => {
433
439
  }
434
440
  processExtractedMessages(adminforth, filePath) {
435
441
  return __awaiter(this, void 0, void 0, function* () {
442
+ yield processFrontendMessagesQueue.wait();
436
443
  // messages file is in i18n-messages.json
437
444
  let messages;
438
445
  try {
@@ -482,7 +489,10 @@ ${JSON.stringify(strings.reduce((acc, s) => {
482
489
  this.processExtractedMessages(adminforth, messagesFile);
483
490
  // we use watcher because file can't be yet created when we start - bundleNow can be done in build time or can be done now
484
491
  // that is why we make attempt to process it now and then watch for changes
485
- const w = chokidar.watch(messagesFile, { persistent: true });
492
+ const w = chokidar.watch(messagesFile, {
493
+ persistent: true,
494
+ ignoreInitial: true, // don't trigger 'add' event for existing file on start
495
+ });
486
496
  w.on('change', () => {
487
497
  process.env.HEAVY_DEBUG && console.log('🪲🔔messagesFile change', messagesFile);
488
498
  this.processExtractedMessages(adminforth, messagesFile);
package/index.ts CHANGED
@@ -5,6 +5,9 @@ import iso6391, { LanguageCode } from 'iso-639-1';
5
5
  import path from 'path';
6
6
  import fs from 'fs-extra';
7
7
  import chokidar from 'chokidar';
8
+ import { AsyncQueue } from '@sapphire/async-queue';
9
+
10
+ const processFrontendMessagesQueue = new AsyncQueue();
8
11
 
9
12
  const SLAVIC_PLURAL_EXAMPLES = {
10
13
  uk: 'яблук | Яблуко | Яблука | Яблук', // zero | singular | 2-4 | 5+
@@ -315,18 +318,22 @@ export default class I18N extends AdminForthPlugin {
315
318
  confirm: 'Are you sure you want to translate selected items?',
316
319
  state: 'selected',
317
320
  action: async ({ selectedIds, tr }) => {
321
+ let translatedCount = 0;
318
322
  try {
319
- await this.bulkTranslate({ selectedIds });
323
+ translatedCount = await this.bulkTranslate({ selectedIds });
320
324
  } catch (e) {
321
325
  if (e instanceof AiTranslateError) {
326
+ process.env.HEAVY_DEBUG && console.error('🪲⛔ bulkTranslate error', e);
322
327
  return { ok: false, error: e.message };
323
328
  }
324
329
  }
325
- console.log('🪲bulkTranslate done', selectedIds);
330
+ process.env.HEAVY_DEBUG && console.log('🪲bulkTranslate done', selectedIds);
326
331
  this.updateUntranslatedMenuBadge();
327
332
  return {
328
333
  ok: true, error: undefined,
329
- successMessage: await tr(`Translated {count} items`, 'backend', {count: selectedIds.length}),
334
+ successMessage: await tr(`Translated {count} items`, 'backend', {
335
+ count: translatedCount,
336
+ }),
330
337
  };
331
338
  }
332
339
  }
@@ -408,7 +415,7 @@ export default class I18N extends AdminForthPlugin {
408
415
  let totalTranslated = 0;
409
416
  for (let i = 0; i < strings.length; i += maxKeysInOneReq) {
410
417
  const slicedStrings = strings.slice(i, i + maxKeysInOneReq);
411
- console.log('🪲🔪slicedStrings ', slicedStrings);
418
+ process.env.HEAVY_DEBUG && console.log('🪲🔪slicedStrings len', slicedStrings.length);
412
419
  totalTranslated += await translateToLang(langIsoCode, slicedStrings, plurals);
413
420
  }
414
421
  return totalTranslated;
@@ -432,7 +439,7 @@ ${
432
439
  \`\`\`
433
440
  `;
434
441
 
435
- process.env.HEAVY_DEBUG && console.log('llm prompt', prompt);
442
+ process.env.HEAVY_DEBUG && console.log('🧠 llm prompt', prompt);
436
443
 
437
444
  // call OpenAI
438
445
  const resp = await this.options.completeAdapter.complete(
@@ -441,7 +448,7 @@ ${
441
448
  300,
442
449
  );
443
450
 
444
- process.env.HEAVY_DEBUG && console.log('llm resp', resp);
451
+ process.env.HEAVY_DEBUG && console.log('🧠 llm resp', resp);
445
452
 
446
453
  if (resp.error) {
447
454
  throw new AiTranslateError(resp.error);
@@ -457,7 +464,7 @@ ${
457
464
  res = resp.content.split("```json")[1].split("```")[0];
458
465
  } catch (e) {
459
466
  console.error('error in parsing OpenAI', resp);
460
- return;
467
+ throw new AiTranslateError('Error in parsing OpenAI response');
461
468
  }
462
469
  res = JSON.parse(res);
463
470
 
@@ -524,6 +531,7 @@ ${
524
531
  }
525
532
 
526
533
  async processExtractedMessages(adminforth: IAdminForth, filePath: string) {
534
+ await processFrontendMessagesQueue.wait();
527
535
  // messages file is in i18n-messages.json
528
536
  let messages;
529
537
  try {
@@ -535,7 +543,7 @@ ${
535
543
  return;
536
544
  }
537
545
  // loop over missingKeys[i].path and add them to database if not exists
538
-
546
+
539
547
  const missingKeysDeduplicated = messages.missingKeys.reduce((acc: any[], missingKey: any) => {
540
548
  if (!acc.find((a) => a.path === missingKey.path)) {
541
549
  acc.push(missingKey);
@@ -579,7 +587,10 @@ ${
579
587
  this.processExtractedMessages(adminforth, messagesFile);
580
588
  // we use watcher because file can't be yet created when we start - bundleNow can be done in build time or can be done now
581
589
  // that is why we make attempt to process it now and then watch for changes
582
- const w = chokidar.watch(messagesFile, { persistent: true });
590
+ const w = chokidar.watch(messagesFile, {
591
+ persistent: true,
592
+ ignoreInitial: true, // don't trigger 'add' event for existing file on start
593
+ });
583
594
  w.on('change', () => {
584
595
  process.env.HEAVY_DEBUG && console.log('🪲🔔messagesFile change', messagesFile);
585
596
 
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@adminforth/i18n",
3
- "version": "1.0.13",
3
+ "version": "1.0.16-next.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
7
7
  "scripts": {
8
8
  "build": "tsc && rsync -av --exclude 'node_modules' custom dist/ && npm version patch",
9
9
  "rollout": "npm run build && npm publish --access public",
10
+ "rollout-next": "npm run build && npm version prerelease --preid=next && npm publish --tag next",
10
11
  "prepare": "npm link adminforth"
11
12
  },
12
13
  "keywords": [],
@@ -15,6 +16,7 @@
15
16
  "description": "",
16
17
  "dependencies": {
17
18
  "@aws-sdk/client-ses": "^3.654.0",
19
+ "@sapphire/async-queue": "^1.5.5",
18
20
  "chokidar": "^4.0.1",
19
21
  "iso-639-1": "^3.1.3"
20
22
  },