@adminforth/i18n 1.0.21-next.1 → 1.0.22-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
@@ -5,11 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  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
- ## [1.0.21] - next
8
+ ## [1.0.22] - next
9
+
10
+
11
+ ## [1.0.21] - 2024-12-30
9
12
 
10
13
  ### Fixed
11
14
  - improve cache reset when editing messages manually
12
15
 
16
+ ### Added
17
+ - Translating external app" feature by using feedCategoryTranslations
18
+
13
19
  ## [1.0.20]
14
20
 
15
21
  ### Fixed
package/dist/index.js CHANGED
@@ -222,18 +222,14 @@ export default class I18N extends AdminForthPlugin {
222
222
  if (lang === 'en') {
223
223
  continue;
224
224
  }
225
- if (updates[this.trFieldNames[lang]]) {
225
+ if (updates[this.trFieldNames[lang]] !== undefined) {
226
226
  langsChanged.push(lang);
227
227
  }
228
228
  }
229
229
  // clear frontend cache for all langsChanged
230
230
  for (const lang of langsChanged) {
231
- if (oldRecord[this.options.categoryFieldName] === 'frontend') {
232
- this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
233
- }
234
- else {
235
- this.cache.clear(`${this.resourceConfig.resourceId}:${oldRecord[this.options.categoryFieldName]}:${lang}:${oldRecord[this.enFieldName]}`);
236
- }
231
+ this.cache.clear(`${this.resourceConfig.resourceId}:${oldRecord[this.options.categoryFieldName]}:${lang}`);
232
+ this.cache.clear(`${this.resourceConfig.resourceId}:${oldRecord[this.options.categoryFieldName]}:${lang}:${oldRecord[this.enFieldName]}`);
237
233
  }
238
234
  this.updateUntranslatedMenuBadge();
239
235
  }
@@ -244,12 +240,8 @@ export default class I18N extends AdminForthPlugin {
244
240
  resourceConfig.hooks.delete.afterSave.push((_e) => __awaiter(this, [_e], void 0, function* ({ record }) {
245
241
  for (const lang of this.options.supportedLanguages) {
246
242
  // if frontend, clear frontend cache
247
- if (record[this.options.categoryFieldName] === 'frontend') {
248
- this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
249
- }
250
- else {
251
- this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}:${record[this.enFieldName]}`);
252
- }
243
+ this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}`);
244
+ this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}:${record[this.enFieldName]}`);
253
245
  }
254
246
  this.updateUntranslatedMenuBadge();
255
247
  return { ok: true };
@@ -509,33 +501,13 @@ ${JSON.stringify(strings.reduce((acc, s) => {
509
501
  return;
510
502
  }
511
503
  // loop over missingKeys[i].path and add them to database if not exists
512
- const missingKeysDeduplicated = messages.missingKeys.reduce((acc, missingKey) => {
513
- if (!acc.find((a) => a.path === missingKey.path)) {
514
- acc.push(missingKey);
515
- }
516
- return acc;
517
- }, []);
518
- yield Promise.all(missingKeysDeduplicated.map((missingKey) => __awaiter(this, void 0, void 0, function* () {
519
- const key = missingKey.path;
520
- const file = missingKey.file;
521
- const category = 'frontend';
522
- const exists = yield adminforth.resource(this.resourceConfig.resourceId).count(Filters.EQ(this.enFieldName, key));
523
- if (exists) {
524
- return;
525
- }
526
- if (!key) {
527
- throw new Error(`Faced an empty key in Fronted messages, file ${file}`);
528
- }
529
- const record = Object.assign({ [this.enFieldName]: key, [this.options.categoryFieldName]: category }, (this.options.sourceFieldName ? { [this.options.sourceFieldName]: file } : {}));
530
- try {
531
- yield adminforth.resource(this.resourceConfig.resourceId).create(record);
532
- }
533
- catch (e) {
534
- console.error('🐛 Error creating record', e);
535
- }
536
- })));
537
- // updateBadge
538
- this.updateUntranslatedMenuBadge();
504
+ const messagesForFeed = messages.missingKeys.map((mk) => {
505
+ return {
506
+ en_string: mk.path,
507
+ source: mk.file,
508
+ };
509
+ });
510
+ yield this.feedCategoryTranslations(messagesForFeed, 'frontend');
539
511
  });
540
512
  }
541
513
  tryProcessAndWatch(adminforth) {
@@ -653,6 +625,54 @@ ${JSON.stringify(strings.reduce((acc, s) => {
653
625
  // Needed if plugin can have multiple instances on one resource
654
626
  return `single`;
655
627
  }
628
+ getCategoryTranslations(category, lang) {
629
+ return __awaiter(this, void 0, void 0, function* () {
630
+ const resource = this.adminforth.resource(this.resourceConfig.resourceId);
631
+ const cacheKey = `${this.resourceConfig.resourceId}:${category}:${lang}`;
632
+ const cached = yield this.cache.get(cacheKey);
633
+ if (cached) {
634
+ return cached;
635
+ }
636
+ const translations = {};
637
+ const allTranslations = yield resource.list([Filters.EQ(this.options.categoryFieldName, category)]);
638
+ for (const tr of allTranslations) {
639
+ translations[tr[this.enFieldName]] = tr[this.trFieldNames[lang]];
640
+ }
641
+ yield this.cache.set(cacheKey, translations);
642
+ return translations;
643
+ });
644
+ }
645
+ feedCategoryTranslations(messages, category) {
646
+ return __awaiter(this, void 0, void 0, function* () {
647
+ const adminforth = this.adminforth;
648
+ const missingKeysDeduplicated = messages.reduce((acc, missingKey) => {
649
+ if (!acc.find((a) => a.en_string === missingKey.en_string)) {
650
+ acc.push(missingKey);
651
+ }
652
+ return acc;
653
+ }, []);
654
+ yield Promise.all(missingKeysDeduplicated.map((missingKey) => __awaiter(this, void 0, void 0, function* () {
655
+ const key = missingKey.en_string;
656
+ const source = missingKey.source;
657
+ const exists = yield adminforth.resource(this.resourceConfig.resourceId).count(Filters.EQ(this.enFieldName, key));
658
+ if (exists) {
659
+ return;
660
+ }
661
+ if (!key) {
662
+ console.error(`Faced an empty key in feeding ${category} messages, source ${source}`);
663
+ }
664
+ const record = Object.assign({ [this.enFieldName]: key, [this.options.categoryFieldName]: category }, (this.options.sourceFieldName ? { [this.options.sourceFieldName]: source } : {}));
665
+ try {
666
+ yield adminforth.resource(this.resourceConfig.resourceId).create(record);
667
+ }
668
+ catch (e) {
669
+ console.error('🐛 Error creating record', e);
670
+ }
671
+ })));
672
+ // updateBadge
673
+ this.updateUntranslatedMenuBadge();
674
+ });
675
+ }
656
676
  setupEndpoints(server) {
657
677
  server.endpoint({
658
678
  method: 'GET',
@@ -661,18 +681,7 @@ ${JSON.stringify(strings.reduce((acc, s) => {
661
681
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ query }) {
662
682
  const lang = query.lang;
663
683
  // form map of translations
664
- const resource = this.adminforth.resource(this.resourceConfig.resourceId);
665
- const cacheKey = `${this.resourceConfig.resourceId}:frontend:${lang}`;
666
- const cached = yield this.cache.get(cacheKey);
667
- if (cached) {
668
- return cached;
669
- }
670
- const translations = {};
671
- const allTranslations = yield resource.list([Filters.EQ(this.options.categoryFieldName, 'frontend')]);
672
- for (const tr of allTranslations) {
673
- translations[tr[this.enFieldName]] = tr[this.trFieldNames[lang]];
674
- }
675
- yield this.cache.set(cacheKey, translations);
684
+ const translations = yield this.getCategoryTranslations('frontend', lang);
676
685
  return translations;
677
686
  })
678
687
  });
package/index.ts CHANGED
@@ -251,18 +251,15 @@ export default class I18N extends AdminForthPlugin {
251
251
  if (lang === 'en') {
252
252
  continue;
253
253
  }
254
- if (updates[this.trFieldNames[lang]]) {
254
+ if (updates[this.trFieldNames[lang]] !== undefined) {
255
255
  langsChanged.push(lang);
256
256
  }
257
257
  }
258
258
 
259
259
  // clear frontend cache for all langsChanged
260
260
  for (const lang of langsChanged) {
261
- if (oldRecord[this.options.categoryFieldName] === 'frontend') {
262
- this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
263
- } else {
264
- this.cache.clear(`${this.resourceConfig.resourceId}:${oldRecord[this.options.categoryFieldName]}:${lang}:${oldRecord[this.enFieldName]}`);
265
- }
261
+ this.cache.clear(`${this.resourceConfig.resourceId}:${oldRecord[this.options.categoryFieldName]}:${lang}`);
262
+ this.cache.clear(`${this.resourceConfig.resourceId}:${oldRecord[this.options.categoryFieldName]}:${lang}:${oldRecord[this.enFieldName]}`);
266
263
  }
267
264
  this.updateUntranslatedMenuBadge();
268
265
  }
@@ -274,11 +271,8 @@ export default class I18N extends AdminForthPlugin {
274
271
  resourceConfig.hooks.delete.afterSave.push(async ({ record }: { record: any }): Promise<{ ok: boolean, error?: string }> => {
275
272
  for (const lang of this.options.supportedLanguages) {
276
273
  // if frontend, clear frontend cache
277
- if (record[this.options.categoryFieldName] === 'frontend') {
278
- this.cache.clear(`${this.resourceConfig.resourceId}:frontend:${lang}`);
279
- } else {
280
- this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}:${record[this.enFieldName]}`);
281
- }
274
+ this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}`);
275
+ this.cache.clear(`${this.resourceConfig.resourceId}:${record[this.options.categoryFieldName]}:${lang}:${record[this.enFieldName]}`);
282
276
  }
283
277
  this.updateUntranslatedMenuBadge();
284
278
  return { ok: true };
@@ -609,39 +603,16 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
609
603
  return;
610
604
  }
611
605
  // loop over missingKeys[i].path and add them to database if not exists
612
-
613
- const missingKeysDeduplicated = messages.missingKeys.reduce((acc: any[], missingKey: any) => {
614
- if (!acc.find((a) => a.path === missingKey.path)) {
615
- acc.push(missingKey);
616
- }
617
- return acc;
618
- }, []);
619
-
620
- await Promise.all(missingKeysDeduplicated.map(async (missingKey: any) => {
621
- const key = missingKey.path;
622
- const file = missingKey.file;
623
- const category = 'frontend';
624
- const exists = await adminforth.resource(this.resourceConfig.resourceId).count(Filters.EQ(this.enFieldName, key));
625
- if (exists) {
626
- return;
627
- }
628
- if (!key) {
629
- throw new Error(`Faced an empty key in Fronted messages, file ${file}`);
630
- }
631
- const record = {
632
- [this.enFieldName]: key,
633
- [this.options.categoryFieldName]: category,
634
- ...(this.options.sourceFieldName ? { [this.options.sourceFieldName]: file } : {}),
606
+ const messagesForFeed = messages.missingKeys.map((mk) => {
607
+ return {
608
+ en_string: mk.path,
609
+ source: mk.file,
635
610
  };
636
- try {
637
- await adminforth.resource(this.resourceConfig.resourceId).create(record);
638
- } catch (e) {
639
- console.error('🐛 Error creating record', e);
640
- }
641
- }));
611
+ });
642
612
 
643
- // updateBadge
644
- this.updateUntranslatedMenuBadge()
613
+ await this.feedCategoryTranslations(messagesForFeed, 'frontend')
614
+
615
+
645
616
  }
646
617
 
647
618
 
@@ -770,6 +741,60 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
770
741
  return `single`;
771
742
  }
772
743
 
744
+ async getCategoryTranslations(category: string, lang: string): Promise<Record<string, string>> {
745
+ const resource = this.adminforth.resource(this.resourceConfig.resourceId);
746
+ const cacheKey = `${this.resourceConfig.resourceId}:${category}:${lang}`;
747
+ const cached = await this.cache.get(cacheKey);
748
+ if (cached) {
749
+ return cached;
750
+ }
751
+ const translations = {};
752
+ const allTranslations = await resource.list([Filters.EQ(this.options.categoryFieldName, category)]);
753
+ for (const tr of allTranslations) {
754
+ translations[tr[this.enFieldName]] = tr[this.trFieldNames[lang]];
755
+ }
756
+ await this.cache.set(cacheKey, translations);
757
+ return translations;
758
+ }
759
+
760
+ async feedCategoryTranslations(messages: {
761
+ en_string: string;
762
+ source: string;
763
+ }[], category: string): Promise<void> {
764
+ const adminforth = this.adminforth;
765
+ const missingKeysDeduplicated = messages.reduce((acc: any[], missingKey: any) => {
766
+ if (!acc.find((a) => a.en_string === missingKey.en_string)) {
767
+ acc.push(missingKey);
768
+ }
769
+ return acc;
770
+ }, []);
771
+
772
+ await Promise.all(missingKeysDeduplicated.map(async (missingKey: any) => {
773
+ const key = missingKey.en_string;
774
+ const source = missingKey.source;
775
+ const exists = await adminforth.resource(this.resourceConfig.resourceId).count(Filters.EQ(this.enFieldName, key));
776
+ if (exists) {
777
+ return;
778
+ }
779
+ if (!key) {
780
+ console.error(`Faced an empty key in feeding ${category} messages, source ${source}`);
781
+ }
782
+ const record = {
783
+ [this.enFieldName]: key,
784
+ [this.options.categoryFieldName]: category,
785
+ ...(this.options.sourceFieldName ? { [this.options.sourceFieldName]: source } : {}),
786
+ };
787
+ try {
788
+ await adminforth.resource(this.resourceConfig.resourceId).create(record);
789
+ } catch (e) {
790
+ console.error('🐛 Error creating record', e);
791
+ }
792
+ }));
793
+
794
+ // updateBadge
795
+ this.updateUntranslatedMenuBadge();
796
+ }
797
+
773
798
 
774
799
  setupEndpoints(server: IHttpServer) {
775
800
  server.endpoint({
@@ -780,18 +805,7 @@ JSON.stringify(strings.reduce((acc: object, s: { en_string: string }): object =>
780
805
  const lang = query.lang;
781
806
 
782
807
  // form map of translations
783
- const resource = this.adminforth.resource(this.resourceConfig.resourceId);
784
- const cacheKey = `${this.resourceConfig.resourceId}:frontend:${lang}`;
785
- const cached = await this.cache.get(cacheKey);
786
- if (cached) {
787
- return cached;
788
- }
789
- const translations = {};
790
- const allTranslations = await resource.list([Filters.EQ(this.options.categoryFieldName, 'frontend')]);
791
- for (const tr of allTranslations) {
792
- translations[tr[this.enFieldName]] = tr[this.trFieldNames[lang]];
793
- }
794
- await this.cache.set(cacheKey, translations);
808
+ const translations = await this.getCategoryTranslations('frontend', lang);
795
809
  return translations;
796
810
 
797
811
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/i18n",
3
- "version": "1.0.21-next.1",
3
+ "version": "1.0.22-next.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",